Merge commit 'JIRI_HEAD' into ath10k

Change-Id: If150e0d68ce2978e062d66435fb482cefdbad017
diff --git a/bin/appmgr/BUILD.gn b/bin/appmgr/BUILD.gn
index 43b2900..7897163 100644
--- a/bin/appmgr/BUILD.gn
+++ b/bin/appmgr/BUILD.gn
@@ -40,6 +40,8 @@
     "sandbox_metadata.h",
     "url_resolver.cc",
     "url_resolver.h",
+    "util.cc",
+    "util.h",
   ]
 
   public_deps = [
@@ -50,6 +52,7 @@
     "//garnet/public/lib/svc/cpp",
     "//third_party/rapidjson",
     "//zircon/public/fidl/process",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/fs",
     "//zircon/public/lib/launchpad",
     "//zircon/public/lib/loader-service",
@@ -59,10 +62,30 @@
   defines = [ "_ALL_SOURCE=1" ]
 }
 
+source_set("appmgr_for_test") {
+  testonly = true
+
+  sources = [
+    "appmgr.cc",
+    "appmgr.h",
+  ]
+
+  public_deps = [
+    ":lib",
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/app/fidl",
+    "//garnet/public/lib/fxl",
+    "//zircon/public/lib/fs",
+    "//zircon/public/lib/zx",
+  ]
+}
+
 executable("bin") {
   output_name = "appmgr"
 
   sources = [
+    "appmgr.cc",
+    "appmgr.h",
     "main.cc",
   ]
 
@@ -77,16 +100,21 @@
   output_name = "appmgr_unittests"
 
   sources = [
+    "appmgr_unittest.cc",
     "cmx_metadata_unittest.cc",
+    "component_controller_unittest.cc",
     "hub/hub_holder_unittest.cc",
     "namespace_builder_unittest.cc",
     "runtime_metadata_unittest.cc",
     "sandbox_metadata_unittest.cc",
+    "util_unittest.cc",
   ]
 
   deps = [
+    ":appmgr_for_test",
     ":lib",
     "//garnet/public/lib/fxl/test:gtest_main",
+    "//garnet/public/lib/gtest",
   ]
 }
 
@@ -103,7 +131,7 @@
   ]
 }
 
-package("appmgr_tests") {
+package("appmgr_unittests") {
   testonly = true
   deprecated_system_image = true
 
@@ -116,3 +144,17 @@
     },
   ]
 }
+
+package("appmgr_integrationtests") {
+  testonly = true
+  deprecated_system_image = true
+
+  deps = [
+    "integration_tests:tests",
+  ]
+  tests = [
+    {
+      name = "appmgr_integration_tests"
+    },
+  ]
+}
diff --git a/bin/appmgr/appmgr.cc b/bin/appmgr/appmgr.cc
new file mode 100644
index 0000000..ad1424c
--- /dev/null
+++ b/bin/appmgr/appmgr.cc
@@ -0,0 +1,75 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/appmgr/appmgr.h"
+
+namespace fuchsia {
+namespace sys {
+namespace {
+constexpr char kRootLabel[] = "app";
+}  // namespace
+
+Appmgr::Appmgr(async_t* async, AppmgrArgs args)
+    : loader_vfs_(async),
+      loader_dir_(fbl::AdoptRef(new fs::PseudoDir())),
+      publish_vfs_(async),
+      publish_dir_(fbl::AdoptRef(new fs::PseudoDir())),
+      sysmgr_url_(std::move(args.sysmgr_url)),
+      sysmgr_args_(std::move(args.sysmgr_args)) {
+  // 1. Serve loader.
+  loader_dir_->AddEntry(
+      Loader::Name_, fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
+        root_loader_.AddBinding(
+            fidl::InterfaceRequest<Loader>(std::move(channel)));
+        return ZX_OK;
+      })));
+
+  zx::channel h1, h2;
+  if (zx::channel::create(0, &h1, &h2) < 0) {
+    FXL_LOG(FATAL) << "Appmgr unable to create channel.";
+    return;
+  }
+
+  if (loader_vfs_.ServeDirectory(loader_dir_, std::move(h2)) != ZX_OK) {
+    FXL_LOG(FATAL) << "Appmgr unable to serve directory.";
+    return;
+  }
+
+  RealmArgs realm_args{nullptr, std::move(h1), kRootLabel,
+                       args.run_virtual_console};
+  root_realm_ = std::make_unique<Realm>(std::move(realm_args));
+
+  // 2. Publish outgoing directories.
+  if (args.pa_directory_request != ZX_HANDLE_INVALID) {
+    auto svc = fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
+      return root_realm_->BindSvc(std::move(channel));
+    }));
+    publish_dir_->AddEntry("hub", root_realm_->hub_dir());
+    publish_dir_->AddEntry("svc", svc);
+    publish_vfs_.ServeDirectory(publish_dir_,
+                                zx::channel(args.pa_directory_request));
+  }
+
+  // 3. Run sysmgr
+  auto run_sysmgr = [this] {
+    LaunchInfo launch_info;
+    launch_info.url = sysmgr_url_;
+    launch_info.arguments.reset(sysmgr_args_);
+    root_realm_->CreateComponent(std::move(launch_info), sysmgr_.NewRequest());
+  };
+
+  if (!args.retry_sysmgr_crash) {
+    run_sysmgr();
+    return;
+  }
+  async::PostTask(async, [this, &run_sysmgr] {
+    run_sysmgr();
+    sysmgr_.set_error_handler(run_sysmgr);
+  });
+}
+
+Appmgr::~Appmgr() = default;
+
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/bin/appmgr/appmgr.h b/bin/appmgr/appmgr.h
new file mode 100644
index 0000000..85afbc6
--- /dev/null
+++ b/bin/appmgr/appmgr.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_APPMGR_APPMGR_H_
+#define GARNET_BIN_APPMGR_APPMGR_H_
+
+#include <fs/pseudo-dir.h>
+#include <fs/service.h>
+#include <fs/synchronous-vfs.h>
+
+#include "garnet/bin/appmgr/realm.h"
+#include "garnet/bin/appmgr/root_loader.h"
+#include "lib/fxl/macros.h"
+
+namespace fuchsia {
+namespace sys {
+
+struct AppmgrArgs {
+  zx_handle_t pa_directory_request;
+  std::string sysmgr_url;
+  fidl::VectorPtr<fidl::StringPtr> sysmgr_args;
+  bool run_virtual_console;
+  bool retry_sysmgr_crash;
+};
+
+class Appmgr {
+ public:
+  Appmgr(async_t* async, AppmgrArgs args);
+  ~Appmgr();
+
+ private:
+  fs::SynchronousVfs loader_vfs_;
+  RootLoader root_loader_;
+  fbl::RefPtr<fs::PseudoDir> loader_dir_;
+
+  std::unique_ptr<Realm> root_realm_;
+  fs::SynchronousVfs publish_vfs_;
+  fbl::RefPtr<fs::PseudoDir> publish_dir_;
+
+  ComponentControllerPtr sysmgr_;
+  std::string sysmgr_url_;
+  fidl::VectorPtr<fidl::StringPtr> sysmgr_args_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(Appmgr);
+};
+
+}  // namespace sys
+}  // namespace fuchsia
+
+#endif  // GARNET_BIN_APPMGR_APPMGR_H_
diff --git a/bin/appmgr/appmgr_unittest.cc b/bin/appmgr/appmgr_unittest.cc
new file mode 100644
index 0000000..69e8010
--- /dev/null
+++ b/bin/appmgr/appmgr_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/appmgr/appmgr.h"
+
+#include <fbl/ref_ptr.h>
+#include <fs/pseudo-dir.h>
+#include <lib/async-loop/cpp/loop.h>
+#include <zx/channel.h>
+
+#include "gtest/gtest.h"
+
+namespace fuchsia {
+namespace sys {
+namespace {
+
+TEST(Appmgr, RunUntilIdle) {
+  async::Loop loop(&kAsyncLoopConfigMakeDefault);
+  AppmgrArgs args{.pa_directory_request = ZX_HANDLE_INVALID,
+                  .sysmgr_url = "sysmgr",
+                  .sysmgr_args = {},
+                  .run_virtual_console = false,
+                  .retry_sysmgr_crash = false};
+  Appmgr appmgr(loop.async(), std::move(args));
+  EXPECT_FALSE(loop.RunUntilIdle());
+}
+
+}  // namespace
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/bin/appmgr/component_container.h b/bin/appmgr/component_container.h
new file mode 100644
index 0000000..b287878
--- /dev/null
+++ b/bin/appmgr/component_container.h
@@ -0,0 +1,15 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_APPMGR_COMPONENT_CONTAINER_H_
+#define GARNET_BIN_APPMGR_COMPONENT_CONTAINER_H_
+
+template <typename T>
+class ComponentContainer {
+ public:
+  virtual std::unique_ptr<T> ExtractComponent(T* controller) = 0;
+  virtual ~ComponentContainer(){};
+};
+
+#endif  // GARNET_BIN_APPMGR_COMPONENT_CONTAINER_H_
diff --git a/bin/appmgr/component_controller_impl.cc b/bin/appmgr/component_controller_impl.cc
index 47a4897..1b5d98a 100644
--- a/bin/appmgr/component_controller_impl.cc
+++ b/bin/appmgr/component_controller_impl.cc
@@ -5,40 +5,35 @@
 #include "garnet/bin/appmgr/component_controller_impl.h"
 
 #include <fbl/string_printf.h>
-#include <fdio/util.h>
 #include <fs/pseudo-file.h>
 #include <fs/remote-dir.h>
 #include <lib/async/default.h>
+#include <lib/fdio/util.h>
+#include <lib/fit/function.h>
 
 #include <cinttypes>
 #include <utility>
 
+#include "garnet/bin/appmgr/component_container.h"
 #include "garnet/bin/appmgr/namespace.h"
-#include "garnet/bin/appmgr/realm.h"
 #include "lib/fsl/handles/object_info.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace fuchsia {
 namespace sys {
 
-ComponentControllerImpl::ComponentControllerImpl(
-    fidl::InterfaceRequest<ComponentController> request, Realm* realm,
-    std::unique_ptr<archive::FileSystem> fs, zx::process process,
-    std::string url, std::string args, std::string label,
-    fxl::RefPtr<Namespace> ns, ExportedDirType export_dir_type,
-    zx::channel exported_dir, zx::channel client_request)
+ComponentControllerBase::ComponentControllerBase(
+    fidl::InterfaceRequest<ComponentController> request,
+    std::unique_ptr<archive::FileSystem> fs, std::string url, std::string args,
+    std::string label, std::string hub_instance_id, fxl::RefPtr<Namespace> ns,
+    ExportedDirType export_dir_type, zx::channel exported_dir,
+    zx::channel client_request)
     : binding_(this),
-      realm_(realm),
       fs_(std::move(fs)),
-      process_(std::move(process)),
       label_(std::move(label)),
-      koid_(std::to_string(fsl::GetKoid(process_.get()))),
+      hub_instance_id_(std::move(hub_instance_id)),
       hub_(fbl::AdoptRef(new fs::PseudoDir())),
       exported_dir_(std::move(exported_dir)),
-      ns_(std::move(ns)),
-      wait_(this, process_.get(), ZX_TASK_TERMINATED) {
-  zx_status_t status = wait_.Begin(async_get_default());
-  FXL_DCHECK(status == ZX_OK);
+      ns_(std::move(ns)) {
   if (request.is_valid()) {
     binding_.Bind(std::move(request));
     binding_.set_error_handler([this] { Kill(); });
@@ -56,9 +51,8 @@
       fdio_service_clone_to(exported_dir_.get(), client_request.release());
     }
   }
+
   hub_.SetName(label_);
-  hub_.SetJobId(realm_->koid());
-  hub_.SetProcessId(koid_);
   hub_.AddEntry("url", fbl::move(url));
   hub_.AddEntry("args", fbl::move(args));
   if (export_dir_type == ExportedDirType::kPublicDebugCtrlLayout) {
@@ -72,24 +66,48 @@
   }
 }
 
+ComponentControllerBase::~ComponentControllerBase() {}
+
+HubInfo ComponentControllerBase::HubInfo() {
+  return fuchsia::sys::HubInfo(label_, hub_instance_id_, hub_.dir());
+}
+
+void ComponentControllerBase::Detach() { binding_.set_error_handler(nullptr); }
+
+ComponentControllerImpl::ComponentControllerImpl(
+    fidl::InterfaceRequest<ComponentController> request,
+    ComponentContainer<ComponentControllerImpl>* container, std::string job_id,
+    std::unique_ptr<archive::FileSystem> fs, zx::process process,
+    std::string url, std::string args, std::string label,
+    fxl::RefPtr<Namespace> ns, ExportedDirType export_dir_type,
+    zx::channel exported_dir, zx::channel client_request)
+    : ComponentControllerBase(
+          std::move(request), std::move(fs), std::move(url), std::move(args),
+          std::move(label), std::to_string(fsl::GetKoid(process.get())),
+          std::move(ns), std::move(export_dir_type), std::move(exported_dir),
+          std::move(client_request)),
+      container_(container),
+      process_(std::move(process)),
+      koid_(std::to_string(fsl::GetKoid(process_.get()))),
+      wait_(this, process_.get(), ZX_TASK_TERMINATED) {
+  zx_status_t status = wait_.Begin(async_get_default());
+  FXL_DCHECK(status == ZX_OK);
+
+  hub()->SetJobId(job_id);
+  hub()->SetProcessId(koid_);
+}
+
 ComponentControllerImpl::~ComponentControllerImpl() {
   // Two ways we end up here:
   // 1) OnHandleReady() destroys this object; in which case, process is dead.
   // 2) Our owner destroys this object; in which case, the process may still be
   //    alive.
-  if (process_) process_.kill();
-}
-
-HubInfo ComponentControllerImpl::HubInfo() {
-  return fuchsia::sys::HubInfo(label_, koid_, hub_.dir());
+  if (process_)
+    process_.kill();
 }
 
 void ComponentControllerImpl::Kill() { process_.kill(); }
 
-void ComponentControllerImpl::Detach() {
-  binding_.set_error_handler(fxl::Closure());
-}
-
 bool ComponentControllerImpl::SendReturnCodeIfTerminated() {
   // Get process info.
   zx_info_process_t process_info;
@@ -113,6 +131,17 @@
   SendReturnCodeIfTerminated();
 }
 
+zx_status_t ComponentControllerImpl::AddSubComponentHub(
+    const fuchsia::sys::HubInfo& hub_info) {
+  hub()->EnsureComponentDir();
+  return hub()->AddComponent(hub_info);
+}
+
+zx_status_t ComponentControllerImpl::RemoveSubComponentHub(
+    const fuchsia::sys::HubInfo& hub_info) {
+  return hub()->RemoveComponent(hub_info);
+}
+
 // Called when process terminates, regardless of if Kill() was invoked.
 void ComponentControllerImpl::Handler(async_t* async, async::WaitBase* wait,
                                       zx_status_t status,
@@ -126,10 +155,43 @@
 
   process_.reset();
 
-  realm_->ExtractApplication(this);
-  // The destructor of the temporary returned by ExtractApplication destroys
+  container_->ExtractComponent(this);
+  // The destructor of the temporary returned by ExtractComponent destroys
   // |this| at the end of the previous statement.
 }
 
+ComponentBridge::ComponentBridge(
+    fidl::InterfaceRequest<ComponentController> request,
+    ComponentControllerPtr remote_controller,
+    ComponentContainer<ComponentBridge>* container,
+    std::unique_ptr<archive::FileSystem> fs, std::string url, std::string args,
+    std::string label, std::string hub_instance_id, fxl::RefPtr<Namespace> ns,
+    ExportedDirType export_dir_type, zx::channel exported_dir,
+    zx::channel client_request)
+    : ComponentControllerBase(
+          std::move(request), std::move(fs), std::move(url), std::move(args),
+          std::move(label), hub_instance_id, std::move(ns),
+          std::move(export_dir_type), std::move(exported_dir),
+          std::move(client_request)),
+      remote_controller_(std::move(remote_controller)),
+      container_(std::move(container)) {
+  remote_controller_.set_error_handler(
+      [this] { container_->ExtractComponent(this); });
+  // The destructor of the temporary returned by ExtractComponent destroys
+  // |this| at the end of the previous statement.
+}
+
+ComponentBridge::~ComponentBridge() {}
+
+void ComponentBridge::SetParentJobId(const std::string& id) {
+  hub()->SetJobId(id);
+}
+
+void ComponentBridge::Kill() { remote_controller_->Kill(); }
+
+void ComponentBridge::Wait(WaitCallback callback) {
+  remote_controller_->Wait(callback);
+}
+
 }  // namespace sys
 }  // namespace fuchsia
diff --git a/bin/appmgr/component_controller_impl.h b/bin/appmgr/component_controller_impl.h
index e543e13..0fe0405 100644
--- a/bin/appmgr/component_controller_impl.h
+++ b/bin/appmgr/component_controller_impl.h
@@ -5,11 +5,12 @@
 #ifndef GARNET_BIN_APPMGR_COMPONENT_CONTROLLER_IMPL_H_
 #define GARNET_BIN_APPMGR_COMPONENT_CONTROLLER_IMPL_H_
 
-#include <fuchsia/sys/cpp/fidl.h>
 #include <fs/pseudo-dir.h>
+#include <fuchsia/sys/cpp/fidl.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/zx/process.h>
 
+#include "garnet/bin/appmgr/component_container.h"
 #include "garnet/bin/appmgr/hub/component_hub.h"
 #include "garnet/bin/appmgr/hub/hub_info.h"
 #include "garnet/bin/appmgr/namespace.h"
@@ -21,7 +22,6 @@
 
 namespace fuchsia {
 namespace sys {
-class Realm;
 
 enum class ExportedDirType {
   // Legacy exported directory layout where each file / service is exposed at
@@ -37,26 +37,59 @@
   kPublicDebugCtrlLayout,
 };
 
-class ComponentControllerImpl : public ComponentController {
+class ComponentControllerBase : public ComponentController {
  public:
-  ComponentControllerImpl(fidl::InterfaceRequest<ComponentController> request,
-                          Realm* realm, std::unique_ptr<archive::FileSystem> fs,
-                          zx::process process, std::string url,
-                          std::string args, std::string label,
+  ComponentControllerBase(fidl::InterfaceRequest<ComponentController> request,
+                          std::unique_ptr<archive::FileSystem> fs,
+                          std::string url, std::string args, std::string label,
+                          std::string hub_instance_id,
                           fxl::RefPtr<Namespace> ns,
                           ExportedDirType export_dir_type,
                           zx::channel exported_dir, zx::channel client_request);
-  ~ComponentControllerImpl() override;
+  ~ComponentControllerBase() override;
 
+ public:
   HubInfo HubInfo();
-
   const std::string& label() const { return label_; }
-  const std::string& koid() const { return koid_; }
   const fbl::RefPtr<fs::PseudoDir>& hub_dir() const { return hub_.dir(); }
 
   // |ComponentController| implementation:
-  void Kill() override;
   void Detach() override;
+
+ protected:
+  ComponentHub* hub() { return &hub_; }
+
+ private:
+  fidl::Binding<ComponentController> binding_;
+  std::unique_ptr<archive::FileSystem> fs_;
+  std::string label_;
+  std::string hub_instance_id_;
+
+  ComponentHub hub_;
+
+  zx::channel exported_dir_;
+
+  fxl::RefPtr<Namespace> ns_;
+};
+
+class ComponentControllerImpl : public ComponentControllerBase {
+ public:
+  ComponentControllerImpl(
+      fidl::InterfaceRequest<ComponentController> request,
+      ComponentContainer<ComponentControllerImpl>* container,
+      std::string job_id, std::unique_ptr<archive::FileSystem> fs,
+      zx::process process, std::string url, std::string args, std::string label,
+      fxl::RefPtr<Namespace> ns, ExportedDirType export_dir_type,
+      zx::channel exported_dir, zx::channel client_request);
+  ~ComponentControllerImpl() override;
+
+  const std::string& koid() const { return koid_; }
+
+  zx_status_t AddSubComponentHub(const fuchsia::sys::HubInfo& hub_info);
+  zx_status_t RemoveSubComponentHub(const fuchsia::sys::HubInfo& hub_info);
+
+  // |ComponentController| implementation:
+  void Kill() override;
   void Wait(WaitCallback callback) override;
 
  private:
@@ -65,18 +98,10 @@
 
   bool SendReturnCodeIfTerminated();
 
-  fidl::Binding<ComponentController> binding_;
-  Realm* realm_;
-  std::unique_ptr<archive::FileSystem> fs_;
+  ComponentContainer<ComponentControllerImpl>* container_;
   zx::process process_;
-  std::string label_;
   const std::string koid_;
   std::vector<WaitCallback> wait_callbacks_;
-  ComponentHub hub_;
-
-  zx::channel exported_dir_;
-
-  fxl::RefPtr<Namespace> ns_;
 
   async::WaitMethod<ComponentControllerImpl, &ComponentControllerImpl::Handler>
       wait_;
@@ -84,6 +109,34 @@
   FXL_DISALLOW_COPY_AND_ASSIGN(ComponentControllerImpl);
 };
 
+// This class acts as a bridge between the components created by ComponentRunner
+// and |request|.
+class ComponentBridge : public ComponentControllerBase {
+ public:
+  ComponentBridge(fidl::InterfaceRequest<ComponentController> request,
+                  ComponentControllerPtr remote_controller,
+                  ComponentContainer<ComponentBridge>* container,
+                  std::unique_ptr<archive::FileSystem> fs, std::string url,
+                  std::string args, std::string label,
+                  std::string hub_instance_id, fxl::RefPtr<Namespace> ns,
+                  ExportedDirType export_dir_type, zx::channel exported_dir,
+                  zx::channel client_request);
+
+  ~ComponentBridge() override;
+
+  void SetParentJobId(const std::string& id);
+
+  // |ComponentController| implementation:
+  void Kill() override;
+  void Wait(WaitCallback callback) override;
+
+ private:
+  ComponentControllerPtr remote_controller_;
+  ComponentContainer<ComponentBridge>* container_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(ComponentBridge);
+};
+
 }  // namespace sys
 }  // namespace fuchsia
 
diff --git a/bin/appmgr/component_controller_unittest.cc b/bin/appmgr/component_controller_unittest.cc
new file mode 100644
index 0000000..bd9dd08
--- /dev/null
+++ b/bin/appmgr/component_controller_unittest.cc
@@ -0,0 +1,238 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/appmgr/component_controller_impl.h"
+
+#include <fs/pseudo-dir.h>
+#include <fs/remote-dir.h>
+#include <lib/fdio/spawn.h>
+
+#include "gtest/gtest.h"
+#include "lib/fsl/handles/object_info.h"
+#include "lib/gtest/test_with_message_loop.h"
+
+namespace fuchsia {
+namespace sys {
+namespace {
+
+class RealmMock : public ComponentContainer<ComponentControllerImpl> {
+ public:
+  size_t ComponentCount() { return components_.size(); }
+  const std::string koid() { return "5342"; }
+
+  void AddComponent(std::unique_ptr<ComponentControllerImpl> component);
+
+  std::unique_ptr<ComponentControllerImpl> ExtractComponent(
+      ComponentControllerImpl* controller) override;
+
+ private:
+  std::unordered_map<ComponentControllerBase*,
+                     std::unique_ptr<ComponentControllerImpl>>
+      components_;
+};
+
+void RealmMock::AddComponent(
+    std::unique_ptr<ComponentControllerImpl> component) {
+  auto key = component.get();
+  components_.emplace(key, std::move(component));
+}
+
+std::unique_ptr<ComponentControllerImpl> RealmMock::ExtractComponent(
+    ComponentControllerImpl* controller) {
+  auto it = components_.find(controller);
+  if (it == components_.end()) {
+    return nullptr;
+  }
+  auto component = std::move(it->second);
+
+  components_.erase(it);
+  return component;
+}
+
+class ComponentControllerTest : public gtest::TestWithMessageLoop {
+ public:
+  void SetUp() override {
+    gtest::TestWithMessageLoop::SetUp();
+
+    // create process
+    const char* argv[] = {"sh", NULL};
+    char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
+    zx_status_t status = fdio_spawn_etc(
+        ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL, "/boot/bin/sh", argv, NULL, 0,
+        NULL, process_.reset_and_get_address(), err_msg);
+    ASSERT_EQ(status, ZX_OK) << err_msg;
+    process_koid_ = std::to_string(fsl::GetKoid(process_.get()));
+  }
+
+  void TearDown() override {
+    if (process_) {
+      process_.kill();
+    }
+    gtest::TestWithMessageLoop::TearDown();
+  }
+
+ protected:
+  std::unique_ptr<ComponentControllerImpl> create_component(
+      ComponentControllerPtr& controller,
+      ExportedDirType export_dir_type = ExportedDirType::kLegacyFlatLayout,
+      zx::channel export_dir = zx::channel()) {
+    return std::make_unique<ComponentControllerImpl>(
+        controller.NewRequest(), &realm_, realm_.koid(), nullptr,
+        std::move(process_), "test-url", "test-arg", "test-label", nullptr,
+        export_dir_type, std::move(export_dir), zx::channel());
+  }
+
+  RealmMock realm_;
+  std::string process_koid_;
+  zx::process process_;
+};
+
+std::vector<std::string> split(const std::string& s, char delim) {
+  std::vector<std::string> tokens;
+  auto i = 0;
+  auto pos = s.find(delim);
+  while (pos != std::string::npos) {
+    tokens.push_back(s.substr(i, pos - i));
+    i = ++pos;
+    pos = s.find(delim, pos);
+  }
+  if (pos == std::string::npos)
+    tokens.push_back(s.substr(i, s.length()));
+  return tokens;
+}
+
+fbl::String get_value(const fbl::RefPtr<fs::PseudoDir>& hub_dir,
+                      std::string path) {
+  auto tokens = split(path, '/');
+  auto ntokens = tokens.size();
+  fbl::RefPtr<fs::Vnode> node = hub_dir;
+  fbl::RefPtr<fs::Vnode> pdir;
+  for (size_t i = 0; i < ntokens; i++) {
+    auto token = tokens[i];
+    pdir = node;
+    if (pdir->Lookup(&node, token) != ZX_OK) {
+      EXPECT_FALSE(true) << token << " not found";
+      return "";
+    }
+  }
+  fbl::RefPtr<fs::Vnode> file;
+  if (node->Open(ZX_FS_RIGHT_READABLE, &file) != ZX_OK) {
+    EXPECT_FALSE(true) << "cannot open: " << path;
+    return "";
+  }
+  char buf[1024];
+  size_t read_len;
+  file->Read(buf, sizeof(buf), 0, &read_len);
+  return fbl::String(buf, read_len);
+}
+
+bool path_exists(const fbl::RefPtr<fs::PseudoDir>& hub_dir, std::string path,
+                 fbl::RefPtr<fs::Vnode>* out = nullptr) {
+  auto tokens = split(path, '/');
+  auto ntokens = tokens.size();
+  fbl::RefPtr<fs::Vnode> dir = hub_dir;
+  fbl::RefPtr<fs::Vnode> pdir;
+  for (size_t i = 0; i < ntokens; i++) {
+    auto token = tokens[i];
+    pdir = dir;
+    if (pdir->Lookup(&dir, token) != ZX_OK) {
+      return false;
+    }
+  }
+  if (out != nullptr) {
+    *out = dir;
+  }
+  return true;
+}
+
+TEST_F(ComponentControllerTest, CreateAndKill) {
+  ComponentControllerPtr component_ptr;
+  auto component = create_component(component_ptr);
+  auto hub_info = component->HubInfo();
+
+  EXPECT_EQ(hub_info.label(), "test-label");
+  EXPECT_EQ(hub_info.koid(), process_koid_);
+
+  ASSERT_EQ(realm_.ComponentCount(), 0u);
+  realm_.AddComponent(std::move(component));
+
+  ASSERT_EQ(realm_.ComponentCount(), 1u);
+
+  bool wait = false;
+  component_ptr->Wait([&wait](int errcode) { wait = true; });
+  component_ptr->Kill();
+  EXPECT_TRUE(RunLoopUntilWithTimeout([&wait] { return wait; },
+                                      fxl::TimeDelta::FromSeconds(5)));
+
+  // make sure all messages are processed after wait was called
+  RunLoopUntilIdle();
+  EXPECT_EQ(realm_.ComponentCount(), 0u);
+}
+
+TEST_F(ComponentControllerTest, ControllerScope) {
+  bool wait = false;
+  auto hub_path = "c/test-label/" + process_koid_;
+  {
+    ComponentControllerPtr component_ptr;
+    auto component = create_component(component_ptr);
+    component->Wait([&wait](int errcode) { wait = true; });
+    realm_.AddComponent(std::move(component));
+
+    ASSERT_EQ(realm_.ComponentCount(), 1u);
+  }
+  EXPECT_TRUE(RunLoopUntilWithTimeout([&wait] { return wait; },
+                                      fxl::TimeDelta::FromSeconds(5)));
+
+  // make sure all messages are processed after wait was called
+  RunLoopUntilIdle();
+  EXPECT_EQ(realm_.ComponentCount(), 0u);
+}
+
+TEST_F(ComponentControllerTest, DetachController) {
+  bool wait = false;
+  {
+    ComponentControllerPtr component_ptr;
+    auto component = create_component(component_ptr);
+    component->Wait([&wait](int errcode) { wait = true; });
+    realm_.AddComponent(std::move(component));
+
+    ASSERT_EQ(realm_.ComponentCount(), 1u);
+
+    // detach controller before it goes out of scope and then test that our
+    // component did not die.
+    component_ptr->Detach();
+    RunLoopUntilIdle();
+  }
+
+  // make sure all messages are processed if Kill was called.
+  RunLoopUntilIdle();
+  ASSERT_FALSE(wait);
+  EXPECT_EQ(realm_.ComponentCount(), 1u);
+}
+
+TEST_F(ComponentControllerTest, Hub) {
+  zx::channel export_dir, export_dir_req;
+  ASSERT_EQ(zx::channel::create(0, &export_dir, &export_dir_req), ZX_OK);
+
+  ComponentControllerPtr component_ptr;
+
+  auto component =
+      create_component(component_ptr, ExportedDirType::kPublicDebugCtrlLayout,
+                       std::move(export_dir_req));
+
+  EXPECT_STREQ(get_value(component->hub_dir(), "name").c_str(), "test-label");
+  EXPECT_STREQ(get_value(component->hub_dir(), "args").c_str(), "test-arg");
+  EXPECT_STREQ(get_value(component->hub_dir(), "job-id").c_str(),
+               realm_.koid().c_str());
+  EXPECT_STREQ(get_value(component->hub_dir(), "url").c_str(), "test-url");
+  EXPECT_STREQ(get_value(component->hub_dir(), "process-id").c_str(),
+               process_koid_.c_str());
+  fbl::RefPtr<fs::Vnode> out_dir;
+  ASSERT_TRUE(path_exists(component->hub_dir(), "out", &out_dir));
+  ASSERT_TRUE(out_dir->IsRemote());
+}
+
+}  // namespace
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/bin/appmgr/environment_controller_impl.cc b/bin/appmgr/environment_controller_impl.cc
index b5551f8..f54e180 100644
--- a/bin/appmgr/environment_controller_impl.cc
+++ b/bin/appmgr/environment_controller_impl.cc
@@ -6,8 +6,9 @@
 
 #include <utility>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/appmgr/realm.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace fuchsia {
 namespace sys {
@@ -38,7 +39,7 @@
 }
 
 void EnvironmentControllerImpl::Detach() {
-  binding_.set_error_handler(fxl::Closure());
+  binding_.set_error_handler(nullptr);
 }
 
 }  // namespace sys
diff --git a/bin/appmgr/hub/hub.cc b/bin/appmgr/hub/hub.cc
index 4014bbe..0fe8d6a 100644
--- a/bin/appmgr/hub/hub.cc
+++ b/bin/appmgr/hub/hub.cc
@@ -27,7 +27,10 @@
                             }))));
 }
 
-zx_status_t Hub::CreateComponentDir() {
+zx_status_t Hub::EnsureComponentDir() {
+  if (component_dir_) {
+    return ZX_OK;
+  }
   component_dir_ = fbl::AdoptRef(new fs::PseudoDir());
   return AddEntry("c", component_dir_);
 }
diff --git a/bin/appmgr/hub/hub.h b/bin/appmgr/hub/hub.h
index 270a5e3..d2bd17a 100644
--- a/bin/appmgr/hub/hub.h
+++ b/bin/appmgr/hub/hub.h
@@ -34,12 +34,11 @@
     return AddEntry("job-id", fbl::move(koid));
   }
 
+  zx_status_t EnsureComponentDir();
   zx_status_t AddComponent(const HubInfo& hub_info);
   zx_status_t RemoveComponent(const HubInfo& hub_info);
 
  protected:
-  zx_status_t CreateComponentDir();
-
   fbl::RefPtr<fs::PseudoDir> dir_;
   fbl::RefPtr<fs::PseudoDir> component_dir_;
 
diff --git a/bin/appmgr/hub/realm_hub.cc b/bin/appmgr/hub/realm_hub.cc
index a734007..dd589a8 100644
--- a/bin/appmgr/hub/realm_hub.cc
+++ b/bin/appmgr/hub/realm_hub.cc
@@ -17,7 +17,7 @@
 RealmHub::RealmHub(fbl::RefPtr<fs::PseudoDir> root)
     : Hub(root), realm_dir_(fbl::AdoptRef(new fs::PseudoDir())) {
   AddEntry("r", realm_dir_);
-  CreateComponentDir();
+  EnsureComponentDir();
 }
 
 zx_status_t RealmHub::AddRealm(const HubInfo& hub_info) {
diff --git a/bin/appmgr/integration_tests/BUILD.gn b/bin/appmgr/integration_tests/BUILD.gn
new file mode 100644
index 0000000..4a04a5a
--- /dev/null
+++ b/bin/appmgr/integration_tests/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+
+executable("tests") {
+  testonly = true
+
+  output_name = "appmgr_integration_tests"
+
+  sources = [
+    "hub_integration_test.cc",
+  ]
+
+  deps = [
+    "//garnet/public/lib/fxl",
+    "//garnet/public/lib/fxl/test:gtest_main",
+  ]
+}
diff --git a/bin/appmgr/integration_tests/hub_integration_test.cc b/bin/appmgr/integration_tests/hub_integration_test.cc
new file mode 100644
index 0000000..3eb8fe5
--- /dev/null
+++ b/bin/appmgr/integration_tests/hub_integration_test.cc
@@ -0,0 +1,34 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <glob.h>
+
+#include "gtest/gtest.h"
+#include "lib/fxl/strings/string_printf.h"
+
+namespace fuchsia {
+namespace sys {
+namespace {
+
+TEST(ProbeHub, Component) {
+  auto glob_str = fxl::StringPrintf("/hub/c/sysmgr/*/out/debug");
+  glob_t globbuf;
+  ASSERT_EQ(glob(glob_str.data(), 0, NULL, &globbuf), 0)
+      << glob_str << " does not exist.";
+  ASSERT_EQ(globbuf.gl_pathc, 1u);
+  globfree(&globbuf);
+}
+
+TEST(ProbeHub, Realm) {
+  auto glob_str = fxl::StringPrintf("/hub/r/sys/*/c/");
+  glob_t globbuf;
+  ASSERT_EQ(glob(glob_str.data(), 0, NULL, &globbuf), 0)
+      << glob_str << " does not exist.";
+  ASSERT_EQ(globbuf.gl_pathc, 1u);
+  globfree(&globbuf);
+}
+
+}  // namespace
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/bin/appmgr/main.cc b/bin/appmgr/main.cc
index 9a55e78..f2f61ef 100644
--- a/bin/appmgr/main.cc
+++ b/bin/appmgr/main.cc
@@ -2,85 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <stdlib.h>
-
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <fs/pseudo-dir.h>
-#include <fs/service.h>
-#include <fs/synchronous-vfs.h>
-#include <fs/vfs.h>
 #include <lib/async-loop/cpp/loop.h>
-#include <lib/async/cpp/task.h>
 #include <zircon/process.h>
 #include <zircon/processargs.h>
 
-#include "garnet/bin/appmgr/dynamic_library_loader.h"
-#include "garnet/bin/appmgr/realm.h"
-#include "garnet/bin/appmgr/root_loader.h"
+#include "garnet/bin/appmgr/appmgr.h"
 #include "lib/fxl/command_line.h"
-#include "lib/fxl/files/file.h"
-#include "lib/fxl/log_settings.h"
-
-namespace {
-
-constexpr char kRootLabel[] = "app";
-
-void PublishRootDir(fuchsia::sys::Realm* root, fs::SynchronousVfs* vfs) {
-  static zx_handle_t request = zx_get_startup_handle(PA_DIRECTORY_REQUEST);
-  if (request == ZX_HANDLE_INVALID)
-    return;
-  fbl::RefPtr<fs::PseudoDir> dir(fbl::AdoptRef(new fs::PseudoDir()));
-  auto svc = fbl::AdoptRef(new fs::Service([root](zx::channel channel) {
-    return root->BindSvc(std::move(channel));
-  }));
-  dir->AddEntry("hub", root->hub_dir());
-  dir->AddEntry("svc", svc);
-
-  vfs->ServeDirectory(dir, zx::channel(request));
-  request = ZX_HANDLE_INVALID;
-}
-
-}  // namespace
 
 int main(int argc, char** argv) {
   auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
 
   async::Loop loop(&kAsyncLoopConfigMakeDefault);
+  auto request = zx_get_startup_handle(PA_DIRECTORY_REQUEST);
 
-  fs::SynchronousVfs vfs(loop.async());
-  fuchsia::sys::RootLoader root_loader;
-  fbl::RefPtr<fs::PseudoDir> directory(fbl::AdoptRef(new fs::PseudoDir()));
-  directory->AddEntry(
-      fuchsia::sys::Loader::Name_,
-      fbl::AdoptRef(new fs::Service([&root_loader](zx::channel channel) {
-        root_loader.AddBinding(
-            fidl::InterfaceRequest<fuchsia::sys::Loader>(std::move(channel)));
-        return ZX_OK;
-      })));
-
-  zx::channel h1, h2;
-  if (zx::channel::create(0, &h1, &h2) < 0)
-    return -1;
-  if (vfs.ServeDirectory(directory, std::move(h2)) != ZX_OK)
-    return -1;
-  fuchsia::sys::Realm root_realm(nullptr, std::move(h1), kRootLabel);
-  fs::SynchronousVfs publish_vfs(loop.async());
-  PublishRootDir(&root_realm, &publish_vfs);
-
-  fuchsia::sys::ComponentControllerPtr sysmgr;
-  auto run_sysmgr = [&root_realm, &sysmgr] {
-    fuchsia::sys::LaunchInfo launch_info;
-    launch_info.url = "sysmgr";
-    root_realm.CreateComponent(std::move(launch_info), sysmgr.NewRequest());
-  };
-
-  async::PostTask(loop.async(), [&run_sysmgr, &sysmgr] {
-    run_sysmgr();
-    sysmgr.set_error_handler(run_sysmgr);
-  });
+  fuchsia::sys::AppmgrArgs args{.pa_directory_request = std::move(request),
+                                .sysmgr_url = "sysmgr",
+                                .sysmgr_args = {},
+                                .run_virtual_console = true,
+                                .retry_sysmgr_crash = true};
+  fuchsia::sys::Appmgr appmgr(loop.async(), std::move(args));
 
   loop.Run();
   return 0;
diff --git a/bin/appmgr/namespace.cc b/bin/appmgr/namespace.cc
index 6d1ffd5..45f58e0 100644
--- a/bin/appmgr/namespace.cc
+++ b/bin/appmgr/namespace.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/bin/appmgr/namespace.h"
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <fuchsia/process/cpp/fidl.h>
 
 #include <utility>
diff --git a/bin/appmgr/namespace_builder.cc b/bin/appmgr/namespace_builder.cc
index 8ff0b79..a2531a2 100644
--- a/bin/appmgr/namespace_builder.cc
+++ b/bin/appmgr/namespace_builder.cc
@@ -4,8 +4,8 @@
 
 #include "garnet/bin/appmgr/namespace_builder.h"
 
-#include <fdio/limits.h>
-#include <fdio/util.h>
+#include <lib/fdio/limits.h>
+#include <lib/fdio/util.h>
 #include <zircon/processargs.h>
 
 #include <fcntl.h>
diff --git a/bin/appmgr/namespace_builder.h b/bin/appmgr/namespace_builder.h
index 9524b80..a558a1d 100644
--- a/bin/appmgr/namespace_builder.h
+++ b/bin/appmgr/namespace_builder.h
@@ -5,7 +5,8 @@
 #ifndef GARNET_BIN_APPMGR_NAMESPACE_BUILDER_H_
 #define GARNET_BIN_APPMGR_NAMESPACE_BUILDER_H_
 
-#include <fdio/namespace.h>
+#include <lib/fdio/namespace.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
 #include <vector>
@@ -30,7 +31,7 @@
   void AddServices(zx::channel services);
 
   // A factory function that returns a new directory that /hub points to.
-  using HubDirectoryFactory = std::function<zx::channel()>;
+  using HubDirectoryFactory = fit::function<zx::channel()>;
   void AddSandbox(const SandboxMetadata& sandbox,
                   const HubDirectoryFactory& hub_directory_factory);
 
diff --git a/bin/appmgr/namespace_builder_unittest.cc b/bin/appmgr/namespace_builder_unittest.cc
index 3e83d83..bb71e1a 100644
--- a/bin/appmgr/namespace_builder_unittest.cc
+++ b/bin/appmgr/namespace_builder_unittest.cc
@@ -10,17 +10,26 @@
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "third_party/rapidjson/rapidjson/document.h"
 
 namespace fuchsia {
 namespace sys {
 namespace {
 
 TEST(NamespaceBuilder, Control) {
+  rapidjson::Document document;
+  document.SetObject();
+  rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+  rapidjson::Value dev_array(rapidjson::kArrayType);
+  dev_array.PushBack("class/input", allocator);
+  dev_array.PushBack("class/display-controller", allocator);
+  document.AddMember("dev", dev_array, allocator);
+  rapidjson::Value feat_array(rapidjson::kArrayType);
+  feat_array.PushBack("vulkan", allocator);
+  document.AddMember("features", feat_array, allocator);
   SandboxMetadata sandbox;
-  EXPECT_TRUE(sandbox.Parse(R"JSON({
-    "dev": [ "class/input", "class/display-controller" ],
-    "features": [ "vulkan" ]
-  })JSON"));
+
+  EXPECT_TRUE(sandbox.Parse(document));
 
   NamespaceBuilder builder;
   builder.AddSandbox(sandbox, [] { return zx::channel(); });
@@ -48,10 +57,15 @@
 }
 
 TEST(NamespaceBuilder, Shell) {
+  rapidjson::Document document;
+  document.SetObject();
+  rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
+  rapidjson::Value feat_array(rapidjson::kArrayType);
+  feat_array.PushBack("shell", allocator);
+  document.AddMember("features", feat_array, allocator);
   SandboxMetadata sandbox;
-  EXPECT_TRUE(sandbox.Parse(R"JSON({
-    "features": [ "shell" ]
-  })JSON"));
+
+  EXPECT_TRUE(sandbox.Parse(document));
 
   NamespaceBuilder builder;
   builder.AddSandbox(sandbox, [] { return zx::channel(); });
@@ -66,32 +80,22 @@
   // /config/ssl is included because "shell" implies "root-ssl-certificates"
   EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/config/ssl") !=
               paths.end());
-  // While "shell" implies "root-ssl-certificates", it does NOT include /system/data/boringssl
-  // (see comment in namespace_builder.cc for details).
+  // While "shell" implies "root-ssl-certificates", it does NOT include
+  // /system/data/boringssl (see comment in namespace_builder.cc for details).
   EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/system/data/boringssl") ==
               paths.end());
 
   // Paths that are only part of "shell", not "root-ssl-certificates"
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/blob") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/boot") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/data") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/dev") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/hub") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/install") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/pkgfs") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/system") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/tmp") !=
-              paths.end());
-  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/volume") !=
-              paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/blob") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/boot") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/data") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/dev") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/hub") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/install") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/pkgfs") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/system") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/tmp") != paths.end());
+  EXPECT_TRUE(std::find(paths.begin(), paths.end(), "/volume") != paths.end());
 
   for (size_t i = 0; i < flat->count; ++i)
     zx_handle_close(flat->handle[i]);
diff --git a/bin/appmgr/realm.cc b/bin/appmgr/realm.cc
index 7753e2c..d1e4f12 100644
--- a/bin/appmgr/realm.cc
+++ b/bin/appmgr/realm.cc
@@ -5,10 +5,10 @@
 #include "garnet/bin/appmgr/realm.h"
 
 #include <fcntl.h>
-#include <fdio/namespace.h>
-#include <fdio/util.h>
 #include <launchpad/launchpad.h>
 #include <lib/async/default.h>
+#include <lib/fdio/namespace.h>
+#include <lib/fdio/util.h>
 #include <lib/zx/process.h>
 #include <unistd.h>
 #include <zircon/process.h>
@@ -24,6 +24,7 @@
 #include "garnet/bin/appmgr/runtime_metadata.h"
 #include "garnet/bin/appmgr/sandbox_metadata.h"
 #include "garnet/bin/appmgr/url_resolver.h"
+#include "garnet/bin/appmgr/util.h"
 #include "garnet/lib/far/format.h"
 #include "lib/app/cpp/connect.h"
 #include "lib/fsl/handles/object_info.h"
@@ -46,7 +47,6 @@
 constexpr char kAppArv0[] = "/pkg/bin/app";
 constexpr char kLegacyFlatExportedDirPath[] = "meta/legacy_flat_exported_dir";
 constexpr char kRuntimePath[] = "meta/runtime";
-constexpr char kSandboxPath[] = "meta/sandbox";
 
 enum class LaunchType {
   kProcess,
@@ -63,13 +63,6 @@
   return argv;
 }
 
-std::string GetLabelFromURL(const std::string& url) {
-  size_t last_slash = url.rfind('/');
-  if (last_slash == std::string::npos || last_slash + 1 == url.length())
-    return url;
-  return url.substr(last_slash + 1);
-}
-
 void PushFileDescriptor(fuchsia::sys::FileDescriptorPtr fd, int new_fd,
                         std::vector<uint32_t>* ids,
                         std::vector<zx_handle_t>* handles) {
@@ -96,7 +89,7 @@
   if (!data)
     return zx::process();
 
-  std::string label = GetLabelFromURL(launch_info.url);
+  std::string label = util::GetLabelFromURL(launch_info.url);
   std::vector<const char*> argv = GetArgv(argv0, launch_info);
 
   std::vector<uint32_t> ids;
@@ -161,49 +154,13 @@
   return LaunchType::kProcess;
 }
 
-struct ExportedDirChannels {
-  // The client side of the channel serving connected application's exported
-  // dir.
-  zx::channel exported_dir;
-
-  // The server side of our client's |LaunchInfo.directory_request|.
-  zx::channel client_request;
-};
-
-ExportedDirChannels BindDirectory(LaunchInfo* launch_info) {
-  zx::channel exported_dir_server, exported_dir_client;
-  zx_status_t status =
-      zx::channel::create(0u, &exported_dir_server, &exported_dir_client);
-  if (status != ZX_OK) {
-    FXL_LOG(ERROR) << "Failed to create channel for service directory: status="
-                   << status;
-    return {zx::channel(), zx::channel()};
-  }
-
-  auto client_request = std::move(launch_info->directory_request);
-  launch_info->directory_request = std::move(exported_dir_server);
-  return {std::move(exported_dir_client), std::move(client_request)};
-}
-
-std::string GetArgsString(
-    const ::fidl::VectorPtr<::fidl::StringPtr>& arguments) {
-  std::string args = "";
-  if (!arguments->empty()) {
-    std::ostringstream buf;
-    std::copy(arguments->begin(), arguments->end() - 1,
-              std::ostream_iterator<std::string>(buf, " "));
-    buf << *arguments->rbegin();
-    args = buf.str();
-  }
-  return args;
-}
-
 }  // namespace
 
 uint32_t Realm::next_numbered_label_ = 1u;
 
-Realm::Realm(Realm* parent, zx::channel host_directory, fidl::StringPtr label)
-    : parent_(parent),
+Realm::Realm(RealmArgs args)
+    : parent_(args.parent),
+      run_virtual_console_(args.run_virtual_console),
       default_namespace_(
           fxl::MakeRefCounted<Namespace>(nullptr, this, nullptr)),
       hub_(fbl::AdoptRef(new fs::PseudoDir())),
@@ -222,16 +179,17 @@
   FXL_CHECK(job_.duplicate(kChildJobRights, &job_for_child_) == ZX_OK);
 
   koid_ = std::to_string(fsl::GetKoid(job_.get()));
-  if (label->size() == 0)
+  if (args.label->size() == 0)
     label_ = fxl::StringPrintf(kNumberedLabelFormat, next_numbered_label_++);
   else
-    label_ = label.get().substr(0, fuchsia::sys::kLabelMaxLength);
+    label_ = args.label.get().substr(0, fuchsia::sys::kLabelMaxLength);
 
   fsl::SetObjectName(job_.get(), label_);
   hub_.SetName(label_);
   hub_.SetJobId(koid_);
 
-  default_namespace_->services().set_backing_dir(std::move(host_directory));
+  default_namespace_->services().set_backing_dir(
+      std::move(args.host_directory));
 
   ServiceProviderPtr service_provider;
   default_namespace_->services().AddBinding(service_provider.NewRequest());
@@ -265,9 +223,9 @@
     zx::channel host_directory, fidl::InterfaceRequest<Environment> environment,
     fidl::InterfaceRequest<EnvironmentController> controller_request,
     fidl::StringPtr label) {
+  RealmArgs args{this, std::move(host_directory), label, false};
   auto controller = std::make_unique<EnvironmentControllerImpl>(
-      std::move(controller_request),
-      std::make_unique<Realm>(this, std::move(host_directory), label));
+      std::move(controller_request), std::make_unique<Realm>(std::move(args)));
   Realm* child = controller->realm();
   child->AddBinding(std::move(environment));
 
@@ -283,7 +241,7 @@
   child->default_namespace_->services().ServeDirectory(
       std::move(root_realm->svc_channel_server_));
 
-  if (!parent()) {
+  if (run_virtual_console_) {
     child->CreateShell("/boot/bin/run-vc");
     child->CreateShell("/boot/bin/run-vc");
     child->CreateShell("/boot/bin/run-vc");
@@ -292,7 +250,8 @@
 
 void Realm::CreateComponent(
     LaunchInfo launch_info,
-    fidl::InterfaceRequest<ComponentController> controller) {
+    fidl::InterfaceRequest<ComponentController> controller,
+    ComponentObjectCreatedCallback callback) {
   if (launch_info.url.get().empty()) {
     FXL_LOG(ERROR) << "Cannot create application because launch_info contains"
                       " an empty url";
@@ -310,7 +269,8 @@
   fidl::StringPtr url = launch_info.url;
   loader_->LoadComponent(
       url, fxl::MakeCopyable([this, launch_info = std::move(launch_info),
-                              controller = std::move(controller)](
+                              controller = std::move(controller),
+                              callback = fbl::move(callback)](
                                  PackagePtr package) mutable {
         fxl::RefPtr<Namespace> ns = default_namespace_;
         if (launch_info.additional_services) {
@@ -327,18 +287,18 @@
               case LaunchType::kProcess:
                 CreateComponentWithProcess(
                     std::move(package), std::move(launch_info),
-                    std::move(controller), std::move(ns));
+                    std::move(controller), std::move(ns), fbl::move(callback));
                 break;
               case LaunchType::kArchive:
                 CreateComponentFromPackage(
                     std::move(package), std::move(launch_info),
-                    std::move(controller), std::move(ns));
+                    std::move(controller), std::move(ns), fbl::move(callback));
                 break;
             }
           } else if (package->directory) {
-            CreateComponentFromPackage(std::move(package),
-                                       std::move(launch_info),
-                                       std::move(controller), std::move(ns));
+            CreateComponentFromPackage(
+                std::move(package), std::move(launch_info),
+                std::move(controller), std::move(ns), fbl::move(callback));
           }
         }
       }));
@@ -381,7 +341,7 @@
   return controller;
 }
 
-std::unique_ptr<ComponentControllerImpl> Realm::ExtractApplication(
+std::unique_ptr<ComponentControllerImpl> Realm::ExtractComponent(
     ComponentControllerImpl* controller) {
   auto it = applications_.find(controller);
   if (it == applications_.end()) {
@@ -403,7 +363,7 @@
 void Realm::CreateComponentWithProcess(
     PackagePtr package, LaunchInfo launch_info,
     fidl::InterfaceRequest<ComponentController> controller,
-    fxl::RefPtr<Namespace> ns) {
+    fxl::RefPtr<Namespace> ns, ComponentObjectCreatedCallback callback) {
   zx::channel svc = ns->services().OpenAsDirectory();
   if (!svc)
     return;
@@ -425,22 +385,25 @@
   if (!fsl::SizedVmo::FromTransport(std::move(*package->data), &executable))
     return;
 
-  const std::string args = GetArgsString(launch_info.arguments);
+  const std::string args = util::GetArgsString(launch_info.arguments);
   const std::string url = launch_info.url;  // Keep a copy before moving it.
-  auto channels = BindDirectory(&launch_info);
+  auto channels = util::BindDirectory(&launch_info);
   zx::process process =
       CreateProcess(job_for_child_, std::move(executable), url,
                     std::move(launch_info), zx::channel(), builder.Build());
 
   if (process) {
     auto application = std::make_unique<ComponentControllerImpl>(
-        std::move(controller), this, nullptr, std::move(process), url,
-        std::move(args), GetLabelFromURL(url), std::move(ns),
+        std::move(controller), this, koid_, nullptr, std::move(process), url,
+        std::move(args), util::GetLabelFromURL(url), std::move(ns),
         ExportedDirType::kPublicDebugCtrlLayout,
         std::move(channels.exported_dir), std::move(channels.client_request));
     // update hub
     hub_.AddComponent(application->HubInfo());
     ComponentControllerImpl* key = application.get();
+    if (callback != nullptr) {
+      callback(key);
+    }
     applications_.emplace(key, std::move(application));
   }
 }
@@ -448,7 +411,7 @@
 void Realm::CreateComponentFromPackage(
     PackagePtr package, LaunchInfo launch_info,
     fidl::InterfaceRequest<ComponentController> controller,
-    fxl::RefPtr<Namespace> ns) {
+    fxl::RefPtr<Namespace> ns, ComponentObjectCreatedCallback callback) {
   zx::channel svc = ns->services().OpenAsDirectory();
   if (!svc)
     return;
@@ -468,7 +431,6 @@
         std::make_unique<archive::FileSystem>(std::move(package->data->vmo));
     pkg = pkg_fs->OpenAsDirectory();
     pkg_fs->GetFileAsString(cmx_path, &cmx_data);
-    pkg_fs->GetFileAsString(kSandboxPath, &sandbox_data);
     if (!pkg_fs->GetFileAsString(kRuntimePath, &runtime_data))
       app_data = pkg_fs->GetFileAsVMO(kAppPath);
     exported_dir_layout = pkg_fs->IsFile(kLegacyFlatExportedDirPath)
@@ -480,7 +442,6 @@
     if (!cmx_path.empty()) {
       files::ReadFileToStringAt(fd.get(), cmx_path, &cmx_data);
     }
-    files::ReadFileToStringAt(fd.get(), kSandboxPath, &sandbox_data);
     if (!files::ReadFileToStringAt(fd.get(), kRuntimePath, &runtime_data))
       VmoFromFilenameAt(fd.get(), kAppPath, &app_data);
     exported_dir_layout = files::IsFileAt(fd.get(), kLegacyFlatExportedDirPath)
@@ -502,20 +463,13 @@
   builder.AddPackage(std::move(pkg));
   builder.AddServices(std::move(svc));
 
-  // If meta/*.cmx exists, read sandbox data from it, instead of meta/sandbox.
-  // TODO(CP-37): Remove meta/sandbox once completely migrated.
-  if (!sandbox_data.empty() || !cmx_data.empty()) {
+  // If meta/*.cmx exists, read sandbox data from it.
+  if (!cmx_data.empty()) {
     SandboxMetadata sandbox;
 
     CmxMetadata cmx;
     if (!cmx_data.empty()) {
       sandbox.Parse(cmx.ParseSandboxMetadata(cmx_data));
-    } else {
-      if (!sandbox.Parse(sandbox_data)) {
-        FXL_LOG(ERROR) << "Failed to parse sandbox metadata for "
-                       << launch_info.url;
-        return;
-      }
     }
 
     // If an app has the "shell" feature, then we use the libraries from the
@@ -534,22 +488,25 @@
   builder.AddFlatNamespace(std::move(launch_info.flat_namespace));
 
   if (app_data) {
-    const std::string args = GetArgsString(launch_info.arguments);
+    const std::string args = util::GetArgsString(launch_info.arguments);
     const std::string url = launch_info.url;  // Keep a copy before moving it.
-    auto channels = BindDirectory(&launch_info);
+    auto channels = util::BindDirectory(&launch_info);
     zx::process process = CreateProcess(
         job_for_child_, std::move(app_data), kAppArv0, std::move(launch_info),
         std::move(loader_service), builder.Build());
 
     if (process) {
       auto application = std::make_unique<ComponentControllerImpl>(
-          std::move(controller), this, std::move(pkg_fs), std::move(process),
-          url, std::move(args), GetLabelFromURL(url), std::move(ns),
-          exported_dir_layout, std::move(channels.exported_dir),
+          std::move(controller), this, koid_, std::move(pkg_fs),
+          std::move(process), url, std::move(args), util::GetLabelFromURL(url),
+          std::move(ns), exported_dir_layout, std::move(channels.exported_dir),
           std::move(channels.client_request));
       // update hub
       hub_.AddComponent(application->HubInfo());
       ComponentControllerImpl* key = application.get();
+      if (callback != nullptr) {
+        callback(key);
+      }
       applications_.emplace(key, std::move(application));
     }
   } else {
@@ -589,14 +546,11 @@
     LaunchInfo runner_launch_info;
     runner_launch_info.url = runner;
     runner_launch_info.directory_request = runner_services.NewRequest();
-    CreateComponent(std::move(runner_launch_info),
-                    runner_controller.NewRequest());
-
-    runner_controller.set_error_handler(
+    result.first->second = std::make_unique<RunnerHolder>(
+        std::move(runner_services), std::move(runner_controller),
+        std::move(runner_launch_info), this,
         [this, runner] { runners_.erase(runner); });
 
-    result.first->second = std::make_unique<RunnerHolder>(
-        std::move(runner_services), std::move(runner_controller));
   } else if (!result.first->second) {
     // There was a cycle in the runner graph.
     FXL_LOG(ERROR) << "Detected a cycle in the runner graph for " << runner
diff --git a/bin/appmgr/realm.h b/bin/appmgr/realm.h
index 682e8d5..ea9c543 100644
--- a/bin/appmgr/realm.h
+++ b/bin/appmgr/realm.h
@@ -14,6 +14,7 @@
 #include <unordered_map>
 
 #include <fuchsia/sys/cpp/fidl.h>
+#include "garnet/bin/appmgr/component_container.h"
 #include "garnet/bin/appmgr/component_controller_impl.h"
 #include "garnet/bin/appmgr/environment_controller_impl.h"
 #include "garnet/bin/appmgr/hub/hub_info.h"
@@ -21,6 +22,7 @@
 #include "garnet/bin/appmgr/namespace.h"
 #include "garnet/bin/appmgr/runner_holder.h"
 #include "lib/fidl/cpp/binding_set.h"
+#include "lib/fit/function.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_ptr.h"
 #include "lib/fxl/strings/string_view.h"
@@ -29,9 +31,16 @@
 namespace fuchsia {
 namespace sys {
 
-class Realm {
+struct RealmArgs {
+  Realm* parent;
+  zx::channel host_directory;
+  fidl::StringPtr label;
+  bool run_virtual_console;
+};
+
+class Realm : public ComponentContainer<ComponentControllerImpl> {
  public:
-  Realm(Realm* parent, zx::channel host_directory, fidl::StringPtr label);
+  Realm(RealmArgs args);
   ~Realm();
 
   Realm* parent() const { return parent_; }
@@ -47,8 +56,12 @@
                        fidl::InterfaceRequest<EnvironmentController> controller,
                        fidl::StringPtr label);
 
+  using ComponentObjectCreatedCallback =
+      fit::function<void(ComponentControllerImpl* component)>;
+
   void CreateComponent(LaunchInfo launch_info,
-                       fidl::InterfaceRequest<ComponentController> controller);
+                       fidl::InterfaceRequest<ComponentController> controller,
+                       ComponentObjectCreatedCallback callback = nullptr);
 
   // Removes the child realm from this realm and returns the owning
   // reference to the child's controller. The caller of this function typically
@@ -60,8 +73,8 @@
   // reference to the application's controller. The caller of this function
   // typically destroys the controller (and hence the application) shortly after
   // calling this function.
-  std::unique_ptr<ComponentControllerImpl> ExtractApplication(
-      ComponentControllerImpl* controller);
+  std::unique_ptr<ComponentControllerImpl> ExtractComponent(
+      ComponentControllerImpl* controller) override;
 
   void AddBinding(fidl::InterfaceRequest<Environment> environment);
 
@@ -76,11 +89,14 @@
   void CreateComponentWithProcess(
       PackagePtr package, LaunchInfo launch_info,
       fidl::InterfaceRequest<ComponentController> controller,
-      fxl::RefPtr<Namespace> ns);
+      fxl::RefPtr<Namespace> ns,
+      ComponentObjectCreatedCallback callback = nullptr);
+
   void CreateComponentFromPackage(
       PackagePtr package, LaunchInfo launch_info,
       fidl::InterfaceRequest<ComponentController> controller,
-      fxl::RefPtr<Namespace> ns);
+      fxl::RefPtr<Namespace> ns,
+      ComponentObjectCreatedCallback callback = nullptr);
 
   zx::channel OpenRootInfoDir();
 
@@ -88,6 +104,7 @@
   LoaderPtr loader_;
   std::string label_;
   std::string koid_;
+  const bool run_virtual_console_;
 
   zx::job job_;
   zx::job job_for_child_;
diff --git a/bin/appmgr/root_loader.h b/bin/appmgr/root_loader.h
index d2853d6..1aa1267 100644
--- a/bin/appmgr/root_loader.h
+++ b/bin/appmgr/root_loader.h
@@ -5,14 +5,9 @@
 #ifndef GARNET_BIN_APPMGR_ROOT_LOADER_H_
 #define GARNET_BIN_APPMGR_ROOT_LOADER_H_
 
-#include <functional>
-#include <string>
-#include <tuple>
-#include <vector>
-
+#include <fuchsia/sys/cpp/fidl.h>
 #include <lib/zx/vmo.h>
 
-#include <fuchsia/sys/cpp/fidl.h>
 #include "lib/fidl/cpp/binding_set.h"
 #include "lib/fxl/macros.h"
 
diff --git a/bin/appmgr/runner_holder.cc b/bin/appmgr/runner_holder.cc
index f052702..28a3512 100644
--- a/bin/appmgr/runner_holder.cc
+++ b/bin/appmgr/runner_holder.cc
@@ -10,26 +10,107 @@
 
 #include <utility>
 
+#include "garnet/bin/appmgr/component_controller_impl.h"
+#include "garnet/bin/appmgr/realm.h"
+#include "garnet/bin/appmgr/util.h"
 #include "lib/fsl/vmo/file.h"
 
 namespace fuchsia {
 namespace sys {
 
-RunnerHolder::RunnerHolder(Services services, ComponentControllerPtr controller)
-    : services_(std::move(services)), controller_(std::move(controller)) {
+RunnerHolder::RunnerHolder(Services services, ComponentControllerPtr controller,
+                           LaunchInfo launch_info, Realm* realm,
+                           std::function<void()> error_handler)
+    : services_(std::move(services)),
+      controller_(std::move(controller)),
+      impl_object_(nullptr),
+      error_handler_(error_handler),
+      component_id_counter_(0) {
+  realm->CreateComponent(std::move(launch_info), controller_.NewRequest(),
+                         [this](ComponentControllerImpl* component) {
+                           CreateComponentCallback(component);
+                         });
+
+  controller_.set_error_handler([this] {
+    Cleanup();
+
+    if (error_handler_) {
+      error_handler_();
+    }
+  });
+
   services_.ConnectToService(runner_.NewRequest());
 }
 
 RunnerHolder::~RunnerHolder() = default;
 
+void RunnerHolder::Cleanup() {
+  impl_object_ = nullptr;
+  components_.clear();
+}
+
+void RunnerHolder::CreateComponentCallback(ComponentControllerImpl* component) {
+  impl_object_ = component;
+  koid_ = component->koid();
+
+  // add error handler
+  impl_object_->Wait([this](int exit_code) { Cleanup(); });
+
+  // update hub
+  for (auto& n : components_) {
+    n.second->SetParentJobId(koid_);
+    impl_object_->AddSubComponentHub(n.second->HubInfo());
+  }
+}
+
 void RunnerHolder::StartComponent(
     Package package, StartupInfo startup_info,
     std::unique_ptr<archive::FileSystem> file_system, fxl::RefPtr<Namespace> ns,
     fidl::InterfaceRequest<ComponentController> controller) {
-  file_systems_.push_back(std::move(file_system));
-  namespaces_.push_back(std::move(ns));
+  auto url = startup_info.launch_info.url;
+  const std::string args =
+      util::GetArgsString(startup_info.launch_info.arguments);
+  auto channels = util::BindDirectory(&startup_info.launch_info);
+
+  ComponentControllerPtr remote_controller;
+  auto remote_controller_request = remote_controller.NewRequest();
+
+  // TODO(anmittal): Create better unique instance id, instead of 1,2,3,4,...
+  auto component = std::make_unique<ComponentBridge>(
+      std::move(controller), std::move(remote_controller), this,
+      std::move(file_system), url, std::move(args), util::GetLabelFromURL(url),
+      std::to_string(++component_id_counter_), std::move(ns),
+      ExportedDirType::kLegacyFlatLayout, std::move(channels.exported_dir),
+      std::move(channels.client_request));
+
+  // update hub
+  if (impl_object_) {
+    component->SetParentJobId(koid_);
+    impl_object_->AddSubComponentHub(component->HubInfo());
+  }
+
+  ComponentBridge* key = component.get();
+  components_.emplace(key, std::move(component));
+
   runner_->StartComponent(std::move(package), std::move(startup_info),
-                          std::move(controller));
+                          std::move(remote_controller_request));
+}
+
+std::unique_ptr<ComponentBridge> RunnerHolder::ExtractComponent(
+    ComponentBridge* controller) {
+  auto it = components_.find(controller);
+  if (it == components_.end()) {
+    return nullptr;
+  }
+  auto component = std::move(it->second);
+
+  // update hub
+  if (impl_object_) {
+    impl_object_->RemoveSubComponentHub(component->HubInfo());
+  }
+
+  components_.erase(it);
+  return component;
 }
 
 }  // namespace sys
diff --git a/bin/appmgr/runner_holder.h b/bin/appmgr/runner_holder.h
index b15c03f..84a6c93 100644
--- a/bin/appmgr/runner_holder.h
+++ b/bin/appmgr/runner_holder.h
@@ -8,6 +8,8 @@
 #include <lib/zx/vmo.h>
 
 #include <fuchsia/sys/cpp/fidl.h>
+#include "garnet/bin/appmgr/component_container.h"
+#include "garnet/bin/appmgr/component_controller_impl.h"
 #include "garnet/bin/appmgr/namespace.h"
 #include "garnet/lib/farfs/file_system.h"
 #include "lib/fxl/files/unique_fd.h"
@@ -18,9 +20,13 @@
 namespace fuchsia {
 namespace sys {
 
-class RunnerHolder {
+class Realm;
+
+class RunnerHolder : public ComponentContainer<ComponentBridge> {
  public:
-  RunnerHolder(Services services, ComponentControllerPtr controller);
+  RunnerHolder(Services services, ComponentControllerPtr controller,
+               LaunchInfo launch_info, Realm* realm,
+               std::function<void()> error_handler = nullptr);
   ~RunnerHolder();
 
   void StartComponent(Package package, StartupInfo startup_info,
@@ -28,15 +34,22 @@
                       fxl::RefPtr<Namespace> ns,
                       fidl::InterfaceRequest<ComponentController> controller);
 
+  std::unique_ptr<ComponentBridge> ExtractComponent(
+      ComponentBridge* controller) override;
+
  private:
+  void CreateComponentCallback(ComponentControllerImpl* component);
+  void Cleanup();
+
   Services services_;
   ComponentControllerPtr controller_;
   RunnerPtr runner_;
-
-  // TODO(abarth): We hold these objects for the lifetime of the runner, but we
-  // should actuall drop them once their controller is done.
-  std::vector<std::unique_ptr<archive::FileSystem>> file_systems_;
-  std::vector<fxl::RefPtr<Namespace>> namespaces_;
+  ComponentControllerImpl* impl_object_;
+  std::function<void()> error_handler_;
+  std::unordered_map<ComponentBridge*, std::unique_ptr<ComponentBridge>>
+      components_;
+  uint64_t component_id_counter_;
+  std::string koid_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(RunnerHolder);
 };
diff --git a/bin/appmgr/sandbox_metadata.cc b/bin/appmgr/sandbox_metadata.cc
index 7b003f9..eac9844 100644
--- a/bin/appmgr/sandbox_metadata.cc
+++ b/bin/appmgr/sandbox_metadata.cc
@@ -35,14 +35,6 @@
 
 SandboxMetadata::~SandboxMetadata() = default;
 
-bool SandboxMetadata::Parse(const std::string& data) {
-  rapidjson::Document document;
-  document.Parse(data);
-  if (!document.IsObject())
-    return false;
-  return Parse(document);
-}
-
 bool SandboxMetadata::Parse(const rapidjson::Value& sandbox_value) {
   dev_.clear();
   features_.clear();
diff --git a/bin/appmgr/sandbox_metadata.h b/bin/appmgr/sandbox_metadata.h
index cdb1ba3..bb60069 100644
--- a/bin/appmgr/sandbox_metadata.h
+++ b/bin/appmgr/sandbox_metadata.h
@@ -18,7 +18,6 @@
   SandboxMetadata();
   ~SandboxMetadata();
 
-  bool Parse(const std::string& data);
   bool Parse(const rapidjson::Value& sandbox_value);
   bool HasFeature(const std::string& feature);
   void AddFeature(std::string feature);
diff --git a/bin/appmgr/sandbox_metadata_unittest.cc b/bin/appmgr/sandbox_metadata_unittest.cc
index 8fc110d..746f4bf 100644
--- a/bin/appmgr/sandbox_metadata_unittest.cc
+++ b/bin/appmgr/sandbox_metadata_unittest.cc
@@ -12,39 +12,34 @@
 namespace sys {
 namespace {
 
-TEST(SandboxMetadata, Parse) {
-  SandboxMetadata sandbox;
-  EXPECT_FALSE(sandbox.Parse(""));
-  EXPECT_TRUE(sandbox.Parse("{}"));
-
-  EXPECT_TRUE(sandbox.Parse(R"JSON({ "dev": [ "class/input" ]})JSON"));
-  EXPECT_EQ(1u, sandbox.dev().size());
-  EXPECT_EQ(0u, sandbox.features().size());
-  EXPECT_EQ("class/input", sandbox.dev()[0]);
-
-  EXPECT_TRUE(sandbox.Parse(R"JSON({ "features": [ "vulkan" ]})JSON"));
-  EXPECT_EQ(0u, sandbox.dev().size());
-  EXPECT_EQ(1u, sandbox.features().size());
-  EXPECT_EQ("vulkan", sandbox.features()[0]);
-
-  EXPECT_TRUE(sandbox.HasFeature("vulkan"));
-  EXPECT_FALSE(sandbox.HasFeature("banana"));
-}
-
 TEST(SandboxMetadata, ParseRapidJson) {
-  rapidjson::Document document;
-  document.SetObject();
-  rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
-  rapidjson::Value array(rapidjson::kArrayType);
-  array.PushBack("class/input", allocator);
-  document.AddMember("dev", array, allocator);
+  rapidjson::Document dev_document;
+  dev_document.SetObject();
+  rapidjson::Document::AllocatorType& dev_allocator =
+      dev_document.GetAllocator();
+  rapidjson::Value dev_array(rapidjson::kArrayType);
+  dev_array.PushBack("class/input", dev_allocator);
+  dev_document.AddMember("dev", dev_array, dev_allocator);
+  SandboxMetadata dev_sandbox;
+  EXPECT_TRUE(dev_sandbox.Parse(dev_document));
+  EXPECT_EQ(1u, dev_sandbox.dev().size());
+  EXPECT_EQ(0u, dev_sandbox.features().size());
+  EXPECT_EQ("class/input", dev_sandbox.dev()[0]);
 
-  SandboxMetadata sandbox;
-
-  EXPECT_TRUE(sandbox.Parse(document));
-  EXPECT_EQ(1u, sandbox.dev().size());
-  EXPECT_EQ(0u, sandbox.features().size());
-  EXPECT_EQ("class/input", sandbox.dev()[0]);
+  rapidjson::Document feat_document;
+  feat_document.SetObject();
+  rapidjson::Document::AllocatorType& feat_allocator =
+      feat_document.GetAllocator();
+  rapidjson::Value feat_array(rapidjson::kArrayType);
+  feat_array.PushBack("vulkan", feat_allocator);
+  feat_document.AddMember("features", feat_array, feat_allocator);
+  SandboxMetadata feat_sandbox;
+  EXPECT_TRUE(feat_sandbox.Parse(feat_document));
+  EXPECT_EQ(0u, feat_sandbox.dev().size());
+  EXPECT_EQ(1u, feat_sandbox.features().size());
+  EXPECT_EQ("vulkan", feat_sandbox.features()[0]);
+  EXPECT_TRUE(feat_sandbox.HasFeature("vulkan"));
+  EXPECT_FALSE(feat_sandbox.HasFeature("banana"));
 }
 
 }  // namespace
diff --git a/bin/appmgr/util.cc b/bin/appmgr/util.cc
new file mode 100644
index 0000000..dd549dc
--- /dev/null
+++ b/bin/appmgr/util.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/appmgr/util.h"
+
+#include <fuchsia/sys/cpp/fidl.h>
+#include <zx/channel.h>
+
+#include <string>
+
+#include "lib/fxl/logging.h"
+
+namespace fuchsia {
+namespace sys {
+namespace util {
+
+std::string GetLabelFromURL(const std::string& url) {
+  size_t last_slash = url.rfind('/');
+  if (last_slash == std::string::npos || last_slash + 1 == url.length())
+    return url;
+  return url.substr(last_slash + 1);
+}
+
+ExportedDirChannels BindDirectory(LaunchInfo* launch_info) {
+  zx::channel exported_dir_server, exported_dir_client;
+  zx_status_t status =
+      zx::channel::create(0u, &exported_dir_server, &exported_dir_client);
+  if (status != ZX_OK) {
+    FXL_LOG(ERROR) << "Failed to create channel for service directory: status="
+                   << status;
+    return {zx::channel(), zx::channel()};
+  }
+
+  auto client_request = std::move(launch_info->directory_request);
+  launch_info->directory_request = std::move(exported_dir_server);
+  return {std::move(exported_dir_client), std::move(client_request)};
+}
+
+std::string GetArgsString(
+    const ::fidl::VectorPtr<::fidl::StringPtr>& arguments) {
+  std::string args = "";
+  if (!arguments->empty()) {
+    std::ostringstream buf;
+    std::copy(arguments->begin(), arguments->end() - 1,
+              std::ostream_iterator<std::string>(buf, " "));
+    buf << *arguments->rbegin();
+    args = buf.str();
+  }
+  return args;
+}
+
+}  // namespace util
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/bin/appmgr/util.h b/bin/appmgr/util.h
new file mode 100644
index 0000000..883f85b
--- /dev/null
+++ b/bin/appmgr/util.h
@@ -0,0 +1,36 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_APPMGR_UTIL_H_
+#define GARNET_BIN_APPMGR_UTIL_H_
+
+#include <fuchsia/sys/cpp/fidl.h>
+
+#include <string>
+
+namespace fuchsia {
+namespace sys {
+namespace util {
+
+struct ExportedDirChannels {
+  // The client side of the channel serving connected application's exported
+  // dir.
+  zx::channel exported_dir;
+
+  // The server side of our client's |LaunchInfo.directory_request|.
+  zx::channel client_request;
+};
+
+std::string GetLabelFromURL(const std::string& url);
+
+ExportedDirChannels BindDirectory(LaunchInfo* launch_info);
+
+std::string GetArgsString(
+    const ::fidl::VectorPtr<::fidl::StringPtr>& arguments);
+
+}  // namespace util
+}  // namespace sys
+}  // namespace fuchsia
+
+#endif  // GARNET_BIN_APPMGR_UTIL_H_
diff --git a/bin/appmgr/util_unittest.cc b/bin/appmgr/util_unittest.cc
new file mode 100644
index 0000000..dbfba21
--- /dev/null
+++ b/bin/appmgr/util_unittest.cc
@@ -0,0 +1,70 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/appmgr/util.h"
+
+#include "gtest/gtest.h"
+
+namespace fuchsia {
+namespace sys {
+namespace {
+
+TEST(UtilTests, GetLabelFromURL) {
+  std::string values[][2] = {
+      {"", ""},        {"foo/bar", "bar"},  {"foo/bar/", "foo/bar/"},
+      {"/foo", "foo"}, {"/foo/bar", "bar"}, {"foo", "foo"},
+      {"foo/", "foo/"}};
+  for (auto value : values) {
+    auto& url = value[0];
+    auto& expected = value[1];
+    EXPECT_EQ(util::GetLabelFromURL(url), expected) << "for url: " << url;
+  }
+}
+
+TEST(UtilTests, GetArgsString) {
+  ::fidl::VectorPtr<::fidl::StringPtr> null_vec;
+  EXPECT_EQ(util::GetArgsString(null_vec), "");
+
+  ::fidl::VectorPtr<::fidl::StringPtr> empty_vec(3);
+  EXPECT_EQ(util::GetArgsString(empty_vec), "  ");
+
+  ::fidl::VectorPtr<::fidl::StringPtr> vec;
+  vec.push_back("foo");
+  EXPECT_EQ(util::GetArgsString(vec), "foo");
+  vec.push_back("bar");
+  EXPECT_EQ(util::GetArgsString(vec), "foo bar");
+  vec.push_back("blah");
+  EXPECT_EQ(util::GetArgsString(vec), "foo bar blah");
+}
+
+TEST(UtilTests, BindDirectory) {
+  zx::channel dir, dir_req;
+  ASSERT_EQ(zx::channel::create(0, &dir, &dir_req), ZX_OK);
+  LaunchInfo launchInfo;
+  launchInfo.directory_request = std::move(dir_req);
+  auto channels = util::BindDirectory(&launchInfo);
+  ASSERT_TRUE(channels.exported_dir.is_valid());
+  ASSERT_TRUE(channels.client_request.is_valid());
+
+  const char* msg1 = "message1";
+  dir.write(0, msg1, strlen(msg1) + 1, nullptr, 0);
+
+  const char* msg2 = "message2";
+  channels.exported_dir.write(0, msg2, strlen(msg2) + 1, nullptr, 0);
+
+  char got1[strlen(msg1) + 1];
+  char got2[strlen(msg2) + 1];
+
+  channels.client_request.read(0, got1, sizeof(got1), nullptr, nullptr, 0,
+                               nullptr);
+  launchInfo.directory_request.read(0, got2, sizeof(got2), nullptr, nullptr, 0,
+                                    nullptr);
+
+  EXPECT_STREQ(got1, msg1);
+  EXPECT_STREQ(got2, msg2);
+}
+
+}  // namespace
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/bin/auth/prototype/.gitignore b/bin/auth/prototype/.gitignore
deleted file mode 100644
index 324c57f..0000000
--- a/bin/auth/prototype/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-target/
-**/*.rs.bk
diff --git a/bin/auth/prototype/LICENSE b/bin/auth/prototype/LICENSE
deleted file mode 100644
index cdfb473..0000000
--- a/bin/auth/prototype/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 The Fuchsia Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/bin/auth/prototype/README.md b/bin/auth/prototype/README.md
deleted file mode 100644
index 8c82860..0000000
--- a/bin/auth/prototype/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Fuchsia Authentication - Rust Implementation
-============================================
-
-This directory contains (WIP) the Rust implementation of the basic user
-authentication and authorization services for onboarding new users on Fuchsia
-and to access their data from external third party providers.
-
-
-This implementation is a prototype and should not be depended on.
diff --git a/bin/auth/prototype/src/main.rs b/bin/auth/prototype/src/main.rs
deleted file mode 100644
index e7a11a9..0000000
--- a/bin/auth/prototype/src/main.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    println!("Hello, world!");
-}
diff --git a/bin/benchmarks/benchmarks.sh b/bin/benchmarks/benchmarks.sh
index 4d67f9a..ae7a828 100644
--- a/bin/benchmarks/benchmarks.sh
+++ b/bin/benchmarks/benchmarks.sh
@@ -35,5 +35,8 @@
 runbench_exec "${OUT_DIR}/zircon_benchmarks.json" \
     /system/bin/zircon_benchmarks -p --out="${OUT_DIR}/zircon_benchmarks.json"
 
+# Scenic performance tests.
+runbench_exec "${OUT_DIR}/benchmark_hello_scenic.json" \
+    /system/data/scenic_benchmarks/hello_scenic_benchmark.sh "${OUT_DIR}" "${OUT_DIR}/benchmark_hello_scenic.json"
 # Exit with a code indicating whether any errors occurred.
 runbench_finish "${OUT_DIR}"
diff --git a/bin/bluetooth/bt-gap/src/control_service.rs b/bin/bluetooth/bt-gap/src/control_service.rs
index 90875a8..b763322 100644
--- a/bin/bluetooth/bt-gap/src/control_service.rs
+++ b/bin/bluetooth/bt-gap/src/control_service.rs
@@ -4,8 +4,8 @@
 
 use async;
 use fidl::encoding2::OutOfLine;
-use fidl_bluetooth;
-use fidl_bluetooth_control::{Control, ControlImpl};
+use fidl_fuchsia_bluetooth;
+use fidl_fuchsia_bluetooth_control::{Control, ControlImpl};
 use futures::{future, Future, FutureExt, Never};
 use futures::future::Either::{Left, Right};
 use futures::prelude::*;
diff --git a/bin/bluetooth/bt-gap/src/adapter.rs b/bin/bluetooth/bt-gap/src/host_device.rs
similarity index 61%
rename from bin/bluetooth/bt-gap/src/adapter.rs
rename to bin/bluetooth/bt-gap/src/host_device.rs
index 270d9eb..cfb4b4c 100644
--- a/bin/bluetooth/bt-gap/src/adapter.rs
+++ b/bin/bluetooth/bt-gap/src/host_device.rs
@@ -3,28 +3,26 @@
 // found in the LICENSE file.
 
 use fidl;
-use fidl_bluetooth::Status;
-use fidl_bluetooth_control::AdapterInfo;
-use fidl_bluetooth_host::{AdapterEvent, AdapterEventStream, AdapterProxy, HostProxy};
+use fidl_fuchsia_bluetooth::Status;
+use fidl_fuchsia_bluetooth_control::AdapterInfo;
+use fidl_fuchsia_bluetooth_host::{HostEvent, HostEventStream, HostProxy};
 use futures::{FutureExt, StreamExt};
 use futures::Future;
 use futures::future::ok as fok;
 use host_dispatcher::HostDispatcher;
 use parking_lot::RwLock;
 use std::sync::Arc;
-use util::clone_adapter_state;
+use util::clone_host_state;
 
 pub struct HostDevice {
     host: HostProxy,
-    adapter: AdapterProxy,
     info: AdapterInfo,
 }
 
 impl HostDevice {
-    pub fn new(host: HostProxy, adapter: AdapterProxy, info: AdapterInfo) -> Self {
+    pub fn new(host: HostProxy, info: AdapterInfo) -> Self {
         HostDevice {
             host,
-            adapter,
             info,
         }
     }
@@ -38,11 +36,11 @@
     }
 
     pub fn set_name(&self, mut name: String) -> impl Future<Item = Status, Error = fidl::Error> {
-        self.adapter.set_local_name(&mut name)
+        self.host.set_local_name(&mut name)
     }
 
     pub fn start_discovery(&mut self) -> impl Future<Item = Status, Error = fidl::Error> {
-        self.adapter.start_discovery()
+        self.host.start_discovery()
     }
 
     pub fn close(&self) -> Result<(), fidl::Error> {
@@ -50,28 +48,28 @@
     }
 
     pub fn stop_discovery(&self) -> impl Future<Item = Status, Error = fidl::Error> {
-        self.adapter.stop_discovery()
+        self.host.stop_discovery()
     }
 
     pub fn set_discoverable(
         &mut self, discoverable: bool
     ) -> impl Future<Item = Status, Error = fidl::Error> {
-        self.adapter.set_discoverable(discoverable)
+        self.host.set_discoverable(discoverable)
     }
 }
 
-pub fn run_host_device(
-    hd: Arc<RwLock<HostDispatcher>>, adapter: Arc<RwLock<HostDevice>>
-) -> impl Future<Item = AdapterEventStream, Error = fidl::Error> {
-    make_clones!(adapter => stream_adapter, adapter);
-    let stream = stream_adapter.read().adapter.take_event_stream();
+pub fn run(
+    hd: Arc<RwLock<HostDispatcher>>, host: Arc<RwLock<HostDevice>>
+) -> impl Future<Item = HostEventStream, Error = fidl::Error> {
+    make_clones!(host => host_stream, host);
+    let stream = host_stream.read().host.take_event_stream();
     stream
         .for_each(move |evt| {
             match evt {
-                AdapterEvent::OnAdapterStateChanged { ref state } => {
-                    adapter.write().info.state = Some(Box::new(clone_adapter_state(&state)));
+                HostEvent::OnHostStateChanged { ref state } => {
+                    host.write().info.state = Some(Box::new(clone_host_state(&state)));
                 }
-                AdapterEvent::OnDeviceDiscovered { mut device } => {
+                HostEvent::OnDeviceDiscovered { mut device } => {
                     if let Some(ref events) = hd.write().events {
                         let _res = events
                             .send_on_device_updated(&mut device)
diff --git a/bin/bluetooth/bt-gap/src/host_dispatcher.rs b/bin/bluetooth/bt-gap/src/host_dispatcher.rs
index 82ef5ed..903497f 100644
--- a/bin/bluetooth/bt-gap/src/host_dispatcher.rs
+++ b/bin/bluetooth/bt-gap/src/host_dispatcher.rs
@@ -2,22 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use adapter::{self, HostDevice};
 use async;
 use bt;
-use bt::util::clone_adapter_info;
+use bt::util::clone_host_info;
 use failure::Error;
 use fidl;
-use fidl::endpoints2::{Proxy, ServerEnd};
-use fidl_bluetooth;
-use fidl_bluetooth_control::{ControlControlHandle, PairingDelegateProxy};
-use fidl_bluetooth_control::AdapterInfo;
-use fidl_bluetooth_host::{AdapterMarker, AdapterProxy, HostProxy};
+use fidl_fuchsia_bluetooth;
+use fidl_fuchsia_bluetooth_control::{ControlControlHandle, PairingDelegateProxy};
+use fidl_fuchsia_bluetooth_control::AdapterInfo;
+use fidl_fuchsia_bluetooth_host::HostProxy;
 use futures::{Poll, task, Async, Future, FutureExt};
 use futures::IntoFuture;
 use futures::StreamExt;
 use futures::future::Either::{Left, Right};
 use futures::future::ok as fok;
+use host_device::{self, HostDevice};
 use parking_lot::RwLock;
 use std::collections::HashMap;
 use std::fs::File;
@@ -26,13 +25,10 @@
 use std::sync::{Arc, Weak};
 use util;
 use vfs_watcher;
-use zx;
 
 static BT_HOST_DIR: &'static str = "/dev/class/bt-host";
 static DEFAULT_NAME: &'static str = "fuchsia";
 
-type HostAdapterPtr = ServerEnd<AdapterMarker>;
-
 pub struct DiscoveryRequestToken {
     adap: Weak<RwLock<HostDevice>>,
 }
@@ -85,7 +81,7 @@
 
     pub fn set_name(
         &mut self, name: Option<String>
-    ) -> impl Future<Item = fidl_bluetooth::Status, Error = fidl::Error> {
+    ) -> impl Future<Item = fidl_fuchsia_bluetooth::Status, Error = fidl::Error> {
         match name {
             Some(name) => self.name = name,
             None => self.name = DEFAULT_NAME.to_string(),
@@ -118,7 +114,7 @@
     pub fn start_discovery(
         hd: &Arc<RwLock<HostDispatcher>>
     ) -> impl Future<
-        Item = (fidl_bluetooth::Status, Option<Arc<DiscoveryRequestToken>>),
+        Item = (fidl_fuchsia_bluetooth::Status, Option<Arc<DiscoveryRequestToken>>),
         Error = fidl::Error,
     > {
         let strong_current_token = match hd.read().discovery {
@@ -159,7 +155,7 @@
         hd: &Arc<RwLock<HostDispatcher>>
     ) -> impl Future<
         Item = (
-            fidl_bluetooth::Status,
+            fidl_fuchsia_bluetooth::Status,
             Option<Arc<DiscoverableRequestToken>>,
         ),
         Error = fidl::Error,
@@ -199,7 +195,7 @@
         }
     }
 
-    pub fn set_active_adapter(&mut self, adapter_id: String) -> fidl_bluetooth::Status {
+    pub fn set_active_adapter(&mut self, adapter_id: String) -> fidl_fuchsia_bluetooth::Status {
         if self.host_devices.contains_key(&adapter_id) {
             // Close the prior adapter
             if let Some(ref id) = self.active_id {
@@ -217,7 +213,7 @@
             Some(ref id) => {
                 // Id must always be valid
                 let adap = self.host_devices.get(id).unwrap().read();
-                Some(util::clone_adapter_info(adap.get_info()))
+                Some(util::clone_host_info(adap.get_info()))
             }
             None => None,
         }
@@ -253,7 +249,7 @@
         let mut host_devices = vec![];
         for adapter in self.0.read().host_devices.values() {
             let adapter = adapter.read();
-            host_devices.push(util::clone_adapter_info(adapter.get_info()));
+            host_devices.push(util::clone_host_info(adapter.get_info()));
         }
         Ok(Async::Ready(host_devices))
     }
@@ -277,40 +273,31 @@
                 .map(|info| (host, info))
         })
         .and_then(move |(host, adapter_info)| {
-            // Setup the delegates for proxying calls through the bt-host
-            let (host_local, host_remote) = zx::Channel::create().unwrap();
-            let host_adapter =
-                AdapterProxy::from_channel(async::Channel::from_channel(host_local).unwrap());
-            let host_req = HostAdapterPtr::new(host_remote);
-            let _ = host.request_adapter(host_req);
-
             // Set the adapter as connectable
-            host_adapter
-                .set_connectable(true)
+            host.set_connectable(true)
                 .map_err(|e| {
                     error!("Failed to set host adapter as connectable");
                     e.into()
                 })
-                .map(|_| (host_adapter, host, adapter_info))
+                .map(|_| (host, adapter_info))
         })
-        .and_then(move |(host_adapter, host, adapter_info)| {
+        .and_then(move |(host, adapter_info)| {
             // Add to the adapters
             let id = adapter_info.identifier.clone();
-            let adapter = Arc::new(RwLock::new(HostDevice::new(
+            let host_device = Arc::new(RwLock::new(HostDevice::new(
                 host,
-                host_adapter,
                 adapter_info,
             )));
-            hd.write().host_devices.insert(id, adapter.clone());
-            fok((hd.clone(), adapter))
+            hd.write().host_devices.insert(id, host_device.clone());
+            fok((hd.clone(), host_device))
         })
-        .and_then(|(hd, adapter)| {
+        .and_then(|(hd, host_device)| {
             if let Some(ref events) = hd.read().events {
                 let _res = events
-                    .send_on_adapter_updated(&mut clone_adapter_info(adapter.read().get_info()));
+                    .send_on_adapter_updated(&mut clone_host_info(host_device.read().get_info()));
             }
-            info!("Host added: {:?}", adapter.read().get_info().identifier);
-            adapter::run_host_device(hd.clone(), adapter.clone())
+            info!("Host added: {:?}", host_device.read().get_info().identifier);
+            host_device::run(hd.clone(), host_device.clone())
                 .err_into()
                 .map(|_| ())
         })
diff --git a/bin/bluetooth/bt-gap/src/main.rs b/bin/bluetooth/bt-gap/src/main.rs
index 534de61..7ccf69f 100644
--- a/bin/bluetooth/bt-gap/src/main.rs
+++ b/bin/bluetooth/bt-gap/src/main.rs
@@ -7,11 +7,11 @@
 extern crate failure;
 extern crate fdio;
 extern crate fidl;
-extern crate fidl_bluetooth;
-extern crate fidl_bluetooth_control;
-extern crate fidl_bluetooth_gatt;
-extern crate fidl_bluetooth_host;
-extern crate fidl_bluetooth_low_energy;
+extern crate fidl_fuchsia_bluetooth;
+extern crate fidl_fuchsia_bluetooth_control;
+extern crate fidl_fuchsia_bluetooth_gatt;
+extern crate fidl_fuchsia_bluetooth_host;
+extern crate fidl_fuchsia_bluetooth_le;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 #[macro_use]
@@ -30,15 +30,15 @@
 use bt::util;
 use failure::{Error, ResultExt};
 use fidl::endpoints2::{ServerEnd, ServiceMarker};
-use fidl_bluetooth_control::ControlMarker;
-use fidl_bluetooth_gatt::Server_Marker;
-use fidl_bluetooth_low_energy::{CentralMarker, PeripheralMarker};
+use fidl_fuchsia_bluetooth_control::ControlMarker;
+use fidl_fuchsia_bluetooth_gatt::Server_Marker;
+use fidl_fuchsia_bluetooth_le::{CentralMarker, PeripheralMarker};
 use futures::FutureExt;
 use parking_lot::RwLock;
 use std::sync::Arc;
 
-mod adapter;
 mod control_service;
+mod host_device;
 mod host_dispatcher;
 mod logger;
 
diff --git a/bin/bluetooth/tests/integration/tests/lifecycle.rs b/bin/bluetooth/tests/integration/tests/lifecycle.rs
index 15c82bd..c2f5136 100644
--- a/bin/bluetooth/tests/integration/tests/lifecycle.rs
+++ b/bin/bluetooth/tests/integration/tests/lifecycle.rs
@@ -1,13 +1,16 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 extern crate fdio;
 extern crate failure;
 extern crate rand;
 pub extern crate fuchsia_bluetooth as bluetooth;
 extern crate fuchsia_async as async;
-extern crate fidl_bluetooth_host;
+extern crate fidl_fuchsia_bluetooth_host;
 extern crate futures;
 
-
-use fidl_bluetooth_host::HostProxy;
+use fidl_fuchsia_bluetooth_host::HostProxy;
 use std::path::PathBuf;
 use std::{thread, time};
 use bluetooth::hci;
diff --git a/bin/bluetooth/tools/BUILD.gn b/bin/bluetooth/tools/BUILD.gn
index 8a2a86a..a199a3e 100644
--- a/bin/bluetooth/tools/BUILD.gn
+++ b/bin/bluetooth/tools/BUILD.gn
@@ -8,7 +8,7 @@
   deprecated_system_image = true
 
   deps = [
-    "bt-cli",
+    "bt-cli:bin",
     "bt-fake-hci",
     "bt-hci-tool",
     "bt-intel-tool",
diff --git a/bin/bluetooth/tools/bt-cli/src/main.rs b/bin/bluetooth/tools/bt-cli/src/main.rs
index 268f240..aa19d1b 100644
--- a/bin/bluetooth/tools/bt-cli/src/main.rs
+++ b/bin/bluetooth/tools/bt-cli/src/main.rs
@@ -5,7 +5,7 @@
 #![deny(warnings)]
 
 extern crate failure;
-extern crate fidl_bluetooth_control;
+extern crate fidl_fuchsia_bluetooth_control;
 extern crate fuchsia_app as app;
 #[macro_use]
 extern crate fuchsia_async as async;
@@ -20,9 +20,8 @@
 use commands::{Cmd, CmdCompleter};
 use failure::{Fail, ResultExt};
 use failure::Error;
-use fidl_bluetooth_control::{ControlEvent, ControlMarker, ControlProxy};
+use fidl_fuchsia_bluetooth_control::{ControlEvent, ControlMarker, ControlProxy};
 use futures::{Future, FutureExt, StreamExt};
-use futures::{task, Poll};
 use futures::future::ok as fok;
 use parking_lot::RwLock;
 use rustyline::{CompletionType, Config, EditMode, Editor};
diff --git a/bin/bluetooth/tools/bt-cli/src/types.rs b/bin/bluetooth/tools/bt-cli/src/types.rs
index 2c97a1e..a5c87ad 100644
--- a/bin/bluetooth/tools/bt-cli/src/types.rs
+++ b/bin/bluetooth/tools/bt-cli/src/types.rs
@@ -1,18 +1,22 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 use bluetooth::types::Bool;
-use bluetooth::util::clone_adapter_state;
+use bluetooth::util::clone_host_state;
 use bluetooth::util::clone_bt_fidl_bool;
-use fidl_bluetooth_control;
+use fidl_fuchsia_bluetooth_control as fidl_control;
 use std::fmt;
 
-pub struct AdapterInfo(fidl_bluetooth_control::AdapterInfo);
+pub struct AdapterInfo(fidl_control::AdapterInfo);
 
-impl From<fidl_bluetooth_control::AdapterInfo> for AdapterInfo {
-    fn from(b: fidl_bluetooth_control::AdapterInfo) -> AdapterInfo {
+impl From<fidl_control::AdapterInfo> for AdapterInfo {
+    fn from(b: fidl_control::AdapterInfo) -> AdapterInfo {
         AdapterInfo(b)
     }
 }
-impl Into<fidl_bluetooth_control::AdapterInfo> for AdapterInfo {
-    fn into(self) -> fidl_bluetooth_control::AdapterInfo {
+impl Into<fidl_control::AdapterInfo> for AdapterInfo {
+    fn into(self) -> fidl_control::AdapterInfo {
         self.0
     }
 }
@@ -24,7 +28,7 @@
         let _ = writeln!(fmt, "\tAddress:\t{}", self.0.address);
         let _ = writeln!(fmt, "\tTechnology:\t{:?}", self.0.technology);
         if let Some(ref state) = self.0.state {
-            for line in AdapterState::from(clone_adapter_state(state))
+            for line in AdapterState::from(clone_host_state(state))
                 .to_string()
                 .lines()
             {
@@ -35,15 +39,15 @@
     }
 }
 
-pub struct AdapterState(fidl_bluetooth_control::AdapterState);
+pub struct AdapterState(fidl_control::AdapterState);
 
-impl From<fidl_bluetooth_control::AdapterState> for AdapterState {
-    fn from(b: fidl_bluetooth_control::AdapterState) -> AdapterState {
+impl From<fidl_control::AdapterState> for AdapterState {
+    fn from(b: fidl_control::AdapterState) -> AdapterState {
         AdapterState(b)
     }
 }
-impl Into<fidl_bluetooth_control::AdapterState> for AdapterState {
-    fn into(self) -> fidl_bluetooth_control::AdapterState {
+impl Into<fidl_control::AdapterState> for AdapterState {
+    fn into(self) -> fidl_control::AdapterState {
         self.0
     }
 }
diff --git a/bin/bluetooth/tools/bt-hci-tool/commands.cc b/bin/bluetooth/tools/bt-hci-tool/commands.cc
index 5a0be3d..4d0eeb0 100644
--- a/bin/bluetooth/tools/bt-hci-tool/commands.cc
+++ b/bin/bluetooth/tools/bt-hci-tool/commands.cc
@@ -19,36 +19,28 @@
 #include "lib/fxl/strings/string_printf.h"
 #include "lib/fxl/time/time_delta.h"
 
-using namespace bluetooth;
-
-using std::placeholders::_1;
-using std::placeholders::_2;
-
 namespace hcitool {
 namespace {
 
-void StatusFilterCallback(fxl::Closure complete_cb,
-                          ::btlib::hci::CommandChannel::CommandCallback& cb,
-                          ::btlib::hci::CommandChannel::TransactionId id,
-                          const ::btlib::hci::EventPacket& event) {
-  if (event.event_code() == ::btlib::hci::kCommandStatusEventCode) {
-    auto status = event.ToStatus();
-    std::cout << "  Command Status: " << status.ToString() << " (id=" << id
-              << ")" << std::endl;
-    if (status != ::btlib::hci::StatusCode::kSuccess) complete_cb();
-    return;
-  }
-  cb(id, event);
-}
-
 ::btlib::hci::CommandChannel::TransactionId SendCommand(
     const CommandData* cmd_data,
     std::unique_ptr<::btlib::hci::CommandPacket> packet,
-    const ::btlib::hci::CommandChannel::CommandCallback& cb,
-    const fxl::Closure& complete_cb) {
+    ::btlib::hci::CommandChannel::CommandCallback cb,
+    fit::closure complete_cb) {
   return cmd_data->cmd_channel()->SendCommand(
       std::move(packet), cmd_data->dispatcher(),
-      std::bind(&StatusFilterCallback, complete_cb, cb, _1, _2));
+      [complete_cb = std::move(complete_cb), cb = std::move(cb)](
+          ::btlib::hci::CommandChannel::TransactionId id,
+          const ::btlib::hci::EventPacket& event) {
+        if (event.event_code() == ::btlib::hci::kCommandStatusEventCode) {
+          auto status = event.ToStatus();
+          std::cout << "  Command Status: " << status.ToString() << " (id=" << id
+                    << ")" << std::endl;
+          if (status != ::btlib::hci::StatusCode::kSuccess) complete_cb();
+          return;
+        }
+        cb(id, event);
+      });
 }
 
 void LogCommandResult(::btlib::hci::StatusCode status,
@@ -61,15 +53,15 @@
 ::btlib::hci::CommandChannel::TransactionId SendCompleteCommand(
     const CommandData* cmd_data,
     std::unique_ptr<::btlib::hci::CommandPacket> packet,
-    const fxl::Closure& complete_cb) {
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+    fit::closure complete_cb) {
+  auto cb = [complete_cb = complete_cb.share()](::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::SimpleReturnParams>();
     LogCommandResult(return_params->status, id);
     complete_cb();
   };
-  return SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  return SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
 }
 
 // TODO(armansito): Move this to a library header as it will be useful
@@ -211,13 +203,13 @@
 
 bool HandleVersionInfo(const CommandData* cmd_data,
                        const fxl::CommandLine& cmd_line,
-                       const fxl::Closure& complete_cb) {
+                       fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: version-info" << std::endl;
     return false;
   }
 
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+  auto cb = [complete_cb = complete_cb.share()](::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto params =
         event.return_params<::btlib::hci::ReadLocalVersionInfoReturnParams>();
@@ -241,7 +233,7 @@
 
   auto packet =
       ::btlib::hci::CommandPacket::New(::btlib::hci::kReadLocalVersionInfo);
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Read_Local_Version_Information (id=" << id << ")"
             << std::endl;
@@ -249,14 +241,14 @@
 }
 
 bool HandleReset(const CommandData* cmd_data, const fxl::CommandLine& cmd_line,
-                 const fxl::Closure& complete_cb) {
+                 fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: reset" << std::endl;
     return false;
   }
 
   auto packet = ::btlib::hci::CommandPacket::New(::btlib::hci::kReset);
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Reset (id=" << id << ")" << std::endl;
 
@@ -265,13 +257,13 @@
 
 bool HandleReadBDADDR(const CommandData* cmd_data,
                       const fxl::CommandLine& cmd_line,
-                      const fxl::Closure& complete_cb) {
+                      fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: read-bdaddr" << std::endl;
     return false;
   }
 
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+  auto cb = [complete_cb = complete_cb.share()](::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::ReadBDADDRReturnParams>();
@@ -287,7 +279,7 @@
   };
 
   auto packet = ::btlib::hci::CommandPacket::New(::btlib::hci::kReadBDADDR);
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Read_BDADDR (id=" << id << ")" << std::endl;
 
@@ -296,13 +288,13 @@
 
 bool HandleReadLocalName(const CommandData* cmd_data,
                          const fxl::CommandLine& cmd_line,
-                         const fxl::Closure& complete_cb) {
+                         fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: read-local-name" << std::endl;
     return false;
   }
 
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+  auto cb = [complete_cb = complete_cb.share()](::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::ReadLocalNameReturnParams>();
@@ -318,7 +310,7 @@
   };
 
   auto packet = ::btlib::hci::CommandPacket::New(::btlib::hci::kReadLocalName);
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
   std::cout << "  Sent HCI_Read_Local_Name (id=" << id << ")" << std::endl;
 
   return true;
@@ -326,7 +318,7 @@
 
 bool HandleWriteLocalName(const CommandData* cmd_data,
                           const fxl::CommandLine& cmd_line,
-                          const fxl::Closure& complete_cb) {
+                          fit::closure complete_cb) {
   if (cmd_line.positional_args().size() != 1 || cmd_line.options().size()) {
     std::cout << "  Usage: write-local-name <name>" << std::endl;
     return false;
@@ -340,7 +332,7 @@
                   ->local_name,
               name.c_str());
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
   std::cout << "  Sent HCI_Write_Local_Name (id=" << id << ")" << std::endl;
 
   return true;
@@ -348,7 +340,7 @@
 
 bool HandleSetEventMask(const CommandData* cmd_data,
                         const fxl::CommandLine& cmd_line,
-                        const fxl::Closure& complete_cb) {
+                        fit::closure complete_cb) {
   if (cmd_line.positional_args().size() != 1 || cmd_line.options().size()) {
     std::cout << "  Usage: set-event-mask [hex]" << std::endl;
     return false;
@@ -373,7 +365,7 @@
       ->mutable_payload<::btlib::hci::SetEventMaskCommandParams>()
       ->event_mask = htole64(mask);
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Set_Event_Mask("
             << fxl::NumberToString(mask, fxl::Base::k16) << ") (id=" << id
@@ -383,7 +375,7 @@
 
 bool HandleLESetAdvEnable(const CommandData* cmd_data,
                           const fxl::CommandLine& cmd_line,
-                          const fxl::Closure& complete_cb) {
+                          fit::closure complete_cb) {
   if (cmd_line.positional_args().size() != 1 || cmd_line.options().size()) {
     std::cout << "  Usage: set-adv-enable [enable|disable]" << std::endl;
     return false;
@@ -410,7 +402,7 @@
       ->mutable_payload<::btlib::hci::LESetAdvertisingEnableCommandParams>()
       ->advertising_enable = value;
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_LE_Set_Advertising_Enable (id=" << id << ")"
             << std::endl;
@@ -419,7 +411,7 @@
 
 bool HandleLESetAdvParams(const CommandData* cmd_data,
                           const fxl::CommandLine& cmd_line,
-                          const fxl::Closure& complete_cb) {
+                          fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: set-adv-params [--help|--type]" << std::endl;
     return false;
@@ -478,7 +470,7 @@
   params->adv_channel_map = ::btlib::hci::kLEAdvertisingChannelAll;
   params->adv_filter_policy = ::btlib::hci::LEAdvFilterPolicy::kAllowAll;
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_LE_Set_Advertising_Parameters (id=" << id << ")"
             << std::endl;
@@ -488,7 +480,7 @@
 
 bool HandleLESetAdvData(const CommandData* cmd_data,
                         const fxl::CommandLine& cmd_line,
-                        const fxl::Closure& complete_cb) {
+                        fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: set-adv-data [--help|--name]" << std::endl;
     return false;
@@ -532,7 +524,7 @@
         ->adv_data_length = 0;
   }
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_LE_Set_Advertising_Data (id=" << id << ")"
             << std::endl;
@@ -542,7 +534,7 @@
 
 bool HandleLESetScanParams(const CommandData* cmd_data,
                            const fxl::CommandLine& cmd_line,
-                           const fxl::Closure& complete_cb) {
+                           fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: set-scan-params [--help|--type]" << std::endl;
     return false;
@@ -585,7 +577,7 @@
   params->own_address_type = ::btlib::hci::LEOwnAddressType::kPublic;
   params->filter_policy = ::btlib::hci::LEScanFilterPolicy::kNoWhiteList;
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_LE_Set_Scan_Parameters (id=" << id << ")"
             << std::endl;
@@ -594,7 +586,7 @@
 }
 
 bool HandleLEScan(const CommandData* cmd_data, const fxl::CommandLine& cmd_line,
-                  const fxl::Closure& complete_cb) {
+                  fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: set-scan-params "
                  "[--help|--timeout=<t>|--no-dedup|--name-filter]"
@@ -677,15 +669,16 @@
       ::btlib::hci::kLEAdvertisingReportSubeventCode, le_adv_report_cb,
       cmd_data->dispatcher());
 
-  auto cleanup_cb = [complete_cb, event_handler_id,
+  fit::closure cleanup_cb = [complete_cb = complete_cb.share(), event_handler_id,
                      cmd_channel = cmd_data->cmd_channel()] {
     cmd_channel->RemoveEventHandler(event_handler_id);
     complete_cb();
   };
 
   // The callback invoked after scanning is stopped.
-  auto final_cb = [cleanup_cb](::btlib::hci::CommandChannel::TransactionId id,
-                               const ::btlib::hci::EventPacket& event) {
+  auto final_cb = [cleanup_cb = cleanup_cb.share()](
+                      ::btlib::hci::CommandChannel::TransactionId id,
+                      const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::SimpleReturnParams>();
     LogCommandResult(return_params->status, id);
@@ -693,7 +686,8 @@
   };
 
   // Delayed task that stops scanning.
-  auto scan_disable_cb = [cleanup_cb, final_cb, cmd_data] {
+  auto scan_disable_cb = [cleanup_cb = cleanup_cb.share(),
+                          final_cb = std::move(final_cb), cmd_data]() mutable {
     auto packet = ::btlib::hci::CommandPacket::New(
         ::btlib::hci::kLESetScanEnable, kPayloadSize);
     auto params =
@@ -702,16 +696,17 @@
     params->scanning_enabled = ::btlib::hci::GenericEnableParam::kDisable;
     params->filter_duplicates = ::btlib::hci::GenericEnableParam::kDisable;
 
-    auto id = SendCommand(cmd_data, std::move(packet), final_cb, cleanup_cb);
+    auto id = SendCommand(cmd_data, std::move(packet), std::move(final_cb), std::move(cleanup_cb));
 
     std::cout << "  Sent HCI_LE_Set_Scan_Enable (disabled) (id=" << id << ")"
               << std::endl;
   };
 
-  auto cb = [scan_disable_cb, cleanup_cb, timeout,
-             dispatcher = cmd_data->dispatcher()](
+  auto cb = [scan_disable_cb = std::move(scan_disable_cb),
+             cleanup_cb = cleanup_cb.share(), timeout,
+             dispatcher = cmd_data->dispatcher()] (
                 ::btlib::hci::CommandChannel::TransactionId id,
-                const ::btlib::hci::EventPacket& event) {
+                const ::btlib::hci::EventPacket& event) mutable {
     auto return_params =
         event.return_params<::btlib::hci::SimpleReturnParams>();
     LogCommandResult(return_params->status, id);
@@ -719,11 +714,11 @@
       cleanup_cb();
       return;
     }
-    async::PostDelayedTask(dispatcher, scan_disable_cb,
+    async::PostDelayedTask(dispatcher, std::move(scan_disable_cb),
                            zx::duration(timeout.ToNanoseconds()));
   };
 
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
 
   std::cout << "  Sent HCI_LE_Set_Scan_Enable (enabled) (id=" << id << ")"
             << std::endl;
@@ -732,7 +727,7 @@
 }
 
 bool HandleBRScan(const CommandData* cmd_data, const fxl::CommandLine& cmd_line,
-                  const fxl::Closure& complete_cb) {
+                  fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: scan "
                  "[--help|--timeout=<t>|--filter=<prefix>|--max-responses=<n>]"
@@ -804,7 +799,7 @@
 
   auto event_handler_ids = std::make_shared<
       std::vector<btlib::hci::CommandChannel::EventHandlerId>>();
-  auto cleanup_cb = [complete_cb, event_handler_ids,
+  fit::closure cleanup_cb = [complete_cb = std::move(complete_cb), event_handler_ids,
                      cmd_channel = cmd_data->cmd_channel()] {
     for (const auto& handler_id : *event_handler_ids) {
       cmd_channel->RemoveEventHandler(handler_id);
@@ -830,12 +825,12 @@
   };
 
   event_handler_ids->push_back(cmd_data->cmd_channel()->AddEventHandler(
-      ::btlib::hci::kInquiryResultEventCode, inquiry_result_cb,
+      ::btlib::hci::kInquiryResultEventCode, std::move(inquiry_result_cb),
       cmd_data->dispatcher()));
 
   // The callback invoked for an Inquiry Complete response.
   auto inquiry_complete_cb =
-      [cleanup_cb](const ::btlib::hci::EventPacket& event) {
+      [cleanup_cb = cleanup_cb.share()](const ::btlib::hci::EventPacket& event) mutable {
         auto params =
             event.view().payload<::btlib::hci::InquiryCompleteEventParams>();
         std::cout << fxl::StringPrintf("  Inquiry Complete - status: 0x%02x\n",
@@ -844,21 +839,22 @@
       };
 
   event_handler_ids->push_back(cmd_data->cmd_channel()->AddEventHandler(
-      ::btlib::hci::kInquiryCompleteEventCode, inquiry_complete_cb,
+      ::btlib::hci::kInquiryCompleteEventCode, std::move(inquiry_complete_cb),
       cmd_data->dispatcher()));
 
   // Delayed task that stops scanning.
-  auto inquiry_cancel_cb = [cleanup_cb, cmd_data] {
+  auto inquiry_cancel_cb = [cleanup_cb = cleanup_cb.share(), cmd_data]() mutable {
     auto packet =
         ::btlib::hci::CommandPacket::New(::btlib::hci::kInquiryCancel, 0);
-    auto id = SendCompleteCommand(cmd_data, std::move(packet), cleanup_cb);
+    auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(cleanup_cb));
     std::cout << "  Sent HCI_Inquiry_Cancel (id=" << id << ")" << std::endl;
   };
 
-  auto cb = [inquiry_cancel_cb, cleanup_cb, timeout,
+  auto cb = [inquiry_cancel_cb = std::move(inquiry_cancel_cb),
+             cleanup_cb = cleanup_cb.share(), timeout,
              dispatcher = cmd_data->dispatcher()](
                 ::btlib::hci::CommandChannel::TransactionId id,
-                const ::btlib::hci::EventPacket& event) {
+                const ::btlib::hci::EventPacket& event) mutable {
     auto return_params =
         event.view().payload<::btlib::hci::CommandStatusEventParams>();
     LogCommandResult(return_params.status, id, "Command Status");
@@ -866,14 +862,14 @@
       cleanup_cb();
       return;
     }
-    async::PostDelayedTask(dispatcher, inquiry_cancel_cb, timeout);
+    async::PostDelayedTask(dispatcher, std::move(inquiry_cancel_cb), timeout);
   };
 
   // Inquiry sends a Command Status, and then we wait for the Inquiry Complete,
   // or the timer to run out, for a long time. Count this as "complete" when the
   // Status comes in.
   auto id = cmd_data->cmd_channel()->SendCommand(
-      std::move(packet), cmd_data->dispatcher(), cb,
+      std::move(packet), cmd_data->dispatcher(), std::move(cb),
       ::btlib::hci::kCommandStatusEventCode);
   std::cout << "  Sent HCI_Inquiry (id=" << id << ")" << std::endl;
 
@@ -882,7 +878,7 @@
 
 bool HandleWritePageScanActivity(const CommandData* cmd_data,
                                  const fxl::CommandLine& cmd_line,
-                                 const fxl::Closure& complete_cb) {
+                                 fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: write-page-scan-activity [--help\n"
                  "                                   |--interval=<interval>\n"
@@ -976,7 +972,7 @@
   params->page_scan_interval = page_scan_interval;
   params->page_scan_window = page_scan_window;
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Write_Page_Scan_Activity (id=" << id << ")"
             << std::endl;
@@ -986,13 +982,14 @@
 
 bool HandleReadPageScanActivity(const CommandData* cmd_data,
                                 const fxl::CommandLine& cmd_line,
-                                const fxl::Closure& complete_cb) {
+                                fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: read-page-scan-activity" << std::endl;
     return false;
   }
 
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+  auto cb = [complete_cb = complete_cb.share()](
+                          ::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::ReadPageScanActivityReturnParams>();
@@ -1011,7 +1008,7 @@
 
   auto packet =
       ::btlib::hci::CommandPacket::New(::btlib::hci::kReadPageScanActivity);
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
   std::cout << "  Sent HCI_Read_Page_Scan_Activity (id=" << id << ")"
             << std::endl;
 
@@ -1020,7 +1017,7 @@
 
 bool HandleWritePageScanType(const CommandData* cmd_data,
                              const fxl::CommandLine& cmd_line,
-                             const fxl::Closure& complete_cb) {
+                             fit::closure complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout
         << "  Usage: write-page-scan-type [--help|--standard|--interlaced]"
@@ -1058,7 +1055,7 @@
       ->mutable_payload<::btlib::hci::WritePageScanTypeCommandParams>()
       ->page_scan_type = page_scan_type;
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Write_Page_Scan_Type (id=" << id << ")" << std::endl;
 
@@ -1067,13 +1064,14 @@
 
 bool HandleReadPageScanType(const CommandData* cmd_data,
                             const fxl::CommandLine& cmd_line,
-                            const fxl::Closure& complete_cb) {
+                            fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: read-page-scan-type" << std::endl;
     return false;
   }
 
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+  auto cb = [complete_cb = complete_cb.share()](
+                          ::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::ReadPageScanTypeReturnParams>();
@@ -1098,7 +1096,7 @@
 
   auto packet =
       ::btlib::hci::CommandPacket::New(::btlib::hci::kReadPageScanType);
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
   std::cout << "  Sent HCI_Read_Page_Scan_Type (id=" << id << ")" << std::endl;
 
   return true;
@@ -1106,7 +1104,7 @@
 
 bool HandleWriteScanEnable(const CommandData* cmd_data,
                            const fxl::CommandLine& cmd_line,
-                           const fxl::Closure& complete_cb) {
+                           fit::closure complete_cb) {
   if (cmd_line.positional_args().size() > 2) {
     std::cout << "  Usage: write-scan-enable [--help] [page] [inquiry]"
               << std::endl;
@@ -1147,7 +1145,7 @@
       ->mutable_payload<::btlib::hci::WriteScanEnableCommandParams>()
       ->scan_enable = scan_enable;
 
-  auto id = SendCompleteCommand(cmd_data, std::move(packet), complete_cb);
+  auto id = SendCompleteCommand(cmd_data, std::move(packet), std::move(complete_cb));
 
   std::cout << "  Sent HCI_Write_Scan_Enable (id=" << id << ")" << std::endl;
 
@@ -1156,13 +1154,14 @@
 
 bool HandleReadScanEnable(const CommandData* cmd_data,
                           const fxl::CommandLine& cmd_line,
-                          const fxl::Closure& complete_cb) {
+                          fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: read-scan-enable" << std::endl;
     return false;
   }
 
-  auto cb = [complete_cb](::btlib::hci::CommandChannel::TransactionId id,
+  auto cb = [complete_cb = complete_cb.share()](
+                          ::btlib::hci::CommandChannel::TransactionId id,
                           const ::btlib::hci::EventPacket& event) {
     auto return_params =
         event.return_params<::btlib::hci::ReadScanEnableReturnParams>();
@@ -1190,7 +1189,7 @@
   };
 
   auto packet = ::btlib::hci::CommandPacket::New(::btlib::hci::kReadScanEnable);
-  auto id = SendCommand(cmd_data, std::move(packet), cb, complete_cb);
+  auto id = SendCommand(cmd_data, std::move(packet), std::move(cb), std::move(complete_cb));
   std::cout << "  Sent HCI_Read_Scan_Enable (id=" << id << ")" << std::endl;
 
   return true;
diff --git a/bin/bluetooth/tools/bt-intel-tool/BUILD.gn b/bin/bluetooth/tools/bt-intel-tool/BUILD.gn
index d7fddfa..52b0031 100644
--- a/bin/bluetooth/tools/bt-intel-tool/BUILD.gn
+++ b/bin/bluetooth/tools/bt-intel-tool/BUILD.gn
@@ -20,4 +20,8 @@
     "//garnet/drivers/bluetooth/lib/gap",
     "//garnet/drivers/bluetooth/lib/hci",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
diff --git a/bin/bluetooth/tools/bt-intel-tool/command_channel.cc b/bin/bluetooth/tools/bt-intel-tool/command_channel.cc
index 93f47fa..6d92c7b 100644
--- a/bin/bluetooth/tools/bt-intel-tool/command_channel.cc
+++ b/bin/bluetooth/tools/bt-intel-tool/command_channel.cc
@@ -85,8 +85,8 @@
   acl_channel_wait_.Cancel();
 }
 
-void CommandChannel::SetEventCallback(const EventCallback& callback) {
-  event_callback_ = callback;
+void CommandChannel::SetEventCallback(EventCallback callback) {
+  event_callback_ = std::move(callback);
 }
 
 void CommandChannel::SendCommand(
@@ -108,18 +108,18 @@
 
 void CommandChannel::SendCommandSync(
     const ::btlib::common::PacketView<::btlib::hci::CommandHeader>& command,
-    const EventCallback& callback) {
+    EventCallback callback) {
   bool received = false;
-  auto previous_cb = event_callback_;
+  auto previous_cb = std::move(event_callback_);
 
-  auto cb = [this, &received, callback](const auto& event_packet) {
+  auto cb = [this, &received, callback = std::move(callback)](const auto& event_packet) {
     if (callback) {
       callback(event_packet);
     }
     received = true;
   };
 
-  SetEventCallback(cb);
+  SetEventCallback(std::move(cb));
   SendCommand(command);
 
   zx_status_t status = ZX_OK;
@@ -143,7 +143,7 @@
     }
   }
 
-  SetEventCallback(previous_cb);
+  SetEventCallback(std::move(previous_cb));
 
   if (status != ZX_OK) {
     std::cerr << "CommandChannel: error waiting for event "
diff --git a/bin/bluetooth/tools/bt-intel-tool/command_channel.h b/bin/bluetooth/tools/bt-intel-tool/command_channel.h
index 5b601d7..49e58b6 100644
--- a/bin/bluetooth/tools/bt-intel-tool/command_channel.h
+++ b/bin/bluetooth/tools/bt-intel-tool/command_channel.h
@@ -8,6 +8,7 @@
 #include <fbl/unique_fd.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/zx/channel.h>
+#include <lib/fit/function.h>
 #include <zircon/types.h>
 
 #include "garnet/drivers/bluetooth/lib/hci/control_packets.h"
@@ -28,8 +29,8 @@
   // Sets the event callback to be called when an HCI Event arrives on the
   // channel.
   using EventCallback =
-      std::function<void(const ::btlib::hci::EventPacket& event_packet)>;
-  void SetEventCallback(const EventCallback& callback);
+      fit::function<void(const ::btlib::hci::EventPacket& event_packet)>;
+  void SetEventCallback(EventCallback callback);
 
   // Sends the command in |command| to the controller. The channel must
   // be Ready when this is called.
@@ -41,7 +42,7 @@
   // returns.
   void SendCommandSync(
       const ::btlib::common::PacketView<::btlib::hci::CommandHeader>& command,
-      const EventCallback& callback);
+      EventCallback callback);
 
  private:
   // Common read handler implemntation
diff --git a/bin/bluetooth/tools/bt-intel-tool/commands.cc b/bin/bluetooth/tools/bt-intel-tool/commands.cc
index 11a5d5d..15ce990 100644
--- a/bin/bluetooth/tools/bt-intel-tool/commands.cc
+++ b/bin/bluetooth/tools/bt-intel-tool/commands.cc
@@ -110,7 +110,7 @@
 
 bool HandleReadVersion(CommandChannel* cmd_channel,
                        const fxl::CommandLine& cmd_line,
-                       const fxl::Closure& complete_cb) {
+                       const fit::closure& complete_cb) {
   if (cmd_line.positional_args().size()) {
     std::cout << "  Usage: read-version [--verbose]" << std::endl;
     return false;
@@ -161,7 +161,7 @@
 
 bool HandleReadBootParams(CommandChannel* cmd_channel,
                           const fxl::CommandLine& cmd_line,
-                          const fxl::Closure& complete_cb) {
+                          fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: read-boot-params" << std::endl;
     return false;
@@ -202,7 +202,7 @@
 }
 
 bool HandleReset(CommandChannel* cmd_channel, const fxl::CommandLine& cmd_line,
-                 const fxl::Closure& complete_cb) {
+                 fit::closure complete_cb) {
   if (cmd_line.positional_args().size() || cmd_line.options().size()) {
     std::cout << "  Usage: reset" << std::endl;
     return false;
@@ -235,7 +235,7 @@
 
 bool HandleLoadBseq(CommandChannel* cmd_channel,
                     const fxl::CommandLine& cmd_line,
-                    const fxl::Closure& complete_cb) {
+                    fit::closure complete_cb) {
   if (cmd_line.positional_args().size() != 1) {
     std::cout << "  Usage: load-bseq [--verbose] <filename>" << std::endl;
     return false;
@@ -260,7 +260,7 @@
 
 bool HandleLoadSecure(CommandChannel* cmd_channel,
                       const fxl::CommandLine& cmd_line,
-                      const fxl::Closure& complete_cb) {
+                      fit::closure complete_cb) {
   if (cmd_line.positional_args().size() != 1) {
     std::cout << "  Usage: load-sfi [--verbose] <filename>" << std::endl;
     return false;
diff --git a/bin/bluetooth/tools/bt-le-central/src/common/central.rs b/bin/bluetooth/tools/bt-le-central/src/common/central.rs
index edb151f..d58e568 100644
--- a/bin/bluetooth/tools/bt-le-central/src/common/central.rs
+++ b/bin/bluetooth/tools/bt-le-central/src/common/central.rs
@@ -8,8 +8,9 @@
 use async;
 
 use bt::error::Error as BTError;
-use common::gatt::{create_client_pair, start_gatt_loop};
+use common::gatt::start_gatt_loop;
 use failure::Error;
+use fidl::endpoints2;
 use fidl_ble::{CentralDelegate, CentralDelegateImpl, CentralProxy, RemoteDevice};
 use futures::future;
 use futures::future::Either::{Left, Right};
@@ -103,7 +104,7 @@
 // GATT REPL if this succeeds.
 fn connect_peripheral(state: CentralStatePtr, mut id: String)
     -> impl Future<Item = (), Error = Error> {
-    let (proxy, server) = match create_client_pair() {
+    let (proxy, server) = match endpoints2::create_endpoints() {
         Err(_) => {
             return Left(future::err(
                 BTError::new("Failed to create Client pair").into(),
diff --git a/bin/bluetooth/tools/bt-le-central/src/common/gatt.rs b/bin/bluetooth/tools/bt-le-central/src/common/gatt.rs
index ba06fef..cd1ad6a 100644
--- a/bin/bluetooth/tools/bt-le-central/src/common/gatt.rs
+++ b/bin/bluetooth/tools/bt-le-central/src/common/gatt.rs
@@ -8,9 +8,9 @@
 use bt::error::Error as BTError;
 use common::gatt_types::Service;
 use failure::Error;
-use fidl::endpoints2::ServerEnd;
-use fidl_gatt::{Characteristic as FidlCharacteristic, ClientMarker, ClientProxy,
-                RemoteServiceEvent, RemoteServiceMarker, RemoteServiceProxy, ServiceInfo};
+use fidl::endpoints2;
+use fidl_gatt::{Characteristic as FidlCharacteristic, ClientProxy,
+                RemoteServiceEvent, RemoteServiceProxy, ServiceInfo};
 use futures::{Future, FutureExt, Never, Stream, StreamExt, future};
 use futures::channel::mpsc::channel;
 use futures::future::Either::{Left, Right};
@@ -21,7 +21,6 @@
 use std::string::String;
 use std::sync::Arc;
 use std::thread;
-use zx;
 
 macro_rules! left_ok {
     () => (Left(future::ok(())))
@@ -251,26 +250,6 @@
     future::ok(())
 }
 
-fn create_remote_service_pair()
-    -> Result<(RemoteServiceProxy, ServerEnd<RemoteServiceMarker>), Error>
-{
-    let (chan_local, chan_remote) = zx::Channel::create()?;
-    let local = async::Channel::from_channel(chan_local)?;
-    let server_end = ServerEnd::<RemoteServiceMarker>::new(chan_remote);
-    let proxy = RemoteServiceProxy::new(local);
-
-    Ok((proxy, server_end))
-}
-
-pub fn create_client_pair() -> Result<(ClientProxy, ServerEnd<ClientMarker>), Error> {
-    let (chan_local, chan_remote) = zx::Channel::create()?;
-    let local = async::Channel::from_channel(chan_local)?;
-    let server_end = ServerEnd::<ClientMarker>::new(chan_remote);
-    let proxy = ClientProxy::new(local);
-
-    Ok((proxy, server_end))
-}
-
 fn do_connect(args: Vec<&str>, client: GattClientPtr) -> impl Future<Item = (), Error = Error> {
     if args.len() != 1 {
         println!("usage: connect <index>");
@@ -294,7 +273,7 @@
     };
 
     // Initialize the remote service proxy.
-    match create_remote_service_pair() {
+    match endpoints2::create_endpoints() {
         Err(e) => Left(future::err(e.into())),
         Ok((proxy, server)) => {
             // First close the connection to the currently active service.
diff --git a/bin/bluetooth/tools/bt-le-central/src/main.rs b/bin/bluetooth/tools/bt-le-central/src/main.rs
index 0608a91..2aa6a94 100644
--- a/bin/bluetooth/tools/bt-le-central/src/main.rs
+++ b/bin/bluetooth/tools/bt-le-central/src/main.rs
@@ -7,9 +7,9 @@
 
 extern crate failure;
 extern crate fidl;
-extern crate fidl_bluetooth as fidl_bt;
-extern crate fidl_bluetooth_gatt as fidl_gatt;
-extern crate fidl_bluetooth_low_energy as fidl_ble;
+extern crate fidl_fuchsia_bluetooth as fidl_bt;
+extern crate fidl_fuchsia_bluetooth_gatt as fidl_gatt;
+extern crate fidl_fuchsia_bluetooth_le as fidl_ble;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 extern crate fuchsia_bluetooth as bt;
@@ -121,15 +121,13 @@
         return Left(future::err(BTError::new("invalid input").into()));
     }
 
-    let (_, remote) = match zx::Channel::create() {
+    let (_, server_end) = match fidl::endpoints2::create_endpoints() {
         Err(e) => {
             return Left(future::err(e.into()));
         }
         Ok(x) => x,
     };
 
-    let server_end = fidl::endpoints2::ServerEnd::<fidl_gatt::ClientMarker>::new(remote);
-
     Right(
         central
             .connect_peripheral(&mut args[0].clone(), server_end)
diff --git a/bin/bluetooth/tools/lib/BUILD.gn b/bin/bluetooth/tools/lib/BUILD.gn
index 8798b1d..533a01c 100644
--- a/bin/bluetooth/tools/lib/BUILD.gn
+++ b/bin/bluetooth/tools/lib/BUILD.gn
@@ -11,4 +11,8 @@
   deps = [
     "//garnet/public/lib/fxl",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
diff --git a/bin/bluetooth/tools/lib/command_dispatcher.cc b/bin/bluetooth/tools/lib/command_dispatcher.cc
index f55e739..9bb2016 100644
--- a/bin/bluetooth/tools/lib/command_dispatcher.cc
+++ b/bin/bluetooth/tools/lib/command_dispatcher.cc
@@ -12,11 +12,11 @@
 namespace bluetooth_tools {
 
 CommandDispatcher::CommandHandlerData::CommandHandlerData(
-    const std::string& description, const CommandHandler& handler)
-    : description(description), handler(handler) {}
+    const std::string& description, CommandHandler handler)
+    : description(description), handler(std::move(handler)) {}
 
 bool CommandDispatcher::ExecuteCommand(const std::vector<std::string>& argv,
-                                       const fxl::Closure& complete_cb,
+                                       fit::closure complete_cb,
                                        bool* out_cmd_found) {
   FXL_DCHECK(out_cmd_found);
 
@@ -34,7 +34,7 @@
   *out_cmd_found = true;
 
   auto cl = fxl::CommandLineFromIterators(argv.begin(), argv.end());
-  return iter->second.handler(cl, complete_cb);
+  return iter->second.handler(cl, std::move(complete_cb));
 }
 
 void CommandDispatcher::DescribeAllCommands() const {
@@ -46,12 +46,12 @@
 
 void CommandDispatcher::RegisterHandler(const std::string& name,
                                         const std::string& description,
-                                        const CommandHandler& handler) {
+                                        CommandHandler handler) {
   FXL_DCHECK(!name.empty());
   FXL_DCHECK(!description.empty());
   FXL_DCHECK(handler_map_.find(name) == handler_map_.end());
 
-  handler_map_[name] = CommandHandlerData(description, handler);
+  handler_map_[name] = CommandHandlerData(description, std::move(handler));
 }
 
 std::vector<std::string> CommandDispatcher::GetCommandsThatMatch(
diff --git a/bin/bluetooth/tools/lib/command_dispatcher.h b/bin/bluetooth/tools/lib/command_dispatcher.h
index 0db9288..c70311b 100644
--- a/bin/bluetooth/tools/lib/command_dispatcher.h
+++ b/bin/bluetooth/tools/lib/command_dispatcher.h
@@ -4,11 +4,11 @@
 
 #pragma once
 
-#include <functional>
 #include <map>
 
+#include <lib/fit/function.h>
+
 #include "lib/fxl/command_line.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
 namespace bluetooth_tools {
@@ -28,7 +28,7 @@
   // previously registered. |out_cmd_found| will be set to false if no comand
   // handler for this command was registered, true otherwise.
   bool ExecuteCommand(const std::vector<std::string>& argv,
-                      const fxl::Closure& complete_cb, bool* out_cmd_found);
+                      fit::closure complete_cb, bool* out_cmd_found);
 
   // Prints the names of all commands and their descriptions.
   void DescribeAllCommands() const;
@@ -41,15 +41,15 @@
   //
   // Once a command has been executed, |complete_cb| should be called to mark
   // completion the of the command.
-  using CommandHandler = std::function<bool(
-      const fxl::CommandLine& command_line, const fxl::Closure& complete_cb)>;
+  using CommandHandler = fit::function<bool(
+      const fxl::CommandLine& command_line, fit::closure complete_cb)>;
 
   // Registers a handler to be executed for the command |command_name|.
   // |description| is the string that describes the command (to be displayed by
   // DescribedAllCommands()).
   void RegisterHandler(const std::string& command_name,
                        const std::string& description,
-                       const CommandHandler& handler);
+                       CommandHandler handler);
 
   // Returns a list of currently registered command names that start with
   // |prefix|.
@@ -59,7 +59,7 @@
  private:
   struct CommandHandlerData {
     CommandHandlerData(const std::string& description,
-                       const CommandHandler& handler);
+                       CommandHandler handler);
     CommandHandlerData() = default;
 
     std::string description;
diff --git a/bin/cobalt/BUILD.gn b/bin/cobalt/BUILD.gn
index 374e92f..3c059aa 100644
--- a/bin/cobalt/BUILD.gn
+++ b/bin/cobalt/BUILD.gn
@@ -24,6 +24,7 @@
     "testapp:cobalt_testapp",
     "testapp:cobalt_testapp_no_environment",
     "testapp:cobalt_testapp_no_network",
+    "utils:cobalt_utils_unittests",
   ]
 
   binaries = [
@@ -38,6 +39,10 @@
     },
 
     {
+      name = "cobalt_utils_unittests"
+    },
+
+    {
       name = "cobalt_encoder_unittests"
     },
 
diff --git a/bin/cobalt/app/BUILD.gn b/bin/cobalt/app/BUILD.gn
index 864bd5a..44a1e8f 100644
--- a/bin/cobalt/app/BUILD.gn
+++ b/bin/cobalt/app/BUILD.gn
@@ -23,10 +23,12 @@
   ]
 
   public_deps = [
+    "//garnet/bin/cobalt/utils:fuchsia_http_client",
     "//garnet/lib/wlan/mlme:mlme",
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
+    "//garnet/public/lib/network_wrapper",
     "//third_party/cobalt/config:client_config",
     "//third_party/cobalt/config:cobalt_config_proto",
     "//third_party/cobalt/encoder",
diff --git a/bin/cobalt/app/cobalt_app.cc b/bin/cobalt/app/cobalt_app.cc
index 3df4da5..8e02ce8 100644
--- a/bin/cobalt/app/cobalt_app.cc
+++ b/bin/cobalt/app/cobalt_app.cc
@@ -5,14 +5,21 @@
 #include "garnet/bin/cobalt/app/cobalt_app.h"
 
 #include "garnet/bin/cobalt/app/utils.h"
+#include "garnet/bin/cobalt/utils/fuchsia_http_client.h"
+#include "lib/backoff/exponential_backoff.h"
 
 namespace cobalt {
 
+namespace http = ::fuchsia::net::oldhttp;
+
+using clearcut::ClearcutUploader;
 using config::ClientConfig;
+using encoder::ClearcutV1ShippingManager;
 using encoder::ClientSecret;
 using encoder::CobaltEncoderFactoryImpl;
 using encoder::LegacyShippingManager;
 using encoder::ShippingManager;
+using utils::FuchsiaHTTPClient;
 
 // Each "send attempt" is actually a cycle of potential retries. These
 // two parameters configure the SendRetryer.
@@ -24,6 +31,7 @@
 const size_t kMinEnvelopeSendSize = 10 * 1024;   // 10 K
 
 constexpr char kCloudShufflerUri[] = "shuffler.cobalt-api.fuchsia.com:443";
+const char kClearcutServerUri[] = "https://jmt17.google.com/log";
 
 constexpr char kConfigBinProtoPath[] = "/pkg/data/cobalt_config.binproto";
 constexpr char kAnalyzerPublicKeyPemPath[] =
@@ -38,6 +46,12 @@
       context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
       shuffler_client_(kCloudShufflerUri, true),
       send_retryer_(&shuffler_client_),
+      network_wrapper_(
+          async, std::make_unique<backoff::ExponentialBackoff>(),
+          [this] {
+            return context_
+                ->ConnectToEnvironmentService<http::HttpService>();
+          }),
       timer_manager_(async),
       controller_impl_(new CobaltControllerImpl(async, &shipping_dispatcher_)) {
   auto size_params = ShippingManager::SizeParams(
@@ -57,6 +71,13 @@
           ShippingManager::SendRetryerParams(kInitialRpcDeadline,
                                              kDeadlinePerSendAttempt),
           &send_retryer_));
+  shipping_dispatcher_.Register(
+      ObservationMetadata::V1_BACKEND,
+      std::make_unique<ClearcutV1ShippingManager>(
+          size_params, schedule_params, envelope_maker_params,
+          std::make_unique<ClearcutUploader>(
+              kClearcutServerUri,
+              std::make_unique<FuchsiaHTTPClient>(&network_wrapper_, async))));
   shipping_dispatcher_.Start();
 
   // Open the cobalt config file.
diff --git a/bin/cobalt/app/cobalt_app.h b/bin/cobalt/app/cobalt_app.h
index be66d5a..92e61a3 100644
--- a/bin/cobalt/app/cobalt_app.h
+++ b/bin/cobalt/app/cobalt_app.h
@@ -19,6 +19,7 @@
 #include "garnet/bin/cobalt/app/cobalt_encoder_impl.h"
 #include "garnet/bin/cobalt/app/timer_manager.h"
 #include "lib/app/cpp/startup_context.h"
+#include "lib/network_wrapper/network_wrapper_impl.h"
 #include "third_party/cobalt/encoder/client_secret.h"
 #include "third_party/cobalt/encoder/send_retryer.h"
 #include "third_party/cobalt/encoder/shipping_dispatcher.h"
@@ -28,6 +29,16 @@
 
 class CobaltApp {
  public:
+  // |async| The async_t to be used for all asynchronous operations.
+  //
+  // |schedule_interval| The scheduling interval provided to
+  //                     ShippingManager::ScheduleParams.
+  //
+  // |min_interval| The minimum interval provided to
+  //                ShippingManager::ScheduleParams.
+  //
+  // |product_name| A product name to override the one used in the
+  //                ObservationMetadata.
   CobaltApp(async_t* async, std::chrono::seconds schedule_interval,
             std::chrono::seconds min_interval, const std::string& product_name);
 
@@ -40,6 +51,7 @@
 
   encoder::ShufflerClient shuffler_client_;
   encoder::send_retryer::SendRetryer send_retryer_;
+  network_wrapper::NetworkWrapperImpl network_wrapper_;
   encoder::ShippingDispatcher shipping_dispatcher_;
   TimerManager timer_manager_;
 
diff --git a/bin/cobalt/app/cobalt_controller_impl.cc b/bin/cobalt/app/cobalt_controller_impl.cc
index 14be13e..34cf260 100644
--- a/bin/cobalt/app/cobalt_controller_impl.cc
+++ b/bin/cobalt/app/cobalt_controller_impl.cc
@@ -14,10 +14,10 @@
 
 void CobaltControllerImpl::RequestSendSoon(RequestSendSoonCallback callback) {
   // callback_adapter invokes |callback| on the main thread.
-  std::function<void(bool)> callback_adapter = [this, callback](bool success) {
+  auto callback_adapter = [this, callback](bool success) {
     async::PostTask(async_, [callback, success]() { callback(success); });
   };
-  shipping_dispatcher_->RequestSendSoon(callback_adapter);
+  shipping_dispatcher_->RequestSendSoon(std::move(callback_adapter));
 }
 
 void CobaltControllerImpl::BlockUntilEmpty(uint32_t max_wait_seconds,
diff --git a/bin/cobalt/testapp/cobalt_testapp.cc b/bin/cobalt/testapp/cobalt_testapp.cc
index be52ef2..fdd2c27 100644
--- a/bin/cobalt/testapp/cobalt_testapp.cc
+++ b/bin/cobalt/testapp/cobalt_testapp.cc
@@ -101,6 +101,11 @@
 const std::string kAppPartName = "app_name";
 const uint32_t kAppNameEncodingId = 4;
 
+// For testing V1_BACKEND.
+const uint32_t kV1BackendMetricId = 10;
+const uint32_t kV1BackendEncodingId = 4;
+const std::string kV1BackendEvent = "Send-to-V1";
+
 std::string StatusToString(cobalt::Status status) {
   switch (status) {
     case cobalt::Status::OK:
@@ -185,6 +190,8 @@
 
   bool TestAppStartupTime();
 
+  bool TestV1Backend();
+
   bool RequestSendSoonTests();
 
   // Synchronously invokes AddStringObservation() |num_observations_per_batch_|
@@ -396,6 +403,9 @@
   if (!TestAppStartupTime()) {
     return false;
   }
+  if (!TestV1Backend()) {
+    return false;
+  }
   return true;
 }
 
@@ -538,6 +548,16 @@
   return success;
 }
 
+bool CobaltTestApp::TestV1Backend() {
+  FXL_LOG(INFO) << "========================";
+  FXL_LOG(INFO) << "TestV1Backend";
+  bool use_request_send_soon = true;
+  bool success = EncodeStringAndSend(kV1BackendMetricId, kV1BackendEncodingId,
+                                     kV1BackendEvent, use_request_send_soon);
+  FXL_LOG(INFO) << "TestV1Backend : " << (success ? "PASS" : "FAIL");
+  return success;
+}
+
 bool CobaltTestApp::EncodeStringAndSend(uint32_t metric_id,
                                         uint32_t encoding_config_id,
                                         std::string val,
diff --git a/bin/cobalt/utils/BUILD.gn b/bin/cobalt/utils/BUILD.gn
new file mode 100644
index 0000000..77c49e9
--- /dev/null
+++ b/bin/cobalt/utils/BUILD.gn
@@ -0,0 +1,31 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("fuchsia_http_client") {
+  sources = [
+    "fuchsia_http_client.cc",
+    "fuchsia_http_client.h",
+  ]
+  public_deps = [
+    "//garnet/public/lib/network_wrapper:network_wrapper",
+    "//third_party/cobalt/third_party/clearcut:clearcut",
+    "//third_party/cobalt/third_party/tensorflow_statusor:statusor",
+  ]
+}
+
+executable("cobalt_utils_unittests") {
+  testonly = true
+
+  sources = [
+    "fuchsia_http_client_test.cc",
+  ]
+
+  deps = [
+    ":fuchsia_http_client",
+    "//garnet/public/lib/fxl/test:gtest_main",
+    "//garnet/public/lib/gtest",
+    "//garnet/public/lib/network_wrapper:fake",
+    "//third_party/googletest:gtest",
+  ]
+}
diff --git a/bin/cobalt/utils/fuchsia_http_client.cc b/bin/cobalt/utils/fuchsia_http_client.cc
new file mode 100644
index 0000000..c272227
--- /dev/null
+++ b/bin/cobalt/utils/fuchsia_http_client.cc
@@ -0,0 +1,160 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
+#include <lib/async/cpp/task.h>
+#include <lib/async/cpp/time.h>
+#include <lib/async/default.h>
+
+#include "garnet/bin/cobalt/utils/fuchsia_http_client.h"
+#include "lib/fsl/socket/strings.h"
+#include "lib/fsl/vmo/strings.h"
+#include "lib/fxl/memory/ref_counted.h"
+
+namespace cobalt {
+namespace utils {
+
+namespace http = ::fuchsia::net::oldhttp;
+
+using clearcut::HTTPClient;
+using clearcut::HTTPRequest;
+using clearcut::HTTPResponse;
+using tensorflow_statusor::StatusOr;
+
+namespace {
+
+http::URLRequest MakeRequest(fxl::RefPtr<NetworkRequest> network_request) {
+  http::URLRequest fx_request;
+  fx_request.url = network_request->request().url;
+  fx_request.method = "POST";
+  fx_request.auto_follow_redirects = true;
+  fx_request.body = http::URLBody::New();
+
+  fsl::SizedVmo data;
+  auto result = fsl::VmoFromString(network_request->request().body, &data);
+  FXL_CHECK(result);
+
+  fx_request.body->set_sized_buffer(std::move(data).ToTransport());
+  for (const auto& header : network_request->request().headers) {
+    http::HttpHeader hdr;
+    hdr.name = header.first;
+    hdr.value = header.second;
+    fx_request.headers.push_back(std::move(hdr));
+  }
+  return fx_request;
+}
+
+}  // namespace
+
+void NetworkRequest::ReadResponse(async_t* async,
+                                  fxl::RefPtr<NetworkRequest> self,
+                                  uint32_t http_code, zx::socket source) {
+  // Store a reference to myself, so that I don't get deleted while reading from
+  // the socket.
+  self_ = self;
+  http_code_ = http_code;
+  socket_drainer_ = std::make_unique<fsl::SocketDrainer>(this, async);
+  socket_drainer_->Start(std::move(source));
+}
+
+void NetworkRequest::OnDataAvailable(const void* data, size_t num_bytes) {
+  response_.append(static_cast<const char*>(data), num_bytes);
+}
+
+void NetworkRequest::OnDataComplete() {
+  HTTPResponse response;
+  response.response = response_;
+  response.http_code = http_code_;
+  SetValueAndCleanUp(std::move(response));
+}
+
+FuchsiaHTTPClient::FuchsiaHTTPClient(
+    network_wrapper::NetworkWrapper* network_wrapper, async_t* async)
+    : network_wrapper_(network_wrapper), async_(async) {}
+
+void FuchsiaHTTPClient::HandleResponse(fxl::RefPtr<NetworkRequest> req,
+                                       http::URLResponse fx_response) {
+  req->CancelCallbacks();
+  if (fx_response.error) {
+    std::ostringstream ss;
+    ss << fx_response.url << " error " << fx_response.error->description;
+    req->SetValueAndCleanUp(util::Status(util::StatusCode::INTERNAL, ss.str()));
+    return;
+  }
+  if (fx_response.body) {
+    FXL_DCHECK(fx_response.body->is_stream());
+    req->ReadResponse(async_, req, fx_response.status_code,
+                      std::move(fx_response.body->stream()));
+  } else {
+    HTTPResponse response;
+    response.response = "";
+    response.http_code = fx_response.status_code;
+    req->SetValueAndCleanUp(std::move(response));
+  }
+}
+
+void FuchsiaHTTPClient::HandleDeadline(fxl::RefPtr<NetworkRequest> req) {
+  req->CancelCallbacks();
+  req->SetValueAndCleanUp(
+      util::Status(util::StatusCode::DEADLINE_EXCEEDED,
+                   "Deadline exceeded while waiting for network request"));
+}
+
+void FuchsiaHTTPClient::SendRequest(
+    fxl::RefPtr<NetworkRequest> network_request) {
+  network_request->SetNetworkWrapperCancel(network_wrapper_->Request(
+      std::bind(&MakeRequest, network_request),
+      [this, network_request](http::URLResponse fx_response) {
+        HandleResponse(network_request, std::move(fx_response));
+      }));
+}
+
+void NetworkRequest::CancelCallbacks() {
+  if (network_wrapper_cancel_) {
+    network_wrapper_cancel_->Cancel();
+  }
+  if (deadline_task_) {
+    deadline_task_->Cancel();
+  }
+}
+
+void NetworkRequest::SetValueAndCleanUp(StatusOr<HTTPResponse> value) {
+  promise_.set_value(std::move(value));
+
+  // Clean up stored references so NetworkRequest can be freed.
+  if (network_wrapper_cancel_) {
+    network_wrapper_cancel_ = nullptr;
+  }
+  if (deadline_task_) {
+    deadline_task_ = nullptr;
+  }
+  if (socket_drainer_) {
+    socket_drainer_ = nullptr;
+  }
+  self_ = nullptr;
+}
+
+std::future<StatusOr<HTTPResponse>> FuchsiaHTTPClient::Post(
+    HTTPRequest request, std::chrono::steady_clock::time_point deadline) {
+  ZX_ASSERT_MSG(async_get_default() != async_,
+                "Post should not be called from the same thread as async_, as "
+                "this may cause deadlocks");
+  auto network_request =
+      fxl::MakeRefCounted<NetworkRequest>(std::move(request));
+  network_request->SetDeadlineTask(std::make_unique<async::TaskClosure>(
+      [this, network_request] { HandleDeadline(network_request); }));
+
+  async::PostTask(async_,
+                  [this, network_request]() { SendRequest(network_request); });
+
+  auto duration = zx::nsec(std::chrono::duration_cast<std::chrono::nanoseconds>(
+                               deadline - std::chrono::steady_clock::now())
+                               .count());
+  network_request->ScheduleDeadline(async_, duration);
+
+  return network_request->get_future();
+}
+
+}  // namespace utils
+}  // namespace cobalt
diff --git a/bin/cobalt/utils/fuchsia_http_client.h b/bin/cobalt/utils/fuchsia_http_client.h
new file mode 100644
index 0000000..31a848f
--- /dev/null
+++ b/bin/cobalt/utils/fuchsia_http_client.h
@@ -0,0 +1,113 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_COBALT_UTILS_FUCHSIA_HTTP_CLIENT_H_
+#define GARNET_BIN_COBALT_UTILS_FUCHSIA_HTTP_CLIENT_H_
+
+#include "garnet/public/lib/network_wrapper/network_wrapper.h"
+#include "lib/fsl/socket/socket_drainer.h"
+#include "third_party/cobalt/third_party/clearcut/http_client.h"
+#include "third_party/cobalt/third_party/tensorflow_statusor/statusor.h"
+
+namespace cobalt {
+namespace utils {
+
+class NetworkRequest;
+
+// FuchsiaHTTPClient implements clearcut::HTTPClient using fuchsia's
+// NetworkWrapper library. Since this class uses the async_t supplied to the
+// constructor to run all of the tasks on a single thread, this class is thread
+// safe. However, the response from Post should not be waited on from that
+// thread or a deadlock will occur.
+class FuchsiaHTTPClient : public ::clearcut::HTTPClient {
+ public:
+  FuchsiaHTTPClient(network_wrapper::NetworkWrapper* network_wrapper,
+                    async_t* async);
+
+  // Posts an HTTPRequest to fuchsia's network backend.
+  //
+  // Note: Do not invoke this method from |async_|'s thread.
+  // Note: Do not wait on the returned future from |async_|'s thread.
+  std::future<tensorflow_statusor::StatusOr<clearcut::HTTPResponse>> Post(
+      clearcut::HTTPRequest request,
+      std::chrono::steady_clock::time_point deadline);
+
+ protected:
+  // These are internal only functions that are intended to make
+  // instrumentation of tests easier.
+  virtual void HandleResponse(fxl::RefPtr<NetworkRequest> req,
+                              ::fuchsia::net::oldhttp::URLResponse fx_response);
+  virtual void HandleDeadline(fxl::RefPtr<NetworkRequest> req);
+
+ private:
+  virtual void SendRequest(fxl::RefPtr<NetworkRequest> network_request);
+
+  // |network_wrapper_| is thread averse, and should only be accessed on the
+  // main thread of |async_|.
+  network_wrapper::NetworkWrapper* network_wrapper_;
+  async_t* async_;
+};
+
+// NetworkRequest holds the state information for a single call to
+// FuchsiaHTTPClient::Post.
+class NetworkRequest : public fxl::RefCountedThreadSafe<NetworkRequest>,
+                       public fsl::SocketDrainer::Client {
+ public:
+  NetworkRequest(clearcut::HTTPRequest req) : request_(std::move(req)) {}
+
+  void ReadResponse(async_t* async, fxl::RefPtr<NetworkRequest> self,
+                    uint32_t http_code, zx::socket source);
+  void OnDataAvailable(const void* data, size_t num_bytes);
+  void OnDataComplete();
+
+  void CancelCallbacks();
+
+  std::future<tensorflow_statusor::StatusOr<clearcut::HTTPResponse>>
+  get_future() {
+    return promise_.get_future();
+  }
+
+  void SetValueAndCleanUp(
+      tensorflow_statusor::StatusOr<clearcut::HTTPResponse> value);
+
+  const clearcut::HTTPRequest& request() { return request_; }
+
+  void SetNetworkWrapperCancel(
+      fxl::RefPtr<callback::Cancellable> network_wrapper_cancel) {
+    network_wrapper_cancel_ = network_wrapper_cancel;
+  }
+
+  void SetDeadlineTask(std::unique_ptr<async::TaskClosure> deadline_task) {
+    deadline_task_ = std::move(deadline_task);
+  }
+
+  void ScheduleDeadline(async_t* async, zx::duration duration) {
+    deadline_task_->PostDelayed(async, duration);
+  }
+
+ private:
+  FRIEND_REF_COUNTED_THREAD_SAFE(NetworkRequest);
+  ~NetworkRequest() {}
+
+  // The request object.
+  clearcut::HTTPRequest request_;
+  // Response information to be sent to the promise.
+  std::string response_;
+  uint32_t http_code_;
+  // The promise used for returning a value.
+  std::promise<tensorflow_statusor::StatusOr<clearcut::HTTPResponse>> promise_;
+  // A reference to itself that will be set when ReadResponse is used.
+  fxl::RefPtr<NetworkRequest> self_;
+  // Task which will cancel the network request if triggered.
+  std::unique_ptr<async::TaskClosure> deadline_task_;
+  // The callback to cancel the network request.
+  fxl::RefPtr<callback::Cancellable> network_wrapper_cancel_;
+  // The SocketDrainer used to read the data from the network
+  std::unique_ptr<fsl::SocketDrainer> socket_drainer_;
+};
+
+}  // namespace utils
+}  // namespace cobalt
+
+#endif  // GARNET_BIN_COBALT_UTILS_FUCHSIA_HTTP_CLIENT_H_
diff --git a/bin/cobalt/utils/fuchsia_http_client_test.cc b/bin/cobalt/utils/fuchsia_http_client_test.cc
new file mode 100644
index 0000000..30daee6
--- /dev/null
+++ b/bin/cobalt/utils/fuchsia_http_client_test.cc
@@ -0,0 +1,193 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <lib/async/cpp/task.h>
+
+#include "garnet/bin/cobalt/utils/fuchsia_http_client.h"
+#include "gtest/gtest.h"
+#include "lib/gtest/test_with_loop.h"
+#include "lib/network_wrapper/fake_network_wrapper.h"
+
+namespace cobalt {
+namespace utils {
+
+namespace http = ::fuchsia::net::oldhttp;
+
+using clearcut::HTTPRequest;
+using clearcut::HTTPResponse;
+using network_wrapper::FakeNetworkWrapper;
+using network_wrapper::NetworkWrapper;
+using tensorflow_statusor::StatusOr;
+
+class CVBool {
+ public:
+  CVBool() : set_(false) {}
+
+  void Notify() {
+    {
+      std::unique_lock<std::mutex> lock(mutex_);
+      set_ = true;
+    }
+    cv_.notify_all();
+  }
+
+  template <class Rep, class Period>
+  bool Wait(const std::chrono::duration<Rep, Period>& duration) {
+    std::unique_lock<std::mutex> lock(mutex_);
+    if (set_) {
+      return true;
+    }
+    return cv_.wait_for(lock, duration, [this] { return set_; });
+  }
+
+  bool Check() {
+    std::unique_lock<std::mutex> lock(mutex_);
+    return set_;
+  }
+
+ private:
+  std::mutex mutex_;
+  std::condition_variable cv_;
+  bool set_;
+};
+
+class TestFuchsiaHTTPClient : public FuchsiaHTTPClient {
+ public:
+  TestFuchsiaHTTPClient(NetworkWrapper* network_wrapper, async_t* async)
+      : FuchsiaHTTPClient(network_wrapper, async) {}
+
+  void HandleResponse(fxl::RefPtr<NetworkRequest> req,
+                      http::URLResponse fx_response) override {
+    FuchsiaHTTPClient::HandleResponse(req, std::move(fx_response));
+    response_handled_.Notify();
+  }
+
+  void HandleDeadline(fxl::RefPtr<NetworkRequest> req) override {
+    deadline_triggered_.Notify();
+    FuchsiaHTTPClient::HandleDeadline(req);
+  }
+
+  bool CheckResponseHandled() { return response_handled_.Check(); }
+  bool CheckDeadlineTriggered() { return deadline_triggered_.Check(); }
+
+  CVBool response_handled_;
+  CVBool deadline_triggered_;
+};
+
+class FuchsiaHTTPClientTest : public ::gtest::TestWithLoop {
+ public:
+  FuchsiaHTTPClientTest()
+      : ::gtest::TestWithLoop(),
+        network_wrapper_(dispatcher()),
+        delete_after_post_(false),
+        http_client(
+            new TestFuchsiaHTTPClient(&network_wrapper_, dispatcher())) {}
+
+  void PrepareResponse(const std::string& body, uint32_t status_code = 200) {
+    network_wrapper_.SetStringResponse(body, status_code);
+  }
+
+  void PrepareResponse(zx::socket body, uint32_t status_code = 200) {
+    network_wrapper_.SetSocketResponse(std::move(body), status_code);
+  }
+
+  std::future<StatusOr<HTTPResponse>> PostString(const std::string& body) {
+    auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(1);
+    auto future = std::async(std::launch::async, [this, body, deadline] {
+      auto post_future =
+          http_client->Post(HTTPRequest("http://www.test.com", body), deadline);
+      if (delete_after_post_) {
+        delete_after_post_ = false;
+        http_client.reset(nullptr);
+      }
+      post_sent_.Notify();
+      return post_future.get();
+    });
+    // Wait up to 10 second for std::async to run. This should happen almost
+    // immediately.
+    EXPECT_TRUE(post_sent_.Wait(std::chrono::seconds(10)));
+
+    return future;
+  }
+
+  template <class F>
+  StatusOr<F> RunUntilReady(std::future<StatusOr<F>>* future,
+                            zx::duration max_wait,
+                            zx::duration increment = zx::msec(100)) {
+    zx::duration elapsed;
+    while (elapsed < max_wait) {
+      elapsed += increment;
+      RunLoopFor(increment);
+      if (std::future_status::ready ==
+          future->wait_for(std::chrono::milliseconds(1))) {
+        return future->get();
+      }
+    }
+    return util::Status(util::StatusCode::CANCELLED, "Ran out of time");
+  }
+
+  void DeleteHttpClientAfterPost() { delete_after_post_ = true; }
+
+ private:
+  FakeNetworkWrapper network_wrapper_;
+  bool delete_after_post_;
+  CVBool post_sent_;
+
+ public:
+  std::unique_ptr<TestFuchsiaHTTPClient> http_client;
+};
+
+TEST_F(FuchsiaHTTPClientTest, MakePostAndGet) {
+  PrepareResponse("Response");
+  auto response_future = PostString("Request");
+  RunLoopUntilIdle();
+  EXPECT_TRUE(http_client->CheckResponseHandled());
+  auto response_or = response_future.get();
+  EXPECT_TRUE(response_or.ok());
+  auto response = response_or.ConsumeValueOrDie();
+  EXPECT_EQ(response.response, "Response");
+}
+
+TEST_F(FuchsiaHTTPClientTest, TestTimeout) {
+  auto response_future = PostString("Request");
+
+  RunLoopFor(zx::msec(100));
+  EXPECT_FALSE(http_client->CheckDeadlineTriggered());
+
+  RunLoopFor(zx::sec(1));
+  EXPECT_TRUE(http_client->CheckDeadlineTriggered());
+
+  auto response_or = response_future.get();
+  ASSERT_FALSE(response_or.ok());
+  EXPECT_EQ(response_or.status().error_code(),
+            util::StatusCode::DEADLINE_EXCEEDED);
+}
+
+TEST_F(FuchsiaHTTPClientTest, WaitAfterRelease) {
+  zx::socket socket_in, socket_out;
+  ASSERT_EQ(zx::socket::create(0u, &socket_in, &socket_out), ZX_OK);
+  PrepareResponse(std::move(socket_in));
+
+  DeleteHttpClientAfterPost();
+  auto response_future = PostString("Request");
+
+  const char message[] = "Response";
+  for (const char* it = message; *it; ++it) {
+    RunLoopFor(zx::sec(1));
+    size_t bytes_written;
+    socket_out.write(0u, it, 1, &bytes_written);
+    EXPECT_EQ(1u, bytes_written);
+    EXPECT_NE(std::future_status::ready,
+              response_future.wait_for(std::chrono::milliseconds(1)));
+  }
+  socket_out.reset();
+
+  auto response_or = RunUntilReady(&response_future, zx::sec(1));
+  EXPECT_EQ(response_or.status().error_code(), util::StatusCode::OK);
+  auto response = response_or.ConsumeValueOrDie();
+  EXPECT_EQ(response.response, "Response");
+}
+
+}  // namespace utils
+}  // namespace cobalt
diff --git a/bin/crashpad/crashpad_analyzer.cc b/bin/crashpad/crashpad_analyzer.cc
index 3789388..ccd48eb 100644
--- a/bin/crashpad/crashpad_analyzer.cc
+++ b/bin/crashpad/crashpad_analyzer.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <launchpad/launchpad.h>
 #include <lib/zx/handle.h>
 #include <lib/zx/log.h>
diff --git a/bin/debug_agent/launcher.cc b/bin/debug_agent/launcher.cc
index 40dde22..d7c5786 100644
--- a/bin/debug_agent/launcher.cc
+++ b/bin/debug_agent/launcher.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/bin/debug_agent/launcher.h"
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <launchpad/launchpad.h>
 
 namespace debug_agent {
diff --git a/bin/debug_agent/process_info.cc b/bin/debug_agent/process_info.cc
index 18e3cf0..37e8f4c 100644
--- a/bin/debug_agent/process_info.cc
+++ b/bin/debug_agent/process_info.cc
@@ -32,6 +32,13 @@
       {ZX_THREAD_STATE_DYING, debug_ipc::ThreadRecord::State::kDying},
       {ZX_THREAD_STATE_DEAD, debug_ipc::ThreadRecord::State::kDead}};
 
+// TODO(ZX-1843): This #ifdef is temporary to handle the transition.
+// It can be deleted once the new version of zircon rolls out that has
+// this macro.
+#ifdef ZX_THREAD_STATE_BASIC
+  state = ZX_THREAD_STATE_BASIC(state);
+#endif
+
   for (const Mapping& mapping : mappings) {
     if (mapping.int_state == state)
       return mapping.enum_state;
diff --git a/bin/debugserver/BUILD.gn b/bin/debugserver/BUILD.gn
index 7c6a794..3d908c0 100644
--- a/bin/debugserver/BUILD.gn
+++ b/bin/debugserver/BUILD.gn
@@ -35,6 +35,10 @@
     "//zircon/public/lib/zx",
   ]
 
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
+
   libs = [
     "zircon",
   ]
diff --git a/bin/debugserver/cmd_handler.cc b/bin/debugserver/cmd_handler.cc
index 9ad4f7a..8f29b91 100644
--- a/bin/debugserver/cmd_handler.cc
+++ b/bin/debugserver/cmd_handler.cc
@@ -60,7 +60,7 @@
 
 // This always returns true so that command handlers can simple call "return
 // ReplyOK()" rather than "ReplyOK(); return true;
-bool ReplyOK(const CommandHandler::ResponseCallback& callback) {
+bool ReplyOK(CommandHandler::ResponseCallback callback) {
   callback("OK");
   return true;
 }
@@ -68,7 +68,7 @@
 // This always returns true so that command handlers can simple call "return
 // ReplyWithError()" rather than "ReplyWithError(); return true;
 bool ReplyWithError(util::ErrorCode error_code,
-                    const CommandHandler::ResponseCallback& callback) {
+                    CommandHandler::ResponseCallback callback) {
   std::string error_rsp = util::BuildErrorPacket(error_code);
   callback(error_rsp);
   return true;
@@ -111,7 +111,7 @@
 }
 
 bool CommandHandler::HandleCommand(const fxl::StringView& packet,
-                                   const ResponseCallback& callback) {
+                                   ResponseCallback callback) {
   // GDB packets are prefixed with a letter that maps to a particular command
   // "family". We do the initial multiplexing here and let each individual
   // sub-handler deal with the rest.
@@ -125,25 +125,25 @@
     case '?':  // Indicate the reason the target halted
       if (packet.size() > 1)
         break;
-      return HandleQuestionMark(callback);
+      return HandleQuestionMark(std::move(callback));
     case 'c':  // Continue (at addr)
-      return Handle_c(packet.substr(1), callback);
+      return Handle_c(packet.substr(1), std::move(callback));
     case 'C':  // Continue with signal (optionally at addr)
-      return Handle_C(packet.substr(1), callback);
+      return Handle_C(packet.substr(1), std::move(callback));
     case 'D':  // Detach
-      return Handle_D(packet.substr(1), callback);
+      return Handle_D(packet.substr(1), std::move(callback));
     case 'g':  // Read general registers
       if (packet.size() > 1)
         break;
-      return Handle_g(callback);
+      return Handle_g(std::move(callback));
     case 'G':  // Write general registers
-      return Handle_G(packet.substr(1), callback);
+      return Handle_G(packet.substr(1), std::move(callback));
     case 'H':  // Set a thread for subsequent operations
-      return Handle_H(packet.substr(1), callback);
+      return Handle_H(packet.substr(1), std::move(callback));
     case 'm':  // Read memory
-      return Handle_m(packet.substr(1), callback);
+      return Handle_m(packet.substr(1), std::move(callback));
     case 'M':  // Write memory
-      return Handle_M(packet.substr(1), callback);
+      return Handle_M(packet.substr(1), std::move(callback));
     case 'q':  // General query packet
     case 'Q':  // General set packet
     {
@@ -154,16 +154,16 @@
                   << ", params: " << params;
 
       if (packet[0] == 'q')
-        return Handle_q(prefix, params, callback);
-      return Handle_Q(prefix, params, callback);
+        return Handle_q(prefix, params, std::move(callback));
+      return Handle_Q(prefix, params, std::move(callback));
     }
     case 'T':  // Is thread alive?
-      return Handle_T(packet.substr(1), callback);
+      return Handle_T(packet.substr(1), std::move(callback));
     case 'v':  // v-packets
-      return Handle_v(packet.substr(1), callback);
+      return Handle_v(packet.substr(1), std::move(callback));
     case 'z':  // Remove software breakpoint
     case 'Z':  // Insert software breakpoint
-      return Handle_zZ(packet[0] == 'Z', packet.substr(1), callback);
+      return Handle_zZ(packet[0] == 'Z', packet.substr(1), std::move(callback));
     default:
       break;
   }
@@ -171,7 +171,7 @@
   return false;
 }
 
-bool CommandHandler::HandleQuestionMark(const ResponseCallback& callback) {
+bool CommandHandler::HandleQuestionMark(ResponseCallback callback) {
   // TODO(armansito): Implement this once we actually listen to thread/process
   // exceptions. The logic for NonStop mode is fairly simple:
   //    1. Tell Server to drop any pending and/or queued Stop Reply
@@ -182,17 +182,17 @@
   //
   //    3. If there is no inferior or the current inferior is not started, then
   //    reply "OK".
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_c(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "c: No inferior";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   Thread* current_thread = server_->current_thread();
@@ -205,25 +205,25 @@
     if (!fxl::StringToNumberWithError<zx_vaddr_t>(packet, &addr,
                                                   fxl::Base::k16)) {
       FXL_LOG(ERROR) << "c: Malformed address given: " << packet;
-      return ReplyWithError(util::ErrorCode::INVAL, callback);
+      return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
     }
 
     // If there is no current thread, then report error. This is a special case
     // that means that the process hasn't started yet.
     if (!current_thread) {
       FXL_DCHECK(!current_process->IsLive());
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
 
     if (!current_thread->registers()->RefreshGeneralRegisters()) {
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
     if (!current_thread->registers()->SetRegister(arch::GetPCRegisterNumber(),
                                                   &addr, sizeof(addr))) {
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
     if (!current_thread->registers()->WriteGeneralRegisters()) {
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
 
     // TODO(armansito): Restore the PC register to its original state in case of
@@ -233,9 +233,9 @@
   // If there is a current thread, then tell it to continue.
   if (current_thread) {
     if (!current_thread->Resume())
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
 
-    return ReplyOK(callback);
+    return ReplyOK(std::move(callback));
   }
 
   // There is no current thread. This means that the process hasn't been started
@@ -246,7 +246,7 @@
   FXL_DCHECK(!current_process->IsLive());
   if (!current_process->Start()) {
     FXL_LOG(ERROR) << "c: Failed to start the current inferior";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // Try to set the current thread.
@@ -255,23 +255,23 @@
   if (current_thread)
     server_->SetCurrentThread(current_thread);
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_C(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "C: No inferior";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   Thread* current_thread = server_->current_thread();
   if (!current_thread) {
     FXL_LOG(ERROR) << "C: No current thread";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // Parse the parameters. The packet format is: sig[;addr]
@@ -283,21 +283,21 @@
   if (!fxl::StringToNumberWithError<int>(packet.substr(0, semicolon),
                                          &signo, fxl::Base::k16)) {
     FXL_LOG(ERROR) << "C: Malformed packet: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   arch::GdbSignal thread_signo = current_thread->GetGdbSignal();
   // TODO(dje): kNone may be a better value to use here.
   if (thread_signo == arch::GdbSignal::kUnsupported) {
     FXL_LOG(ERROR) << "C: Current thread has received no signal";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
   int int_thread_signo = static_cast<int>(thread_signo);
 
   if (int_thread_signo != signo) {
     FXL_LOG(ERROR) << "C: Signal numbers don't match - actual: "
                    << int_thread_signo << ", received: " << signo;
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   auto addr_param = packet.substr(semicolon);
@@ -312,18 +312,18 @@
     if (!fxl::StringToNumberWithError<zx_vaddr_t>(addr_param, &addr,
                                                   fxl::Base::k16)) {
       FXL_LOG(ERROR) << "C: Malformed address given: " << packet;
-      return ReplyWithError(util::ErrorCode::INVAL, callback);
+      return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
     }
 
     if (!current_thread->registers()->RefreshGeneralRegisters()) {
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
     if (!current_thread->registers()->SetRegister(arch::GetPCRegisterNumber(),
                                                   &addr, sizeof(addr))) {
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
     if (!current_thread->registers()->WriteGeneralRegisters()) {
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
 
     // TODO(armansito): Restore the PC register to its original state in case of
@@ -332,20 +332,20 @@
 
   if (!current_thread->Resume()) {
     FXL_LOG(ERROR) << "Failed to resume thread";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_D(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "D: No inferior";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // For now we only support detaching from the one process we have.
@@ -354,38 +354,38 @@
     if (!fxl::StringToNumberWithError<zx_koid_t>(packet.substr(1), &pid,
                                                  fxl::Base::k16)) {
       FXL_LOG(ERROR) << "D: bad pid: " << packet;
-      return ReplyWithError(util::ErrorCode::INVAL, callback);
+      return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
     }
     if (pid != current_process->id()) {
       FXL_LOG(ERROR) << "D: unknown pid: " << pid;
-      return ReplyWithError(util::ErrorCode::INVAL, callback);
+      return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
     }
   } else if (packet != "") {
     FXL_LOG(ERROR) << "D: Malformed packet: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   if (!current_process->IsAttached()) {
     FXL_LOG(ERROR) << "D: Not attached to process " << current_process->id();
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   if (!current_process->Detach()) {
     // At the moment this shouldn't happen, but we don't want to kill the
     // debug session because of it. The details of the failure are already
     // logged by Detach().
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
-bool CommandHandler::Handle_g(const ResponseCallback& callback) {
+bool CommandHandler::Handle_g(ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "g: No inferior";
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   // If there is no current thread, then we reply with "0"s for all registers.
@@ -404,7 +404,7 @@
 
   if (result.empty()) {
     FXL_LOG(ERROR) << "g: Failed to read register values";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   callback(result);
@@ -412,20 +412,20 @@
 }
 
 bool CommandHandler::Handle_G(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "G: No inferior";
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   // If there is no current thread report an error.
   Thread* current_thread = server_->current_thread();
   if (!current_thread) {
     FXL_LOG(ERROR) << "G: No current thread";
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   // We pass the packet here directly since arch::Registers handles the parsing.
@@ -435,17 +435,17 @@
   // registers.
   if (!current_thread->registers()->SetGeneralRegistersFromString(packet)) {
     FXL_LOG(ERROR) << "G: Failed to write to general registers";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
   if (!current_thread->registers()->WriteGeneralRegisters()) {
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_H(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // Here we set the "current thread" for subsequent operations
   // (‘m’, ‘M’, ‘g’, ‘G’, et.al.).
   // There are two types of an H packet. 'c' and 'g'. We claim to not support
@@ -454,7 +454,7 @@
   // Packet should at least contain 'c' or 'g' and some characters for the
   // thread id.
   if (packet.size() < 2)
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 
   switch (packet[0]) {
     case 'c':  // fall through
@@ -462,7 +462,7 @@
       int64_t pid, tid;
       bool has_pid;
       if (!util::ParseThreadId(packet.substr(1), &has_pid, &pid, &tid))
-        return ReplyWithError(util::ErrorCode::INVAL, callback);
+        return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 
       // We currently support debugging only one process.
       // TODO(armansito): What to do with a process ID? Replying with an empty
@@ -477,7 +477,7 @@
       // Setting the current thread to "all threads" doesn't make much sense.
       if (tid < 0) {
         FXL_LOG(ERROR) << "Cannot set the current thread to all threads";
-        return ReplyWithError(util::ErrorCode::INVAL, callback);
+        return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
       }
 
       Process* current_process = server_->current_process();
@@ -492,13 +492,13 @@
         // inferior, then report error?
         if (!tid) {
           FXL_LOG(ERROR) << "Cannot set a current thread with no inferior";
-          return ReplyWithError(util::ErrorCode::PERM, callback);
+          return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
         }
 
         FXL_LOG(WARNING) << "Setting current thread to NULL for tid=0";
 
         server_->SetCurrentThread(nullptr);
-        return ReplyOK(callback);
+        return ReplyOK(std::move(callback));
       }
 
       // If the process hasn't started yet it will have no threads. Since "Hg0"
@@ -509,7 +509,7 @@
         FXL_LOG(INFO) << "Current process has no threads yet but we pretend to "
                       << "set one";
         server_->SetCurrentThread(nullptr);
-        return ReplyOK(callback);
+        return ReplyOK(std::move(callback));
       }
 
       current_process->EnsureThreadMapFresh();
@@ -524,11 +524,11 @@
 
       if (!thread) {
         FXL_LOG(ERROR) << "Failed to set the current thread";
-        return ReplyWithError(util::ErrorCode::PERM, callback);
+        return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
       }
 
       server_->SetCurrentThread(thread);
-      return ReplyOK(callback);
+      return ReplyOK(std::move(callback));
     }
     default:
       break;
@@ -538,13 +538,13 @@
 }
 
 bool CommandHandler::Handle_m(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "m: No inferior";
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   // The "m" packet should have two arguments for addr and length, separated by
@@ -553,7 +553,7 @@
                                  fxl::kSplitWantNonEmpty);
   if (params.size() != 2) {
     FXL_LOG(ERROR) << "m: Malformed packet: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   uintptr_t addr;
@@ -563,13 +563,13 @@
       !fxl::StringToNumberWithError<size_t>(params[1], &length,
                                             fxl::Base::k16)) {
     FXL_LOG(ERROR) << "m: Malformed params: " << packet;
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   std::unique_ptr<uint8_t[]> buffer(new uint8_t[length]);
   if (!current_process->ReadMemory(addr, buffer.get(), length)) {
     FXL_LOG(ERROR) << "m: Failed to read memory";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   std::string result = util::EncodeByteArrayString(buffer.get(), length);
@@ -578,13 +578,13 @@
 }
 
 bool CommandHandler::Handle_M(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "M: No inferior";
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   // The "M" packet parameters look like this: "addr,length:XX...".
@@ -595,7 +595,7 @@
       fxl::SplitString(packet, ":", fxl::kKeepWhitespace, fxl::kSplitWantAll);
   if (params.size() != 2) {
     FXL_LOG(ERROR) << "M: Malformed packet: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   fxl::StringView data = params[1];
@@ -605,7 +605,7 @@
                             fxl::kSplitWantNonEmpty);
   if (params.size() != 2) {
     FXL_LOG(ERROR) << "M: Malformed packet: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   uintptr_t addr;
@@ -615,7 +615,7 @@
       !fxl::StringToNumberWithError<size_t>(params[1], &length,
                                             fxl::Base::k16)) {
     FXL_LOG(ERROR) << "M: Malformed params: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   FXL_VLOG(1) << fxl::StringPrintf("M: addr=0x%" PRIxPTR ", len=%lu", addr,
@@ -626,7 +626,7 @@
     FXL_LOG(ERROR) << "M: payload length doesn't match length argument - "
                    << "payload size: " << data_bytes.size()
                    << ", length requested: " << length;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   // Short-circuit if |length| is 0.
@@ -638,36 +638,36 @@
     // granular enough to aid debug various error conditions (e.g. we may want
     // to report why the memory write failed based on the zx_status_t returned
     // from Zircon). (See TODO in util.h).
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_q(const fxl::StringView& prefix,
                               const fxl::StringView& params,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   if (prefix == kAttached)
-    return HandleQueryAttached(params, callback);
+    return HandleQueryAttached(params, std::move(callback));
 
   if (prefix == kCurrentThreadId)
-    return HandleQueryCurrentThreadId(params, callback);
+    return HandleQueryCurrentThreadId(params, std::move(callback));
 
   if (prefix == kFirstThreadInfo)
-    return HandleQueryThreadInfo(true, callback);
+    return HandleQueryThreadInfo(true, std::move(callback));
 
   // The qRcmd packet is different than most. It uses , as a delimiter, not :.
   if (StartsWith(prefix, kRcmd))
-    return HandleQueryRcmd(prefix.substr(std::strlen(kRcmd)), callback);
+    return HandleQueryRcmd(prefix.substr(std::strlen(kRcmd)), std::move(callback));
 
   if (prefix == kSubsequentThreadInfo)
-    return HandleQueryThreadInfo(false, callback);
+    return HandleQueryThreadInfo(false, std::move(callback));
 
   if (prefix == kSupported)
-    return HandleQuerySupported(params, callback);
+    return HandleQuerySupported(params, std::move(callback));
 
   if (prefix == kXfer)
-    return HandleQueryXfer(params, callback);
+    return HandleQueryXfer(params, std::move(callback));
 
   // TODO(dje): TO-195
   // - QDisableRandomization:VALUE ?
@@ -679,60 +679,60 @@
 
 bool CommandHandler::Handle_Q(const fxl::StringView& prefix,
                               const fxl::StringView& params,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   if (prefix == kNonStop)
-    return HandleSetNonStop(params, callback);
+    return HandleSetNonStop(params, std::move(callback));
 
   return false;
 }
 
 bool CommandHandler::Handle_T(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   // If there is no current process or if the current process isn't attached,
   // then report an error.
   Process* current_process = server_->current_process();
   if (!current_process || !current_process->IsAttached()) {
     FXL_LOG(ERROR) << "T: No inferior";
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
   zx_koid_t tid;
   if (!fxl::StringToNumberWithError<zx_koid_t>(packet, &tid,
                                                fxl::Base::k16)) {
     FXL_LOG(ERROR) << "T: Malformed thread id given: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   Thread* thread = current_process->FindThreadById(tid);
   if (!thread) {
     FXL_LOG(ERROR) << "T: no such thread: " << packet;
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
   if (!thread->IsLive()) {
     FXL_LOG(ERROR) << "T: thread found, but not live: " << packet;
-    return ReplyWithError(util::ErrorCode::NOENT, callback);
+    return ReplyWithError(util::ErrorCode::NOENT, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_v(const fxl::StringView& packet,
-                              const ResponseCallback& callback) {
+                              ResponseCallback callback) {
   if (StartsWith(packet, kAttach))
-    return Handle_vAttach(packet.substr(std::strlen(kAttach)), callback);
+    return Handle_vAttach(packet.substr(std::strlen(kAttach)), std::move(callback));
   if (StartsWith(packet, kCont))
-    return Handle_vCont(packet.substr(std::strlen(kCont)), callback);
+    return Handle_vCont(packet.substr(std::strlen(kCont)), std::move(callback));
   if (StartsWith(packet, kKill))
-    return Handle_vKill(packet.substr(std::strlen(kKill)), callback);
+    return Handle_vKill(packet.substr(std::strlen(kKill)), std::move(callback));
   if (StartsWith(packet, kRun))
-    return Handle_vRun(packet.substr(std::strlen(kRun)), callback);
+    return Handle_vRun(packet.substr(std::strlen(kRun)), std::move(callback));
 
   return false;
 }
 
 bool CommandHandler::Handle_zZ(bool insert,
                                const fxl::StringView& packet,
-                               const ResponseCallback& callback) {
+                               ResponseCallback callback) {
 // Z0 needs more work. Disabled until ready.
 // One issue is we need to support the swbreak feature.
 #if 0
@@ -751,7 +751,7 @@
                                  fxl::kKeepWhitespace, fxl::kSplitWantNonEmpty);
   if (params.size() != 3) {
     FXL_LOG(ERROR) << "zZ: 3 required parameters missing";
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   size_t type;
@@ -763,7 +763,7 @@
                                                fxl::Base::k16) ||
       !fxl::StringToNumberWithError<size_t>(params[2], &kind, fxl::Base::k16)) {
     FXL_LOG(ERROR) << "zZ: Failed to parse |type|, |addr| and |kind|";
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   auto optional_params = packet.substr(semicolon);
@@ -771,14 +771,14 @@
   // "Remove breakpoint" packets don't contain any optional fields.
   if (!insert && !optional_params.empty()) {
     FXL_LOG(ERROR) << "zZ: Malformed packet";
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   switch (type) {
     case 0:
       if (insert)
-        return InsertSoftwareBreakpoint(addr, kind, optional_params, callback);
-      return RemoveSoftwareBreakpoint(addr, kind, callback);
+        return InsertSoftwareBreakpoint(addr, kind, optional_params, std::move(callback));
+      return RemoveSoftwareBreakpoint(addr, kind, std::move(callback));
     default:
       break;
   }
@@ -790,11 +790,11 @@
 }
 
 bool CommandHandler::HandleQueryAttached(const fxl::StringView& params,
-                                         const ResponseCallback& callback) {
+                                         ResponseCallback callback) {
   // We don't support multiprocessing yet, so make sure we received the version
   // of qAttached that doesn't have a "pid" parameter.
   if (!params.empty())
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 
   // The response is "1" if we attached to an existing process, or "0" if we
   // created a new one. We currently don't support the former, so always send
@@ -805,10 +805,10 @@
 
 bool CommandHandler::HandleQueryCurrentThreadId(
     const fxl::StringView& params,
-    const ResponseCallback& callback) {
+    ResponseCallback callback) {
   // The "qC" packet has no parameters.
   if (!params.empty())
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 
   Thread* current_thread = server_->current_thread();
   if (!current_thread) {
@@ -818,14 +818,14 @@
     Process* current_process = server_->current_process();
     if (!current_process || !current_process->IsLive()) {
       FXL_LOG(ERROR) << "qC: Current thread has not been set";
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
 
     FXL_VLOG(1) << "qC: Picking one arbitrary thread";
     current_thread = current_process->PickOneThread();
     if (!current_thread) {
       FXL_VLOG(1) << "qC: Failed to pick a thread";
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
   }
 
@@ -838,14 +838,14 @@
 }
 
 bool CommandHandler::HandleQueryRcmd(const fxl::StringView& command,
-                                     const ResponseCallback& callback) {
+                                     ResponseCallback callback) {
   auto cmd_string = util::DecodeString(command);
   std::vector<fxl::StringView> argv =
     fxl::SplitString(cmd_string, " ",
                      fxl::kTrimWhitespace, fxl::kSplitWantNonEmpty);
   if (argv.size() == 0) {
     // No command, just reply OK.
-    return ReplyOK(callback);
+    return ReplyOK(std::move(callback));
   }
   auto cmd = argv[0];
 
@@ -853,7 +853,7 @@
   if (cmd == kQuit || cmd == kExit) {
     if (argv.size() != 1)
       goto bad_command;
-    ReplyOK(callback);
+    ReplyOK(std::move(callback));
     server_->PostQuitMessageLoop(true);
   } else if (cmd == kHelp) {
     if (argv.size() != 1)
@@ -873,7 +873,7 @@
       goto bad_command;
     if (!server_->SetParameter(argv[1], argv[2]))
       goto bad_command;
-    ReplyOK(callback);
+    ReplyOK(std::move(callback));
   } else if (cmd == kShow) {
     if (argv.size() != 2)
       goto bad_command;
@@ -896,7 +896,7 @@
 }
 
 bool CommandHandler::HandleQuerySupported(const fxl::StringView& params,
-                                          const ResponseCallback& callback) {
+                                          ResponseCallback callback) {
   // We ignore the parameters for qSupported. Respond with the supported
   // features.
   callback(kSupportedFeatures);
@@ -904,31 +904,31 @@
 }
 
 bool CommandHandler::HandleSetNonStop(const fxl::StringView& params,
-                                      const ResponseCallback& callback) {
+                                      ResponseCallback callback) {
   // The only values we accept are "1" and "0".
   if (params.size() != 1)
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 
   // We currently only support non-stop mode.
   char value = params[0];
   if (value == '1')
-    return ReplyOK(callback);
+    return ReplyOK(std::move(callback));
 
   if (value == '0')
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
 
   FXL_LOG(ERROR) << "QNonStop received with invalid value: " << (unsigned)value;
-  return ReplyWithError(util::ErrorCode::INVAL, callback);
+  return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 }
 
 bool CommandHandler::HandleQueryThreadInfo(bool is_first,
-                                           const ResponseCallback& callback) {
+                                           ResponseCallback callback) {
   FXL_DCHECK(server_);
 
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "Current process is not set";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // For the "first" thread info query we reply with the complete list of
@@ -943,7 +943,7 @@
     if (!in_thread_info_sequence_) {
       FXL_LOG(ERROR) << "qsThreadInfo received without first receiving "
                      << "qfThreadInfo";
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     }
 
     in_thread_info_sequence_ = false;
@@ -955,7 +955,7 @@
   if (in_thread_info_sequence_) {
     FXL_LOG(ERROR) << "qfThreadInfo received while already in an active "
                    << "sequence";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   current_process->EnsureThreadMapFresh();
@@ -990,7 +990,7 @@
 }
 
 bool CommandHandler::HandleQueryXfer(const fxl::StringView& params,
-                                     const ResponseCallback& callback) {
+                                     ResponseCallback callback) {
   // We only support qXfer:auxv:read::
   // TODO(dje): TO-195
   // - qXfer::osdata::read::OFFSET,LENGTH
@@ -1006,20 +1006,20 @@
                                fxl::kKeepWhitespace, fxl::kSplitWantNonEmpty);
   if (args.size() != 2) {
     FXL_LOG(ERROR) << "qXfer:auxv:read:: Malformed params: " << params;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   size_t offset, length;
   if (!fxl::StringToNumberWithError<size_t>(args[0], &offset, fxl::Base::k16) ||
       !fxl::StringToNumberWithError<size_t>(args[1], &length, fxl::Base::k16)) {
     FXL_LOG(ERROR) << "qXfer:auxv:read:: Malformed params: " << params;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "qXfer:auxv:read: No current process is not set";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // Build the auxiliary vector. This definition is provided by the Linux manual
@@ -1065,7 +1065,7 @@
   // in reading 0 bytes.
   if (offset > sizeof(auxv)) {
     FXL_LOG(ERROR) << "qXfer:auxv:read: invalid offset";
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   size_t end = n * sizeof(auxv[0]);
@@ -1080,20 +1080,20 @@
 }
 
 bool CommandHandler::Handle_vAttach(const fxl::StringView& packet,
-                                    const ResponseCallback& callback) {
+                                    ResponseCallback callback) {
   // TODO(dje): The terminology we use makes this confusing.
   // Here when you see "process" think "inferior". An inferior must be created
   // first, and then we can attach the inferior to a process.
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "vAttach: no inferior selected";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   zx_koid_t pid;
   if (!fxl::StringToNumberWithError<zx_koid_t>(packet, &pid, fxl::Base::k16)) {
     FXL_LOG(ERROR) << "vAttach:: Malformed pid: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   switch (current_process->state()) {
@@ -1103,33 +1103,33 @@
     default:
       FXL_LOG(ERROR)
           << "vAttach: need to kill the currently running process first";
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   if (!current_process->Attach(pid)) {
     FXL_LOG(ERROR) << "vAttach: failed to attach to inferior " << pid;
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // It's Attach()'s job to mark the process as live, since it knows we just
   // attached to an already running program.
   FXL_DCHECK(current_process->IsLive());
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_vCont(const fxl::StringView& packet,
-                                  const ResponseCallback& callback) {
+                                  ResponseCallback callback) {
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "vCont: no current process to run!";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   ThreadActionList actions(packet, current_process->id());
   if (!actions.valid()) {
     FXL_LOG(ERROR) << "vCont: \"" << packet << "\": error / not supported.";
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   FXL_DCHECK(current_process->IsLive());
@@ -1174,7 +1174,7 @@
         }
       });
   if (!action_list_ok)
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
 
   current_process->ForEachLiveThread([&actions](Thread* thread) {
     zx_koid_t pid = thread->process()->id();
@@ -1208,59 +1208,59 @@
 
   // We defer sending a stop-reply packet. Server will send it out when threads
   // stop. At this point in time GDB is just expecting "OK".
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_vKill(const fxl::StringView& packet,
-                                  const ResponseCallback& callback) {
+                                  ResponseCallback callback) {
   FXL_VLOG(2) << "Handle_vKill: " << packet;
 
   Process* current_process = server_->current_process();
   if (!current_process) {
     // This can't happen today, but it might eventually.
     FXL_LOG(ERROR) << "vRun: no current process to kill!";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   zx_koid_t pid;
   if (!fxl::StringToNumberWithError<zx_koid_t>(packet, &pid, fxl::Base::k16)) {
     FXL_LOG(ERROR) << "vAttach:: Malformed pid: " << packet;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   // Since we only support one process at the moment, only allow killing
   // that one.
   if (pid != current_process->id()) {
     FXL_LOG(ERROR) << "vAttach:: not our pid: " << pid;
-    return ReplyWithError(util::ErrorCode::INVAL, callback);
+    return ReplyWithError(util::ErrorCode::INVAL, std::move(callback));
   }
 
   switch (current_process->state()) {
     case Process::State::kNew:
     case Process::State::kGone:
       FXL_LOG(ERROR) << "vKill: process not running";
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
     default:
       break;
   }
 
   if (!current_process->Kill()) {
     FXL_LOG(ERROR) << "Failed to kill inferior";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::Handle_vRun(const fxl::StringView& packet,
-                                 const ResponseCallback& callback) {
+                                 ResponseCallback callback) {
   FXL_VLOG(2) << "Handle_vRun: " << packet;
 
   Process* current_process = server_->current_process();
   if (!current_process) {
     // This can't happen today, but it might eventually.
     FXL_LOG(ERROR) << "vRun: no current process to run!";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   if (!packet.empty()) {
@@ -1275,12 +1275,12 @@
     default:
       FXL_LOG(ERROR)
           << "vRun: need to kill the currently running process first";
-      return ReplyWithError(util::ErrorCode::PERM, callback);
+      return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   if (!current_process->Initialize()) {
     FXL_LOG(ERROR) << "Failed to set up inferior";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // On Linux, the program is considered "live" after vRun, e.g. $pc is set. On
@@ -1290,7 +1290,7 @@
   // call to zx_task_resume (i.e. called by Thread::Resume() in gdbserver).
   if (!current_process->Start()) {
     FXL_LOG(ERROR) << "vRun: Failed to start process";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   FXL_DCHECK(current_process->IsLive());
@@ -1305,45 +1305,45 @@
     uintptr_t addr,
     size_t kind,
     const fxl::StringView& optional_params,
-    const ResponseCallback& callback) {
+    ResponseCallback callback) {
   FXL_VLOG(1) << fxl::StringPrintf(
       "Insert software breakpoint at %" PRIxPTR ", kind: %lu", addr, kind);
 
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "No current process exists";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   // TODO(armansito): Handle |optional_params|.
 
   if (!current_process->breakpoints()->InsertSoftwareBreakpoint(addr, kind)) {
     FXL_LOG(ERROR) << "Failed to insert software breakpoint";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 bool CommandHandler::RemoveSoftwareBreakpoint(
     uintptr_t addr,
     size_t kind,
-    const ResponseCallback& callback) {
+    ResponseCallback callback) {
   FXL_VLOG(1) << fxl::StringPrintf("Remove software breakpoint at %" PRIxPTR,
                                    addr);
 
   Process* current_process = server_->current_process();
   if (!current_process) {
     FXL_LOG(ERROR) << "No current process exists";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
   if (!current_process->breakpoints()->RemoveSoftwareBreakpoint(addr)) {
     FXL_LOG(ERROR) << "Failed to remove software breakpoint";
-    return ReplyWithError(util::ErrorCode::PERM, callback);
+    return ReplyWithError(util::ErrorCode::PERM, std::move(callback));
   }
 
-  return ReplyOK(callback);
+  return ReplyOK(std::move(callback));
 }
 
 }  // namespace debugserver
diff --git a/bin/debugserver/cmd_handler.h b/bin/debugserver/cmd_handler.h
index 9ae0740..0db9bdf 100644
--- a/bin/debugserver/cmd_handler.h
+++ b/bin/debugserver/cmd_handler.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <functional>
+#include <lib/fit/function.h>
 
 #include "lib/fxl/macros.h"
 #include "lib/fxl/strings/string_view.h"
@@ -28,83 +28,83 @@
   // If this method returns false, then |callback| will never be called. If this
   // returns true, |callback| is guaranteed to be called exactly once.
   // |callback| can be called before HandleCommand returns.
-  using ResponseCallback = std::function<void(const fxl::StringView& rsp)>;
+  using ResponseCallback = fit::function<void(const fxl::StringView& rsp)>;
   bool HandleCommand(const fxl::StringView& packet,
-                     const ResponseCallback& callback);
+                     ResponseCallback callback);
 
  private:
   // Command handlers for each "letter" packet. We use underscores in the method
   // names to clearly delineate lowercase letters.
-  bool HandleQuestionMark(const ResponseCallback& callback);
+  bool HandleQuestionMark(ResponseCallback callback);
   bool Handle_c(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_C(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_D(const fxl::StringView& packet,
-                const ResponseCallback& callback);
-  bool Handle_g(const ResponseCallback& callback);
+                ResponseCallback callback);
+  bool Handle_g(ResponseCallback callback);
   bool Handle_G(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_H(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_m(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_M(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_q(const fxl::StringView& prefix,
                 const fxl::StringView& params,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_Q(const fxl::StringView& prefix,
                 const fxl::StringView& params,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_T(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_v(const fxl::StringView& packet,
-                const ResponseCallback& callback);
+                ResponseCallback callback);
   bool Handle_zZ(bool insert,
                  const fxl::StringView& packet,
-                 const ResponseCallback& callback);
+                 ResponseCallback callback);
 
   // q/Q packets:
   // qAttached
   bool HandleQueryAttached(const fxl::StringView& params,
-                           const ResponseCallback& callback);
+                           ResponseCallback callback);
   // qC
   bool HandleQueryCurrentThreadId(const fxl::StringView& params,
-                                  const ResponseCallback& callback);
+                                  ResponseCallback callback);
   // qRcmd
   bool HandleQueryRcmd(const fxl::StringView& command,
-                       const ResponseCallback& callback);
+                       ResponseCallback callback);
   // qSupported
   bool HandleQuerySupported(const fxl::StringView& params,
-                            const ResponseCallback& callback);
+                            ResponseCallback callback);
   // qfThreadInfo and qsThreadInfo
-  bool HandleQueryThreadInfo(bool is_first, const ResponseCallback& callback);
+  bool HandleQueryThreadInfo(bool is_first, ResponseCallback callback);
   // qXfer
   bool HandleQueryXfer(const fxl::StringView& params,
-                       const ResponseCallback& callback);
+                       ResponseCallback callback);
   // QNonStop
   bool HandleSetNonStop(const fxl::StringView& params,
-                        const ResponseCallback& callback);
+                        ResponseCallback callback);
 
   // v packets:
   bool Handle_vAttach(const fxl::StringView& packet,
-                      const ResponseCallback& callback);
+                      ResponseCallback callback);
   bool Handle_vCont(const fxl::StringView& packet,
-                    const ResponseCallback& callback);
+                    ResponseCallback callback);
   bool Handle_vKill(const fxl::StringView& packet,
-                    const ResponseCallback& callback);
+                    ResponseCallback callback);
   bool Handle_vRun(const fxl::StringView& packet,
-                   const ResponseCallback& callback);
+                   ResponseCallback callback);
 
   // Breakpoints
   bool InsertSoftwareBreakpoint(uintptr_t addr,
                                 size_t kind,
                                 const fxl::StringView& optional_params,
-                                const ResponseCallback& callback);
+                                ResponseCallback callback);
   bool RemoveSoftwareBreakpoint(uintptr_t addr,
                                 size_t kind,
-                                const ResponseCallback& callback);
+                                ResponseCallback callback);
 
   // The root Server instance that owns us.
   RspServer* server_;  // weak
diff --git a/bin/device_settings/src/main.rs b/bin/device_settings/src/main.rs
index 9c261a6..0583e48 100644
--- a/bin/device_settings/src/main.rs
+++ b/bin/device_settings/src/main.rs
@@ -7,7 +7,7 @@
 extern crate failure;
 extern crate fdio;
 extern crate fidl;
-extern crate fidl_device_settings;
+extern crate fidl_fuchsia_devicesettings;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 #[macro_use]
@@ -32,7 +32,7 @@
 use std::sync::Arc;
 
 // Include the generated FIDL bindings for the `DeviceSetting` service.
-use fidl_device_settings::{
+use fidl_fuchsia_devicesettings::{
     DeviceSettingsManager,
     DeviceSettingsManagerImpl,
     DeviceSettingsManagerMarker,
@@ -238,7 +238,7 @@
     use futures::prelude::*;
     use super::*;
 
-    use fidl_device_settings::DeviceSettingsManagerProxy;
+    use fidl_fuchsia_devicesettings::DeviceSettingsManagerProxy;
 
     fn async_test<F, Fut>(keys: &[&str], f: F)
     where
diff --git a/bin/dhcpd/src/protocol.rs b/bin/dhcpd/src/protocol.rs
index df1f395..b763290 100644
--- a/bin/dhcpd/src/protocol.rs
+++ b/bin/dhcpd/src/protocol.rs
@@ -160,7 +160,7 @@
 
     /// Returns a reference to the `Message`'s `ConfigOption` with `code`, or `None`
     /// if `Message` does not have the specified `ConfigOption`.
-    pub fn get_config_option_with(&self, code: OptionCode) -> Option<&ConfigOption> {
+    pub fn get_config_option(&self, code: OptionCode) -> Option<&ConfigOption> {
         // There should generally be few (~0 - 10) options attached to a message
         // so the linear search should not be unreasonably costly.
         for opt in &self.options {
diff --git a/bin/dhcpd/src/server.rs b/bin/dhcpd/src/server.rs
index 0071cda..67dbab8 100644
--- a/bin/dhcpd/src/server.rs
+++ b/bin/dhcpd/src/server.rs
@@ -15,80 +15,50 @@
 /// This comment will be expanded upon in future CLs as the server design
 /// is iterated upon.
 pub struct Server {
-    client_configs_cache: HashMap<MacAddr, CachedConfig>,
-    addr_pool: AddressPool,
-    server_config: ServerConfig,
+    cache: CachedClients,
+    pool: AddressPool,
+    config: ServerConfig,
 }
 
 impl Server {
     /// Returns an initialized `Server` value.
     pub fn new() -> Self {
         Server {
-            client_configs_cache: HashMap::new(),
-            addr_pool: AddressPool::new(),
-            server_config: ServerConfig::new(),
+            cache: HashMap::new(),
+            pool: AddressPool::new(),
+            config: ServerConfig::new(),
         }
     }
 
-    fn handle_discover_message(&mut self, disc_msg: Message) -> Option<Message> {
-        let offer_msg = self.generate_offer_message(disc_msg)?;
-        self.update_server_cache(Ipv4Addr::from(offer_msg.yiaddr), offer_msg.chaddr, vec![]);
+    fn handle_discover(&mut self, disc: Message) -> Option<Message> {
+        let offered_ip = self.get_addr(&disc)?;
+        let mut offer = build_offer(disc, &self.config);
+        offer.yiaddr = offered_ip;
+        self.update_server_cache(Ipv4Addr::from(offer.yiaddr), offer.chaddr, vec![]);
 
-        Some(offer_msg)
+        Some(offer)
     }
 
-    fn generate_offer_message(&mut self, client_msg: Message) -> Option<Message> {
-        let mut offer_msg = client_msg.clone();
-        offer_msg.op = OpCode::BOOTREPLY;
-        offer_msg.secs = 0;
-        offer_msg.ciaddr = Ipv4Addr::new(0, 0, 0, 0);
-        offer_msg.siaddr = Ipv4Addr::new(0, 0, 0, 0);
-        offer_msg.sname = String::new();
-        offer_msg.file = String::new();
-        self.add_required_options_to(&mut offer_msg);
-        offer_msg.yiaddr = self.get_addr_for_msg(client_msg)?;
-
-        Some(offer_msg)
-    }
-
-    fn add_required_options_to(&self, offer_msg: &mut Message) {
-        offer_msg.options.clear();
-        let mut lease = vec![0; 4];
-        BigEndian::write_u32(&mut lease, self.server_config.default_lease_time);
-        offer_msg.options.push(ConfigOption {
-            code: OptionCode::IpAddrLeaseTime,
-            value: lease,
-        });
-        offer_msg.options.push(ConfigOption {
-            code: OptionCode::DhcpMessageType,
-            value: vec![MessageType::DHCPOFFER as u8],
-        });
-        offer_msg.options.push(ConfigOption {
-            code: OptionCode::ServerId,
-            value: self.server_config.server_ip.octets().to_vec(),
-        });
-    }
-
-    fn get_addr_for_msg(&mut self, client_msg: Message) -> Option<Ipv4Addr> {
-        if let Some(config) = self.client_configs_cache.get(&client_msg.chaddr) {
+    fn get_addr(&mut self, client: &Message) -> Option<Ipv4Addr> {
+        if let Some(config) = self.cache.get(&client.chaddr) {
             if !config.expired {
                 return Some(config.client_addr);
-            } else if self.addr_pool.addr_is_available(config.client_addr) {
-                self.addr_pool.allocate_addr(config.client_addr);
+            } else if self.pool.addr_is_available(config.client_addr) {
+                self.pool.allocate_addr(config.client_addr);
                 return Some(config.client_addr);
             }
         }
-        if let Some(opt) = client_msg.get_config_option_with(OptionCode::RequestedIpAddr) {
+        if let Some(opt) = client.get_config_option(OptionCode::RequestedIpAddr) {
             if opt.value.len() >= 4 {
                 let requested_addr = protocol::ip_addr_from_buf_at(&opt.value, 0)
                     .expect("out of range indexing on opt.value");
-                if self.addr_pool.addr_is_available(requested_addr) {
-                    self.addr_pool.allocate_addr(requested_addr);
+                if self.pool.addr_is_available(requested_addr) {
+                    self.pool.allocate_addr(requested_addr);
                     return Some(requested_addr);
                 }
             }
         }
-        self.addr_pool.get_next_available_addr()
+        self.pool.get_next_available_addr()
     }
 
     fn update_server_cache(
@@ -99,11 +69,60 @@
             options: client_opts,
             expired: false,
         };
-        self.client_configs_cache.insert(client_mac, config);
-        self.addr_pool.allocate_addr(client_addr);
+        self.cache.insert(client_mac, config);
+        self.pool.allocate_addr(client_addr);
+    }
+
+    fn handle_request(&mut self, req: Message) -> Option<Message> {
+        match get_client_state(&req) {
+            ClientState::Selecting => self.handle_request_selecting(req),
+            ClientState::InitReboot => self.handle_request_init_reboot(req),
+            ClientState::Renewing => self.handle_request_renewing(req),
+            ClientState::Unknown => None,
+        }
+    }
+
+    fn handle_request_selecting(&mut self, req: Message) -> Option<Message> {
+        let requested_ip = get_requested_ip_addr(&req)?;
+        if !is_recipient(self.config.server_ip, &req)
+            || !is_assigned(&req, requested_ip, &self.cache, &self.pool)
+        {
+            return None;
+        }
+        Some(build_ack(req, requested_ip, &self.config))
+    }
+
+    fn handle_request_init_reboot(&mut self, req: Message) -> Option<Message> {
+        let requested_ip = get_requested_ip_addr(&req)?;
+        if !is_in_subnet(requested_ip, &self.config) {
+            return Some(build_nak(req, &self.config));
+        }
+        if !is_client_mac_known(req.chaddr, &self.cache) {
+            return None;
+        }
+        if !is_assigned(&req, requested_ip, &self.cache, &self.pool) {
+            return Some(build_nak(req, &self.config));
+        }
+        Some(build_ack(req, requested_ip, &self.config))
+    }
+
+    fn handle_request_renewing(&mut self, req: Message) -> Option<Message> {
+        let client_ip = req.ciaddr;
+        if !is_assigned(&req, client_ip, &self.cache, &self.pool) {
+            return None;
+        }
+        Some(build_ack(req, client_ip, &self.config))
     }
 }
 
+/// A cache mapping clients to their configuration data.
+///
+/// The server should store configuration data for all clients
+/// to which it has sent a DHCPOFFER message. Entries in the cache
+/// will eventually timeout, although such functionality is currently
+/// unimplemented.
+type CachedClients = HashMap<MacAddr, CachedConfig>;
+
 type MacAddr = [u8; 6];
 
 #[derive(Debug)]
@@ -123,6 +142,12 @@
     }
 }
 
+/// The pool of addresses managed by the server.
+///
+/// Any address managed by the server should be stored in only one
+/// of the available/allocated sets at a time. In other words, an
+/// address in `available_addrs` must not be in `allocated_addrs` and
+/// vice-versa.
 #[derive(Debug)]
 struct AddressPool {
     // available_addrs uses a BTreeSet so that addresses are allocated
@@ -155,12 +180,17 @@
     fn addr_is_available(&self, addr: Ipv4Addr) -> bool {
         self.available_addrs.contains(&addr) && !self.allocated_addrs.contains(&addr)
     }
+
+    fn addr_is_allocated(&self, addr: Ipv4Addr) -> bool {
+        !self.available_addrs.contains(&addr) && self.allocated_addrs.contains(&addr)
+    }
 }
 
 #[derive(Debug)]
 struct ServerConfig {
     server_ip: Ipv4Addr,
     default_lease_time: u32,
+    subnet_mask: u8,
 }
 
 impl ServerConfig {
@@ -168,95 +198,300 @@
         ServerConfig {
             server_ip: Ipv4Addr::new(0, 0, 0, 0),
             default_lease_time: 0,
+            subnet_mask: 24,
         }
     }
 }
 
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+enum ClientState {
+    Unknown,
+    Selecting,
+    InitReboot,
+    Renewing,
+}
+
+fn build_offer(client: Message, config: &ServerConfig) -> Message {
+    let mut offer = client;
+    offer.op = OpCode::BOOTREPLY;
+    offer.secs = 0;
+    offer.ciaddr = Ipv4Addr::new(0, 0, 0, 0);
+    offer.siaddr = Ipv4Addr::new(0, 0, 0, 0);
+    offer.sname = String::new();
+    offer.file = String::new();
+    add_required_options(&mut offer, &config);
+
+    offer
+}
+
+fn add_required_options(offer: &mut Message, config: &ServerConfig) {
+    offer.options.clear();
+    let mut lease = vec![0; 4];
+    BigEndian::write_u32(&mut lease, config.default_lease_time);
+    offer.options.push(ConfigOption {
+        code: OptionCode::IpAddrLeaseTime,
+        value: lease,
+    });
+    offer.options.push(ConfigOption {
+        code: OptionCode::DhcpMessageType,
+        value: vec![MessageType::DHCPOFFER as u8],
+    });
+    offer.options.push(ConfigOption {
+        code: OptionCode::ServerId,
+        value: config.server_ip.octets().to_vec(),
+    });
+}
+
+fn is_recipient(server_ip: Ipv4Addr, req: &Message) -> bool {
+    if let Some(server_id) = get_server_id_from(&req) {
+        return server_id == server_ip;
+    }
+    false
+}
+
+fn is_assigned(
+    req: &Message, requested_ip: Ipv4Addr, cache: &CachedClients, pool: &AddressPool,
+) -> bool {
+    if let Some(client_config) = cache.get(&req.chaddr) {
+        return client_config.client_addr == requested_ip && !client_config.expired
+            && pool.addr_is_allocated(requested_ip);
+    }
+    false
+}
+
+fn build_ack(req: Message, requested_ip: Ipv4Addr, config: &ServerConfig) -> Message {
+    let mut ack = req;
+    ack.op = OpCode::BOOTREPLY;
+    ack.secs = 0;
+    ack.yiaddr = requested_ip;
+    ack.options.clear();
+    let mut lease = vec![0; 4];
+    BigEndian::write_u32(&mut lease, config.default_lease_time);
+    ack.options.push(ConfigOption {
+        code: OptionCode::IpAddrLeaseTime,
+        value: lease,
+    });
+    ack.options.push(ConfigOption {
+        code: OptionCode::DhcpMessageType,
+        value: vec![MessageType::DHCPACK as u8],
+    });
+    ack.options.push(ConfigOption {
+        code: OptionCode::ServerId,
+        value: config.server_ip.octets().to_vec(),
+    });
+
+    ack
+}
+
+fn is_in_subnet(ip: Ipv4Addr, config: &ServerConfig) -> bool {
+    apply_subnet_mask_to(config.subnet_mask, ip)
+        == apply_subnet_mask_to(config.subnet_mask, config.server_ip)
+}
+
+fn is_client_mac_known(mac: MacAddr, cache: &CachedClients) -> bool {
+    cache.get(&mac).is_some()
+}
+
+fn build_nak(req: Message, config: &ServerConfig) -> Message {
+    let mut nak = req;
+    nak.op = OpCode::BOOTREPLY;
+    nak.secs = 0;
+    nak.ciaddr = Ipv4Addr::new(0, 0, 0, 0);
+    nak.yiaddr = Ipv4Addr::new(0, 0, 0, 0);
+    nak.siaddr = Ipv4Addr::new(0, 0, 0, 0);
+    nak.options.clear();
+    let mut lease = vec![0; 4];
+    BigEndian::write_u32(&mut lease, config.default_lease_time);
+    nak.options.push(ConfigOption {
+        code: OptionCode::DhcpMessageType,
+        value: vec![MessageType::DHCPNAK as u8],
+    });
+    nak.options.push(ConfigOption {
+        code: OptionCode::ServerId,
+        value: config.server_ip.octets().to_vec(),
+    });
+
+    nak
+}
+
+fn get_client_state(msg: &Message) -> ClientState {
+    let maybe_server_id = get_server_id_from(&msg);
+    let maybe_requested_ip = get_requested_ip_addr(&msg);
+    let zero_ciaddr = Ipv4Addr::new(0, 0, 0, 0);
+
+    if maybe_server_id.is_some() && maybe_requested_ip.is_some() && msg.ciaddr == zero_ciaddr {
+        return ClientState::Selecting;
+    } else if maybe_requested_ip.is_some() && msg.ciaddr == zero_ciaddr {
+        return ClientState::InitReboot;
+    } else if msg.ciaddr != zero_ciaddr {
+        return ClientState::Renewing;
+    } else {
+        return ClientState::Unknown;
+    }
+}
+
+fn get_requested_ip_addr(req: &Message) -> Option<Ipv4Addr> {
+    let req_ip_opt = req.options
+        .iter()
+        .find(|opt| opt.code == OptionCode::RequestedIpAddr)?;
+    let raw_ip = BigEndian::read_u32(&req_ip_opt.value);
+    Some(Ipv4Addr::from(raw_ip))
+}
+
+fn get_server_id_from(req: &Message) -> Option<Ipv4Addr> {
+    let server_id_opt = req.options
+        .iter()
+        .find(|opt| opt.code == OptionCode::ServerId)?;
+    let raw_server_id = BigEndian::read_u32(&server_id_opt.value);
+    Some(Ipv4Addr::from(raw_server_id))
+}
+
+fn apply_subnet_mask_to(prefix_len: u8, ip_addr: Ipv4Addr) -> Ipv4Addr {
+    assert!(prefix_len < 32);
+    let subnet_mask_bits = ::std::u32::MAX << (32 - prefix_len);
+    let ip_addr_bits = BigEndian::read_u32(&ip_addr.octets());
+    Ipv4Addr::from(ip_addr_bits & subnet_mask_bits)
+}
+
 #[cfg(test)]
 mod tests {
 
-    use super::{CachedConfig, Server};
+    use super::*;
     use protocol::{ConfigOption, Message, MessageType, OpCode, OptionCode};
     use std::net::Ipv4Addr;
 
-    fn new_test_client_msg() -> Message {
-        let mut client_msg = Message::new();
-        client_msg.xid = 42;
-        client_msg.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
-        client_msg
-    }
-
     fn new_test_server() -> Server {
         let mut server = Server::new();
-        server.server_config.server_ip = Ipv4Addr::new(192, 168, 1, 1);
-        server.server_config.default_lease_time = 42;
+        server.config.server_ip = Ipv4Addr::new(192, 168, 1, 1);
+        server.config.default_lease_time = 42;
         server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::from([192, 168, 1, 2]));
         server
     }
 
-    fn new_test_server_msg() -> Message {
-        let mut server_msg = Message::new();
-        server_msg.op = OpCode::BOOTREPLY;
-        server_msg.xid = 42;
-        server_msg.yiaddr = Ipv4Addr::new(192, 168, 1, 2);
-        server_msg.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
-        server_msg.options.push(ConfigOption {
+    fn new_test_discover() -> Message {
+        let mut disc = Message::new();
+        disc.xid = 42;
+        disc.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
+        disc
+    }
+
+    fn new_test_offer() -> Message {
+        let mut offer = Message::new();
+        offer.op = OpCode::BOOTREPLY;
+        offer.xid = 42;
+        offer.yiaddr = Ipv4Addr::new(192, 168, 1, 2);
+        offer.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
+        offer.options.push(ConfigOption {
             code: OptionCode::IpAddrLeaseTime,
             value: vec![0, 0, 0, 42],
         });
-        server_msg.options.push(ConfigOption {
+        offer.options.push(ConfigOption {
             code: OptionCode::DhcpMessageType,
             value: vec![MessageType::DHCPOFFER as u8],
         });
-        server_msg.options.push(ConfigOption {
+        offer.options.push(ConfigOption {
             code: OptionCode::ServerId,
             value: vec![192, 168, 1, 1],
         });
-        server_msg
+        offer
+    }
+
+    fn new_test_request() -> Message {
+        let mut req = Message::new();
+        req.xid = 42;
+        req.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
+        req.options.push(ConfigOption {
+            code: OptionCode::RequestedIpAddr,
+            value: vec![192, 168, 1, 2],
+        });
+        req.options.push(ConfigOption {
+            code: OptionCode::DhcpMessageType,
+            value: vec![MessageType::DHCPREQUEST as u8],
+        });
+        req.options.push(ConfigOption {
+            code: OptionCode::ServerId,
+            value: vec![192, 168, 1, 1],
+        });
+        req
+    }
+
+    fn new_test_ack() -> Message {
+        let mut ack = Message::new();
+        ack.op = OpCode::BOOTREPLY;
+        ack.xid = 42;
+        ack.yiaddr = Ipv4Addr::new(192, 168, 1, 2);
+        ack.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
+        ack.options.push(ConfigOption {
+            code: OptionCode::IpAddrLeaseTime,
+            value: vec![0, 0, 0, 42],
+        });
+        ack.options.push(ConfigOption {
+            code: OptionCode::DhcpMessageType,
+            value: vec![MessageType::DHCPACK as u8],
+        });
+        ack.options.push(ConfigOption {
+            code: OptionCode::ServerId,
+            value: vec![192, 168, 1, 1],
+        });
+        ack
+    }
+
+    fn new_test_nak() -> Message {
+        let mut nak = Message::new();
+        nak.op = OpCode::BOOTREPLY;
+        nak.xid = 42;
+        nak.chaddr = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF];
+        nak.options.push(ConfigOption {
+            code: OptionCode::DhcpMessageType,
+            value: vec![MessageType::DHCPNAK as u8],
+        });
+        nak.options.push(ConfigOption {
+            code: OptionCode::ServerId,
+            value: vec![192, 168, 1, 1],
+        });
+        nak
     }
 
     #[test]
     fn test_handle_discover_returns_correct_response() {
-        let disc_msg = new_test_client_msg();
+        let disc = new_test_discover();
 
         let mut server = new_test_server();
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        let want = new_test_server_msg();
+        let want = new_test_offer();
 
         assert_eq!(got, want);
     }
 
     #[test]
     fn test_handle_discover_updates_server_state() {
-        let disc_msg = new_test_client_msg();
-        let mac_addr = disc_msg.chaddr;
+        let disc = new_test_discover();
+        let mac_addr = disc.chaddr;
         let mut server = new_test_server();
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        assert_eq!(server.addr_pool.available_addrs.len(), 0);
-        assert_eq!(server.addr_pool.allocated_addrs.len(), 1);
-        assert_eq!(server.client_configs_cache.len(), 1);
-        let want_config = server.client_configs_cache.get(&mac_addr).unwrap();
+        assert_eq!(server.pool.available_addrs.len(), 0);
+        assert_eq!(server.pool.allocated_addrs.len(), 1);
+        assert_eq!(server.cache.len(), 1);
+        let want_config = server.cache.get(&mac_addr).unwrap();
         assert_eq!(want_config.client_addr, Ipv4Addr::new(192, 168, 1, 2));
     }
 
     #[test]
     fn test_handle_discover_with_client_binding_returns_bound_addr() {
-        let disc_msg = new_test_client_msg();
+        let disc = new_test_discover();
         let mut server = new_test_server();
         let mut client_config = CachedConfig::new();
         client_config.client_addr = Ipv4Addr::new(192, 168, 1, 42);
-        server
-            .client_configs_cache
-            .insert(disc_msg.chaddr, client_config);
+        server.cache.insert(disc.chaddr, client_config);
 
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        let mut want = new_test_server_msg();
+        let mut want = new_test_offer();
         want.yiaddr = Ipv4Addr::new(192, 168, 1, 42);
 
         assert_eq!(got, want);
@@ -264,22 +499,20 @@
 
     #[test]
     fn test_handle_discover_with_expired_client_binding_returns_available_old_addr() {
-        let disc_msg = new_test_client_msg();
+        let disc = new_test_discover();
         let mut server = new_test_server();
         let mut client_config = CachedConfig::new();
         client_config.client_addr = Ipv4Addr::new(192, 168, 1, 42);
         client_config.expired = true;
+        server.cache.insert(disc.chaddr, client_config);
         server
-            .client_configs_cache
-            .insert(disc_msg.chaddr, client_config);
-        server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 42));
 
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        let mut want = new_test_server_msg();
+        let mut want = new_test_offer();
         want.yiaddr = Ipv4Addr::new(192, 168, 1, 42);
 
         assert_eq!(got, want);
@@ -287,26 +520,24 @@
 
     #[test]
     fn test_handle_discover_with_unavailable_expired_client_binding_returns_new_addr() {
-        let disc_msg = new_test_client_msg();
+        let disc = new_test_discover();
         let mut server = new_test_server();
         let mut client_config = CachedConfig::new();
         client_config.client_addr = Ipv4Addr::new(192, 168, 1, 42);
         client_config.expired = true;
+        server.cache.insert(disc.chaddr, client_config);
         server
-            .client_configs_cache
-            .insert(disc_msg.chaddr, client_config);
-        server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 2));
         server
-            .addr_pool
+            .pool
             .allocated_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 42));
 
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        let mut want = new_test_server_msg();
+        let mut want = new_test_offer();
         want.yiaddr = Ipv4Addr::new(192, 168, 1, 2);
 
         assert_eq!(got, want);
@@ -314,53 +545,294 @@
 
     #[test]
     fn test_handle_discover_with_available_requested_addr_returns_requested_addr() {
-        let mut disc_msg = new_test_client_msg();
-        disc_msg.options.push(ConfigOption {
+        let mut disc = new_test_discover();
+        disc.options.push(ConfigOption {
             code: OptionCode::RequestedIpAddr,
             value: vec![192, 168, 1, 3],
         });
 
         let mut server = new_test_server();
         server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 2));
         server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 3));
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        let mut want = new_test_server_msg();
+        let mut want = new_test_offer();
         want.yiaddr = Ipv4Addr::new(192, 168, 1, 3);
         assert_eq!(got, want);
     }
 
     #[test]
     fn test_handle_discover_with_unavailable_requested_addr_returns_next_addr() {
-        let mut disc_msg = new_test_client_msg();
-        disc_msg.options.push(ConfigOption {
+        let mut disc = new_test_discover();
+        disc.options.push(ConfigOption {
             code: OptionCode::RequestedIpAddr,
             value: vec![192, 168, 1, 42],
         });
 
         let mut server = new_test_server();
         server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 2));
         server
-            .addr_pool
+            .pool
             .available_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 3));
         server
-            .addr_pool
+            .pool
             .allocated_addrs
             .insert(Ipv4Addr::new(192, 168, 1, 42));
-        let got = server.handle_discover_message(disc_msg).unwrap();
+        let got = server.handle_discover(disc).unwrap();
 
-        let mut want = new_test_server_msg();
+        let mut want = new_test_offer();
         want.yiaddr = Ipv4Addr::new(192, 168, 1, 2);
         assert_eq!(got, want);
     }
+
+    #[test]
+    fn test_handle_selecting_request_with_valid_selecting_request_returns_ack() {
+        let req = new_test_request();
+
+        let mut server = new_test_server();
+        let requested_ip_addr = Ipv4Addr::new(192, 168, 1, 2);
+        server.cache.insert(
+            req.chaddr,
+            CachedConfig {
+                client_addr: requested_ip_addr,
+                options: vec![],
+                expired: false,
+            },
+        );
+        server.pool.allocate_addr(requested_ip_addr);
+        let got = server.handle_request(req).unwrap();
+
+        let mut want = new_test_ack();
+        assert_eq!(got, want);
+    }
+
+    #[test]
+    fn test_handle_selecting_request_with_no_address_allocation_to_client_returns_none() {
+        let req = new_test_request();
+
+        let mut server = new_test_server();
+        let got = server.handle_request(req);
+
+        assert!(got.is_none());
+    }
+
+    #[test]
+    fn test_handle_selecting_request_with_wrong_server_id_returns_none() {
+        let req = new_test_request();
+
+        let mut server = new_test_server();
+        let requested_ip_addr = Ipv4Addr::new(192, 168, 1, 2);
+        server.cache.insert(
+            req.chaddr,
+            CachedConfig {
+                client_addr: requested_ip_addr,
+                options: vec![],
+                expired: false,
+            },
+        );
+        server.pool.allocate_addr(requested_ip_addr);
+        server.config.server_ip = Ipv4Addr::new(1, 2, 3, 4);
+        let got = server.handle_request(req);
+
+        assert!(got.is_none());
+    }
+
+    #[test]
+    fn test_handle_selecting_request_with_valid_selecting_request_maintains_server_invariants() {
+        let req = new_test_request();
+
+        let mut server = new_test_server();
+        let requested_ip_addr = Ipv4Addr::new(192, 168, 1, 2);
+        server.cache.insert(
+            req.chaddr,
+            CachedConfig {
+                client_addr: requested_ip_addr,
+                options: vec![],
+                expired: false,
+            },
+        );
+        server.pool.allocate_addr(requested_ip_addr);
+        let _ = server.handle_request(req.clone()).unwrap();
+
+        assert!(server.cache.contains_key(&req.chaddr));
+        assert!(server.pool.addr_is_allocated(requested_ip_addr));
+    }
+
+    #[test]
+    fn test_handle_selecting_request_with_no_address_allocation_maintains_server_invariants() {
+        let req = new_test_request();
+
+        let mut server = new_test_server();
+        let _ = server.handle_request(req.clone());
+
+        assert!(!server.cache.contains_key(&req.chaddr));
+        assert!(!server.pool.addr_is_allocated(Ipv4Addr::new(192, 168, 1, 2)));
+    }
+
+    #[test]
+    fn test_handle_init_reboot_request_with_correct_address_returns_ack() {
+        let mut req = new_test_request();
+        req.options.remove(2);
+        let requested_ip_addr = get_requested_ip_addr(&req).unwrap();
+
+        let mut server = new_test_server();
+        server.cache.insert(
+            req.chaddr,
+            CachedConfig {
+                client_addr: requested_ip_addr,
+                options: vec![],
+                expired: false,
+            },
+        );
+        server.pool.allocate_addr(requested_ip_addr);
+        let got = server.handle_request(req).unwrap();
+
+        let want = new_test_ack();
+        assert_eq!(got, want);
+    }
+
+    #[test]
+    fn test_handle_init_reboot_request_with_incorrect_address_returns_nak() {
+        let mut req = new_test_request();
+        req.options.remove(0);
+        req.options.remove(1);
+        req.options.push(ConfigOption {
+            code: OptionCode::RequestedIpAddr,
+            value: vec![192, 168, 1, 42],
+        });
+
+        let mut server = new_test_server();
+        let assigned_ip = Ipv4Addr::new(192, 168, 1, 2);
+        server.cache.insert(
+            req.chaddr,
+            CachedConfig {
+                client_addr: assigned_ip,
+                options: vec![],
+                expired: false,
+            },
+        );
+        server.pool.allocate_addr(assigned_ip);
+        let got = server.handle_request(req).unwrap();
+
+        let want = new_test_nak();
+        assert_eq!(got, want);
+    }
+
+    #[test]
+    fn test_handle_init_reboot_request_with_unknown_client_returns_none() {
+        let mut req = new_test_request();
+        req.options.remove(2);
+
+        let mut server = new_test_server();
+        let got = server.handle_request(req);
+
+        assert!(got.is_none());
+    }
+
+    #[test]
+    fn test_handle_init_reboot_request_with_client_on_wrong_subnet_returns_nak() {
+        let mut req = new_test_request();
+        req.options.remove(0);
+        req.options.remove(1);
+        req.options.push(ConfigOption {
+            code: OptionCode::RequestedIpAddr,
+            value: vec![10, 0, 0, 1],
+        });
+
+        let mut server = new_test_server();
+        let got = server.handle_request(req).unwrap();
+
+        let want = new_test_nak();
+        assert_eq!(got, want);
+    }
+
+    #[test]
+    fn test_handle_renewing_request_with_valid_request_returns_ack() {
+        let mut req = new_test_request();
+        req.options.remove(0);
+        req.options.remove(1);
+        let client_ip = Ipv4Addr::new(192, 168, 1, 2);
+        req.ciaddr = client_ip;
+
+        let mut server = new_test_server();
+        server.cache.insert(
+            req.chaddr,
+            CachedConfig {
+                client_addr: client_ip,
+                options: vec![],
+                expired: false,
+            },
+        );
+        server.pool.allocate_addr(client_ip);
+        let got = server.handle_request(req).unwrap();
+
+        let mut want = new_test_ack();
+        want.ciaddr = client_ip;
+        assert_eq!(got, want);
+    }
+
+    #[test]
+    fn test_handle_renewing_request_with_unknown_client_returns_none() {
+        let mut req = new_test_request();
+        req.options.remove(0);
+        req.options.remove(1);
+        let client_ip = Ipv4Addr::new(192, 168, 1, 2);
+        req.ciaddr = client_ip;
+
+        let mut server = new_test_server();
+        let got = server.handle_request(req);
+
+        assert!(got.is_none());
+    }
+
+    #[test]
+    fn test_get_client_state_with_selecting_returns_selecting() {
+        let msg = new_test_request();
+
+        let got = get_client_state(&msg);
+
+        assert_eq!(got, ClientState::Selecting);
+    }
+
+    #[test]
+    fn test_get_client_state_with_initreboot_returns_initreboot() {
+        let mut msg = new_test_request();
+        msg.options.remove(2);
+
+        let got = get_client_state(&msg);
+
+        assert_eq!(got, ClientState::InitReboot);
+    }
+
+    #[test]
+    fn test_get_client_state_with_renewing_returns_renewing() {
+        let mut msg = new_test_request();
+        msg.options.remove(0);
+        msg.options.remove(1);
+        msg.ciaddr = Ipv4Addr::new(1, 2, 3, 4);
+
+        let got = get_client_state(&msg);
+
+        assert_eq!(got, ClientState::Renewing);
+    }
+
+    #[test]
+    fn test_get_client_state_with_unknown_returns_unknown() {
+        let mut msg = new_test_request();
+        msg.options.clear();
+
+        let got = get_client_state(&msg);
+
+        assert_eq!(got, ClientState::Unknown);
+    }
 }
diff --git a/bin/fidl_compatibility_test/BUILD.gn b/bin/fidl_compatibility_test/BUILD.gn
index 6ff2040..4448176 100644
--- a/bin/fidl_compatibility_test/BUILD.gn
+++ b/bin/fidl_compatibility_test/BUILD.gn
@@ -4,6 +4,24 @@
 
 import("//build/package.gni")
 
+executable("fidl_compatibility_test") {
+  testonly = true
+
+  sources = [
+    "compatibility_test.cc",
+  ]
+
+  deps = [
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/fidl/compatibility_test:compatibility_test_service",
+    "//garnet/public/lib/fidl/compatibility_test:echo_client_app",
+    "//garnet/public/lib/fidl/cpp",
+    "//third_party/googletest:gtest",
+    "//zircon/public/lib/async-default",
+    "//zircon/public/lib/async-loop-cpp",
+  ]
+}
+
 executable("compatibility_test_server_cpp_bin") {
   output_name = "compatibility_test_server_cpp"
 
@@ -21,6 +39,11 @@
   ]
 }
 
+copy("run_fidl_compatibility_test_garnet_sh") {
+  sources = [ "run_fidl_compatibility_test_garnet.sh" ]
+  outputs = [ "${root_build_dir}/run_fidl_compatibility_test_garnet.sh" ]
+}
+
 package("fidl_compatibility_test_server_cpp") {
   deps = [
     ":compatibility_test_server_cpp_bin",
@@ -30,3 +53,36 @@
 
   binary = "compatibility_test_server_cpp"
 }
+
+# The test binary that gets invoked by shell scripts.
+package("fidl_compatibility_test_bin") {
+  package_name = "fidl_compatibility_test_bin"
+
+  deps = [
+    ":fidl_compatibility_test",
+  ]
+
+  testonly = true
+
+  # Declare it as a binary so humans and automation don't try to run it
+  # directly as a test, which would fail.
+  binary = "fidl_compatibility_test"
+}
+
+# Contains the shell script that runs the test binary.
+package("package") {
+  package_name = "fidl_compatibility_test"
+
+  deps = [
+    ":run_fidl_compatibility_test_garnet_sh"
+  ]
+
+  testonly = true
+
+  tests = [
+    {
+      name = "run_fidl_compatibility_test_garnet.sh"
+      disabled = true # TODO(FIDL-214): re-enable when not flaky
+    },
+  ]
+}
diff --git a/bin/fidl_compatibility_test/compatibility_test.cc b/bin/fidl_compatibility_test/compatibility_test.cc
new file mode 100644
index 0000000..fc47d31
--- /dev/null
+++ b/bin/fidl_compatibility_test/compatibility_test.cc
@@ -0,0 +1,1016 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#define FIDL_ENABLE_LEGACY_WAIT_FOR_RESPONSE
+
+#include <fidl/test/compatibility/cpp/fidl.h>
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/async/default.h>
+#include <stdio.h>
+#include <zircon/assert.h>
+#include <zircon/errors.h>
+#include <zircon/processargs.h>
+#include <algorithm>
+#include <cstdlib>
+#include <random>
+#include <vector>
+
+#include "garnet/public/lib/fidl/compatibility_test/echo_client_app.h"
+#include "gtest/gtest.h"
+#include "lib/fidl/cpp/binding_set.h"
+#include "lib/fxl/files/path.h"
+#include "lib/fxl/strings/split_string.h"
+#include "lib/fxl/strings/utf_codecs.h"
+
+using fidl::test::compatibility::Struct;
+using fidl::VectorPtr;
+using std::string;
+
+namespace {
+// Want a size small enough that it doesn't get too big to transmit but
+// large enough to exercise interesting code paths.
+constexpr uint8_t kArbitraryVectorSize = 3;
+// This is used as a literal constant in compatibility_test_service.fidl.
+constexpr uint8_t kArbitraryConstant = 2;
+
+constexpr char kServersEnvVarName[] = "FIDL_COMPATIBILITY_TEST_SERVERS";
+constexpr char kUsage[] = (
+    "Usage:\n  FIDL_COMPATIBILITY_TEST_SERVERS=foo_server,bar_server "
+    "fidl_compatibility_test\n"
+    "You must set the environment variable FIDL_COMPATIBILITY_TEST_SERVERS to a"
+    "comma-separated list of server URLs when running this test.");
+
+zx::handle Handle() {
+  zx_handle_t raw_event;
+  const zx_status_t status = zx_event_create(0u, &raw_event);
+  // Can't use gtest ASSERT_EQ because we're in a non-void function.
+  ZX_ASSERT_MSG(status == ZX_OK, "status = %d", status);
+  return zx::handle(raw_event);
+}
+
+::testing::AssertionResult HandlesEq(const zx::object_base& a,
+                                     const zx::object_base& b) {
+  if (a.is_valid() != b.is_valid()) {
+    return ::testing::AssertionFailure()
+           << "Handles are not equally valid :" << a.is_valid() << " vs "
+           << b.is_valid();
+  }
+  if (!a.is_valid()) {
+    return ::testing::AssertionSuccess() << "Both handles invalid";
+  }
+  zx_info_handle_basic_t a_info, b_info;
+  zx_status_t status = zx_object_get_info(
+      a.get(), ZX_INFO_HANDLE_BASIC, &a_info, sizeof(a_info), nullptr, nullptr);
+  if (ZX_OK != status) {
+    return ::testing::AssertionFailure()
+           << "zx_object_get_info(a) returned " << status;
+  }
+  status = zx_object_get_info(b.get(), ZX_INFO_HANDLE_BASIC, &b_info,
+                              sizeof(b_info), nullptr, nullptr);
+  if (ZX_OK != status) {
+    return ::testing::AssertionFailure()
+           << "zx_object_get_info(b) returned " << status;
+  }
+  if (a_info.koid != b_info.koid) {
+    return ::testing::AssertionFailure()
+           << std::endl
+           << "a_info.koid is: " << a_info.koid << std::endl
+           << "b_info.koid is: " << b_info.koid;
+  }
+  return ::testing::AssertionSuccess();
+}
+
+void ExpectEq(const Struct& a, const Struct& b) {
+  // primitive types
+  EXPECT_EQ(a.primitive_types.b, b.primitive_types.b);
+  EXPECT_EQ(a.primitive_types.i8, b.primitive_types.i8);
+  EXPECT_EQ(a.primitive_types.i16, b.primitive_types.i16);
+  EXPECT_EQ(a.primitive_types.i32, b.primitive_types.i32);
+  EXPECT_EQ(a.primitive_types.i64, b.primitive_types.i64);
+  EXPECT_EQ(a.primitive_types.u8, b.primitive_types.u8);
+  EXPECT_EQ(a.primitive_types.u16, b.primitive_types.u16);
+  EXPECT_EQ(a.primitive_types.u32, b.primitive_types.u32);
+  EXPECT_EQ(a.primitive_types.u64, b.primitive_types.u64);
+  EXPECT_EQ(a.primitive_types.f32, b.primitive_types.f32);
+  EXPECT_EQ(a.primitive_types.f64, b.primitive_types.f64);
+
+  // arrays
+  EXPECT_EQ(a.arrays.b_0[0], b.arrays.b_0[0]);
+  EXPECT_EQ(a.arrays.i8_0[0], b.arrays.i8_0[0]);
+  EXPECT_EQ(a.arrays.i16_0[0], b.arrays.i16_0[0]);
+  EXPECT_EQ(a.arrays.i32_0[0], b.arrays.i32_0[0]);
+  EXPECT_EQ(a.arrays.i64_0[0], b.arrays.i64_0[0]);
+  EXPECT_EQ(a.arrays.u8_0[0], b.arrays.u8_0[0]);
+  EXPECT_EQ(a.arrays.u16_0[0], b.arrays.u16_0[0]);
+  EXPECT_EQ(a.arrays.u32_0[0], b.arrays.u32_0[0]);
+  EXPECT_EQ(a.arrays.u64_0[0], b.arrays.u64_0[0]);
+  EXPECT_EQ(a.arrays.f32_0[0], b.arrays.f32_0[0]);
+  EXPECT_EQ(a.arrays.f64_0[0], b.arrays.f64_0[0]);
+  EXPECT_TRUE(HandlesEq(a.arrays.handle_0[0], b.arrays.handle_0[0]));
+  for (uint32_t i = 0; i < fidl::test::compatibility::arrays_size; ++i) {
+    EXPECT_EQ(a.arrays.b_1[i], b.arrays.b_1[i]);
+    EXPECT_EQ(a.arrays.i8_1[i], b.arrays.i8_1[i]);
+    EXPECT_EQ(a.arrays.i16_1[i], b.arrays.i16_1[i]);
+    EXPECT_EQ(a.arrays.i32_1[i], b.arrays.i32_1[i]);
+    EXPECT_EQ(a.arrays.i64_1[i], b.arrays.i64_1[i]);
+    EXPECT_EQ(a.arrays.u8_1[i], b.arrays.u8_1[i]);
+    EXPECT_EQ(a.arrays.u16_1[i], b.arrays.u16_1[i]);
+    EXPECT_EQ(a.arrays.u32_1[i], b.arrays.u32_1[i]);
+    EXPECT_EQ(a.arrays.u64_1[i], b.arrays.u64_1[i]);
+    EXPECT_EQ(a.arrays.f32_1[i], b.arrays.f32_1[i]);
+    EXPECT_EQ(a.arrays.f64_1[i], b.arrays.f64_1[i]);
+    EXPECT_TRUE(HandlesEq(a.arrays.handle_1[i], b.arrays.handle_1[i]));
+  }
+  // arrays_2d
+  for (uint32_t i = 0; i < fidl::test::compatibility::arrays_size; ++i) {
+    for (uint32_t j = 0; j < kArbitraryConstant; ++j) {
+      EXPECT_EQ(a.arrays_2d.b[i][j], b.arrays_2d.b[i][j]);
+      EXPECT_EQ(a.arrays_2d.i8[i][j], b.arrays_2d.i8[i][j]);
+      EXPECT_EQ(a.arrays_2d.i16[i][j], b.arrays_2d.i16[i][j]);
+      EXPECT_EQ(a.arrays_2d.i32[i][j], b.arrays_2d.i32[i][j]);
+      EXPECT_EQ(a.arrays_2d.i64[i][j], b.arrays_2d.i64[i][j]);
+      EXPECT_EQ(a.arrays_2d.u8[i][j], b.arrays_2d.u8[i][j]);
+      EXPECT_EQ(a.arrays_2d.u16[i][j], b.arrays_2d.u16[i][j]);
+      EXPECT_EQ(a.arrays_2d.u32[i][j], b.arrays_2d.u32[i][j]);
+      EXPECT_EQ(a.arrays_2d.u64[i][j], b.arrays_2d.u64[i][j]);
+      EXPECT_EQ(a.arrays_2d.f32[i][j], b.arrays_2d.f32[i][j]);
+      EXPECT_EQ(a.arrays_2d.f64[i][j], b.arrays_2d.f64[i][j]);
+      EXPECT_TRUE(HandlesEq(a.arrays_2d.handle_handle[i][j],
+                            b.arrays_2d.handle_handle[i][j]));
+    }
+  }
+  // vectors
+  EXPECT_EQ(a.vectors.b_0.get(), b.vectors.b_0.get());
+  EXPECT_EQ(a.vectors.i8_0.get(), b.vectors.i8_0.get());
+  EXPECT_EQ(a.vectors.i16_0.get(), b.vectors.i16_0.get());
+  EXPECT_EQ(a.vectors.i32_0.get(), b.vectors.i32_0.get());
+  EXPECT_EQ(a.vectors.i64_0.get(), b.vectors.i64_0.get());
+  EXPECT_EQ(a.vectors.u8_0.get(), b.vectors.u8_0.get());
+  EXPECT_EQ(a.vectors.u16_0.get(), b.vectors.u16_0.get());
+  EXPECT_EQ(a.vectors.u32_0.get(), b.vectors.u32_0.get());
+  EXPECT_EQ(a.vectors.u64_0.get(), b.vectors.u64_0.get());
+  EXPECT_EQ(a.vectors.f32_0.get(), b.vectors.f32_0.get());
+  EXPECT_EQ(a.vectors.f64_0.get(), b.vectors.f64_0.get());
+  for (uint8_t i = 0; i < kArbitraryVectorSize; ++i) {
+    EXPECT_TRUE(
+        HandlesEq(a.vectors.handle_0.get()[i], b.vectors.handle_0.get()[i]));
+  }
+
+  for (uint8_t i = 0; i < kArbitraryVectorSize; ++i) {
+    EXPECT_EQ(a.vectors.b_1.get()[i].get(), b.vectors.b_1.get()[i].get());
+    EXPECT_EQ(a.vectors.i8_1.get()[i].get(), b.vectors.i8_1.get()[i].get());
+    EXPECT_EQ(a.vectors.i16_1.get()[i].get(), b.vectors.i16_1.get()[i].get());
+    EXPECT_EQ(a.vectors.i32_1.get()[i].get(), b.vectors.i32_1.get()[i].get());
+    EXPECT_EQ(a.vectors.i64_1.get()[i].get(), b.vectors.i64_1.get()[i].get());
+    EXPECT_EQ(a.vectors.u8_1.get()[i].get(), b.vectors.u8_1.get()[i].get());
+    EXPECT_EQ(a.vectors.u16_1.get()[i].get(), b.vectors.u16_1.get()[i].get());
+    EXPECT_EQ(a.vectors.u32_1.get()[i].get(), b.vectors.u32_1.get()[i].get());
+    EXPECT_EQ(a.vectors.u64_1.get()[i].get(), b.vectors.u64_1.get()[i].get());
+    EXPECT_EQ(a.vectors.f32_1.get()[i].get(), b.vectors.f32_1.get()[i].get());
+    EXPECT_EQ(a.vectors.f64_1.get()[i].get(), b.vectors.f64_1.get()[i].get());
+    for (uint8_t j = 0; j < kArbitraryConstant; ++j) {
+      EXPECT_TRUE(HandlesEq(a.vectors.handle_1.get()[i].get()[j],
+                            b.vectors.handle_1.get()[i].get()[j]));
+    }
+  }
+
+  EXPECT_EQ(a.vectors.b_sized_0.get(), b.vectors.b_sized_0.get());
+  EXPECT_EQ(a.vectors.i8_sized_0.get(), b.vectors.i8_sized_0.get());
+  EXPECT_EQ(a.vectors.i16_sized_0.get(), b.vectors.i16_sized_0.get());
+  EXPECT_EQ(a.vectors.i32_sized_0.get(), b.vectors.i32_sized_0.get());
+  EXPECT_EQ(a.vectors.i64_sized_0.get(), b.vectors.i64_sized_0.get());
+  EXPECT_EQ(a.vectors.u8_sized_0.get(), b.vectors.u8_sized_0.get());
+  EXPECT_EQ(a.vectors.u16_sized_0.get(), b.vectors.u16_sized_0.get());
+  EXPECT_EQ(a.vectors.u32_sized_0.get(), b.vectors.u32_sized_0.get());
+  EXPECT_EQ(a.vectors.u64_sized_0.get(), b.vectors.u64_sized_0.get());
+  EXPECT_EQ(a.vectors.f32_sized_0.get(), b.vectors.f32_sized_0.get());
+  EXPECT_EQ(a.vectors.f64_sized_0.get(), b.vectors.f64_sized_0.get());
+  EXPECT_TRUE(HandlesEq(a.vectors.handle_sized_0.get()[0],
+                        b.vectors.handle_sized_0.get()[0]));
+
+  EXPECT_EQ(a.vectors.b_sized_1.get(), b.vectors.b_sized_1.get());
+  EXPECT_EQ(a.vectors.i8_sized_1.get(), b.vectors.i8_sized_1.get());
+  EXPECT_EQ(a.vectors.i16_sized_1.get(), b.vectors.i16_sized_1.get());
+  EXPECT_EQ(a.vectors.i32_sized_1.get(), b.vectors.i32_sized_1.get());
+  EXPECT_EQ(a.vectors.i64_sized_1.get(), b.vectors.i64_sized_1.get());
+  EXPECT_EQ(a.vectors.u8_sized_1.get(), b.vectors.u8_sized_1.get());
+  EXPECT_EQ(a.vectors.u16_sized_1.get(), b.vectors.u16_sized_1.get());
+  EXPECT_EQ(a.vectors.u32_sized_1.get(), b.vectors.u32_sized_1.get());
+  EXPECT_EQ(a.vectors.u64_sized_1.get(), b.vectors.u64_sized_1.get());
+  EXPECT_EQ(a.vectors.f32_sized_1.get(), b.vectors.f32_sized_1.get());
+  EXPECT_EQ(a.vectors.f64_sized_1.get(), b.vectors.f64_sized_1.get());
+  for (uint32_t i = 0; i < fidl::test::compatibility::vectors_size; ++i) {
+    EXPECT_TRUE(HandlesEq(a.vectors.handle_sized_1.get()[i],
+                          b.vectors.handle_sized_1.get()[i]));
+  }
+
+  for (uint32_t i = 0; i < fidl::test::compatibility::vectors_size; ++i) {
+    EXPECT_EQ(a.vectors.b_sized_2.get()[i].get(),
+              b.vectors.b_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.i8_sized_2.get()[i].get(),
+              b.vectors.i8_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.i16_sized_2.get()[i].get(),
+              b.vectors.i16_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.i32_sized_2.get()[i].get(),
+              b.vectors.i32_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.i64_sized_2.get()[i].get(),
+              b.vectors.i64_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.u8_sized_2.get()[i].get(),
+              b.vectors.u8_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.u16_sized_2.get()[i].get(),
+              b.vectors.u16_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.u32_sized_2.get()[i].get(),
+              b.vectors.u32_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.u64_sized_2.get()[i].get(),
+              b.vectors.u64_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.f32_sized_2.get()[i].get(),
+              b.vectors.f32_sized_2.get()[i].get());
+    EXPECT_EQ(a.vectors.f64_sized_2.get()[i].get(),
+              b.vectors.f64_sized_2.get()[i].get());
+    for (uint8_t j = 0; j < kArbitraryConstant; ++j) {
+      EXPECT_TRUE(HandlesEq(a.vectors.handle_sized_2.get()[i].get()[j],
+                            b.vectors.handle_sized_2.get()[i].get()[j]));
+    }
+  }
+
+  EXPECT_EQ(a.vectors.b_nullable_0.is_null(), b.vectors.b_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.i8_nullable_0.is_null(),
+            b.vectors.i8_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.i16_nullable_0.is_null(),
+            b.vectors.i16_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.i32_nullable_0.is_null(),
+            b.vectors.i32_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.i64_nullable_0.is_null(),
+            b.vectors.i64_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.u8_nullable_0.is_null(),
+            b.vectors.u8_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.u16_nullable_0.is_null(),
+            b.vectors.u16_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.u32_nullable_0.is_null(),
+            b.vectors.u32_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.u64_nullable_0.is_null(),
+            b.vectors.u64_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.f32_nullable_0.is_null(),
+            b.vectors.f32_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.f64_nullable_0.is_null(),
+            b.vectors.f64_nullable_0.is_null());
+  EXPECT_EQ(a.vectors.handle_nullable_0.is_null(),
+            b.vectors.handle_nullable_0.is_null());
+
+  EXPECT_EQ(a.vectors.b_nullable_1.is_null(), b.vectors.b_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.i8_nullable_1.is_null(),
+            b.vectors.i8_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.i16_nullable_1.is_null(),
+            b.vectors.i16_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.i32_nullable_1.is_null(),
+            b.vectors.i32_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.i64_nullable_1.is_null(),
+            b.vectors.i64_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.u8_nullable_1.is_null(),
+            b.vectors.u8_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.u16_nullable_1.is_null(),
+            b.vectors.u16_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.u32_nullable_1.is_null(),
+            b.vectors.u32_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.u64_nullable_1.is_null(),
+            b.vectors.u64_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.f32_nullable_1.is_null(),
+            b.vectors.f32_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.f64_nullable_1.is_null(),
+            b.vectors.f64_nullable_1.is_null());
+  EXPECT_EQ(a.vectors.handle_nullable_1.is_null(),
+            b.vectors.handle_nullable_1.is_null());
+
+  for (uint8_t i = 0; i < kArbitraryVectorSize; ++i) {
+    EXPECT_EQ(a.vectors.i8_nullable_1.get()[i].get(),
+              b.vectors.i8_nullable_1.get()[i].get());
+  }
+
+  EXPECT_EQ(a.vectors.b_nullable_sized_0.is_null(),
+            b.vectors.b_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.i8_nullable_sized_0.is_null(),
+            b.vectors.i8_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.i16_nullable_sized_0.is_null(),
+            b.vectors.i16_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.i32_nullable_sized_0.is_null(),
+            b.vectors.i32_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.i64_nullable_sized_0.is_null(),
+            b.vectors.i64_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.u8_nullable_sized_0.is_null(),
+            b.vectors.u8_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.u16_nullable_sized_0.is_null(),
+            b.vectors.u16_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.u32_nullable_sized_0.is_null(),
+            b.vectors.u32_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.u64_nullable_sized_0.is_null(),
+            b.vectors.u64_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.f32_nullable_sized_0.is_null(),
+            b.vectors.f32_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.f64_nullable_sized_0.is_null(),
+            b.vectors.f64_nullable_sized_0.is_null());
+  EXPECT_EQ(a.vectors.handle_nullable_sized_0.is_null(),
+            b.vectors.handle_nullable_sized_0.is_null());
+
+  EXPECT_EQ(a.vectors.i16_nullable_sized_0.get(),
+            b.vectors.i16_nullable_sized_0.get());
+
+  EXPECT_EQ(a.vectors.b_nullable_sized_1.is_null(),
+            b.vectors.b_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.i8_nullable_sized_1.is_null(),
+            b.vectors.i8_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.i16_nullable_sized_1.is_null(),
+            b.vectors.i16_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.i32_nullable_sized_1.is_null(),
+            b.vectors.i32_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.i64_nullable_sized_1.is_null(),
+            b.vectors.i64_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.u8_nullable_sized_1.is_null(),
+            b.vectors.u8_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.u16_nullable_sized_1.is_null(),
+            b.vectors.u16_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.u32_nullable_sized_1.is_null(),
+            b.vectors.u32_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.u64_nullable_sized_1.is_null(),
+            b.vectors.u64_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.f32_nullable_sized_1.is_null(),
+            b.vectors.f32_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.f64_nullable_sized_1.is_null(),
+            b.vectors.f64_nullable_sized_1.is_null());
+  EXPECT_EQ(a.vectors.handle_nullable_sized_1.is_null(),
+            b.vectors.handle_nullable_sized_1.is_null());
+
+  EXPECT_EQ(a.vectors.f64_nullable_sized_1.get(),
+            b.vectors.f64_nullable_sized_1.get());
+
+  EXPECT_EQ(a.vectors.b_nullable_sized_2.is_null(),
+            b.vectors.b_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.i8_nullable_sized_2.is_null(),
+            b.vectors.i8_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.i16_nullable_sized_2.is_null(),
+            b.vectors.i16_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.i32_nullable_sized_2.is_null(),
+            b.vectors.i32_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.i64_nullable_sized_2.is_null(),
+            b.vectors.i64_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.u8_nullable_sized_2.is_null(),
+            b.vectors.u8_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.u16_nullable_sized_2.is_null(),
+            b.vectors.u16_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.u32_nullable_sized_2.is_null(),
+            b.vectors.u32_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.u64_nullable_sized_2.is_null(),
+            b.vectors.u64_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.f32_nullable_sized_2.is_null(),
+            b.vectors.f32_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.f64_nullable_sized_2.is_null(),
+            b.vectors.f64_nullable_sized_2.is_null());
+  EXPECT_EQ(a.vectors.handle_nullable_sized_2.is_null(),
+            b.vectors.handle_nullable_sized_2.is_null());
+
+  for (uint32_t i = 0; i < fidl::test::compatibility::vectors_size; ++i) {
+    for (uint8_t j = 0; j < kArbitraryConstant; ++j) {
+      EXPECT_TRUE(
+          HandlesEq(a.vectors.handle_nullable_sized_2.get()[i].get()[j],
+                    b.vectors.handle_nullable_sized_2.get()[i].get()[j]));
+    }
+  }
+
+  // handles
+  EXPECT_TRUE(HandlesEq(a.handles.handle_handle, b.handles.handle_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.process_handle, b.handles.process_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.thread_handle, b.handles.thread_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.vmo_handle, b.handles.vmo_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.event_handle, b.handles.event_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.port_handle, b.handles.port_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.log_handle, b.handles.log_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.socket_handle, b.handles.socket_handle));
+  EXPECT_TRUE(
+      HandlesEq(a.handles.eventpair_handle, b.handles.eventpair_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.job_handle, b.handles.job_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.vmar_handle, b.handles.vmar_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.fifo_handle, b.handles.fifo_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.timer_handle, b.handles.timer_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_handle_handle,
+                        b.handles.nullable_handle_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_process_handle,
+                        b.handles.nullable_process_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_thread_handle,
+                        b.handles.nullable_thread_handle));
+  EXPECT_TRUE(
+      HandlesEq(a.handles.nullable_vmo_handle, b.handles.nullable_vmo_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_channel_handle,
+                        b.handles.nullable_channel_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_event_handle,
+                        b.handles.nullable_event_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_port_handle,
+                        b.handles.nullable_port_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_interrupt_handle,
+                        b.handles.nullable_interrupt_handle));
+  EXPECT_TRUE(
+      HandlesEq(a.handles.nullable_log_handle, b.handles.nullable_log_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_socket_handle,
+                        b.handles.nullable_socket_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_eventpair_handle,
+                        b.handles.nullable_eventpair_handle));
+  EXPECT_TRUE(
+      HandlesEq(a.handles.nullable_job_handle, b.handles.nullable_job_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_vmar_handle,
+                        b.handles.nullable_vmar_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_fifo_handle,
+                        b.handles.nullable_fifo_handle));
+  EXPECT_TRUE(HandlesEq(a.handles.nullable_timer_handle,
+                        b.handles.nullable_timer_handle));
+
+  // strings
+  EXPECT_EQ(a.strings.s, b.strings.s);
+  EXPECT_EQ(a.strings.size_0_s, b.strings.size_0_s);
+  EXPECT_EQ(a.strings.size_1_s, b.strings.size_1_s);
+  EXPECT_EQ(a.strings.nullable_size_0_s.get(),
+            b.strings.nullable_size_0_s.get());
+  EXPECT_EQ(a.strings.nullable_size_1_s.is_null(),
+            b.strings.nullable_size_1_s.is_null());
+
+  // enums
+  EXPECT_EQ(a.default_enum, b.default_enum);
+  EXPECT_EQ(a.i8_enum, b.i8_enum);
+  EXPECT_EQ(a.i16_enum, b.i16_enum);
+  EXPECT_EQ(a.i32_enum, b.i32_enum);
+  EXPECT_EQ(a.i64_enum, b.i64_enum);
+  EXPECT_EQ(a.u8_enum, b.u8_enum);
+  EXPECT_EQ(a.u16_enum, b.u16_enum);
+  EXPECT_EQ(a.u32_enum, b.u32_enum);
+  EXPECT_EQ(a.u64_enum, b.u64_enum);
+
+  // structs
+  EXPECT_EQ(a.structs.s.s, b.structs.s.s);
+  EXPECT_EQ(a.structs.nullable_s, b.structs.nullable_s);
+
+  // unions
+  EXPECT_EQ(a.unions.u.is_s(), b.unions.u.is_s());
+  EXPECT_EQ(a.unions.u.s(), b.unions.u.s());
+  EXPECT_EQ(a.unions.nullable_u->is_b(), b.unions.nullable_u->is_b());
+  EXPECT_EQ(a.unions.nullable_u->b(), b.unions.nullable_u->b());
+
+  // bool
+  EXPECT_EQ(a.b, b.b);
+}
+
+std::string RandomUTF8(size_t count) {
+  // Prepare randomness.
+  std::default_random_engine rand_engine;
+  // Using randomness to avoid having to come up with varied values by hand.
+  // Seed deterministically so that this function's outputs are predictable.
+  rand_engine.seed(count);
+  std::uniform_int_distribution<uint32_t> uint32_distribution;
+
+  std::string random_string;
+  random_string.reserve(count);
+  do {
+    // Generate a random 32 bit unsigned int to use a the code point.
+    uint32_t code_point = uint32_distribution(rand_engine);
+    // Mask the random number so that it can be encoded into the number of bytes
+    // remaining.
+    size_t remaining = count - random_string.size();
+    if (remaining == 1) {
+      code_point &= 0x7F;
+    } else if (remaining == 2) {
+      code_point &= 0x7FF;
+    } else if (remaining == 3) {
+      code_point &= 0xFFFF;
+    } else {
+      // Mask to fall within the general range of code points.
+      code_point &= 0x1FFFFF;
+    }
+    // Check that it's really a valid code point, otherwise try again.
+    if (!fxl::IsValidCodepoint(code_point)) {
+      continue;
+    }
+    // Add the character to the random string.
+    fxl::WriteUnicodeCharacter(code_point, &random_string);
+    FXL_CHECK(random_string.size() <= count);
+  } while (random_string.size() < count);
+  return random_string;
+}
+
+void Initialize(Struct* s) {
+  // Prepare randomness.
+  std::default_random_engine rand_engine;
+  // Using randomness to avoid having to come up with varied values by hand.
+  // Seed deterministically so that this function's outputs are predictable.
+  rand_engine.seed(42);
+  std::uniform_int_distribution<bool> bool_distribution;
+  std::uniform_int_distribution<int8_t> int8_distribution;
+  std::uniform_int_distribution<int16_t> int16_distribution;
+  std::uniform_int_distribution<int32_t> int32_distribution;
+  std::uniform_int_distribution<int64_t> int64_distribution;
+  std::uniform_int_distribution<uint8_t> uint8_distribution;
+  std::uniform_int_distribution<uint16_t> uint16_distribution;
+  std::uniform_int_distribution<uint32_t> uint32_distribution;
+  std::uniform_int_distribution<uint64_t> uint64_distribution;
+  std::uniform_real_distribution<float> float_distribution;
+  std::uniform_real_distribution<double> double_distribution;
+  std::string random_string =
+      RandomUTF8(fidl::test::compatibility::strings_size);
+  std::string random_short_string = RandomUTF8(kArbitraryConstant);
+
+  // primitive_types
+  s->primitive_types.b = bool_distribution(rand_engine);
+  s->primitive_types.i8 = int8_distribution(rand_engine);
+  s->primitive_types.i16 = int16_distribution(rand_engine);
+  s->primitive_types.i32 = int32_distribution(rand_engine);
+  s->primitive_types.i64 = int64_distribution(rand_engine);
+  s->primitive_types.u8 = uint8_distribution(rand_engine);
+  s->primitive_types.u16 = uint16_distribution(rand_engine);
+  s->primitive_types.u32 = uint32_distribution(rand_engine);
+  s->primitive_types.u64 = uint64_distribution(rand_engine);
+  s->primitive_types.f32 = float_distribution(rand_engine);
+  s->primitive_types.f64 = double_distribution(rand_engine);
+
+  // arrays
+  s->arrays.b_0[0] = bool_distribution(rand_engine);
+  s->arrays.i8_0[0] = int8_distribution(rand_engine);
+  s->arrays.i16_0[0] = int16_distribution(rand_engine);
+  s->arrays.i32_0[0] = int32_distribution(rand_engine);
+  s->arrays.i64_0[0] = int64_distribution(rand_engine);
+  s->arrays.u8_0[0] = uint8_distribution(rand_engine);
+  s->arrays.u16_0[0] = uint16_distribution(rand_engine);
+  s->arrays.u32_0[0] = uint32_distribution(rand_engine);
+  s->arrays.u64_0[0] = uint64_distribution(rand_engine);
+  s->arrays.f32_0[0] = float_distribution(rand_engine);
+  s->arrays.f64_0[0] = double_distribution(rand_engine);
+  s->arrays.handle_0[0] = Handle();
+
+  for (uint32_t i = 0; i < fidl::test::compatibility::arrays_size; ++i) {
+    s->arrays.b_1[i] = bool_distribution(rand_engine);
+    s->arrays.i8_1[i] = int8_distribution(rand_engine);
+    s->arrays.i16_1[i] = int16_distribution(rand_engine);
+    s->arrays.i32_1[i] = int32_distribution(rand_engine);
+    s->arrays.i64_1[i] = int64_distribution(rand_engine);
+    s->arrays.u8_1[i] = uint8_distribution(rand_engine);
+    s->arrays.u16_1[i] = uint16_distribution(rand_engine);
+    s->arrays.u32_1[i] = uint32_distribution(rand_engine);
+    s->arrays.u64_1[i] = uint64_distribution(rand_engine);
+    s->arrays.f32_1[i] = float_distribution(rand_engine);
+    s->arrays.f64_1[i] = double_distribution(rand_engine);
+    s->arrays.handle_1[i] = Handle();
+  }
+
+  // arrays_2d
+  for (uint32_t i = 0; i < fidl::test::compatibility::arrays_size; ++i) {
+    for (uint32_t j = 0; j < kArbitraryConstant; ++j) {
+      s->arrays_2d.b[i][j] = bool_distribution(rand_engine);
+      s->arrays_2d.i8[i][j] = int8_distribution(rand_engine);
+      s->arrays_2d.i16[i][j] = int16_distribution(rand_engine);
+      s->arrays_2d.i32[i][j] = int32_distribution(rand_engine);
+      s->arrays_2d.i64[i][j] = int64_distribution(rand_engine);
+      s->arrays_2d.u8[i][j] = uint8_distribution(rand_engine);
+      s->arrays_2d.u16[i][j] = uint16_distribution(rand_engine);
+      s->arrays_2d.u32[i][j] = uint32_distribution(rand_engine);
+      s->arrays_2d.u64[i][j] = uint64_distribution(rand_engine);
+      s->arrays_2d.f32[i][j] = float_distribution(rand_engine);
+      s->arrays_2d.f64[i][j] = double_distribution(rand_engine);
+      s->arrays_2d.handle_handle[i][j] = Handle();
+    }
+  }
+
+  // vectors
+  s->vectors.b_0 = VectorPtr<bool>(
+      std::vector<bool>(kArbitraryVectorSize, bool_distribution(rand_engine)));
+  s->vectors.i8_0 = VectorPtr<int8_t>(std::vector<int8_t>(
+      kArbitraryVectorSize, int8_distribution(rand_engine)));
+  s->vectors.i16_0 = VectorPtr<int16_t>(std::vector<int16_t>(
+      kArbitraryVectorSize, int16_distribution(rand_engine)));
+  s->vectors.i32_0 = VectorPtr<int32_t>(std::vector<int32_t>(
+      kArbitraryVectorSize, int32_distribution(rand_engine)));
+  s->vectors.i64_0 = VectorPtr<int64_t>(std::vector<int64_t>(
+      kArbitraryVectorSize, int64_distribution(rand_engine)));
+  s->vectors.u8_0 = VectorPtr<uint8_t>(std::vector<uint8_t>(
+      kArbitraryVectorSize, uint8_distribution(rand_engine)));
+  s->vectors.u16_0 = VectorPtr<uint16_t>(std::vector<uint16_t>(
+      kArbitraryVectorSize, uint16_distribution(rand_engine)));
+  s->vectors.u32_0 = VectorPtr<uint32_t>(std::vector<uint32_t>(
+      kArbitraryVectorSize, uint32_distribution(rand_engine)));
+  s->vectors.u64_0 = VectorPtr<uint64_t>(std::vector<uint64_t>(
+      kArbitraryVectorSize, uint64_distribution(rand_engine)));
+  s->vectors.f32_0 = VectorPtr<float>(std::vector<float>(
+      kArbitraryVectorSize, float_distribution(rand_engine)));
+  s->vectors.f64_0 = VectorPtr<double>(std::vector<double>(
+      kArbitraryVectorSize, double_distribution(rand_engine)));
+
+  {
+    std::vector<zx::handle> underlying_vec;
+    for (uint8_t i = 0; i < kArbitraryVectorSize; ++i) {
+      underlying_vec.emplace_back(Handle());
+    }
+    s->vectors.handle_0 = VectorPtr<zx::handle>(std::move(underlying_vec));
+  }
+
+  {
+    std::vector<VectorPtr<bool>> bool_outer_vector;
+    std::vector<VectorPtr<int8_t>> int8_outer_vector;
+    std::vector<VectorPtr<int16_t>> int16_outer_vector;
+    std::vector<VectorPtr<int32_t>> int32_outer_vector;
+    std::vector<VectorPtr<int64_t>> int64_outer_vector;
+    std::vector<VectorPtr<uint8_t>> uint8_outer_vector;
+    std::vector<VectorPtr<uint16_t>> uint16_outer_vector;
+    std::vector<VectorPtr<uint32_t>> uint32_outer_vector;
+    std::vector<VectorPtr<uint64_t>> uint64_outer_vector;
+    std::vector<VectorPtr<float>> float_outer_vector;
+    std::vector<VectorPtr<double>> double_outer_vector;
+    std::vector<VectorPtr<zx::handle>> handle_outer_vector;
+    for (uint8_t i = 0; i < kArbitraryVectorSize; ++i) {
+      bool_outer_vector.emplace_back(VectorPtr<bool>(std::vector<bool>(
+          kArbitraryConstant, bool_distribution(rand_engine))));
+      int8_outer_vector.emplace_back(VectorPtr<int8_t>(std::vector<int8_t>(
+          kArbitraryConstant, int8_distribution(rand_engine))));
+      int16_outer_vector.emplace_back(VectorPtr<int16_t>(std::vector<int16_t>(
+          kArbitraryConstant, int16_distribution(rand_engine))));
+      int32_outer_vector.emplace_back(VectorPtr<int32_t>(std::vector<int32_t>(
+          kArbitraryConstant, int32_distribution(rand_engine))));
+      int64_outer_vector.emplace_back(VectorPtr<int64_t>(std::vector<int64_t>(
+          kArbitraryConstant, int64_distribution(rand_engine))));
+      uint8_outer_vector.emplace_back(VectorPtr<uint8_t>(std::vector<uint8_t>(
+          kArbitraryConstant, uint8_distribution(rand_engine))));
+      uint16_outer_vector.emplace_back(
+          VectorPtr<uint16_t>(std::vector<uint16_t>(
+              kArbitraryConstant, uint16_distribution(rand_engine))));
+      uint32_outer_vector.emplace_back(
+          VectorPtr<uint32_t>(std::vector<uint32_t>(
+              kArbitraryConstant, uint32_distribution(rand_engine))));
+      uint64_outer_vector.emplace_back(
+          VectorPtr<uint64_t>(std::vector<uint64_t>(
+              kArbitraryConstant, uint64_distribution(rand_engine))));
+      float_outer_vector.emplace_back(VectorPtr<float>(std::vector<float>(
+          kArbitraryConstant, float_distribution(rand_engine))));
+      double_outer_vector.emplace_back(VectorPtr<double>(std::vector<double>(
+          kArbitraryConstant, double_distribution(rand_engine))));
+      std::vector<zx::handle> handle_inner_vector;
+      for (uint8_t i = 0; i < kArbitraryConstant; ++i) {
+        handle_inner_vector.emplace_back(Handle());
+      }
+      handle_outer_vector.emplace_back(
+          VectorPtr<zx::handle>(std::move(handle_inner_vector)));
+    }
+    s->vectors.b_1 = VectorPtr<VectorPtr<bool>>(std::move(bool_outer_vector));
+    s->vectors.i8_1 =
+        VectorPtr<VectorPtr<int8_t>>(std::move(int8_outer_vector));
+    s->vectors.i16_1 =
+        VectorPtr<VectorPtr<int16_t>>(std::move(int16_outer_vector));
+    s->vectors.i32_1 =
+        VectorPtr<VectorPtr<int32_t>>(std::move(int32_outer_vector));
+    s->vectors.i64_1 =
+        VectorPtr<VectorPtr<int64_t>>(std::move(int64_outer_vector));
+    s->vectors.u8_1 =
+        VectorPtr<VectorPtr<uint8_t>>(std::move(uint8_outer_vector));
+    s->vectors.u16_1 =
+        VectorPtr<VectorPtr<uint16_t>>(std::move(uint16_outer_vector));
+    s->vectors.u32_1 =
+        VectorPtr<VectorPtr<uint32_t>>(std::move(uint32_outer_vector));
+    s->vectors.u64_1 =
+        VectorPtr<VectorPtr<uint64_t>>(std::move(uint64_outer_vector));
+    s->vectors.f32_1 =
+        VectorPtr<VectorPtr<float>>(std::move(float_outer_vector));
+    s->vectors.f64_1 =
+        VectorPtr<VectorPtr<double>>(std::move(double_outer_vector));
+    s->vectors.handle_1 =
+        VectorPtr<VectorPtr<zx::handle>>(std::move(handle_outer_vector));
+  }
+
+  s->vectors.b_sized_0 =
+      VectorPtr<bool>(std::vector<bool>{bool_distribution(rand_engine)});
+  s->vectors.i8_sized_0 =
+      VectorPtr<int8_t>(std::vector<int8_t>{int8_distribution(rand_engine)});
+  s->vectors.i16_sized_0 =
+      VectorPtr<int16_t>(std::vector<int16_t>{int16_distribution(rand_engine)});
+  s->vectors.i32_sized_0 =
+      VectorPtr<int32_t>(std::vector<int32_t>{int32_distribution(rand_engine)});
+  s->vectors.i64_sized_0 =
+      VectorPtr<int64_t>(std::vector<int64_t>{int64_distribution(rand_engine)});
+  s->vectors.u8_sized_0 =
+      VectorPtr<uint8_t>(std::vector<uint8_t>{uint8_distribution(rand_engine)});
+  s->vectors.u16_sized_0 = VectorPtr<uint16_t>(
+      std::vector<uint16_t>{uint16_distribution(rand_engine)});
+  s->vectors.u32_sized_0 = VectorPtr<uint32_t>(
+      std::vector<uint32_t>{uint32_distribution(rand_engine)});
+  s->vectors.u64_sized_0 = VectorPtr<uint64_t>(
+      std::vector<uint64_t>{uint64_distribution(rand_engine)});
+  s->vectors.f32_sized_0 =
+      VectorPtr<float>(std::vector<float>{float_distribution(rand_engine)});
+  s->vectors.f64_sized_0 =
+      VectorPtr<double>(std::vector<double>{double_distribution(rand_engine)});
+
+  {
+    std::vector<zx::handle> underlying_vec;
+    underlying_vec.emplace_back(Handle());
+    s->vectors.handle_sized_0 =
+        VectorPtr<zx::handle>(std::move(underlying_vec));
+  }
+
+  s->vectors.b_sized_1 = VectorPtr<bool>(
+      std::vector<bool>(fidl::test::compatibility::vectors_size,
+                        bool_distribution(rand_engine)));
+  s->vectors.i8_sized_1 = VectorPtr<int8_t>(
+      std::vector<int8_t>(fidl::test::compatibility::vectors_size,
+                          int8_distribution(rand_engine)));
+  s->vectors.i16_sized_1 = VectorPtr<int16_t>(
+      std::vector<int16_t>(fidl::test::compatibility::vectors_size,
+                           int16_distribution(rand_engine)));
+  s->vectors.i32_sized_1 = VectorPtr<int32_t>(
+      std::vector<int32_t>(fidl::test::compatibility::vectors_size,
+                           int32_distribution(rand_engine)));
+  s->vectors.i64_sized_1 = VectorPtr<int64_t>(
+      std::vector<int64_t>(fidl::test::compatibility::vectors_size,
+                           int64_distribution(rand_engine)));
+  s->vectors.u8_sized_1 = VectorPtr<uint8_t>(
+      std::vector<uint8_t>(fidl::test::compatibility::vectors_size,
+                           uint8_distribution(rand_engine)));
+  s->vectors.u16_sized_1 = VectorPtr<uint16_t>(
+      std::vector<uint16_t>(fidl::test::compatibility::vectors_size,
+                            uint16_distribution(rand_engine)));
+  s->vectors.u32_sized_1 = VectorPtr<uint32_t>(
+      std::vector<uint32_t>(fidl::test::compatibility::vectors_size,
+                            uint32_distribution(rand_engine)));
+  s->vectors.u64_sized_1 = VectorPtr<uint64_t>(
+      std::vector<uint64_t>(fidl::test::compatibility::vectors_size,
+                            uint64_distribution(rand_engine)));
+  s->vectors.f32_sized_1 = VectorPtr<float>(
+      std::vector<float>(fidl::test::compatibility::vectors_size,
+                         float_distribution(rand_engine)));
+  s->vectors.f64_sized_1 = VectorPtr<double>(
+      std::vector<double>(fidl::test::compatibility::vectors_size,
+                          double_distribution(rand_engine)));
+  {
+    std::vector<zx::handle> underlying_vec;
+    for (uint32_t i = 0; i < fidl::test::compatibility::vectors_size; ++i) {
+      underlying_vec.emplace_back(Handle());
+    }
+    s->vectors.handle_sized_1 =
+        VectorPtr<zx::handle>(std::move(underlying_vec));
+  }
+  {
+    std::vector<VectorPtr<bool>> bool_outer_vector;
+    std::vector<VectorPtr<int8_t>> int8_outer_vector;
+    std::vector<VectorPtr<int16_t>> int16_outer_vector;
+    std::vector<VectorPtr<int32_t>> int32_outer_vector;
+    std::vector<VectorPtr<int64_t>> int64_outer_vector;
+    std::vector<VectorPtr<uint8_t>> uint8_outer_vector;
+    std::vector<VectorPtr<uint16_t>> uint16_outer_vector;
+    std::vector<VectorPtr<uint32_t>> uint32_outer_vector;
+    std::vector<VectorPtr<uint64_t>> uint64_outer_vector;
+    std::vector<VectorPtr<float>> float_outer_vector;
+    std::vector<VectorPtr<double>> double_outer_vector;
+    std::vector<VectorPtr<zx::handle>> handle_outer_vector;
+    for (uint32_t i = 0; i < fidl::test::compatibility::vectors_size; ++i) {
+      bool_outer_vector.emplace_back(VectorPtr<bool>(std::vector<bool>(
+          kArbitraryConstant, bool_distribution(rand_engine))));
+      int8_outer_vector.emplace_back(VectorPtr<int8_t>(std::vector<int8_t>(
+          kArbitraryConstant, int8_distribution(rand_engine))));
+      int16_outer_vector.emplace_back(VectorPtr<int16_t>(std::vector<int16_t>(
+          kArbitraryConstant, int16_distribution(rand_engine))));
+      int32_outer_vector.emplace_back(VectorPtr<int32_t>(std::vector<int32_t>(
+          kArbitraryConstant, int32_distribution(rand_engine))));
+      int64_outer_vector.emplace_back(VectorPtr<int64_t>(std::vector<int64_t>(
+          kArbitraryConstant, int64_distribution(rand_engine))));
+      uint8_outer_vector.emplace_back(VectorPtr<uint8_t>(std::vector<uint8_t>(
+          kArbitraryConstant, uint8_distribution(rand_engine))));
+      uint16_outer_vector.emplace_back(
+          VectorPtr<uint16_t>(std::vector<uint16_t>(
+              kArbitraryConstant, uint16_distribution(rand_engine))));
+      uint32_outer_vector.emplace_back(
+          VectorPtr<uint32_t>(std::vector<uint32_t>(
+              kArbitraryConstant, uint32_distribution(rand_engine))));
+      uint64_outer_vector.emplace_back(
+          VectorPtr<uint64_t>(std::vector<uint64_t>(
+              kArbitraryConstant, uint64_distribution(rand_engine))));
+      float_outer_vector.emplace_back(VectorPtr<float>(std::vector<float>(
+          kArbitraryConstant, float_distribution(rand_engine))));
+      double_outer_vector.emplace_back(VectorPtr<double>(std::vector<double>(
+          kArbitraryConstant, double_distribution(rand_engine))));
+      std::vector<zx::handle> handle_inner_vector;
+      for (uint8_t i = 0; i < kArbitraryConstant; ++i) {
+        handle_inner_vector.emplace_back(Handle());
+      }
+      handle_outer_vector.emplace_back(
+          VectorPtr<zx::handle>(std::move(handle_inner_vector)));
+    }
+    s->vectors.b_sized_2 =
+        VectorPtr<VectorPtr<bool>>(std::move(bool_outer_vector));
+    s->vectors.i8_sized_2 =
+        VectorPtr<VectorPtr<int8_t>>(std::move(int8_outer_vector));
+    s->vectors.i16_sized_2 =
+        VectorPtr<VectorPtr<int16_t>>(std::move(int16_outer_vector));
+    s->vectors.i32_sized_2 =
+        VectorPtr<VectorPtr<int32_t>>(std::move(int32_outer_vector));
+    s->vectors.i64_sized_2 =
+        VectorPtr<VectorPtr<int64_t>>(std::move(int64_outer_vector));
+    s->vectors.u8_sized_2 =
+        VectorPtr<VectorPtr<uint8_t>>(std::move(uint8_outer_vector));
+    s->vectors.u16_sized_2 =
+        VectorPtr<VectorPtr<uint16_t>>(std::move(uint16_outer_vector));
+    s->vectors.u32_sized_2 =
+        VectorPtr<VectorPtr<uint32_t>>(std::move(uint32_outer_vector));
+    s->vectors.u64_sized_2 =
+        VectorPtr<VectorPtr<uint64_t>>(std::move(uint64_outer_vector));
+    s->vectors.f32_sized_2 =
+        VectorPtr<VectorPtr<float>>(std::move(float_outer_vector));
+    s->vectors.f64_sized_2 =
+        VectorPtr<VectorPtr<double>>(std::move(double_outer_vector));
+    s->vectors.handle_sized_2 =
+        VectorPtr<VectorPtr<zx::handle>>(std::move(handle_outer_vector));
+  }
+
+  // intentionally leave most of the nullable vectors as null, just set one
+  // from each category.
+  s->vectors.b_nullable_0 =
+      VectorPtr<bool>(std::vector<bool>{bool_distribution(rand_engine)});
+  {
+    std::vector<VectorPtr<int8_t>> int8_outer_vector;
+    for (uint8_t i = 0; i < kArbitraryVectorSize; ++i) {
+      int8_outer_vector.emplace_back(VectorPtr<int8_t>(std::vector<int8_t>(
+          kArbitraryConstant, int8_distribution(rand_engine))));
+    }
+    s->vectors.i8_nullable_1 =
+        VectorPtr<VectorPtr<int8_t>>(std::move(int8_outer_vector));
+  }
+  s->vectors.i16_nullable_sized_0 =
+      VectorPtr<int16_t>(std::vector<int16_t>{int16_distribution(rand_engine)});
+  s->vectors.f64_nullable_sized_1 = VectorPtr<double>(
+      std::vector<double>(fidl::test::compatibility::vectors_size,
+                          double_distribution(rand_engine)));
+  {
+    std::vector<VectorPtr<zx::handle>> handle_outer_vector;
+    for (uint32_t i = 0; i < fidl::test::compatibility::vectors_size; ++i) {
+      std::vector<zx::handle> handle_inner_vector;
+      for (uint8_t i = 0; i < kArbitraryConstant; ++i) {
+        handle_inner_vector.emplace_back(Handle());
+      }
+      handle_outer_vector.emplace_back(
+          VectorPtr<zx::handle>(std::move(handle_inner_vector)));
+    }
+    s->vectors.handle_nullable_sized_2 =
+        VectorPtr<VectorPtr<zx::handle>>(std::move(handle_outer_vector));
+  }
+
+  // handles
+  s->handles.handle_handle = Handle();
+
+  zx_handle_t duplicate_process = ZX_HANDLE_INVALID;
+  zx_handle_duplicate(zx::process::self().get(), ZX_RIGHT_SAME_RIGHTS,
+                      &duplicate_process);
+  s->handles.process_handle = zx::process(duplicate_process);
+
+  ASSERT_EQ(ZX_OK, zx::thread::create(zx::process::self(), "dummy", 5u, 0u,
+                                      &s->handles.thread_handle));
+  ASSERT_EQ(ZX_OK, zx::vmo::create(0u, 0u, &s->handles.vmo_handle));
+  ASSERT_EQ(ZX_OK, zx::event::create(0u, &s->handles.event_handle));
+  ASSERT_EQ(ZX_OK, zx::port::create(0u, &s->handles.port_handle));
+  ASSERT_EQ(ZX_OK, zx::log::create(0u, &s->handles.log_handle));
+
+  zx::socket socket1;
+  ASSERT_EQ(ZX_OK, zx::socket::create(0u, &s->handles.socket_handle, &socket1));
+
+  zx::eventpair eventpair1;
+  ASSERT_EQ(ZX_OK, zx::eventpair::create(0u, &s->handles.eventpair_handle,
+                                         &eventpair1));
+
+  ASSERT_EQ(ZX_OK,
+            zx::job::create(zx_job_default(), 0u, &s->handles.job_handle));
+
+  uintptr_t vmar_addr;
+  ASSERT_EQ(ZX_OK, zx::vmar::root_self().allocate(
+                       0u, getpagesize(), ZX_VM_FLAG_CAN_MAP_READ,
+                       &s->handles.vmar_handle, &vmar_addr));
+
+  zx::fifo fifo1;
+  ASSERT_EQ(ZX_OK,
+            zx::fifo::create(1u, 1u, 0u, &s->handles.fifo_handle, &fifo1));
+
+  ASSERT_EQ(ZX_OK, zx::timer::create(0u, ZX_CLOCK_MONOTONIC,
+                                     &s->handles.timer_handle));
+
+  // For the nullable ones, just set one of them.
+  s->handles.nullable_handle_handle = Handle();
+
+  // strings
+  s->strings.s = fidl::StringPtr(random_string);
+  s->strings.size_0_s = fidl::StringPtr(random_short_string);
+  s->strings.size_1_s = fidl::StringPtr(random_string);
+  s->strings.nullable_size_0_s = fidl::StringPtr(random_short_string);
+
+  // enums
+  s->default_enum = fidl::test::compatibility::default_enum::kOne;
+  s->i8_enum = fidl::test::compatibility::i8_enum::kNegativeOne;
+  s->i16_enum = fidl::test::compatibility::i16_enum::kNegativeOne;
+  s->i32_enum = fidl::test::compatibility::i32_enum::kNegativeOne;
+  s->i64_enum = fidl::test::compatibility::i64_enum::kNegativeOne;
+  s->u8_enum = fidl::test::compatibility::u8_enum::kOne;
+  s->u16_enum = fidl::test::compatibility::u16_enum::kTwo;
+  s->u32_enum = fidl::test::compatibility::u32_enum::kThree;
+  s->u64_enum = fidl::test::compatibility::u64_enum::kFour;
+
+  // structs
+  s->structs.s.s = fidl::StringPtr(random_string);
+
+  // unions
+  s->unions.u.set_s(fidl::StringPtr(random_string));
+  s->unions.nullable_u = fidl::test::compatibility::this_is_a_union::New();
+  s->unions.nullable_u->set_b(bool_distribution(rand_engine));
+
+  // bool
+  s->b = bool_distribution(rand_engine);
+}
+
+class CompatibilityTest
+    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+ protected:
+  void SetUp() override {
+    proxy_url_ = ::testing::get<0>(GetParam());
+    server_url_ = ::testing::get<1>(GetParam());
+  }
+  std::string proxy_url_;
+  std::string server_url_;
+};
+
+TEST_P(CompatibilityTest, EchoStruct) {
+  RecordProperty("proxy_url", proxy_url_);
+  RecordProperty("server_url", server_url_);
+  Struct sent;
+  Initialize(&sent);
+  fidl::test::compatibility::EchoClientApp app;
+  app.Start(proxy_url_);
+
+  Struct sent_clone;
+  sent.Clone(&sent_clone);
+  Struct resp_clone;
+  app.echo()->EchoStruct(
+      std::move(sent), server_url_,
+      [&resp_clone](Struct resp) {
+        ASSERT_EQ(ZX_OK, resp.Clone(&resp_clone));
+      });
+
+  ASSERT_EQ(ZX_OK, app.echo().WaitForResponse())
+      << "Failed to wait for response from proxy "
+      << files::GetBaseName(proxy_url_) << " and server "
+      << files::GetBaseName(server_url_);
+  ExpectEq(sent_clone, resp_clone);
+}
+
+TEST_P(CompatibilityTest, EchoStructNoRetVal) {
+  RecordProperty("proxy_url", proxy_url_);
+  RecordProperty("server_url", server_url_);
+  Struct sent;
+  Initialize(&sent);
+  fidl::test::compatibility::EchoClientApp app;
+  app.Start(proxy_url_);
+
+  Struct sent_clone;
+  sent.Clone(&sent_clone);
+  std::mutex m;
+  std::condition_variable cv;
+  fidl::test::compatibility::Struct resp_clone;
+  bool event_received = false;
+  app.echo().events().EchoEvent = [&m, &cv, &resp_clone,
+                                   &event_received](Struct resp) {
+    std::unique_lock<std::mutex> lk(m);
+    resp.Clone(&resp_clone);
+    event_received = true;
+    cv.notify_one();
+  };
+  app.echo()->EchoStructNoRetVal(std::move(sent), server_url_);
+  std::unique_lock<std::mutex> lk(m);
+  cv.wait(lk, [&event_received]{ return event_received; });
+  ExpectEq(sent_clone, resp_clone);
+}
+
+// It'd be better to take these on the command-line but googletest doesn't
+// support instantiating tests after main() is called.
+std::vector<std::string> ServerURLsFromEnv() {
+  const char* servers_raw = getenv(kServersEnvVarName);
+  FXL_CHECK(servers_raw != nullptr) << kUsage;
+  std::vector<std::string> servers = fxl::SplitStringCopy(
+      fxl::StringView(servers_raw, strlen(servers_raw)), ",",
+      fxl::WhiteSpaceHandling::kTrimWhitespace,
+      fxl::SplitResult::kSplitWantNonEmpty);
+  FXL_CHECK(!servers.empty()) << kUsage;
+  return servers;
+}
+
+}  // namespace
+
+INSTANTIATE_TEST_CASE_P(
+    CompatibilityTest, CompatibilityTest,
+    ::testing::Combine(::testing::ValuesIn(ServerURLsFromEnv()),
+                       ::testing::ValuesIn(ServerURLsFromEnv())));
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  // The FIDL support lib requires async_get_default() to return non-null.
+  async::Loop loop(&kAsyncLoopConfigMakeDefault);
+  // Start another thread so that one can block while the other handles events.
+  const zx_status_t start_thread_status = loop.StartThread();
+  ZX_ASSERT_MSG(start_thread_status == ZX_OK, "start_thread_status = %d",
+                start_thread_status);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/bin/fidl_compatibility_test/compatibility_test_server_cpp.cc b/bin/fidl_compatibility_test/compatibility_test_server_cpp.cc
index a9971c5..e68768c 100644
--- a/bin/fidl_compatibility_test/compatibility_test_server_cpp.cc
+++ b/bin/fidl_compatibility_test/compatibility_test_server_cpp.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#define FIDL_ENABLE_LEGACY_WAIT_FOR_RESPONSE
+
 #include <fidl/test/compatibility/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <zx/channel.h>
@@ -30,30 +32,57 @@
 
   ~EchoServerApp() {}
 
-  void EchoStruct(Struct value, EchoStructCallback callback) override {
-    fprintf(stderr, "Server received EchoStruct()\n");
-    if (!value.forward_to_server.get().empty()) {
-      const std::string forward_to_server = value.forward_to_server;
-      value.forward_to_server.reset();  // Prevent recursion.
+  void EchoStruct(Struct value, fidl::StringPtr forward_to_server,
+                  EchoStructCallback callback) override {
+    if (!forward_to_server->empty()) {
       EchoClientApp app;
-      app.Start(forward_to_server);
-      app.echo()->EchoStruct(std::move(value), callback);
+      app.Start(forward_to_server.get());
+      app.echo()->EchoStruct(std::move(value), "", callback);
       const zx_status_t wait_status = app.echo().WaitForResponse();
       if (wait_status != ZX_OK) {
         fprintf(stderr, "Proxy Got error %d waiting for response from %s\n",
-                wait_status, forward_to_server.c_str());
+                wait_status, forward_to_server->c_str());
       }
     } else {
       callback(std::move(value));
     }
   }
 
+  void EchoStructNoRetVal(Struct value,
+                          fidl::StringPtr forward_to_server) override {
+    if (!forward_to_server->empty()) {
+      std::unique_ptr<EchoClientApp> app(new EchoClientApp);
+      app->Start(forward_to_server.get());
+      app->echo().events().EchoEvent = [this](Struct resp) {
+        this->HandleEchoEvent(std::move(resp));
+      };
+      app->echo()->EchoStructNoRetVal(std::move(value), "");
+      client_apps_.push_back(std::move(app));
+    } else {
+      for (const auto& binding : bindings_.bindings()) {
+        Struct to_send;
+        value.Clone(&to_send);
+        binding->events().EchoEvent(std::move(to_send));
+      }
+    }
+  }
+
  private:
+  void HandleEchoEvent(Struct value) {
+    for (const auto& binding : bindings_.bindings()) {
+      Struct to_send;
+      value.Clone(&to_send);
+      binding->events().EchoEvent(std::move(to_send));
+    }
+  }
+
+  EchoPtr server_ptr;
   EchoServerApp(const EchoServerApp&) = delete;
   EchoServerApp& operator=(const EchoServerApp&) = delete;
 
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
   fidl::BindingSet<Echo> bindings_;
+  std::vector<std::unique_ptr<EchoClientApp>> client_apps_;
 };
 
 }  // namespace compatibility
diff --git a/bin/fidl_compatibility_test/run_fidl_compatibility_test_garnet.sh b/bin/fidl_compatibility_test/run_fidl_compatibility_test_garnet.sh
new file mode 100644
index 0000000..0c96b35
--- /dev/null
+++ b/bin/fidl_compatibility_test/run_fidl_compatibility_test_garnet.sh
@@ -0,0 +1,4 @@
+#!/boot/bin/sh
+
+export FIDL_COMPATIBILITY_TEST_SERVERS=fidl_compatibility_test_server_cpp
+/pkgfs/packages/fidl_compatibility_test_bin/0/bin/app
diff --git a/bin/guest/cli/BUILD.gn b/bin/guest/cli/BUILD.gn
index e1d2b9e..994f037 100644
--- a/bin/guest/cli/BUILD.gn
+++ b/bin/guest/cli/BUILD.gn
@@ -27,7 +27,7 @@
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/guest/fidl",
     "//garnet/public/lib/svc/cpp",
-    "//garnet/public/lib/ui/presentation/fidl",
+    "//garnet/public/lib/ui/policy/fidl",
     "//garnet/public/lib/ui/views/fidl:v1",
     "//zircon/public/lib/fit",
     "//zircon/public/lib/pretty",
diff --git a/bin/guest/cli/launch.cc b/bin/guest/cli/launch.cc
index bb7d3e0..573d4f8 100644
--- a/bin/guest/cli/launch.cc
+++ b/bin/guest/cli/launch.cc
@@ -6,7 +6,7 @@
 
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/guest/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
 
 #include "garnet/bin/guest/cli/serial.h"
@@ -41,7 +41,7 @@
   view_provider->CreateView(view_owner.NewRequest(), nullptr);
 
   // Ask the presenter to display it.
-  presentation::PresenterSyncPtr presenter;
+  fuchsia::ui::policy::PresenterSyncPtr presenter;
   fuchsia::sys::ConnectToEnvironmentService(presenter.NewRequest());
   presenter->Present(std::move(view_owner), nullptr);
 
diff --git a/bin/guest/cli/serial.cc b/bin/guest/cli/serial.cc
index a050e39..35b4688 100644
--- a/bin/guest/cli/serial.cc
+++ b/bin/guest/cli/serial.cc
@@ -7,7 +7,7 @@
 #include <poll.h>
 #include <iostream>
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <fuchsia/guest/cpp/fidl.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/fit/function.h>
diff --git a/bin/guest/cli/socat.cc b/bin/guest/cli/socat.cc
index e405df5..892cf94 100644
--- a/bin/guest/cli/socat.cc
+++ b/bin/guest/cli/socat.cc
@@ -28,7 +28,7 @@
       return;
     }
     callback(ZX_OK, std::move(h2));
-    console_.Start(std::move(h2));
+    console_.Start(std::move(h1));
   }
 
  private:
diff --git a/bin/network/BUILD.gn b/bin/http/BUILD.gn
similarity index 66%
rename from bin/network/BUILD.gn
rename to bin/http/BUILD.gn
index 2f9adfd..79ad61c 100644
--- a/bin/network/BUILD.gn
+++ b/bin/http/BUILD.gn
@@ -6,9 +6,9 @@
 
 source_set("errors") {
   sources = [
-    "net_error_list.h",
-    "net_errors.cc",
-    "net_errors.h",
+    "http_error_list.h",
+    "http_errors.cc",
+    "http_errors.h",
   ]
 
   deps = [
@@ -21,22 +21,22 @@
   defines = [ "NETWORK_SERVICE_USE_HTTPS" ]
 
   sources = [
+    "http_adapters.cc",
+    "http_adapters.h",
     "http_client.h",
-    "net_adapters.cc",
-    "net_adapters.h",
-    "network_service_delegate.cc",
-    "network_service_delegate.h",
-    "network_service_impl.cc",
-    "network_service_impl.h",
+    "http_service_delegate.cc",
+    "http_service_delegate.h",
+    "http_service_impl.cc",
+    "http_service_impl.h",
+    "http_url_loader_impl.cc",
+    "http_url_loader_impl.h",
     "upload_element_reader.cc",
     "upload_element_reader.h",
-    "url_loader_impl.cc",
-    "url_loader_impl.h",
   ]
 
   deps = [
+    "//garnet/public/lib/net/oldhttp/fidl",
     "//garnet/public/lib/netstack/fidl",
-    "//garnet/public/lib/network/fidl",
     "//garnet/public/lib/url",
     "//third_party/asio",
     "//third_party/boringssl:boringssl",
@@ -48,11 +48,12 @@
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
+    "//zircon/public/lib/fit",
   ]
 }
 
 executable("bin") {
-  output_name = "network"
+  output_name = "http"
 
   sources = [
     "main.cc",
@@ -65,29 +66,29 @@
   ]
 }
 
-package("network") {
+package("http") {
   deps = [
     ":bin",
   ]
 
-  binary = "network"
+  binary = "http"
 
   meta = [
     {
-      path = rebase_path("meta/network.cmx")
-      dest = "network.cmx"
+      path = rebase_path("meta/http.cmx")
+      dest = "http.cmx"
     },
   ]
 }
 
-executable("network_service_tests_bin") {
+executable("http_service_tests_bin") {
   testonly = true
 
   sources = [
     "upload_element_reader_unittest.cc",
   ]
 
-  output_name = "network_service_tests"
+  output_name = "http_service_tests"
 
   deps = [
     ":lib",
@@ -95,17 +96,17 @@
   ]
 }
 
-package("network_service_tests") {
+package("http_service_tests") {
   testonly = true
   deprecated_system_image = true
 
   deps = [
-    ":network_service_tests_bin",
+    ":http_service_tests_bin",
   ]
 
   tests = [
     {
-      name = "network_service_tests"
+      name = "http_service_tests"
     },
   ]
 }
diff --git a/bin/network/MAINTAINERS b/bin/http/MAINTAINERS
similarity index 100%
rename from bin/network/MAINTAINERS
rename to bin/http/MAINTAINERS
diff --git a/bin/network/README.md b/bin/http/README.md
similarity index 90%
rename from bin/network/README.md
rename to bin/http/README.md
index dc2859d..3962d7a 100644
--- a/bin/network/README.md
+++ b/bin/http/README.md
@@ -1,15 +1,15 @@
 # Network
 
 This repository contains the interface and implementation of FIDL
-Network Service.
+HTTP Service.
 
      +-----------+           +-----------+
      | FIDL app  |           | POSIX app |
      +------+----+           +-----+-----+
             |                      |
     +-------v----------------+     |
-    |  FIDL network service  |     |
-    | (//garnet/bin/network) |     |
+    |  FIDL http service     |     |
+    | (//garnet/bin/http)    |     |
     +-------+----------------+     |
             |                      |
       +-----v----------------------v---+
diff --git a/bin/http/http_adapters.cc b/bin/http/http_adapters.cc
new file mode 100644
index 0000000..555d578
--- /dev/null
+++ b/bin/http/http_adapters.cc
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/http/http_adapters.h"
+#include "garnet/bin/http/http_errors.h"
+
+namespace http {
+
+namespace oldhttp = ::fuchsia::net::oldhttp;
+
+oldhttp::HttpErrorPtr MakeHttpError(int error_code) {
+  oldhttp::HttpErrorPtr error = oldhttp::HttpError::New();
+  error->code = error_code;
+  if (error_code <= 0)
+    error->description = ErrorToString(error_code);
+  return error;
+}
+
+}  // namespace http
diff --git a/bin/http/http_adapters.h b/bin/http/http_adapters.h
new file mode 100644
index 0000000..b252755
--- /dev/null
+++ b/bin/http/http_adapters.h
@@ -0,0 +1,17 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_HTTP_HTTP_ADAPTERS_H_
+#define GARNET_BIN_HTTP_HTTP_ADAPTERS_H_
+
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
+
+namespace http {
+
+// Creates a new http error object from a http error code.
+::fuchsia::net::oldhttp::HttpErrorPtr MakeHttpError(int error_code);
+
+}  // namespace http
+
+#endif  // GARNET_BIN_HTTP_HTTP_ADAPTERS_H_
diff --git a/bin/network/http_client.h b/bin/http/http_client.h
similarity index 90%
rename from bin/network/http_client.h
rename to bin/http/http_client.h
index c5fbb56..1b0bd16 100644
--- a/bin/network/http_client.h
+++ b/bin/http/http_client.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef GARNET_BIN_NETWORK_HTTP_CLIENT_H_
-#define GARNET_BIN_NETWORK_HTTP_CLIENT_H_
+#ifndef GARNET_BIN_HTTP_HTTP_NEW_CLIENT_H_
+#define GARNET_BIN_HTTP_HTTP_NEW_CLIENT_H_
 
 #include <zircon/status.h>
 
 #include <set>
 
-#include "garnet/bin/network/net_errors.h"
-#include "garnet/bin/network/upload_element_reader.h"
+#include "garnet/bin/http/http_errors.h"
+#include "garnet/bin/http/upload_element_reader.h"
 #include "lib/fsl/vmo/sized_vmo.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/strings/ascii.h"
@@ -20,7 +20,7 @@
 
 using asio::ip::tcp;
 
-namespace network {
+namespace http {
 
 typedef asio::ssl::stream<tcp::socket> ssl_socket_t;
 typedef tcp::socket nonssl_socket_t;
@@ -47,7 +47,7 @@
       const std::string& path,
       const std::string& method,
       const std::map<std::string, std::string>& extra_headers,
-      std::unique_ptr<UploadElementReader> request_body_reader);
+      std::unique_ptr<http::UploadElementReader> request_body_reader);
   void Start(const std::string& server, const std::string& port);
 
  private:
@@ -74,7 +74,7 @@
   void OnStreamBody(const asio::error_code& err);
   void OnBufferBody(const asio::error_code& err);
 
-  void SendResponse(URLResponse response);
+  void SendResponse(::fuchsia::net::oldhttp::URLResponse response);
   void SendError(int error_code);
 
  public:
@@ -87,7 +87,7 @@
   tcp::resolver resolver_;
   T socket_;
   asio::streambuf request_header_buf_;
-  std::unique_ptr<UploadElementReader> request_body_reader_;
+  std::unique_ptr<http::UploadElementReader> request_body_reader_;
   asio::streambuf request_body_buf_;
   std::ostream request_body_stream_;
   asio::streambuf response_buf_;
@@ -95,7 +95,7 @@
   std::string http_version_;
   std::string status_message_;
 
-  URLResponse response_;             // used for buffered responses
+  ::fuchsia::net::oldhttp::URLResponse response_;  // used for buffered responses
   zx::socket response_body_stream_;  // used for streamed responses (default)
 };
 
@@ -148,7 +148,7 @@
     const std::string& path,
     const std::string& method,
     const std::map<std::string, std::string>& extra_headers,
-    std::unique_ptr<UploadElementReader> request_body_reader) {
+    std::unique_ptr<http::UploadElementReader> request_body_reader) {
   if (!IsMethodAllowed(method)) {
     FXL_VLOG(1) << "Method " << method << " is not allowed";
     return ZX_ERR_INVALID_ARGS;
@@ -178,7 +178,7 @@
     if (request_body_reader_->err() != ZX_OK) {
       return request_body_reader_->err();
     }
-    if (content_length != UploadElementReader::kUnknownSize) {
+    if (content_length != http::UploadElementReader::kUnknownSize) {
       request_header_stream << "Content-Length: " << content_length << "\r\n";
     }
   }
@@ -226,7 +226,7 @@
                                   std::placeholders::_1));
   } else {
     FXL_VLOG(1) << "Resolve(SSL): " << err.message();
-    SendError(network::NETWORK_ERR_NAME_NOT_RESOLVED);
+    SendError(HTTP_ERR_NAME_NOT_RESOLVED);
   }
 }
 
@@ -240,7 +240,7 @@
                                   std::placeholders::_1));
   } else {
     FXL_VLOG(1) << "Resolve(NonSSL): " << err.message();
-    SendError(network::NETWORK_ERR_NAME_NOT_RESOLVED);
+    SendError(HTTP_ERR_NAME_NOT_RESOLVED);
   }
 }
 
@@ -269,7 +269,7 @@
                                       this, std::placeholders::_1));
   } else {
     FXL_VLOG(1) << "Connect(SSL): " << err.message();
-    SendError(network::NETWORK_ERR_CONNECTION_FAILED);
+    SendError(HTTP_ERR_CONNECTION_FAILED);
   }
 }
 
@@ -283,7 +283,7 @@
                   std::placeholders::_1, std::placeholders::_2));
   } else {
     FXL_VLOG(1) << "Connect(NonSSL): " << err.message();
-    SendError(network::NETWORK_ERR_CONNECTION_FAILED);
+    SendError(HTTP_ERR_CONNECTION_FAILED);
   }
 }
 
@@ -295,7 +295,7 @@
                                 std::placeholders::_1, std::placeholders::_2));
   } else {
     FXL_VLOG(1) << "HandShake: " << err.message();
-    SendError(network::NETWORK_ERR_SSL_HANDSHAKE_NOT_COMPLETED);
+    SendError(HTTP_ERR_SSL_HANDSHAKE_NOT_COMPLETED);
   }
 }
 
@@ -317,7 +317,7 @@
   } else {
     FXL_VLOG(1) << "WriteRequestHeaders: " << err.message();
     // TODO(toshik): better error code?
-    SendError(network::NETWORK_ERR_FAILED);
+    SendError(HTTP_ERR_FAILED);
   }
 }
 
@@ -330,7 +330,7 @@
                       std::bind(&HTTPClient<T>::OnWriteRequestBody, this,
                                 std::placeholders::_1, std::placeholders::_2));
   } else if (request_body_reader_ && request_body_reader_->err() != ZX_OK) {
-    SendError(network::NETWORK_ERR_FAILED);
+    SendError(HTTP_ERR_FAILED);
   } else {
     // TODO(toshik): The response_ streambuf will automatically grow
     // The growth may be limited by passing a maximum size to the
@@ -351,7 +351,7 @@
   } else {
     FXL_VLOG(1) << "WriteRequestBody: " << err.message();
     // TODO(toshik): better error code?
-    SendError(network::NETWORK_ERR_FAILED);
+    SendError(HTTP_ERR_FAILED);
   }
 }
 
@@ -366,7 +366,7 @@
     std::getline(response_stream, status_message_);
     if (!response_stream || http_version_.substr(0, 5) != "HTTP/") {
       FXL_VLOG(1) << "ReadStatusLine: Invalid response\n";
-      SendError(network::NETWORK_ERR_INVALID_RESPONSE);
+      SendError(HTTP_ERR_INVALID_RESPONSE);
       return;
     }
     // TODO(toshik): we don't treat any status code as an NETWORK_ERR for now
@@ -451,11 +451,11 @@
       done += todo;
     } while (done < size);
 
-    if (loader_->response_body_mode_ == ResponseBodyMode::BUFFER) {
+    if (loader_->response_body_mode_ == ::fuchsia::net::oldhttp::ResponseBodyMode::BUFFER) {
       response_.body->set_buffer(std::move(vmo));
     } else {
       FXL_DCHECK(loader_->response_body_mode_ ==
-                 ResponseBodyMode::SIZED_BUFFER);
+                 ::fuchsia::net::oldhttp::ResponseBodyMode::SIZED_BUFFER);
       response_.body->set_sized_buffer(
           fsl::SizedVmo(std::move(vmo), size).ToTransport());
     }
@@ -488,7 +488,8 @@
       redirect_location_.clear();
 
       while (std::getline(response_stream, header) && header != "\r") {
-        HttpHeaderPtr hdr = HttpHeader::New();
+        ::fuchsia::net::oldhttp::HttpHeaderPtr hdr =
+            ::fuchsia::net::oldhttp::HttpHeader::New();
         std::string name, value;
         ParseHeaderField(header, &name, &value);
         if (name == "Location") {
@@ -497,14 +498,14 @@
         }
       }
     } else {
-      URLResponse response;
+      ::fuchsia::net::oldhttp::URLResponse response;
       response.status_code = status_code_;
       response.status_line =
           http_version_ + " " + std::to_string(status_code_) + status_message_;
       response.url = loader_->current_url_.spec();
 
       while (std::getline(response_stream, header) && header != "\r") {
-        HttpHeader hdr;
+        ::fuchsia::net::oldhttp::HttpHeader hdr;
         std::string name, value;
         ParseHeaderField(header, &name, &value);
         hdr.name = std::move(name);
@@ -512,19 +513,19 @@
         response.headers.push_back(std::move(hdr));
       }
 
-      response.body = std::make_unique<network::URLBody>();
+      response.body = std::make_unique<::fuchsia::net::oldhttp::URLBody>();
 
       switch (loader_->response_body_mode_) {
-        case ResponseBodyMode::BUFFER:
-        case ResponseBodyMode::SIZED_BUFFER:
+        case ::fuchsia::net::oldhttp::ResponseBodyMode::BUFFER:
+        case ::fuchsia::net::oldhttp::ResponseBodyMode::SIZED_BUFFER:
           response_ = std::move(response);
 
           asio::async_read(socket_, response_buf_,
                            std::bind(&HTTPClient<T>::OnBufferBody, this,
                                      std::placeholders::_1));
           break;
-        case ResponseBodyMode::STREAM:
-        case ResponseBodyMode::BUFFER_OR_STREAM:
+        case ::fuchsia::net::oldhttp::ResponseBodyMode::STREAM:
+        case ::fuchsia::net::oldhttp::ResponseBodyMode::BUFFER_OR_STREAM:
           zx::socket consumer;
           zx::socket producer;
           zx_status_t status = zx::socket::create(0u, &producer, &consumer);
@@ -563,7 +564,7 @@
     // Content-Length header).
     FXL_VLOG(1) << "OnBufferBody: " << err.message() << " (" << err << ")";
     // TODO(somebody who knows asio/network errors): real translation
-    SendError(network::NETWORK_ERR_FAILED);
+    SendError(HTTP_ERR_FAILED);
   } else {
     SendBufferedBody();
     loader_->SendResponse(std::move(response_));
@@ -585,7 +586,8 @@
 }
 
 template <typename T>
-void URLLoaderImpl::HTTPClient<T>::SendResponse(URLResponse response) {
+void URLLoaderImpl::HTTPClient<T>::SendResponse(
+        ::fuchsia::net::oldhttp::URLResponse response) {
   loader_->SendResponse(std::move(response));
 }
 
@@ -594,7 +596,7 @@
   loader_->SendError(error_code);
 }
 
-}  // namespace network
+}  // namespace http
 
 #if defined(ASIO_NO_EXCEPTIONS)
 // If C++ exception is disabled, ASIO calls this function instead of throwing
@@ -608,4 +610,4 @@
 }
 #endif
 
-#endif  // GARNET_BIN_NETWORK_HTTP_CLIENT_H_
+#endif  // GARNET_BIN_HTTP_HTTP_NEW_CLIENT_H_
diff --git a/bin/network/net_error_list.h b/bin/http/http_error_list.h
similarity index 70%
rename from bin/network/net_error_list.h
rename to bin/http/http_error_list.h
index 4eca642..502860d 100644
--- a/bin/network/net_error_list.h
+++ b/bin/http/http_error_list.h
@@ -5,7 +5,7 @@
 // This file intentionally does not have header guards, it's included
 // inside a macro to generate enum values.
 
-// This file contains the list of network errors.
+// This file contains the list of http errors.
 
 //
 // Ranges:
@@ -23,235 +23,235 @@
 // indicate a fatal error.  Typically this error will be generated as a
 // notification to wait for some external notification that the IO operation
 // finally completed.
-NET_ERROR(IO_PENDING, -1)
+HTTP_ERROR(IO_PENDING, -1)
 
 // A generic failure occurred.
-NET_ERROR(FAILED, -2)
+HTTP_ERROR(FAILED, -2)
 
 // An operation was aborted (due to user action).
-NET_ERROR(ABORTED, -3)
+HTTP_ERROR(ABORTED, -3)
 
 // An argument to the function is incorrect.
-NET_ERROR(INVALID_ARGUMENT, -4)
+HTTP_ERROR(INVALID_ARGUMENT, -4)
 
 // The handle or file descriptor is invalid.
-NET_ERROR(INVALID_HANDLE, -5)
+HTTP_ERROR(INVALID_HANDLE, -5)
 
 // The file or directory cannot be found.
-NET_ERROR(FILE_NOT_FOUND, -6)
+HTTP_ERROR(FILE_NOT_FOUND, -6)
 
 // An operation timed out.
-NET_ERROR(TIMED_OUT, -7)
+HTTP_ERROR(TIMED_OUT, -7)
 
 // The file is too large.
-NET_ERROR(FILE_TOO_BIG, -8)
+HTTP_ERROR(FILE_TOO_BIG, -8)
 
 // An unexpected error.  This may be caused by a programming mistake or an
 // invalid assumption.
-NET_ERROR(UNEXPECTED, -9)
+HTTP_ERROR(UNEXPECTED, -9)
 
 // Permission to access a resource, other than the network, was denied.
-NET_ERROR(ACCESS_DENIED, -10)
+HTTP_ERROR(ACCESS_DENIED, -10)
 
 // The operation failed because of unimplemented functionality.
-NET_ERROR(NOT_IMPLEMENTED, -11)
+HTTP_ERROR(NOT_IMPLEMENTED, -11)
 
 // There were not enough resources to complete the operation.
-NET_ERROR(INSUFFICIENT_RESOURCES, -12)
+HTTP_ERROR(INSUFFICIENT_RESOURCES, -12)
 
 // Memory allocation failed.
-NET_ERROR(OUT_OF_MEMORY, -13)
+HTTP_ERROR(OUT_OF_MEMORY, -13)
 
 // The file upload failed because the file's modification time was different
 // from the expectation.
-NET_ERROR(UPLOAD_FILE_CHANGED, -14)
+HTTP_ERROR(UPLOAD_FILE_CHANGED, -14)
 
 // The socket is not connected.
-NET_ERROR(SOCKET_NOT_CONNECTED, -15)
+HTTP_ERROR(SOCKET_NOT_CONNECTED, -15)
 
 // The file already exists.
-NET_ERROR(FILE_EXISTS, -16)
+HTTP_ERROR(FILE_EXISTS, -16)
 
 // The path or file name is too long.
-NET_ERROR(FILE_PATH_TOO_LONG, -17)
+HTTP_ERROR(FILE_PATH_TOO_LONG, -17)
 
 // Not enough room left on the disk.
-NET_ERROR(FILE_NO_SPACE, -18)
+HTTP_ERROR(FILE_NO_SPACE, -18)
 
 // The file has a virus.
-NET_ERROR(FILE_VIRUS_INFECTED, -19)
+HTTP_ERROR(FILE_VIRUS_INFECTED, -19)
 
 // The client chose to block the request.
-NET_ERROR(BLOCKED_BY_CLIENT, -20)
+HTTP_ERROR(BLOCKED_BY_CLIENT, -20)
 
 // The network changed.
-NET_ERROR(NETWORK_CHANGED, -21)
+HTTP_ERROR(NETWORK_CHANGED, -21)
 
 // The request was blocked by the URL blacklist configured by the domain
 // administrator.
-NET_ERROR(BLOCKED_BY_ADMINISTRATOR, -22)
+HTTP_ERROR(BLOCKED_BY_ADMINISTRATOR, -22)
 
 // The socket is already connected.
-NET_ERROR(SOCKET_IS_CONNECTED, -23)
+HTTP_ERROR(SOCKET_IS_CONNECTED, -23)
 
 // The request was blocked because the forced reenrollment check is still
 // pending. This error can only occur on ChromeOS.
 // The error can be emitted by code in chrome/browser/policy/policy_helpers.cc.
-NET_ERROR(BLOCKED_ENROLLMENT_CHECK_PENDING, -24)
+HTTP_ERROR(BLOCKED_ENROLLMENT_CHECK_PENDING, -24)
 
 // The upload failed because the upload stream needed to be re-read, due to a
 // retry or a redirect, but the upload stream doesn't support that operation.
-NET_ERROR(UPLOAD_STREAM_REWIND_NOT_SUPPORTED, -25)
+HTTP_ERROR(UPLOAD_STREAM_REWIND_NOT_SUPPORTED, -25)
 
 // The request failed because the URLRequestContext is shutting down, or has
 // been shut down.
-NET_ERROR(CONTEXT_SHUT_DOWN, -26)
+HTTP_ERROR(CONTEXT_SHUT_DOWN, -26)
 
 // A connection was closed (corresponding to a TCP FIN).
-NET_ERROR(CONNECTION_CLOSED, -100)
+HTTP_ERROR(CONNECTION_CLOSED, -100)
 
 // A connection was reset (corresponding to a TCP RST).
-NET_ERROR(CONNECTION_RESET, -101)
+HTTP_ERROR(CONNECTION_RESET, -101)
 
 // A connection attempt was refused.
-NET_ERROR(CONNECTION_REFUSED, -102)
+HTTP_ERROR(CONNECTION_REFUSED, -102)
 
 // A connection timed out as a result of not receiving an ACK for data sent.
 // This can include a FIN packet that did not get ACK'd.
-NET_ERROR(CONNECTION_ABORTED, -103)
+HTTP_ERROR(CONNECTION_ABORTED, -103)
 
 // A connection attempt failed.
-NET_ERROR(CONNECTION_FAILED, -104)
+HTTP_ERROR(CONNECTION_FAILED, -104)
 
 // The host name could not be resolved.
-NET_ERROR(NAME_NOT_RESOLVED, -105)
+HTTP_ERROR(NAME_NOT_RESOLVED, -105)
 
 // The Internet connection has been lost.
-NET_ERROR(INTERNET_DISCONNECTED, -106)
+HTTP_ERROR(INTERNET_DISCONNECTED, -106)
 
 // An SSL protocol error occurred.
-NET_ERROR(SSL_PROTOCOL_ERROR, -107)
+HTTP_ERROR(SSL_PROTOCOL_ERROR, -107)
 
 // The IP address or port number is invalid (e.g., cannot connect to the IP
 // address 0 or the port 0).
-NET_ERROR(ADDRESS_INVALID, -108)
+HTTP_ERROR(ADDRESS_INVALID, -108)
 
 // The IP address is unreachable.  This usually means that there is no route to
 // the specified host or network.
-NET_ERROR(ADDRESS_UNREACHABLE, -109)
+HTTP_ERROR(ADDRESS_UNREACHABLE, -109)
 
 // The server requested a client certificate for SSL client authentication.
-NET_ERROR(SSL_CLIENT_AUTH_CERT_NEEDED, -110)
+HTTP_ERROR(SSL_CLIENT_AUTH_CERT_NEEDED, -110)
 
 // A tunnel connection through the proxy could not be established.
-NET_ERROR(TUNNEL_CONNECTION_FAILED, -111)
+HTTP_ERROR(TUNNEL_CONNECTION_FAILED, -111)
 
 // No SSL protocol versions are enabled.
-NET_ERROR(NO_SSL_VERSIONS_ENABLED, -112)
+HTTP_ERROR(NO_SSL_VERSIONS_ENABLED, -112)
 
 // The client and server don't support a common SSL protocol version or
 // cipher suite.
-NET_ERROR(SSL_VERSION_OR_CIPHER_MISMATCH, -113)
+HTTP_ERROR(SSL_VERSION_OR_CIPHER_MISMATCH, -113)
 
 // The server requested a renegotiation (rehandshake).
-NET_ERROR(SSL_RENEGOTIATION_REQUESTED, -114)
+HTTP_ERROR(SSL_RENEGOTIATION_REQUESTED, -114)
 
 // The proxy requested authentication (for tunnel establishment) with an
 // unsupported method.
-NET_ERROR(PROXY_AUTH_UNSUPPORTED, -115)
+HTTP_ERROR(PROXY_AUTH_UNSUPPORTED, -115)
 
 // During SSL renegotiation (rehandshake), the server sent a certificate with
 // an error.
 //
 // Note: this error is not in the -2xx range so that it won't be handled as a
 // certificate error.
-NET_ERROR(CERT_ERROR_IN_SSL_RENEGOTIATION, -116)
+HTTP_ERROR(CERT_ERROR_IN_SSL_RENEGOTIATION, -116)
 
 // The SSL handshake failed because of a bad or missing client certificate.
-NET_ERROR(BAD_SSL_CLIENT_AUTH_CERT, -117)
+HTTP_ERROR(BAD_SSL_CLIENT_AUTH_CERT, -117)
 
 // A connection attempt timed out.
-NET_ERROR(CONNECTION_TIMED_OUT, -118)
+HTTP_ERROR(CONNECTION_TIMED_OUT, -118)
 
 // There are too many pending DNS resolves, so a request in the queue was
 // aborted.
-NET_ERROR(HOST_RESOLVER_QUEUE_TOO_LARGE, -119)
+HTTP_ERROR(HOST_RESOLVER_QUEUE_TOO_LARGE, -119)
 
 // Failed establishing a connection to the SOCKS proxy server for a target host.
-NET_ERROR(SOCKS_CONNECTION_FAILED, -120)
+HTTP_ERROR(SOCKS_CONNECTION_FAILED, -120)
 
 // The SOCKS proxy server failed establishing connection to the target host
 // because that host is unreachable.
-NET_ERROR(SOCKS_CONNECTION_HOST_UNREACHABLE, -121)
+HTTP_ERROR(SOCKS_CONNECTION_HOST_UNREACHABLE, -121)
 
 // The request to negotiate an alternate protocol failed.
-NET_ERROR(NPN_NEGOTIATION_FAILED, -122)
+HTTP_ERROR(NPN_NEGOTIATION_FAILED, -122)
 
 // The peer sent an SSL no_renegotiation alert message.
-NET_ERROR(SSL_NO_RENEGOTIATION, -123)
+HTTP_ERROR(SSL_NO_RENEGOTIATION, -123)
 
 // Winsock sometimes reports more data written than passed.  This is probably
 // due to a broken LSP.
-NET_ERROR(WINSOCK_UNEXPECTED_WRITTEN_BYTES, -124)
+HTTP_ERROR(WINSOCK_UNEXPECTED_WRITTEN_BYTES, -124)
 
 // An SSL peer sent us a fatal decompression_failure alert. This typically
 // occurs when a peer selects DEFLATE compression in the mistaken belief that
 // it supports it.
-NET_ERROR(SSL_DECOMPRESSION_FAILURE_ALERT, -125)
+HTTP_ERROR(SSL_DECOMPRESSION_FAILURE_ALERT, -125)
 
 // An SSL peer sent us a fatal bad_record_mac alert. This has been observed
 // from servers with buggy DEFLATE support.
-NET_ERROR(SSL_BAD_RECORD_MAC_ALERT, -126)
+HTTP_ERROR(SSL_BAD_RECORD_MAC_ALERT, -126)
 
 // The proxy requested authentication (for tunnel establishment).
-NET_ERROR(PROXY_AUTH_REQUESTED, -127)
+HTTP_ERROR(PROXY_AUTH_REQUESTED, -127)
 
 // A known TLS strict server didn't offer the renegotiation extension.
-NET_ERROR(SSL_UNSAFE_NEGOTIATION, -128)
+HTTP_ERROR(SSL_UNSAFE_NEGOTIATION, -128)
 
 // The SSL server attempted to use a weak ephemeral Diffie-Hellman key.
-NET_ERROR(SSL_WEAK_SERVER_EPHEMERAL_DH_KEY, -129)
+HTTP_ERROR(SSL_WEAK_SERVER_EPHEMERAL_DH_KEY, -129)
 
 // Could not create a connection to the proxy server. An error occurred
 // either in resolving its name, or in connecting a socket to it.
 // Note that this does NOT include failures during the actual "CONNECT" method
 // of an HTTP proxy.
-NET_ERROR(PROXY_CONNECTION_FAILED, -130)
+HTTP_ERROR(PROXY_CONNECTION_FAILED, -130)
 
 // A mandatory proxy configuration could not be used. Currently this means
 // that a mandatory PAC script could not be fetched, parsed or executed.
-NET_ERROR(MANDATORY_PROXY_CONFIGURATION_FAILED, -131)
+HTTP_ERROR(MANDATORY_PROXY_CONFIGURATION_FAILED, -131)
 
 // -132 was formerly ERR_ESET_ANTI_VIRUS_SSL_INTERCEPTION
 
 // We've hit the max socket limit for the socket pool while preconnecting.  We
 // don't bother trying to preconnect more sockets.
-NET_ERROR(PRECONNECT_MAX_SOCKET_LIMIT, -133)
+HTTP_ERROR(PRECONNECT_MAX_SOCKET_LIMIT, -133)
 
 // The permission to use the SSL client certificate's private key was denied.
-NET_ERROR(SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED, -134)
+HTTP_ERROR(SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED, -134)
 
 // The SSL client certificate has no private key.
-NET_ERROR(SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY, -135)
+HTTP_ERROR(SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY, -135)
 
 // The certificate presented by the HTTPS Proxy was invalid.
-NET_ERROR(PROXY_CERTIFICATE_INVALID, -136)
+HTTP_ERROR(PROXY_CERTIFICATE_INVALID, -136)
 
 // An error occurred when trying to do a name resolution (DNS).
-NET_ERROR(NAME_RESOLUTION_FAILED, -137)
+HTTP_ERROR(NAME_RESOLUTION_FAILED, -137)
 
 // Permission to access the network was denied. This is used to distinguish
 // errors that were most likely caused by a firewall from other access denied
 // errors. See also ZX_ERR_ACCESS_DENIED.
-NET_ERROR(NETWORK_ACCESS_DENIED, -138)
+HTTP_ERROR(NETWORK_ACCESS_DENIED, -138)
 
 // The request throttler module cancelled this request to avoid DDOS.
-NET_ERROR(TEMPORARILY_THROTTLED, -139)
+HTTP_ERROR(TEMPORARILY_THROTTLED, -139)
 
 // A request to create an SSL tunnel connection through the HTTPS proxy
 // received a non-200 (OK) and non-407 (Proxy Auth) response.  The response
 // body might include a description of why the request failed.
-NET_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140)
+HTTP_ERROR(HTTPS_PROXY_TUNNEL_RESPONSE, -140)
 
 // We were unable to sign the CertificateVerify data of an SSL client auth
 // handshake with the client certificate's private key.
@@ -260,95 +260,95 @@
 // denying access to the private key, the private key may not be valid for
 // signing, the key may be relying on a cached handle which is no longer
 // valid, or the CSP won't allow arbitrary data to be signed.
-NET_ERROR(SSL_CLIENT_AUTH_SIGNATURE_FAILED, -141)
+HTTP_ERROR(SSL_CLIENT_AUTH_SIGNATURE_FAILED, -141)
 
 // The message was too large for the transport.  (for example a UDP message
 // which exceeds size threshold).
-NET_ERROR(MSG_TOO_BIG, -142)
+HTTP_ERROR(MSG_TOO_BIG, -142)
 
 // A SPDY session already exists, and should be used instead of this connection.
-NET_ERROR(SPDY_SESSION_ALREADY_EXISTS, -143)
+HTTP_ERROR(SPDY_SESSION_ALREADY_EXISTS, -143)
 
 // Error -144 was removed (LIMIT_VIOLATION).
 
 // Websocket protocol error. Indicates that we are terminating the connection
 // due to a malformed frame or other protocol violation.
-NET_ERROR(WS_PROTOCOL_ERROR, -145)
+HTTP_ERROR(WS_PROTOCOL_ERROR, -145)
 
 // Error -146 was removed (PROTOCOL_SWITCHED)
 
 // Returned when attempting to bind an address that is already in use.
-NET_ERROR(ADDRESS_IN_USE, -147)
+HTTP_ERROR(ADDRESS_IN_USE, -147)
 
 // An operation failed because the SSL handshake has not completed.
-NET_ERROR(SSL_HANDSHAKE_NOT_COMPLETED, -148)
+HTTP_ERROR(SSL_HANDSHAKE_NOT_COMPLETED, -148)
 
 // SSL peer's public key is invalid.
-NET_ERROR(SSL_BAD_PEER_PUBLIC_KEY, -149)
+HTTP_ERROR(SSL_BAD_PEER_PUBLIC_KEY, -149)
 
 // The certificate didn't match the built-in public key pins for the host name.
 // The pins are set in net/http/transport_security_state.cc and require that
 // one of a set of public keys exist on the path from the leaf to the root.
-NET_ERROR(SSL_PINNED_KEY_NOT_IN_CERT_CHAIN, -150)
+HTTP_ERROR(SSL_PINNED_KEY_NOT_IN_CERT_CHAIN, -150)
 
 // Server request for client certificate did not contain any types we support.
-NET_ERROR(CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, -151)
+HTTP_ERROR(CLIENT_AUTH_CERT_TYPE_UNSUPPORTED, -151)
 
 // Server requested one type of cert, then requested a different type while the
 // first was still being generated.
-NET_ERROR(ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH, -152)
+HTTP_ERROR(ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH, -152)
 
 // An SSL peer sent us a fatal decrypt_error alert. This typically occurs when
 // a peer could not correctly verify a signature (in CertificateVerify or
 // ServerKeyExchange) or validate a Finished message.
-NET_ERROR(SSL_DECRYPT_ERROR_ALERT, -153)
+HTTP_ERROR(SSL_DECRYPT_ERROR_ALERT, -153)
 
 // There are too many pending WebSocketJob instances, so the new job was not
 // pushed to the queue.
-NET_ERROR(WS_THROTTLE_QUEUE_TOO_LARGE, -154)
+HTTP_ERROR(WS_THROTTLE_QUEUE_TOO_LARGE, -154)
 
 // Error -155 was removed (TOO_MANY_SOCKET_STREAMS)
 
 // The SSL server certificate changed in a renegotiation.
-NET_ERROR(SSL_SERVER_CERT_CHANGED, -156)
+HTTP_ERROR(SSL_SERVER_CERT_CHANGED, -156)
 
 // The SSL server indicated that an unnecessary TLS version fallback was
 // performed.
-NET_ERROR(SSL_INAPPROPRIATE_FALLBACK, -157)
+HTTP_ERROR(SSL_INAPPROPRIATE_FALLBACK, -157)
 
 // Certificate Transparency: All Signed Certificate Timestamps failed to verify.
-NET_ERROR(CT_NO_SCTS_VERIFIED_OK, -158)
+HTTP_ERROR(CT_NO_SCTS_VERIFIED_OK, -158)
 
 // The SSL server sent us a fatal unrecognized_name alert.
-NET_ERROR(SSL_UNRECOGNIZED_NAME_ALERT, -159)
+HTTP_ERROR(SSL_UNRECOGNIZED_NAME_ALERT, -159)
 
 // Failed to set the socket's receive buffer size as requested.
-NET_ERROR(SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR, -160)
+HTTP_ERROR(SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR, -160)
 
 // Failed to set the socket's send buffer size as requested.
-NET_ERROR(SOCKET_SET_SEND_BUFFER_SIZE_ERROR, -161)
+HTTP_ERROR(SOCKET_SET_SEND_BUFFER_SIZE_ERROR, -161)
 
 // Failed to set the socket's receive buffer size as requested, despite success
 // return code from setsockopt.
-NET_ERROR(SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE, -162)
+HTTP_ERROR(SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE, -162)
 
 // Failed to set the socket's send buffer size as requested, despite success
 // return code from setsockopt.
-NET_ERROR(SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE, -163)
+HTTP_ERROR(SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE, -163)
 
 // Failed to import a client certificate from the platform store into the SSL
 // library.
-NET_ERROR(SSL_CLIENT_AUTH_CERT_BAD_FORMAT, -164)
+HTTP_ERROR(SSL_CLIENT_AUTH_CERT_BAD_FORMAT, -164)
 
 // The SSL server requires falling back to a version older than the configured
 // minimum fallback version, and thus fallback failed.
-NET_ERROR(SSL_FALLBACK_BEYOND_MINIMUM_VERSION, -165)
+HTTP_ERROR(SSL_FALLBACK_BEYOND_MINIMUM_VERSION, -165)
 
 // Resolving a hostname to an IP address list included the IPv4 address
 // "127.0.53.53". This is a special IP address which ICANN has recommended to
 // indicate there was a name collision, and alert admins to a potential
 // problem.
-NET_ERROR(ICANN_NAME_COLLISION, -166)
+HTTP_ERROR(ICANN_NAME_COLLISION, -166)
 
 // Certificate error codes
 //
@@ -368,7 +368,7 @@
 // 4. The OS has used a DNS search suffix and the server doesn't have
 //    a certificate for the abbreviated name in the address bar.
 //
-NET_ERROR(CERT_COMMON_NAME_INVALID, -200)
+HTTP_ERROR(CERT_COMMON_NAME_INVALID, -200)
 
 // The server responded with a certificate that, by our clock, appears to
 // either not yet be valid or to have expired.  This could mean:
@@ -380,7 +380,7 @@
 //
 // 3. Our clock is wrong.
 //
-NET_ERROR(CERT_DATE_INVALID, -201)
+HTTP_ERROR(CERT_DATE_INVALID, -201)
 
 // The server responded with a certificate that is signed by an authority
 // we don't trust.  The could mean:
@@ -394,7 +394,7 @@
 // 3. The server is presenting a self-signed certificate, providing no
 //    defense against active attackers (but foiling passive attackers).
 //
-NET_ERROR(CERT_AUTHORITY_INVALID, -202)
+HTTP_ERROR(CERT_AUTHORITY_INVALID, -202)
 
 // The server responded with a certificate that contains errors.
 // This error is not recoverable.
@@ -404,11 +404,11 @@
 // NOTE: It's unclear how this differs from ERR_CERT_INVALID. For consistency,
 // use that code instead of this one from now on.
 //
-NET_ERROR(CERT_CONTAINS_ERRORS, -203)
+HTTP_ERROR(CERT_CONTAINS_ERRORS, -203)
 
 // The certificate has no mechanism for determining if it is revoked.  In
 // effect, this certificate cannot be revoked.
-NET_ERROR(CERT_NO_REVOCATION_MECHANISM, -204)
+HTTP_ERROR(CERT_NO_REVOCATION_MECHANISM, -204)
 
 // Revocation information for the security certificate for this site is not
 // available.  This could mean:
@@ -419,12 +419,12 @@
 // 2. The certificate is unrevoked, but the revocation server is busy or
 //    unavailable.
 //
-NET_ERROR(CERT_UNABLE_TO_CHECK_REVOCATION, -205)
+HTTP_ERROR(CERT_UNABLE_TO_CHECK_REVOCATION, -205)
 
 // The server responded with a certificate has been revoked.
 // We have the capability to ignore this error, but it is probably not the
 // thing to do.
-NET_ERROR(CERT_REVOKED, -206)
+HTTP_ERROR(CERT_REVOKED, -206)
 
 // The server responded with a certificate that is invalid.
 // This error is not recoverable.
@@ -432,26 +432,26 @@
 // MSDN describes this error as follows:
 //   "The SSL certificate is invalid."
 //
-NET_ERROR(CERT_INVALID, -207)
+HTTP_ERROR(CERT_INVALID, -207)
 
 // The server responded with a certificate that is signed using a weak
 // signature algorithm.
-NET_ERROR(CERT_WEAK_SIGNATURE_ALGORITHM, -208)
+HTTP_ERROR(CERT_WEAK_SIGNATURE_ALGORITHM, -208)
 
 // -209 is availible: was CERT_NOT_IN_DNS.
 
 // The host name specified in the certificate is not unique.
-NET_ERROR(CERT_NON_UNIQUE_NAME, -210)
+HTTP_ERROR(CERT_NON_UNIQUE_NAME, -210)
 
 // The server responded with a certificate that contains a weak key (e.g.
 // a too-small RSA key).
-NET_ERROR(CERT_WEAK_KEY, -211)
+HTTP_ERROR(CERT_WEAK_KEY, -211)
 
 // The certificate claimed DNS names that are in violation of name constraints.
-NET_ERROR(CERT_NAME_CONSTRAINT_VIOLATION, -212)
+HTTP_ERROR(CERT_NAME_CONSTRAINT_VIOLATION, -212)
 
 // The certificate's validity period is too long.
-NET_ERROR(CERT_VALIDITY_TOO_LONG, -213)
+HTTP_ERROR(CERT_VALIDITY_TOO_LONG, -213)
 
 // Add new certificate error codes here.
 //
@@ -459,327 +459,327 @@
 // code.
 
 // The value immediately past the last certificate error code.
-NET_ERROR(CERT_END, -214)
+HTTP_ERROR(CERT_END, -214)
 
 // The URL is invalid.
-NET_ERROR(INVALID_URL, -300)
+HTTP_ERROR(INVALID_URL, -300)
 
 // The scheme of the URL is disallowed.
-NET_ERROR(DISALLOWED_URL_SCHEME, -301)
+HTTP_ERROR(DISALLOWED_URL_SCHEME, -301)
 
 // The scheme of the URL is unknown.
-NET_ERROR(UNKNOWN_URL_SCHEME, -302)
+HTTP_ERROR(UNKNOWN_URL_SCHEME, -302)
 
 // Attempting to load an URL resulted in too many redirects.
-NET_ERROR(TOO_MANY_REDIRECTS, -310)
+HTTP_ERROR(TOO_MANY_REDIRECTS, -310)
 
 // Attempting to load an URL resulted in an unsafe redirect (e.g., a redirect
 // to file:// is considered unsafe).
-NET_ERROR(UNSAFE_REDIRECT, -311)
+HTTP_ERROR(UNSAFE_REDIRECT, -311)
 
 // Attempting to load an URL with an unsafe port number.  These are port
 // numbers that correspond to services, which are not robust to spurious input
 // that may be constructed as a result of an allowed web construct (e.g., HTTP
 // looks a lot like SMTP, so form submission to port 25 is denied).
-NET_ERROR(UNSAFE_PORT, -312)
+HTTP_ERROR(UNSAFE_PORT, -312)
 
 // The server's response was invalid.
-NET_ERROR(INVALID_RESPONSE, -320)
+HTTP_ERROR(INVALID_RESPONSE, -320)
 
 // Error in chunked transfer encoding.
-NET_ERROR(INVALID_CHUNKED_ENCODING, -321)
+HTTP_ERROR(INVALID_CHUNKED_ENCODING, -321)
 
 // The server did not support the request method.
-NET_ERROR(METHOD_NOT_SUPPORTED, -322)
+HTTP_ERROR(METHOD_NOT_SUPPORTED, -322)
 
 // The response was 407 (Proxy Authentication Required), yet we did not send
 // the request to a proxy.
-NET_ERROR(UNEXPECTED_PROXY_AUTH, -323)
+HTTP_ERROR(UNEXPECTED_PROXY_AUTH, -323)
 
 // The server closed the connection without sending any data.
-NET_ERROR(EMPTY_RESPONSE, -324)
+HTTP_ERROR(EMPTY_RESPONSE, -324)
 
 // The headers section of the response is too large.
-NET_ERROR(RESPONSE_HEADERS_TOO_BIG, -325)
+HTTP_ERROR(RESPONSE_HEADERS_TOO_BIG, -325)
 
 // The PAC requested by HTTP did not have a valid status code (non-200).
-NET_ERROR(PAC_STATUS_NOT_OK, -326)
+HTTP_ERROR(PAC_STATUS_NOT_OK, -326)
 
 // The evaluation of the PAC script failed.
-NET_ERROR(PAC_SCRIPT_FAILED, -327)
+HTTP_ERROR(PAC_SCRIPT_FAILED, -327)
 
 // The response was 416 (Requested range not satisfiable) and the server cannot
 // satisfy the range requested.
-NET_ERROR(REQUEST_RANGE_NOT_SATISFIABLE, -328)
+HTTP_ERROR(REQUEST_RANGE_NOT_SATISFIABLE, -328)
 
 // The identity used for authentication is invalid.
-NET_ERROR(MALFORMED_IDENTITY, -329)
+HTTP_ERROR(MALFORMED_IDENTITY, -329)
 
 // Content decoding of the response body failed.
-NET_ERROR(CONTENT_DECODING_FAILED, -330)
+HTTP_ERROR(CONTENT_DECODING_FAILED, -330)
 
 // An operation could not be completed because all network IO
 // is suspended.
-NET_ERROR(NETWORK_IO_SUSPENDED, -331)
+HTTP_ERROR(NETWORK_IO_SUSPENDED, -331)
 
 // FLIP data received without receiving a SYN_REPLY on the stream.
-NET_ERROR(SYN_REPLY_NOT_RECEIVED, -332)
+HTTP_ERROR(SYN_REPLY_NOT_RECEIVED, -332)
 
 // Converting the response to target encoding failed.
-NET_ERROR(ENCODING_CONVERSION_FAILED, -333)
+HTTP_ERROR(ENCODING_CONVERSION_FAILED, -333)
 
 // The server sent an FTP directory listing in a format we do not understand.
-NET_ERROR(UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT, -334)
+HTTP_ERROR(UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT, -334)
 
 // Attempted use of an unknown SPDY stream id.
-NET_ERROR(INVALID_SPDY_STREAM, -335)
+HTTP_ERROR(INVALID_SPDY_STREAM, -335)
 
 // There are no supported proxies in the provided list.
-NET_ERROR(NO_SUPPORTED_PROXIES, -336)
+HTTP_ERROR(NO_SUPPORTED_PROXIES, -336)
 
 // There is a SPDY protocol error.
-NET_ERROR(SPDY_PROTOCOL_ERROR, -337)
+HTTP_ERROR(SPDY_PROTOCOL_ERROR, -337)
 
 // Credentials could not be established during HTTP Authentication.
-NET_ERROR(INVALID_AUTH_CREDENTIALS, -338)
+HTTP_ERROR(INVALID_AUTH_CREDENTIALS, -338)
 
 // An HTTP Authentication scheme was tried which is not supported on this
 // machine.
-NET_ERROR(UNSUPPORTED_AUTH_SCHEME, -339)
+HTTP_ERROR(UNSUPPORTED_AUTH_SCHEME, -339)
 
 // Detecting the encoding of the response failed.
-NET_ERROR(ENCODING_DETECTION_FAILED, -340)
+HTTP_ERROR(ENCODING_DETECTION_FAILED, -340)
 
 // (GSSAPI) No Kerberos credentials were available during HTTP Authentication.
-NET_ERROR(MISSING_AUTH_CREDENTIALS, -341)
+HTTP_ERROR(MISSING_AUTH_CREDENTIALS, -341)
 
 // An unexpected, but documented, SSPI or GSSAPI status code was returned.
-NET_ERROR(UNEXPECTED_SECURITY_LIBRARY_STATUS, -342)
+HTTP_ERROR(UNEXPECTED_SECURITY_LIBRARY_STATUS, -342)
 
 // The environment was not set up correctly for authentication (for
 // example, no KDC could be found or the principal is unknown.
-NET_ERROR(MISCONFIGURED_AUTH_ENVIRONMENT, -343)
+HTTP_ERROR(MISCONFIGURED_AUTH_ENVIRONMENT, -343)
 
 // An undocumented SSPI or GSSAPI status code was returned.
-NET_ERROR(UNDOCUMENTED_SECURITY_LIBRARY_STATUS, -344)
+HTTP_ERROR(UNDOCUMENTED_SECURITY_LIBRARY_STATUS, -344)
 
 // The HTTP response was too big to drain.
-NET_ERROR(RESPONSE_BODY_TOO_BIG_TO_DRAIN, -345)
+HTTP_ERROR(RESPONSE_BODY_TOO_BIG_TO_DRAIN, -345)
 
 // The HTTP response contained multiple distinct Content-Length headers.
-NET_ERROR(RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, -346)
+HTTP_ERROR(RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, -346)
 
 // SPDY Headers have been received, but not all of them - status or version
 // headers are missing, so we're expecting additional frames to complete them.
-NET_ERROR(INCOMPLETE_SPDY_HEADERS, -347)
+HTTP_ERROR(INCOMPLETE_SPDY_HEADERS, -347)
 
 // No PAC URL configuration could be retrieved from DHCP. This can indicate
 // either a failure to retrieve the DHCP configuration, or that there was no
 // PAC URL configured in DHCP.
-NET_ERROR(PAC_NOT_IN_DHCP, -348)
+HTTP_ERROR(PAC_NOT_IN_DHCP, -348)
 
 // The HTTP response contained multiple Content-Disposition headers.
-NET_ERROR(RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, -349)
+HTTP_ERROR(RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, -349)
 
 // The HTTP response contained multiple Location headers.
-NET_ERROR(RESPONSE_HEADERS_MULTIPLE_LOCATION, -350)
+HTTP_ERROR(RESPONSE_HEADERS_MULTIPLE_LOCATION, -350)
 
 // SPDY server refused the stream. Client should retry. This should never be a
 // user-visible error.
-NET_ERROR(SPDY_SERVER_REFUSED_STREAM, -351)
+HTTP_ERROR(SPDY_SERVER_REFUSED_STREAM, -351)
 
 // SPDY server didn't respond to the PING message.
-NET_ERROR(SPDY_PING_FAILED, -352)
+HTTP_ERROR(SPDY_PING_FAILED, -352)
 
 // Obsolete.  Kept here to avoid reuse, as the old error can still appear on
 // histograms.
-// NET_ERROR(PIPELINE_EVICTION, -353)
+// HTTP_ERROR(PIPELINE_EVICTION, -353)
 
 // The HTTP response body transferred fewer bytes than were advertised by the
 // Content-Length header when the connection is closed.
-NET_ERROR(CONTENT_LENGTH_MISMATCH, -354)
+HTTP_ERROR(CONTENT_LENGTH_MISMATCH, -354)
 
 // The HTTP response body is transferred with Chunked-Encoding, but the
 // terminating zero-length chunk was never sent when the connection is closed.
-NET_ERROR(INCOMPLETE_CHUNKED_ENCODING, -355)
+HTTP_ERROR(INCOMPLETE_CHUNKED_ENCODING, -355)
 
 // There is a QUIC protocol error.
-NET_ERROR(QUIC_PROTOCOL_ERROR, -356)
+HTTP_ERROR(QUIC_PROTOCOL_ERROR, -356)
 
 // The HTTP headers were truncated by an EOF.
-NET_ERROR(RESPONSE_HEADERS_TRUNCATED, -357)
+HTTP_ERROR(RESPONSE_HEADERS_TRUNCATED, -357)
 
 // The QUIC crytpo handshake failed.  This means that the server was unable
 // to read any requests sent, so they may be resent.
-NET_ERROR(QUIC_HANDSHAKE_FAILED, -358)
+HTTP_ERROR(QUIC_HANDSHAKE_FAILED, -358)
 
 // An https resource was requested over an insecure QUIC connection.
-NET_ERROR(REQUEST_FOR_SECURE_RESOURCE_OVER_INSECURE_QUIC, -359)
+HTTP_ERROR(REQUEST_FOR_SECURE_RESOURCE_OVER_INSECURE_QUIC, -359)
 
 // Transport security is inadequate for the SPDY version.
-NET_ERROR(SPDY_INADEQUATE_TRANSPORT_SECURITY, -360)
+HTTP_ERROR(SPDY_INADEQUATE_TRANSPORT_SECURITY, -360)
 
 // The peer violated SPDY flow control.
-NET_ERROR(SPDY_FLOW_CONTROL_ERROR, -361)
+HTTP_ERROR(SPDY_FLOW_CONTROL_ERROR, -361)
 
 // The peer sent an improperly sized SPDY frame.
-NET_ERROR(SPDY_FRAME_SIZE_ERROR, -362)
+HTTP_ERROR(SPDY_FRAME_SIZE_ERROR, -362)
 
 // Decoding or encoding of compressed SPDY headers failed.
-NET_ERROR(SPDY_COMPRESSION_ERROR, -363)
+HTTP_ERROR(SPDY_COMPRESSION_ERROR, -363)
 
 // Proxy Auth Requested without a valid Client Socket Handle.
-NET_ERROR(PROXY_AUTH_REQUESTED_WITH_NO_CONNECTION, -364)
+HTTP_ERROR(PROXY_AUTH_REQUESTED_WITH_NO_CONNECTION, -364)
 
 // HTTP_1_1_REQUIRED error code received on HTTP/2 session.
-NET_ERROR(HTTP_1_1_REQUIRED, -365)
+HTTP_ERROR(HTTP_1_1_REQUIRED, -365)
 
 // HTTP_1_1_REQUIRED error code received on HTTP/2 session to proxy.
-NET_ERROR(PROXY_HTTP_1_1_REQUIRED, -366)
+HTTP_ERROR(PROXY_HTTP_1_1_REQUIRED, -366)
 
 // The PAC script terminated fatally and must be reloaded.
-NET_ERROR(PAC_SCRIPT_TERMINATED, -367)
+HTTP_ERROR(PAC_SCRIPT_TERMINATED, -367)
 
 // The certificate offered by the alternative server is not valid for the
 // origin, a violation of HTTP Alternative Services specification Section 2.1,
 // https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html#host_auth.
-NET_ERROR(ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, -368)
+HTTP_ERROR(ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, -368)
 
 // The cache does not have the requested entry.
-NET_ERROR(CACHE_MISS, -400)
+HTTP_ERROR(CACHE_MISS, -400)
 
 // Unable to read from the disk cache.
-NET_ERROR(CACHE_READ_FAILURE, -401)
+HTTP_ERROR(CACHE_READ_FAILURE, -401)
 
 // Unable to write to the disk cache.
-NET_ERROR(CACHE_WRITE_FAILURE, -402)
+HTTP_ERROR(CACHE_WRITE_FAILURE, -402)
 
 // The operation is not supported for this entry.
-NET_ERROR(CACHE_OPERATION_NOT_SUPPORTED, -403)
+HTTP_ERROR(CACHE_OPERATION_NOT_SUPPORTED, -403)
 
 // The disk cache is unable to open this entry.
-NET_ERROR(CACHE_OPEN_FAILURE, -404)
+HTTP_ERROR(CACHE_OPEN_FAILURE, -404)
 
 // The disk cache is unable to create this entry.
-NET_ERROR(CACHE_CREATE_FAILURE, -405)
+HTTP_ERROR(CACHE_CREATE_FAILURE, -405)
 
 // Multiple transactions are racing to create disk cache entries. This is an
 // internal error returned from the HttpCache to the HttpCacheTransaction that
 // tells the transaction to restart the entry-creation logic because the state
 // of the cache has changed.
-NET_ERROR(CACHE_RACE, -406)
+HTTP_ERROR(CACHE_RACE, -406)
 
 // The cache was unable to read a checksum record on an entry. This can be
 // returned from attempts to read from the cache. It is an internal error,
 // returned by the SimpleCache backend, but not by any URLRequest methods
 // or members.
-NET_ERROR(CACHE_CHECKSUM_READ_FAILURE, -407)
+HTTP_ERROR(CACHE_CHECKSUM_READ_FAILURE, -407)
 
 // The cache found an entry with an invalid checksum. This can be returned from
 // attempts to read from the cache. It is an internal error, returned by the
 // SimpleCache backend, but not by any URLRequest methods or members.
-NET_ERROR(CACHE_CHECKSUM_MISMATCH, -408)
+HTTP_ERROR(CACHE_CHECKSUM_MISMATCH, -408)
 
 // Internal error code for the HTTP cache. The cache lock timeout has fired.
-NET_ERROR(CACHE_LOCK_TIMEOUT, -409)
+HTTP_ERROR(CACHE_LOCK_TIMEOUT, -409)
 
 // The server's response was insecure (e.g. there was a cert error).
-NET_ERROR(INSECURE_RESPONSE, -501)
+HTTP_ERROR(INSECURE_RESPONSE, -501)
 
 // The server responded to a <keygen> with a generated client cert that we
 // don't have the matching private key for.
-NET_ERROR(NO_PRIVATE_KEY_FOR_CERT, -502)
+HTTP_ERROR(NO_PRIVATE_KEY_FOR_CERT, -502)
 
 // An error adding to the OS certificate database (e.g. OS X Keychain).
-NET_ERROR(ADD_USER_CERT_FAILED, -503)
+HTTP_ERROR(ADD_USER_CERT_FAILED, -503)
 
 // *** Code -600 is reserved (was FTP_PASV_COMMAND_FAILED). ***
 
 // A generic error for failed FTP control connection command.
 // If possible, please use or add a more specific error code.
-NET_ERROR(FTP_FAILED, -601)
+HTTP_ERROR(FTP_FAILED, -601)
 
 // The server cannot fulfill the request at this point. This is a temporary
 // error.
 // FTP response code 421.
-NET_ERROR(FTP_SERVICE_UNAVAILABLE, -602)
+HTTP_ERROR(FTP_SERVICE_UNAVAILABLE, -602)
 
 // The server has aborted the transfer.
 // FTP response code 426.
-NET_ERROR(FTP_TRANSFER_ABORTED, -603)
+HTTP_ERROR(FTP_TRANSFER_ABORTED, -603)
 
 // The file is busy, or some other temporary error condition on opening
 // the file.
 // FTP response code 450.
-NET_ERROR(FTP_FILE_BUSY, -604)
+HTTP_ERROR(FTP_FILE_BUSY, -604)
 
 // Server rejected our command because of syntax errors.
 // FTP response codes 500, 501.
-NET_ERROR(FTP_SYNTAX_ERROR, -605)
+HTTP_ERROR(FTP_SYNTAX_ERROR, -605)
 
 // Server does not support the command we issued.
 // FTP response codes 502, 504.
-NET_ERROR(FTP_COMMAND_NOT_SUPPORTED, -606)
+HTTP_ERROR(FTP_COMMAND_NOT_SUPPORTED, -606)
 
 // Server rejected our command because we didn't issue the commands in right
 // order.
 // FTP response code 503.
-NET_ERROR(FTP_BAD_COMMAND_SEQUENCE, -607)
+HTTP_ERROR(FTP_BAD_COMMAND_SEQUENCE, -607)
 
 // PKCS #12 import failed due to incorrect password.
-NET_ERROR(PKCS12_IMPORT_BAD_PASSWORD, -701)
+HTTP_ERROR(PKCS12_IMPORT_BAD_PASSWORD, -701)
 
 // PKCS #12 import failed due to other error.
-NET_ERROR(PKCS12_IMPORT_FAILED, -702)
+HTTP_ERROR(PKCS12_IMPORT_FAILED, -702)
 
 // CA import failed - not a CA cert.
-NET_ERROR(IMPORT_CA_CERT_NOT_CA, -703)
+HTTP_ERROR(IMPORT_CA_CERT_NOT_CA, -703)
 
 // Import failed - certificate already exists in database.
 // Note it's a little weird this is an error but reimporting a PKCS12 is ok
 // (no-op).  That's how Mozilla does it, though.
-NET_ERROR(IMPORT_CERT_ALREADY_EXISTS, -704)
+HTTP_ERROR(IMPORT_CERT_ALREADY_EXISTS, -704)
 
 // CA import failed due to some other error.
-NET_ERROR(IMPORT_CA_CERT_FAILED, -705)
+HTTP_ERROR(IMPORT_CA_CERT_FAILED, -705)
 
 // Server certificate import failed due to some internal error.
-NET_ERROR(IMPORT_SERVER_CERT_FAILED, -706)
+HTTP_ERROR(IMPORT_SERVER_CERT_FAILED, -706)
 
 // PKCS #12 import failed due to invalid MAC.
-NET_ERROR(PKCS12_IMPORT_INVALID_MAC, -707)
+HTTP_ERROR(PKCS12_IMPORT_INVALID_MAC, -707)
 
 // PKCS #12 import failed due to invalid/corrupt file.
-NET_ERROR(PKCS12_IMPORT_INVALID_FILE, -708)
+HTTP_ERROR(PKCS12_IMPORT_INVALID_FILE, -708)
 
 // PKCS #12 import failed due to unsupported features.
-NET_ERROR(PKCS12_IMPORT_UNSUPPORTED, -709)
+HTTP_ERROR(PKCS12_IMPORT_UNSUPPORTED, -709)
 
 // Key generation failed.
-NET_ERROR(KEY_GENERATION_FAILED, -710)
+HTTP_ERROR(KEY_GENERATION_FAILED, -710)
 
 // Server-bound certificate generation failed.
-NET_ERROR(ORIGIN_BOUND_CERT_GENERATION_FAILED, -711)
+HTTP_ERROR(ORIGIN_BOUND_CERT_GENERATION_FAILED, -711)
 
 // Failure to export private key.
-NET_ERROR(PRIVATE_KEY_EXPORT_FAILED, -712)
+HTTP_ERROR(PRIVATE_KEY_EXPORT_FAILED, -712)
 
 // Self-signed certificate generation failed.
-NET_ERROR(SELF_SIGNED_CERT_GENERATION_FAILED, -713)
+HTTP_ERROR(SELF_SIGNED_CERT_GENERATION_FAILED, -713)
 
 // The certificate database changed in some way.
-NET_ERROR(CERT_DATABASE_CHANGED, -714)
+HTTP_ERROR(CERT_DATABASE_CHANGED, -714)
 
 // Failure to import Channel ID.
-NET_ERROR(CHANNEL_ID_IMPORT_FAILED, -715)
+HTTP_ERROR(CHANNEL_ID_IMPORT_FAILED, -715)
 
 // DNS error codes.
 
 // DNS resolver received a malformed response.
-NET_ERROR(DNS_MALFORMED_RESPONSE, -800)
+HTTP_ERROR(DNS_MALFORMED_RESPONSE, -800)
 
 // DNS server requires TCP
-NET_ERROR(DNS_SERVER_REQUIRES_TCP, -801)
+HTTP_ERROR(DNS_SERVER_REQUIRES_TCP, -801)
 
 // DNS server failed.  This error is returned for all of the following
 // error conditions:
@@ -790,16 +790,16 @@
 //     kind of query.
 // 5 - Refused - The name server refuses to perform the specified
 //     operation for policy reasons.
-NET_ERROR(DNS_SERVER_FAILED, -802)
+HTTP_ERROR(DNS_SERVER_FAILED, -802)
 
 // DNS transaction timed out.
-NET_ERROR(DNS_TIMED_OUT, -803)
+HTTP_ERROR(DNS_TIMED_OUT, -803)
 
 // The entry was not found in cache, for cache-only lookups.
-NET_ERROR(DNS_CACHE_MISS, -804)
+HTTP_ERROR(DNS_CACHE_MISS, -804)
 
 // Suffix search list rules prevent resolution of the given host name.
-NET_ERROR(DNS_SEARCH_EMPTY, -805)
+HTTP_ERROR(DNS_SEARCH_EMPTY, -805)
 
 // Failed to sort addresses according to RFC3484.
-NET_ERROR(DNS_SORT_ERROR, -806)
+HTTP_ERROR(DNS_SORT_ERROR, -806)
diff --git a/bin/network/net_errors.cc b/bin/http/http_errors.cc
similarity index 61%
rename from bin/network/net_errors.cc
rename to bin/http/http_errors.cc
index fdd8560..7866412 100644
--- a/bin/network/net_errors.cc
+++ b/bin/http/http_errors.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net_errors.h"
+#include "http_errors.h"
 
 #include "lib/fxl/logging.h"
 
-namespace network {
+namespace http {
 
 std::string ErrorToString(int error) {
-  return "network::" + ErrorToShortString(error);
+  return "http::" + ErrorToShortString(error);
 }
 
 std::string ErrorToShortString(int error) {
@@ -18,17 +18,17 @@
 
   const char* error_string;
   switch (error) {
-#define NET_ERROR(label, value) \
-  case NETWORK_ERR_##label:     \
+#define HTTP_ERROR(label, value) \
+  case HTTP_ERR_##label:     \
     error_string = #label;      \
     break;
-#include "garnet/bin/network/net_error_list.h"
-#undef NET_ERROR
+#include "garnet/bin/http/http_error_list.h"
+#undef HTTP_ERROR
     default:
       FXL_NOTREACHED();
       error_string = "<unknown>";
   }
-  return std::string("NETWORK_ERR_") + error_string;
+  return std::string("HTTP_ERR_") + error_string;
 }
 
-}  // namespace network
+}  // namespace http
diff --git a/bin/http/http_errors.h b/bin/http/http_errors.h
new file mode 100644
index 0000000..61cd167
--- /dev/null
+++ b/bin/http/http_errors.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_HTTP_HTTP_ERRORS_H_
+#define GARNET_BIN_HTTP_HTTP_ERRORS_H_
+
+#include <string>
+
+namespace http {
+
+enum Error {
+  // No error.
+  OK = 0,
+
+#define HTTP_ERROR(label, value) HTTP_ERR_##label = value,
+#include "garnet/bin/http/http_error_list.h"
+#undef HTTP_ERROR
+};
+
+// Returns a textual representation of the error code for logging purposes.
+std::string ErrorToString(int error);
+
+// Same as above, but leaves off the leading "http::".
+std::string ErrorToShortString(int error);
+
+}  // namespace http
+
+#endif  // GARNET_BIN_HTTP_HTTP_ERRORS_H_
diff --git a/bin/http/http_service_delegate.cc b/bin/http/http_service_delegate.cc
new file mode 100644
index 0000000..bba3b1e
--- /dev/null
+++ b/bin/http/http_service_delegate.cc
@@ -0,0 +1,23 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/http/http_service_delegate.h"
+
+namespace http {
+
+namespace oldhttp = ::fuchsia::net::oldhttp;
+
+HttpServiceDelegate::HttpServiceDelegate(async_t* dispatcher)
+    : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
+      http_provider_(dispatcher) {
+  FXL_DCHECK(dispatcher),
+      context_->outgoing().AddPublicService<oldhttp::HttpService>(
+          [this](fidl::InterfaceRequest<oldhttp::HttpService> request) {
+            http_provider_.AddBinding(std::move(request));
+          });
+}
+
+HttpServiceDelegate::~HttpServiceDelegate() {}
+
+}  // namespace http
diff --git a/bin/http/http_service_delegate.h b/bin/http/http_service_delegate.h
new file mode 100644
index 0000000..c503c9d
--- /dev/null
+++ b/bin/http/http_service_delegate.h
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_HTTP_HTTP_SERVICE_DELEGATE_H_
+#define GARNET_BIN_HTTP_HTTP_SERVICE_DELEGATE_H_
+
+#include <memory>
+
+#include "garnet/bin/http/http_service_impl.h"
+#include "lib/app/cpp/startup_context.h"
+
+namespace http {
+
+class HttpServiceDelegate {
+ public:
+  HttpServiceDelegate(async_t* dispatcher);
+  ~HttpServiceDelegate();
+
+ private:
+  std::unique_ptr<fuchsia::sys::StartupContext> context_;
+  HttpServiceImpl http_provider_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(HttpServiceDelegate);
+};
+
+}  // namespace http
+
+#endif  // GARNET_BIN_HTTP_HTTP_SERVICE_DELEGATE_H_
diff --git a/bin/network/network_service_impl.cc b/bin/http/http_service_impl.cc
similarity index 77%
rename from bin/network/network_service_impl.cc
rename to bin/http/http_service_impl.cc
index cc34a7b..3237d21 100644
--- a/bin/network/network_service_impl.cc
+++ b/bin/http/http_service_impl.cc
@@ -2,23 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "network_service_impl.h"
+#include "http_service_impl.h"
 
 #include <utility>
 
-#include <fdio/limits.h>
+#include <lib/fdio/limits.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async-loop/cpp/loop.h>
 
-#include "garnet/bin/network/net_adapters.h"
-#include "garnet/bin/network/net_errors.h"
-#include "garnet/bin/network/network_service_impl.h"
-#include "garnet/bin/network/url_loader_impl.h"
+#include "garnet/bin/http/http_service_impl.h"
+#include "garnet/bin/http/http_url_loader_impl.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/memory/ref_ptr.h"
 #include "lib/fxl/memory/weak_ptr.h"
 
-namespace network {
+namespace http {
+
+namespace oldhttp = ::fuchsia::net::oldhttp;
 
 // Number of file descriptors each UrlLoader instance uses. (This
 // depends on the implementation of the reactor in third_party/asio:
@@ -28,17 +28,17 @@
 constexpr size_t kNumFDReserved = 3;
 // This is some random margin.
 constexpr size_t kMargin = 4;
-// Maximum number of slots used to run network requests concurrently.
+// Maximum number of slots used to run http requests concurrently.
 constexpr size_t kMaxSlots = ((FDIO_MAX_FD - kNumFDReserved) / kNumFDPerConnection) - kMargin;
 
 // Container for the url loader implementation. The loader is run on his own
 // thread.
-class NetworkServiceImpl::UrlLoaderContainer
+class HttpServiceImpl::UrlLoaderContainer
     : public URLLoaderImpl::Coordinator {
  public:
   UrlLoaderContainer(URLLoaderImpl::Coordinator* top_coordinator,
                      async_t* main_dispatcher,
-                     fidl::InterfaceRequest<URLLoader> request)
+                     fidl::InterfaceRequest<oldhttp::URLLoader> request)
       : request_(std::move(request)),
         top_coordinator_(top_coordinator),
         main_dispatcher_(main_dispatcher),
@@ -55,22 +55,22 @@
     async::PostTask(io_loop_.async(), [this] { StartOnIOThread(); });
   }
 
-  void set_on_done(fxl::Closure on_done) { on_done_ = std::move(on_done); }
+  void set_on_done(fit::closure on_done) { on_done_ = std::move(on_done); }
 
  private:
   // URLLoaderImpl::Coordinator:
   void RequestNetworkSlot(
-      std::function<void(fxl::Closure)> slot_request) override {
+      fit::function<void(fit::closure)> slot_request) override {
     // On IO Thread.
     async::PostTask(main_dispatcher_,
-        [ weak_this = weak_ptr_, slot_request = std::move(slot_request) ] {
+        [ weak_this = weak_ptr_, slot_request = std::move(slot_request) ]() mutable {
           // On Main Thread.
           if (!weak_this)
             return;
 
           weak_this->top_coordinator_->RequestNetworkSlot([
             weak_this, slot_request = std::move(slot_request)
-          ](fxl::Closure on_inactive) {
+          ](fit::closure on_inactive) mutable {
             if (!weak_this) {
               on_inactive();
               return;
@@ -117,7 +117,7 @@
 
   void StartOnIOThread() {
     url_loader_ = std::make_unique<URLLoaderImpl>(this);
-    binding_ = std::make_unique<fidl::Binding<URLLoader>>(url_loader_.get(),
+    binding_ = std::make_unique<fidl::Binding<oldhttp::URLLoader>>(url_loader_.get(),
                                                           std::move(request_));
     binding_->set_error_handler([this] { StopOnIOThread(); });
   }
@@ -130,12 +130,12 @@
   }
 
   // This is set on the constructor, and then accessed on the io thread.
-  fidl::InterfaceRequest<URLLoader> request_;
+  fidl::InterfaceRequest<oldhttp::URLLoader> request_;
 
   // These variables can only be accessed on the main thread.
   URLLoaderImpl::Coordinator* top_coordinator_;
-  fxl::Closure on_inactive_;
-  fxl::Closure on_done_;
+  fit::closure on_inactive_;
+  fit::closure on_done_;
   bool stopped_ = true;
   bool joined_ = false;
 
@@ -143,7 +143,7 @@
   async::Loop io_loop_;
 
   // The binding and the implementation can only be accessed on the io thread.
-  std::unique_ptr<fidl::Binding<URLLoader>> binding_;
+  std::unique_ptr<fidl::Binding<oldhttp::URLLoader>> binding_;
   std::unique_ptr<URLLoaderImpl> url_loader_;
 
   // Copyable on any thread, but can only be de-referenced on the main thread.
@@ -155,20 +155,20 @@
   FXL_DISALLOW_COPY_AND_ASSIGN(UrlLoaderContainer);
 };
 
-NetworkServiceImpl::NetworkServiceImpl(async_t* dispatcher)
+HttpServiceImpl::HttpServiceImpl(async_t* dispatcher)
   : dispatcher_(dispatcher), available_slots_(kMaxSlots) {
   FXL_DCHECK(dispatcher_);
 }
 
-NetworkServiceImpl::~NetworkServiceImpl() = default;
+HttpServiceImpl::~HttpServiceImpl() = default;
 
-void NetworkServiceImpl::AddBinding(
-    fidl::InterfaceRequest<NetworkService> request) {
+void HttpServiceImpl::AddBinding(
+    fidl::InterfaceRequest<oldhttp::HttpService> request) {
   bindings_.AddBinding(this, std::move(request));
 }
 
-void NetworkServiceImpl::CreateURLLoader(
-    fidl::InterfaceRequest<URLLoader> request) {
+void HttpServiceImpl::CreateURLLoader(
+    fidl::InterfaceRequest<oldhttp::URLLoader> request) {
   loaders_.emplace_back(this, dispatcher_, std::move(request));
   UrlLoaderContainer* container = &loaders_.back();
   container->set_on_done([this, container] {
@@ -180,16 +180,8 @@
   container->Start();
 }
 
-void NetworkServiceImpl::GetCookieStore(zx::channel cookie_store) {
-  FXL_NOTIMPLEMENTED();
-}
-
-void NetworkServiceImpl::CreateWebSocket(zx::channel socket) {
-  FXL_NOTIMPLEMENTED();
-}
-
-void NetworkServiceImpl::RequestNetworkSlot(
-    std::function<void(fxl::Closure)> slot_request) {
+void HttpServiceImpl::RequestNetworkSlot(
+    fit::function<void(fit::closure)> slot_request) {
   if (available_slots_ == 0) {
     slot_requests_.push(std::move(slot_request));
     return;
@@ -198,7 +190,7 @@
   slot_request([this]() { OnSlotReturned(); });
 }
 
-void NetworkServiceImpl::OnSlotReturned() {
+void HttpServiceImpl::OnSlotReturned() {
   FXL_DCHECK(available_slots_ < kMaxSlots);
 
   if (slot_requests_.empty()) {
@@ -210,4 +202,4 @@
   request([this] { OnSlotReturned(); });
 }
 
-}  // namespace network
+}  // namespace http
diff --git a/bin/http/http_service_impl.h b/bin/http/http_service_impl.h
new file mode 100644
index 0000000..d7bf5db
--- /dev/null
+++ b/bin/http/http_service_impl.h
@@ -0,0 +1,51 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_HTTP_HTTP_SERVICE_IMPL_H_
+#define GARNET_BIN_HTTP_HTTP_SERVICE_IMPL_H_
+
+#include <list>
+#include <queue>
+
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
+#include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
+#include <lib/zx/channel.h>
+
+#include "garnet/bin/http/http_url_loader_impl.h"
+#include "lib/fidl/cpp/binding_set.h"
+#include "lib/fidl/cpp/interface_request.h"
+
+namespace http {
+
+class HttpServiceImpl : public ::fuchsia::net::oldhttp::HttpService,
+                        public URLLoaderImpl::Coordinator {
+ public:
+  HttpServiceImpl(async_t* dispatcher);
+  ~HttpServiceImpl() override;
+
+  void AddBinding(fidl::InterfaceRequest<::fuchsia::net::oldhttp::HttpService> request);
+
+  // HttpService methods:
+  void CreateURLLoader(fidl::InterfaceRequest<::fuchsia::net::oldhttp::URLLoader> request) override;
+
+ private:
+  class UrlLoaderContainer;
+
+  // URLLoaderImpl::Coordinator:
+  void RequestNetworkSlot(
+      fit::function<void(fit::closure)> slot_request) override;
+
+  void OnSlotReturned();
+
+  async_t* const dispatcher_;
+  size_t available_slots_;
+  fidl::BindingSet<::fuchsia::net::oldhttp::HttpService> bindings_;
+  std::list<UrlLoaderContainer> loaders_;
+  std::queue<fit::function<void(fit::closure)>> slot_requests_;
+};
+
+}  // namespace http
+
+#endif  // GARNET_BIN_HTTP_HTTP_SERVICE_IMPL_H_
diff --git a/bin/network/url_loader_impl.cc b/bin/http/http_url_loader_impl.cc
similarity index 75%
rename from bin/network/url_loader_impl.cc
rename to bin/http/http_url_loader_impl.cc
index 319f821..fa16cf2 100644
--- a/bin/network/url_loader_impl.cc
+++ b/bin/http/http_url_loader_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "url_loader_impl.h"
+#include "http_url_loader_impl.h"
 
 #include <istream>
 #include <memory>
@@ -10,14 +10,16 @@
 #include <string>
 #include <vector>
 
-#include "garnet/bin/network/http_client.h"
-#include "garnet/bin/network/net_adapters.h"
-#include "garnet/bin/network/net_errors.h"
+#include "garnet/bin/http/http_client.h"
+#include "garnet/bin/http/http_adapters.h"
+#include "garnet/bin/http/http_errors.h"
 #include "lib/fxl/functional/make_copyable.h"
 #include "lib/fxl/logging.h"
 #include "lib/url/gurl.h"
 
-namespace network {
+namespace http {
+
+namespace oldhttp = ::fuchsia::net::oldhttp;
 
 namespace {
 const size_t kMaxRedirects = 20;
@@ -28,10 +30,10 @@
 
 URLLoaderImpl::~URLLoaderImpl() {}
 
-void URLLoaderImpl::Start(URLRequest request, Callback callback) {
+void URLLoaderImpl::Start(oldhttp::URLRequest request, Callback callback) {
   callback_ = std::move(callback);
   coordinator_->RequestNetworkSlot(fxl::MakeCopyable(
-      [ this, request = std::move(request) ](fxl::Closure on_inactive) mutable {
+      [ this, request = std::move(request) ](fit::closure on_inactive) mutable {
         StartInternal(std::move(request));
         on_inactive();
       }));
@@ -40,19 +42,19 @@
 void URLLoaderImpl::FollowRedirect(Callback callback) {
   FXL_NOTIMPLEMENTED();
   callback_ = callback;
-  SendError(network::NETWORK_ERR_NOT_IMPLEMENTED);
+  SendError(HTTP_ERR_NOT_IMPLEMENTED);
 }
 
 void URLLoaderImpl::QueryStatus(QueryStatusCallback callback) {
-  URLLoaderStatus status;
+  oldhttp::URLLoaderStatus status;
   FXL_NOTIMPLEMENTED();
-  status.error = MakeNetworkError(network::NETWORK_ERR_NOT_IMPLEMENTED);
+  status.error = MakeHttpError(HTTP_ERR_NOT_IMPLEMENTED);
   callback(std::move(status));
 }
 
 void URLLoaderImpl::SendError(int error_code) {
-  URLResponse response;
-  response.error = MakeNetworkError(error_code);
+  oldhttp::URLResponse response;
+  response.error = MakeHttpError(error_code);
   if (current_url_.is_valid()) {
     response.url = current_url_.spec();
   }
@@ -63,17 +65,17 @@
   /* TODO(toshik) */
 }
 
-void URLLoaderImpl::SendResponse(URLResponse response) {
+void URLLoaderImpl::SendResponse(oldhttp::URLResponse response) {
   Callback callback;
   std::swap(callback_, callback);
   callback(std::move(response));
 }
 
-void URLLoaderImpl::StartInternal(URLRequest request) {
+void URLLoaderImpl::StartInternal(oldhttp::URLRequest request) {
   std::string url_str = request.url;
   std::string method = request.method;
   std::map<std::string, std::string> extra_headers;
-  std::unique_ptr<UploadElementReader> request_body_reader;
+  std::unique_ptr<http::UploadElementReader> request_body_reader;
 
   if (request.headers) {
     for (size_t i = 0; i < request.headers->size(); ++i)
@@ -84,14 +86,14 @@
   if (request.body) {
     // TODO(kulakowski) Implement responses into a shared_buffer
     if (request.body->is_stream()) {
-      request_body_reader = std::make_unique<SocketUploadElementReader>(
+      request_body_reader = std::make_unique<http::SocketUploadElementReader>(
           std::move(request.body->stream()));
     } else if (request.body->is_buffer()) {
-      request_body_reader = std::make_unique<VmoUploadElementReader>(
+      request_body_reader = std::make_unique<http::VmoUploadElementReader>(
           std::move(request.body->buffer()));
     } else {
       FXL_DCHECK(request.body->is_sized_buffer());
-      request_body_reader = std::make_unique<VmoUploadElementReader>(
+      request_body_reader = std::make_unique<http::VmoUploadElementReader>(
           std::move(request.body->sized_buffer().vmo),
           request.body->sized_buffer().size);
     }
@@ -104,7 +106,7 @@
 
   current_url_ = url::GURL(url_str);
   if (!current_url_.is_valid()) {
-    SendError(network::NETWORK_ERR_INVALID_ARGUMENT);
+    SendError(HTTP_ERR_INVALID_ARGUMENT);
     return;
   }
 
@@ -122,7 +124,7 @@
               (current_url_.has_query() ? "?" + current_url_.query() : ""),
           method, extra_headers, std::move(request_body_reader));
       if (result != ZX_OK) {
-        SendError(network::NETWORK_ERR_INVALID_ARGUMENT);
+        SendError(HTTP_ERR_INVALID_ARGUMENT);
         return;
       }
       c.Start(current_url_.host(),
@@ -132,7 +134,7 @@
       if (c.status_code_ == 301 || c.status_code_ == 302) {
         current_url_ = url::GURL(c.redirect_location_);
         if (!current_url_.is_valid()) {
-          SendError(network::NETWORK_ERR_INVALID_RESPONSE);
+          SendError(HTTP_ERR_INVALID_RESPONSE);
           return;
         }
         // Follow redirect
@@ -142,7 +144,7 @@
 #else
       FXL_LOG(WARNING) << "https is not built-in. "
                           "please build with NETWORK_SERVICE_USE_HTTPS";
-      SendError(network::NETWORK_ERR_INVALID_ARGUMENT);
+      SendError(HTTP_ERR_INVALID_ARGUMENT);
       return;
 #endif
     } else if (current_url_.SchemeIs("http")) {
@@ -153,7 +155,7 @@
               (current_url_.has_query() ? "?" + current_url_.query() : ""),
           method, extra_headers, std::move(request_body_reader));
       if (result != ZX_OK) {
-        SendError(network::NETWORK_ERR_INVALID_ARGUMENT);
+        SendError(HTTP_ERR_INVALID_ARGUMENT);
         return;
       }
       c.Start(current_url_.host(),
@@ -163,7 +165,7 @@
       if (c.status_code_ == 301 || c.status_code_ == 302) {
         current_url_ = url::GURL(c.redirect_location_);
         if (!current_url_.is_valid()) {
-          SendError(network::NETWORK_ERR_INVALID_RESPONSE);
+          SendError(HTTP_ERR_INVALID_RESPONSE);
           return;
         }
         // Follow redirect
@@ -172,13 +174,13 @@
       }
     } else {
       // unknown protocol
-      SendError(network::NETWORK_ERR_INVALID_ARGUMENT);
+      SendError(HTTP_ERR_INVALID_ARGUMENT);
       return;
     }
     // Success without redirect
     return;
   } while (--redirectsLeft);
-  SendError(network::NETWORK_ERR_TOO_MANY_REDIRECTS);
+  SendError(HTTP_ERR_TOO_MANY_REDIRECTS);
 }
 
-}  // namespace network
+}  // namespace http
diff --git a/bin/http/http_url_loader_impl.h b/bin/http/http_url_loader_impl.h
new file mode 100644
index 0000000..b6ff717
--- /dev/null
+++ b/bin/http/http_url_loader_impl.h
@@ -0,0 +1,55 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_HTTP_HTTP_URL_LOADER_IMPL_H_
+#define GARNET_BIN_HTTP_HTTP_URL_LOADER_IMPL_H_
+
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
+
+#include <lib/fit/function.h>
+#include "lib/fidl/cpp/binding.h"
+#include "lib/url/gurl.h"
+
+namespace http {
+
+class URLLoaderImpl : public ::fuchsia::net::oldhttp::URLLoader {
+ public:
+  // Coordinates requests to limit the number of concurrent active requests.
+  class Coordinator {
+   public:
+    virtual ~Coordinator() {}
+    virtual void RequestNetworkSlot(
+        fit::function<void(fit::closure)> slot_request) = 0;
+  };
+
+  URLLoaderImpl(Coordinator* coordinator);
+  ~URLLoaderImpl() override;
+
+ private:
+  template <typename T>
+  class HTTPClient;
+
+  using Callback = std::function<void(::fuchsia::net::oldhttp::URLResponse)>;
+
+  // URLLoader methods:
+  void Start(::fuchsia::net::oldhttp::URLRequest request, Callback callback) override;
+  void FollowRedirect(Callback callback) override;
+  void QueryStatus(QueryStatusCallback callback) override;
+
+  void SendError(int error_code);
+  void FollowRedirectInternal();
+  void SendResponse(::fuchsia::net::oldhttp::URLResponse response);
+  void StartInternal(::fuchsia::net::oldhttp::URLRequest request);
+
+  Coordinator* coordinator_;
+  Callback callback_;
+  ::fuchsia::net::oldhttp::ResponseBodyMode response_body_mode_;
+  // bool auto_follow_redirects_;
+  url::GURL current_url_;
+  ::fuchsia::net::oldhttp::URLLoaderStatus last_status_;
+};
+
+}  // namespace http
+
+#endif  // GARNET_BIN_HTTP_HTTP_URL_LOADER_IMPL_H_
diff --git a/bin/network/main.cc b/bin/http/main.cc
similarity index 82%
rename from bin/network/main.cc
rename to bin/http/main.cc
index 6faec0c..c09d43f 100644
--- a/bin/network/main.cc
+++ b/bin/http/main.cc
@@ -4,7 +4,7 @@
 
 #include <lib/async-loop/cpp/loop.h>
 
-#include "garnet/bin/network/network_service_delegate.h"
+#include "garnet/bin/http/http_service_delegate.h"
 #include "lib/fxl/command_line.h"
 #include "lib/fxl/log_settings_command_line.h"
 
@@ -14,7 +14,7 @@
     return 1;
 
   async::Loop loop(&kAsyncLoopConfigMakeDefault);
-  network::NetworkServiceDelegate delegate(loop.async());
+  http::HttpServiceDelegate delegate2(loop.async());
   loop.Run();
   return 0;
 }
diff --git a/bin/network/meta/network.cmx b/bin/http/meta/http.cmx
similarity index 100%
rename from bin/network/meta/network.cmx
rename to bin/http/meta/http.cmx
diff --git a/bin/network/tests/manual/mwget/BUILD.gn b/bin/http/tests/manual/mwget/BUILD.gn
similarity index 92%
rename from bin/network/tests/manual/mwget/BUILD.gn
rename to bin/http/tests/manual/mwget/BUILD.gn
index 7766643..c9f0bf1 100644
--- a/bin/network/tests/manual/mwget/BUILD.gn
+++ b/bin/http/tests/manual/mwget/BUILD.gn
@@ -16,7 +16,7 @@
     "//garnet/public/lib/fidl/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
-    "//garnet/public/lib/network/fidl",
+    "//garnet/public/lib/net/oldhttp/fidl",
   ]
 }
 
diff --git a/bin/network/tests/manual/mwget/mwget.cc b/bin/http/tests/manual/mwget/mwget.cc
similarity index 86%
rename from bin/network/tests/manual/mwget/mwget.cc
rename to bin/http/tests/manual/mwget/mwget.cc
index fbb0e6d..540a598 100644
--- a/bin/network/tests/manual/mwget/mwget.cc
+++ b/bin/http/tests/manual/mwget/mwget.cc
@@ -5,7 +5,7 @@
 #include <stdlib.h>
 
 #include <lib/async-loop/cpp/loop.h>
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
@@ -14,13 +14,15 @@
 
 namespace examples {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 // ResponseConsumer consumes the response silently.
 class ResponseConsumer {
  public:
   ResponseConsumer(int id) : id_(id) {}
   ResponseConsumer() = delete;
 
-  void Run(network::URLResponse response) const {
+  void Run(http::URLResponse response) const {
     if (response.error) {
       printf("#%d: Got error: %d (%s)\n", id_, response.error->code,
              response.error->description.get().c_str());
@@ -61,10 +63,10 @@
   MWGetApp(async::Loop* loop)
       : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
         loop_(loop) {
-    network_service_ =
-        context_->ConnectToEnvironmentService<network::NetworkService>();
+    http_service_ =
+        context_->ConnectToEnvironmentService<http::HttpService>();
     FXL_DCHECK(loop);
-    FXL_DCHECK(network_service_);
+    FXL_DCHECK(http_service_);
   }
 
   bool Start(const std::vector<std::string>& args) {
@@ -85,15 +87,15 @@
 
     num_done_ = 0;
     for (int i = 0; i < num_loaders_; i++) {
-      network_service_->CreateURLLoader(url_loader_[i].NewRequest());
+      http_service_->CreateURLLoader(url_loader_[i].NewRequest());
 
-      network::URLRequest request;
+      http::URLRequest request;
       request.url = url;
       request.method = "GET";
       request.auto_follow_redirects = true;
 
       url_loader_[i]->Start(std::move(request),
-                            [this, i](network::URLResponse response) {
+                            [this, i](http::URLResponse response) {
                               ResponseConsumer consumer(i);
                               consumer.Run(std::move(response));
                               ++num_done_;
@@ -111,8 +113,8 @@
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
 
   async::Loop* const loop_;
-  network::NetworkServicePtr network_service_;
-  network::URLLoaderPtr url_loader_[MAX_LOADERS];
+  http::HttpServicePtr http_service_;
+  http::URLLoaderPtr url_loader_[MAX_LOADERS];
   int num_loaders_;
   int num_done_;
 };
diff --git a/bin/network/upload_element_reader.cc b/bin/http/upload_element_reader.cc
similarity index 98%
rename from bin/network/upload_element_reader.cc
rename to bin/http/upload_element_reader.cc
index 4a7ad64..1fe2cd2 100644
--- a/bin/network/upload_element_reader.cc
+++ b/bin/http/upload_element_reader.cc
@@ -8,7 +8,7 @@
 
 #include "lib/fxl/logging.h"
 
-namespace network {
+namespace http {
 
 UploadElementReader::UploadElementReader() : err_(ZX_OK) {}
 UploadElementReader::~UploadElementReader() = default;
@@ -95,4 +95,4 @@
   }
 }
 
-}  // namespace network
+}  // namespace http
diff --git a/bin/network/upload_element_reader.h b/bin/http/upload_element_reader.h
similarity index 88%
rename from bin/network/upload_element_reader.h
rename to bin/http/upload_element_reader.h
index a77aded..0962009 100644
--- a/bin/network/upload_element_reader.h
+++ b/bin/http/upload_element_reader.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef GARNET_BIN_NETWORK_UPLOAD_ELEMENT_READER_H_
-#define GARNET_BIN_NETWORK_UPLOAD_ELEMENT_READER_H_
+#ifndef GARNET_BIN_HTTP_UPLOAD_ELEMENT_READER_H_
+#define GARNET_BIN_HTTP_UPLOAD_ELEMENT_READER_H_
 
 #include <array>
 #include <limits>
@@ -12,7 +12,7 @@
 #include <lib/zx/socket.h>
 #include <lib/zx/vmo.h>
 
-namespace network {
+namespace http {
 
 class UploadElementReader {
  public:
@@ -68,6 +68,6 @@
   std::array<char, BUFSIZE> buf_;
 };
 
-}  // namespace network
+}  // namespace http
 
-#endif  // GARNET_BIN_NETWORK_UPLOAD_ELEMENT_READER_H_
+#endif  // GARNET_BIN_HTTP_UPLOAD_ELEMENT_READER_H_
diff --git a/bin/network/upload_element_reader_unittest.cc b/bin/http/upload_element_reader_unittest.cc
similarity index 92%
rename from bin/network/upload_element_reader_unittest.cc
rename to bin/http/upload_element_reader_unittest.cc
index dcb0fdc..6e8a540 100644
--- a/bin/network/upload_element_reader_unittest.cc
+++ b/bin/http/upload_element_reader_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "garnet/bin/network/upload_element_reader.h"
+#include "garnet/bin/http/upload_element_reader.h"
 
 #include <sstream>
 
@@ -11,7 +11,7 @@
 
 #include <gtest/gtest.h>
 
-namespace network {
+namespace http {
 
 namespace {
 
@@ -53,4 +53,4 @@
 
 }  // namespace
 
-}  // namespace network
+}  // namespace http
diff --git a/bin/insntrace/control.cc b/bin/insntrace/control.cc
index 094e0b2..555ee4f 100644
--- a/bin/insntrace/control.cc
+++ b/bin/insntrace/control.cc
@@ -20,7 +20,7 @@
 #include <zircon/ktrace.h>
 #include <zircon/syscalls.h>
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <lib/zx/handle.h>
 #include <lib/zx/vmo.h>
 
diff --git a/bin/insntrace/main.cc b/bin/insntrace/main.cc
index 6e78ecc..c32ad7b 100644
--- a/bin/insntrace/main.cc
+++ b/bin/insntrace/main.cc
@@ -13,7 +13,7 @@
 
 #include <iostream>
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 
 #include "lib/fxl/command_line.h"
 #include "lib/fxl/log_settings.h"
diff --git a/bin/installer/install-fuchsia.c b/bin/installer/install-fuchsia.c
index b365c32..a17c310 100644
--- a/bin/installer/install-fuchsia.c
+++ b/bin/installer/install-fuchsia.c
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include <dirent.h>
-#include <fdio/spawn.h>
+#include <lib/fdio/spawn.h>
 #include <fnmatch.h>
 #include <limits.h>
 #include <stdio.h>
diff --git a/bin/listen/listen.cc b/bin/listen/listen.cc
index 2664a9e..758e153 100644
--- a/bin/listen/listen.cc
+++ b/bin/listen/listen.cc
@@ -4,9 +4,9 @@
 
 #include <arpa/inet.h>
 #include <errno.h>
-#include <fdio/io.h>
-#include <fdio/spawn.h>
-#include <fdio/util.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
+#include <lib/fdio/util.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/async/default.h>
@@ -135,7 +135,7 @@
 
     zx_status_t status =
         fdio_spawn_etc(job_.get(),
-                       FDIO_SPAWN_SHARE_JOB | FDIO_SPAWN_CLONE_LDSVC |
+                       FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC |
                            FDIO_SPAWN_CLONE_NAMESPACE,
                        argv_[0], argv_, nullptr, kActionCount, actions,
                        process.reset_and_get_address(), err_msg);
diff --git a/bin/log_listener/src/main.rs b/bin/log_listener/src/main.rs
index 753763a..eba40ae 100644
--- a/bin/log_listener/src/main.rs
+++ b/bin/log_listener/src/main.rs
@@ -20,9 +20,9 @@
 use std::io::{stdout, Write};
 
 // Include the generated FIDL bindings for the `Logger` service.
-extern crate fidl_logger;
-use fidl_logger::{LogFilterOptions, LogLevelFilter, LogListener, LogListenerImpl,
-                  LogListenerMarker, LogMarker, LogMessage, MAX_TAGS, MAX_TAG_LEN};
+extern crate fidl_fuchsia_logger;
+use fidl_fuchsia_logger::{LogFilterOptions, LogLevelFilter, LogListener, LogListenerImpl,
+                          LogListenerMarker, LogMarker, LogMessage, MAX_TAGS, MAX_TAG_LEN};
 
 fn default_log_filter_options() -> LogFilterOptions {
     LogFilterOptions {
@@ -215,7 +215,7 @@
 {
     LogListenerImpl {
         state: listener,
-        on_open: |_,_| fok(()),
+        on_open: |_, _| fok(()),
         done: |_, _| {
             //ignore, only called when dump_logs is called.
             fok(())
@@ -238,8 +238,7 @@
     let logger = connect_to_service::<LogMarker>()?;
     let (log_listener_local, log_listener_remote) = zx::Channel::create()?;
     let log_listener_local = async::Channel::from_channel(log_listener_local)?;
-    let listener_ptr =
-        fidl::endpoints2::ClientEnd::<LogListenerMarker>::new(log_listener_remote);
+    let listener_ptr = fidl::endpoints2::ClientEnd::<LogListenerMarker>::new(log_listener_remote);
 
     let options = options.map(OutOfLine);
     logger
diff --git a/bin/logger/BUILD.gn b/bin/logger/BUILD.gn
index 3205d14..ef8725e 100644
--- a/bin/logger/BUILD.gn
+++ b/bin/logger/BUILD.gn
@@ -24,19 +24,6 @@
   ]
 }
 
-executable("logger_integration_cpp_tests") {
-  testonly = true
-
-  sources = [
-    "test/logger_tests.cc",
-    "test/run_all_tests.cc",
-  ]
-  deps = [
-    "//third_party/gtest",
-    "//zircon/public/lib/syslog",
-  ]
-}
-
 package("logger") {
   deps = [
     ":bin",
@@ -58,8 +45,7 @@
 
   deps = [
     ":bin",
-    ":logger_integration_cpp_tests",
-    "test/go/src/logger_integration_test:logger_integration_go_tests",
+    "tests",
   ]
 
   tests = [
diff --git a/bin/logger/src/klogger.rs b/bin/logger/src/klogger.rs
index 667e40e..85af43b 100644
--- a/bin/logger/src/klogger.rs
+++ b/bin/logger/src/klogger.rs
@@ -6,7 +6,7 @@
 
 use async;
 use byteorder::{ByteOrder, LittleEndian};
-use fidl_logger::{self, LogMessage};
+use fidl_fuchsia_logger::{self, LogMessage};
 use futures::future::{loop_fn, Loop};
 use futures::FutureExt;
 use logger;
@@ -46,7 +46,7 @@
                 time: LittleEndian::read_u64(&buf[8..16]),
                 pid: LittleEndian::read_u64(&buf[16..24]),
                 tid: LittleEndian::read_u64(&buf[24..32]),
-                severity: fidl_logger::LogLevelFilter::Info as i32,
+                severity: fidl_fuchsia_logger::LogLevelFilter::Info as i32,
                 dropped_logs: 0,
                 tags: vec!["klog".to_string()],
                 msg: String::new(),
diff --git a/bin/logger/src/logger.rs b/bin/logger/src/logger.rs
index 20cd579..a81d379 100644
--- a/bin/logger/src/logger.rs
+++ b/bin/logger/src/logger.rs
@@ -4,7 +4,7 @@
 
 use async;
 use byteorder::{ByteOrder, LittleEndian};
-use fidl_logger::LogMessage;
+use fidl_fuchsia_logger::LogMessage;
 use futures::io;
 use futures::prelude::*;
 use libc::{c_char, c_int, uint32_t, uint64_t, uint8_t};
diff --git a/bin/logger/src/main.rs b/bin/logger/src/main.rs
index 6aa8c78..90b5fae 100644
--- a/bin/logger/src/main.rs
+++ b/bin/logger/src/main.rs
@@ -7,7 +7,7 @@
 extern crate byteorder;
 extern crate failure;
 extern crate fidl;
-extern crate fidl_logger;
+extern crate fidl_fuchsia_logger;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
@@ -30,8 +30,9 @@
 use std::collections::{vec_deque, VecDeque};
 use std::sync::Arc;
 
-use fidl_logger::{Log, LogFilterOptions, LogImpl, LogLevelFilter, LogListenerMarker,
-                  LogListenerProxy, LogMarker, LogMessage, LogSink, LogSinkImpl, LogSinkMarker};
+use fidl_fuchsia_logger::{Log, LogFilterOptions, LogImpl, LogLevelFilter, LogListenerMarker,
+                          LogListenerProxy, LogMarker, LogMessage, LogSink, LogSinkImpl,
+                          LogSinkMarker};
 
 mod klogger;
 mod logger;
@@ -205,12 +206,12 @@
 
     if let Some(mut options) = options {
         lw.tags = options.tags.drain(..).collect();
-        if lw.tags.len() > fidl_logger::MAX_TAGS as usize {
+        if lw.tags.len() > fidl_fuchsia_logger::MAX_TAGS as usize {
             // TODO: close channel
             return fok(());
         }
         for tag in &lw.tags {
-            if tag.len() > fidl_logger::MAX_TAG_LEN as usize {
+            if tag.len() > fidl_fuchsia_logger::MAX_TAG_LEN as usize {
                 // TODO: close channel
                 return fok(());
             }
@@ -233,7 +234,7 @@
         let mut v = vec![];
         for (msg, s) in shared_members.log_msg_buffer.iter_mut() {
             if lw.filter(msg) {
-                if log_length + s > fidl_logger::MAX_LOG_MANY_SIZE as usize {
+                if log_length + s > fidl_fuchsia_logger::MAX_LOG_MANY_SIZE as usize {
                     if ListenerStatus::Fine != lw.send_filtered_logs(&mut v) {
                         return fok(());
                     }
@@ -361,8 +362,8 @@
     use std::sync::atomic::{AtomicBool, Ordering};
 
     use fidl::encoding2::OutOfLine;
-    use fidl_logger::{LogFilterOptions, LogListener, LogListenerImpl, LogListenerMarker, LogProxy,
-                      LogSinkProxy};
+    use fidl_fuchsia_logger::{LogFilterOptions, LogListener, LogListenerImpl, LogListenerMarker,
+                              LogProxy, LogSinkProxy};
     use logger::fx_log_packet_t;
     use zx::prelude::*;
 
diff --git a/bin/logger/test/run_all_tests.cc b/bin/logger/test/run_all_tests.cc
deleted file mode 100644
index 00b3816..0000000
--- a/bin/logger/test/run_all_tests.cc
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gtest/gtest.h"
-
-int main(int argc, char** argv) {
-  testing::InitGoogleTest(&argc, argv);
-  return RUN_ALL_TESTS();
-}
diff --git a/bin/logger/tests/BUILD.gn b/bin/logger/tests/BUILD.gn
new file mode 100644
index 0000000..377fb48
--- /dev/null
+++ b/bin/logger/tests/BUILD.gn
@@ -0,0 +1,12 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+group("tests") {
+  testonly = true
+
+  public_deps = [
+    "cpp:logger_integration_cpp_tests",
+    "go/src:logger_integration_go_tests",
+  ]
+}
diff --git a/bin/logger/tests/cpp/BUILD.gn b/bin/logger/tests/cpp/BUILD.gn
new file mode 100644
index 0000000..a99dde7
--- /dev/null
+++ b/bin/logger/tests/cpp/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+executable("logger_integration_cpp_tests") {
+  testonly = true
+
+  sources = [
+    "logger_tests.cc",
+  ]
+  deps = [
+    "//garnet/public/lib/fxl/test:gtest_main",
+    "//third_party/gtest",
+    "//zircon/public/lib/syslog",
+  ]
+}
diff --git a/bin/logger/test/logger_tests.cc b/bin/logger/tests/cpp/logger_tests.cc
similarity index 100%
rename from bin/logger/test/logger_tests.cc
rename to bin/logger/tests/cpp/logger_tests.cc
diff --git a/bin/logger/test/go/src/logger_integration_test/BUILD.gn b/bin/logger/tests/go/src/BUILD.gn
similarity index 100%
rename from bin/logger/test/go/src/logger_integration_test/BUILD.gn
rename to bin/logger/tests/go/src/BUILD.gn
diff --git a/bin/logger/test/go/src/logger_integration_test/logger_integration_test.go b/bin/logger/tests/go/src/logger_integration_test.go
similarity index 100%
rename from bin/logger/test/go/src/logger_integration_test/logger_integration_test.go
rename to bin/logger/tests/go/src/logger_integration_test.go
diff --git a/bin/mdns/service/BUILD.gn b/bin/mdns/service/BUILD.gn
index 63869af..5686fd6 100644
--- a/bin/mdns/service/BUILD.gn
+++ b/bin/mdns/service/BUILD.gn
@@ -93,6 +93,10 @@
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/netstack/fidl",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
 
 package("service") {
diff --git a/bin/mdns/service/address_prober.cc b/bin/mdns/service/address_prober.cc
index d1c79fa..e92f9c4 100644
--- a/bin/mdns/service/address_prober.cc
+++ b/bin/mdns/service/address_prober.cc
@@ -8,15 +8,12 @@
 
 namespace mdns {
 
-AddressProber::AddressProber(MdnsAgent::Host* host,
-                             const CompletionCallback& callback)
-    : Prober(host, DnsType::kA, callback) {}
+AddressProber::AddressProber(MdnsAgent::Host* host, CompletionCallback callback)
+    : Prober(host, DnsType::kA, std::move(callback)) {}
 
 AddressProber::~AddressProber() {}
 
-const std::string& AddressProber::ResourceName() {
-  return host_full_name();
-}
+const std::string& AddressProber::ResourceName() { return host_full_name(); }
 
 void AddressProber::SendProposedResources(MdnsResourceSection section) {
   SendAddresses(section);
diff --git a/bin/mdns/service/address_prober.h b/bin/mdns/service/address_prober.h
index 1e036db..c57eff0 100644
--- a/bin/mdns/service/address_prober.h
+++ b/bin/mdns/service/address_prober.h
@@ -2,19 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_ADDRESS_PROBER_H_
+#define GARNET_BIN_MDNS_SERVICE_ADDRESS_PROBER_H_
 
 #include "garnet/bin/mdns/service/prober.h"
 
+#include <lib/fit/function.h>
+
 namespace mdns {
 
 // Probes for host name conflicts prior to invoking |AddressResponder|.
 class AddressProber : public Prober {
  public:
-  using CompletionCallback = std::function<void(bool)>;
+  using CompletionCallback = fit::function<void(bool)>;
 
   // Creates an |AddressProber|.
-  AddressProber(MdnsAgent::Host* host, const CompletionCallback& callback);
+  AddressProber(MdnsAgent::Host* host, CompletionCallback callback);
 
   ~AddressProber() override;
 
@@ -26,3 +29,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_ADDRESS_PROBER_H_
diff --git a/bin/mdns/service/address_responder.h b/bin/mdns/service/address_responder.h
index 5b39c67..3973643 100644
--- a/bin/mdns/service/address_responder.h
+++ b/bin/mdns/service/address_responder.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_ADDRESS_RESPONDER_H_
+#define GARNET_BIN_MDNS_SERVICE_ADDRESS_RESPONDER_H_
 
 #include <memory>
 #include <string>
@@ -32,3 +33,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_ADDRESS_RESPONDER_H_
diff --git a/bin/mdns/service/dns_formatting.cc b/bin/mdns/service/dns_formatting.cc
index 151522c..47a937c 100644
--- a/bin/mdns/service/dns_formatting.cc
+++ b/bin/mdns/service/dns_formatting.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/mdns/service/dns_formatting.h"
+
 #include <iomanip>
 #include <iostream>
 
-#include "garnet/bin/mdns/service/dns_formatting.h"
 #include "garnet/bin/mdns/service/dns_message.h"
 
 namespace mdns {
diff --git a/bin/mdns/service/dns_formatting.h b/bin/mdns/service/dns_formatting.h
index 6ca5e65..9884e23 100644
--- a/bin/mdns/service/dns_formatting.h
+++ b/bin/mdns/service/dns_formatting.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_DNS_FORMATTING_H_
+#define GARNET_BIN_MDNS_SERVICE_DNS_FORMATTING_H_
 
 #include <iomanip>
 #include <iostream>
@@ -49,3 +50,5 @@
 std::ostream& operator<<(std::ostream& os, const DnsMessage& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_DNS_FORMATTING_H_
diff --git a/bin/mdns/service/dns_message.h b/bin/mdns/service/dns_message.h
index 5e35e9b..aa3f75e 100644
--- a/bin/mdns/service/dns_message.h
+++ b/bin/mdns/service/dns_message.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_DNS_MESSAGE_H_
+#define GARNET_BIN_MDNS_SERVICE_DNS_MESSAGE_H_
 
 #include <memory>
 #include <string>
@@ -299,3 +300,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_DNS_MESSAGE_H_
diff --git a/bin/mdns/service/dns_reading.cc b/bin/mdns/service/dns_reading.cc
index 5beb258..d3a73bd 100644
--- a/bin/mdns/service/dns_reading.cc
+++ b/bin/mdns/service/dns_reading.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/mdns/service/dns_reading.h"
+
 #include <string.h>
 
-#include "garnet/bin/mdns/service/dns_reading.h"
 #include "lib/fxl/logging.h"
 
 namespace mdns {
diff --git a/bin/mdns/service/dns_reading.h b/bin/mdns/service/dns_reading.h
index 93d7306..29ba48c 100644
--- a/bin/mdns/service/dns_reading.h
+++ b/bin/mdns/service/dns_reading.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_DNS_READING_H_
+#define GARNET_BIN_MDNS_SERVICE_DNS_READING_H_
 
 #include <memory>
 
@@ -43,3 +44,5 @@
 PacketReader& operator>>(PacketReader& reader, DnsMessage& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_DNS_READING_H_
diff --git a/bin/mdns/service/dns_writing.cc b/bin/mdns/service/dns_writing.cc
index 8bdf8f3..efbd380 100644
--- a/bin/mdns/service/dns_writing.cc
+++ b/bin/mdns/service/dns_writing.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/mdns/service/dns_writing.h"
+
 #include <limits>
 
-#include "garnet/bin/mdns/service/dns_writing.h"
 #include "lib/fxl/logging.h"
 
 namespace mdns {
diff --git a/bin/mdns/service/dns_writing.h b/bin/mdns/service/dns_writing.h
index 9c142ed..c00c3a5 100644
--- a/bin/mdns/service/dns_writing.h
+++ b/bin/mdns/service/dns_writing.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_DNS_WRITING_H_
+#define GARNET_BIN_MDNS_SERVICE_DNS_WRITING_H_
 
 #include <memory>
 
@@ -41,3 +42,5 @@
 PacketWriter& operator<<(PacketWriter& writer, const DnsMessage& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_DNS_WRITING_H_
diff --git a/bin/mdns/service/fidl_interface_monitor.cc b/bin/mdns/service/fidl_interface_monitor.cc
index 4e1cf0c..efdc637 100644
--- a/bin/mdns/service/fidl_interface_monitor.cc
+++ b/bin/mdns/service/fidl_interface_monitor.cc
@@ -19,10 +19,11 @@
 FidlInterfaceMonitor::FidlInterfaceMonitor(
     fuchsia::sys::StartupContext* startup_context)
     : binding_(this) {
-  netstack_ =
-      startup_context->ConnectToEnvironmentService<netstack::Netstack>();
+  netstack_ = startup_context
+                  ->ConnectToEnvironmentService<fuchsia::netstack::Netstack>();
 
-  fidl::InterfaceHandle<netstack::NotificationListener> listener_handle;
+  fidl::InterfaceHandle<fuchsia::netstack::NotificationListener>
+      listener_handle;
 
   binding_.Bind(listener_handle.NewRequest());
   binding_.set_error_handler([this]() {
@@ -34,7 +35,7 @@
   netstack_->RegisterListener(std::move(listener_handle));
 
   netstack_->GetInterfaces(
-      [this](fidl::VectorPtr<netstack::NetInterface> interfaces) {
+      [this](fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces) {
         OnInterfacesChanged(std::move(interfaces));
       });
 }
@@ -46,9 +47,8 @@
   }
 }
 
-void FidlInterfaceMonitor::RegisterLinkChangeCallback(
-    const fxl::Closure& callback) {
-  link_change_callback_ = callback;
+void FidlInterfaceMonitor::RegisterLinkChangeCallback(fit::closure callback) {
+  link_change_callback_ = std::move(callback);
 }
 
 const std::vector<std::unique_ptr<InterfaceDescriptor>>&
@@ -57,14 +57,14 @@
 }
 
 void FidlInterfaceMonitor::OnInterfacesChanged(
-    fidl::VectorPtr<netstack::NetInterface> interfaces) {
+    fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces) {
   bool link_change = false;
 
   for (const auto& if_info : *interfaces) {
     IpAddress address = MdnsFidlUtil::IpAddressFrom(&if_info.addr);
 
     if (!address.is_valid() || address.is_loopback() ||
-        (if_info.flags & netstack::NetInterfaceFlagUp) == 0) {
+        (if_info.flags & fuchsia::netstack::NetInterfaceFlagUp) == 0) {
       if (interfaces_.size() > if_info.id &&
           interfaces_[if_info.id] != nullptr) {
         // Interface went away.
diff --git a/bin/mdns/service/fidl_interface_monitor.h b/bin/mdns/service/fidl_interface_monitor.h
index 0213e55..17b8638 100644
--- a/bin/mdns/service/fidl_interface_monitor.h
+++ b/bin/mdns/service/fidl_interface_monitor.h
@@ -7,14 +7,15 @@
 
 #include <memory>
 
-#include <netstack/cpp/fidl.h>
+#include <fuchsia/netstack/cpp/fidl.h>
+
 #include "garnet/bin/mdns/service/interface_monitor.h"
 #include "lib/app/cpp/startup_context.h"
 
 namespace mdns {
 
 // FIDL-based interface monitor implementation.
-class FidlInterfaceMonitor : public netstack::NotificationListener,
+class FidlInterfaceMonitor : public fuchsia::netstack::NotificationListener,
                              public InterfaceMonitor {
  public:
   static std::unique_ptr<InterfaceMonitor> Create(
@@ -25,7 +26,7 @@
   ~FidlInterfaceMonitor();
 
   // InterfaceMonitor implementation.
-  void RegisterLinkChangeCallback(const fxl::Closure& callback) override;
+  void RegisterLinkChangeCallback(fit::closure callback) override;
 
   const std::vector<std::unique_ptr<InterfaceDescriptor>>& GetInterfaces()
       override;
@@ -33,11 +34,11 @@
  private:
   // NotificationListener implementation.
   void OnInterfacesChanged(
-      fidl::VectorPtr<netstack::NetInterface> interfaces) override;
+      fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces) override;
 
-  netstack::NetstackPtr netstack_;
-  fidl::Binding<netstack::NotificationListener> binding_;
-  fxl::Closure link_change_callback_;
+  fuchsia::netstack::NetstackPtr netstack_;
+  fidl::Binding<fuchsia::netstack::NotificationListener> binding_;
+  fit::closure link_change_callback_;
   std::vector<std::unique_ptr<InterfaceDescriptor>> interfaces_;
 };
 
diff --git a/bin/mdns/service/host_name.cc b/bin/mdns/service/host_name.cc
index bf86d32..8c35d94 100644
--- a/bin/mdns/service/host_name.cc
+++ b/bin/mdns/service/host_name.cc
@@ -4,10 +4,10 @@
 
 #include "garnet/bin/mdns/service/host_name.h"
 
+#include <fuchsia/netstack/cpp/fidl.h>
 #include <limits.h>
 #include <unistd.h>
 
-#include <netstack/cpp/fidl.h>
 #include "garnet/bin/mdns/service/mdns_fidl_util.h"
 #include "garnet/bin/mdns/service/socket_address.h"
 #include "lib/app/cpp/startup_context.h"
@@ -22,10 +22,11 @@
 class NetstackClient {
  public:
   static void GetInterfaces(
-      const netstack::Netstack::GetInterfacesCallback& callback) {
+      const fuchsia::netstack::Netstack::GetInterfacesCallback& callback) {
     NetstackClient* client = new NetstackClient();
     client->netstack_->GetInterfaces(
-        [client, callback](fidl::VectorPtr<netstack::NetInterface> interfaces) {
+        [client, callback](
+            fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces) {
           callback(std::move(interfaces));
           delete client;
         });
@@ -35,12 +36,13 @@
   NetstackClient()
       : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
     FXL_DCHECK(context_);
-    netstack_ = context_->ConnectToEnvironmentService<netstack::Netstack>();
+    netstack_ =
+        context_->ConnectToEnvironmentService<fuchsia::netstack::Netstack>();
     FXL_DCHECK(netstack_);
   }
 
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
-  netstack::NetstackPtr netstack_;
+  fuchsia::netstack::NetstackPtr netstack_;
 };
 
 // Returns a host address, preferably V4. Returns an invalid address if no
@@ -52,13 +54,15 @@
     return ip_address;
 
   NetstackClient::GetInterfaces(
-      [](const fidl::VectorPtr<netstack::NetInterface>& interfaces) {
+      [](const fidl::VectorPtr<fuchsia::netstack::NetInterface>& interfaces) {
         for (const auto& interface : *interfaces) {
-          if (interface.addr.family == netstack::NetAddressFamily::IPV4) {
+          if (interface.addr.family ==
+              fuchsia::netstack::NetAddressFamily::IPV4) {
             ip_address = MdnsFidlUtil::IpAddressFrom(&interface.addr);
             break;
           }
-          if (interface.addr.family == netstack::NetAddressFamily::IPV6) {
+          if (interface.addr.family ==
+              fuchsia::netstack::NetAddressFamily::IPV6) {
             ip_address = MdnsFidlUtil::IpAddressFrom(&interface.addr);
             // Keep looking...v4 is preferred.
           }
diff --git a/bin/mdns/service/host_name.h b/bin/mdns/service/host_name.h
index 26bdea9..4148fd9 100644
--- a/bin/mdns/service/host_name.h
+++ b/bin/mdns/service/host_name.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_HOST_NAME_H_
+#define GARNET_BIN_MDNS_SERVICE_HOST_NAME_H_
 
 #include <string>
 
@@ -15,3 +16,5 @@
 std::string GetHostName();
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_HOST_NAME_H_
diff --git a/bin/mdns/service/host_name_resolver.cc b/bin/mdns/service/host_name_resolver.cc
index e4b55cc..9ccaec3 100644
--- a/bin/mdns/service/host_name_resolver.cc
+++ b/bin/mdns/service/host_name_resolver.cc
@@ -10,16 +10,15 @@
 
 namespace mdns {
 
-HostNameResolver::HostNameResolver(
-    MdnsAgent::Host* host,
-    const std::string& host_name,
-    fxl::TimePoint timeout,
-    const Mdns::ResolveHostNameCallback& callback)
+HostNameResolver::HostNameResolver(MdnsAgent::Host* host,
+                                   const std::string& host_name,
+                                   fxl::TimePoint timeout,
+                                   Mdns::ResolveHostNameCallback callback)
     : MdnsAgent(host),
       host_name_(host_name),
       host_full_name_(MdnsNames::LocalHostFullName(host_name)),
       timeout_(timeout),
-      callback_(callback) {
+      callback_(std::move(callback)) {
   FXL_DCHECK(callback_);
 }
 
diff --git a/bin/mdns/service/host_name_resolver.h b/bin/mdns/service/host_name_resolver.h
index c0fce60..e9a0e6f 100644
--- a/bin/mdns/service/host_name_resolver.h
+++ b/bin/mdns/service/host_name_resolver.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_HOST_NAME_RESOLVER_H_
+#define GARNET_BIN_MDNS_SERVICE_HOST_NAME_RESOLVER_H_
 
 #include <memory>
 #include <string>
@@ -18,10 +19,9 @@
 class HostNameResolver : public MdnsAgent {
  public:
   // Creates a |HostNameResolver|.
-  HostNameResolver(MdnsAgent::Host* host,
-                   const std::string& host_name,
+  HostNameResolver(MdnsAgent::Host* host, const std::string& host_name,
                    fxl::TimePoint timeout,
-                   const Mdns::ResolveHostNameCallback& callback);
+                   Mdns::ResolveHostNameCallback callback);
 
   ~HostNameResolver() override;
 
@@ -45,3 +45,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_HOST_NAME_RESOLVER_H_
diff --git a/bin/mdns/service/instance_prober.cc b/bin/mdns/service/instance_prober.cc
index 3e7ae54..ae238d6 100644
--- a/bin/mdns/service/instance_prober.cc
+++ b/bin/mdns/service/instance_prober.cc
@@ -11,10 +11,9 @@
 
 InstanceProber::InstanceProber(MdnsAgent::Host* host,
                                const std::string& service_name,
-                               const std::string& instance_name,
-                               IpPort port,
-                               const CompletionCallback& callback)
-    : Prober(host, DnsType::kSrv, callback),
+                               const std::string& instance_name, IpPort port,
+                               CompletionCallback callback)
+    : Prober(host, DnsType::kSrv, std::move(callback)),
       instance_full_name_(
           MdnsNames::LocalInstanceFullName(instance_name, service_name)),
       port_(port) {}
diff --git a/bin/mdns/service/instance_prober.h b/bin/mdns/service/instance_prober.h
index b62a5ec..e51363f 100644
--- a/bin/mdns/service/instance_prober.h
+++ b/bin/mdns/service/instance_prober.h
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_INSTANCE_PROBER_H_
+#define GARNET_BIN_MDNS_SERVICE_INSTANCE_PROBER_H_
+
+#include <lib/fit/function.h>
 
 #include "garnet/bin/mdns/service/prober.h"
 
@@ -11,14 +14,12 @@
 // Probes for SRV record conflicts prior to invoking |InstanceResponder|.
 class InstanceProber : public Prober {
  public:
-  using CompletionCallback = std::function<void(bool)>;
+  using CompletionCallback = fit::function<void(bool)>;
 
   // Creates a |InstanceProber|.
-  InstanceProber(MdnsAgent::Host* host,
-                 const std::string& service_name,
-                 const std::string& instance_name,
-                 IpPort port,
-                 const CompletionCallback& callback);
+  InstanceProber(MdnsAgent::Host* host, const std::string& service_name,
+                 const std::string& instance_name, IpPort port,
+                 CompletionCallback callback);
 
   ~InstanceProber() override;
 
@@ -34,3 +35,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_INSTANCE_PROBER_H_
diff --git a/bin/mdns/service/instance_requestor.h b/bin/mdns/service/instance_requestor.h
index f69e557..e4c1e70 100644
--- a/bin/mdns/service/instance_requestor.h
+++ b/bin/mdns/service/instance_requestor.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_INSTANCE_REQUESTOR_H_
+#define GARNET_BIN_MDNS_SERVICE_INSTANCE_REQUESTOR_H_
 
 #include <memory>
 #include <string>
@@ -74,8 +75,7 @@
                           InstanceInfo* instance_info);
 
   void ReceiveAResource(const DnsResource& resource,
-                        MdnsResourceSection section,
-                        TargetInfo* target_info);
+                        MdnsResourceSection section, TargetInfo* target_info);
 
   void ReceiveAaaaResource(const DnsResource& resource,
                            MdnsResourceSection section,
@@ -93,3 +93,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_INSTANCE_REQUESTOR_H_
diff --git a/bin/mdns/service/instance_responder.cc b/bin/mdns/service/instance_responder.cc
index 9d78503..00695f6 100644
--- a/bin/mdns/service/instance_responder.cc
+++ b/bin/mdns/service/instance_responder.cc
@@ -113,25 +113,24 @@
 }
 
 void InstanceResponder::GetAndSendPublication(
-    bool query,
-    const std::string& subtype,
+    bool query, const std::string& subtype,
     const ReplyAddress& reply_address) const {
   if (publisher_ == nullptr) {
     return;
   }
 
-  publisher_->GetPublication(query, subtype, [
-    this, subtype, reply_address = reply_address
-  ](std::unique_ptr<Mdns::Publication> publication) {
-    if (publication) {
-      SendPublication(*publication, subtype, reply_address);
-    }
-  });
+  publisher_->GetPublication(
+      query, subtype,
+      [this, subtype, reply_address = reply_address](
+          std::unique_ptr<Mdns::Publication> publication) {
+        if (publication) {
+          SendPublication(*publication, subtype, reply_address);
+        }
+      });
 }
 
 void InstanceResponder::SendPublication(
-    const Mdns::Publication& publication,
-    const std::string& subtype,
+    const Mdns::Publication& publication, const std::string& subtype,
     const ReplyAddress& reply_address) const {
   if (!subtype.empty()) {
     SendSubtypePtrRecord(subtype, publication.ptr_ttl_seconds, reply_address);
@@ -160,8 +159,7 @@
 }
 
 void InstanceResponder::SendSubtypePtrRecord(
-    const std::string& subtype,
-    uint32_t ttl,
+    const std::string& subtype, uint32_t ttl,
     const ReplyAddress& reply_address) const {
   FXL_DCHECK(!subtype.empty());
 
diff --git a/bin/mdns/service/instance_responder.h b/bin/mdns/service/instance_responder.h
index 92aa0a2..cf82b64 100644
--- a/bin/mdns/service/instance_responder.h
+++ b/bin/mdns/service/instance_responder.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_INSTANCE_RESPONDER_H_
+#define GARNET_BIN_MDNS_SERVICE_INSTANCE_RESPONDER_H_
 
 #include <memory>
 #include <string>
@@ -20,8 +21,7 @@
  public:
   // Creates an |InstanceResponder|. The publisher is consulted to determine
   // how queries are handled.
-  InstanceResponder(MdnsAgent::Host* host,
-                    const std::string& service_name,
+  InstanceResponder(MdnsAgent::Host* host, const std::string& service_name,
                     const std::string& instance_name,
                     Mdns::Publisher* publisher);
 
@@ -57,8 +57,7 @@
 
   // Gets an |Mdns::Publication| from |mdns_responder_| and, if not null, sends
   // it. An empty |subtype| indicates no subtype.
-  void GetAndSendPublication(bool query,
-                             const std::string& subtype = "",
+  void GetAndSendPublication(bool query, const std::string& subtype = "",
                              const ReplyAddress& reply_address =
                                  MdnsAddresses::kV4MulticastReply) const;
 
@@ -88,3 +87,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_INSTANCE_RESPONDER_H_
diff --git a/bin/mdns/service/interface_monitor.h b/bin/mdns/service/interface_monitor.h
index 41db5a4..b576b38 100644
--- a/bin/mdns/service/interface_monitor.h
+++ b/bin/mdns/service/interface_monitor.h
@@ -2,14 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_INTERFACE_MONITOR_H_
+#define GARNET_BIN_MDNS_SERVICE_INTERFACE_MONITOR_H_
 
 #include <memory>
 #include <string>
 #include <vector>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/mdns/service/ip_address.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace mdns {
 
@@ -28,7 +30,7 @@
   virtual ~InterfaceMonitor() {}
 
   // Registers a callback to be called when a link change occurs.
-  virtual void RegisterLinkChangeCallback(const fxl::Closure& callback) = 0;
+  virtual void RegisterLinkChangeCallback(fit::closure callback) = 0;
 
   // Returns the current collection of viable interfaces.
   virtual const std::vector<std::unique_ptr<InterfaceDescriptor>>&
@@ -39,3 +41,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_INTERFACE_MONITOR_H_
diff --git a/bin/mdns/service/ip_address.cc b/bin/mdns/service/ip_address.cc
index c539d2e..1aec566 100644
--- a/bin/mdns/service/ip_address.cc
+++ b/bin/mdns/service/ip_address.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/mdns/service/ip_address.h"
+
 #include <sstream>
 
 #include <arpa/inet.h>
 #include <endian.h>
+#include <fuchsia/netstack/cpp/fidl.h>
 #include <netdb.h>
 #include <sys/socket.h>
 
-#include "garnet/bin/mdns/service/ip_address.h"
-#include <netstack/cpp/fidl.h>
-
 namespace mdns {
 
 // static
@@ -79,14 +79,8 @@
   v4_ = addr;
 }
 
-IpAddress::IpAddress(uint16_t w0,
-                     uint16_t w1,
-                     uint16_t w2,
-                     uint16_t w3,
-                     uint16_t w4,
-                     uint16_t w5,
-                     uint16_t w6,
-                     uint16_t w7) {
+IpAddress::IpAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3,
+                     uint16_t w4, uint16_t w5, uint16_t w6, uint16_t w7) {
   family_ = AF_INET;
   uint16_t* words = v6_.s6_addr16;
   words[0] = htobe16(w0);
diff --git a/bin/mdns/service/ip_address.h b/bin/mdns/service/ip_address.h
index 288cb39..8e32aae 100644
--- a/bin/mdns/service/ip_address.h
+++ b/bin/mdns/service/ip_address.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_IP_ADDRESS_H_
+#define GARNET_BIN_MDNS_SERVICE_IP_ADDRESS_H_
 
 #include <arpa/inet.h>
 
@@ -35,14 +36,8 @@
   explicit IpAddress(const in_addr& addr);
 
   // Creates an IPV6 address from eight address words.
-  IpAddress(uint16_t w0,
-            uint16_t w1,
-            uint16_t w2,
-            uint16_t w3,
-            uint16_t w4,
-            uint16_t w5,
-            uint16_t w6,
-            uint16_t w7);
+  IpAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4,
+            uint16_t w5, uint16_t w6, uint16_t w7);
 
   // Creates an IPV6 address from two address words (first and last).
   IpAddress(uint16_t w0, uint16_t w7);
@@ -113,3 +108,5 @@
 std::ostream& operator<<(std::ostream& os, const IpAddress& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_IP_ADDRESS_H_
diff --git a/bin/mdns/service/ip_port.h b/bin/mdns/service/ip_port.h
index 42cf8a6..1b67286 100644
--- a/bin/mdns/service/ip_port.h
+++ b/bin/mdns/service/ip_port.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_IP_PORT_H_
+#define GARNET_BIN_MDNS_SERVICE_IP_PORT_H_
 
 #include <ostream>
 
@@ -80,3 +81,5 @@
 std::ostream& operator<<(std::ostream& os, IpPort value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_IP_PORT_H_
diff --git a/bin/mdns/service/mdns.cc b/bin/mdns/service/mdns.cc
index 4f2f4c9..c7906cb 100644
--- a/bin/mdns/service/mdns.cc
+++ b/bin/mdns/service/mdns.cc
@@ -34,9 +34,7 @@
   transceiver_.EnableInterface(name, family);
 }
 
-void Mdns::SetVerbose(bool verbose) {
-  verbose_ = verbose;
-}
+void Mdns::SetVerbose(bool verbose) { verbose_ = verbose; }
 
 void Mdns::Start(std::unique_ptr<InterfaceMonitor> interface_monitor,
                  const std::string& host_name) {
@@ -125,14 +123,13 @@
   state_ = State::kNotStarted;
 }
 
-void Mdns::ResolveHostName(const std::string& host_name,
-                           fxl::TimePoint timeout,
+void Mdns::ResolveHostName(const std::string& host_name, fxl::TimePoint timeout,
                            ResolveHostNameCallback callback) {
   FXL_DCHECK(MdnsNames::IsValidHostName(host_name));
   FXL_DCHECK(callback);
 
-  AddAgent(
-      std::make_shared<HostNameResolver>(this, host_name, timeout, callback));
+  AddAgent(std::make_shared<HostNameResolver>(this, host_name, timeout,
+                                              std::move(callback)));
 }
 
 void Mdns::SubscribeToService(const std::string& service_name,
@@ -169,9 +166,7 @@
                                       IpPort::From_uint16_t(0), agent);
 }
 
-void Mdns::LogTraffic() {
-  transceiver_.LogTraffic();
-}
+void Mdns::LogTraffic() { transceiver_.LogTraffic(); }
 
 void Mdns::StartAddressProbe(const std::string& host_name) {
   state_ = State::kAddressProbeInProgress;
@@ -230,10 +225,9 @@
   StartAddressProbe(os.str());
 }
 
-void Mdns::PostTaskForTime(MdnsAgent* agent,
-                           fxl::Closure task,
+void Mdns::PostTaskForTime(MdnsAgent* agent, fit::closure task,
                            fxl::TimePoint target_time) {
-  task_queue_.emplace(agent, task, target_time);
+  task_queue_.emplace(agent, std::move(task), target_time);
   PostTask();
 }
 
@@ -302,7 +296,7 @@
 
   while (!temp.empty()) {
     if (temp.top().agent_ != agent) {
-      task_queue_.emplace(temp.top().agent_, temp.top().task_,
+      task_queue_.emplace(temp.top().agent_, std::move(temp.top().task_),
                           temp.top().time_);
     }
 
@@ -330,10 +324,8 @@
 }
 
 bool Mdns::ProbeAndAddInstanceResponder(
-    const std::string& service_name,
-    const std::string& instance_name,
-    IpPort port,
-    std::shared_ptr<InstanceResponder> agent) {
+    const std::string& service_name, const std::string& instance_name,
+    IpPort port, std::shared_ptr<InstanceResponder> agent) {
   FXL_DCHECK(MdnsNames::IsValidServiceName(service_name));
   FXL_DCHECK(MdnsNames::IsValidInstanceName(instance_name));
 
@@ -433,7 +425,7 @@
         fxl::TimePoint now = fxl::TimePoint::Now();
 
         while (!task_queue_.empty() && task_queue_.top().time_ <= now) {
-          fxl::Closure task = task_queue_.top().task_;
+          fit::closure task = std::move(task_queue_.top().task_);
           task_queue_.pop();
           task();
         }
@@ -452,8 +444,7 @@
 
 // static
 std::unique_ptr<Mdns::Publication> Mdns::Publication::Create(
-    IpPort port,
-    const std::vector<std::string>& text) {
+    IpPort port, const std::vector<std::string>& text) {
   auto publication = new Publication();
   publication->port_ = port;
   publication->text_ = text;
@@ -462,9 +453,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-Mdns::Subscriber::~Subscriber() {
-  Unsubscribe();
-}
+Mdns::Subscriber::~Subscriber() { Unsubscribe(); }
 
 void Mdns::Subscriber::Connect(
     std::shared_ptr<InstanceRequestor> instance_requestor) {
@@ -481,9 +470,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-Mdns::Publisher::~Publisher() {
-  Unpublish();
-}
+Mdns::Publisher::~Publisher() { Unpublish(); }
 
 void Mdns::Publisher::SetSubtypes(std::vector<std::string> subtypes) {
   if (instance_responder_) {
diff --git a/bin/mdns/service/mdns.h b/bin/mdns/service/mdns.h
index 42523d1..4097a22 100644
--- a/bin/mdns/service/mdns.h
+++ b/bin/mdns/service/mdns.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_H_
 
 #include <memory>
 #include <queue>
@@ -11,12 +12,12 @@
 #include <vector>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/mdns/service/dns_message.h"
 #include "garnet/bin/mdns/service/mdns_agent.h"
 #include "garnet/bin/mdns/service/mdns_transceiver.h"
 #include "garnet/bin/mdns/service/socket_address.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/time/time_point.h"
 
@@ -114,9 +115,8 @@
     // empty. If the publication provided by the callback is null, no
     // announcement or response is transmitted.
     virtual void GetPublication(
-        bool query,
-        const std::string& subtype,
-        const std::function<void(std::unique_ptr<Publication>)>& callback) = 0;
+        bool query, const std::string& subtype,
+        fit::function<void(std::unique_ptr<Publication>)> callback) = 0;
 
    protected:
     Publisher() {}
@@ -129,10 +129,9 @@
     friend class Mdns;
   };
 
-  using ResolveHostNameCallback =
-      std::function<void(const std::string& host_name,
-                         const IpAddress& v4_address,
-                         const IpAddress& v6_address)>;
+  using ResolveHostNameCallback = fit::function<void(
+      const std::string& host_name, const IpAddress& v4_address,
+      const IpAddress& v6_address)>;
 
   Mdns();
 
@@ -159,8 +158,7 @@
   std::string host_name() { return host_name_; }
 
   // Resolves |host_name| to one or two |IpAddress|es.
-  void ResolveHostName(const std::string& host_name,
-                       fxl::TimePoint timeout,
+  void ResolveHostName(const std::string& host_name, fxl::TimePoint timeout,
                        ResolveHostNameCallback callback);
 
   // Subscribes to the specified service. The subscription is cancelled when
@@ -188,11 +186,14 @@
   };
 
   struct TaskQueueEntry {
-    TaskQueueEntry(MdnsAgent* agent, fxl::Closure task, fxl::TimePoint time)
-        : agent_(agent), task_(task), time_(time) {}
+    TaskQueueEntry(MdnsAgent* agent, fit::closure task, fxl::TimePoint time)
+        : agent_(agent), task_(std::move(task)), time_(time) {}
 
     MdnsAgent* agent_;
-    fxl::Closure task_;
+    // mutable because std::priority_queue doesn't provide a non-const accessor
+    // for its contents which makes it otherwise impossible to move the closure
+    // out of the queue when it is time to dispatch the task
+    mutable fit::closure task_;
     fxl::TimePoint time_;
 
     bool operator<(const TaskQueueEntry& other) const {
@@ -227,8 +228,7 @@
   void OnHostNameConflict();
 
   // MdnsAgent::Host implementation.
-  void PostTaskForTime(MdnsAgent* agent,
-                       fxl::Closure task,
+  void PostTaskForTime(MdnsAgent* agent, fit::closure task,
                        fxl::TimePoint target_time) override;
 
   void SendQuestion(std::shared_ptr<DnsQuestion> question) override;
@@ -304,3 +304,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_H_
diff --git a/bin/mdns/service/mdns_addresses.h b/bin/mdns/service/mdns_addresses.h
index b98f01f..9eb13f9 100644
--- a/bin/mdns/service/mdns_addresses.h
+++ b/bin/mdns/service/mdns_addresses.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_ADDRESSES_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_ADDRESSES_H_
 
 #include <memory>
 #include <vector>
@@ -25,3 +26,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_ADDRESSES_H_
diff --git a/bin/mdns/service/mdns_agent.h b/bin/mdns/service/mdns_agent.h
index 2ad07f0..f6fb2e4 100644
--- a/bin/mdns/service/mdns_agent.h
+++ b/bin/mdns/service/mdns_agent.h
@@ -2,14 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_AGENT_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_AGENT_H_
 
 #include <memory>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/mdns/service/dns_message.h"
 #include "garnet/bin/mdns/service/mdns_addresses.h"
 #include "garnet/bin/mdns/service/socket_address.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/time/time_point.h"
 
 namespace mdns {
@@ -27,8 +29,7 @@
 
     // Posts a task to be executed at the specified time. Scheduled tasks posted
     // by agents that have since been removed are not executed.
-    virtual void PostTaskForTime(MdnsAgent* agent,
-                                 fxl::Closure task,
+    virtual void PostTaskForTime(MdnsAgent* agent, fit::closure task,
                                  fxl::TimePoint target_time) = 0;
 
     // Sends a question to the multicast address.
@@ -87,8 +88,8 @@
 
   // Posts a task to be executed at the specified time. Scheduled tasks posted
   // by agents that have since been removed are not executed.
-  void PostTaskForTime(fxl::Closure task, fxl::TimePoint target_time) {
-    host_->PostTaskForTime(this, task, target_time);
+  void PostTaskForTime(fit::closure task, fxl::TimePoint target_time) {
+    host_->PostTaskForTime(this, std::move(task), target_time);
   }
 
   // Sends a question to the multicast address.
@@ -139,3 +140,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_AGENT_H_
diff --git a/bin/mdns/service/mdns_fidl_util.cc b/bin/mdns/service/mdns_fidl_util.cc
index 8b41c9f..677984c 100644
--- a/bin/mdns/service/mdns_fidl_util.cc
+++ b/bin/mdns/service/mdns_fidl_util.cc
@@ -5,8 +5,8 @@
 #include "garnet/bin/mdns/service/mdns_fidl_util.h"
 
 #include "lib/fsl/types/type_converters.h"
-#include "lib/fxl/type_converter.h"
 #include "lib/fxl/logging.h"
+#include "lib/fxl/type_converter.h"
 
 namespace mdns {
 
@@ -15,10 +15,8 @@
 
 // static
 MdnsServiceInstancePtr MdnsFidlUtil::CreateServiceInstance(
-    const std::string& service_name,
-    const std::string& instance_name,
-    const SocketAddress& v4_address,
-    const SocketAddress& v6_address,
+    const std::string& service_name, const std::string& instance_name,
+    const SocketAddress& v4_address, const SocketAddress& v6_address,
     const std::vector<std::string>& text) {
   MdnsServiceInstancePtr service_instance = MdnsServiceInstance::New();
 
@@ -40,8 +38,7 @@
 // static
 void MdnsFidlUtil::UpdateServiceInstance(
     const MdnsServiceInstancePtr& service_instance,
-    const SocketAddress& v4_address,
-    const SocketAddress& v6_address,
+    const SocketAddress& v4_address, const SocketAddress& v6_address,
     const std::vector<std::string>& text) {
   service_instance->text = fxl::To<fidl::VectorPtr<fidl::StringPtr>>(text);
 
@@ -59,7 +56,7 @@
 }
 
 // static
-netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv4(
+fuchsia::netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv4(
     const IpAddress& ip_address) {
   if (!ip_address) {
     return nullptr;
@@ -67,9 +64,10 @@
 
   FXL_DCHECK(ip_address.is_v4());
 
-  netstack::SocketAddressPtr result = netstack::SocketAddress::New();
-  result->addr.family = netstack::NetAddressFamily::IPV4;
-  result->addr.ipv4 = netstack::Ipv4Address::New();
+  fuchsia::netstack::SocketAddressPtr result =
+      fuchsia::netstack::SocketAddress::New();
+  result->addr.family = fuchsia::netstack::NetAddressFamily::IPV4;
+  result->addr.ipv4 = fuchsia::netstack::Ipv4Address::New();
 
   FXL_DCHECK(result->addr.ipv4->addr.count() == ip_address.byte_count());
   std::memcpy(result->addr.ipv4->addr.mutable_data(), ip_address.as_bytes(),
@@ -79,7 +77,7 @@
 }
 
 // static
-netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv6(
+fuchsia::netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv6(
     const IpAddress& ip_address) {
   if (!ip_address) {
     return nullptr;
@@ -87,9 +85,10 @@
 
   FXL_DCHECK(ip_address.is_v6());
 
-  netstack::SocketAddressPtr result = netstack::SocketAddress::New();
-  result->addr.family = netstack::NetAddressFamily::IPV6;
-  result->addr.ipv6 = netstack::Ipv6Address::New();
+  fuchsia::netstack::SocketAddressPtr result =
+      fuchsia::netstack::SocketAddress::New();
+  result->addr.family = fuchsia::netstack::NetAddressFamily::IPV6;
+  result->addr.ipv6 = fuchsia::netstack::Ipv6Address::New();
 
   FXL_DCHECK(result->addr.ipv6->addr.count() == ip_address.byte_count());
   std::memcpy(result->addr.ipv6->addr.mutable_data(), ip_address.as_bytes(),
@@ -99,7 +98,7 @@
 }
 
 // static
-netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv4(
+fuchsia::netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv4(
     const SocketAddress& socket_address) {
   if (!socket_address) {
     return nullptr;
@@ -107,7 +106,7 @@
 
   FXL_DCHECK(socket_address.is_v4());
 
-  netstack::SocketAddressPtr result =
+  fuchsia::netstack::SocketAddressPtr result =
       CreateSocketAddressIPv4(socket_address.address());
 
   result->port = socket_address.port().as_uint16_t();
@@ -116,7 +115,7 @@
 }
 
 // static
-netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv6(
+fuchsia::netstack::SocketAddressPtr MdnsFidlUtil::CreateSocketAddressIPv6(
     const SocketAddress& socket_address) {
   if (!socket_address) {
     return nullptr;
@@ -124,7 +123,7 @@
 
   FXL_DCHECK(socket_address.is_v6());
 
-  netstack::SocketAddressPtr result =
+  fuchsia::netstack::SocketAddressPtr result =
       CreateSocketAddressIPv6(socket_address.address());
 
   result->port = socket_address.port().as_uint16_t();
@@ -133,23 +132,26 @@
 }
 
 // static
-IpAddress MdnsFidlUtil::IpAddressFrom(const netstack::NetAddress* addr) {
+IpAddress MdnsFidlUtil::IpAddressFrom(
+    const fuchsia::netstack::NetAddress* addr) {
   FXL_DCHECK(addr != nullptr);
   switch (addr->family) {
-    case netstack::NetAddressFamily::IPV4:
+    case fuchsia::netstack::NetAddressFamily::IPV4:
       if (!addr->ipv4) {
         return IpAddress();
       }
 
       FXL_DCHECK(addr->ipv4->addr.count() == sizeof(in_addr));
-      return IpAddress(*reinterpret_cast<const in_addr*>(addr->ipv4->addr.data()));
-    case netstack::NetAddressFamily::IPV6:
+      return IpAddress(
+          *reinterpret_cast<const in_addr*>(addr->ipv4->addr.data()));
+    case fuchsia::netstack::NetAddressFamily::IPV6:
       if (!addr->ipv6) {
         return IpAddress();
       }
 
       FXL_DCHECK(addr->ipv6->addr.count() == sizeof(in6_addr));
-      return IpAddress(*reinterpret_cast<const in6_addr*>(addr->ipv6->addr.data()));
+      return IpAddress(
+          *reinterpret_cast<const in6_addr*>(addr->ipv6->addr.data()));
     default:
       return IpAddress();
   }
diff --git a/bin/mdns/service/mdns_fidl_util.h b/bin/mdns/service/mdns_fidl_util.h
index 61ad18c..3d440b8 100644
--- a/bin/mdns/service/mdns_fidl_util.h
+++ b/bin/mdns/service/mdns_fidl_util.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_FIDL_UTIL_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_FIDL_UTIL_H_
+
+#include <mdns/cpp/fidl.h>
 
 #include "garnet/bin/mdns/service/mdns.h"
 #include "garnet/bin/mdns/service/socket_address.h"
-#include <mdns/cpp/fidl.h>
 
 namespace mdns {
 
@@ -16,34 +18,33 @@
   static const std::string kFuchsiaServiceName;
 
   static MdnsServiceInstancePtr CreateServiceInstance(
-      const std::string& service_name,
-      const std::string& instance_name,
-      const SocketAddress& v4_address,
-      const SocketAddress& v6_address,
+      const std::string& service_name, const std::string& instance_name,
+      const SocketAddress& v4_address, const SocketAddress& v6_address,
       const std::vector<std::string>& text);
 
   static void UpdateServiceInstance(
       const MdnsServiceInstancePtr& service_instance,
-      const SocketAddress& v4_address,
-      const SocketAddress& v6_address,
+      const SocketAddress& v4_address, const SocketAddress& v6_address,
       const std::vector<std::string>& text);
 
-  static netstack::SocketAddressPtr CreateSocketAddressIPv4(
+  static fuchsia::netstack::SocketAddressPtr CreateSocketAddressIPv4(
       const IpAddress& ip_address);
 
-  static netstack::SocketAddressPtr CreateSocketAddressIPv6(
+  static fuchsia::netstack::SocketAddressPtr CreateSocketAddressIPv6(
       const IpAddress& ip_address);
 
-  static netstack::SocketAddressPtr CreateSocketAddressIPv4(
+  static fuchsia::netstack::SocketAddressPtr CreateSocketAddressIPv4(
       const SocketAddress& socket_address);
 
-  static netstack::SocketAddressPtr CreateSocketAddressIPv6(
+  static fuchsia::netstack::SocketAddressPtr CreateSocketAddressIPv6(
       const SocketAddress& socket_address);
 
-  static IpAddress IpAddressFrom(const netstack::NetAddress* addr);
+  static IpAddress IpAddressFrom(const fuchsia::netstack::NetAddress* addr);
 
   static std::unique_ptr<Mdns::Publication> Convert(
       const MdnsPublicationPtr& publication_ptr);
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_FIDL_UTIL_H_
diff --git a/bin/mdns/service/mdns_interface_transceiver.cc b/bin/mdns/service/mdns_interface_transceiver.cc
index 00bfa3c..0649739 100644
--- a/bin/mdns/service/mdns_interface_transceiver.cc
+++ b/bin/mdns/service/mdns_interface_transceiver.cc
@@ -4,15 +4,14 @@
 
 #include "garnet/bin/mdns/service/mdns_interface_transceiver.h"
 
-#include <arpa/inet.h>
-#include <errno.h>
-#include <poll.h>
-#include <sys/socket.h>
-
 #include <iostream>
 
+#include <arpa/inet.h>
+#include <errno.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
+#include <poll.h>
+#include <sys/socket.h>
 
 #include "garnet/bin/mdns/service/dns_formatting.h"
 #include "garnet/bin/mdns/service/dns_reading.h"
@@ -53,7 +52,7 @@
 
 MdnsInterfaceTransceiver::~MdnsInterfaceTransceiver() {}
 
-bool MdnsInterfaceTransceiver::Start(const InboundMessageCallback& callback) {
+bool MdnsInterfaceTransceiver::Start(InboundMessageCallback callback) {
   FXL_DCHECK(callback);
   FXL_DCHECK(!socket_fd_.is_valid()) << "Start called when already started.";
 
@@ -76,7 +75,7 @@
     return false;
   }
 
-  inbound_message_callback_ = callback;
+  inbound_message_callback_ = std::move(callback);
 
   WaitForInbound();
   return true;
diff --git a/bin/mdns/service/mdns_interface_transceiver.h b/bin/mdns/service/mdns_interface_transceiver.h
index de8c39b..32a65a4 100644
--- a/bin/mdns/service/mdns_interface_transceiver.h
+++ b/bin/mdns/service/mdns_interface_transceiver.h
@@ -2,11 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_H_
 
 #include <memory>
 #include <vector>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/mdns/service/dns_message.h"
 #include "garnet/bin/mdns/service/ip_address.h"
 #include "garnet/bin/mdns/service/reply_address.h"
@@ -24,13 +27,13 @@
  public:
   // Callback to deliver inbound messages with reply address.
   using InboundMessageCallback =
-      std::function<void(std::unique_ptr<DnsMessage>, const ReplyAddress&)>;
+      fit::function<void(std::unique_ptr<DnsMessage>, const ReplyAddress&)>;
 
   // Creates the variant of |MdnsInterfaceTransceiver| appropriate for the
   // address family specified in |address|. |name| is the name of the interface,
   // and |index| is its index.
-  static std::unique_ptr<MdnsInterfaceTransceiver>
-  Create(IpAddress address, const std::string& name, uint32_t index);
+  static std::unique_ptr<MdnsInterfaceTransceiver> Create(
+      IpAddress address, const std::string& name, uint32_t index);
 
   virtual ~MdnsInterfaceTransceiver();
 
@@ -39,7 +42,7 @@
   const IpAddress& address() const { return address_; }
 
   // Starts the interface transceiver.
-  bool Start(const InboundMessageCallback& callback);
+  bool Start(InboundMessageCallback callback);
 
   // Stops the interface transceiver.
   void Stop();
@@ -68,8 +71,7 @@
   static constexpr int kTimeToLive_ = 255;
   static constexpr size_t kMaxPacketSize = 1500;
 
-  MdnsInterfaceTransceiver(IpAddress address,
-                           const std::string& name,
+  MdnsInterfaceTransceiver(IpAddress address, const std::string& name,
                            uint32_t index);
 
   uint32_t index() const { return index_; }
@@ -82,8 +84,7 @@
   virtual int SetOptionMulticastTtl() = 0;
   virtual int SetOptionFamilySpecific() = 0;
   virtual int Bind() = 0;
-  virtual int SendTo(const void* buffer,
-                     size_t size,
+  virtual int SendTo(const void* buffer, size_t size,
                      const SocketAddress& address) = 0;
 
  private:
@@ -105,8 +106,7 @@
 
   // Makes an address resource (A/AAAA) record with the given name and address.
   std::shared_ptr<DnsResource> MakeAddressResource(
-      const std::string& host_full_name,
-      const IpAddress& address);
+      const std::string& host_full_name, const IpAddress& address);
 
   // Fixes up the address records in the vector. This method expects there to
   // be at most two address records in the vector and, if there are two, that
@@ -134,3 +134,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_H_
diff --git a/bin/mdns/service/mdns_interface_transceiver_v4.cc b/bin/mdns/service/mdns_interface_transceiver_v4.cc
index a563047..09f6851 100644
--- a/bin/mdns/service/mdns_interface_transceiver_v4.cc
+++ b/bin/mdns/service/mdns_interface_transceiver_v4.cc
@@ -84,8 +84,7 @@
   return result;
 }
 
-int MdnsInterfaceTransceiverV4::SendTo(const void* buffer,
-                                       size_t size,
+int MdnsInterfaceTransceiverV4::SendTo(const void* buffer, size_t size,
                                        const SocketAddress& address) {
   return sendto(socket_fd().get(), buffer, size, 0, address.as_sockaddr(),
                 address.socklen());
diff --git a/bin/mdns/service/mdns_interface_transceiver_v4.h b/bin/mdns/service/mdns_interface_transceiver_v4.h
index 0a2b7b6..04a7311 100644
--- a/bin/mdns/service/mdns_interface_transceiver_v4.h
+++ b/bin/mdns/service/mdns_interface_transceiver_v4.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_V4_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_V4_H_
 
 #include "garnet/bin/mdns/service/mdns_interface_transceiver.h"
 
@@ -21,16 +22,16 @@
   int SetOptionMulticastTtl() override;
   int SetOptionFamilySpecific() override;
   int Bind() override;
-  int SendTo(const void* buffer,
-             size_t size,
+  int SendTo(const void* buffer, size_t size,
              const SocketAddress& address) override;
 
  private:
-  MdnsInterfaceTransceiverV4(IpAddress address,
-                             const std::string& name,
+  MdnsInterfaceTransceiverV4(IpAddress address, const std::string& name,
                              uint32_t index);
 
   friend class MdnsInterfaceTransceiver;  // For constructor.
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_V4_H_
diff --git a/bin/mdns/service/mdns_interface_transceiver_v6.cc b/bin/mdns/service/mdns_interface_transceiver_v6.cc
index 44268eb..1c92a43 100644
--- a/bin/mdns/service/mdns_interface_transceiver_v6.cc
+++ b/bin/mdns/service/mdns_interface_transceiver_v6.cc
@@ -105,8 +105,7 @@
   return result;
 }
 
-int MdnsInterfaceTransceiverV6::SendTo(const void* buffer,
-                                       size_t size,
+int MdnsInterfaceTransceiverV6::SendTo(const void* buffer, size_t size,
                                        const SocketAddress& address) {
   if (address == MdnsAddresses::kV4Multicast) {
     return sendto(socket_fd().get(), buffer, size, 0,
diff --git a/bin/mdns/service/mdns_interface_transceiver_v6.h b/bin/mdns/service/mdns_interface_transceiver_v6.h
index 39c5b60..6cee9c1 100644
--- a/bin/mdns/service/mdns_interface_transceiver_v6.h
+++ b/bin/mdns/service/mdns_interface_transceiver_v6.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_V6_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_V6_H_
 
 #include "garnet/bin/mdns/service/mdns_interface_transceiver.h"
 
@@ -21,16 +22,16 @@
   int SetOptionMulticastTtl() override;
   int SetOptionFamilySpecific() override;
   int Bind() override;
-  int SendTo(const void* buffer,
-             size_t size,
+  int SendTo(const void* buffer, size_t size,
              const SocketAddress& address) override;
 
  private:
-  MdnsInterfaceTransceiverV6(IpAddress address,
-                             const std::string& name,
+  MdnsInterfaceTransceiverV6(IpAddress address, const std::string& name,
                              uint32_t index);
 
   friend class MdnsInterfaceTransceiver;  // For constructor.
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_INTERFACE_TRANSCEIVER_V6_H_
diff --git a/bin/mdns/service/mdns_names.cc b/bin/mdns/service/mdns_names.cc
index a506ea2..02f9ec2 100644
--- a/bin/mdns/service/mdns_names.cc
+++ b/bin/mdns/service/mdns_names.cc
@@ -43,8 +43,7 @@
 // Otherwise leaves |*index_in_out| unchanged and returns false. This function
 // is useful for scanning strings from right to left where |*index_in_out| is
 // initially |name.size()|.
-bool MatchRight(const std::string& name,
-                const std::string& right,
+bool MatchRight(const std::string& name, const std::string& right,
                 size_t* index_in_out) {
   FXL_DCHECK(index_in_out);
   size_t index = *index_in_out;
@@ -82,8 +81,7 @@
 
 // static
 std::string MdnsNames::LocalServiceSubtypeFullName(
-    const std::string& service_name,
-    const std::string& subtype) {
+    const std::string& service_name, const std::string& subtype) {
   FXL_DCHECK(IsValidServiceName(service_name));
   FXL_DCHECK(IsValidOtherName(subtype));
 
diff --git a/bin/mdns/service/mdns_names.h b/bin/mdns/service/mdns_names.h
index e17823f..72b9acd 100644
--- a/bin/mdns/service/mdns_names.h
+++ b/bin/mdns/service/mdns_names.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_NAMES_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_NAMES_H_
 
 #include <string>
 
@@ -24,8 +25,7 @@
   // For example, produces "_bar._sub_foo._tcp.local." from "_foo._tcp." and
   // subtype "_bar.". The simple service name and subtype must both end in ".".
   static std::string LocalServiceSubtypeFullName(
-      const std::string& service_name,
-      const std::string& subtype);
+      const std::string& service_name, const std::string& subtype);
 
   // Constructs a local service instance name from a simple instance name and
   // a simple service name. For example, produces "myfoo._foo._tcp.local." from
@@ -60,3 +60,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_NAMES_H_
diff --git a/bin/mdns/service/mdns_service_impl.cc b/bin/mdns/service/mdns_service_impl.cc
index c81ec73..9e5c93a 100644
--- a/bin/mdns/service/mdns_service_impl.cc
+++ b/bin/mdns/service/mdns_service_impl.cc
@@ -13,6 +13,7 @@
 #include "garnet/bin/mdns/service/mdns_names.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fsl/types/type_converters.h"
+#include "lib/fxl/functional/make_copyable.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/type_converter.h"
 
@@ -210,9 +211,9 @@
 
 MdnsServiceImpl::Subscriber::Subscriber(
     fidl::InterfaceRequest<MdnsServiceSubscription> request,
-    const fxl::Closure& deleter)
+    fit::closure deleter)
     : binding_(this, std::move(request)) {
-  binding_.set_error_handler([this, deleter]() {
+  binding_.set_error_handler([this, deleter = std::move(deleter)]() {
     binding_.set_error_handler(nullptr);
     deleter();
   });
@@ -279,16 +280,16 @@
 
 void MdnsServiceImpl::SimplePublisher::GetPublication(
     bool query, const std::string& subtype,
-    const std::function<void(std::unique_ptr<Mdns::Publication>)>& callback) {
+    fit::function<void(std::unique_ptr<Mdns::Publication>)> callback) {
   callback(Mdns::Publication::Create(port_, text_));
 }
 
 MdnsServiceImpl::ResponderPublisher::ResponderPublisher(
-    MdnsResponderPtr responder, const fxl::Closure& deleter)
+    MdnsResponderPtr responder, fit::closure deleter)
     : responder_(std::move(responder)) {
   FXL_DCHECK(responder_);
 
-  responder_.set_error_handler([this, deleter]() {
+  responder_.set_error_handler([this, deleter = std::move(deleter)]() {
     responder_.set_error_handler(nullptr);
     deleter();
   });
@@ -302,12 +303,14 @@
 
 void MdnsServiceImpl::ResponderPublisher::GetPublication(
     bool query, const std::string& subtype,
-    const std::function<void(std::unique_ptr<Mdns::Publication>)>& callback) {
+    fit::function<void(std::unique_ptr<Mdns::Publication>)> callback) {
   FXL_DCHECK(responder_);
-  responder_->GetPublication(query, subtype,
-                             [callback](MdnsPublicationPtr publication_ptr) {
-                               callback(MdnsFidlUtil::Convert(publication_ptr));
-                             });
+  responder_->GetPublication(
+      query, subtype,
+      fxl::MakeCopyable(
+          [callback = std::move(callback)](MdnsPublicationPtr publication_ptr) {
+            callback(MdnsFidlUtil::Convert(publication_ptr));
+          }));
 }
 
 }  // namespace mdns
diff --git a/bin/mdns/service/mdns_service_impl.h b/bin/mdns/service/mdns_service_impl.h
index 6f78a62..92b9533 100644
--- a/bin/mdns/service/mdns_service_impl.h
+++ b/bin/mdns/service/mdns_service_impl.h
@@ -7,7 +7,9 @@
 
 #include <unordered_map>
 
+#include <lib/fit/function.h>
 #include <mdns/cpp/fidl.h>
+
 #include "garnet/bin/mdns/service/mdns.h"
 #include "garnet/bin/media/util/fidl_publisher.h"
 #include "lib/app/cpp/startup_context.h"
@@ -54,7 +56,7 @@
   class Subscriber : public Mdns::Subscriber, public MdnsServiceSubscription {
    public:
     Subscriber(fidl::InterfaceRequest<MdnsServiceSubscription> request,
-               const fxl::Closure& deleter);
+               fit::closure deleter);
 
     ~Subscriber() override;
 
@@ -98,10 +100,9 @@
     // Mdns::Publisher implementation.
     void ReportSuccess(bool success) override;
 
-    void GetPublication(
-        bool query, const std::string& subtype,
-        const std::function<void(std::unique_ptr<Mdns::Publication>)>& callback)
-        override;
+    void GetPublication(bool query, const std::string& subtype,
+                        fit::function<void(std::unique_ptr<Mdns::Publication>)>
+                            callback) override;
 
     IpPort port_;
     std::vector<std::string> text_;
@@ -113,15 +114,14 @@
   // Publisher for AddResponder.
   class ResponderPublisher : public Mdns::Publisher {
    public:
-    ResponderPublisher(MdnsResponderPtr responder, const fxl::Closure& deleter);
+    ResponderPublisher(MdnsResponderPtr responder, fit::closure deleter);
 
     // Mdns::Publisher implementation.
     void ReportSuccess(bool success) override;
 
-    void GetPublication(
-        bool query, const std::string& subtype,
-        const std::function<void(std::unique_ptr<Mdns::Publication>)>& callback)
-        override;
+    void GetPublication(bool query, const std::string& subtype,
+                        fit::function<void(std::unique_ptr<Mdns::Publication>)>
+                            callback) override;
 
     MdnsResponderPtr responder_;
 
diff --git a/bin/mdns/service/mdns_transceiver.cc b/bin/mdns/service/mdns_transceiver.cc
index 5824f72..e6f57aa 100644
--- a/bin/mdns/service/mdns_transceiver.cc
+++ b/bin/mdns/service/mdns_transceiver.cc
@@ -23,17 +23,16 @@
   enabled_interfaces_.emplace_back(name, family);
 }
 
-void MdnsTransceiver::Start(
-    std::unique_ptr<InterfaceMonitor> interface_monitor,
-    const LinkChangeCallback& link_change_callback,
-    const InboundMessageCallback& inbound_message_callback) {
+void MdnsTransceiver::Start(std::unique_ptr<InterfaceMonitor> interface_monitor,
+                            LinkChangeCallback link_change_callback,
+                            InboundMessageCallback inbound_message_callback) {
   FXL_DCHECK(interface_monitor);
   FXL_DCHECK(link_change_callback);
   FXL_DCHECK(inbound_message_callback);
 
   interface_monitor_ = std::move(interface_monitor);
-  link_change_callback_ = link_change_callback;
-  inbound_message_callback_ = inbound_message_callback;
+  link_change_callback_ = std::move(link_change_callback);
+  inbound_message_callback_ = std::move(inbound_message_callback);
 
   interface_monitor_->RegisterLinkChangeCallback([this]() { OnLinkChange(); });
 
@@ -181,14 +180,13 @@
 }  // namespace mdns
 
 bool MdnsTransceiver::AddInterfaceTransceiver(
-    size_t index,
-    const InterfaceDescriptor& interface_descr) {
+    size_t index, const InterfaceDescriptor& interface_descr) {
   FXL_DCHECK(GetInterfaceTransceiver(index) == nullptr);
 
   auto interface_transceiver = MdnsInterfaceTransceiver::Create(
       interface_descr.address_, interface_descr.name_, index);
 
-  if (!interface_transceiver->Start(inbound_message_callback_)) {
+  if (!interface_transceiver->Start(inbound_message_callback_.share())) {
     // Couldn't start the transceiver.
     return false;
   }
@@ -206,8 +204,7 @@
 }
 
 void MdnsTransceiver::ReplaceInterfaceTransceiver(
-    size_t index,
-    const InterfaceDescriptor& interface_descr) {
+    size_t index, const InterfaceDescriptor& interface_descr) {
   auto interface_transceiver = GetInterfaceTransceiver(index);
   FXL_DCHECK(interface_transceiver);
 
diff --git a/bin/mdns/service/mdns_transceiver.h b/bin/mdns/service/mdns_transceiver.h
index cf033d2..861145e 100644
--- a/bin/mdns/service/mdns_transceiver.h
+++ b/bin/mdns/service/mdns_transceiver.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_MDNS_TRANSCEIVER_H_
+#define GARNET_BIN_MDNS_SERVICE_MDNS_TRANSCEIVER_H_
 
 #include <memory>
 #include <vector>
 
+#include <lib/fit/function.h>
 #include <netinet/in.h>
 
 #include "garnet/bin/mdns/service/interface_monitor.h"
@@ -18,9 +20,9 @@
 // Sends and receives mDNS messages on any number of interfaces.
 class MdnsTransceiver {
  public:
-  using LinkChangeCallback = std::function<void()>;
+  using LinkChangeCallback = fit::closure;
   using InboundMessageCallback =
-      std::function<void(std::unique_ptr<DnsMessage>, const ReplyAddress&)>;
+      fit::function<void(std::unique_ptr<DnsMessage>, const ReplyAddress&)>;
 
   MdnsTransceiver();
 
@@ -34,8 +36,8 @@
 
   // Starts the transceiver.
   void Start(std::unique_ptr<InterfaceMonitor> interface_monitor,
-             const fxl::Closure& link_change_callback,
-             const InboundMessageCallback& inbound_message_callback);
+             fit::closure link_change_callback,
+             InboundMessageCallback inbound_message_callback);
 
   // Stops the transceiver.
   void Stop();
@@ -104,3 +106,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_MDNS_TRANSCEIVER_H_
diff --git a/bin/mdns/service/packet_reader.h b/bin/mdns/service/packet_reader.h
index 940355e..b0b8bcf 100644
--- a/bin/mdns/service/packet_reader.h
+++ b/bin/mdns/service/packet_reader.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_PACKET_READER_H_
+#define GARNET_BIN_MDNS_SERVICE_PACKET_READER_H_
 
 #include <vector>
 
@@ -72,3 +73,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_PACKET_READER_H_
diff --git a/bin/mdns/service/packet_writer.h b/bin/mdns/service/packet_writer.h
index b42d632..9d07bda 100644
--- a/bin/mdns/service/packet_writer.h
+++ b/bin/mdns/service/packet_writer.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_PACKET_WRITER_H_
+#define GARNET_BIN_MDNS_SERVICE_PACKET_WRITER_H_
 
 #include <limits>
 #include <string>
@@ -86,3 +87,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_PACKET_WRITER_H_
diff --git a/bin/mdns/service/prober.cc b/bin/mdns/service/prober.cc
index 7e6f252..643f524 100644
--- a/bin/mdns/service/prober.cc
+++ b/bin/mdns/service/prober.cc
@@ -15,10 +15,8 @@
 constexpr fxl::TimeDelta Prober::kMaxProbeInterval =
     fxl::TimeDelta::FromMilliseconds(250);
 
-Prober::Prober(MdnsAgent::Host* host,
-               DnsType type,
-               const CompletionCallback& callback)
-    : MdnsAgent(host), type_(type), callback_(callback) {
+Prober::Prober(MdnsAgent::Host* host, DnsType type, CompletionCallback callback)
+    : MdnsAgent(host), type_(type), callback_(std::move(callback)) {
   FXL_DCHECK(callback_);
 }
 
@@ -46,7 +44,7 @@
     // so we aren't calling |RemoveSelf| from |ReceiveResource|.
     PostTaskForTime(
         [this]() {
-          CompletionCallback callback = callback_;
+          CompletionCallback callback = std::move(callback_);
           RemoveSelf();
           // This |Prober| has probably been deleted at this point, so we avoid
           // referencing any members.
@@ -69,7 +67,7 @@
       [this]() {
         if (++probe_attempt_count_ > kMaxProbeAttemptCount) {
           // No conflict detected.
-          CompletionCallback callback = callback_;
+          CompletionCallback callback = std::move(callback_);
           RemoveSelf();
           // This |Prober| has probably been deleted at this point, so
           // we avoid referencing any members.
diff --git a/bin/mdns/service/prober.h b/bin/mdns/service/prober.h
index e56129e..e5f2c10 100644
--- a/bin/mdns/service/prober.h
+++ b/bin/mdns/service/prober.h
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_PROBER_H_
+#define GARNET_BIN_MDNS_SERVICE_PROBER_H_
 
-#include <functional>
 #include <memory>
 #include <string>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/mdns/service/mdns_agent.h"
 #include "lib/fxl/time/time_delta.h"
 
@@ -31,13 +33,11 @@
 // there's a conflict. If not, the probe has completed successfully.
 class Prober : public MdnsAgent {
  public:
-  using CompletionCallback = std::function<void(bool)>;
+  using CompletionCallback = fit::function<void(bool)>;
 
   // Creates a |Prober|. |type| is the resource type for which we're probing.
   // Use |kA| for address types (A and AAAA).
-  Prober(MdnsAgent::Host* host,
-         DnsType type,
-         const CompletionCallback& callback);
+  Prober(MdnsAgent::Host* host, DnsType type, CompletionCallback callback);
 
   ~Prober() override;
 
@@ -75,3 +75,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_PROBER_H_
diff --git a/bin/mdns/service/reply_address.h b/bin/mdns/service/reply_address.h
index ac02010..f47e609 100644
--- a/bin/mdns/service/reply_address.h
+++ b/bin/mdns/service/reply_address.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_REPLY_ADDRESS_H_
+#define GARNET_BIN_MDNS_SERVICE_REPLY_ADDRESS_H_
 
 #include <ostream>
 
@@ -45,3 +46,5 @@
 std::ostream& operator<<(std::ostream& os, const ReplyAddress& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_REPLY_ADDRESS_H_
diff --git a/bin/mdns/service/resource_renewer.h b/bin/mdns/service/resource_renewer.h
index 907b0f9..49ae5cf 100644
--- a/bin/mdns/service/resource_renewer.h
+++ b/bin/mdns/service/resource_renewer.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_RESOURCE_RENEWER_H_
+#define GARNET_BIN_MDNS_SERVICE_RESOURCE_RENEWER_H_
 
 #include <memory>
 #include <queue>
@@ -122,3 +123,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_RESOURCE_RENEWER_H_
diff --git a/bin/mdns/service/socket_address.cc b/bin/mdns/service/socket_address.cc
index 5d3fdba..3cce59e 100644
--- a/bin/mdns/service/socket_address.cc
+++ b/bin/mdns/service/socket_address.cc
@@ -13,14 +13,9 @@
 // static
 const SocketAddress SocketAddress::kInvalid;
 
-SocketAddress::SocketAddress() {
-  std::memset(&v6_, 0, sizeof(v6_));
-}
+SocketAddress::SocketAddress() { std::memset(&v6_, 0, sizeof(v6_)); }
 
-SocketAddress::SocketAddress(uint8_t b0,
-                             uint8_t b1,
-                             uint8_t b2,
-                             uint8_t b3,
+SocketAddress::SocketAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3,
                              IpPort port) {
   std::memset(&v4_, 0, sizeof(v4_));
   v4_.sin_family = AF_INET;
@@ -44,14 +39,8 @@
   v4_ = addr;
 }
 
-SocketAddress::SocketAddress(uint16_t w0,
-                             uint16_t w1,
-                             uint16_t w2,
-                             uint16_t w3,
-                             uint16_t w4,
-                             uint16_t w5,
-                             uint16_t w6,
-                             uint16_t w7,
+SocketAddress::SocketAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3,
+                             uint16_t w4, uint16_t w5, uint16_t w6, uint16_t w7,
                              IpPort port) {
   std::memset(&v6_, 0, sizeof(v6_));
   v6_.sin6_family = AF_INET6;
diff --git a/bin/mdns/service/socket_address.h b/bin/mdns/service/socket_address.h
index 662ef67..e5a7911 100644
--- a/bin/mdns/service/socket_address.h
+++ b/bin/mdns/service/socket_address.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_SERVICE_SOCKET_ADDRESS_H_
+#define GARNET_BIN_MDNS_SERVICE_SOCKET_ADDRESS_H_
 
 #include <ostream>
 
@@ -33,15 +34,8 @@
   explicit SocketAddress(const sockaddr_in& addr);
 
   // Creates an IPV6 socket address from eight address words and an IpPort.
-  SocketAddress(uint16_t w0,
-                uint16_t w1,
-                uint16_t w2,
-                uint16_t w3,
-                uint16_t w4,
-                uint16_t w5,
-                uint16_t w6,
-                uint16_t w7,
-                IpPort port);
+  SocketAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4,
+                uint16_t w5, uint16_t w6, uint16_t w7, IpPort port);
 
   // Creates an IPV6 socket address from two address words and an IpPort.
   SocketAddress(uint16_t w0, uint16_t w7, IpPort port);
@@ -111,3 +105,5 @@
 std::ostream& operator<<(std::ostream& os, const SocketAddress& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_SERVICE_SOCKET_ADDRESS_H_
diff --git a/bin/mdns/standalone/ioctl_interface_monitor.cc b/bin/mdns/standalone/ioctl_interface_monitor.cc
index 5979737..a827ed9 100644
--- a/bin/mdns/standalone/ioctl_interface_monitor.cc
+++ b/bin/mdns/standalone/ioctl_interface_monitor.cc
@@ -5,10 +5,9 @@
 #include "garnet/bin/mdns/standalone/ioctl_interface_monitor.h"
 
 #include <errno.h>
-#include <sys/socket.h>
-
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
+#include <sys/socket.h>
 #include <zx/time.h>
 
 #include "garnet/bin/mdns/service/ip_address.h"
@@ -37,9 +36,8 @@
 
 IoctlInterfaceMonitor::~IoctlInterfaceMonitor() {}
 
-void IoctlInterfaceMonitor::RegisterLinkChangeCallback(
-    const fxl::Closure& callback) {
-  link_change_callback_ = callback;
+void IoctlInterfaceMonitor::RegisterLinkChangeCallback(fit::closure callback) {
+  link_change_callback_ = std::move(callback);
 }
 
 const std::vector<std::unique_ptr<InterfaceDescriptor>>&
@@ -66,7 +64,8 @@
   }
 
   netc_get_if_info_t if_infos;
-  const ssize_t size = ioctl_netc_get_num_ifs(socket_fd.get(), &if_infos.n_info);
+  const ssize_t size =
+      ioctl_netc_get_num_ifs(socket_fd.get(), &if_infos.n_info);
   if (size < 0 || if_infos.n_info == 0) {
     return true;
   }
diff --git a/bin/mdns/standalone/ioctl_interface_monitor.h b/bin/mdns/standalone/ioctl_interface_monitor.h
index 58fd178..a881809 100644
--- a/bin/mdns/standalone/ioctl_interface_monitor.h
+++ b/bin/mdns/standalone/ioctl_interface_monitor.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_STANDALONE_IOCTL_INTERFACE_MONITOR_H_
+#define GARNET_BIN_MDNS_STANDALONE_IOCTL_INTERFACE_MONITOR_H_
 
 #include <memory>
 
@@ -21,7 +22,7 @@
   ~IoctlInterfaceMonitor();
 
   // InterfaceMonitor implementation.
-  void RegisterLinkChangeCallback(const fxl::Closure& callback) override;
+  void RegisterLinkChangeCallback(fit::closure callback) override;
 
   const std::vector<std::unique_ptr<InterfaceDescriptor>>& GetInterfaces()
       override;
@@ -35,9 +36,11 @@
   // interfaces should be checked again soon.
   bool CheckInterfaces();
 
-  fxl::Closure link_change_callback_;
+  fit::closure link_change_callback_;
   std::vector<std::unique_ptr<InterfaceDescriptor>> interfaces_;
   fxl::CancelableClosure poll_closure_;
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_STANDALONE_IOCTL_INTERFACE_MONITOR_H_
diff --git a/bin/mdns/standalone/mdns_standalone.cc b/bin/mdns/standalone/mdns_standalone.cc
index da30e72..2a51119 100644
--- a/bin/mdns/standalone/mdns_standalone.cc
+++ b/bin/mdns/standalone/mdns_standalone.cc
@@ -114,9 +114,8 @@
 }
 
 void MdnsStandalone::GetPublication(
-    bool query,
-    const std::string& subtype,
-    const std::function<void(std::unique_ptr<Mdns::Publication>)>& callback) {
+    bool query, const std::string& subtype,
+    fit::function<void(std::unique_ptr<Mdns::Publication>)> callback) {
   FXL_DCHECK(callback);
   callback(Mdns::Publication::Create(IpPort::From_uint16_t(6666),
                                      {"some", "metadata"}));
diff --git a/bin/mdns/standalone/mdns_standalone.h b/bin/mdns/standalone/mdns_standalone.h
index 78186f4..2a216d9 100644
--- a/bin/mdns/standalone/mdns_standalone.h
+++ b/bin/mdns/standalone/mdns_standalone.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_STANDALONE_MDNS_STANDALONE_H_
+#define GARNET_BIN_MDNS_STANDALONE_MDNS_STANDALONE_H_
 
 #include "garnet/bin/mdns/service/mdns.h"
 #include "lib/fxl/macros.h"
@@ -25,8 +26,7 @@
                           const SocketAddress& v6_address,
                           const std::vector<std::string>& text) override;
 
-  void InstanceChanged(const std::string& service,
-                       const std::string& instance,
+  void InstanceChanged(const std::string& service, const std::string& instance,
                        const SocketAddress& v4_address,
                        const SocketAddress& v6_address,
                        const std::vector<std::string>& text) override;
@@ -39,11 +39,9 @@
   // Mdns::Publisher implementation:
   void ReportSuccess(bool success) override;
 
-  void GetPublication(
-      bool query,
-      const std::string& subtype,
-      const std::function<void(std::unique_ptr<Mdns::Publication>)>& callback)
-      override;
+  void GetPublication(bool query, const std::string& subtype,
+                      fit::function<void(std::unique_ptr<Mdns::Publication>)>
+                          callback) override;
 
   mdns::Mdns mdns_;
 
@@ -51,3 +49,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_STANDALONE_MDNS_STANDALONE_H_
diff --git a/bin/mdns/tool/formatting.cc b/bin/mdns/tool/formatting.cc
index fcafaae..ef3379c 100644
--- a/bin/mdns/tool/formatting.cc
+++ b/bin/mdns/tool/formatting.cc
@@ -55,12 +55,12 @@
 }
 
 std::ostream& operator<<(std::ostream& os,
-                         const netstack::SocketAddress& value) {
-  if (value.addr.family == netstack::NetAddressFamily::UNSPECIFIED) {
+                         const fuchsia::netstack::SocketAddress& value) {
+  if (value.addr.family == fuchsia::netstack::NetAddressFamily::UNSPECIFIED) {
     return os << "<unspecified>";
   }
 
-  if (value.addr.family == netstack::NetAddressFamily::IPV4) {
+  if (value.addr.family == fuchsia::netstack::NetAddressFamily::IPV4) {
     const uint8_t* bytes =
         reinterpret_cast<const uint8_t*>(value.addr.ipv4->addr.data());
     os << static_cast<int>(bytes[0]) << '.' << static_cast<int>(bytes[1]) << '.'
diff --git a/bin/mdns/tool/formatting.h b/bin/mdns/tool/formatting.h
index ca74a70..7ceb482 100644
--- a/bin/mdns/tool/formatting.h
+++ b/bin/mdns/tool/formatting.h
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_TOOL_FORMATTING_H_
+#define GARNET_BIN_MDNS_TOOL_FORMATTING_H_
 
 #include <iomanip>
 #include <iostream>
 
+#include <fuchsia/netstack/cpp/fidl.h>
 #include <mdns/cpp/fidl.h>
-#include <netstack/cpp/fidl.h>
 
 namespace mdns {
 
@@ -32,6 +33,8 @@
 
 std::ostream& operator<<(std::ostream& os, const MdnsServiceInstance& value);
 std::ostream& operator<<(std::ostream& os,
-                         const netstack::SocketAddress& value);
+                         const fuchsia::netstack::SocketAddress& value);
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_TOOL_FORMATTING_H_
diff --git a/bin/mdns/tool/mdns_impl.cc b/bin/mdns/tool/mdns_impl.cc
index 62c1fa2..b661445 100644
--- a/bin/mdns/tool/mdns_impl.cc
+++ b/bin/mdns/tool/mdns_impl.cc
@@ -9,8 +9,8 @@
 
 #include <lib/async-loop/loop.h>
 #include <lib/async/default.h>
-
 #include <mdns/cpp/fidl.h>
+
 #include "garnet/bin/mdns/tool/formatting.h"
 #include "garnet/bin/mdns/tool/mdns_params.h"
 #include "lib/fsl/types/type_converters.h"
@@ -20,8 +20,8 @@
 namespace mdns {
 
 MdnsImpl::MdnsImpl(fuchsia::sys::StartupContext* startup_context,
-                   MdnsParams* params, fxl::Closure quit_callback)
-    : quit_callback_(quit_callback), binding_(this) {
+                   MdnsParams* params, fit::closure quit_callback)
+    : quit_callback_(std::move(quit_callback)), binding_(this) {
   FXL_DCHECK(startup_context);
   FXL_DCHECK(params);
   FXL_DCHECK(quit_callback_);
@@ -89,8 +89,8 @@
   std::cout << "resolving " << host_name << "\n";
   mdns_service_->ResolveHostName(
       host_name, timeout_seconds * 1000,
-      [this](netstack::SocketAddressPtr v4Address,
-             netstack::SocketAddressPtr v6Address) {
+      [this](fuchsia::netstack::SocketAddressPtr v4Address,
+             fuchsia::netstack::SocketAddressPtr v6Address) {
         if (v4Address) {
           std::cout << "IPv4 address: " << *v4Address << "\n";
         }
diff --git a/bin/mdns/tool/mdns_impl.h b/bin/mdns/tool/mdns_impl.h
index ae3779d..28e9ffe 100644
--- a/bin/mdns/tool/mdns_impl.h
+++ b/bin/mdns/tool/mdns_impl.h
@@ -5,13 +5,13 @@
 #ifndef GARNET_BIN_MDNS_TOOL_MDNS_IMPL_H_
 #define GARNET_BIN_MDNS_TOOL_MDNS_IMPL_H_
 
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 #include <mdns/cpp/fidl.h>
 
 #include "garnet/bin/mdns/tool/mdns_params.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fsl/tasks/fd_waiter.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/mdns/cpp/service_subscriber.h"
 
@@ -20,7 +20,7 @@
 class MdnsImpl : public MdnsResponder {
  public:
   MdnsImpl(fuchsia::sys::StartupContext* startup_context, MdnsParams* params,
-           fxl::Closure quit_callback);
+           fit::closure quit_callback);
 
   ~MdnsImpl() override;
 
@@ -51,7 +51,7 @@
   void GetPublication(bool query, fidl::StringPtr subtype,
                       GetPublicationCallback callback) override;
 
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   MdnsServicePtr mdns_service_;
   ServiceSubscriber subscriber_;
   fidl::Binding<MdnsResponder> binding_;
diff --git a/bin/mdns/tool/mdns_params.cc b/bin/mdns/tool/mdns_params.cc
index 17819d8..5eaaed2 100644
--- a/bin/mdns/tool/mdns_params.cc
+++ b/bin/mdns/tool/mdns_params.cc
@@ -4,6 +4,7 @@
 
 #include "garnet/bin/mdns/tool/mdns_params.h"
 
+#include <functional>
 #include <iostream>
 
 #include "lib/fxl/logging.h"
@@ -165,7 +166,7 @@
 }
 
 bool MdnsParams::Parse(const std::string& string_value,
-                           std::vector<std::string>* out) {
+                       std::vector<std::string>* out) {
   FXL_DCHECK(out);
 
   if (string_value.empty()) {
@@ -187,7 +188,7 @@
 }
 
 bool MdnsParams::ParseHostName(const std::string& string_value,
-                                   std::string* out) {
+                               std::string* out) {
   FXL_DCHECK(out);
 
   if (string_value.empty() || string_value[string_value.size() - 1] == '.') {
@@ -200,7 +201,7 @@
 }
 
 bool MdnsParams::ParseServiceName(const std::string& string_value,
-                                      std::string* out) {
+                                  std::string* out) {
   FXL_DCHECK(out);
 
   if (string_value.size() <= kTcpSuffix.size()) {
@@ -221,7 +222,7 @@
 }
 
 bool MdnsParams::ParseInstanceName(const std::string& string_value,
-                                       std::string* out) {
+                                   std::string* out) {
   FXL_DCHECK(out);
 
   if (string_value.empty() || string_value[string_value.size() - 1] == '.') {
diff --git a/bin/mdns/tool/mdns_params.h b/bin/mdns/tool/mdns_params.h
index 7db686c..412f804 100644
--- a/bin/mdns/tool/mdns_params.h
+++ b/bin/mdns/tool/mdns_params.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MDNS_TOOL_MDNS_PARAMS_H_
+#define GARNET_BIN_MDNS_TOOL_MDNS_PARAMS_H_
 
 #include <string>
 
@@ -58,3 +59,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // GARNET_BIN_MDNS_TOOL_MDNS_PARAMS_H_
diff --git a/bin/media/audio_policy/audio_policy_service_impl.cc b/bin/media/audio_policy/audio_policy_service_impl.cc
index cae556f..d1fa73f 100644
--- a/bin/media/audio_policy/audio_policy_service_impl.cc
+++ b/bin/media/audio_policy/audio_policy_service_impl.cc
@@ -11,8 +11,6 @@
 #include "lib/fxl/files/directory.h"
 #include "lib/fxl/files/file.h"
 
-using media::kMutedGain;
-
 namespace audio_policy {
 namespace {
 
@@ -50,17 +48,17 @@
 }
 
 void AudioPolicyServiceImpl::SetSystemAudioGain(float db) {
-  db = std::max(std::min(db, kMaxSystemAudioGain), kMutedGain);
+  db = std::max(std::min(db, kMaxSystemAudioGain), fuchsia::media::kMutedGain);
 
   if (system_audio_gain_db_ == db) {
     return;
   }
 
-  if (db == kMutedGain) {
+  if (db == fuchsia::media::kMutedGain) {
     // System audio gain is being set to |kMutedGain|. This implicitly mutes
     // system audio.
     system_audio_muted_ = true;
-  } else if (system_audio_gain_db_ == kMutedGain) {
+  } else if (system_audio_gain_db_ == fuchsia::media::kMutedGain) {
     // System audio was muted, because gain was set to |kMutedGain|. We're
     // raising the gain now, so we unmute.
     system_audio_muted_ = false;
@@ -74,7 +72,7 @@
 }
 
 void AudioPolicyServiceImpl::SetSystemAudioMute(bool muted) {
-  if (system_audio_gain_db_ == kMutedGain) {
+  if (system_audio_gain_db_ == fuchsia::media::kMutedGain) {
     // Keep audio muted if system audio gain is set to |kMutedGain|.
     muted = true;
   }
@@ -163,7 +161,8 @@
   }
 
   audio_service_ =
-      startup_context_->ConnectToEnvironmentService<media::AudioServer>();
+      startup_context_
+          ->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   audio_service_.set_error_handler([this]() {
     audio_service_.set_error_handler(nullptr);
diff --git a/bin/media/audio_policy/audio_policy_service_impl.h b/bin/media/audio_policy/audio_policy_service_impl.h
index b23649a..630a502 100644
--- a/bin/media/audio_policy/audio_policy_service_impl.h
+++ b/bin/media/audio_policy/audio_policy_service_impl.h
@@ -58,7 +58,8 @@
   // Returns the effective system audio gain based on |system_audio_gain_db_|
   // and |system_audio_muted_|.
   float effective_system_audio_gain() {
-    return system_audio_muted_ ? media::kMutedGain : system_audio_gain_db_;
+    return system_audio_muted_ ? fuchsia::media::kMutedGain
+                               : system_audio_gain_db_;
   }
 
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
@@ -66,7 +67,7 @@
   float system_audio_gain_db_ = kDefaultSystemAudioGainDb;
   bool system_audio_muted_ = kDefaultSystemMuted;
   media::FidlPublisher<GetStatusCallback> status_publisher_;
-  media::AudioServerPtr audio_service_;
+  fuchsia::media::AudioServerPtr audio_service_;
   uint32_t initialize_attempts_remaining_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(AudioPolicyServiceImpl);
diff --git a/bin/media/audio_server/BUILD.gn b/bin/media/audio_server/BUILD.gn
index 15918f1..2600a99 100644
--- a/bin/media/audio_server/BUILD.gn
+++ b/bin/media/audio_server/BUILD.gn
@@ -61,14 +61,14 @@
     "audio_pipe.h",
     "audio_plug_detector.cc",
     "audio_plug_detector.h",
-    "audio_renderer_format_info.cc",
-    "audio_renderer_format_info.h",
-    "audio_renderer_impl.cc",
-    "audio_renderer_impl.h",
     "audio_renderer1_impl.cc",
     "audio_renderer1_impl.h",
     "audio_renderer2_impl.cc",
     "audio_renderer2_impl.h",
+    "audio_renderer_format_info.cc",
+    "audio_renderer_format_info.h",
+    "audio_renderer_impl.cc",
+    "audio_renderer_impl.h",
     "audio_server_impl.cc",
     "audio_server_impl.h",
     "driver_output.cc",
@@ -105,8 +105,13 @@
     "//zircon/public/lib/audio-proto-utils",
     "//zircon/public/lib/dispatcher-pool",
     "//zircon/public/lib/fbl",
+    "//zircon/public/lib/vmo-utils",
     "//zircon/public/lib/zx",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
 
 test("tests") {
diff --git a/bin/media/audio_server/audio_capturer_impl.cc b/bin/media/audio_server/audio_capturer_impl.cc
index 8554f7a..b64d706 100644
--- a/bin/media/audio_server/audio_capturer_impl.cc
+++ b/bin/media/audio_server/audio_capturer_impl.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/media/audio_server/audio_capturer_impl.h"
+
 #include <fbl/auto_call.h>
 
 #include "garnet/bin/media/audio_server/audio_server_impl.h"
 #include "lib/fxl/logging.h"
 #include "lib/media/audio/types.h"
 
-#include "garnet/bin/media/audio_server/audio_capturer_impl.h"
-
 // Allow up to (at most) 256 slabs of pending capture buffers.  At 16KB per
 // slab, this means we will deny allocations after 4MB.  If we ever need more
 // than 4MB of pending capture buffer bookkeeping, something has gone seriously
@@ -28,14 +28,16 @@
 AtomicGenerationId AudioCapturerImpl::PendingCaptureBuffer::sequence_generator;
 
 fbl::RefPtr<AudioCapturerImpl> AudioCapturerImpl::Create(
-    fidl::InterfaceRequest<AudioCapturer> audio_capturer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioCapturer>
+        audio_capturer_request,
     AudioServerImpl* owner, bool loopback) {
   return fbl::AdoptRef(new AudioCapturerImpl(std::move(audio_capturer_request),
                                              owner, loopback));
 }
 
 AudioCapturerImpl::AudioCapturerImpl(
-    fidl::InterfaceRequest<AudioCapturer> audio_capturer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioCapturer>
+        audio_capturer_request,
     AudioServerImpl* owner, bool loopback)
     : AudioObject(Type::Capturer),
       binding_(this, std::move(audio_capturer_request)),
@@ -54,8 +56,8 @@
 
   // TODO(johngro) : Initialize this with the native configuration of the source
   // we are initally bound to.
-  format_ = AudioMediaTypeDetails::New();
-  UpdateFormat(media::AudioSampleFormat::SIGNED_16, 1, 8000);
+  format_ = fuchsia::media::AudioMediaTypeDetails::New();
+  UpdateFormat(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 8000);
 }
 
 AudioCapturerImpl::~AudioCapturerImpl() {
@@ -65,7 +67,8 @@
   FXL_DCHECK(payload_buf_size_ == 0);
 }
 
-void AudioCapturerImpl::SetInitialFormat(AudioMediaTypeDetails format) {
+void AudioCapturerImpl::SetInitialFormat(
+    fuchsia::media::AudioMediaTypeDetails format) {
   UpdateFormat(format.sample_format, format.channels, format.frames_per_second);
 }
 
@@ -142,14 +145,14 @@
 }
 
 void AudioCapturerImpl::GetMediaType(GetMediaTypeCallback cbk) {
-  MediaType ret;
-  ret.medium = MediaTypeMedium::AUDIO;
-  ret.encoding = kAudioEncodingLpcm;
+  fuchsia::media::MediaType ret;
+  ret.medium = fuchsia::media::MediaTypeMedium::AUDIO;
+  ret.encoding = fuchsia::media::kAudioEncodingLpcm;
   ret.details.set_audio(*format_);
   cbk(std::move(ret));
 }
 
-void AudioCapturerImpl::SetMediaType(MediaType media_type) {
+void AudioCapturerImpl::SetMediaType(fuchsia::media::MediaType media_type) {
   // If something goes wrong, hang up the phone and shutdown.
   auto cleanup = fbl::MakeAutoCall([this]() { Shutdown(); });
 
@@ -164,8 +167,8 @@
   }
 
   // The specified media type needs to be audio LPCM
-  if ((media_type.medium != MediaTypeMedium::AUDIO) ||
-      (media_type.encoding != kAudioEncodingLpcm) ||
+  if ((media_type.medium != fuchsia::media::MediaTypeMedium::AUDIO) ||
+      (media_type.encoding != fuchsia::media::kAudioEncodingLpcm) ||
       !media_type.details.is_audio()) {
     FXL_LOG(ERROR) << "Bad media type!";
     return;
@@ -173,27 +176,29 @@
 
   // Sanity check the details of the mode request.
   const auto& details = media_type.details.audio();
-  if ((details.channels < media::kMinLpcmChannelCount) ||
-      (details.channels > media::kMaxLpcmChannelCount)) {
+  if ((details.channels < fuchsia::media::kMinLpcmChannelCount) ||
+      (details.channels > fuchsia::media::kMaxLpcmChannelCount)) {
     FXL_LOG(ERROR) << "Bad channel count, " << details.channels
-                   << " is not in the range [" << media::kMinLpcmChannelCount
-                   << ", " << media::kMaxLpcmChannelCount << "]";
+                   << " is not in the range ["
+                   << fuchsia::media::kMinLpcmChannelCount << ", "
+                   << fuchsia::media::kMaxLpcmChannelCount << "]";
     return;
   }
 
-  if ((details.frames_per_second < media::kMinLpcmFramesPerSecond) ||
-      (details.frames_per_second > media::kMaxLpcmFramesPerSecond)) {
+  if ((details.frames_per_second < fuchsia::media::kMinLpcmFramesPerSecond) ||
+      (details.frames_per_second > fuchsia::media::kMaxLpcmFramesPerSecond)) {
     FXL_LOG(ERROR) << "Bad frame rate, " << details.frames_per_second
-                   << " is not in the range [" << media::kMinLpcmFramesPerSecond
-                   << ", " << media::kMaxLpcmFramesPerSecond << "]";
+                   << " is not in the range ["
+                   << fuchsia::media::kMinLpcmFramesPerSecond << ", "
+                   << fuchsia::media::kMaxLpcmFramesPerSecond << "]";
     return;
   }
 
   switch (details.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
-    case AudioSampleFormat::SIGNED_16:
-    case AudioSampleFormat::SIGNED_24_IN_32:
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       break;
 
     default:
@@ -453,7 +458,7 @@
   }
 
   if (!finished.is_empty()) {
-    finished.back().flags |= kFlagEos;
+    finished.back().flags |= fuchsia::media::kFlagEos;
     FinishBuffers(finished);
   }
 }
@@ -615,7 +620,7 @@
         // produce is guaranteed to be discontinuous relative to the previous
         // one (if any).
         if (!frames_to_clock_mono_.invertable()) {
-          p.flags |= kFlagDiscontinuous;
+          p.flags |= fuchsia::media::kFlagDiscontinuous;
         }
 
         // If we are still running, there should be no way that our shared
@@ -744,7 +749,7 @@
           FXL_DCHECK(p.filled_frames <= p.num_frames);
 
           // Assign a timestamp if one has not already been assigned.
-          if (p.capture_timestamp == kNoTimestamp) {
+          if (p.capture_timestamp == fuchsia::media::kNoTimestamp) {
             FXL_DCHECK(frames_to_clock_mono_.invertable());
             p.capture_timestamp = frames_to_clock_mono_.Apply(frame_count_);
           }
@@ -1153,7 +1158,7 @@
     }
 
     if (!finished_capture_buffers_.is_empty()) {
-      finished_capture_buffers_.back().flags |= kFlagEos;
+      finished_capture_buffers_.back().flags |= fuchsia::media::kFlagEos;
     }
   }
 
@@ -1246,12 +1251,12 @@
   if (!finished.is_empty()) {
     FinishBuffers(std::move(finished));
   } else {
-    MediaPacket pkt;
+    fuchsia::media::MediaPacket pkt;
 
-    pkt.pts = kNoTimestamp;
+    pkt.pts = fuchsia::media::kNoTimestamp;
     pkt.pts_rate_ticks = format_->frames_per_second;
     pkt.pts_rate_seconds = 1u;
-    pkt.flags = kFlagEos;
+    pkt.flags = fuchsia::media::kFlagEos;
     pkt.payload_buffer_id = 0u;
     pkt.payload_offset = 0u;
     pkt.payload_size = 0u;
@@ -1294,7 +1299,7 @@
       continue;
     }
 
-    MediaPacket pkt;
+    fuchsia::media::MediaPacket pkt;
 
     pkt.pts = finished_buffer.capture_timestamp;
     pkt.pts_rate_ticks = format_->frames_per_second;
@@ -1312,9 +1317,9 @@
   }
 }
 
-void AudioCapturerImpl::UpdateFormat(media::AudioSampleFormat sample_format,
-                                     uint32_t channels,
-                                     uint32_t frames_per_second) {
+void AudioCapturerImpl::UpdateFormat(
+    fuchsia::media::AudioSampleFormat sample_format, uint32_t channels,
+    uint32_t frames_per_second) {
   // Record our new format.
   FXL_DCHECK(state_.load() == State::WaitingForVmo);
   format_->sample_format = sample_format;
@@ -1367,7 +1372,7 @@
 
   // Get the driver's currently configured format.  If it does not have one, we
   // cannot set up the mixer.
-  AudioMediaTypeDetailsPtr source_format;
+  fuchsia::media::AudioMediaTypeDetailsPtr source_format;
   source_format = device->driver()->GetSourceFormat();
   if (!source_format) {
     FXL_LOG(INFO)
diff --git a/bin/media/audio_server/audio_capturer_impl.h b/bin/media/audio_server/audio_capturer_impl.h
index 4027205..8d1298f 100644
--- a/bin/media/audio_server/audio_capturer_impl.h
+++ b/bin/media/audio_server/audio_capturer_impl.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_CAPTURER_IMPL_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_CAPTURER_IMPL_H_
 
 #include <dispatcher-pool/dispatcher-channel.h>
 #include <dispatcher-pool/dispatcher-timer.h>
@@ -10,11 +11,14 @@
 #include <fbl/intrusive_double_list.h>
 #include <fbl/slab_allocator.h>
 #include <fbl/unique_ptr.h>
+#include <fuchsia/media/cpp/fidl.h>
 
-#include <media/cpp/fidl.h>
+#include "garnet/bin/media/audio_server/audio_driver.h"
+#include "garnet/bin/media/audio_server/audio_link.h"
 #include "garnet/bin/media/audio_server/audio_object.h"
 #include "garnet/bin/media/audio_server/mixer/mixer.h"
 #include "garnet/bin/media/audio_server/mixer/output_formatter.h"
+#include "garnet/bin/media/audio_server/utils.h"
 #include "lib/fidl/cpp/binding.h"
 #include "lib/media/timeline/timeline_function.h"
 #include "lib/media/timeline/timeline_rate.h"
@@ -24,14 +28,16 @@
 
 class AudioServerImpl;
 
-class AudioCapturerImpl : public AudioObject, public AudioCapturer {
+class AudioCapturerImpl : public AudioObject,
+                          public fuchsia::media::AudioCapturer {
  public:
   static fbl::RefPtr<AudioCapturerImpl> Create(
-      fidl::InterfaceRequest<AudioCapturer> audio_capturer_request,
+      fidl::InterfaceRequest<fuchsia::media::AudioCapturer>
+          audio_capturer_request,
       AudioServerImpl* owner, bool loopback);
 
   bool loopback() const { return loopback_; }
-  void SetInitialFormat(AudioMediaTypeDetails format)
+  void SetInitialFormat(fuchsia::media::AudioMediaTypeDetails format)
       FXL_LOCKS_EXCLUDED(mix_domain_->token());
   void Shutdown() FXL_LOCKS_EXCLUDED(mix_domain_->token());
 
@@ -118,7 +124,7 @@
     const uint32_t num_frames;
     const CaptureAtCallback cbk;
 
-    int64_t capture_timestamp = kNoTimestamp;
+    int64_t capture_timestamp = fuchsia::media::kNoTimestamp;
     uint32_t flags = 0;
     uint32_t filled_frames = 0;
     const uint32_t sequence_number = sequence_generator.Next();
@@ -141,13 +147,13 @@
     uint32_t source_trans_gen_id = kInvalidGenerationId;
   };
 
-  AudioCapturerImpl(
-      fidl::InterfaceRequest<AudioCapturer> audio_capturer_request,
-      AudioServerImpl* owner, bool loopback);
+  AudioCapturerImpl(fidl::InterfaceRequest<fuchsia::media::AudioCapturer>
+                        audio_capturer_request,
+                    AudioServerImpl* owner, bool loopback);
 
   // AudioCapturer FIDL implementation
   void GetMediaType(GetMediaTypeCallback cbk) final;
-  void SetMediaType(MediaType media_type) final;
+  void SetMediaType(fuchsia::media::MediaType media_type) final;
   void SetGain(float gain) final;
   void SetPayloadBuffer(zx::vmo payload_buf_vmo) final;
   void CaptureAt(uint32_t offset_frames, uint32_t num_frames,
@@ -184,21 +190,21 @@
       FXL_LOCKS_EXCLUDED(mix_domain_->token());
 
   // Bookkeeping helper.
-  void UpdateFormat(media::AudioSampleFormat sample_format, uint32_t channels,
-                    uint32_t frames_per_second)
+  void UpdateFormat(fuchsia::media::AudioSampleFormat sample_format,
+                    uint32_t channels, uint32_t frames_per_second)
       FXL_LOCKS_EXCLUDED(mix_domain_->token());
 
   // Select a mixer for the link supplied and return true, or return false if
   // one cannot be found.
   zx_status_t ChooseMixer(const std::shared_ptr<AudioLink>& link);
 
-  fidl::Binding<AudioCapturer> binding_;
+  fidl::Binding<fuchsia::media::AudioCapturer> binding_;
   AudioServerImpl* owner_ = nullptr;
   std::atomic<State> state_;
   const bool loopback_;
 
   // Capture format and gain state.
-  AudioMediaTypeDetailsPtr format_;
+  fuchsia::media::AudioMediaTypeDetailsPtr format_;
   uint32_t bytes_per_frame_;
   TimelineRate frames_to_clock_mono_rate_;
   uint32_t max_frames_per_capture_;
@@ -252,3 +258,5 @@
 
 FWD_DECL_STATIC_SLAB_ALLOCATOR(
     ::media::audio::AudioCapturerImpl::PcbAllocatorTraits);
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_CAPTURER_IMPL_H_
diff --git a/bin/media/audio_server/audio_device.cc b/bin/media/audio_server/audio_device.cc
index 794b8d92..6f6d38f 100644
--- a/bin/media/audio_server/audio_device.cc
+++ b/bin/media/audio_server/audio_device.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "garnet/bin/media/audio_server/audio_output.h"
+#include "garnet/bin/media/audio_server/audio_device.h"
 
 #include "garnet/bin/media/audio_server/audio_device_manager.h"
 #include "garnet/bin/media/audio_server/audio_link.h"
+#include "garnet/bin/media/audio_server/audio_output.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/time/time_delta.h"
 
@@ -25,14 +26,14 @@
   mix_wakeup_->Signal();
 }
 
-MediaResult AudioDevice::Init() {
+fuchsia::media::MediaResult AudioDevice::Init() {
   // TODO(johngro) : See MG-940.  Eliminate this priority boost as soon as we
   // have a more official way of meeting real-time latency requirements.
   mix_domain_ = ::dispatcher::ExecutionDomain::Create(24);
   mix_wakeup_ = ::dispatcher::WakeupEvent::Create();
 
   if ((mix_domain_ == nullptr) || (mix_wakeup_ == nullptr)) {
-    return MediaResult::INSUFFICIENT_RESOURCES;
+    return fuchsia::media::MediaResult::INSUFFICIENT_RESOURCES;
   }
 
   // clang-format off
@@ -50,10 +51,10 @@
   if (res != ZX_OK) {
     FXL_LOG(ERROR) << "Failed to activate wakeup event for AudioDevice!  "
                    << "(res " << res << ")";
-    return MediaResult::INTERNAL_ERROR;
+    return fuchsia::media::MediaResult::INTERNAL_ERROR;
   }
 
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void AudioDevice::Cleanup() {}
@@ -83,12 +84,12 @@
   }
 }
 
-MediaResult AudioDevice::Startup() {
+fuchsia::media::MediaResult AudioDevice::Startup() {
   // If our derived class failed to initialize, Just get out.  We are being
   // called by the output manager, and they will remove us from the set of
   // active outputs as a result of us failing to initialize.
-  MediaResult res = Init();
-  if (res != MediaResult::OK) {
+  fuchsia::media::MediaResult res = Init();
+  if (res != fuchsia::media::MediaResult::OK) {
     DeactivateDomain();
     return res;
   }
@@ -96,7 +97,7 @@
   // Poke the output once so it gets a chance to actually start running.
   Wakeup();
 
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void AudioDevice::Shutdown() {
diff --git a/bin/media/audio_server/audio_device.h b/bin/media/audio_server/audio_device.h
index e31deec..0e1e610 100644
--- a/bin/media/audio_server/audio_device.h
+++ b/bin/media/audio_server/audio_device.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DEVICE_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DEVICE_H_
 
 #include <deque>
 #include <memory>
@@ -63,7 +64,8 @@
   //
   // TODO(johngro) : Remove this once device driver format selection is under
   // control of the policy manager layer instead of here.
-  virtual void NotifyDestFormatPreference(const AudioMediaTypeDetailsPtr& fmt)
+  virtual void NotifyDestFormatPreference(
+      const fuchsia::media::AudioMediaTypeDetailsPtr& fmt)
       FXL_LOCKS_EXCLUDED(mix_domain_->token()) {}
 
   // GetSourceFormatPreference
@@ -76,7 +78,7 @@
   // what formats they support, and to influence what their capturers can be
   // bound to or not.  "Preference" of an audio device is not a concept which
   // belongs in the mixer.
-  virtual AudioMediaTypeDetailsPtr GetSourceFormatPreference() {
+  virtual fuchsia::media::AudioMediaTypeDetailsPtr GetSourceFormatPreference() {
     return nullptr;
   }
 
@@ -97,7 +99,7 @@
   // locks are being held at this point.  Derived classes should allocate their
   // hardware resources and initialize any internal state.  Return
   // MediaResult::OK if everything is good and the output is ready to do work.
-  virtual MediaResult Init();
+  virtual fuchsia::media::MediaResult Init();
 
   // Cleanup
   //
@@ -211,7 +213,7 @@
   // Gives derived classes a chance to set up hardware, then sets up the
   // machinery needed for scheduling processing tasks and schedules the first
   // processing callback immediately in order to get the process running.
-  MediaResult Startup();
+  fuchsia::media::MediaResult Startup();
 
   // Called from the AudioDeviceManager on the main message loop
   // thread.  Makes certain that the process of shutdown has started,
@@ -230,3 +232,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DEVICE_H_
diff --git a/bin/media/audio_server/audio_device_manager.cc b/bin/media/audio_server/audio_device_manager.cc
index c48522b..111ce04 100644
--- a/bin/media/audio_server/audio_device_manager.cc
+++ b/bin/media/audio_server/audio_device_manager.cc
@@ -4,9 +4,10 @@
 
 #include "garnet/bin/media/audio_server/audio_device_manager.h"
 
-#include <fbl/algorithm.h>
 #include <string>
 
+#include <fbl/algorithm.h>
+
 #include "garnet/bin/media/audio_server/audio_capturer_impl.h"
 #include "garnet/bin/media/audio_server/audio_link.h"
 #include "garnet/bin/media/audio_server/audio_output.h"
@@ -25,17 +26,17 @@
   FXL_DCHECK(devices_.is_empty());
 }
 
-MediaResult AudioDeviceManager::Init() {
+fuchsia::media::MediaResult AudioDeviceManager::Init() {
   // Step #1: Instantiate and initialize the default throttle output.
   auto throttle_output = ThrottleOutput::Create(this);
   if (throttle_output == nullptr) {
     FXL_LOG(WARNING)
         << "AudioDeviceManager failed to create default throttle output!";
-    return MediaResult::INSUFFICIENT_RESOURCES;
+    return fuchsia::media::MediaResult::INSUFFICIENT_RESOURCES;
   }
 
-  MediaResult res = throttle_output->Startup();
-  if (res != MediaResult::OK) {
+  fuchsia::media::MediaResult res = throttle_output->Startup();
+  if (res != fuchsia::media::MediaResult::OK) {
     FXL_LOG(WARNING)
         << "AudioDeviceManager failed to initalize the throttle output (res "
         << res << ")";
@@ -46,13 +47,13 @@
   // Step #2: Being monitoring for plug/unplug events for pluggable audio
   // output devices.
   res = plug_detector_.Start(this);
-  if (res != MediaResult::OK) {
+  if (res != fuchsia::media::MediaResult::OK) {
     FXL_LOG(WARNING) << "AudioDeviceManager failed to start plug detector (res "
                      << res << ")";
     return res;
   }
 
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void AudioDeviceManager::Shutdown() {
@@ -84,7 +85,7 @@
   throttle_output_ = nullptr;
 }
 
-MediaResult AudioDeviceManager::AddDevice(
+fuchsia::media::MediaResult AudioDeviceManager::AddDevice(
     const fbl::RefPtr<AudioDevice>& device) {
   FXL_DCHECK(device != nullptr);
   FXL_DCHECK(!device->in_object_list());
@@ -96,8 +97,8 @@
   }
   devices_.push_back(device);
 
-  MediaResult res = device->Startup();
-  if (res != MediaResult::OK) {
+  fuchsia::media::MediaResult res = device->Startup();
+  if (res != fuchsia::media::MediaResult::OK) {
     devices_.erase(*device);
     device->Shutdown();
   }
@@ -145,7 +146,7 @@
 }
 
 void AudioDeviceManager::SetMasterGain(float db_gain) {
-  master_gain_ = fbl::clamp(db_gain, kMutedGain, 0.0f);
+  master_gain_ = fbl::clamp(db_gain, fuchsia::media::kMutedGain, 0.0f);
   for (auto& device : devices_) {
     if (device.is_input()) {
       continue;
@@ -241,9 +242,9 @@
   capturers_.erase(*capturer);
 }
 
-void AudioDeviceManager::ScheduleMainThreadTask(const fxl::Closure& task) {
+void AudioDeviceManager::ScheduleMainThreadTask(fit::closure task) {
   FXL_DCHECK(server_);
-  server_->ScheduleMainThreadTask(task);
+  server_->ScheduleMainThreadTask(std::move(task));
 }
 
 fbl::RefPtr<AudioDevice> AudioDeviceManager::FindLastPlugged(
diff --git a/bin/media/audio_server/audio_device_manager.h b/bin/media/audio_server/audio_device_manager.h
index 7a0083f..e733d0a 100644
--- a/bin/media/audio_server/audio_device_manager.h
+++ b/bin/media/audio_server/audio_device_manager.h
@@ -2,20 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DEVICE_MANAGER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DEVICE_MANAGER_H_
 
 #include <set>
 
 #include <fbl/intrusive_double_list.h>
 #include <fbl/ref_ptr.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/audio_server/audio_device.h"
 #include "garnet/bin/media/audio_server/audio_input.h"
 #include "garnet/bin/media/audio_server/audio_output.h"
 #include "garnet/bin/media/audio_server/audio_plug_detector.h"
 #include "garnet/bin/media/audio_server/fwd_decls.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace media {
 namespace audio {
@@ -34,7 +35,7 @@
   // 2) Instantiate all of the built-in audio output devices.
   // 3) Being monitoring for plug/unplug events for pluggable audio output
   //    devices.
-  MediaResult Init();
+  fuchsia::media::MediaResult Init();
 
   // Blocking call.  Called by the service, once, when it is time to shutdown
   // the service implementation.  While this function is blocking, it must never
@@ -73,10 +74,10 @@
   void RemoveCapturer(AudioCapturerImpl* capturer);
 
   // Schedule a closure to run on our encapsulating server's main message loop.
-  void ScheduleMainThreadTask(const fxl::Closure& task);
+  void ScheduleMainThreadTask(fit::closure task);
 
   // Attempt to initialize an output and add it to the set of active outputs.
-  MediaResult AddDevice(const fbl::RefPtr<AudioDevice>& device);
+  fuchsia::media::MediaResult AddDevice(const fbl::RefPtr<AudioDevice>& device);
 
   // Shutdown the specified audio device and remove it from the appropriate set
   // of active devices.
@@ -163,3 +164,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DEVICE_MANAGER_H_
diff --git a/bin/media/audio_server/audio_driver.cc b/bin/media/audio_server/audio_driver.cc
index 504ce3d..3ecb83a 100644
--- a/bin/media/audio_server/audio_driver.cc
+++ b/bin/media/audio_server/audio_driver.cc
@@ -111,12 +111,13 @@
   snapshot->gen_id = ring_buffer_state_gen_.get();
 }
 
-AudioMediaTypeDetailsPtr AudioDriver::GetSourceFormat() const {
+fuchsia::media::AudioMediaTypeDetailsPtr AudioDriver::GetSourceFormat() const {
   std::lock_guard<std::mutex> lock(configured_format_lock_);
 
-  if (!configured_format_) return nullptr;
+  if (!configured_format_)
+    return nullptr;
 
-  AudioMediaTypeDetailsPtr result;
+  fuchsia::media::AudioMediaTypeDetailsPtr result;
   fidl::Clone(configured_format_, &result);
   return result;
 }
@@ -160,7 +161,8 @@
 }
 
 zx_status_t AudioDriver::Configure(uint32_t frames_per_second,
-                                   uint32_t channels, AudioSampleFormat fmt,
+                                   uint32_t channels,
+                                   fuchsia::media::AudioSampleFormat fmt,
                                    zx_duration_t min_ring_buffer_duration) {
   // TODO(johngro) : Figure out a better way to assert this!
   OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);
@@ -229,7 +231,7 @@
 
   {
     std::lock_guard<std::mutex> lock(configured_format_lock_);
-    configured_format_ = AudioMediaTypeDetails::New();
+    configured_format_ = fuchsia::media::AudioMediaTypeDetails::New();
     configured_format_->sample_format = fmt;
     configured_format_->channels = channels;
     configured_format_->frames_per_second = frames_per_second;
diff --git a/bin/media/audio_server/audio_driver.h b/bin/media/audio_server/audio_driver.h
index afa59de..9e3ed79 100644
--- a/bin/media/audio_server/audio_driver.h
+++ b/bin/media/audio_server/audio_driver.h
@@ -2,7 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DRIVER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DRIVER_H_
+
+#include <mutex>
+#include <string>
 
 #include <dispatcher-pool/dispatcher-channel.h>
 #include <dispatcher-pool/dispatcher-timer.h>
@@ -12,9 +16,6 @@
 #include <lib/zx/vmo.h>
 #include <zircon/device/audio.h>
 
-#include <mutex>
-#include <string>
-
 #include "garnet/bin/media/audio_server/audio_device.h"
 #include "garnet/bin/media/audio_server/driver_ring_buffer.h"
 #include "garnet/bin/media/audio_server/utils.h"
@@ -53,7 +54,7 @@
   zx_status_t Init(zx::channel stream_channel);
   void Cleanup();
   void SnapshotRingBuffer(RingBufferSnapshot* snapshot) const;
-  AudioMediaTypeDetailsPtr GetSourceFormat() const;
+  fuchsia::media::AudioMediaTypeDetailsPtr GetSourceFormat() const;
 
   bool plugged() const {
     fbl::AutoLock lock(&plugged_lock_);
@@ -89,7 +90,7 @@
 
   zx_status_t GetSupportedFormats();
   zx_status_t Configure(uint32_t frames_per_second, uint32_t channels,
-                        AudioSampleFormat fmt,
+                        fuchsia::media::AudioSampleFormat fmt,
                         zx_duration_t min_ring_buffer_duration);
   zx_status_t Start();
   zx_status_t Stop();
@@ -207,7 +208,7 @@
   // destintions (either outputs or capturers) when determining what mixer to
   // use.
   mutable std::mutex configured_format_lock_;
-  AudioMediaTypeDetailsPtr configured_format_
+  fuchsia::media::AudioMediaTypeDetailsPtr configured_format_
       FXL_GUARDED_BY(configured_format_lock_);
 
   // Ring buffer state.  Note, the details of the ring buffer state are
@@ -234,3 +235,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_DRIVER_H_
diff --git a/bin/media/audio_server/audio_input.cc b/bin/media/audio_server/audio_input.cc
index 6c53da5..32e8e43 100644
--- a/bin/media/audio_server/audio_input.cc
+++ b/bin/media/audio_server/audio_input.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/audio_server/audio_input.h"
+
 #include "garnet/bin/media/audio_server/audio_device_manager.h"
 
 namespace media {
@@ -21,18 +22,18 @@
     : AudioDevice(Type::Input, manager),
       initial_stream_channel_(std::move(channel)) {}
 
-MediaResult AudioInput::Init() {
-  MediaResult init_res = AudioDevice::Init();
-  if (init_res != MediaResult::OK) {
+fuchsia::media::MediaResult AudioInput::Init() {
+  fuchsia::media::MediaResult init_res = AudioDevice::Init();
+  if (init_res != fuchsia::media::MediaResult::OK) {
     return init_res;
   }
 
   if (driver_->Init(fbl::move(initial_stream_channel_)) != ZX_OK) {
-    return MediaResult::INTERNAL_ERROR;
+    return fuchsia::media::MediaResult::INTERNAL_ERROR;
   }
 
   state_ = State::Initialized;
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void AudioInput::OnWakeup() {
@@ -52,7 +53,8 @@
 
   uint32_t pref_fps = 48000;
   uint32_t pref_chan = 1;
-  AudioSampleFormat pref_fmt = AudioSampleFormat::SIGNED_16;
+  fuchsia::media::AudioSampleFormat pref_fmt =
+      fuchsia::media::AudioSampleFormat::SIGNED_16;
 
   zx_status_t res = SelectBestFormat(driver_->format_ranges(), &pref_fps,
                                      &pref_chan, &pref_fmt);
diff --git a/bin/media/audio_server/audio_input.h b/bin/media/audio_server/audio_input.h
index 0328dd0..5e8ad2c 100644
--- a/bin/media/audio_server/audio_input.h
+++ b/bin/media/audio_server/audio_input.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_INPUT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_INPUT_H_
 
 #include <lib/zx/channel.h>
 
@@ -20,7 +21,8 @@
                                         AudioDeviceManager* manager);
 
  protected:
-  MediaResult Init() override FXL_LOCKS_EXCLUDED(mix_domain_->token());
+  fuchsia::media::MediaResult Init() override
+      FXL_LOCKS_EXCLUDED(mix_domain_->token());
 
   void OnWakeup() override FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain_->token());
 
@@ -58,3 +60,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_INPUT_H_
diff --git a/bin/media/audio_server/audio_link.cc b/bin/media/audio_server/audio_link.cc
index 3999508..2776d71 100644
--- a/bin/media/audio_server/audio_link.cc
+++ b/bin/media/audio_server/audio_link.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/audio_server/audio_link.h"
+
 #include "garnet/bin/media/audio_server/audio_object.h"
 
 namespace media {
diff --git a/bin/media/audio_server/audio_link.h b/bin/media/audio_server/audio_link.h
index 2735c0e..64a805d 100644
--- a/bin/media/audio_server/audio_link.h
+++ b/bin/media/audio_server/audio_link.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_H_
 
 #include <fbl/ref_ptr.h>
 
@@ -72,3 +73,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_H_
diff --git a/bin/media/audio_server/audio_link_packet_source.cc b/bin/media/audio_server/audio_link_packet_source.cc
index 8ef8e7f..57bb0dd 100644
--- a/bin/media/audio_server/audio_link_packet_source.cc
+++ b/bin/media/audio_server/audio_link_packet_source.cc
@@ -100,7 +100,8 @@
   FXL_DCHECK(this != other.get());
 
   std::lock_guard<std::mutex> source_locker(other->pending_mutex_);
-  if (other->pending_packet_queue_.empty()) return;
+  if (other->pending_packet_queue_.empty())
+    return;
 
   std::lock_guard<std::mutex> locker(pending_mutex_);
   FXL_DCHECK(pending_packet_queue_.empty());
diff --git a/bin/media/audio_server/audio_link_packet_source.h b/bin/media/audio_server/audio_link_packet_source.h
index da0fa3d..8c6c591 100644
--- a/bin/media/audio_server/audio_link_packet_source.h
+++ b/bin/media/audio_server/audio_link_packet_source.h
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_PACKET_SOURCE_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_PACKET_SOURCE_H_
 
-#include <fbl/ref_ptr.h>
 #include <deque>
 #include <memory>
 #include <mutex>
 
+#include <fbl/ref_ptr.h>
+
 #include "garnet/bin/media/audio_server/audio_link.h"
 #include "garnet/bin/media/audio_server/audio_packet_ref.h"
 #include "garnet/bin/media/audio_server/audio_pipe.h"
@@ -89,3 +91,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_PACKET_SOURCE_H_
diff --git a/bin/media/audio_server/audio_link_ring_buffer_source.cc b/bin/media/audio_server/audio_link_ring_buffer_source.cc
index 9aabeab..738ac1e 100644
--- a/bin/media/audio_server/audio_link_ring_buffer_source.cc
+++ b/bin/media/audio_server/audio_link_ring_buffer_source.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/audio_server/audio_link_ring_buffer_source.h"
+
 #include "garnet/bin/media/audio_server/audio_device.h"
 
 namespace media {
diff --git a/bin/media/audio_server/audio_link_ring_buffer_source.h b/bin/media/audio_server/audio_link_ring_buffer_source.h
index 7383e6b..af7b279 100644
--- a/bin/media/audio_server/audio_link_ring_buffer_source.h
+++ b/bin/media/audio_server/audio_link_ring_buffer_source.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_RING_BUFFER_SOURCE_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_RING_BUFFER_SOURCE_H_
 
 #include <fbl/ref_ptr.h>
 
@@ -28,3 +29,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_LINK_RING_BUFFER_SOURCE_H_
diff --git a/bin/media/audio_server/audio_object.h b/bin/media/audio_server/audio_object.h
index 19672d8..261a2a2 100644
--- a/bin/media/audio_server/audio_object.h
+++ b/bin/media/audio_server/audio_object.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_OBJECT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_OBJECT_H_
 
 #include <fbl/auto_lock.h>
 #include <fbl/intrusive_double_list.h>
@@ -126,3 +127,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_OBJECT_H_
diff --git a/bin/media/audio_server/audio_output.h b/bin/media/audio_server/audio_output.h
index 1147dc6..cf83372 100644
--- a/bin/media/audio_server/audio_output.h
+++ b/bin/media/audio_server/audio_output.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_OUTPUT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_OUTPUT_H_
 
 #include <deque>
 #include <memory>
@@ -46,3 +47,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_OUTPUT_H_
diff --git a/bin/media/audio_server/audio_packet_ref.cc b/bin/media/audio_server/audio_packet_ref.cc
index b3374a7..d0fcd00 100644
--- a/bin/media/audio_server/audio_packet_ref.cc
+++ b/bin/media/audio_server/audio_packet_ref.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/audio_server/audio_packet_ref.h"
+
 #include "garnet/bin/media/audio_server/audio_server_impl.h"
 #include "lib/fxl/logging.h"
 
diff --git a/bin/media/audio_server/audio_packet_ref.h b/bin/media/audio_server/audio_packet_ref.h
index 03b4308..66cab15 100644
--- a/bin/media/audio_server/audio_packet_ref.h
+++ b/bin/media/audio_server/audio_packet_ref.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PACKET_REF_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PACKET_REF_H_
 
 #include <fbl/intrusive_double_list.h>
 #include <fbl/ref_counted.h>
@@ -81,3 +82,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PACKET_REF_H_
diff --git a/bin/media/audio_server/audio_pipe.cc b/bin/media/audio_server/audio_pipe.cc
index cadfd4b..1250d7a 100644
--- a/bin/media/audio_server/audio_pipe.cc
+++ b/bin/media/audio_server/audio_pipe.cc
@@ -61,7 +61,8 @@
   }
 }
 
-void AudioPipe::PrimeRequested(MediaTimelineControlPoint::PrimeCallback cbk) {
+void AudioPipe::PrimeRequested(
+    fuchsia::media::MediaTimelineControlPoint::PrimeCallback cbk) {
   if (prime_callback_) {
     // Prime was already requested. Complete the old one and warn.
     FXL_LOG(WARNING) << "multiple prime requests received";
@@ -134,7 +135,7 @@
 
   // Figure out the starting PTS.
   int64_t start_pts;
-  if (supplied_packet->packet().pts != kNoTimestamp) {
+  if (supplied_packet->packet().pts != fuchsia::media::kNoTimestamp) {
     // The user provided an explicit PTS for this audio.  Transform it into
     // units of fractional frames.
     start_pts = supplied_packet->packet().pts *
@@ -151,7 +152,8 @@
   next_pts_ = start_pts + pts_delta;
   next_pts_known_ = true;
 
-  bool end_of_stream = supplied_packet->packet().flags & kFlagEos;
+  bool end_of_stream =
+      supplied_packet->packet().flags & fuchsia::media::kFlagEos;
 
   // Send the packet along unless it falls outside the program range.
   if (next_pts_ >= min_pts_) {
diff --git a/bin/media/audio_server/audio_pipe.h b/bin/media/audio_server/audio_pipe.h
index f2dc6da..cf3575d 100644
--- a/bin/media/audio_server/audio_pipe.h
+++ b/bin/media/audio_server/audio_pipe.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PIPE_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PIPE_H_
 
 #include <memory>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/audio_server/audio_packet_ref.h"
 #include "garnet/bin/media/audio_server/fwd_decls.h"
 #include "lib/media/transport/media_packet_consumer_base.h"
@@ -41,7 +43,8 @@
 
   // Indicates the priming was requested. The pipe is responsible for calling
   // the callback when priming is complete.
-  void PrimeRequested(MediaTimelineControlPoint::PrimeCallback callback);
+  void PrimeRequested(
+      fuchsia::media::MediaTimelineControlPoint::PrimeCallback callback);
 
  protected:
   void OnPacketSupplied(
@@ -56,8 +59,8 @@
   AudioRenderer1Impl* owner_;
   AudioServerImpl* server_;
 
-  MediaTimelineControlPoint::PrimeCallback prime_callback_;
-  int64_t min_pts_ = kMinTime;
+  fuchsia::media::MediaTimelineControlPoint::PrimeCallback prime_callback_;
+  int64_t min_pts_ = fuchsia::media::kMinTime;
   bool min_pts_dirty_ = false;
 
   // State used for timestamp interpolation
@@ -67,3 +70,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PIPE_H_
diff --git a/bin/media/audio_server/audio_plug_detector.cc b/bin/media/audio_server/audio_plug_detector.cc
index f86c781..bb65878 100644
--- a/bin/media/audio_server/audio_plug_detector.cc
+++ b/bin/media/audio_server/audio_plug_detector.cc
@@ -36,7 +36,8 @@
 
 AudioPlugDetector::~AudioPlugDetector() { FXL_DCHECK(manager_ == nullptr); }
 
-MediaResult AudioPlugDetector::Start(AudioDeviceManager* manager) {
+fuchsia::media::MediaResult AudioPlugDetector::Start(
+    AudioDeviceManager* manager) {
   FXL_DCHECK(manager != nullptr);
 
   // If we fail to set up monitoring for any of our target directories,
@@ -48,7 +49,7 @@
   if (manager_ != nullptr) {
     FXL_DLOG(WARNING) << "Attempted to start the AudioPlugDetector twice!";
     error_cleanup.cancel();
-    return MediaResult::OK;
+    return fuchsia::media::MediaResult::OK;
   }
 
   // Record our new manager
@@ -66,7 +67,7 @@
       FXL_LOG(ERROR)
           << "AudioPlugDetector failed to create DeviceWatcher for \""
           << devnode.path << "\".";
-      return MediaResult::INSUFFICIENT_RESOURCES;
+      return fuchsia::media::MediaResult::INSUFFICIENT_RESOURCES;
     }
 
     watchers_.emplace_back(std::move(watcher));
@@ -74,7 +75,7 @@
 
   error_cleanup.cancel();
 
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void AudioPlugDetector::Stop() {
diff --git a/bin/media/audio_server/audio_plug_detector.h b/bin/media/audio_server/audio_plug_detector.h
index 1eee4c5..43723a4 100644
--- a/bin/media/audio_server/audio_plug_detector.h
+++ b/bin/media/audio_server/audio_plug_detector.h
@@ -2,15 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PLUG_DETECTOR_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PLUG_DETECTOR_H_
 
 #include <fbl/macros.h>
 #include <fbl/mutex.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <zircon/compiler.h>
 #include <zircon/device/vfs.h>
 #include <zircon/types.h>
 
-#include <media/cpp/fidl.h>
 #include "lib/fsl/io/device_watcher.h"
 #include "lib/fxl/files/unique_fd.h"
 
@@ -24,7 +25,7 @@
   AudioPlugDetector() {}
   ~AudioPlugDetector();
 
-  MediaResult Start(AudioDeviceManager* manager);
+  fuchsia::media::MediaResult Start(AudioDeviceManager* manager);
   void Stop();
 
  private:
@@ -35,3 +36,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_PLUG_DETECTOR_H_
diff --git a/bin/media/audio_server/audio_renderer1_impl.cc b/bin/media/audio_server/audio_renderer1_impl.cc
index b8a805e..43658a1 100644
--- a/bin/media/audio_server/audio_renderer1_impl.cc
+++ b/bin/media/audio_server/audio_renderer1_impl.cc
@@ -23,38 +23,40 @@
 // TODO(johngro): If there is ever a better way to do this type of static-table
 // initialization using fidl generated structs, we should switch to it.
 static const struct {
-  AudioSampleFormat sample_format;
+  fuchsia::media::AudioSampleFormat sample_format;
   uint32_t min_channels;
   uint32_t max_channels;
   uint32_t min_frames_per_second;
   uint32_t max_frames_per_second;
 } kSupportedAudioTypeSets[] = {
     {
-        .sample_format = AudioSampleFormat::UNSIGNED_8,
-        .min_channels = media::kMinLpcmChannelCount,
-        .max_channels = media::kMaxLpcmChannelCount,
-        .min_frames_per_second = media::kMinLpcmFramesPerSecond,
-        .max_frames_per_second = media::kMaxLpcmFramesPerSecond,
+        .sample_format = fuchsia::media::AudioSampleFormat::UNSIGNED_8,
+        .min_channels = fuchsia::media::kMinLpcmChannelCount,
+        .max_channels = fuchsia::media::kMaxLpcmChannelCount,
+        .min_frames_per_second = fuchsia::media::kMinLpcmFramesPerSecond,
+        .max_frames_per_second = fuchsia::media::kMaxLpcmFramesPerSecond,
     },
     {
-        .sample_format = AudioSampleFormat::SIGNED_16,
-        .min_channels = media::kMinLpcmChannelCount,
-        .max_channels = media::kMaxLpcmChannelCount,
-        .min_frames_per_second = media::kMinLpcmFramesPerSecond,
-        .max_frames_per_second = media::kMaxLpcmFramesPerSecond,
+        .sample_format = fuchsia::media::AudioSampleFormat::SIGNED_16,
+        .min_channels = fuchsia::media::kMinLpcmChannelCount,
+        .max_channels = fuchsia::media::kMaxLpcmChannelCount,
+        .min_frames_per_second = fuchsia::media::kMinLpcmFramesPerSecond,
+        .max_frames_per_second = fuchsia::media::kMaxLpcmFramesPerSecond,
     },
     {
-        .sample_format = AudioSampleFormat::FLOAT,
-        .min_channels = media::kMinLpcmChannelCount,
-        .max_channels = media::kMaxLpcmChannelCount,
-        .min_frames_per_second = media::kMinLpcmFramesPerSecond,
-        .max_frames_per_second = media::kMaxLpcmFramesPerSecond,
+        .sample_format = fuchsia::media::AudioSampleFormat::FLOAT,
+        .min_channels = fuchsia::media::kMinLpcmChannelCount,
+        .max_channels = fuchsia::media::kMaxLpcmChannelCount,
+        .min_frames_per_second = fuchsia::media::kMinLpcmFramesPerSecond,
+        .max_frames_per_second = fuchsia::media::kMaxLpcmFramesPerSecond,
     },
 };
 
 AudioRenderer1Impl::AudioRenderer1Impl(
-    fidl::InterfaceRequest<AudioRenderer> audio_renderer_request,
-    fidl::InterfaceRequest<MediaRenderer> media_renderer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer>
+        audio_renderer_request,
+    fidl::InterfaceRequest<fuchsia::media::MediaRenderer>
+        media_renderer_request,
     AudioServerImpl* owner)
     : owner_(owner),
       audio_renderer_binding_(this, std::move(audio_renderer_request)),
@@ -102,8 +104,10 @@
 }
 
 fbl::RefPtr<AudioRenderer1Impl> AudioRenderer1Impl::Create(
-    fidl::InterfaceRequest<AudioRenderer> audio_renderer_request,
-    fidl::InterfaceRequest<MediaRenderer> media_renderer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer>
+        audio_renderer_request,
+    fidl::InterfaceRequest<fuchsia::media::MediaRenderer>
+        media_renderer_request,
     AudioServerImpl* owner) {
   return fbl::AdoptRef(new AudioRenderer1Impl(std::move(audio_renderer_request),
                                               std::move(media_renderer_request),
@@ -153,13 +157,13 @@
   cbk(SupportedMediaTypes());
 }
 
-void AudioRenderer1Impl::SetMediaType(MediaType media_type) {
+void AudioRenderer1Impl::SetMediaType(fuchsia::media::MediaType media_type) {
   // Check the requested configuration.
-  if ((media_type.medium != MediaTypeMedium::AUDIO) ||
-      (media_type.encoding != kAudioEncodingLpcm) ||
+  if ((media_type.medium != fuchsia::media::MediaTypeMedium::AUDIO) ||
+      (media_type.encoding != fuchsia::media::kAudioEncodingLpcm) ||
       (!media_type.details.is_audio())) {
     FXL_LOG(ERROR) << "Unsupported configuration requested in "
-                   << "AudioRenderer::SetMediaType.  "
+                   << "fuchsia::media::AudioRenderer::SetMediaType.  "
                    << "Media type must be LPCM audio.";
     Shutdown();
     return;
@@ -183,7 +187,7 @@
 
   if (i >= arraysize(kSupportedAudioTypeSets)) {
     FXL_LOG(ERROR) << "Unsupported LPCM configuration requested in "
-                   << "AudioRenderer::SetMediaType.  "
+                   << "fuchsia::media::AudioRenderer::SetMediaType.  "
                    << "(format = " << cfg.sample_format
                    << ", channels = " << static_cast<uint32_t>(cfg.channels)
                    << ", frames_per_second = " << cfg.frames_per_second << ")";
@@ -244,7 +248,8 @@
 }
 
 void AudioRenderer1Impl::GetPacketConsumer(
-    fidl::InterfaceRequest<MediaPacketConsumer> consumer_request) {
+    fidl::InterfaceRequest<fuchsia::media::MediaPacketConsumer>
+        consumer_request) {
   // Bind our pipe to the interface request.
   if (pipe_.is_bound()) {
     pipe_.Reset();
@@ -254,12 +259,12 @@
 }
 
 void AudioRenderer1Impl::GetTimelineControlPoint(
-    fidl::InterfaceRequest<MediaTimelineControlPoint> req) {
+    fidl::InterfaceRequest<fuchsia::media::MediaTimelineControlPoint> req) {
   timeline_control_point_.Bind(std::move(req));
 }
 
 void AudioRenderer1Impl::SetGain(float db_gain) {
-  if (db_gain > kMaxGain) {
+  if (db_gain > fuchsia::media::kMaxGain) {
     FXL_LOG(ERROR) << "Gain value too large (" << db_gain
                    << ") for audio renderer.";
     Shutdown();
@@ -344,7 +349,7 @@
     }
   }
 
-  if (packet->flags() & kFlagEos) {
+  if (packet->flags() & fuchsia::media::kFlagEos) {
     timeline_control_point_.SetEndOfStreamPts(
         (packet->end_pts() >> kPtsFractionalBits) /
         format_info_->frames_per_ns());
@@ -352,7 +357,7 @@
 }
 
 bool AudioRenderer1Impl::OnFlushRequested(
-    MediaPacketConsumer::FlushCallback cbk) {
+    fuchsia::media::MediaPacketConsumer::FlushCallback cbk) {
   fbl::RefPtr<PendingFlushToken> flush_token =
       PendingFlushToken::Create(owner_, cbk);
 
@@ -370,7 +375,8 @@
   return true;
 }
 
-fidl::VectorPtr<MediaTypeSet> AudioRenderer1Impl::SupportedMediaTypes() {
+fidl::VectorPtr<fuchsia::media::MediaTypeSet>
+AudioRenderer1Impl::SupportedMediaTypes() {
   // Build a minimal descriptor
   //
   // TODO(johngro): one day, we need to make this description much more rich and
@@ -383,17 +389,17 @@
   // message, but the nature of the structures generated by the C++ bindings
   // make this difficult.  For now, we just create a trivial descriptor entierly
   // by hand.
-  fidl::VectorPtr<MediaTypeSet> supported_media_types(
+  fidl::VectorPtr<fuchsia::media::MediaTypeSet> supported_media_types(
       arraysize(kSupportedAudioTypeSets));
 
   for (size_t i = 0; i < supported_media_types->size(); ++i) {
-    MediaTypeSet& mts = supported_media_types->at(i);
+    fuchsia::media::MediaTypeSet& mts = supported_media_types->at(i);
 
-    mts.medium = MediaTypeMedium::AUDIO;
-    mts.encodings.push_back(kAudioEncodingLpcm);
+    mts.medium = fuchsia::media::MediaTypeMedium::AUDIO;
+    mts.encodings.push_back(fuchsia::media::kAudioEncodingLpcm);
 
     const auto& s = kSupportedAudioTypeSets[i];
-    AudioMediaTypeSetDetails audio_detail;
+    fuchsia::media::AudioMediaTypeSetDetails audio_detail;
     audio_detail.sample_format = s.sample_format;
     audio_detail.min_channels = s.min_channels;
     audio_detail.max_channels = s.max_channels;
diff --git a/bin/media/audio_server/audio_renderer1_impl.h b/bin/media/audio_server/audio_renderer1_impl.h
index abea219..a3edc12 100644
--- a/bin/media/audio_server/audio_renderer1_impl.h
+++ b/bin/media/audio_server/audio_renderer1_impl.h
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER1_IMPL_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER1_IMPL_H_
 
-#include <fbl/ref_ptr.h>
 #include <deque>
 #include <set>
 
-#include <media/cpp/fidl.h>
+#include <fbl/ref_ptr.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/audio_server/audio_link_packet_source.h"
 #include "garnet/bin/media/audio_server/audio_object.h"
 #include "garnet/bin/media/audio_server/audio_packet_ref.h"
@@ -24,13 +26,15 @@
 namespace audio {
 
 class AudioRenderer1Impl : public AudioRendererImpl,
-                           public AudioRenderer,
-                           public MediaRenderer {
+                           public fuchsia::media::AudioRenderer,
+                           public fuchsia::media::MediaRenderer {
  public:
   ~AudioRenderer1Impl() override;
   static fbl::RefPtr<AudioRenderer1Impl> Create(
-      fidl::InterfaceRequest<AudioRenderer> audio_renderer_request,
-      fidl::InterfaceRequest<MediaRenderer> media_renderer_request,
+      fidl::InterfaceRequest<fuchsia::media::AudioRenderer>
+          audio_renderer_request,
+      fidl::InterfaceRequest<fuchsia::media::MediaRenderer>
+          media_renderer_request,
       AudioServerImpl* owner);
 
   // Shutdown the audio renderer, unlinking it from all outputs, closing
@@ -47,10 +51,11 @@
  private:
   friend class AudioPipe;
 
-  AudioRenderer1Impl(
-      fidl::InterfaceRequest<AudioRenderer> audio_renderer_request,
-      fidl::InterfaceRequest<MediaRenderer> media_renderer_request,
-      AudioServerImpl* owner);
+  AudioRenderer1Impl(fidl::InterfaceRequest<fuchsia::media::AudioRenderer>
+                         audio_renderer_request,
+                     fidl::InterfaceRequest<fuchsia::media::MediaRenderer>
+                         media_renderer_request,
+                     AudioServerImpl* owner);
 
   // AudioObject overrides.
   zx_status_t InitializeDestLink(const AudioLinkPtr& link) final;
@@ -61,11 +66,13 @@
 
   // MediaRenderer implementation.
   void GetSupportedMediaTypes(GetSupportedMediaTypesCallback callback) override;
-  void SetMediaType(MediaType media_type) override;
+  void SetMediaType(fuchsia::media::MediaType media_type) override;
   void GetPacketConsumer(
-      fidl::InterfaceRequest<MediaPacketConsumer> consumer_request) override;
-  void GetTimelineControlPoint(fidl::InterfaceRequest<MediaTimelineControlPoint>
-                                   control_point_request) override;
+      fidl::InterfaceRequest<fuchsia::media::MediaPacketConsumer>
+          consumer_request) override;
+  void GetTimelineControlPoint(
+      fidl::InterfaceRequest<fuchsia::media::MediaTimelineControlPoint>
+          control_point_request) override;
 
   // Methods called by our AudioPipe.
   //
@@ -75,12 +82,12 @@
   // encapsulation so that AudioPipe does not have to know that we are an
   // AudioRenderer1Impl (just that we implement its interface).
   void OnPacketReceived(fbl::RefPtr<AudioPacketRef> packet);
-  bool OnFlushRequested(MediaPacketConsumer::FlushCallback cbk);
-  fidl::VectorPtr<MediaTypeSet> SupportedMediaTypes();
+  bool OnFlushRequested(fuchsia::media::MediaPacketConsumer::FlushCallback cbk);
+  fidl::VectorPtr<fuchsia::media::MediaTypeSet> SupportedMediaTypes();
 
   AudioServerImpl* owner_;
-  fidl::Binding<AudioRenderer> audio_renderer_binding_;
-  fidl::Binding<MediaRenderer> media_renderer_binding_;
+  fidl::Binding<fuchsia::media::AudioRenderer> audio_renderer_binding_;
+  fidl::Binding<fuchsia::media::MediaRenderer> media_renderer_binding_;
   AudioPipe pipe_;
   TimelineControlPoint timeline_control_point_;
   bool is_shutdown_ = false;
@@ -88,3 +95,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER1_IMPL_H_
diff --git a/bin/media/audio_server/audio_renderer2_impl.cc b/bin/media/audio_server/audio_renderer2_impl.cc
index 0dc0b8f..a85febc 100644
--- a/bin/media/audio_server/audio_renderer2_impl.cc
+++ b/bin/media/audio_server/audio_renderer2_impl.cc
@@ -14,14 +14,16 @@
 namespace audio {
 
 fbl::RefPtr<AudioRenderer2Impl> AudioRenderer2Impl::Create(
-    fidl::InterfaceRequest<AudioRenderer2> audio_renderer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer2>
+        audio_renderer_request,
     AudioServerImpl* owner) {
   return fbl::AdoptRef(
       new AudioRenderer2Impl(std::move(audio_renderer_request), owner));
 }
 
 AudioRenderer2Impl::AudioRenderer2Impl(
-    fidl::InterfaceRequest<AudioRenderer2> audio_renderer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer2>
+        audio_renderer_request,
     AudioServerImpl* owner)
     : owner_(owner),
       audio_renderer_binding_(this, std::move(audio_renderer_request)),
@@ -147,7 +149,7 @@
 //
 // AudioRenderer2 Interface
 //
-void AudioRenderer2Impl::SetPcmFormat(AudioPcmFormat format) {
+void AudioRenderer2Impl::SetPcmFormat(fuchsia::media::AudioPcmFormat format) {
   auto cleanup = fbl::MakeAutoCall([this]() { Shutdown(); });
 
   // We cannot change the format while we are currently operational
@@ -158,34 +160,36 @@
 
   // Sanity check the requested format
   switch (format.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
-    case AudioSampleFormat::SIGNED_16:
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       break;
 
     // TODO(johngro): Add more sample formats (24 bit, etc..) as the
     // mixer core learns to handle them.
     default:
       FXL_LOG(ERROR) << "Unsupported sample format (" << format.sample_format
-                     << ") in AudioRenderer::SetPcmFormat.";
+                     << ") in fuchsia::media::AudioRenderer::SetPcmFormat.";
       return;
   }
 
-  if ((format.channels < kMinChannelCount) ||
-      (format.channels > kMaxChannelCount)) {
-    FXL_LOG(ERROR)
-        << "Invalid channel count (" << format.channels
-        << ") in AudioRenderer::SetPcmFormat.  Must be on the range ["
-        << kMinChannelCount << ", " << kMaxChannelCount << "]";
+  if ((format.channels < fuchsia::media::kMinChannelCount) ||
+      (format.channels > fuchsia::media::kMaxChannelCount)) {
+    FXL_LOG(ERROR) << "Invalid channel count (" << format.channels
+                   << ") in fuchsia::media::AudioRenderer::SetPcmFormat.  Must "
+                      "be on the range ["
+                   << fuchsia::media::kMinChannelCount << ", "
+                   << fuchsia::media::kMaxChannelCount << "]";
     return;
   }
 
-  if ((format.frames_per_second < kMinFramesPerSecond) ||
-      (format.frames_per_second > kMaxFramesPerSecond)) {
-    FXL_LOG(ERROR)
-        << "Invalid frame rate (" << format.frames_per_second
-        << ") in AudioRenderer::SetPcmFormat.  Must be on the range ["
-        << kMinFramesPerSecond << ", " << kMaxFramesPerSecond << "]";
+  if ((format.frames_per_second < fuchsia::media::kMinFramesPerSecond) ||
+      (format.frames_per_second > fuchsia::media::kMaxFramesPerSecond)) {
+    FXL_LOG(ERROR) << "Invalid frame rate (" << format.frames_per_second
+                   << ") in fuchsia::media::AudioRenderer::SetPcmFormat.  Must "
+                      "be on the range ["
+                   << fuchsia::media::kMinFramesPerSecond << ", "
+                   << fuchsia::media::kMaxFramesPerSecond << "]";
     return;
   }
 
@@ -198,7 +202,7 @@
   // TODO(johngro): Look into eliminating most of the format_info class when we
   // finish removing the old audio renderer interface.  At the very least,
   // switch to using the AudioPcmFormat struct instead of AudioMediaTypeDetails
-  AudioMediaTypeDetails cfg;
+  fuchsia::media::AudioMediaTypeDetails cfg;
   cfg.sample_format = format.sample_format;
   cfg.channels = format.channels;
   cfg.frames_per_second = format.frames_per_second;
@@ -241,7 +245,7 @@
   // Map this into a sub-vmar instead of defaulting to the root
   // once teisenbe@ provides guidance on the best-practice for doing this.
   zx_status_t res;
-  payload_buffer_ = fbl::AdoptRef(new fbl::RefCountedVmoMapper());
+  payload_buffer_ = fbl::AdoptRef(new vmo_utils::RefCountedVmoMapper());
   res = payload_buffer_->Map(payload_buffer, 0, 0, ZX_VM_FLAG_PERM_READ);
   if (res != ZX_OK) {
     FXL_LOG(ERROR) << "Failed to map payload buffer (res = " << res << ")";
@@ -318,7 +322,7 @@
   FXL_LOG(WARNING) << "Not Implemented : " << __PRETTY_FUNCTION__;
 }
 
-void AudioRenderer2Impl::SendPacket(AudioPacket packet,
+void AudioRenderer2Impl::SendPacket(fuchsia::media::AudioPacket packet,
                                     SendPacketCallback callback) {
   auto cleanup = fbl::MakeAutoCall([this]() { Shutdown(); });
 
@@ -369,14 +373,15 @@
   // to frames transformation needs to be computed (this should be needed after
   // startup, and after each flush operation).
   if (!pts_to_frac_frames_valid_) {
-    ComputePtsToFracFrames(
-        (packet.timestamp == kNoTimestamp) ? 0 : packet.timestamp);
+    ComputePtsToFracFrames((packet.timestamp == fuchsia::media::kNoTimestamp)
+                               ? 0
+                               : packet.timestamp);
   }
 
   // Now compute the starting PTS expressed in fractional input frames.  If no
   // explicit PTS was provided, interpolate using the next expected PTS.
   int64_t start_pts;
-  if (packet.timestamp == kNoTimestamp) {
+  if (packet.timestamp == fuchsia::media::kNoTimestamp) {
     start_pts = next_frac_frame_pts_;
   } else {
     // Looks like we have an explicit PTS on this packet.  Boost it into the
@@ -421,7 +426,7 @@
   cleanup.cancel();
 }
 
-void AudioRenderer2Impl::SendPacketNoReply(AudioPacket packet) {
+void AudioRenderer2Impl::SendPacketNoReply(fuchsia::media::AudioPacket packet) {
   SendPacket(std::move(packet), nullptr);
 }
 
@@ -470,7 +475,7 @@
   //
   // TODO(johngro): We need to use our reference clock here, and not just assume
   // clock monotonic is our reference clock.
-  if (reference_time == kNoTimestamp) {
+  if (reference_time == fuchsia::media::kNoTimestamp) {
     // TODO(johngro): How much more than the minimum clock lead time do we want
     // to pad this by?  Also, if/when lead time requirements change, do we want
     // to introduce a discontinuity?
@@ -497,7 +502,7 @@
   // defined when we transition to our operational mode.  We need to remember to
   // translate back and forth as appropriate.
   int64_t frac_frame_media_time;
-  if (media_time == kNoTimestamp) {
+  if (media_time == fuchsia::media::kNoTimestamp) {
     // Are we resuming from pause?
     if (pause_time_frac_frames_valid_) {
       frac_frame_media_time = pause_time_frac_frames_;
@@ -597,8 +602,8 @@
                                      SetGainMuteCallback callback) {
   auto cleanup = fbl::MakeAutoCall([this]() { Shutdown(); });
   bool dirty = false;
-  if ((flags & kGainFlagGainValid) && (db_gain_ != gain)) {
-    if (gain > kMaxGain) {
+  if ((flags & fuchsia::media::kGainFlagGainValid) && (db_gain_ != gain)) {
+    if (gain > fuchsia::media::kMaxGain) {
       FXL_LOG(ERROR) << "Gain value too large (" << gain
                      << ") for audio renderer.";
       return;
@@ -608,13 +613,13 @@
     dirty = true;
   }
 
-  if ((flags & kGainFlagMuteValid) && (mute_ != mute)) {
+  if ((flags & fuchsia::media::kGainFlagMuteValid) && (mute_ != mute)) {
     mute_ = mute;
     dirty = true;
   }
 
   if (dirty) {
-    float effective_gain = mute_ ? kMutedGain : db_gain_;
+    float effective_gain = mute_ ? fuchsia::media::kMutedGain : db_gain_;
 
     fbl::AutoLock links_lock(&links_lock_);
     for (const auto& link : dest_links_) {
@@ -638,7 +643,7 @@
 }
 
 void AudioRenderer2Impl::DuplicateGainControlInterface(
-    fidl::InterfaceRequest<AudioRendererGainControl> request) {
+    fidl::InterfaceRequest<fuchsia::media::AudioRendererGainControl> request) {
   gain_control_bindings_.AddBinding(GainControlBinding::Create(this),
                                     std::move(request));
 }
@@ -660,9 +665,10 @@
 }
 
 AudioRenderer2Impl::AudioPacketRefV2::AudioPacketRefV2(
-    fbl::RefPtr<fbl::RefCountedVmoMapper> vmo_ref,
-    AudioRenderer2::SendPacketCallback callback, AudioPacket packet,
-    AudioServerImpl* server, uint32_t frac_frame_len, int64_t start_pts)
+    fbl::RefPtr<vmo_utils::RefCountedVmoMapper> vmo_ref,
+    fuchsia::media::AudioRenderer2::SendPacketCallback callback,
+    fuchsia::media::AudioPacket packet, AudioServerImpl* server,
+    uint32_t frac_frame_len, int64_t start_pts)
     : AudioPacketRef(server, frac_frame_len, start_pts),
       vmo_ref_(std::move(vmo_ref)),
       callback_(callback),
diff --git a/bin/media/audio_server/audio_renderer2_impl.h b/bin/media/audio_server/audio_renderer2_impl.h
index b8d2d38..05b6141 100644
--- a/bin/media/audio_server/audio_renderer2_impl.h
+++ b/bin/media/audio_server/audio_renderer2_impl.h
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER2_IMPL_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER2_IMPL_H_
 
 #include <fbl/unique_ptr.h>
-#include <fbl/vmo_mapper.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/vmo-utils/vmo_mapper.h>
 
-#include <media/cpp/fidl.h>
 #include "garnet/bin/media/audio_server/audio_object.h"
 #include "garnet/bin/media/audio_server/audio_renderer_impl.h"
 #include "garnet/bin/media/audio_server/utils.h"
@@ -19,10 +20,12 @@
 
 class AudioServerImpl;
 
-class AudioRenderer2Impl : public AudioRendererImpl, public AudioRenderer2 {
+class AudioRenderer2Impl : public AudioRendererImpl,
+                           public fuchsia::media::AudioRenderer2 {
  public:
   static fbl::RefPtr<AudioRenderer2Impl> Create(
-      fidl::InterfaceRequest<AudioRenderer2> audio_renderer_request,
+      fidl::InterfaceRequest<fuchsia::media::AudioRenderer2>
+          audio_renderer_request,
       AudioServerImpl* owner);
 
   // AudioRendererImpl implementation
@@ -35,14 +38,15 @@
                                        uint32_t* generation) override;
 
   // AudioRenderer2 Interface
-  void SetPcmFormat(AudioPcmFormat format) final;
+  void SetPcmFormat(fuchsia::media::AudioPcmFormat format) final;
   void SetPayloadBuffer(zx::vmo payload_buffer) final;
   void SetPtsUnits(uint32_t tick_per_second_numerator,
                    uint32_t tick_per_second_denominator) final;
   void SetPtsContinuityThreshold(float threshold_seconds) final;
   void SetReferenceClock(zx::handle ref_clock) final;
-  void SendPacket(AudioPacket packet, SendPacketCallback callback) final;
-  void SendPacketNoReply(AudioPacket packet) final;
+  void SendPacket(fuchsia::media::AudioPacket packet,
+                  SendPacketCallback callback) final;
+  void SendPacketNoReply(fuchsia::media::AudioPacket packet) final;
   void Flush(FlushCallback callback) final;
   void FlushNoReply() final;
   void Play(int64_t reference_time, int64_t media_time,
@@ -54,7 +58,8 @@
                    SetGainMuteCallback callback) final;
   void SetGainMuteNoReply(float gain, bool mute, uint32_t flags) final;
   void DuplicateGainControlInterface(
-      fidl::InterfaceRequest<AudioRendererGainControl> request) final;
+      fidl::InterfaceRequest<fuchsia::media::AudioRendererGainControl> request)
+      final;
   void EnableMinLeadTimeEvents(bool enabled) final;
   void GetMinLeadTime(GetMinLeadTimeCallback callback) final;
 
@@ -81,20 +86,21 @@
 
     uint32_t flags() final { return packet_.flags; }
 
-    AudioPacketRefV2(fbl::RefPtr<fbl::RefCountedVmoMapper> vmo_ref,
-                     AudioRenderer2::SendPacketCallback callback,
-                     AudioPacket packet, AudioServerImpl* server,
-                     uint32_t frac_frame_len, int64_t start_pts);
+    AudioPacketRefV2(
+        fbl::RefPtr<vmo_utils::RefCountedVmoMapper> vmo_ref,
+        fuchsia::media::AudioRenderer2::SendPacketCallback callback,
+        fuchsia::media::AudioPacket packet, AudioServerImpl* server,
+        uint32_t frac_frame_len, int64_t start_pts);
 
    protected:
     bool NeedsCleanup() final { return callback_ != nullptr; }
 
-    fbl::RefPtr<fbl::RefCountedVmoMapper> vmo_ref_;
-    AudioRenderer2::SendPacketCallback callback_;
-    AudioPacket packet_;
+    fbl::RefPtr<vmo_utils::RefCountedVmoMapper> vmo_ref_;
+    fuchsia::media::AudioRenderer2::SendPacketCallback callback_;
+    fuchsia::media::AudioPacket packet_;
   };
 
-  class GainControlBinding : public AudioRendererGainControl {
+  class GainControlBinding : public fuchsia::media::AudioRendererGainControl {
    public:
     static fbl::unique_ptr<GainControlBinding> Create(
         AudioRenderer2Impl* owner) {
@@ -121,9 +127,9 @@
   friend class fbl::RefPtr<AudioRenderer2Impl>;
   friend class GainControlBinding;
 
-  AudioRenderer2Impl(
-      fidl::InterfaceRequest<AudioRenderer2> audio_renderer_request,
-      AudioServerImpl* owner);
+  AudioRenderer2Impl(fidl::InterfaceRequest<fuchsia::media::AudioRenderer2>
+                         audio_renderer_request,
+                     AudioServerImpl* owner);
 
   ~AudioRenderer2Impl() override;
 
@@ -132,13 +138,13 @@
   void ComputePtsToFracFrames(int64_t first_pts);
 
   AudioServerImpl* owner_ = nullptr;
-  fidl::Binding<AudioRenderer2> audio_renderer_binding_;
-  fidl::BindingSet<AudioRendererGainControl,
+  fidl::Binding<fuchsia::media::AudioRenderer2> audio_renderer_binding_;
+  fidl::BindingSet<fuchsia::media::AudioRendererGainControl,
                    fbl::unique_ptr<GainControlBinding>>
       gain_control_bindings_;
   bool is_shutdown_ = false;
   bool gain_events_enabled_ = false;
-  fbl::RefPtr<fbl::RefCountedVmoMapper> payload_buffer_;
+  fbl::RefPtr<vmo_utils::RefCountedVmoMapper> payload_buffer_;
   bool config_validated_ = false;
 
   // PTS interpolation state.
@@ -166,3 +172,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER2_IMPL_H_
diff --git a/bin/media/audio_server/audio_renderer_format_info.cc b/bin/media/audio_server/audio_renderer_format_info.cc
index 17bd318..82dff3f 100644
--- a/bin/media/audio_server/audio_renderer_format_info.cc
+++ b/bin/media/audio_server/audio_renderer_format_info.cc
@@ -10,7 +10,8 @@
 namespace media {
 namespace audio {
 
-AudioRendererFormatInfo::AudioRendererFormatInfo(AudioMediaTypeDetails format)
+AudioRendererFormatInfo::AudioRendererFormatInfo(
+    fuchsia::media::AudioMediaTypeDetails format)
     : format_(std::move(format)) {
   // Precompute some useful timing/format stuff.
   //
@@ -24,16 +25,16 @@
 
   // Figure out the total number of bytes in a packed frame.
   switch (format_.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       bytes_per_frame_ = 1;
       break;
 
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       bytes_per_frame_ = 2;
       break;
 
-    case AudioSampleFormat::SIGNED_24_IN_32:
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       bytes_per_frame_ = 4;
       break;
 
@@ -52,7 +53,7 @@
 
 // static
 fbl::RefPtr<AudioRendererFormatInfo> AudioRendererFormatInfo::Create(
-    AudioMediaTypeDetails format) {
+    fuchsia::media::AudioMediaTypeDetails format) {
   return fbl::AdoptRef(new AudioRendererFormatInfo(std::move(format)));
 }
 
diff --git a/bin/media/audio_server/audio_renderer_format_info.h b/bin/media/audio_server/audio_renderer_format_info.h
index 45756d6..c78e79c 100644
--- a/bin/media/audio_server/audio_renderer_format_info.h
+++ b/bin/media/audio_server/audio_renderer_format_info.h
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER_FORMAT_INFO_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER_FORMAT_INFO_H_
 
 #include <fbl/ref_counted.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <stdint.h>
 
-#include <media/cpp/fidl.h>
 #include "garnet/bin/media/audio_server/fwd_decls.h"
 #include "lib/media/timeline/timeline_rate.h"
 
@@ -18,9 +19,11 @@
     : public fbl::RefCounted<AudioRendererFormatInfo> {
  public:
   static fbl::RefPtr<AudioRendererFormatInfo> Create(
-      AudioMediaTypeDetails format);
+      fuchsia::media::AudioMediaTypeDetails format);
 
-  const AudioMediaTypeDetails& format() const { return format_; }
+  const fuchsia::media::AudioMediaTypeDetails& format() const {
+    return format_;
+  }
   const TimelineRate& frames_per_ns() const { return frames_per_ns_; }
   const TimelineRate& frame_to_media_ratio() const {
     return frame_to_media_ratio_;
@@ -30,9 +33,9 @@
  private:
   FXL_DISALLOW_COPY_AND_ASSIGN(AudioRendererFormatInfo);
 
-  AudioRendererFormatInfo(AudioMediaTypeDetails format);
+  AudioRendererFormatInfo(fuchsia::media::AudioMediaTypeDetails format);
 
-  AudioMediaTypeDetails format_;
+  fuchsia::media::AudioMediaTypeDetails format_;
   TimelineRate frames_per_ns_;
   TimelineRate frame_to_media_ratio_;
   uint32_t bytes_per_frame_;
@@ -40,3 +43,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER_FORMAT_INFO_H_
diff --git a/bin/media/audio_server/audio_renderer_impl.h b/bin/media/audio_server/audio_renderer_impl.h
index a9d3c93..d578cd5 100644
--- a/bin/media/audio_server/audio_renderer_impl.h
+++ b/bin/media/audio_server/audio_renderer_impl.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER_IMPL_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER_IMPL_H_
 
 #include "garnet/bin/media/audio_server/audio_link_packet_source.h"
 #include "garnet/bin/media/audio_server/audio_object.h"
@@ -61,3 +62,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_RENDERER_IMPL_H_
diff --git a/bin/media/audio_server/audio_server_impl.cc b/bin/media/audio_server/audio_server_impl.cc
index 8f42174..b04666a 100644
--- a/bin/media/audio_server/audio_server_impl.cc
+++ b/bin/media/audio_server/audio_server_impl.cc
@@ -20,10 +20,12 @@
   auto service =
       fbl::AdoptRef(new fs::Service([this](zx::channel ch) -> zx_status_t {
         bindings_.AddBinding(
-            this, fidl::InterfaceRequest<AudioServer>(std::move(ch)));
+            this,
+            fidl::InterfaceRequest<fuchsia::media::AudioServer>(std::move(ch)));
         return ZX_OK;
       }));
-  outgoing_.public_dir()->AddEntry(AudioServer::Name_, std::move(service));
+  outgoing_.public_dir()->AddEntry(fuchsia::media::AudioServer::Name_,
+                                   std::move(service));
 
   // Stash a pointer to our async object.
   async_ = async_get_default();
@@ -44,9 +46,9 @@
       async_, []() { zx_thread_set_priority(24 /* HIGH_PRIORITY in LK */); });
 
   // Set up our output manager.
-  MediaResult res = device_manager_.Init();
+  fuchsia::media::MediaResult res = device_manager_.Init();
   // TODO(johngro): Do better at error handling than this weak check.
-  FXL_DCHECK(res == MediaResult::OK);
+  FXL_DCHECK(res == fuchsia::media::MediaResult::OK);
 
   // Wait for 50 mSec before we export our services and start to process client
   // requests.  This will give the device manager layer time to discover the
@@ -73,20 +75,21 @@
 }
 
 void AudioServerImpl::CreateRenderer(
-    fidl::InterfaceRequest<AudioRenderer> audio_renderer,
-    fidl::InterfaceRequest<MediaRenderer> media_renderer) {
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer> audio_renderer,
+    fidl::InterfaceRequest<fuchsia::media::MediaRenderer> media_renderer) {
   device_manager_.AddRenderer(AudioRenderer1Impl::Create(
       std::move(audio_renderer), std::move(media_renderer), this));
 }
 
 void AudioServerImpl::CreateRendererV2(
-    fidl::InterfaceRequest<AudioRenderer2> audio_renderer) {
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer2> audio_renderer) {
   device_manager_.AddRenderer(
       AudioRenderer2Impl::Create(std::move(audio_renderer), this));
 }
 
 void AudioServerImpl::CreateCapturer(
-    fidl::InterfaceRequest<AudioCapturer> audio_capturer_request,
+    fidl::InterfaceRequest<fuchsia::media::AudioCapturer>
+        audio_capturer_request,
     bool loopback) {
   device_manager_.AddCapturer(AudioCapturerImpl::Create(
       std::move(audio_capturer_request), this, loopback));
diff --git a/bin/media/audio_server/audio_server_impl.h b/bin/media/audio_server/audio_server_impl.h
index 0a9fb74..74af722 100644
--- a/bin/media/audio_server/audio_server_impl.h
+++ b/bin/media/audio_server/audio_server_impl.h
@@ -2,15 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_SERVER_IMPL_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_SERVER_IMPL_H_
+
+#include <mutex>
 
 #include <fbl/intrusive_double_list.h>
 #include <fbl/unique_ptr.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 
-#include <mutex>
-
 #include "garnet/bin/media/audio_server/audio_device_manager.h"
 #include "garnet/bin/media/audio_server/audio_packet_ref.h"
 #include "garnet/bin/media/audio_server/fwd_decls.h"
@@ -23,7 +24,7 @@
 namespace media {
 namespace audio {
 
-class AudioServerImpl : public AudioServer {
+class AudioServerImpl : public fuchsia::media::AudioServer {
  public:
   AudioServerImpl();
   ~AudioServerImpl() override;
@@ -32,13 +33,14 @@
   // TODO(mpuryear): through the codebase, particularly in examples and headers,
   // change 'audio_renderer' variables to 'audio_renderer_request' (media, etc).
   void CreateRenderer(
-      fidl::InterfaceRequest<AudioRenderer> audio_renderer,
-      fidl::InterfaceRequest<MediaRenderer> media_renderer) final;
-  void CreateRendererV2(
-      fidl::InterfaceRequest<AudioRenderer2> audio_renderer) final;
-  void CreateCapturer(
-      fidl::InterfaceRequest<AudioCapturer> audio_capturer_request,
-      bool loopback) final;
+      fidl::InterfaceRequest<fuchsia::media::AudioRenderer> audio_renderer,
+      fidl::InterfaceRequest<fuchsia::media::MediaRenderer> media_renderer)
+      final;
+  void CreateRendererV2(fidl::InterfaceRequest<fuchsia::media::AudioRenderer2>
+                            audio_renderer) final;
+  void CreateCapturer(fidl::InterfaceRequest<fuchsia::media::AudioCapturer>
+                          audio_capturer_request,
+                      bool loopback) final;
   void SetMasterGain(float db_gain) final;
   void GetMasterGain(GetMasterGainCallback cbk) final;
 
@@ -56,9 +58,9 @@
   void ScheduleFlushCleanup(fbl::unique_ptr<PendingFlushToken> token);
 
   // Schedule a closure to run on the server's main message loop.
-  void ScheduleMainThreadTask(const fxl::Closure& task) {
+  void ScheduleMainThreadTask(fit::closure task) {
     FXL_DCHECK(async_);
-    async::PostTask(async_, task);
+    async::PostTask(async_, std::move(task));
   }
 
   // Accessor for our encapsulated device manager.
@@ -69,7 +71,7 @@
   void DoPacketCleanup();
 
   fuchsia::sys::Outgoing outgoing_;
-  fidl::BindingSet<AudioServer> bindings_;
+  fidl::BindingSet<fuchsia::media::AudioServer> bindings_;
 
   // A reference to our thread's async object.  Allows us to post events to
   // be handled by our main application thread from things like the output
@@ -93,3 +95,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_AUDIO_SERVER_IMPL_H_
diff --git a/bin/media/audio_server/constants.h b/bin/media/audio_server/constants.h
index f85bc1a..c925b10 100644
--- a/bin/media/audio_server/constants.h
+++ b/bin/media/audio_server/constants.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_CONSTANTS_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_CONSTANTS_H_
 
 #include <stdint.h>
 
@@ -45,3 +46,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_CONSTANTS_H_
diff --git a/bin/media/audio_server/driver_output.cc b/bin/media/audio_server/driver_output.cc
index 2bb2c65..a2be283 100644
--- a/bin/media/audio_server/driver_output.cc
+++ b/bin/media/audio_server/driver_output.cc
@@ -4,13 +4,14 @@
 
 #include "garnet/bin/media/audio_server/driver_output.h"
 
+#include <iomanip>
+
 #include <audio-proto-utils/format-utils.h>
 #include <dispatcher-pool/dispatcher-channel.h>
 #include <fbl/atomic.h>
 #include <fbl/auto_call.h>
 #include <fbl/limits.h>
 #include <zircon/process.h>
-#include <iomanip>
 
 #include "garnet/bin/media/audio_server/audio_device_manager.h"
 #include "garnet/lib/media/wav_writer/wav_writer.h"
@@ -23,8 +24,8 @@
 
 static constexpr uint32_t kDefaultFramesPerSec = 48000;
 static constexpr uint32_t kDefaultChannelCount = 2;
-static constexpr AudioSampleFormat kDefaultAudioFmt =
-    AudioSampleFormat::SIGNED_16;
+static constexpr fuchsia::media::AudioSampleFormat kDefaultAudioFmt =
+    fuchsia::media::AudioSampleFormat::SIGNED_16;
 static constexpr int64_t kDefaultLowWaterNsec = ZX_MSEC(20);
 static constexpr int64_t kDefaultHighWaterNsec = ZX_MSEC(30);
 static constexpr int64_t kDefaultMaxRetentionNsec = ZX_MSEC(60);
@@ -46,11 +47,11 @@
 
 DriverOutput::~DriverOutput() { wav_writer_.Close(); }
 
-MediaResult DriverOutput::Init() {
+fuchsia::media::MediaResult DriverOutput::Init() {
   FXL_DCHECK(state_ == State::Uninitialized);
 
-  MediaResult init_res = StandardOutputBase::Init();
-  if (init_res != MediaResult::OK) {
+  fuchsia::media::MediaResult init_res = StandardOutputBase::Init();
+  if (init_res != fuchsia::media::MediaResult::OK) {
     return init_res;
   }
 
@@ -58,11 +59,11 @@
   if (zx_res != ZX_OK) {
     FXL_LOG(ERROR) << "Failed to initialize driver object (res " << zx_res
                    << ")";
-    return MediaResult::INTERNAL_ERROR;
+    return fuchsia::media::MediaResult::INTERNAL_ERROR;
   }
 
   state_ = State::FormatsUnknown;
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void DriverOutput::OnWakeup() {
@@ -266,7 +267,7 @@
   // match among the formats supported by the driver.
   uint32_t pref_fps = kDefaultFramesPerSec;
   uint32_t pref_chan = kDefaultChannelCount;
-  AudioSampleFormat pref_fmt = kDefaultAudioFmt;
+  fuchsia::media::AudioSampleFormat pref_fmt = kDefaultAudioFmt;
   zx_duration_t min_rb_duration = kDefaultHighWaterNsec +
                                   kDefaultMaxRetentionNsec +
                                   kDefaultRetentionGapNsec;
@@ -295,7 +296,8 @@
       static_cast<uint32_t>(retention_frames));
 
   // Select our output formatter
-  AudioMediaTypeDetailsPtr config(AudioMediaTypeDetails::New());
+  fuchsia::media::AudioMediaTypeDetailsPtr config(
+      fuchsia::media::AudioMediaTypeDetails::New());
   config->frames_per_second = pref_fps;
   config->channels = pref_chan;
   config->sample_format = pref_fmt;
diff --git a/bin/media/audio_server/driver_output.h b/bin/media/audio_server/driver_output.h
index 38b8023..bc83e31 100644
--- a/bin/media/audio_server/driver_output.h
+++ b/bin/media/audio_server/driver_output.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_OUTPUT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_OUTPUT_H_
 
 #include <dispatcher-pool/dispatcher-channel.h>
 #include <lib/zx/channel.h>
@@ -25,7 +26,7 @@
   ~DriverOutput();
 
   // AudioOutput implementation
-  MediaResult Init() override;
+  fuchsia::media::MediaResult Init() override;
   void OnWakeup() FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain_->token()) override;
 
   void Cleanup() override;
@@ -80,3 +81,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_OUTPUT_H_
diff --git a/bin/media/audio_server/driver_ring_buffer.h b/bin/media/audio_server/driver_ring_buffer.h
index f17abfb..8ebc8acf 100644
--- a/bin/media/audio_server/driver_ring_buffer.h
+++ b/bin/media/audio_server/driver_ring_buffer.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_RING_BUFFER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_RING_BUFFER_H_
 
 #include <fbl/ref_counted.h>
 #include <fbl/ref_ptr.h>
@@ -39,3 +40,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_RING_BUFFER_H_
diff --git a/bin/media/audio_server/driver_utils.cc b/bin/media/audio_server/driver_utils.cc
index 09e689e..da5d845 100644
--- a/bin/media/audio_server/driver_utils.cc
+++ b/bin/media/audio_server/driver_utils.cc
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <audio-proto-utils/format-utils.h>
 #include <map>
 
+#include <audio-proto-utils/format-utils.h>
+
 #include "garnet/bin/media/audio_server/driver_utils.h"
 #include "lib/fxl/logging.h"
 
@@ -16,26 +17,34 @@
     static_cast<audio_sample_format_t>(AUDIO_SAMPLE_FORMAT_8BIT |
                                        AUDIO_SAMPLE_FORMAT_FLAG_UNSIGNED);
 
-static const std::map<audio_sample_format_t, AudioSampleFormat>
+static const std::map<audio_sample_format_t, fuchsia::media::AudioSampleFormat>
     kDriverSampleFormatToSampleFormatMap = {
-        {AUDIO_SAMPLE_FORMAT_UNSIGNED_8BIT, AudioSampleFormat::UNSIGNED_8},
-        {AUDIO_SAMPLE_FORMAT_16BIT, AudioSampleFormat::SIGNED_16},
-        {AUDIO_SAMPLE_FORMAT_24BIT_IN32, AudioSampleFormat::SIGNED_24_IN_32},
-        {AUDIO_SAMPLE_FORMAT_32BIT_FLOAT, AudioSampleFormat::FLOAT},
+        {AUDIO_SAMPLE_FORMAT_UNSIGNED_8BIT,
+         fuchsia::media::AudioSampleFormat::UNSIGNED_8},
+        {AUDIO_SAMPLE_FORMAT_16BIT,
+         fuchsia::media::AudioSampleFormat::SIGNED_16},
+        {AUDIO_SAMPLE_FORMAT_24BIT_IN32,
+         fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32},
+        {AUDIO_SAMPLE_FORMAT_32BIT_FLOAT,
+         fuchsia::media::AudioSampleFormat::FLOAT},
 };
 
-static const std::map<AudioSampleFormat, audio_sample_format_t>
+static const std::map<fuchsia::media::AudioSampleFormat, audio_sample_format_t>
     kSampleFormatToDriverSampleFormatMap = {
-        {AudioSampleFormat::UNSIGNED_8, AUDIO_SAMPLE_FORMAT_UNSIGNED_8BIT},
-        {AudioSampleFormat::SIGNED_16, AUDIO_SAMPLE_FORMAT_16BIT},
-        {AudioSampleFormat::SIGNED_24_IN_32, AUDIO_SAMPLE_FORMAT_24BIT_IN32},
-        {AudioSampleFormat::FLOAT, AUDIO_SAMPLE_FORMAT_32BIT_FLOAT},
+        {fuchsia::media::AudioSampleFormat::UNSIGNED_8,
+         AUDIO_SAMPLE_FORMAT_UNSIGNED_8BIT},
+        {fuchsia::media::AudioSampleFormat::SIGNED_16,
+         AUDIO_SAMPLE_FORMAT_16BIT},
+        {fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32,
+         AUDIO_SAMPLE_FORMAT_24BIT_IN32},
+        {fuchsia::media::AudioSampleFormat::FLOAT,
+         AUDIO_SAMPLE_FORMAT_32BIT_FLOAT},
 };
 
 }  // namespace
 
 bool AudioSampleFormatToDriverSampleFormat(
-    AudioSampleFormat sample_format,
+    fuchsia::media::AudioSampleFormat sample_format,
     audio_sample_format_t* driver_sample_format_out) {
   FXL_DCHECK(driver_sample_format_out != nullptr);
 
@@ -50,7 +59,7 @@
 
 bool DriverSampleFormatToAudioSampleFormat(
     audio_sample_format_t driver_sample_format,
-    AudioSampleFormat* sample_format_out) {
+    fuchsia::media::AudioSampleFormat* sample_format_out) {
   auto iter = kDriverSampleFormatToSampleFormatMap.find(driver_sample_format);
   if (iter == kDriverSampleFormatToSampleFormatMap.end()) {
     return false;
diff --git a/bin/media/audio_server/driver_utils.h b/bin/media/audio_server/driver_utils.h
index aff5d6b..310611c 100644
--- a/bin/media/audio_server/driver_utils.h
+++ b/bin/media/audio_server/driver_utils.h
@@ -2,26 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_UTILS_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_UTILS_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <zircon/device/audio.h>
 
 namespace media {
 namespace driver_utils {
 
-// Convert an AudioSampleFormat into an audio stream driver
-// sample_format.  Returns true if the conversion succeed, or false if it does
-// not.
+// Convert an AudioSampleFormat into an audio stream driver sample_format.
+// Returns true if the conversion succeed, or false if it does not.
 bool AudioSampleFormatToDriverSampleFormat(
-    AudioSampleFormat sample_format,
+    fuchsia::media::AudioSampleFormat sample_format,
     audio_sample_format_t* driver_sample_format_out);
 
 // Convert an audio stream driver sample_format into an AudioSampleFormat.
 // Returns true if the conversion succeed, or false if it does not.
 bool DriverSampleFormatToAudioSampleFormat(
     audio_sample_format_t driver_sample_format,
-    AudioSampleFormat* sample_format_out);
+    fuchsia::media::AudioSampleFormat* sample_format_out);
 
 }  // namespace driver_utils
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_DRIVER_UTILS_H_
diff --git a/bin/media/audio_server/fwd_decls.h b/bin/media/audio_server/fwd_decls.h
index a918bd0..e4a2570 100644
--- a/bin/media/audio_server/fwd_decls.h
+++ b/bin/media/audio_server/fwd_decls.h
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_FWD_DECLS_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_FWD_DECLS_H_
 
-#include <fbl/ref_ptr.h>
 #include <memory>
 #include <set>
 
+#include <fbl/ref_ptr.h>
+
 namespace media {
 namespace audio {
 
@@ -24,3 +26,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_FWD_DECLS_H_
diff --git a/bin/media/audio_server/gain.h b/bin/media/audio_server/gain.h
index 0c0abf3..79946a0 100644
--- a/bin/media/audio_server/gain.h
+++ b/bin/media/audio_server/gain.h
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_GAIN_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_GAIN_H_
 
-#include <stdint.h>
 #include <atomic>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <stdint.h>
 
 #include "garnet/bin/media/audio_server/constants.h"
 
@@ -40,8 +41,8 @@
       (static_cast<AScale>(1u) << kFractionalScaleBits);
   static constexpr AScale kMaxScale = 0xFD9539A4;  // +24.0 dB: kMaxGain
 
-  static constexpr float kMinGain = media::kMutedGain;
-  static constexpr float kMaxGain = media::kMaxGain;
+  static constexpr float kMinGain = fuchsia::media::kMutedGain;
+  static constexpr float kMaxGain = fuchsia::media::kMaxGain;
 
   // TODO(mpuryear): MTWN-70 Clarify/document/test audio::Gain's thread-safety
   //
@@ -85,3 +86,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_GAIN_H_
diff --git a/bin/media/audio_server/mixer/BUILD.gn b/bin/media/audio_server/mixer/BUILD.gn
index 48225ba..84008ae 100644
--- a/bin/media/audio_server/mixer/BUILD.gn
+++ b/bin/media/audio_server/mixer/BUILD.gn
@@ -9,30 +9,30 @@
   output_name = "audio_mixer_tests"
 
   sources = [
-    "test/main.cc",
-    "test/audio_analysis.h",
     "test/audio_analysis.cc",
+    "test/audio_analysis.h",
     "test/audio_analysis_tests.cc",
-    "test/audio_result.h",
-    "test/audio_result.cc",
-    "test/frequency_set.h",
-    "test/frequency_set.cc",
-    "test/mixer_tests_shared.h",
-    "test/mixer_tests_shared.cc",
-    "test/mixer_transparency_tests.cc",
-    "test/mixer_gain_tests.cc",
-    "test/mixer_resampler_tests.cc",
-    "test/mixer_frequency_tests.cc",
-    "test/mixer_dynamic_range_tests.cc",
     "test/audio_performance.cc",
     "test/audio_performance.h",
+    "test/audio_result.cc",
+    "test/audio_result.h",
+    "test/frequency_set.cc",
+    "test/frequency_set.h",
+    "test/main.cc",
+    "test/mixer_dynamic_range_tests.cc",
+    "test/mixer_frequency_tests.cc",
+    "test/mixer_gain_tests.cc",
+    "test/mixer_resampler_tests.cc",
     "test/mixer_tests_recap.cc",
+    "test/mixer_tests_shared.cc",
+    "test/mixer_tests_shared.h",
+    "test/mixer_transparency_tests.cc",
   ]
 
   deps = [
     "//garnet/bin/media/audio_server:audio_mixer_lib",
-    "//third_party/googletest:gtest_main",
     "//garnet/public/lib/fxl",
+    "//third_party/googletest:gtest_main",
     "//zircon/public/lib/fbl",
   ]
 }
diff --git a/bin/media/audio_server/mixer/linear_sampler.cc b/bin/media/audio_server/mixer/linear_sampler.cc
index 24e0bf8..8490344 100644
--- a/bin/media/audio_server/mixer/linear_sampler.cc
+++ b/bin/media/audio_server/mixer/linear_sampler.cc
@@ -561,14 +561,16 @@
 // Templates used to expand all of the different combinations of the possible
 // LinearSampler Mixer configurations.
 template <size_t DChCount, typename SType, size_t SChCount>
-static inline MixerPtr SelectLSM(const AudioMediaTypeDetails& src_format,
-                                 const AudioMediaTypeDetails& dst_format) {
+static inline MixerPtr SelectLSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   return MixerPtr(new LinearSamplerImpl<DChCount, SType, SChCount>());
 }
 
 template <size_t DChCount, typename SType>
-static inline MixerPtr SelectLSM(const AudioMediaTypeDetails& src_format,
-                                 const AudioMediaTypeDetails& dst_format) {
+static inline MixerPtr SelectLSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   switch (src_format.channels) {
     case 1:
       return SelectLSM<DChCount, SType, 1>(src_format, dst_format);
@@ -580,35 +582,38 @@
 }
 
 template <size_t DChCount>
-static inline MixerPtr SelectLSM(const AudioMediaTypeDetails& src_format,
-                                 const AudioMediaTypeDetails& dst_format) {
+static inline MixerPtr SelectLSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   switch (src_format.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return SelectLSM<DChCount, uint8_t>(src_format, dst_format);
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return SelectLSM<DChCount, int16_t>(src_format, dst_format);
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return SelectLSM<DChCount, float>(src_format, dst_format);
     default:
       return nullptr;
   }
 }
 
-static inline MixerPtr SelectNxNLSM(const AudioMediaTypeDetails& src_format) {
+static inline MixerPtr SelectNxNLSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format) {
   switch (src_format.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return MixerPtr(new NxNLinearSamplerImpl<uint8_t>(src_format.channels));
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return MixerPtr(new NxNLinearSamplerImpl<int16_t>(src_format.channels));
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return MixerPtr(new NxNLinearSamplerImpl<float>(src_format.channels));
     default:
       return nullptr;
   }
 }
 
-MixerPtr LinearSampler::Select(const AudioMediaTypeDetails& src_format,
-                               const AudioMediaTypeDetails& dst_format) {
+MixerPtr LinearSampler::Select(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   if (src_format.channels == dst_format.channels && src_format.channels > 2) {
     return SelectNxNLSM(src_format);
   }
diff --git a/bin/media/audio_server/mixer/linear_sampler.h b/bin/media/audio_server/mixer/linear_sampler.h
index ba9c71d..a32d5b2 100644
--- a/bin/media/audio_server/mixer/linear_sampler.h
+++ b/bin/media/audio_server/mixer/linear_sampler.h
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_LINEAR_SAMPLER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_LINEAR_SAMPLER_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/audio_server/mixer/mixer.h"
 
 namespace media {
@@ -13,8 +15,9 @@
 
 class LinearSampler : public Mixer {
  public:
-  static MixerPtr Select(const AudioMediaTypeDetails& src_format,
-                         const AudioMediaTypeDetails& dst_format);
+  static MixerPtr Select(
+      const fuchsia::media::AudioMediaTypeDetails& src_format,
+      const fuchsia::media::AudioMediaTypeDetails& dst_format);
 
  protected:
   LinearSampler(uint32_t pos_filter_width, uint32_t neg_filter_width)
@@ -24,3 +27,5 @@
 }  // namespace mixer
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_LINEAR_SAMPLER_H_
diff --git a/bin/media/audio_server/mixer/mixer.cc b/bin/media/audio_server/mixer/mixer.cc
index 66dde17..bbc9f91 100644
--- a/bin/media/audio_server/mixer/mixer.cc
+++ b/bin/media/audio_server/mixer/mixer.cc
@@ -30,14 +30,18 @@
 // specified, or if Resampler::Default, the existing selection algorithm is
 // used. Note that requiring a specific resampler may cause Mixer::Select() to
 // fail (i.e. return nullptr), even in cases where 'Default' would succeed.
-MixerPtr Mixer::Select(const AudioMediaTypeDetails& src_format,
-                       const AudioMediaTypeDetails& dst_format,
+MixerPtr Mixer::Select(const fuchsia::media::AudioMediaTypeDetails& src_format,
+                       const fuchsia::media::AudioMediaTypeDetails& dst_format,
                        Resampler resampler) {
   // We have no mixer for these formats.
-  FXL_DCHECK(src_format.sample_format != AudioSampleFormat::ANY);
-  FXL_DCHECK(src_format.sample_format != AudioSampleFormat::NONE);
-  FXL_DCHECK(dst_format.sample_format != AudioSampleFormat::ANY);
-  FXL_DCHECK(dst_format.sample_format != AudioSampleFormat::NONE);
+  FXL_DCHECK(src_format.sample_format !=
+             fuchsia::media::AudioSampleFormat::ANY);
+  FXL_DCHECK(src_format.sample_format !=
+             fuchsia::media::AudioSampleFormat::NONE);
+  FXL_DCHECK(dst_format.sample_format !=
+             fuchsia::media::AudioSampleFormat::ANY);
+  FXL_DCHECK(dst_format.sample_format !=
+             fuchsia::media::AudioSampleFormat::NONE);
   // MTWN-93: Consider eliminating these enums; they never lead to happy endings
 
   // If user specified a particular Resampler, directly select it.
diff --git a/bin/media/audio_server/mixer/mixer.h b/bin/media/audio_server/mixer/mixer.h
index 71865a3..4af49ed 100644
--- a/bin/media/audio_server/mixer/mixer.h
+++ b/bin/media/audio_server/mixer/mixer.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_MIXER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_MIXER_H_
 
 #include <memory>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/audio_server/constants.h"
 #include "garnet/bin/media/audio_server/gain.h"
 
@@ -52,9 +54,10 @@
   // For optimum system performance across changing conditions, callers should
   // take care when directly specifying a resampler type, if they do so at all.
   // The default should be allowed whenever possible.
-  static MixerPtr Select(const AudioMediaTypeDetails& src_format,
-                         const AudioMediaTypeDetails& dst_format,
-                         Resampler resampler_type = Resampler::Default);
+  static MixerPtr Select(
+      const fuchsia::media::AudioMediaTypeDetails& src_format,
+      const fuchsia::media::AudioMediaTypeDetails& dst_format,
+      Resampler resampler_type = Resampler::Default);
 
   //
   // Mix
@@ -193,3 +196,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_MIXER_H_
diff --git a/bin/media/audio_server/mixer/mixer_utils.h b/bin/media/audio_server/mixer/mixer_utils.h
index 5d2abca..f40dc8e 100644
--- a/bin/media/audio_server/mixer/mixer_utils.h
+++ b/bin/media/audio_server/mixer/mixer_utils.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_MIXER_UTILS_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_MIXER_UTILS_H_
 
 #include <cmath>
 #include <limits>
@@ -170,3 +171,5 @@
 }  // namespace mixer
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_MIXER_UTILS_H_
diff --git a/bin/media/audio_server/mixer/no_op.h b/bin/media/audio_server/mixer/no_op.h
index eaa5abb..7cc736c 100644
--- a/bin/media/audio_server/mixer/no_op.h
+++ b/bin/media/audio_server/mixer/no_op.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_NO_OP_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_NO_OP_H_
 
 #include "garnet/bin/media/audio_server/mixer/mixer.h"
 
@@ -23,3 +24,5 @@
 }  // namespace mixer
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_NO_OP_H_
diff --git a/bin/media/audio_server/mixer/output_formatter.cc b/bin/media/audio_server/mixer/output_formatter.cc
index f7dba5f..75a4888 100644
--- a/bin/media/audio_server/mixer/output_formatter.cc
+++ b/bin/media/audio_server/mixer/output_formatter.cc
@@ -4,10 +4,11 @@
 
 #include "garnet/bin/media/audio_server/mixer/output_formatter.h"
 
-#include <fbl/algorithm.h>
 #include <limits>
 #include <type_traits>
 
+#include <fbl/algorithm.h>
+
 #include "garnet/bin/media/audio_server/constants.h"
 #include "lib/fidl/cpp/clone.h"
 #include "lib/fxl/logging.h"
@@ -96,7 +97,8 @@
 template <typename DType>
 class OutputFormatterImpl : public OutputFormatter {
  public:
-  explicit OutputFormatterImpl(const AudioMediaTypeDetailsPtr& format)
+  explicit OutputFormatterImpl(
+      const fuchsia::media::AudioMediaTypeDetailsPtr& format)
       : OutputFormatter(format, sizeof(DType)) {}
 
   void ProduceOutput(const int32_t* source, void* dest_void,
@@ -117,8 +119,9 @@
 };
 
 // Constructor/destructor for the common OutputFormatter base class.
-OutputFormatter::OutputFormatter(const AudioMediaTypeDetailsPtr& format,
-                                 uint32_t bytes_per_sample)
+OutputFormatter::OutputFormatter(
+    const fuchsia::media::AudioMediaTypeDetailsPtr& format,
+    uint32_t bytes_per_sample)
     : channels_(format->channels),
       bytes_per_sample_(bytes_per_sample),
       bytes_per_frame_(bytes_per_sample * format->channels) {
@@ -128,18 +131,18 @@
 // Selection routine which will instantiate a particular templatized version of
 // the output formatter.
 OutputFormatterPtr OutputFormatter::Select(
-    const AudioMediaTypeDetailsPtr& format) {
+    const fuchsia::media::AudioMediaTypeDetailsPtr& format) {
   FXL_DCHECK(format);
-  FXL_DCHECK(format->sample_format != AudioSampleFormat::ANY);
-  FXL_DCHECK(format->sample_format != AudioSampleFormat::NONE);
+  FXL_DCHECK(format->sample_format != fuchsia::media::AudioSampleFormat::ANY);
+  FXL_DCHECK(format->sample_format != fuchsia::media::AudioSampleFormat::NONE);
   // MTWN-93: Consider eliminating these enums if we don't foresee using them.
 
   switch (format->sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return OutputFormatterPtr(new OutputFormatterImpl<uint8_t>(format));
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return OutputFormatterPtr(new OutputFormatterImpl<int16_t>(format));
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return OutputFormatterPtr(new OutputFormatterImpl<float>(format));
     default:
       FXL_LOG(ERROR) << "Unsupported output format "
diff --git a/bin/media/audio_server/mixer/output_formatter.h b/bin/media/audio_server/mixer/output_formatter.h
index 12ab440..2661c3e 100644
--- a/bin/media/audio_server/mixer/output_formatter.h
+++ b/bin/media/audio_server/mixer/output_formatter.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_OUTPUT_FORMATTER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_OUTPUT_FORMATTER_H_
 
 #include <memory>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 
 namespace media {
 namespace audio {
@@ -17,7 +18,7 @@
 class OutputFormatter {
  public:
   static OutputFormatterPtr Select(
-      const AudioMediaTypeDetailsPtr& output_format);
+      const fuchsia::media::AudioMediaTypeDetailsPtr& output_format);
 
   virtual ~OutputFormatter() = default;
 
@@ -50,16 +51,18 @@
    */
   virtual void FillWithSilence(void* dest, uint32_t frames) const = 0;
 
-  const AudioMediaTypeDetailsPtr& format() const { return format_; }
+  const fuchsia::media::AudioMediaTypeDetailsPtr& format() const {
+    return format_;
+  }
   uint32_t channels() const { return channels_; }
   uint32_t bytes_per_sample() const { return bytes_per_sample_; }
   uint32_t bytes_per_frame() const { return bytes_per_frame_; }
 
  protected:
-  OutputFormatter(const AudioMediaTypeDetailsPtr& output_format,
+  OutputFormatter(const fuchsia::media::AudioMediaTypeDetailsPtr& output_format,
                   uint32_t bytes_per_sample);
 
-  AudioMediaTypeDetailsPtr format_;
+  fuchsia::media::AudioMediaTypeDetailsPtr format_;
   uint32_t channels_ = 0;
   uint32_t bytes_per_sample_ = 0;
   uint32_t bytes_per_frame_ = 0;
@@ -67,3 +70,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_OUTPUT_FORMATTER_H_
diff --git a/bin/media/audio_server/mixer/point_sampler.cc b/bin/media/audio_server/mixer/point_sampler.cc
index 4a77009..b5f6578 100644
--- a/bin/media/audio_server/mixer/point_sampler.cc
+++ b/bin/media/audio_server/mixer/point_sampler.cc
@@ -370,14 +370,16 @@
 // Templates used to expand all of the different combinations of the possible
 // PointSampler Mixer configurations.
 template <size_t DChCount, typename SType, size_t SChCount>
-static inline MixerPtr SelectPSM(const AudioMediaTypeDetails& src_format,
-                                 const AudioMediaTypeDetails& dst_format) {
+static inline MixerPtr SelectPSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   return MixerPtr(new PointSamplerImpl<DChCount, SType, SChCount>());
 }
 
 template <size_t DChCount, typename SType>
-static inline MixerPtr SelectPSM(const AudioMediaTypeDetails& src_format,
-                                 const AudioMediaTypeDetails& dst_format) {
+static inline MixerPtr SelectPSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   switch (src_format.channels) {
     case 1:
       return SelectPSM<DChCount, SType, 1>(src_format, dst_format);
@@ -389,35 +391,38 @@
 }
 
 template <size_t DChCount>
-static inline MixerPtr SelectPSM(const AudioMediaTypeDetails& src_format,
-                                 const AudioMediaTypeDetails& dst_format) {
+static inline MixerPtr SelectPSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   switch (src_format.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return SelectPSM<DChCount, uint8_t>(src_format, dst_format);
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return SelectPSM<DChCount, int16_t>(src_format, dst_format);
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return SelectPSM<DChCount, float>(src_format, dst_format);
     default:
       return nullptr;
   }
 }
 
-static inline MixerPtr SelectNxNPSM(const AudioMediaTypeDetails& src_format) {
+static inline MixerPtr SelectNxNPSM(
+    const fuchsia::media::AudioMediaTypeDetails& src_format) {
   switch (src_format.sample_format) {
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return MixerPtr(new NxNPointSamplerImpl<uint8_t>(src_format.channels));
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return MixerPtr(new NxNPointSamplerImpl<int16_t>(src_format.channels));
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return MixerPtr(new NxNPointSamplerImpl<float>(src_format.channels));
     default:
       return nullptr;
   }
 }
 
-MixerPtr PointSampler::Select(const AudioMediaTypeDetails& src_format,
-                              const AudioMediaTypeDetails& dst_format) {
+MixerPtr PointSampler::Select(
+    const fuchsia::media::AudioMediaTypeDetails& src_format,
+    const fuchsia::media::AudioMediaTypeDetails& dst_format) {
   if (src_format.channels == dst_format.channels && src_format.channels > 2) {
     return SelectNxNPSM(src_format);
   }
diff --git a/bin/media/audio_server/mixer/point_sampler.h b/bin/media/audio_server/mixer/point_sampler.h
index 8c285ab..6df6863 100644
--- a/bin/media/audio_server/mixer/point_sampler.h
+++ b/bin/media/audio_server/mixer/point_sampler.h
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_POINT_SAMPLER_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_POINT_SAMPLER_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/audio_server/mixer/mixer.h"
 
 namespace media {
@@ -13,8 +15,9 @@
 
 class PointSampler : public Mixer {
  public:
-  static MixerPtr Select(const AudioMediaTypeDetails& src_format,
-                         const AudioMediaTypeDetails& dst_format);
+  static MixerPtr Select(
+      const fuchsia::media::AudioMediaTypeDetails& src_format,
+      const fuchsia::media::AudioMediaTypeDetails& dst_format);
 
  protected:
   PointSampler(uint32_t pos_filter_width, uint32_t neg_filter_width)
@@ -24,3 +27,5 @@
 }  // namespace mixer
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_POINT_SAMPLER_H_
diff --git a/bin/media/audio_server/mixer/test/audio_analysis.h b/bin/media/audio_server/mixer/test/audio_analysis.h
index e9901b5..3968731 100644
--- a/bin/media/audio_server/mixer/test/audio_analysis.h
+++ b/bin/media/audio_server/mixer/test/audio_analysis.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_ANALYSIS_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_ANALYSIS_H_
 
 #include <zircon/types.h>
 #include <cmath>
@@ -74,3 +75,5 @@
 }  // namespace test
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_ANALYSIS_H_
diff --git a/bin/media/audio_server/mixer/test/audio_performance.cc b/bin/media/audio_server/mixer/test/audio_performance.cc
index 2bd731a..cef8f76 100644
--- a/bin/media/audio_server/mixer/test/audio_performance.cc
+++ b/bin/media/audio_server/mixer/test/audio_performance.cc
@@ -114,19 +114,19 @@
                                     Resampler sampler_type,
                                     uint32_t source_rate,
                                     Gain::AScale gain_scale, bool accumulate) {
-  AudioSampleFormat sample_format;
+  fuchsia::media::AudioSampleFormat sample_format;
   double amplitude;
   char format;
   if (std::is_same<SampleType, uint8_t>::value) {
-    sample_format = AudioSampleFormat::UNSIGNED_8;
+    sample_format = fuchsia::media::AudioSampleFormat::UNSIGNED_8;
     amplitude = std::numeric_limits<int8_t>::max();
     format = 'u';
   } else if (std::is_same<SampleType, int16_t>::value) {
-    sample_format = AudioSampleFormat::SIGNED_16;
+    sample_format = fuchsia::media::AudioSampleFormat::SIGNED_16;
     amplitude = std::numeric_limits<int16_t>::max();
     format = 'i';
   } else if (std::is_same<SampleType, float>::value) {
-    sample_format = AudioSampleFormat::FLOAT;
+    sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
     amplitude = 1.0;
     format = 'f';
   } else {
diff --git a/bin/media/audio_server/mixer/test/audio_performance.h b/bin/media/audio_server/mixer/test/audio_performance.h
index c5a0fe9..2fe0d34 100644
--- a/bin/media/audio_server/mixer/test/audio_performance.h
+++ b/bin/media/audio_server/mixer/test/audio_performance.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_PERFORMANCE_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_PERFORMANCE_H_
 
 #include "garnet/bin/media/audio_server/mixer/test/frequency_set.h"
 #include "garnet/bin/media/audio_server/mixer/test/mixer_tests_shared.h"
@@ -54,3 +55,5 @@
 }  // namespace test
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_PERFORMANCE_H_
diff --git a/bin/media/audio_server/mixer/test/audio_result.h b/bin/media/audio_server/mixer/test/audio_result.h
index 8c21288..37142d3 100644
--- a/bin/media/audio_server/mixer/test/audio_result.h
+++ b/bin/media/audio_server/mixer/test/audio_result.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_RESULT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_RESULT_H_
 
 #include <cmath>
 #include "garnet/bin/media/audio_server/constants.h"
@@ -389,3 +390,5 @@
     2018-03-21  Initial frequency response / sinad tests: 1kHz, 40Hz, 12kHz.
     2018-03-20  Initial source/output noise floor tests: 8- & 16-bit, 1kHz.
 */
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_AUDIO_RESULT_H_
diff --git a/bin/media/audio_server/mixer/test/frequency_set.h b/bin/media/audio_server/mixer/test/frequency_set.h
index 1b6893c..85f0314 100644
--- a/bin/media/audio_server/mixer/test/frequency_set.h
+++ b/bin/media/audio_server/mixer/test/frequency_set.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_FREQUENCY_SET_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_FREQUENCY_SET_H_
 
 #include <fbl/algorithm.h>
 #include <zircon/types.h>
@@ -92,3 +93,5 @@
 }  // namespace test
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_FREQUENCY_SET_H_
diff --git a/bin/media/audio_server/mixer/test/mixer_dynamic_range_tests.cc b/bin/media/audio_server/mixer/test/mixer_dynamic_range_tests.cc
index 5360f9b..598c4a6 100644
--- a/bin/media/audio_server/mixer/test/mixer_dynamic_range_tests.cc
+++ b/bin/media/audio_server/mixer/test/mixer_dynamic_range_tests.cc
@@ -19,8 +19,8 @@
 // Ideal accompanying noise is ideal noise floor, minus the reduction in gain.
 void MeasureSummaryDynamicRange(Gain::AScale scale, double* level_db,
                                 double* sinad_db) {
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::FLOAT, 1, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
 
   std::vector<float> source(kFreqTestBufSize);
   std::vector<int32_t> accum(kFreqTestBufSize);
@@ -115,8 +115,8 @@
 
 // Test our mix level and noise floor, when rechannelizing mono into stereo.
 TEST(DynamicRange, MonoToStereo) {
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::FLOAT, 1, 48000, 2, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               48000, 2, 48000, Resampler::SampleAndHold);
 
   std::vector<float> source(kFreqTestBufSize);
   std::vector<int32_t> accum(kFreqTestBufSize * 2);
@@ -158,8 +158,8 @@
 
 // Test our mix level and noise floor, when rechannelizing stereo into mono.
 TEST(DynamicRange, StereoToMono) {
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::FLOAT, 2, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 2,
+                               48000, 1, 48000, Resampler::SampleAndHold);
 
   std::vector<float> mono(kFreqTestBufSize);
   std::vector<float> source(kFreqTestBufSize * 2);
@@ -234,18 +234,18 @@
   double amplitude, expected_amplitude;
 
   if (std::is_same<T, uint8_t>::value) {
-    mixer = SelectMixer(AudioSampleFormat::UNSIGNED_8, 1, 48000, 1, 48000,
-                        Resampler::SampleAndHold);
+    mixer = SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1, 48000,
+                        1, 48000, Resampler::SampleAndHold);
     amplitude = std::numeric_limits<int8_t>::max();
     expected_amplitude = amplitude * (1 << (kAudioPipelineWidth - 8));
   } else if (std::is_same<T, int16_t>::value) {
-    mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                        Resampler::SampleAndHold);
+    mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000,
+                        1, 48000, Resampler::SampleAndHold);
     amplitude = std::numeric_limits<int16_t>::max();
     expected_amplitude = amplitude * (1 << (kAudioPipelineWidth - 16));
   } else {
-    mixer = SelectMixer(AudioSampleFormat::FLOAT, 1, 48000, 1, 48000,
-                        Resampler::SampleAndHold);
+    mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1, 48000, 1,
+                        48000, Resampler::SampleAndHold);
     amplitude = kFullScaleFloatInputAmplitude;
     expected_amplitude = kFullScaleAccumAmplitude;
   }
diff --git a/bin/media/audio_server/mixer/test/mixer_frequency_tests.cc b/bin/media/audio_server/mixer/test/mixer_frequency_tests.cc
index 3ccfa65..348ed39 100644
--- a/bin/media/audio_server/mixer/test/mixer_frequency_tests.cc
+++ b/bin/media/audio_server/mixer/test/mixer_frequency_tests.cc
@@ -32,18 +32,18 @@
   double amplitude, expected_amplitude;
 
   if (std::is_same<T, uint8_t>::value) {
-    mixer = SelectMixer(AudioSampleFormat::UNSIGNED_8, 1, 48000, 1, 48000,
-                        Resampler::SampleAndHold);
+    mixer = SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1, 48000,
+                        1, 48000, Resampler::SampleAndHold);
     amplitude = std::numeric_limits<int8_t>::max();
     expected_amplitude = amplitude * (1 << (kAudioPipelineWidth - 8));
   } else if (std::is_same<T, int16_t>::value) {
-    mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                        Resampler::SampleAndHold);
+    mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000,
+                        1, 48000, Resampler::SampleAndHold);
     amplitude = std::numeric_limits<int16_t>::max();
     expected_amplitude = amplitude * (1 << (kAudioPipelineWidth - 16));
   } else if (std::is_same<T, float>::value) {
-    mixer = SelectMixer(AudioSampleFormat::FLOAT, 1, 48000, 1, 48000,
-                        Resampler::SampleAndHold);
+    mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1, 48000, 1,
+                        48000, Resampler::SampleAndHold);
     amplitude = 1.0;
     expected_amplitude = amplitude * (1 << (kAudioPipelineWidth - 1));
   } else {
@@ -135,15 +135,18 @@
   // For float, 7FFF equates to less than 1.0, so adjust by (32768/32767).
 
   if (std::is_same<T, uint8_t>::value) {
-    output_formatter = SelectOutputFormatter(AudioSampleFormat::UNSIGNED_8, 1);
+    output_formatter =
+        SelectOutputFormatter(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1);
     expected_amplitude = std::numeric_limits<int8_t>::max();
     amplitude = expected_amplitude * (1 << (kAudioPipelineWidth - 8));
   } else if (std::is_same<T, int16_t>::value) {
-    output_formatter = SelectOutputFormatter(AudioSampleFormat::SIGNED_16, 1);
+    output_formatter =
+        SelectOutputFormatter(fuchsia::media::AudioSampleFormat::SIGNED_16, 1);
     expected_amplitude = std::numeric_limits<int16_t>::max();
     amplitude = expected_amplitude * (1 << (kAudioPipelineWidth - 16));
   } else if (std::is_same<T, float>::value) {
-    output_formatter = SelectOutputFormatter(AudioSampleFormat::FLOAT, 1);
+    output_formatter =
+        SelectOutputFormatter(fuchsia::media::AudioSampleFormat::FLOAT, 1);
     expected_amplitude = 1.0;
     amplitude = expected_amplitude * (1 << (kAudioPipelineWidth - 1));
   } else {
@@ -334,8 +337,8 @@
 // SRC). We articulate this with source buffer length equal to dest length.
 void TestUnitySampleRatio(Resampler sampler_type, double* freq_resp_results,
                           double* sinad_results) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 48000, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               48000, 1, 48000, sampler_type);
 
   MeasureFreqRespSinad(std::move(mixer), kFreqTestBufSize, freq_resp_results,
                        sinad_results);
@@ -345,8 +348,8 @@
 // by specifying a source buffer twice the length of the destination buffer.
 void TestDownSampleRatio1(Resampler sampler_type, double* freq_resp_results,
                           double* sinad_results) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 96000, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               96000, 1, 48000, sampler_type);
 
   MeasureFreqRespSinad(std::move(mixer),
                        round(kFreqTestBufSize * 96000.0 / 48000.0),
@@ -357,8 +360,8 @@
 // by specifying a source buffer longer than destination buffer by that ratio.
 void TestDownSampleRatio2(Resampler sampler_type, double* freq_resp_results,
                           double* sinad_results) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 88200, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               88200, 1, 48000, sampler_type);
 
   MeasureFreqRespSinad(std::move(mixer),
                        round(kFreqTestBufSize * 88200.0 / 48000.0),
@@ -369,8 +372,8 @@
 // by specifying a source buffer shorter than destination buffer by that ratio.
 void TestUpSampleRatio1(Resampler sampler_type, double* freq_resp_results,
                         double* sinad_results) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 44100, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               44100, 1, 48000, sampler_type);
 
   MeasureFreqRespSinad(std::move(mixer),
                        round(kFreqTestBufSize * 44100.0 / 48000.0),
@@ -381,8 +384,8 @@
 // by specifying a source buffer at half the length of the destination buffer.
 void TestUpSampleRatio2(Resampler sampler_type, double* freq_resp_results,
                         double* sinad_results) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 24000, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               24000, 1, 48000, sampler_type);
 
   MeasureFreqRespSinad(std::move(mixer),
                        round(kFreqTestBufSize * 24000.0 / 48000.0),
@@ -392,8 +395,8 @@
 // For the given resampler, target micro-sampling -- with a 47999:48000 ratio.
 void TestMicroSampleRatio(Resampler sampler_type, double* freq_resp_results,
                           double* sinad_results) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 47999, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               47999, 1, 48000, sampler_type);
 
   MeasureFreqRespSinad(std::move(mixer),
                        round(kFreqTestBufSize * 47999.0 / 48000.0),
diff --git a/bin/media/audio_server/mixer/test/mixer_gain_tests.cc b/bin/media/audio_server/mixer/test/mixer_gain_tests.cc
index fb63696..53354b9 100644
--- a/bin/media/audio_server/mixer/test/mixer_gain_tests.cc
+++ b/bin/media/audio_server/mixer/test/mixer_gain_tests.cc
@@ -185,8 +185,8 @@
   gain.SetRendererGain(20.0f);
   Gain::AScale stream_scale = gain.GetGainScale(0.0f);
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 44100, 1, 44100,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               44100, 1, 44100, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         stream_scale);
 
@@ -201,8 +201,8 @@
   gain.SetRendererGain(-20.0f);
   stream_scale = gain.GetGainScale(0.0f);
 
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 44100, 1, 44100,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 44100, 1,
+                      44100, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         stream_scale);
 
@@ -222,8 +222,8 @@
   // Before, even slightly below unity reduced all positive vals. Now we round.
   // For this reason, at this gain_scale, resulting audio should be unchanged.
   Gain::AScale gain_scale = AudioResult::kPrevScaleEpsilon + 1;
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         gain_scale);
 
@@ -233,8 +233,8 @@
 
   // This gain is the first (closest-to-unity) to change a full-scale signal.
   gain_scale = AudioResult::kPrevScaleEpsilon;
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         gain_scale);
 
@@ -245,8 +245,8 @@
   // This is lowest gain_scale that produces non-zero from full-scale.
   // Why "+1"? Differences in negative and positive range; see subsequent check.
   gain_scale = AudioResult::kPrevMinScaleNonZero + 1;
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         gain_scale);
 
@@ -256,8 +256,8 @@
   // This 'special' scale straddles boundaries: 32767 is reduced to _just_ less
   // than .5 (and rounds in) while -32768 becomes -.50000 (rounding out to -1).
   gain_scale = AudioResult::kPrevMinScaleNonZero;
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         gain_scale);
 
@@ -267,8 +267,8 @@
   // At this gain, even -32768 is reduced to -.49... thus rounds in to 0.
   // Therefore, nothing should change in the accumulator buffer.
   gain_scale = AudioResult::kPrevMinScaleNonZero - 1;
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, true, fbl::count_of(accum),
         gain_scale);
 
@@ -293,14 +293,14 @@
   NormalizeInt24ToPipelineBitwidth(expect2, fbl::count_of(expect2));
 
   // These values exceed the per-stream range of int16
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, true, fbl::count_of(accum));
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
   // these values even exceed uint16
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 2, 48000, 2, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2, 48000, 2,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, true, 1);
   EXPECT_TRUE(CompareBuffers(accum, expect2, fbl::count_of(accum)));
 }
@@ -314,8 +314,8 @@
                      std::numeric_limits<int32_t>::min() -
                          (source[1] << (kAudioPipelineWidth - 16)) - 1};
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, true, fbl::count_of(accum));
 
   // TODO(mpuryear): when MTWN-83 is fixed, expect max and min (not min & max).
@@ -332,16 +332,16 @@
   int32_t expect[] = {-32768, 32767};
 
   // We will test both SampleAndHold and LinearInterpolation interpolators.
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   // Use the gain guaranteed to silence all signals: Gain::MuteThreshold.
   DoMix(std::move(mixer), source, accum, true, fbl::count_of(accum),
         Gain::MuteThreshold());
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
   // Try with the other sampler.
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::LinearInterpolation);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::LinearInterpolation);
   DoMix(std::move(mixer), source, accum, true, fbl::count_of(accum),
         Gain::MuteThreshold());
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
@@ -349,15 +349,15 @@
   //
   // When accumulate = false, this is overridden: it behaves identically.
   //
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         Gain::MuteThreshold());
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
   // Ensure that both samplers behave identically in this regard.
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                      Resampler::LinearInterpolation);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1, 48000, 1,
+                      48000, Resampler::LinearInterpolation);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum),
         Gain::MuteThreshold());
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
diff --git a/bin/media/audio_server/mixer/test/mixer_resampler_tests.cc b/bin/media/audio_server/mixer/test/mixer_resampler_tests.cc
index 4318f65..6004994 100644
--- a/bin/media/audio_server/mixer/test/mixer_resampler_tests.cc
+++ b/bin/media/audio_server/mixer/test/mixer_resampler_tests.cc
@@ -40,8 +40,8 @@
 TEST(Resampling, Position_Basic_Point) {
   uint32_t frac_step_size = Mixer::FRAC_ONE;
   bool mix_result;
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 24000, 1, 24000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               24000, 1, 24000, Resampler::SampleAndHold);
 
   //
   // Check: source supply exceeds destination demand.
@@ -92,8 +92,8 @@
   uint32_t frac_step_size = Mixer::FRAC_ONE;
   bool mix_result;
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::LinearInterpolation);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::LinearInterpolation);
 
   //
   // Check: source supply equals destination demand.
@@ -164,8 +164,8 @@
 TEST(Resampling, Position_Fractional_Point) {
   uint32_t frac_step_size = Mixer::FRAC_ONE;
   bool mix_result;
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 44100, 1, 44100,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               44100, 1, 44100, Resampler::SampleAndHold);
 
   //
   // Check: source supply exceeds destination demand
@@ -215,8 +215,8 @@
 TEST(Resampling, Position_Fractional_Linear) {
   uint32_t frac_step_size = Mixer::FRAC_ONE;
   bool mix_result;
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::LinearInterpolation);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::LinearInterpolation);
 
   //
   // Check: Source supply exceeds destination demand
@@ -265,8 +265,8 @@
 }
 
 void TestPositionModulo(Resampler sampler_type) {
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, 32000, 1, 48000, sampler_type);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               32000, 1, 48000, sampler_type);
 
   int16_t source[] = {0, 1, 2};
   uint32_t frac_step_size = (Mixer::FRAC_ONE * 2) / 3;
@@ -314,9 +314,9 @@
 void TestInterpolation(uint32_t source_frames_per_second,
                        uint32_t dest_frames_per_second) {
   bool mix_result;
-  MixerPtr mixer =
-      SelectMixer(AudioSampleFormat::FLOAT, 1, source_frames_per_second, 1,
-                  dest_frames_per_second, Resampler::LinearInterpolation);
+  MixerPtr mixer = SelectMixer(
+      fuchsia::media::AudioSampleFormat::FLOAT, 1, source_frames_per_second, 1,
+      dest_frames_per_second, Resampler::LinearInterpolation);
 
   // These values should lead to [-1,1,0,0] in the accumulator.
   float source[] = {-1.0f / (1 << (kAudioPipelineWidth - 1)),
@@ -454,8 +454,8 @@
 
 // Verify PointSampler filter widths.
 TEST(Resampling, FilterWidth_Point) {
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::UNSIGNED_8, 1, 48000, 1,
-                               48000, Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
 
   EXPECT_EQ(mixer->pos_filter_width(), 0u);
   EXPECT_EQ(mixer->neg_filter_width(), Mixer::FRAC_ONE - 1);
@@ -468,8 +468,8 @@
 
 // Verify LinearSampler filter widths.
 TEST(Resampling, FilterWidth_Linear) {
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::FLOAT, 1, 44100, 1, 48000,
-                               Resampler::LinearInterpolation);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               44100, 1, 48000, Resampler::LinearInterpolation);
 
   EXPECT_EQ(mixer->pos_filter_width(), Mixer::FRAC_ONE - 1);
   EXPECT_EQ(mixer->neg_filter_width(), Mixer::FRAC_ONE - 1);
@@ -484,8 +484,8 @@
 // Earlier test (Position_Fractional_Linear) already validates
 // that LinearSampler correctly caches edge values, so just validate Reset.
 TEST(Resampling, Reset_Linear) {
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 1, 48000,
-                               Resampler::LinearInterpolation);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 1, 48000, Resampler::LinearInterpolation);
 
   // When src_offset ends on fractional val, it caches that sample for next mix
   // Source (offset 0.5 of 3) has 2.5. Destination (offset 2 of 4) wants 2.
diff --git a/bin/media/audio_server/mixer/test/mixer_tests_shared.cc b/bin/media/audio_server/mixer/test/mixer_tests_shared.cc
index 124691c..77ed5b0 100644
--- a/bin/media/audio_server/mixer/test/mixer_tests_shared.cc
+++ b/bin/media/audio_server/mixer/test/mixer_tests_shared.cc
@@ -20,16 +20,17 @@
 // our accumulation format (not the destination format), so we need not specify
 // a dst_format. Actual frame rate values are unimportant, but inter-rate RATIO
 // is VERY important: required SRC is the primary factor in Mix selection.
-MixerPtr SelectMixer(AudioSampleFormat src_format, uint32_t src_channels,
-                     uint32_t src_frame_rate, uint32_t dst_channels,
-                     uint32_t dst_frame_rate, Resampler resampler) {
-  AudioMediaTypeDetails src_details;
+MixerPtr SelectMixer(fuchsia::media::AudioSampleFormat src_format,
+                     uint32_t src_channels, uint32_t src_frame_rate,
+                     uint32_t dst_channels, uint32_t dst_frame_rate,
+                     Resampler resampler) {
+  fuchsia::media::AudioMediaTypeDetails src_details;
   src_details.sample_format = src_format;
   src_details.channels = src_channels;
   src_details.frames_per_second = src_frame_rate;
 
-  AudioMediaTypeDetails dst_details;
-  dst_details.sample_format = AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioMediaTypeDetails dst_details;
+  dst_details.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   dst_details.channels = dst_channels;
   dst_details.frames_per_second = dst_frame_rate;
 
@@ -43,9 +44,10 @@
 // destination format. They perform no SRC, gain scaling or rechannelization, so
 // frames_per_second is unimportant and num_channels is only needed so that they
 // can calculate the size of a (multi-channel) audio frame.
-OutputFormatterPtr SelectOutputFormatter(AudioSampleFormat dst_format,
-                                         uint32_t num_channels) {
-  AudioMediaTypeDetailsPtr dst_details = AudioMediaTypeDetails::New();
+OutputFormatterPtr SelectOutputFormatter(
+    fuchsia::media::AudioSampleFormat dst_format, uint32_t num_channels) {
+  fuchsia::media::AudioMediaTypeDetailsPtr dst_details =
+      fuchsia::media::AudioMediaTypeDetails::New();
   dst_details->sample_format = dst_format;
   dst_details->channels = num_channels;
   dst_details->frames_per_second = 48000;
diff --git a/bin/media/audio_server/mixer/test/mixer_tests_shared.h b/bin/media/audio_server/mixer/test/mixer_tests_shared.h
index 6af66e9..9633aa2 100644
--- a/bin/media/audio_server/mixer/test/mixer_tests_shared.h
+++ b/bin/media/audio_server/mixer/test/mixer_tests_shared.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_MIXER_TESTS_SHARED_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_MIXER_TESTS_SHARED_H_
 
 #include "garnet/bin/media/audio_server/gain.h"
 #include "garnet/bin/media/audio_server/mixer/mixer.h"
@@ -25,14 +26,14 @@
 }
 
 // Find a suitable mixer for the provided format, channels and frame rates.
-MixerPtr SelectMixer(AudioSampleFormat src_format, uint32_t src_channels,
-                     uint32_t src_frame_rate, uint32_t dst_channels,
-                     uint32_t dst_frame_rate,
+MixerPtr SelectMixer(fuchsia::media::AudioSampleFormat src_format,
+                     uint32_t src_channels, uint32_t src_frame_rate,
+                     uint32_t dst_channels, uint32_t dst_frame_rate,
                      Mixer::Resampler resampler = Mixer::Resampler::Default);
 
 // OutputFormatters convert frames from accumulation format to dest format.
-OutputFormatterPtr SelectOutputFormatter(AudioSampleFormat dst_format,
-                                         uint32_t num_channels);
+OutputFormatterPtr SelectOutputFormatter(
+    fuchsia::media::AudioSampleFormat dst_format, uint32_t num_channels);
 
 // When doing direct bit-for-bit comparisons in our tests, we must factor in the
 // left-shift biasing that is done while converting input data into the internal
@@ -58,3 +59,5 @@
 }  // namespace test
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_MIXER_TEST_MIXER_TESTS_SHARED_H_
diff --git a/bin/media/audio_server/mixer/test/mixer_transparency_tests.cc b/bin/media/audio_server/mixer/test/mixer_transparency_tests.cc
index 09f8fc1..04059e0 100644
--- a/bin/media/audio_server/mixer/test/mixer_transparency_tests.cc
+++ b/bin/media/audio_server/mixer/test/mixer_transparency_tests.cc
@@ -23,30 +23,32 @@
 //
 // Create PointSampler objects for incoming buffers of type uint8
 TEST(DataFormats, PointSampler_8) {
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::UNSIGNED_8, 2, 32000, 1,
-                                 16000, Resampler::SampleAndHold));
-  EXPECT_NE(nullptr,
-            SelectMixer(AudioSampleFormat::UNSIGNED_8, 4, 48000, 4, 48000));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8,
+                                 2, 32000, 1, 16000, Resampler::SampleAndHold));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8,
+                                 4, 48000, 4, 48000));
 }
 
 // Create PointSampler objects for incoming buffers of type int16
 TEST(DataFormats, PointSampler_16) {
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::SIGNED_16, 1, 24000, 1,
-                                 24000, Resampler::SampleAndHold));
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::SIGNED_16, 1, 44100, 2,
-                                 11025, Resampler::Default));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16,
+                                 1, 24000, 1, 24000, Resampler::SampleAndHold));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16,
+                                 1, 44100, 2, 11025, Resampler::Default));
 }
 
 // Create PointSampler objects for incoming buffers of type float
 TEST(DataFormats, PointSampler_Float) {
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::FLOAT, 2, 48000, 2, 16000));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 2,
+                                 48000, 2, 16000));
 }
 
 // Create PointSampler objects for other formats of incoming buffers
 // This is not expected to work, as these are not yet implemented
 TEST(DataFormats, PointSampler_Other) {
-  EXPECT_EQ(nullptr, SelectMixer(AudioSampleFormat::SIGNED_24_IN_32, 2, 8000, 1,
-                                 8000, Resampler::SampleAndHold));
+  EXPECT_EQ(nullptr,
+            SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32, 2,
+                        8000, 1, 8000, Resampler::SampleAndHold));
 }
 
 // If the source sample rate is NOT an integer-multiple of the destination rate
@@ -55,54 +57,62 @@
 //
 // Create LinearSampler objects for incoming buffers of type uint8
 TEST(DataFormats, LinearSampler_8) {
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::UNSIGNED_8, 1, 22050, 2,
-                                 44100, Resampler::LinearInterpolation));
   EXPECT_NE(nullptr,
-            SelectMixer(AudioSampleFormat::UNSIGNED_8, 2, 44100, 1, 48000));
+            SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1, 22050,
+                        2, 44100, Resampler::LinearInterpolation));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8,
+                                 2, 44100, 1, 48000));
 }
 
 // Create LinearSampler objects for incoming buffers of type int16
 TEST(DataFormats, LinearSampler_16) {
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::SIGNED_16, 2, 16000, 2,
-                                 48000, Resampler::LinearInterpolation));
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::SIGNED_16, 2, 44100, 1,
-                                 48000, Resampler::Default));
   EXPECT_NE(nullptr,
-            SelectMixer(AudioSampleFormat::SIGNED_16, 8, 48000, 8, 44100));
+            SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2, 16000,
+                        2, 48000, Resampler::LinearInterpolation));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16,
+                                 2, 44100, 1, 48000, Resampler::Default));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16,
+                                 8, 48000, 8, 44100));
 }
 
 // Create LinearSampler objects for incoming buffers of type float
 TEST(DataFormats, LinearSampler_Float) {
-  EXPECT_NE(nullptr, SelectMixer(AudioSampleFormat::FLOAT, 2, 48000, 2, 44100));
+  EXPECT_NE(nullptr, SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 2,
+                                 48000, 2, 44100));
 }
 
 // Create LinearSampler objects for other formats of incoming buffers
 // This is not expected to work, as these are not yet implemented
 TEST(DataFormats, LinearSampler_Other) {
   EXPECT_EQ(nullptr,
-            SelectMixer(AudioSampleFormat::SIGNED_24_IN_32, 2, 8000, 1, 11025));
+            SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32, 2,
+                        8000, 1, 11025));
 }
 
 // Create OutputFormatter objects for outgoing buffers of type uint8
 TEST(DataFormats, OutputFormatter_8) {
-  EXPECT_NE(nullptr, SelectOutputFormatter(AudioSampleFormat::UNSIGNED_8, 2));
+  EXPECT_NE(nullptr, SelectOutputFormatter(
+                         fuchsia::media::AudioSampleFormat::UNSIGNED_8, 2));
 }
 
 // Create OutputFormatter objects for outgoing buffers of type int16
 TEST(DataFormats, OutputFormatter_16) {
-  EXPECT_NE(nullptr, SelectOutputFormatter(AudioSampleFormat::SIGNED_16, 4));
+  EXPECT_NE(nullptr, SelectOutputFormatter(
+                         fuchsia::media::AudioSampleFormat::SIGNED_16, 4));
 }
 
 // Create OutputFormatter objects for outgoing buffers of type float
 TEST(DataFormats, OutputFormatter_Float) {
-  EXPECT_NE(nullptr, SelectOutputFormatter(AudioSampleFormat::FLOAT, 1));
+  EXPECT_NE(nullptr,
+            SelectOutputFormatter(fuchsia::media::AudioSampleFormat::FLOAT, 1));
 }
 
 // Create OutputFormatter objects for other output formats
 // This is not expected to work, as these are not yet implemented
 TEST(DataFormats, OutputFormatter_Other) {
   EXPECT_EQ(nullptr,
-            SelectOutputFormatter(AudioSampleFormat::SIGNED_24_IN_32, 3));
+            SelectOutputFormatter(
+                fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32, 3));
 }
 
 //
@@ -125,13 +135,13 @@
                       -0x010000, 0,        0x260000,  -0x130000};
   NormalizeInt24ToPipelineBitwidth(expect, fbl::count_of(expect));
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::UNSIGNED_8, 1, 48000, 1,
-                               48000, Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum));
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
-  mixer = SelectMixer(AudioSampleFormat::UNSIGNED_8, 8, 48000, 8, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 8, 48000,
+                      8, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum) / 8);
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 }
@@ -148,15 +158,15 @@
   NormalizeInt24ToPipelineBitwidth(expect, fbl::count_of(expect));
 
   // Try in 2-channel mode
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 2, 48000, 2, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2,
+                               48000, 2, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum) / 2);
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
   ::memset(accum, 0, sizeof(accum));
   // Now try in 4-channel mode
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 4, 48000, 4, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 4, 48000, 4,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum) / 4);
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 }
@@ -174,15 +184,15 @@
   NormalizeInt24ToPipelineBitwidth(expect, fbl::count_of(expect));
 
   // Try in 1-channel mode
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::FLOAT, 1, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 1,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum));
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
   ::memset(accum, 0, sizeof(accum));
   // Now try in 4-channel mode
-  mixer = SelectMixer(AudioSampleFormat::FLOAT, 4, 48000, 4, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::FLOAT, 4, 48000, 4,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum) / 4);
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 }
@@ -220,8 +230,8 @@
                       0x100,     0x100,     0x7FFF00,  0x7FFF00};
   NormalizeInt24ToPipelineBitwidth(expect, fbl::count_of(expect));
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 1, 48000, 2, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 1,
+                               48000, 2, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum) / 2);
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 }
@@ -232,8 +242,8 @@
                       1,     -1,     -13107, 13107, 3855, -3855};
   int32_t accum[6];
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 2, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2,
+                               48000, 1, 48000, Resampler::SampleAndHold);
 
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum));
   EXPECT_TRUE(CompareBufferToVal(accum, 0, fbl::count_of(accum)));
@@ -250,8 +260,8 @@
   int32_t expect[] = {0x177100, -0x6F00, 0x280, -0x15C980, 0x7FFF00, -0x800000};
   NormalizeInt24ToPipelineBitwidth(expect, fbl::count_of(expect));
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 2, 48000, 1, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2,
+                               48000, 1, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum));
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 }
@@ -265,15 +275,15 @@
   NormalizeInt24ToPipelineBitwidth(accum, fbl::count_of(accum));
   NormalizeInt24ToPipelineBitwidth(expect, fbl::count_of(expect));
 
-  MixerPtr mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 2, 48000, 2, 48000,
-                               Resampler::SampleAndHold);
+  MixerPtr mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2,
+                               48000, 2, 48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, true, fbl::count_of(accum) / 2);
   EXPECT_TRUE(CompareBuffers(accum, expect, fbl::count_of(accum)));
 
   int32_t expect2[] = {-0x10E100, 0x092900, 0x1A8500, -0x223D00};  // =source
   NormalizeInt24ToPipelineBitwidth(expect2, fbl::count_of(expect2));
-  mixer = SelectMixer(AudioSampleFormat::SIGNED_16, 2, 48000, 2, 48000,
-                      Resampler::SampleAndHold);
+  mixer = SelectMixer(fuchsia::media::AudioSampleFormat::SIGNED_16, 2, 48000, 2,
+                      48000, Resampler::SampleAndHold);
   DoMix(std::move(mixer), source, accum, false, fbl::count_of(accum) / 2);
   EXPECT_TRUE(CompareBuffers(accum, expect2, fbl::count_of(accum)));
 }
@@ -290,7 +300,7 @@
   uint8_t expect[] = {0x0, 0x0, 0x3F, 0x80, 0x80, 0xC1, 0xFF, 0xFF, 42};
 
   OutputFormatterPtr output_formatter =
-      SelectOutputFormatter(AudioSampleFormat::UNSIGNED_8, 1);
+      SelectOutputFormatter(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 1);
 
   output_formatter->ProduceOutput(accum, reinterpret_cast<void*>(dest),
                                   fbl::count_of(accum));
@@ -310,7 +320,7 @@
                       0x4080,  0x7FFF,  0x7FFF,  -42};
 
   OutputFormatterPtr output_formatter =
-      SelectOutputFormatter(AudioSampleFormat::SIGNED_16, 2);
+      SelectOutputFormatter(fuchsia::media::AudioSampleFormat::SIGNED_16, 2);
 
   output_formatter->ProduceOutput(accum, reinterpret_cast<void*>(dest),
                                   fbl::count_of(accum) / 2);
@@ -332,7 +342,7 @@
                     4.2f};
 
   audio::OutputFormatterPtr output_formatter =
-      SelectOutputFormatter(AudioSampleFormat::FLOAT, 1);
+      SelectOutputFormatter(fuchsia::media::AudioSampleFormat::FLOAT, 1);
 
   output_formatter->ProduceOutput(accum, reinterpret_cast<void*>(dest),
                                   fbl::count_of(accum));
@@ -345,7 +355,7 @@
   // should be overwritten, except for the last value: we only fill(6)
 
   OutputFormatterPtr output_formatter =
-      SelectOutputFormatter(AudioSampleFormat::UNSIGNED_8, 2);
+      SelectOutputFormatter(fuchsia::media::AudioSampleFormat::UNSIGNED_8, 2);
   ASSERT_NE(nullptr, output_formatter);
 
   output_formatter->FillWithSilence(reinterpret_cast<void*>(dest),
@@ -361,7 +371,7 @@
   // should be overwritten, except for the last value: we only fill(6)
 
   OutputFormatterPtr output_formatter =
-      SelectOutputFormatter(AudioSampleFormat::SIGNED_16, 3);
+      SelectOutputFormatter(fuchsia::media::AudioSampleFormat::SIGNED_16, 3);
   ASSERT_NE(output_formatter, nullptr);
 
   output_formatter->FillWithSilence(reinterpret_cast<void*>(dest),
@@ -377,7 +387,7 @@
   // should be overwritten, except for the last value: we only fill(6)
 
   audio::OutputFormatterPtr output_formatter =
-      SelectOutputFormatter(AudioSampleFormat::FLOAT, 2);
+      SelectOutputFormatter(fuchsia::media::AudioSampleFormat::FLOAT, 2);
   ASSERT_NE(output_formatter, nullptr);
 
   output_formatter->FillWithSilence(reinterpret_cast<void*>(dest),
diff --git a/bin/media/audio_server/pending_flush_token.cc b/bin/media/audio_server/pending_flush_token.cc
index 0775e05..be1e251 100644
--- a/bin/media/audio_server/pending_flush_token.cc
+++ b/bin/media/audio_server/pending_flush_token.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/audio_server/pending_flush_token.h"
+
 #include "garnet/bin/media/audio_server/audio_server_impl.h"
 #include "lib/fxl/logging.h"
 
diff --git a/bin/media/audio_server/pending_flush_token.h b/bin/media/audio_server/pending_flush_token.h
index 94b7930..346c34e 100644
--- a/bin/media/audio_server/pending_flush_token.h
+++ b/bin/media/audio_server/pending_flush_token.h
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_PENDING_FLUSH_TOKEN_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_PENDING_FLUSH_TOKEN_H_
 
 #include <fbl/intrusive_double_list.h>
 #include <fbl/ref_counted.h>
 #include <fbl/ref_ptr.h>
+#include <lib/fit/function.h>
 #include <stdint.h>
-#include <functional>
 
 namespace media {
 namespace audio {
@@ -20,9 +21,9 @@
       public fbl::Recyclable<PendingFlushToken>,
       public fbl::DoublyLinkedListable<fbl::unique_ptr<PendingFlushToken>> {
  public:
-  static fbl::RefPtr<PendingFlushToken> Create(
-      AudioServerImpl* const server, const std::function<void()>& callback) {
-    return fbl::AdoptRef(new PendingFlushToken(server, callback));
+  static fbl::RefPtr<PendingFlushToken> Create(AudioServerImpl* const server,
+                                               fit::closure callback) {
+    return fbl::AdoptRef(new PendingFlushToken(server, std::move(callback)));
   }
 
   void Cleanup() { callback_(); }
@@ -32,21 +33,22 @@
   friend class fbl::Recyclable<PendingFlushToken>;
   friend class fbl::unique_ptr<PendingFlushToken>;
 
-  // TODO(johngro): Change the std::funciton here to an
+  // TODO(johngro): Change the fit::closure here to an
   // AudioRenderer::FlushCallback once we have fully removed the V1 audio
   // renderer.
-  PendingFlushToken(AudioServerImpl* const server,
-                    const std::function<void()>& callback)
-      : server_(server), callback_(callback) {}
+  PendingFlushToken(AudioServerImpl* const server, fit::closure callback)
+      : server_(server), callback_(std::move(callback)) {}
 
   ~PendingFlushToken();
 
   void fbl_recycle();
 
   AudioServerImpl* const server_;
-  std::function<void()> callback_;
+  fit::closure callback_;
   bool was_recycled_ = false;
 };
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_PENDING_FLUSH_TOKEN_H_
diff --git a/bin/media/audio_server/standard_output_base.cc b/bin/media/audio_server/standard_output_base.cc
index d930f96..84d6943 100644
--- a/bin/media/audio_server/standard_output_base.cc
+++ b/bin/media/audio_server/standard_output_base.cc
@@ -4,9 +4,10 @@
 
 #include "garnet/bin/media/audio_server/standard_output_base.h"
 
+#include <limits>
+
 #include <fbl/auto_call.h>
 #include <fbl/auto_lock.h>
-#include <limits>
 
 #include "garnet/bin/media/audio_server/audio_link.h"
 #include "garnet/bin/media/audio_server/audio_renderer_format_info.h"
@@ -34,15 +35,15 @@
 
 StandardOutputBase::~StandardOutputBase() {}
 
-MediaResult StandardOutputBase::Init() {
-  MediaResult res = AudioOutput::Init();
-  if (res != MediaResult::OK) {
+fuchsia::media::MediaResult StandardOutputBase::Init() {
+  fuchsia::media::MediaResult res = AudioOutput::Init();
+  if (res != fuchsia::media::MediaResult::OK) {
     return res;
   }
 
   mix_timer_ = ::dispatcher::Timer::Create();
   if (mix_timer_ == nullptr) {
-    return MediaResult::INSUFFICIENT_RESOURCES;
+    return fuchsia::media::MediaResult::INSUFFICIENT_RESOURCES;
   }
 
   // clang-format off
@@ -59,10 +60,10 @@
       mix_timer_->Activate(mix_domain_, fbl::move(process_handler));
   if (zx_res != ZX_OK) {
     FXL_LOG(ERROR) << "Failed to activate mix_timer_ (res " << res << ")";
-    return MediaResult::INTERNAL_ERROR;
+    return fuchsia::media::MediaResult::INTERNAL_ERROR;
   }
 
-  return MediaResult::OK;
+  return fuchsia::media::MediaResult::OK;
 }
 
 void StandardOutputBase::Process() {
diff --git a/bin/media/audio_server/standard_output_base.h b/bin/media/audio_server/standard_output_base.h
index 4277376..8add262 100644
--- a/bin/media/audio_server/standard_output_base.h
+++ b/bin/media/audio_server/standard_output_base.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_STANDARD_OUTPUT_BASE_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_STANDARD_OUTPUT_BASE_H_
 
 #include <dispatcher-pool/dispatcher-timer.h>
+#include <fuchsia/media/cpp/fidl.h>
 
-#include <media/cpp/fidl.h>
 #include "garnet/bin/media/audio_server/audio_link.h"
 #include "garnet/bin/media/audio_server/audio_link_packet_source.h"
 #include "garnet/bin/media/audio_server/audio_output.h"
@@ -72,7 +73,7 @@
 
   explicit StandardOutputBase(AudioDeviceManager* manager);
 
-  MediaResult Init() override;
+  fuchsia::media::MediaResult Init() override;
 
   void Process() FXL_EXCLUSIVE_LOCKS_REQUIRED(mix_domain_->token());
 
@@ -156,3 +157,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_STANDARD_OUTPUT_BASE_H_
diff --git a/bin/media/audio_server/test/audio_renderer2_tests.cc b/bin/media/audio_server/test/audio_renderer2_tests.cc
index 1b14778..fccafe1 100644
--- a/bin/media/audio_server/test/audio_renderer2_tests.cc
+++ b/bin/media/audio_server/test/audio_renderer2_tests.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
 #include <lib/gtest/test_with_message_loop.h>
-#include <media/cpp/fidl.h>
+
 #include "lib/app/cpp/environment_services.h"
 #include "lib/fidl/cpp/synchronous_interface_ptr.h"
 #include "lib/fxl/logging.h"
@@ -38,15 +39,15 @@
   }
   void TearDown() override { EXPECT_FALSE(error_occurred_); }
 
-  AudioServerPtr audio_server_;
-  AudioRenderer2Ptr audio_renderer_;
+  fuchsia::media::AudioServerPtr audio_server_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer_;
   bool error_occurred_ = false;
 };
 
 // Basic validation of SetPcmFormat() for the asynchronous AudioRenderer2.
 TEST_F(AudioRenderer2Test, SetPcmFormat) {
-  AudioPcmFormat format;
-  format.sample_format = AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   format.channels = 2;
   format.frames_per_second = 48000;
   audio_renderer_->SetPcmFormat(std::move(format));
@@ -63,14 +64,14 @@
 
 // If renderer is not in operational mode, a second SetPcmFormat should succeed.
 TEST_F(AudioRenderer2Test, SetPcmFormat_Double) {
-  AudioPcmFormat format;
-  format.sample_format = AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   format.channels = 2;
   format.frames_per_second = 48000;
   audio_renderer_->SetPcmFormat(std::move(format));
 
-  AudioPcmFormat format2;
-  format2.sample_format = AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioPcmFormat format2;
+  format2.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   format2.channels = 2;
   format2.frames_per_second = 44100;
   audio_renderer_->SetPcmFormat(std::move(format2));
@@ -102,14 +103,14 @@
     ASSERT_TRUE(audio_renderer_);
   }
 
-  AudioServerSyncPtr audio_server_;
-  AudioRenderer2SyncPtr audio_renderer_;
+  fuchsia::media::AudioServerSyncPtr audio_server_;
+  fuchsia::media::AudioRenderer2SyncPtr audio_renderer_;
 };
 
 // Basic validation of SetPcmFormat() for the synchronous AudioRenderer2.
 TEST_F(AudioRenderer2SyncTest, SetPcmFormat) {
-  AudioPcmFormat format;
-  format.sample_format = AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   format.channels = 2;
   format.frames_per_second = 48000;
   EXPECT_TRUE(audio_renderer_->SetPcmFormat(std::move(format)));
@@ -121,14 +122,14 @@
 
 // If renderer is not in operational mode, a second SetPcmFormat should succeed.
 TEST_F(AudioRenderer2SyncTest, SetPcmFormat_Double) {
-  AudioPcmFormat format;
-  format.sample_format = AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   format.channels = 2;
   format.frames_per_second = 48000;
   EXPECT_TRUE(audio_renderer_->SetPcmFormat(std::move(format)));
 
-  AudioPcmFormat format2;
-  format2.sample_format = AudioSampleFormat::SIGNED_16;
+  fuchsia::media::AudioPcmFormat format2;
+  format2.sample_format = fuchsia::media::AudioSampleFormat::SIGNED_16;
   format2.channels = 1;
   format2.frames_per_second = 44100;
   EXPECT_TRUE(audio_renderer_->SetPcmFormat(std::move(format2)));
diff --git a/bin/media/audio_server/test/main.cc b/bin/media/audio_server/test/main.cc
index 8ee01de..11dbba2 100644
--- a/bin/media/audio_server/test/main.cc
+++ b/bin/media/audio_server/test/main.cc
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <cmath>
+
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
 #include <lib/gtest/test_with_message_loop.h>
-#include <media/cpp/fidl.h>
-#include <cmath>
+
 #include "lib/app/cpp/environment_services.h"
 #include "lib/fidl/cpp/synchronous_interface_ptr.h"
 #include "lib/fxl/logging.h"
@@ -33,11 +35,11 @@
 
   void TearDown() override { EXPECT_FALSE(error_occurred_); }
 
-  AudioServerPtr audio_server_;
-  AudioRendererPtr audio_renderer_;
-  MediaRendererPtr media_renderer_;
-  AudioRenderer2Ptr audio_renderer2_;
-  AudioCapturerPtr audio_capturer_;
+  fuchsia::media::AudioServerPtr audio_server_;
+  fuchsia::media::AudioRendererPtr audio_renderer_;
+  fuchsia::media::MediaRendererPtr media_renderer_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer2_;
+  fuchsia::media::AudioCapturerPtr audio_capturer_;
 
   bool error_occurred_ = false;
 };
@@ -151,11 +153,11 @@
     ASSERT_TRUE(audio_server_);
   }
 
-  AudioServerSyncPtr audio_server_;
-  AudioRendererSyncPtr audio_renderer_;
-  MediaRendererSyncPtr media_renderer_;
-  AudioRenderer2SyncPtr audio_renderer2_;
-  AudioCapturerSyncPtr audio_capturer_;
+  fuchsia::media::AudioServerSyncPtr audio_server_;
+  fuchsia::media::AudioRendererSyncPtr audio_renderer_;
+  fuchsia::media::MediaRendererSyncPtr media_renderer_;
+  fuchsia::media::AudioRenderer2SyncPtr audio_renderer2_;
+  fuchsia::media::AudioCapturerSyncPtr audio_capturer_;
 };
 
 // Test creation and survival of synchronous AudioRenderer and MediaRenderer.
diff --git a/bin/media/audio_server/throttle_output.h b/bin/media/audio_server/throttle_output.h
index fa90187..d676b5b 100644
--- a/bin/media/audio_server/throttle_output.h
+++ b/bin/media/audio_server/throttle_output.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_THROTTLE_OUTPUT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_THROTTLE_OUTPUT_H_
 
 #include "garnet/bin/media/audio_server/standard_output_base.h"
 
@@ -31,3 +32,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_THROTTLE_OUTPUT_H_
diff --git a/bin/media/audio_server/timeline_control_point.cc b/bin/media/audio_server/timeline_control_point.cc
index 8e2a6b2..4ada779 100644
--- a/bin/media/audio_server/timeline_control_point.cc
+++ b/bin/media/audio_server/timeline_control_point.cc
@@ -33,7 +33,7 @@
 
   status_publisher_.SetCallbackRunner(
       [this](GetStatusCallback callback, uint64_t version) {
-        MediaTimelineControlPointStatus status;
+        fuchsia::media::MediaTimelineControlPointStatus status;
         {
           std::lock_guard<std::mutex> locker(mutex_);
           status.timeline_transform =
@@ -58,7 +58,7 @@
 }
 
 void TimelineControlPoint::Bind(
-    fidl::InterfaceRequest<MediaTimelineControlPoint> request) {
+    fidl::InterfaceRequest<fuchsia::media::MediaTimelineControlPoint> request) {
   if (control_point_binding_.is_bound()) {
     control_point_binding_.Unbind();
   }
@@ -112,14 +112,14 @@
 
 void TimelineControlPoint::ClearEndOfStream() {
   std::lock_guard<std::mutex> locker(mutex_);
-  if (end_of_stream_pts_ != kUnspecifiedTime) {
-    end_of_stream_pts_ = kUnspecifiedTime;
+  if (end_of_stream_pts_ != fuchsia::media::kUnspecifiedTime) {
+    end_of_stream_pts_ = fuchsia::media::kUnspecifiedTime;
     end_of_stream_published_ = false;
   }
 }
 
 bool TimelineControlPoint::ReachedEndOfStream() {
-  return end_of_stream_pts_ != kUnspecifiedTime &&
+  return end_of_stream_pts_ != fuchsia::media::kUnspecifiedTime &&
          current_timeline_function_(Timeline::local_now()) >=
              end_of_stream_pts_;
 }
@@ -130,7 +130,8 @@
 }
 
 void TimelineControlPoint::GetTimelineConsumer(
-    fidl::InterfaceRequest<TimelineConsumer> timeline_consumer) {
+    fidl::InterfaceRequest<fuchsia::media::TimelineConsumer>
+        timeline_consumer) {
   if (consumer_binding_.is_bound()) {
     consumer_binding_.Unbind();
   }
@@ -154,7 +155,7 @@
 }
 
 void TimelineControlPoint::SetTimelineTransform(
-    TimelineTransform timeline_transform,
+    fuchsia::media::TimelineTransform timeline_transform,
     SetTimelineTransformCallback callback) {
   std::lock_guard<std::mutex> locker(mutex_);
 
@@ -164,24 +165,26 @@
 }
 
 void TimelineControlPoint::SetTimelineTransformNoReply(
-    TimelineTransform timeline_transform) {
+    fuchsia::media::TimelineTransform timeline_transform) {
   std::lock_guard<std::mutex> locker(mutex_);
 
   SetTimelineTransformLocked(std::move(timeline_transform));
 }
 
 void TimelineControlPoint::SetTimelineTransformLocked(
-    TimelineTransform timeline_transform) {
+    fuchsia::media::TimelineTransform timeline_transform) {
   RCHECK(timeline_transform.reference_delta != 0);
 
   bool was_progressing = ProgressingInternal();
 
-  int64_t reference_time = timeline_transform.reference_time == kUnspecifiedTime
-                               ? Timeline::local_now()
-                               : timeline_transform.reference_time;
-  int64_t subject_time = timeline_transform.subject_time == kUnspecifiedTime
-                             ? current_timeline_function_(reference_time)
-                             : timeline_transform.subject_time;
+  int64_t reference_time =
+      timeline_transform.reference_time == fuchsia::media::kUnspecifiedTime
+          ? Timeline::local_now()
+          : timeline_transform.reference_time;
+  int64_t subject_time =
+      timeline_transform.subject_time == fuchsia::media::kUnspecifiedTime
+          ? current_timeline_function_(reference_time)
+          : timeline_transform.subject_time;
 
   // Eject any previous pending change.
   ClearPendingTimelineFunction(false);
@@ -215,8 +218,8 @@
 }
 
 void TimelineControlPoint::ClearPendingTimelineFunction(bool completed) {
-  pending_timeline_function_ =
-      TimelineFunction(kUnspecifiedTime, kUnspecifiedTime, 0, 1);
+  pending_timeline_function_ = TimelineFunction(
+      fuchsia::media::kUnspecifiedTime, fuchsia::media::kUnspecifiedTime, 0, 1);
   if (set_timeline_transform_callback_) {
     SetTimelineTransformCallback callback = set_timeline_transform_callback_;
     set_timeline_transform_callback_ = nullptr;
diff --git a/bin/media/audio_server/timeline_control_point.h b/bin/media/audio_server/timeline_control_point.h
index f8834e1..c62bb34 100644
--- a/bin/media/audio_server/timeline_control_point.h
+++ b/bin/media/audio_server/timeline_control_point.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_TIMELINE_CONTROL_POINT_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_TIMELINE_CONTROL_POINT_H_
 
 #include <mutex>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/util/fidl_publisher.h"
 #include "lib/fidl/cpp/binding.h"
@@ -16,20 +18,21 @@
 namespace media {
 
 // MediaTimelineControlPoint implementation.
-class TimelineControlPoint : public MediaTimelineControlPoint,
-                             public TimelineConsumer {
+class TimelineControlPoint : public fuchsia::media::MediaTimelineControlPoint,
+                             public fuchsia::media::TimelineConsumer {
  public:
   using ProgramRangeSetCallback =
-      std::function<void(uint64_t, int64_t, int64_t)>;
-  using PrimeRequestedCallback = std::function<void(PrimeCallback)>;
-  using ProgressStartedCallback = std::function<void()>;
+      fit::function<void(uint64_t, int64_t, int64_t)>;
+  using PrimeRequestedCallback = fit::function<void(PrimeCallback)>;
+  using ProgressStartedCallback = fit::closure;
 
   TimelineControlPoint();
 
   ~TimelineControlPoint() override;
 
   // Binds to the control point. If a binding exists already, it is closed.
-  void Bind(fidl::InterfaceRequest<MediaTimelineControlPoint> request);
+  void Bind(fidl::InterfaceRequest<fuchsia::media::MediaTimelineControlPoint>
+                request);
 
   // Determines whether the control point is currently bound.
   bool is_bound() { return control_point_binding_.is_bound(); }
@@ -39,17 +42,17 @@
 
   // Sets a callback to be called when priming is requested.
   void SetProgramRangeSetCallback(ProgramRangeSetCallback callback) {
-    program_range_set_callback_ = callback;
+    program_range_set_callback_ = std::move(callback);
   }
 
   // Sets a callback to be called when priming is requested.
   void SetPrimeRequestedCallback(PrimeRequestedCallback callback) {
-    prime_requested_callback_ = callback;
+    prime_requested_callback_ = std::move(callback);
   }
 
   // Sets a callback to be called when priming is requested.
   void SetProgressStartedCallback(ProgressStartedCallback callback) {
-    progress_started_callback_ = callback;
+    progress_started_callback_ = std::move(callback);
   }
 
   // Determines if presentation time is progressing or a pending change will
@@ -76,7 +79,8 @@
                  GetStatusCallback callback) override;
 
   void GetTimelineConsumer(
-      fidl::InterfaceRequest<TimelineConsumer> timeline_consumer) override;
+      fidl::InterfaceRequest<fuchsia::media::TimelineConsumer>
+          timeline_consumer) override;
 
   void SetProgramRange(uint64_t program, int64_t min_pts,
                        int64_t max_pts) override;
@@ -84,11 +88,12 @@
   void Prime(PrimeCallback callback) override;
 
   // TimelineConsumer implementation.
-  void SetTimelineTransform(TimelineTransform timeline_transform,
-                            SetTimelineTransformCallback callback) override;
+  void SetTimelineTransform(
+      fuchsia::media::TimelineTransform timeline_transform,
+      SetTimelineTransformCallback callback) override;
 
   void SetTimelineTransformNoReply(
-      TimelineTransform timeline_transform) override;
+      fuchsia::media::TimelineTransform timeline_transform) override;
 
  private:
   // Applies pending_timeline_function_ if it's time to do so based on the
@@ -103,7 +108,8 @@
 
   // Determines if an unrealized timeline function is currently pending.
   bool TimelineFunctionPending() FXL_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
-    return pending_timeline_function_.reference_time() != kUnspecifiedTime;
+    return pending_timeline_function_.reference_time() !=
+           fuchsia::media::kUnspecifiedTime;
   }
 
   // Determines whether end-of-stream has been reached.
@@ -116,11 +122,13 @@
   // cause it to progress.
   bool ProgressingInternal() FXL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
-  void SetTimelineTransformLocked(TimelineTransform timeline_transform)
+  void SetTimelineTransformLocked(
+      fuchsia::media::TimelineTransform timeline_transform)
       FXL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
-  fidl::Binding<MediaTimelineControlPoint> control_point_binding_;
-  fidl::Binding<TimelineConsumer> consumer_binding_;
+  fidl::Binding<fuchsia::media::MediaTimelineControlPoint>
+      control_point_binding_;
+  fidl::Binding<fuchsia::media::TimelineConsumer> consumer_binding_;
   media::FidlPublisher<GetStatusCallback> status_publisher_;
   ProgramRangeSetCallback program_range_set_callback_;
   PrimeRequestedCallback prime_requested_callback_;
@@ -133,8 +141,11 @@
   SetTimelineTransformCallback set_timeline_transform_callback_
       FXL_GUARDED_BY(mutex_);
   uint32_t generation_ FXL_GUARDED_BY(mutex_) = 1;
-  int64_t end_of_stream_pts_ FXL_GUARDED_BY(mutex_) = kUnspecifiedTime;
+  int64_t end_of_stream_pts_ FXL_GUARDED_BY(mutex_) =
+      fuchsia::media::kUnspecifiedTime;
   bool end_of_stream_published_ FXL_GUARDED_BY(mutex_) = false;
 };
 
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_TIMELINE_CONTROL_POINT_H_
diff --git a/bin/media/audio_server/utils.cc b/bin/media/audio_server/utils.cc
index b37aaba..9bc60f6 100644
--- a/bin/media/audio_server/utils.cc
+++ b/bin/media/audio_server/utils.cc
@@ -15,7 +15,7 @@
 zx_status_t SelectBestFormat(
     const std::vector<audio_stream_format_range_t>& fmts,
     uint32_t* frames_per_second_inout, uint32_t* channels_inout,
-    AudioSampleFormat* sample_format_inout) {
+    fuchsia::media::AudioSampleFormat* sample_format_inout) {
   if ((frames_per_second_inout == nullptr) || (channels_inout == nullptr) ||
       (sample_format_inout == nullptr)) {
     return ZX_ERR_INVALID_ARGS;
diff --git a/bin/media/audio_server/utils.h b/bin/media/audio_server/utils.h
index c3389ab..311e335 100644
--- a/bin/media/audio_server/utils.h
+++ b/bin/media/audio_server/utils.h
@@ -2,15 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_AUDIO_SERVER_UTILS_H_
+#define GARNET_BIN_MEDIA_AUDIO_SERVER_UTILS_H_
 
-#include <stdint.h>
-#include <zircon/device/audio.h>
-#include <zircon/types.h>
 #include <atomic>
 #include <vector>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <stdint.h>
+#include <zircon/device/audio.h>
+#include <zircon/types.h>
+
 #include "garnet/bin/media/audio_server/constants.h"
 
 namespace media {
@@ -55,7 +57,9 @@
 zx_status_t SelectBestFormat(
     const std::vector<audio_stream_format_range_t>& fmts,
     uint32_t* frames_per_second_inout, uint32_t* channels_inout,
-    AudioSampleFormat* sample_format_inout);
+    fuchsia::media::AudioSampleFormat* sample_format_inout);
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_BIN_MEDIA_AUDIO_SERVER_UTILS_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/AHandler.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/AHandler.cc
new file mode 100644
index 0000000..d483866
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/AHandler.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "AHandler.h"
+
+namespace android {
+
+AHandler::AHandler() : id_(0) {}
+
+ALooper::handler_id AHandler::id() const { return id_; }
+
+wp<ALooper> AHandler::getLooper() const { return looper_; }
+
+wp<AHandler> AHandler::getHandler() const {
+  return const_cast<AHandler*>(this);
+}
+
+void AHandler::setID(ALooper::handler_id id, const wp<ALooper>& looper) {
+  id_ = id;
+  looper_ = looper;
+}
+
+void AHandler::deliverMessage(const sp<AMessage>& message) {
+  onMessageReceived(message);
+}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/ALooperRoster.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/ALooperRoster.cc
new file mode 100644
index 0000000..f40d127
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/ALooperRoster.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ALooperRoster.h"
+
+#include "AHandler.h"
+
+namespace android {
+
+ALooperRoster::ALooperRoster() : next_handler_id_(1) {}
+
+ALooper::handler_id ALooperRoster::registerHandler(
+    const sp<ALooper>& looper, const sp<AHandler>& handler) {
+  ALooper::handler_id handler_id;
+  {  // scope lock
+    std::unique_lock<std::mutex> lock(mutex_);
+    handler_id = next_handler_id_++;
+  }  // ~lock
+  handler->setID(handler_id, looper);
+  return handler_id;
+}
+
+void ALooperRoster::unregisterHandler(ALooper::handler_id handler_id) {}
+
+void ALooperRoster::unregisterStaleHandlers() {}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/AMessage.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/AMessage.cc
new file mode 100644
index 0000000..5ea43b5
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/AMessage.cc
@@ -0,0 +1,5 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// nothing needed here so far
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/AString.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/AString.cc
new file mode 100644
index 0000000..2a24408
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/AString.cc
@@ -0,0 +1,58 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "./include/media/stagefright/foundation/AString.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <stdarg.h>
+
+namespace android {
+
+AString::AString() {}
+
+AString::AString(const char* from_string) : std::string(from_string) {}
+
+AString::AString(const char* from_string, size_t size)
+    : std::string(from_string, size) {}
+
+AString::AString(const AString& from) : std::string(from) {}
+
+void AString::append(int int_to_append) {
+  char string_buf[16];
+  int result = snprintf(string_buf, sizeof(string_buf), "%d", int_to_append);
+  (void)result;
+  assert((result > 0) && ((size_t)result) < sizeof(string_buf));
+  append(string_buf);
+}
+
+void AString::append(const char* string_to_append) {
+  (*this) += string_to_append;
+}
+
+void AString::append(const char* string_to_append, size_t size) {
+  (*this) += std::string(string_to_append, size);
+}
+
+void AString::append(const AString& string_to_append) {
+  (*this) += string_to_append;
+}
+
+AString& AString::operator=(const AString& from) {
+  std::string::operator=(from);
+  return (*this);
+}
+
+AString AStringPrintf(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  char* buffer;
+  vasprintf(&buffer, format, ap);
+  va_end(ap);
+  AString result(buffer);
+  free(buffer);
+  buffer = nullptr;
+  return result;
+}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/BUILD.gn b/bin/media/codecs/sw/omx/common/omx_android_pal/BUILD.gn
new file mode 100644
index 0000000..4c03f84
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/BUILD.gn
@@ -0,0 +1,170 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("android_media_headers_config") {
+  visibility = [ ":*" ]
+  include_dirs = [
+    # android media-related include paths
+    "//third_party/android/platform/frameworks/av/media/libstagefright/omx/include",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/foundation/include",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/foundation/include/media/stagefright/foundation",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/include",
+    "//third_party/android/platform/frameworks/native/headers/media_plugin/media/openmax",
+  ]
+}
+
+source_set("android_media_headers_source_set") {
+  visibility = [ ":*" ]
+  public_configs = [ ":android_media_headers_config" ]
+}
+
+config("android_non_media_headers_config") {
+  visibility = [ ":*" ]
+  include_dirs = [
+    # other android headers - we try to minimize these
+    "//third_party/android/platform/system/core/libutils/include",
+  ]
+}
+
+source_set("android_non_media_headers_source_set") {
+  visibility = [ ":*" ]
+
+  # Not sure if this actaully limits included headers to only this list, but
+  # that's the intent.
+  public = [
+    "//third_party/android/platform/system/core/libutils/include/utils/RefBase.h",
+  ]
+  public_configs = [ ":android_non_media_headers_config" ]
+}
+
+config("pal_config") {
+  visibility = [ ":*" ]
+  include_dirs = [
+    # intentionally before android/platform/system/core/libutils/include
+    "include",
+    "include/media/stagefright/foundation",
+  ]
+  cflags = [
+    #"-v",
+    "-Werror",
+    #"-includeclang_typeof.h",
+  ]
+  libs = [
+    # for zx_clock_get()
+    "zircon",
+  ]
+  ldflags = [
+    #"-v",
+  ]
+}
+
+# This source set has a name starting with many 'a's which forces it to go
+# first in the list of omx_android_pal_config_source_set public_deps even
+# across a git-file-format.  We need it to go first because for now we're
+# overriding some android headers with omx_android_pal headers, and some of
+# those headers we're overriding are in the same directories as other headers
+# which we're not overriding, and include path ordering is determined by
+# public_deps list ordering below.  The downside: this is a bit arcane.  The
+# upside: We can build (at least one of - maybe more later) the Android OMX SW
+# codecs from un-modified AOSP sources this way despite them not being in
+# cross-platform libs, and this allows us to more easily track any new
+# potentially-needed changes from there.  If we continue to use these codecs we
+# may at some point consider different ways of building and/or sharing them.
+source_set("aaaaaaa_internal_pal_config_source_set") {
+  visibility = [ ":*" ]
+  public_configs = [ ":pal_config" ]
+}
+
+# We want to control include path ordering.  We choose to do that by having all
+# ordering-sensitive include paths pulled in via public_deps.  A public_deps
+# section can't pull in a config directly, so wrap public_config_config in
+# public_config_source_set.
+source_set("omx_android_pal_config_source_set") {
+  visibility = [ ":*" ]
+  public_deps = [
+    # This internal pal config source set must go first to enable us to override
+    # some AOSP headers while still pulling some other AOSP headers from some of
+    # the same AOSP directories.
+    ":aaaaaaa_internal_pal_config_source_set",
+    ":android_media_headers_source_set",
+    ":android_non_media_headers_source_set",
+    ":omx_so_entry_point_config_source_set",
+  ]
+}
+
+config("so_entry_point_config") {
+  visibility = [ ":*" ]
+  include_dirs = [
+    # so_entry_point.h has it's own include dir, since it's needed by clients
+    # that don't use the omx_android_pal and don't want to include any of the
+    # other PAL headers.  The reason so_entry_point is part of the
+    # omx_android_pal is because on android the OMX libs have a C++ ABI, while
+    # on fuchsia the OMX libs have a C-only ABI, and the omx_android_pal is
+    # what smooths that over (among other things).
+    "so_entry_point",
+
+    # For the structs used by so_entry_point's C-only ABI.
+    "//third_party/android/platform/frameworks/native/headers/media_plugin/media/openmax",
+  ]
+}
+
+source_set("omx_so_entry_point_config_source_set") {
+  visibility = [
+    "//garnet/bin/media/codecs/sw/omx/codec_runner_sw_omx/*",
+    ":omx_android_pal_config_source_set",
+  ]
+  public_configs = [ ":so_entry_point_config" ]
+}
+
+source_set("omx_android_pal") {
+  visibility = [
+    # This "omx_android_pal" is only for building OMX SW codecs from un-modified
+    # AOSP sources.
+    "//garnet/bin/media/codecs/sw/omx/*",
+  ]
+  sources = [
+    # The single linker-level entry point to each .so is declared and
+    # defined here:
+    "so_entry_point.cc",
+
+    # Adapters/shims/replacements to make un-modified AOSP OMX SW codecs build
+    # for Fuchsia (along with the header include path ordering established in
+    # omx_android_pal_config_source_set).
+    "AHandler.cc",
+    "ALooperRoster.cc",
+    "AMessage.cc",
+    "AString.cc",
+    "Condition.cc",
+    "Mutex.cc",
+    "String16.cc",
+    "String8.cc",
+    "Threads.cc",
+    "Timers.cc",
+    "not_Parcel.cc",
+    "port.cc",
+
+    # Enough stagefright code to satisfy OMX SW codec dependencies.
+    "//third_party/android/platform/frameworks/av/media/libstagefright/foundation/ALooper.cpp",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/foundation/AMessage.cpp",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/omx/SimpleSoftOMXComponent.cpp",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/omx/SoftOMXComponent.cpp",
+
+    # We build these two utils classes as-is.
+    "//third_party/android/platform/system/core/libutils/RefBase.cpp",
+    "//third_party/android/platform/system/core/libutils/StrongPointer.cpp",
+  ]
+
+  # All include paths are exposed (to OMX codec target only) via public_deps
+  # instead of as a mix of public_deps and public_configs, since a
+  # public_configs entry can always be converted to public_deps form via an
+  # intervening source_set, and because this way we avoid relying on include
+  # path ordering between public_configs and public_deps (instead only within
+  # public_deps).
+  public_deps = [
+    ":omx_android_pal_config_source_set",
+  ]
+  deps = [
+    "//garnet/public/lib/fxl",
+  ]
+}
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/Condition.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/Condition.cc
new file mode 100644
index 0000000..15464e5
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/Condition.cc
@@ -0,0 +1,33 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utils/Condition.h>
+
+#include <utils/Mutex.h>
+
+namespace android {
+
+status_t Condition::wait(Mutex& mutex) {
+  std::unique_lock<std::mutex> tmp(mutex.mutex_, std::adopt_lock);
+  condition_.wait(tmp);
+  tmp.release();
+  // This _might_ be a lie compared to android's semantics when there's a
+  // spurious wake, but relevant call sites don't appear to care.
+  return OK;
+}
+
+status_t Condition::waitRelative(Mutex& mutex, nsecs_t relative_timeout) {
+  std::unique_lock<std::mutex> tmp(mutex.mutex_, std::adopt_lock);
+  condition_.wait_for(tmp, std::chrono::nanoseconds(relative_timeout));
+  tmp.release();
+  // This _might_ be a lie compared to android's semantics when there's a
+  // spurious wake, but relevant call sites don't appear to care.
+  return OK;
+}
+
+void Condition::signal() { condition_.notify_one(); }
+
+void Condition::broadcast() { condition_.notify_all(); }
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/Mutex.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/Mutex.cc
new file mode 100644
index 0000000..57d8be9
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/Mutex.cc
@@ -0,0 +1,13 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "utils/Mutex.h"
+
+namespace android {
+
+Mutex::Mutex() {}
+
+Mutex::Mutex(const char* mutex_name) {}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/String16.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/String16.cc
new file mode 100644
index 0000000..38bc9c8
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/String16.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utils/String16.h>
+
+#include <wchar.h>
+#include <codecvt>
+#include <locale>
+#include <string>
+
+namespace {
+
+class DestructibleConverter : public std::codecvt<char16_t, char, mbstate_t> {
+ public:
+  DestructibleConverter(std::size_t refs = 0)
+      : std::codecvt<char16_t, char, mbstate_t>(refs) {}
+  ~DestructibleConverter() {}
+};
+
+}  // anonymous namespace
+
+namespace android {
+
+String16::String16(const char* from_string) {
+  std::wstring_convert<DestructibleConverter, char16_t> converter;
+  std::u16string::operator=(converter.from_bytes(from_string));
+}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/String8.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/String8.cc
new file mode 100644
index 0000000..3df3282
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/String8.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utils/String8.h>
+
+#include <wchar.h>
+#include <cassert>
+#include <codecvt>
+#include <locale>
+#include <string>
+
+namespace android {
+
+String8::String8() {}
+
+status_t String8::appendFormat(const char* format, ...) {
+  va_list ap;
+  va_start(ap, format);
+
+  status_t result = appendFormatV(format, ap);
+
+  va_end(ap);
+  return result;
+}
+
+status_t String8::appendFormatV(const char* format, va_list ap) {
+  va_list tmp_ap;
+  // ap is undefined after vsnprintf, so we need a copy here to avoid the secodn
+  // vsnprintf accessing undefined ap.
+  va_copy(tmp_ap, ap);
+  int n = vsnprintf(nullptr, 0, format, tmp_ap);
+  va_end(tmp_ap);
+  if (n) {
+    size_t old_length = size();
+
+    // With -fno-exceptions, I believe the behavior will be to abort() the
+    // process instead of throwing std::bad_alloc.
+    reserve(old_length + n);
+
+    // TODO: C++17 has a data() accessor that'll return non-const CharT*.
+    // Once all relevant toolchains are C++17, we could switch to using that
+    // here to avoid this allocation and copy, and just vsnprintf() directly
+    // into the latter part of the string instead.
+
+    // Similar to above, with -fno-exceptions, I believe the behavior will be to
+    // abort() the proces instead of throwing std::bad_alloc.
+    std::unique_ptr<char> temp = std::make_unique<char>(n + 1);
+
+    int actual = vsnprintf(temp.get(), n + 1, format, ap);
+    (void)actual;
+
+    // Concurrent modification of the string by mulitple threads isn't
+    // supported.
+    assert(n == actual);
+
+    // passing the "n" only to avoid forcing a re-count
+    append(temp.get(), n);
+  }
+  return NO_ERROR;
+}
+
+const char* String8::string() const { return c_str(); }
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/Threads.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/Threads.cc
new file mode 100644
index 0000000..f460bc5
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/Threads.cc
@@ -0,0 +1,196 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "utils/Thread.h"
+
+namespace android {
+
+Thread::Thread(bool can_call_java) {
+  // Fuchsia android::Thread shim doesn't support can_call_java == true.
+  assert(!can_call_java);
+}
+
+Thread::~Thread() {
+  bool is_join_needed = false;
+  {  // scope lock
+    std::unique_lock<std::mutex> lock(lock_);
+    if (!is_run_called_) {
+      // Nothing started, so nothing to shut down.
+      return;
+    }
+    // run() can't fail in any way other than calling abort() on the process.
+    assert(thread_);
+    // The caller _must_ have at least requested that the thread stop by this
+    // point, by calling requestExit() or requestExitAndWait(), or by returning
+    // false from threadLoop(), or by returning a failing status from
+    // readyToRun(), or by dropping the strong refcount to 0.
+    assert(is_exit_requested_);
+    // If the current thread is this thread, then don't try to wait for this
+    // thread to exit.
+    if (std::this_thread::get_id() == thread_->get_id()) {
+      thread_->detach();
+      // This usage pattern isn't necessarily consistent with safe un-load of a
+      // shared library.  For the Fuchsia scenarios involving this code (for
+      // now), we don't currently care about code un-load safety but we may in
+      // future (in those same scenarios), so we assert in this case for now,
+      // since we don't expect this case to get hit in the first place.
+      assert(false);
+      // ~thread_ here will be able to ~std::thread successfully because of the
+      // std::thread::detach() above.
+      return;
+    }
+    if (!is_joiner_selected_) {
+      is_join_needed = true;
+      is_joiner_selected_ = true;
+    } else {
+      // Some other thread was selected as the joiner.  That means that other
+      // thread started running requestExitAndWait().  If that other thread is
+      // _still_ running requestExitAndWait(), that's a bug in calling code,
+      // because that code shouldn't race Thread::requestExitAndWait() with
+      // Thread::~Thread().
+      //
+      // I suppose another way to end up here would be for two threads to both
+      // call ~Thread() on teh same Thread instance, which would of course also
+      // be a bug in calling code.  Note that this assert only potentially
+      // detects one sub-case of that bug - the sub-case where the thread isn't
+      // joined yet.
+      assert(is_joined_);
+    }
+  }
+
+  if (is_join_needed) {
+    joinCommon();
+  }
+
+  // Definitely true by this ponit.  Don't bother acquiring the lock for this
+  // check as once this becomes true it stays true, and we already had the lock
+  // enough above to make lock holding for this check unnecessary.
+  assert(is_joined_);
+
+  // Now it's safe to delete the std::thread, which will happen during ~thread_
+  // implicitly here.
+}
+
+status_t Thread::readyToRun() { return NO_ERROR; }
+
+status_t Thread::run(const char* thread_name, int32_t thread_priority,
+                     size_t stack_size) {
+  assert(thread_name);
+  std::unique_lock<std::mutex> lock(lock_);
+  if (is_run_called_) {
+    return INVALID_OPERATION;
+  }
+  is_run_called_ = true;
+  // hold strong reference on self until _threadLoop() gets going
+  hold_self_ = this;
+  thread_ = std::make_unique<std::thread>([this] { _threadLoop(); });
+  // Can't touch this.
+  return NO_ERROR;
+}
+
+void Thread::_threadLoop() {
+  sp<Thread> strong(hold_self_);
+  wp<Thread> weak(strong);
+  hold_self_.clear();
+  bool first = true;
+  do {
+    bool is_wanting_to_run;
+    if (first) {
+      first = false;
+      start_status_ = readyToRun();
+      is_wanting_to_run = (start_status_ == NO_ERROR);
+      if (is_wanting_to_run && !isExitRequested()) {
+        is_wanting_to_run = threadLoop();
+      }
+    } else {
+      is_wanting_to_run = threadLoop();
+    }
+
+    {  // scope lock
+      std::unique_lock<std::mutex> lock(lock_);
+      if (!is_wanting_to_run) {
+        is_exit_requested_ = true;
+      }
+      if (is_exit_requested_) {
+        // We don't try to self-report that this thread is done, because this
+        // thread isn't done running code of this method until the "ret"
+        // instruction at the end of this method (or equivalent) is over, so the
+        // only safe way to know that this thread is done running code of this
+        // method is to use OS-provided mechanism to determine that this thread
+        // is really done running, which std::thread.join() does do (or at
+        // least, certainly should do).
+        break;
+      }
+    }  // ~lock
+
+    strong.clear();
+    strong = weak.promote();
+    if (strong == 0) {
+      std::unique_lock<std::mutex> lock(lock_);
+      // It's nice to treat the strong refcount dropping to zero as an official
+      // exit request, before ~wp.
+      is_exit_requested_ = true;
+    }
+  } while (strong != 0);
+  // ~wp can be how this gets deleted, but for now we asser in the destructor
+  // if ~wp calls delete this, because that usage pattern isn't consistent with
+  // safe un-load of the code of a shared library.
+}
+
+void Thread::requestExit() {
+  std::unique_lock<std::mutex> lock(lock_);
+  is_exit_requested_ = true;
+}
+
+status_t Thread::requestExitAndWait() {
+  bool is_join_needed = false;
+  {  // scope lock
+    std::unique_lock<std::mutex> lock(lock_);
+    if (!is_run_called_) {
+      return NO_ERROR;
+    }
+    if (thread_->get_id() == std::this_thread::get_id()) {
+      return WOULD_BLOCK;
+    }
+    if (!is_exit_requested_) {
+      is_exit_requested_ = true;
+      is_join_needed = true;
+      is_joiner_selected_ = true;
+    } else {
+      if (!is_joiner_selected_) {
+        is_join_needed = true;
+        is_joiner_selected_ = true;
+      }
+    }
+    // Even if this thread isn't the one selected to do the join, this thread
+    // still has to wait for the join to be done.
+    if (!is_join_needed) {
+      while (!is_joined_) {
+        joined_condition_.wait(lock);
+      }
+      return NO_ERROR;
+    }
+  }  // ~lock
+
+  assert(is_join_needed);
+  joinCommon();
+
+  return start_status_;
+}
+
+bool Thread::isExitRequested() const {
+  std::unique_lock<std::mutex> lock(lock_);
+  return is_exit_requested_;
+}
+
+void Thread::joinCommon() {
+  thread_->join();
+  {  // scope lock
+    std::unique_lock<std::mutex> lock(lock_);
+    is_joined_ = true;
+  }  // ~lock
+  joined_condition_.notify_all();
+}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/Timers.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/Timers.cc
new file mode 100644
index 0000000..039c11e
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/Timers.cc
@@ -0,0 +1,17 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utils/Timers.h>
+
+#include <zircon/syscalls.h>
+
+#include <assert.h>
+
+nsecs_t systemTime(int clock) {
+  if (clock != SYSTEM_TIME_MONOTONIC) {
+    assert(clock == SYSTEM_TIME_MONOTONIC);
+    return 0;
+  }
+  return zx_clock_get(ZX_CLOCK_MONOTONIC);
+}
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/binder/Parcel.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/binder/Parcel.h
new file mode 100644
index 0000000..4eed618
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/binder/Parcel.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_BINDER_PARCEL_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_BINDER_PARCEL_H_
+
+#include <stdint.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Parcel {
+ public:
+  int32_t readInt32() const;
+  const char* readCString() const;
+  int64_t readInt64() const;
+  float readFloat() const;
+  double readDouble() const;
+  status_t writeInt32(int32_t value);
+  status_t writeCString(const char* string);
+  status_t writeInt64(int64_t value);
+  status_t writeFloat(float value);
+  status_t writeDouble(double value);
+
+ private:
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_BINDER_PARCEL_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/cutils/properties.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/cutils/properties.h
new file mode 100644
index 0000000..94a312d
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/cutils/properties.h
@@ -0,0 +1,16 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_CUTILS_PROPERTIES_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_CUTILS_PROPERTIES_H_
+
+#define PROPERTY_VALUE_MAX 92
+
+extern "C" {
+
+// This stub never finds anything.
+int property_get(const char* key, char* value, const char* default_value);
+}
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_CUTILS_PROPERTIES_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/define_typeof_and_unused.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/define_typeof_and_unused.h
new file mode 100644
index 0000000..7213090
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/define_typeof_and_unused.h
@@ -0,0 +1,17 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_DEFINE_TYPEOF_AND_UNUSED_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_DEFINE_TYPEOF_AND_UNUSED_H_
+
+// On android this is a GCC intrinsic, but on Fuchsia we use clang.
+#ifndef typeof
+#define typeof __typeof__
+#endif
+
+// On android this would come from bionic/libc/include/sys/cdefs.h, but on
+// Fuchsia we don't want to bring in Android's libc.
+#define __unused
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_DEFINE_TYPEOF_AND_UNUSED_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/log/log.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/log/log.h
new file mode 100644
index 0000000..c9ad2a9
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/log/log.h
@@ -0,0 +1,82 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_LOG_LOG_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_LOG_LOG_H_
+
+// Some android source relies on this being pulled in:
+#include <unistd.h>
+
+#include <stdint.h>
+
+// This is a convenient place to pull in these non-log-related definitions for
+// "typeof" and "__unused" without resorting to cflags
+// -includedefine_typeof_and_unused.h which editors don't tend to pick up on.
+#include "define_typeof_and_unused.h"
+
+#ifndef LOG_TAG
+#define LOG_TAG nullptr
+#endif
+
+enum {
+  ANDROID_LOG_UNKNOWN = 0,
+  ANDROID_LOG_DEFAULT,
+  ANDROID_LOG_VERBOSE,
+  ANDROID_LOG_DEBUG,
+  ANDROID_LOG_INFO,
+  ANDROID_LOG_WARN,
+  ANDROID_LOG_ERROR,
+  ANDROID_LOG_FATAL,
+  ANDROID_LOG_SILENT,
+};
+
+#define android_errorWriteLog(tag, subTag) \
+  __android_log_error_write(tag, subTag, -1, nullptr, 0)
+
+#define android_printLog(prio, tag, ...) \
+  __android_log_print(prio, tag, __VA_ARGS__)
+
+#define LOG_PRI(priority, tag, ...) android_printLog(priority, tag, __VA_ARGS__)
+#define ALOG(priority, tag, ...) LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
+
+#define __android_second(dummy, second, ...) second
+#define __android_rest(first, ...) , ##__VA_ARGS__
+#define android_printAssert(condition, tag, ...)                \
+  __android_log_assert(condition, tag,                          \
+                       __android_second(0, ##__VA_ARGS__, NULL) \
+                           __android_rest(__VA_ARGS__))
+
+#define LOG_ALWAYS_FATAL_IF(condition, ...)                              \
+  ((condition)                                                           \
+       ? ((void)android_printAssert(#condition, LOG_TAG, ##__VA_ARGS__)) \
+       : (void)0)
+
+#define LOG_ALWAYS_FATAL(...) \
+  (((void)android_printAssert(NULL, LOG_TAG, ##__VA_ARGS__)))
+
+#define ALOGV(...) ((void)ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__))
+#define ALOGE(...) ((void)ALOG(LOG_ERROR, LOG_TAG, __VA_ARGS__))
+#define ALOGW(...) ((void)ALOG(LOG_WARN, LOG_TAG, __VA_ARGS__))
+
+inline void fake_alogi(...) {}
+#define ALOGI(...) fake_alogi(__VA_ARGS__)
+
+#define LOG_FATAL_IF(cond, ...) LOG_ALWAYS_FATAL_IF(cond, ##__VA_ARGS__)
+
+#define LOG_FATAL(...) LOG_ALWAYS_FATAL(__VA_ARGS__)
+
+#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ##__VA_ARGS__)
+
+extern "C" {
+
+int __android_log_error_write(int tag, const char* subTag, int32_t uid,
+                              const char* data, uint32_t dataLength);
+
+int __android_log_print(int priority, const char* tag, const char* format, ...);
+
+void __android_log_assert(const char* condition, const char* tag,
+                          const char* format, ...);
+}
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_LOG_LOG_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/AHandler.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/AHandler.h
new file mode 100644
index 0000000..a19207a
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/AHandler.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_AHANDLER_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_AHANDLER_H_
+
+// Some android code relies on this being pulled in:
+#include <media/stagefright/foundation/ALooper.h>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct AHandler : public RefBase {
+ public:
+  AHandler();
+  ALooper::handler_id id() const;
+  wp<ALooper> getLooper() const;
+  wp<AHandler> getHandler() const;
+
+ protected:
+  virtual void onMessageReceived(const sp<AMessage>& msg) = 0;
+
+ private:
+  friend struct AMessage;
+  friend struct ALooperRoster;
+  ALooper::handler_id id_;
+  wp<ALooper> looper_;
+  void setID(ALooper::handler_id id, const wp<ALooper>& looper);
+  void deliverMessage(const sp<AMessage>& message);
+  DISALLOW_EVIL_CONSTRUCTORS(AHandler);
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_AHANDLER_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/ALooperRoster.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/ALooperRoster.h
new file mode 100644
index 0000000..11b3543
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/ALooperRoster.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_ALOOPERROSTER_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_ALOOPERROSTER_H_
+
+#include "ALooper.h"
+
+#include <mutex>
+
+namespace android {
+
+struct ALooperRoster {
+ public:
+  ALooperRoster();
+  ALooper::handler_id registerHandler(const sp<ALooper>& looper,
+                                      const sp<AHandler>& handler);
+  void unregisterHandler(ALooper::handler_id handler_id);
+  void unregisterStaleHandlers();
+
+ private:
+  std::mutex mutex_;
+  ALooper::handler_id next_handler_id_;
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_ALOOPERROSTER_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/AString.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/AString.h
new file mode 100644
index 0000000..704c649
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/media/stagefright/foundation/AString.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_ASTRING_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_ASTRING_H_
+
+#include <string>
+
+// Some android source relies on this being pulled in:
+#include <utils/Errors.h>
+
+namespace android {
+
+// For now this uses inheritance, but it should be possible to switch to
+// delegation should there be any good reason to do so.
+struct AString : public std::string {
+ public:
+  AString();
+  AString(const char* string);  // implicit single-arg constructor intentional
+  AString(const char* string, size_t size);
+  AString(
+      const AString& copy_from);  // implicit single-arg constructor intentional
+  void append(int number_to_append);
+  void append(const char* string_to_append);
+  void append(const char* string_to_append, size_t size);
+  void append(const AString& string_to_append);
+  AString& operator=(const AString& assign_from);
+
+ private:
+};
+
+AString AStringPrintf(const char* format, ...);
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_MEDIA_STAGEFRIGHT_FOUNDATION_ASTRING_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/system/graphics.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/system/graphics.h
new file mode 100644
index 0000000..b34b72b
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/system/graphics.h
@@ -0,0 +1,8 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_SYSTEM_GRAPHICS_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_SYSTEM_GRAPHICS_H_
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_SYSTEM_GRAPHICS_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/CallStack.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/CallStack.h
new file mode 100644
index 0000000..b212434
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/CallStack.h
@@ -0,0 +1,14 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_CALLSTACK_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_CALLSTACK_H_
+
+// Some android source relies on this getting pulled in here.
+//
+// We might be able to just include log/log.h here instead, but this way is
+// analogous to how android picks up its headers.
+#include <utils/Vector.h>
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_CALLSTACK_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Condition.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Condition.h
new file mode 100644
index 0000000..d8cb595
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Condition.h
@@ -0,0 +1,34 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_CONDITION_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_CONDITION_H_
+
+#include <mutex>
+
+#include <utils/Errors.h>
+
+typedef int64_t nsecs_t;
+
+namespace android {
+
+class Mutex;
+
+class Condition {
+ public:
+  // no timeout
+  status_t wait(Mutex& to_wait_on);
+  status_t waitRelative(Mutex& mutex, nsecs_t relative_timeout);
+  // signal one waiting thread if there are any
+  void signal();
+  // signal all waiting threads
+  void broadcast();
+
+ private:
+  std::condition_variable condition_;
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_CONDITION_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/List.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/List.h
new file mode 100644
index 0000000..028340b
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/List.h
@@ -0,0 +1,17 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_LIST_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_LIST_H_
+
+#include <list>
+
+namespace android {
+
+template <typename T>
+using List = std::list<T>;
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_LIST_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Log.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Log.h
new file mode 100644
index 0000000..768e6b8
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Log.h
@@ -0,0 +1,10 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_LOG_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_LOG_H_
+
+#include <log/log.h>
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_LOG_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Mutex.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Mutex.h
new file mode 100644
index 0000000..e05d20c
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Mutex.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_MUTEX_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_MUTEX_H_
+
+#include <mutex>
+
+namespace android {
+
+// TODO: Maybe map this to fbl::Mutex instead.
+
+// This is not meant to be complete - only meant to get OMX code to compile,
+// link, and run without editing the OMX files.
+
+class Mutex {
+ public:
+  class Autolock {
+   public:
+    explicit Autolock(Mutex& mutex_to_lock) {
+      mutex_ = &mutex_to_lock;
+      mutex_->mutex_.lock();
+    }
+    ~Autolock() { mutex_->mutex_.unlock(); }
+
+   private:
+    Mutex* mutex_;
+  };
+  Mutex();
+  explicit Mutex(const char* name);
+
+ private:
+  friend class Condition;
+  std::mutex mutex_;
+  Mutex(const Mutex&) = delete;
+  Mutex& operator=(const Mutex&) = delete;
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_MUTEX_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/String16.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/String16.h
new file mode 100644
index 0000000..0e5f785
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/String16.h
@@ -0,0 +1,21 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_STRING16_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_STRING16_H_
+
+#include <string>
+
+namespace android {
+
+class String16 : public std::u16string {
+ public:
+  explicit String16(const char* from_string);
+
+ private:
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_STRING16_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/String8.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/String8.h
new file mode 100644
index 0000000..696fc92
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/String8.h
@@ -0,0 +1,26 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_STRING8_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_STRING8_H_
+
+#include <utils/Errors.h>
+#include <string>
+
+namespace android {
+
+class String8 : public std::string {
+ public:
+  String8();
+  status_t appendFormat(const char* format, ...)
+      __attribute__((format(printf, 2, 3)));
+  status_t appendFormatV(const char* format, va_list args);
+  const char* string() const;
+
+ private:
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_STRING8_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Thread.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Thread.h
new file mode 100644
index 0000000..9d76335
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Thread.h
@@ -0,0 +1,85 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREAD_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREAD_H_
+
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <thread>
+
+extern "C" {
+
+enum {
+  ANDROID_PRIORITY_FOREGROUND = -2,
+};
+}
+
+namespace android {
+
+enum {
+  PRIORITY_DEFAULT = 0,
+};
+
+// DO NOT USE FOR NEW CODE - please use std::thread, or something else.  This
+// shim is only to allow some android code to compile and run on Fuchsia.
+
+// Intentionally do not support repeated calls to run(), even if the android
+// implementation may be trying to support that (unclear).  In this
+// implementation an instance of this class can only correspond to up to one
+// underlying thread lifetime, by design.
+//
+// The proper way to wait until the thread is really actually fully done running
+// is to call requestExitAndWait(), or requestExit() and ~Thread.  FWIW, until
+// that's done, it's not safe to do something that could change running code
+// such as un-load of a shared library that contains an instance of the code of
+// this class, since the tail end of _threadLoop() could still be running on the
+// thread.  We expect libc++.so to remain loaded, so we don't need to analyze
+// whether std::thread code itself is robust to code unloading.  We don't
+// currently expect to un-load any code (including the code of this class), but
+// this class should be reasonably ready for code unloading should it be added
+// at some point.
+
+// The virtual inheritance is probably not currently important for the current
+// Fuchsia usage, but is here to maximize compatibility for now.
+class Thread : virtual public RefBase {
+ public:
+  // This Thread shim on Fuchsia only supports can_call_java == false, else
+  // abort().
+  explicit Thread(bool can_call_java = true);
+  virtual ~Thread();
+  virtual status_t run(const char* thread_name,
+                       int32_t thread_priority = PRIORITY_DEFAULT,
+                       size_t stack_size = 0);
+  virtual void requestExit();
+  status_t requestExitAndWait();
+
+ protected:
+  // This would be private or completely removed in the Fuchsia implementation
+  // except for ALooper using it to stash the thread ID.
+  virtual status_t readyToRun();
+
+ private:
+  virtual bool threadLoop() = 0;
+  void _threadLoop();
+  bool isExitRequested() const;
+  void joinCommon();
+  mutable std::mutex lock_;
+  bool is_run_called_ = false;
+  std::unique_ptr<std::thread> thread_;
+  // The status of starting the thread, not anything more.
+  status_t start_status_ = NO_ERROR;
+  bool is_exit_requested_ = false;
+  bool is_joiner_selected_ = false;
+  bool is_joined_ = false;
+  std::condition_variable joined_condition_;
+  sp<Thread> hold_self_;
+};
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREAD_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Vector.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Vector.h
new file mode 100644
index 0000000..4b77a3d
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/Vector.h
@@ -0,0 +1,108 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_VECTOR_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_VECTOR_H_
+
+// Some android sources rely on this being pulled in:
+#include <log/log.h>
+
+#include <vector>
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#if __has_attribute(no_sanitize)
+#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
+#else
+#define UTILS_VECTOR_NO_CFI
+#endif
+
+namespace android {
+
+template <typename T>
+class Vector {
+ public:
+  inline size_t size() const { return vector_.size(); }
+  ssize_t add(const T& item);
+  inline const T& itemAt(size_t index) const;
+  const T& top() const;
+  inline void pop();
+  inline void push();
+  void push(const T& item);
+  T& editItemAt(size_t index);
+  inline ssize_t removeAt(size_t index);
+  inline void clear();
+  inline bool empty() const;
+  inline const T& operator[](size_t index) const;
+
+ private:
+  std::vector<T> vector_;
+};
+
+template <typename T>
+inline ssize_t Vector<T>::add(const T& item) {
+  ssize_t index_of_new_item = vector_.size();
+  vector_.push_back(item);
+  return index_of_new_item;
+}
+
+template <typename T>
+inline const T& Vector<T>::itemAt(size_t index) const {
+  return vector_.operator[](index);
+}
+
+template <typename T>
+inline const T& Vector<T>::top() const {
+  return vector_[vector_.size() - 1];
+}
+
+template <typename T>
+inline void Vector<T>::pop() {
+  if (vector_.empty()) {
+    return;
+  }
+  vector_.pop_back();
+}
+
+template <typename T>
+inline void Vector<T>::push() {
+  vector_.emplace_back();
+}
+
+template <typename T>
+inline void Vector<T>::push(const T& item) {
+  vector_.push_back(item);
+}
+
+template <typename T>
+inline T& Vector<T>::editItemAt(size_t index) {
+  return vector_[index];
+}
+
+template <typename T>
+inline ssize_t Vector<T>::removeAt(size_t index) {
+  vector_.erase(vector_.begin() + index);
+  return index;
+}
+
+template <typename T>
+inline void Vector<T>::clear() {
+  vector_.clear();
+}
+
+template <typename T>
+inline bool Vector<T>::empty() const {
+  return vector_.empty();
+}
+
+template <typename T>
+inline const T& Vector<T>::operator[](size_t index) const {
+  return vector_[index];
+}
+
+}  // namespace android
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_VECTOR_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/threads.h b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/threads.h
new file mode 100644
index 0000000..241a847
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/include/utils/threads.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREADS_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREADS_H_
+
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/Thread.h>
+#include <thread>
+
+using android_thread_id_t = void*;
+
+inline android_thread_id_t androidGetThreadId() {
+  return (android_thread_id_t)pthread_self();
+}
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_INCLUDE_UTILS_THREADS_H_
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/not_Parcel.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/not_Parcel.cc
new file mode 100644
index 0000000..956f651
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/not_Parcel.cc
@@ -0,0 +1,61 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "binder/Parcel.h"
+
+#include <assert.h>
+
+namespace android {
+
+int32_t Parcel::readInt32() const {
+  assert(false && "not implemented");
+  return 0;
+}
+
+const char* Parcel::readCString() const {
+  assert(false && "not implemented");
+  return nullptr;
+}
+
+int64_t Parcel::readInt64() const {
+  assert(false && "not implemented");
+  return 0;
+}
+
+float Parcel::readFloat() const {
+  assert(false && "not implemented");
+  return 0.0f;
+}
+
+double Parcel::readDouble() const {
+  assert(false && "not implemented");
+  return 0.0l;
+}
+
+status_t Parcel::writeInt32(int32_t value) {
+  assert(false && "not implemented");
+  return UNKNOWN_ERROR;
+}
+
+status_t Parcel::writeCString(const char* str) {
+  assert(false && "not implemented");
+  return UNKNOWN_ERROR;
+}
+
+status_t Parcel::writeInt64(int64_t value) {
+  assert(false && "not implemented");
+  return UNKNOWN_ERROR;
+}
+
+status_t Parcel::writeFloat(float value) {
+  assert(false && "not implemented");
+  return UNKNOWN_ERROR;
+}
+
+status_t Parcel::writeDouble(double value) {
+  assert(false && "not implemented");
+  return UNKNOWN_ERROR;
+}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/port.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/port.cc
new file mode 100644
index 0000000..9afbf70
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/port.cc
@@ -0,0 +1,87 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "log/log.h"
+
+extern "C" {
+
+// NOP replacement for Android's property_get:
+int property_get(const char* key, char* value, const char* default_value) {
+  return 0;
+}
+
+int __android_log_print(int priority, const char* tag, const char* format,
+                        ...) {
+  if (priority == ANDROID_LOG_VERBOSE) {
+    return 1;
+  }
+  // TODO: maybe concatenate before sending to printf in hopes that less output
+  // would be split (if it starts to become a problem).
+  const char* local_tag = tag;
+  if (!local_tag) {
+    local_tag = "<NO_TAG>";
+  }
+  printf("%d %s ", priority, local_tag);
+  va_list ap;
+  va_start(ap, format);
+  vprintf(format, ap);
+  va_end(ap);
+  printf("\n");
+  return 1;
+}
+
+void __android_log_assert(const char* condition, const char* tag,
+                          const char* format, ...) {
+  // TODO: maybe concatenate before sending to printf in hopes that less output
+  // would be split (if it starts to become a problem).
+  const char* local_tag = tag;
+  if (!local_tag) {
+    local_tag = "<NO_TAG>";
+  }
+  printf("__android_log_assert: condition: %s tag: %s ", condition, local_tag);
+  if (format) {
+    va_list ap;
+    va_start(ap, format);
+    vprintf(format, ap);
+    va_end(ap);
+  }
+  printf("\n");
+}
+
+void __assert2(const char* file, int line, const char* function,
+               const char* failed_expression) {
+  printf(
+      "omx_android_pal assert failed: file: %s line: %d function: %s "
+      "failed_expression: %s",
+      file, line, function, failed_expression);
+  assert(false && "see omx_android_pal assert failure output above");
+}
+
+int __android_log_error_write(int tag, const char* sub_tag, int32_t uid,
+                              const char* data, uint32_t data_length) {
+  // For now we drop the data part - if we see any of this happening we may need
+  // to plumb that part.
+  printf(
+      "__android_log_error_write: tag: %d sub_tag: %s uid: %d data_length: "
+      "%d\n",
+      tag, sub_tag, uid, data_length);
+  return 0;
+}
+
+}  // extern "C"
+
+namespace android {
+
+struct AString;
+
+void hexdump(const void* data, size_t size, size_t indent, AString* append_to) {
+  printf("hexdump() requested but not yet implemented\n");
+}
+
+}  // namespace android
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/so_entry_point.cc b/bin/media/codecs/sw/omx/common/omx_android_pal/so_entry_point.cc
new file mode 100644
index 0000000..aed4dc8
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/so_entry_point.cc
@@ -0,0 +1,140 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "so_entry_point.h"
+
+// SoftOMXComponent.h assumes that <log/log.h> is included first.
+#include <log/log.h>
+#include <media/stagefright/omx/SoftOMXComponent.h>
+
+#include <lib/fxl/functional/auto_call.h>
+
+// We intentionally don't have a "using namespace android;" because this is an
+// adapter layer and we want to make clear what's raw OMX and what's android
+// stuff that we're hiding from the caller of the entry point defined at the
+// bottom of this file.
+
+// In android sources, the per-OMX-codec common entry point signature isn't in
+// any header file, so we just declare it here.  We're using this symbol locally
+// within each per-codec binary we build for Fuchsia, and wrapping it with an
+// extern "C" shared_library entry point that doesn't return a C++ object.  Only
+// the latter is exported from the per-android-codec fuchsia shared lib.
+android::SoftOMXComponent *createSoftOMXComponent(
+    const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
+    OMX_COMPONENTTYPE **component);
+
+namespace {
+
+// A pointer to this function gets used as an OMX_COMPONENTTYPE.ComponentDeInit.
+OMX_ERRORTYPE ComponentDeInit(OMX_IN OMX_HANDLETYPE hComponent) {
+  android::SoftOMXComponent *me =
+      (android::SoftOMXComponent *)((OMX_COMPONENTTYPE *)hComponent)
+          ->pComponentPrivate;
+  me->prepareForDestruction();
+  me->decStrong(reinterpret_cast<void *>(ComponentDeInit));
+  // It's important that by this point any threads that were created by
+  // SimpleSoftOMXComponent or by the lower-layer codec core (if any) are
+  // totally done running any code of the present shared library, as the caller
+  // of this function will _un-load the code_ of this shared library.
+  return OMX_ErrorNone;
+}
+
+}  // namespace
+
+extern "C" {
+// This interface is not meant to be Fuchsia-wide for SW codecs.  For that, see
+// the Codec FIDL interface defined elsewhere.  This commonality of interface
+// here is just for building and loading various SW codecs from the android
+// sources.
+//
+// Sets *component to nullptr if create fails, or to non-nullptr if create
+// succeeds.
+void entrypoint_createSoftOMXComponent(const char *name,
+                                       const OMX_CALLBACKTYPE *callbacks,
+                                       OMX_PTR appData,
+                                       OMX_COMPONENTTYPE **component) {
+  // default to reporting failure uness we get far enough
+  *component = nullptr;
+  // We use the android::sp to ensure that every path from here forward will
+  // have at least one strong reference on the SoftOMXComponent (added here if
+  // not nullptr), including error paths.
+  android::sp<android::SoftOMXComponent> component_cpp =
+      createSoftOMXComponent(name, callbacks, appData, component);
+  if (!component_cpp) {
+    // TODO: can we log an error somewhere and/or return richer error info from
+    // a shared_library entry point in Fuchsia-standard ways?
+
+    // assert that we are reporting failure:
+    assert(!(*component));
+    return;
+  }
+  // Unfortunately the android code doesn't take advantage of
+  // RefBase::onLastStrongRef(), and doesn't seem worth making a wrapper that
+  // does just for the benefit of this source file.
+  //
+  // unless cancelled
+  auto pfd = fxl::MakeAutoCall(
+      [&component_cpp]() { component_cpp->prepareForDestruction(); });
+  if (OMX_ErrorNone != component_cpp->initCheck()) {
+    assert(!(*component));
+    return;
+  }
+  if (static_cast<OMX_PTR>(component_cpp.get()) !=
+      (*component)->pComponentPrivate) {
+    // The android code changed to no longer stash SoftOMXComponent* where this
+    // code expects.  At the moment there doesn't seem to be any good way to
+    // wrap more thoroughly that doesn't also risk getting broken by android
+    // changes, so if the stashing has changed in android code, fail the create.
+
+    // assert that we are reporting failure:
+    assert(!(*component));
+    // ~pfd
+    // ~component_cpp
+    return;
+  }
+
+  if ((*component)->ComponentDeInit) {
+    // The android code has changed to fill out this function pointer.  Without
+    // a more thourough wrapping, which would itself be subject to breakage by
+    // android changes that add more function pointers (to callbacks and/or to
+    // component), we have no great place to stash the value of ComponentDeInit.
+    // An alternative would be for the present entry point to fill out a wrapper
+    // of OMX_COMPONENTTYPE that just points to an OMX_COMPONENTTYPE, but the
+    // benefit/cost of that doesn't seem high enough, at least for now.  So if
+    // android code changed to start using this function pointer, fail the
+    // create.
+
+    // assert that we are reporting failure:
+    assert(!(*component));
+    // ~pfd
+    // ~component_cpp
+    return;
+  }
+
+  // This ComponentDeInit will call prepareForDestruction().
+  (*component)->ComponentDeInit = ComponentDeInit;
+  // Don't call prepareForDestruction() during ~pfd.
+  pfd.cancel();
+
+  // Prevent ~component_cpp from deleting the codec.  This ref will be removed
+  // by ComponentDeInit, so may as well use that as the void* on the ref.
+  component_cpp->incStrong(reinterpret_cast<void *>(ComponentDeInit));
+
+  // The non-use of setLibHandle() and libHandle() is intentional, since the
+  // loading and un-loading of the shared library is handled in a layer above
+  // that doesn't see SoftOMXComponent.
+
+  return;
+}
+
+// This function is only used when linked as a static lib, for debug-cycle
+// purposes only.
+void direct_createSoftOMXComponent(const char *name,
+                                   const OMX_CALLBACKTYPE *callbacks,
+                                   OMX_PTR appData,
+                                   OMX_COMPONENTTYPE **component) {
+  entrypoint_createSoftOMXComponent(name, callbacks, appData, component);
+}
+
+}  // extern "C"
diff --git a/bin/media/codecs/sw/omx/common/omx_android_pal/so_entry_point/so_entry_point.h b/bin/media/codecs/sw/omx/common/omx_android_pal/so_entry_point/so_entry_point.h
new file mode 100644
index 0000000..9f52275
--- /dev/null
+++ b/bin/media/codecs/sw/omx/common/omx_android_pal/so_entry_point/so_entry_point.h
@@ -0,0 +1,32 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_SO_ENTRY_POINT_SO_ENTRY_POINT_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_SO_ENTRY_POINT_SO_ENTRY_POINT_H_
+
+#include <OMX_Component.h>
+
+// For __EXPORT
+#include <zircon/compiler.h>
+
+__EXPORT
+extern "C" void entrypoint_createSoftOMXComponent(
+    const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData,
+    OMX_COMPONENTTYPE **component);
+
+typedef void (*createSoftOMXComponent_fn)(const char *name,
+                                          const OMX_CALLBACKTYPE *callbacks,
+                                          OMX_PTR appData,
+                                          OMX_COMPONENTTYPE **component);
+
+// This is only available if the .so's code is linked as a static lib instead.
+// This is not the normal way, but can be a faster debug cycle than using the
+// .so. If linking as an .so, this symbol won't be available, so trying to call
+// it will just fail to link.
+extern "C" void direct_createSoftOMXComponent(const char *name,
+                                              const OMX_CALLBACKTYPE *callbacks,
+                                              OMX_PTR appData,
+                                              OMX_COMPONENTTYPE **component);
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_COMMON_OMX_ANDROID_PAL_SO_ENTRY_POINT_SO_ENTRY_POINT_H_
diff --git a/bin/media/codecs/sw/omx/dec/aac/BUILD.gn b/bin/media/codecs/sw/omx/dec/aac/BUILD.gn
new file mode 100644
index 0000000..5eefdbd
--- /dev/null
+++ b/bin/media/codecs/sw/omx/dec/aac/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+loadable_module("libcodec_sw_omx_dec_aac") {
+  visibility = [
+    "//garnet/bin/media:codec_runner_sw_omx",
+    "//garnet/bin/media:codec_runner_sw_omx.manifest",
+  ]
+  sources = [
+    # The AOSP OMX SW AAC decoder code:
+    "//third_party/android/platform/frameworks/av/media/libstagefright/codecs/aacdec/DrcPresModeWrap.cpp",
+    "//third_party/android/platform/frameworks/av/media/libstagefright/codecs/aacdec/SoftAAC2.cpp",
+  ]
+  deps = [
+    "//garnet/bin/media/codecs/sw/omx/common/omx_android_pal:omx_android_pal",
+    "//garnet/bin/media/codecs/sw/omx/low_layer/aac:libFraunhoferAAC",
+  ]
+}
diff --git a/bin/media/codecs/sw/omx/low_layer/aac/BUILD.gn b/bin/media/codecs/sw/omx/low_layer/aac/BUILD.gn
new file mode 100644
index 0000000..2ba0745
--- /dev/null
+++ b/bin/media/codecs/sw/omx/low_layer/aac/BUILD.gn
@@ -0,0 +1,174 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("public_include_dirs") {
+  visibility = [ ":*" ]
+  include_dirs = [
+    # for aacdecoder_lib.h
+    "//third_party/android/platform/external/aac/libAACdec/include",
+
+    # stuff transitively included by aacdecoder_lib.h
+    "//third_party/android/platform/external/aac/libSYS/include",
+  ]
+}
+
+static_library("libFraunhoferAAC") {
+  visibility = [ "//garnet/bin/media/codecs/sw/omx/dec/aac/*" ]
+  public = [
+    "//third_party/android/platform/external/aac/libAACdec/include/aacdecoder_lib.h",
+  ]
+  public_configs = [ ":public_include_dirs" ]
+  sources = [
+    "//third_party/android/platform/external/aac/libAACdec/src/aac_ram.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aac_rom.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdec_drc.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdec_hcr.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdec_hcr_bit.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdec_hcrs.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdec_pns.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdec_tns.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdecoder.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/aacdecoder_lib.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/block.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/channel.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/channelinfo.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/conceal.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/ldfiltbank.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/pulsedata.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/rvlc.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/rvlcbit.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/rvlcconceal.cpp",
+    "//third_party/android/platform/external/aac/libAACdec/src/stereo.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/aacEnc_ram.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/aacEnc_rom.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/aacenc.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/aacenc_lib.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/aacenc_pns.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/aacenc_tns.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/adj_thr.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/band_nrg.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/bandwidth.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/bit_cnt.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/bitenc.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/block_switch.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/channel_map.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/chaosmeasure.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/dyn_bits.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/grp_data.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/intensity.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/line_pe.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/metadata_compressor.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/metadata_main.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/ms_stereo.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/noisedet.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/pnsparam.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/pre_echo_control.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/psy_configuration.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/psy_main.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/qc_main.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/quantize.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/sf_estim.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/spreading.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/tonality.cpp",
+    "//third_party/android/platform/external/aac/libAACenc/src/transform.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/FDK_bitbuffer.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/FDK_core.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/FDK_crc.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/FDK_hybrid.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/FDK_tools_rom.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/FDK_trigFcts.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/autocorr2nd.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/dct.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/fft.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/fft_rad2.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/fixpoint_math.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/mdct.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/qmf.cpp",
+    "//third_party/android/platform/external/aac/libFDK/src/scale.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPDec/src/tpdec_adif.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPDec/src/tpdec_adts.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPDec/src/tpdec_asc.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPDec/src/tpdec_drm.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPDec/src/tpdec_latm.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPDec/src/tpdec_lib.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPEnc/src/tpenc_adif.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPEnc/src/tpenc_adts.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPEnc/src/tpenc_asc.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPEnc/src/tpenc_latm.cpp",
+    "//third_party/android/platform/external/aac/libMpegTPEnc/src/tpenc_lib.cpp",
+    "//third_party/android/platform/external/aac/libPCMutils/src/limiter.cpp",
+    "//third_party/android/platform/external/aac/libPCMutils/src/pcmutils_lib.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/env_calc.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/env_dec.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/env_extr.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/huff_dec.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/lpp_tran.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/psbitdec.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/psdec.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/psdec_hybrid.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbr_crc.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbr_deb.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbr_dec.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbr_ram.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbr_rom.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbrdec_drc.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbrdec_freq_sca.cpp",
+    "//third_party/android/platform/external/aac/libSBRdec/src/sbrdecoder.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/bit_sbr.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/code_env.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/env_bit.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/env_est.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/fram_gen.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/invf_est.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/mh_det.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/nf_est.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/ps_bitenc.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/ps_encode.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/ps_main.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/resampler.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/sbr_encoder.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/sbr_misc.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/sbr_ram.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/sbr_rom.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/sbrenc_freq_sca.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/ton_corr.cpp",
+    "//third_party/android/platform/external/aac/libSBRenc/src/tran_det.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/cmdl_parser.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/conv_string.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/genericStds.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/linux/FDK_stackload_linux.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/linux/audio_linux.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/linux/coresup_linux.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/linux/genericStds_linux.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/linux/uart_linux.cpp",
+    "//third_party/android/platform/external/aac/libSYS/src/wav_file.cpp",
+  ]
+  include_dirs = [
+    "//third_party/android/platform/external/aac/libAACenc/include",
+    "//third_party/android/platform/external/aac/libSBRdec/include",
+    "//third_party/android/platform/external/aac/libSBRenc/include",
+    "//third_party/android/platform/external/aac/libAACdec/include",
+    "//third_party/android/platform/external/aac/libSYS/include",
+    "//third_party/android/platform/external/aac/libFDK/include",
+    "//third_party/android/platform/external/aac/libPCMutils/include",
+    "//third_party/android/platform/external/aac/libMpegTPEnc/include",
+    "//third_party/android/platform/external/aac/libMpegTPDec/include",
+  ]
+  cflags_cc = [
+    "-Werror",
+    "-Wno-constant-conversion",
+    "-Wno-sequence-point",
+    "-Wno-extra",
+    "-Wno-#warnings",
+    "-Wno-constant-logical-operand",
+    "-Wno-self-assign",
+    "-Wno-unused-function",
+    "-Wno-unused-const-variable",
+    "-Wno-unused-variable",
+    "-Wno-unused-label",
+  ]
+  deps = [
+    "//garnet/bin/media/codecs/sw/omx/low_layer/codec_android_pal:codec_android_pal",
+  ]
+}
diff --git a/bin/media/codecs/sw/omx/low_layer/codec_android_pal/BUILD.gn b/bin/media/codecs/sw/omx/low_layer/codec_android_pal/BUILD.gn
new file mode 100644
index 0000000..831610c
--- /dev/null
+++ b/bin/media/codecs/sw/omx/low_layer/codec_android_pal/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+config("public_include_dirs") {
+  visibility = [ ":*" ]
+  include_dirs = [ "include" ]
+}
+
+source_set("codec_android_pal") {
+  visibility = [ "//garnet/bin/media/codecs/sw/omx/low_layer/*" ]
+  public_configs = [ ":public_include_dirs" ]
+}
diff --git a/bin/media/codecs/sw/omx/low_layer/codec_android_pal/include/log/log.h b/bin/media/codecs/sw/omx/low_layer/codec_android_pal/include/log/log.h
new file mode 100644
index 0000000..5ee1204
--- /dev/null
+++ b/bin/media/codecs/sw/omx/low_layer/codec_android_pal/include/log/log.h
@@ -0,0 +1,14 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_CODECS_SW_OMX_LOW_LAYER_ANDROID_PAL_INCLUDE_LOG_LOG_H_
+#define GARNET_BIN_MEDIA_CODECS_SW_OMX_LOW_LAYER_ANDROID_PAL_INCLUDE_LOG_LOG_H_
+
+// Evaluate the arguments (out of paranoia), but do nothing with this, for now.
+#define ALOGE(x) \
+  do {           \
+    (void)(x);   \
+  } while (0)
+
+#endif  // GARNET_BIN_MEDIA_CODECS_SW_OMX_LOW_LAYER_ANDROID_PAL_INCLUDE_LOG_LOG_H_
diff --git a/bin/media/media_player/BUILD.gn b/bin/media/media_player/BUILD.gn
index bb07f57..9b07221 100644
--- a/bin/media/media_player/BUILD.gn
+++ b/bin/media/media_player/BUILD.gn
@@ -53,10 +53,10 @@
     "test/fake_wav_reader.cc",
     "test/fake_wav_reader.h",
     "test/main.cc",
-    "test/media_player_test_unattended.cc",
-    "test/media_player_test_unattended.h",
     "test/media_player_test_params.cc",
     "test/media_player_test_params.h",
+    "test/media_player_test_unattended.cc",
+    "test/media_player_test_unattended.h",
     "test/media_player_test_view.cc",
     "test/media_player_test_view.h",
   ]
diff --git a/bin/media/media_player/decode/BUILD.gn b/bin/media/media_player/decode/BUILD.gn
index cc1b726..cc39228 100644
--- a/bin/media/media_player/decode/BUILD.gn
+++ b/bin/media/media_player/decode/BUILD.gn
@@ -5,9 +5,13 @@
 source_set("decode") {
   sources = [
     "decoder.h",
+    "software_decoder.cc",
+    "software_decoder.h",
   ]
 
   deps = [
     "//garnet/bin/media/media_player/framework",
+    "//garnet/bin/media/media_player/metrics",
+    "//zircon/public/lib/async-loop-cpp",
   ]
 }
diff --git a/bin/media/media_player/decode/software_decoder.cc b/bin/media/media_player/decode/software_decoder.cc
new file mode 100644
index 0000000..aa6a5db
--- /dev/null
+++ b/bin/media/media_player/decode/software_decoder.cc
@@ -0,0 +1,314 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/media/media_player/decode/software_decoder.h"
+
+#include <lib/async/default.h>
+
+#include "garnet/bin/media/media_player/framework/formatting.h"
+#include "lib/fxl/logging.h"
+#include "lib/media/timeline/timeline.h"
+
+namespace media_player {
+
+SoftwareDecoder::SoftwareDecoder() : main_thread_async_(async_get_default()) {
+  output_state_ = OutputState::kIdle;
+  worker_loop_.StartThread();
+}
+
+SoftwareDecoder::~SoftwareDecoder() { FXL_DCHECK(is_main_thread()); }
+
+void SoftwareDecoder::GetConfiguration(size_t* input_count,
+                                       size_t* output_count) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(input_count);
+  FXL_DCHECK(output_count);
+  *input_count = 1;
+  *output_count = 1;
+}
+
+void SoftwareDecoder::FlushInput(bool hold_frame, size_t input_index,
+                                 fit::closure callback) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(input_index == 0);
+  FXL_DCHECK(callback);
+
+  flushing_ = true;
+  input_packet_.reset();
+  end_of_input_stream_ = false;
+
+  // If we were waiting for an input packet, we aren't anymore.
+  if (output_state_ == OutputState::kWaitingForInput) {
+    output_state_ = OutputState::kIdle;
+  }
+
+  callback();
+}
+
+void SoftwareDecoder::FlushOutput(size_t output_index, fit::closure callback) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(output_index == 0);
+  FXL_DCHECK(callback);
+
+  flushing_ = true;
+  end_of_output_stream_ = false;
+
+  if (output_state_ == OutputState::kWaitingForWorker ||
+      output_state_ == OutputState::kWorkerNotDone) {
+    // The worker is busy processing an input packet. Wait until it's done
+    // before calling the callback.
+    flush_callback_ = std::move(callback);
+    return;
+  }
+
+  PostTaskToWorkerThread([this, callback = std::move(callback)]() mutable {
+    Flush();
+    PostTaskToMainThread(std::move(callback));
+  });
+}
+
+std::shared_ptr<PayloadAllocator> SoftwareDecoder::allocator_for_input(
+    size_t input_index) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(input_index == 0);
+  return nullptr;
+}
+
+void SoftwareDecoder::PutInputPacket(PacketPtr packet, size_t input_index) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(packet);
+  FXL_DCHECK(input_index == 0);
+
+  FXL_DCHECK(!input_packet_);
+  FXL_DCHECK(!end_of_input_stream_);
+
+  if (flushing_) {
+    // We're flushing. Discard the packet.
+    return;
+  }
+
+  if (packet->end_of_stream()) {
+    end_of_input_stream_ = true;
+  }
+
+  if (output_state_ != OutputState::kWaitingForInput) {
+    // We weren't waiting for this packet, so save it for later.
+    input_packet_ = std::move(packet);
+    return;
+  }
+
+  output_state_ = OutputState::kWaitingForWorker;
+
+  PostTaskToWorkerThread([this, packet] { HandleInputPacketOnWorker(packet); });
+
+  if (!end_of_input_stream_) {
+    // Request another packet to keep |input_packet_| full.
+    stage()->RequestInputPacket();
+  }
+}
+
+bool SoftwareDecoder::can_accept_allocator_for_output(
+    size_t output_index) const {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(output_index == 0);
+  return true;
+}
+
+void SoftwareDecoder::SetAllocatorForOutput(
+    std::shared_ptr<PayloadAllocator> allocator, size_t output_index) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(output_index == 0);
+  allocator_ = allocator;
+}
+
+void SoftwareDecoder::RequestOutputPacket() {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(!end_of_output_stream_);
+
+  if (flushing_) {
+    FXL_DCHECK(!end_of_input_stream_);
+    FXL_DCHECK(!input_packet_);
+    flushing_ = false;
+    stage()->RequestInputPacket();
+  }
+
+  if (output_state_ == OutputState::kWaitingForWorker) {
+    return;
+  }
+
+  if (output_state_ == OutputState::kWorkerNotDone) {
+    // The worker is processing an input packet and has satisfied a previous
+    // request for an output packet. Indicate that we have a new unsatisfied
+    // request.
+    output_state_ = OutputState::kWaitingForWorker;
+    return;
+  }
+
+  if (!input_packet_) {
+    FXL_DCHECK(!end_of_input_stream_);
+
+    // We're expecting an input packet. Wait for it.
+    output_state_ = OutputState::kWaitingForInput;
+    return;
+  }
+
+  output_state_ = OutputState::kWaitingForWorker;
+
+  PostTaskToWorkerThread([this, packet = std::move(input_packet_)] {
+    HandleInputPacketOnWorker(std::move(packet));
+  });
+
+  if (!end_of_input_stream_) {
+    // Request the next packet, so it will be ready when we need it.
+    stage()->RequestInputPacket();
+  }
+}
+
+void SoftwareDecoder::HandleInputPacketOnWorker(PacketPtr input) {
+  FXL_DCHECK(is_worker_thread());
+  FXL_DCHECK(input);
+
+  bool done = false;
+  bool new_input = true;
+
+  int64_t start_time = media::Timeline::local_now();
+
+  // |TransformPacket| always returns true or produces an output packet or both,
+  // so we won't spin uselessly here.
+  while (!done) {
+    PacketPtr output;
+    done = TransformPacket(input, new_input, &output);
+    FXL_DCHECK(done || output);
+
+    new_input = false;
+
+    if (output) {
+      PostTaskToMainThread([this, output]() { HandleOutputPacket(output); });
+    }
+  }
+
+  {
+    std::lock_guard<std::mutex> locker(decode_duration_mutex_);
+    decode_duration_.AddSample(media::Timeline::local_now() - start_time);
+  }
+
+  PostTaskToMainThread([this]() { WorkerDoneWithInputPacket(); });
+}
+
+void SoftwareDecoder::HandleOutputPacket(PacketPtr packet) {
+  FXL_DCHECK(is_main_thread());
+  FXL_DCHECK(!end_of_output_stream_);
+
+  if (flushing_) {
+    // We're flushing. Discard the packet.
+    return;
+  }
+
+  switch (output_state_) {
+    case OutputState::kIdle:
+      FXL_DCHECK(false) << "HandleOutputPacket called when idle.";
+      break;
+    case OutputState::kWaitingForInput:
+      FXL_DCHECK(false) << "HandleOutputPacket called waiting for input.";
+      break;
+    case OutputState::kWaitingForWorker:
+      // We got the requested packet. Indicate we've satisfied the request for
+      // an output packet, but the worker hasn't finished with the input packet.
+      output_state_ = OutputState::kWorkerNotDone;
+      break;
+    case OutputState::kWorkerNotDone:
+      // We got an additional output packet.
+      break;
+  }
+
+  end_of_output_stream_ = packet->end_of_stream();
+  stage()->PutOutputPacket(std::move(packet));
+}
+
+void SoftwareDecoder::WorkerDoneWithInputPacket() {
+  FXL_DCHECK(is_main_thread());
+
+  switch (output_state_) {
+    case OutputState::kIdle:
+      FXL_DCHECK(false) << "WorkerDoneWithInputPacket called in idle state.";
+      break;
+
+    case OutputState::kWaitingForInput:
+      FXL_DCHECK(false)
+          << "WorkerDoneWithInputPacket called waiting for input.";
+      break;
+
+    case OutputState::kWaitingForWorker:
+      // We didn't get the requested output packet. Behave as though we just
+      // got a new request.
+      output_state_ = OutputState::kIdle;
+      if (!flushing_) {
+        RequestOutputPacket();
+      }
+
+      break;
+
+    case OutputState::kWorkerNotDone:
+      // We got the requested output packet. Done for now.
+      output_state_ = OutputState::kIdle;
+      break;
+  }
+
+  if (flush_callback_) {
+    PostTaskToWorkerThread(
+        [this, callback = std::move(flush_callback_)]() mutable {
+          Flush();
+          PostTaskToMainThread(std::move(callback));
+        });
+  }
+}
+
+void SoftwareDecoder::Dump(std::ostream& os) const {
+  FXL_DCHECK(is_main_thread());
+
+  os << label() << indent;
+  stage()->Dump(os);
+  os << newl << "output stream type:" << output_stream_type();
+  os << newl << "state:             ";
+
+  switch (output_state_) {
+    case OutputState::kIdle:
+      os << "idle";
+      break;
+    case OutputState::kWaitingForInput:
+      os << "waiting for input";
+      break;
+    case OutputState::kWaitingForWorker:
+      os << "waiting for worker";
+      break;
+    case OutputState::kWorkerNotDone:
+      os << "worker not done";
+      break;
+  }
+
+  os << newl << "flushing:          " << flushing_;
+  os << newl << "end of input:      " << end_of_input_stream_;
+  os << newl << "end of output:     " << end_of_output_stream_;
+
+  if (input_packet_) {
+    os << newl << "input packet:      " << input_packet_;
+  }
+
+  {
+    std::lock_guard<std::mutex> locker(decode_duration_mutex_);
+    if (decode_duration_.count() != 0) {
+      os << newl << "decodes:           " << decode_duration_.count();
+      os << newl << "decode durations:";
+      os << indent;
+      os << newl << "minimum        " << AsNs(decode_duration_.min());
+      os << newl << "average        " << AsNs(decode_duration_.average());
+      os << newl << "maximum        " << AsNs(decode_duration_.max());
+      os << outdent;
+    }
+  }
+
+  os << outdent;
+}
+
+}  // namespace media_player
diff --git a/bin/media/media_player/decode/software_decoder.h b/bin/media/media_player/decode/software_decoder.h
new file mode 100644
index 0000000..90b25fe
--- /dev/null
+++ b/bin/media/media_player/decode/software_decoder.h
@@ -0,0 +1,188 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_DECODE_SOFTWARE_DECODER_H_
+#define GARNET_BIN_MEDIA_MEDIA_PLAYER_DECODE_SOFTWARE_DECODER_H_
+
+#include <mutex>
+
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/async/cpp/task.h>
+#include <lib/async/default.h>
+#include <lib/async/dispatcher.h>
+
+#include "garnet/bin/media/media_player/decode/decoder.h"
+#include "garnet/bin/media/media_player/metrics/value_tracker.h"
+#include "lib/fxl/synchronization/thread_annotations.h"
+
+namespace media_player {
+
+// Abstract base class for software decoders.
+//
+// This base class implements a simple model for packet transformation on a
+// worker thread. Most member variables are accessed on the graph's main thread
+// exclusively. The worker and main thread communicate via posted tasks.
+//
+// The worker's sole responsibility is to process a single input packet when
+// |HandleInputPacketOnWorker| is called. The worker posts a call to
+// |HandleOutputPacket| to the main thread for each output packet it generates.
+// When the input packet is completely processed, the worker posts a call to
+// |WorkerDoneWithInputPacket| to the main thread. Any number of calls to
+// |HandleOutputPacket| may result from a single |HandleInputPacketOnWorker|
+// call.
+//
+// The main thread logic, under normal operation, maintains an input packet in
+// |input_packet_| so it's ready for decoding. When an output packet is
+// requested, the main thread logic posts a call to |HandleInputPacketOnWorker|
+// passing the input packet. A request for a new input packet is issued at that
+// time.
+//
+// Downstream nodes (the renderer, probably) is responsible for requesting
+// packets early enough to make sure it doesn't starve.
+//
+// The main thread logic uses packets delivered via |HandleOutputPacket| to
+// satisfy the output packet request. Any additional output packets produced
+// are queued by the stage. If |WorkerDoneWithInputPacket| is called without
+// any output packet being delivered, the cycle begins again.
+//
+// Exceptions to this behavior are many:
+// 1) Initially and after a flush, |input_packet_| is not proactively filled.
+//    The initial request for an output packet causes the main thread logic to
+//    request an input packet. |PutInputPacket| is called when it arrives.
+// 2) A request for an output packet may arrive when |input_packet_| is empty.
+//    In this case, the main thread logic yields until an input packet, arrives
+//    via |PutInputPacket|.
+// 3) Input packets from upstream and output packets from the worker thread are
+//    discarded when the node is flushing.
+// 4) The main thread logic desists from requesting input packets after an
+//    end-of-stream input packet arrives (until the input is flushed). When an
+//    end-of-stream input packet is processed by the worker, it must produce
+//    an end-of-stream output packet immediately before posting
+//    |WorkerDoneWithInputPacket|.
+//
+class SoftwareDecoder : public Decoder {
+ public:
+  SoftwareDecoder();
+
+  ~SoftwareDecoder() override;
+
+  // AsyncNode implementation.
+  void Dump(std::ostream& os) const override;
+
+  void GetConfiguration(size_t* input_count, size_t* output_count) override;
+
+  void FlushInput(bool hold_frame, size_t input_index,
+                  fit::closure callback) override;
+
+  void FlushOutput(size_t output_index, fit::closure callback) override;
+
+  std::shared_ptr<PayloadAllocator> allocator_for_input(
+      size_t input_index) override;
+
+  void PutInputPacket(PacketPtr packet, size_t input_index) override;
+
+  bool can_accept_allocator_for_output(size_t output_index) const override;
+
+  void SetAllocatorForOutput(std::shared_ptr<PayloadAllocator> allocator,
+                             size_t output_index) override;
+
+  void RequestOutputPacket() override;
+
+ protected:
+  void PostTaskToMainThread(fit::closure task) const {
+    async::PostTask(main_thread_async_, std::move(task));
+  }
+
+  void PostTaskToWorkerThread(fit::closure task) const {
+    async::PostTask(worker_loop_.async(), std::move(task));
+  }
+
+  bool is_main_thread() const {
+    return async_get_default() == main_thread_async_;
+  }
+
+  bool is_worker_thread() const {
+    return async_get_default() == worker_loop_.async();
+  }
+
+  const std::shared_ptr<PayloadAllocator>& allocator() const {
+    return allocator_;
+  }
+
+  // Notifies that a flush has occurred on the worker thread.
+  virtual void Flush() {}
+
+  // Processes a packet on the worker thread. Returns true to indicate we're
+  // done processing the input packet. Returns false to indicate the input
+  // packet should be processed again. |new_input| indicates whether the input
+  // packet is new (true) or is being processed again (false). An output
+  // packet may or may not be generated for any given invocation of this
+  // method. |*output| is always set by this method, possibly to null.
+  //
+  // This method must always 'progress' decoding in one way or another. That is,
+  // either the result must be true or an output packet must be generated or
+  // both.
+  virtual bool TransformPacket(const PacketPtr& input, bool new_input,
+                               PacketPtr* output) = 0;
+
+ private:
+  // |OutputState| indicates where we are with respect to satisifying a request
+  // for an output packet:
+  //     |kIdle|: no output packet has been requested, and we're not currently
+  //         processing an input packet on the worker
+  //     |kWaitingForInput|: an output packet has been requested, and we're
+  //         waiting for an input packet to arrive before we can proceed
+  //     |kWaitingForWorker|: we're waiting for the worker to produce the output
+  //         packet
+  //     |kWorkerNotDone|: the worker has satisfied the request, but is still
+  //         processing the input packet and may produce more output packets
+  // Note that |OutputState| is not intended to reflect the prefetch of an input
+  // packet.
+  enum class OutputState {
+    kIdle,
+    kWaitingForInput,
+    kWaitingForWorker,
+    kWorkerNotDone
+  };
+
+  // Processes a single input packet on the worker thread.
+  void HandleInputPacketOnWorker(PacketPtr packet);
+
+  // Delivers an output packet from |HandleInputPacketOnWorker| to the main
+  // thread.
+  void HandleOutputPacket(PacketPtr packet);
+
+  // Indicates that the worker thread is done with an input packet submitted
+  // via |HandleInputPacketOnWorker|. Called on the main thread.
+  void WorkerDoneWithInputPacket();
+
+  async_t* main_thread_async_;
+  async::Loop worker_loop_;
+
+  // These fields are accessed on the main thread only.
+  OutputState output_state_;
+  bool flushing_ = true;
+  bool end_of_input_stream_ = false;
+  bool end_of_output_stream_ = false;
+  // When we're not flushed and the input stream hasn't ended, we endeavor to
+  // keep a packet in |input_packet_| waiting to be decoded. That is, if
+  // |flushing_| and |end_of_input_stream_| are false and |input_packet_| is
+  // null, we can be sure we've requested an input packet from upstream.
+  PacketPtr input_packet_;
+  fit::closure flush_callback_;
+
+  // |allocator_| is initialized on the main thread during prepare and isn't
+  // changed until unprepare. The worker thread uses it to allocate payload
+  // memory.
+  std::shared_ptr<PayloadAllocator> allocator_;
+
+  // |decode_duration_| is updated on the worker thread and read on the main
+  // thread when |Dump| is called.
+  mutable std::mutex decode_duration_mutex_;
+  ValueTracker<int64_t> decode_duration_ FXL_GUARDED_BY(decode_duration_mutex_);
+};
+
+}  // namespace media_player
+
+#endif  // GARNET_BIN_MEDIA_MEDIA_PLAYER_DECODE_SOFTWARE_DECODER_H_
diff --git a/bin/media/media_player/demux/BUILD.gn b/bin/media/media_player/demux/BUILD.gn
index 7747bc8..86ef55c 100644
--- a/bin/media/media_player/demux/BUILD.gn
+++ b/bin/media/media_player/demux/BUILD.gn
@@ -21,14 +21,18 @@
   ]
 
   deps = [
+    "//garnet/bin/http:errors",
     "//garnet/bin/media/media_player/fidl",
     "//garnet/bin/media/media_player/framework",
     "//garnet/bin/media/media_player/util",
-    "//garnet/bin/network:errors",
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
-    "//garnet/public/lib/network/fidl",
+    "//garnet/public/lib/net/oldhttp/fidl",
+  ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
   ]
 }
 
diff --git a/bin/media/media_player/demux/demux.h b/bin/media/media_player/demux/demux.h
index 0f3e32e..478b2a6 100644
--- a/bin/media/media_player/demux/demux.h
+++ b/bin/media/media_player/demux/demux.h
@@ -8,6 +8,8 @@
 #include <memory>
 #include <vector>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/demux/reader.h"
 #include "garnet/bin/media/media_player/framework/metadata.h"
 #include "garnet/bin/media/media_player/framework/models/async_node.h"
@@ -21,8 +23,8 @@
 // produce one or more output streams.
 class Demux : public AsyncNode {
  public:
-  using SeekCallback = std::function<void()>;
-  using StatusCallback = std::function<void(
+  using SeekCallback = fit::closure;
+  using StatusCallback = fit::function<void(
       const std::unique_ptr<Metadata>& metadata,
       const std::string& problem_type, const std::string& problem_details)>;
 
@@ -50,7 +52,7 @@
 
   // Calls the callback when the initial streams and metadata have
   // established.
-  virtual void WhenInitialized(std::function<void(Result)> callback) = 0;
+  virtual void WhenInitialized(fit::function<void(Result)> callback) = 0;
 
   // Gets the stream collection. This method should not be called until the
   // WhenInitialized callback has been called.
diff --git a/bin/media/media_player/demux/fidl_reader.cc b/bin/media/media_player/demux/fidl_reader.cc
index 3b39819..66df7e3 100644
--- a/bin/media/media_player/demux/fidl_reader.cc
+++ b/bin/media/media_player/demux/fidl_reader.cc
@@ -7,7 +7,7 @@
 #include <limits>
 #include <string>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
 
@@ -16,14 +16,15 @@
 
 namespace media_player {
 
-FidlReader::FidlReader(fidl::InterfaceHandle<SeekingReader> seeking_reader)
+FidlReader::FidlReader(
+    fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader> seeking_reader)
     : seeking_reader_(seeking_reader.Bind()), async_(async_get_default()) {
   FXL_DCHECK(async_);
 
   read_in_progress_ = false;
 
   seeking_reader_->Describe(
-      [this](media::MediaResult result, uint64_t size, bool can_seek) {
+      [this](fuchsia::media::MediaResult result, uint64_t size, bool can_seek) {
         result_ = fxl::To<Result>(result);
         if (result_ == Result::kOk) {
           size_ = size;
@@ -36,12 +37,12 @@
 FidlReader::~FidlReader() {}
 
 void FidlReader::Describe(DescribeCallback callback) {
-  ready_.When([this, callback]() { callback(result_, size_, can_seek_); });
+  ready_.When([this, callback = std::move(callback)]() {
+    callback(result_, size_, can_seek_);
+  });
 }
 
-void FidlReader::ReadAt(size_t position,
-                        uint8_t* buffer,
-                        size_t bytes_to_read,
+void FidlReader::ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
                         ReadAtCallback callback) {
   FXL_DCHECK(buffer);
   FXL_DCHECK(bytes_to_read);
@@ -52,7 +53,7 @@
   read_at_position_ = position;
   read_at_buffer_ = buffer;
   read_at_bytes_to_read_ = bytes_to_read;
-  read_at_callback_ = callback;
+  read_at_callback_ = std::move(callback);
 
   // ReadAt may be called on non-fidl threads, so we use the runner.
   async::PostTask(
@@ -93,18 +94,19 @@
       return;
     }
 
-    seeking_reader_->ReadAt(read_at_position_, [this](media::MediaResult result,
-                                                      zx::socket socket) {
-      result_ = fxl::To<Result>(result);
-      if (result_ != Result::kOk) {
-        CompleteReadAt(result_);
-        return;
-      }
+    seeking_reader_->ReadAt(
+        read_at_position_,
+        [this](fuchsia::media::MediaResult result, zx::socket socket) {
+          result_ = fxl::To<Result>(result);
+          if (result_ != Result::kOk) {
+            CompleteReadAt(result_);
+            return;
+          }
 
-      socket_ = std::move(socket);
-      socket_position_ = read_at_position_;
-      ReadFromSocket();
-    });
+          socket_ = std::move(socket);
+          socket_position_ = read_at_position_;
+          ReadFromSocket();
+        });
   });
 }
 
diff --git a/bin/media/media_player/demux/fidl_reader.h b/bin/media/media_player/demux/fidl_reader.h
index 46f84a2..f24664f 100644
--- a/bin/media/media_player/demux/fidl_reader.h
+++ b/bin/media/media_player/demux/fidl_reader.h
@@ -8,7 +8,7 @@
 #include <atomic>
 #include <memory>
 
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/zx/socket.h>
@@ -24,7 +24,8 @@
  public:
   // Creates an FidlReader. Must be called on a fidl thread.
   static std::shared_ptr<Reader> Create(
-      fidl::InterfaceHandle<SeekingReader> seeking_reader) {
+      fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader>
+          seeking_reader) {
     return std::shared_ptr<Reader>(new FidlReader(std::move(seeking_reader)));
   }
 
@@ -33,13 +34,12 @@
   // Reader implementation.
   void Describe(DescribeCallback callback) override;
 
-  void ReadAt(size_t position,
-              uint8_t* buffer,
-              size_t bytes_to_read,
+  void ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
               ReadAtCallback callback) override;
 
  private:
-  FidlReader(fidl::InterfaceHandle<SeekingReader> seeking_reader);
+  FidlReader(fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader>
+                 seeking_reader);
 
   // Continues a ReadAt operation on the thread on which this reader was
   // constructed (a fidl thread).
@@ -54,7 +54,7 @@
   // Shuts down the consumer handle and calls CompleteReadAt.
   void FailReadAt(zx_status_t status);
 
-  SeekingReaderPtr seeking_reader_;
+  fuchsia::mediaplayer::SeekingReaderPtr seeking_reader_;
   Result result_ = Result::kOk;
   size_t size_ = kUnknownSize;
   bool can_seek_ = false;
diff --git a/bin/media/media_player/demux/file_reader.cc b/bin/media/media_player/demux/file_reader.cc
index 89d619d..2685ca8 100644
--- a/bin/media/media_player/demux/file_reader.cc
+++ b/bin/media/media_player/demux/file_reader.cc
@@ -44,9 +44,7 @@
   callback(result_, size_, true);
 }
 
-void FileReader::ReadAt(size_t position,
-                        uint8_t* buffer,
-                        size_t bytes_to_read,
+void FileReader::ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
                         ReadAtCallback callback) {
   FXL_DCHECK(position < size_);
 
diff --git a/bin/media/media_player/demux/file_reader.h b/bin/media/media_player/demux/file_reader.h
index 46f11ca..6e127f7 100644
--- a/bin/media/media_player/demux/file_reader.h
+++ b/bin/media/media_player/demux/file_reader.h
@@ -25,9 +25,7 @@
   // Reader implementation.
   void Describe(DescribeCallback callback) override;
 
-  void ReadAt(size_t position,
-              uint8_t* buffer,
-              size_t bytes_to_read,
+  void ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
               ReadAtCallback callback) override;
 
  private:
diff --git a/bin/media/media_player/demux/http_reader.cc b/bin/media/media_player/demux/http_reader.cc
index 7c8e903..bf445c0 100644
--- a/bin/media/media_player/demux/http_reader.cc
+++ b/bin/media/media_player/demux/http_reader.cc
@@ -4,14 +4,17 @@
 
 #include "garnet/bin/media/media_player/demux/http_reader.h"
 
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 #include <lib/async/default.h>
-#include <network/cpp/fidl.h>
 
-#include "garnet/bin/network/net_errors.h"
+#include "garnet/bin/http/http_errors.h"
 #include "lib/app/cpp/connect.h"
 #include "lib/fxl/logging.h"
 
 namespace media_player {
+
+namespace http = ::fuchsia::net::oldhttp;
+
 namespace {
 
 const char* kContentLengthHeaderName = "Content-Length";
@@ -34,64 +37,63 @@
 HttpReader::HttpReader(fuchsia::sys::StartupContext* startup_context,
                        const std::string& url)
     : url_(url) {
-  network::NetworkServicePtr network_service =
-      startup_context->ConnectToEnvironmentService<network::NetworkService>();
+  http::HttpServicePtr network_service =
+      startup_context->ConnectToEnvironmentService<http::HttpService>();
 
   network_service->CreateURLLoader(url_loader_.NewRequest());
 
-  network::URLRequest url_request;
+  http::URLRequest url_request;
   url_request.url = url_;
   url_request.method = "HEAD";
   url_request.auto_follow_redirects = true;
 
-  url_loader_->Start(
-      std::move(url_request), [this](network::URLResponse response) {
-        if (response.error) {
-          FXL_LOG(ERROR) << "HEAD response error " << response.error->code
-                         << " "
-                         << (response.error->description
-                                 ? response.error->description
-                                 : "<no description>");
-          result_ =
-              response.error->code == network::NETWORK_ERR_NAME_NOT_RESOLVED
-                  ? Result::kNotFound
-                  : Result::kUnknownError;
-          ready_.Occur();
-          return;
-        }
+  url_loader_->Start(std::move(url_request), [this](
+                                                 http::URLResponse response) {
+    if (response.error) {
+      FXL_LOG(ERROR) << "HEAD response error " << response.error->code << " "
+                     << (response.error->description
+                             ? response.error->description
+                             : "<no description>");
+      result_ = response.error->code == ::http::HTTP_ERR_NAME_NOT_RESOLVED
+                    ? Result::kNotFound
+                    : Result::kUnknownError;
+      ready_.Occur();
+      return;
+    }
 
-        if (response.status_code != kStatusOk) {
-          FXL_LOG(ERROR) << "HEAD response status code "
-                         << response.status_code;
-          result_ = response.status_code == kStatusNotFound
-                        ? Result::kNotFound
-                        : Result::kUnknownError;
-          ready_.Occur();
-          return;
-        }
+    if (response.status_code != kStatusOk) {
+      FXL_LOG(ERROR) << "HEAD response status code " << response.status_code;
+      result_ = response.status_code == kStatusNotFound ? Result::kNotFound
+                                                        : Result::kUnknownError;
+      ready_.Occur();
+      return;
+    }
 
-        for (const network::HttpHeader& header : *response.headers) {
-          if (header.name == kContentLengthHeaderName) {
-            size_ = std::stoull(header.value);
-          } else if (header.name == kAcceptRangesHeaderName &&
-                     header.value == kAcceptRangesHeaderBytesValue) {
-            can_seek_ = true;
-          }
-        }
+    for (const http::HttpHeader& header : *response.headers) {
+      if (header.name == kContentLengthHeaderName) {
+        size_ = std::stoull(header.value);
+      } else if (header.name == kAcceptRangesHeaderName &&
+                 header.value == kAcceptRangesHeaderBytesValue) {
+        can_seek_ = true;
+      }
+    }
 
-        ready_.Occur();
-      });
+    ready_.Occur();
+  });
 }
 
 HttpReader::~HttpReader() {}
 
 void HttpReader::Describe(DescribeCallback callback) {
-  ready_.When([this, callback]() { callback(result_, size_, can_seek_); });
+  ready_.When([this, callback = std::move(callback)]() {
+    callback(result_, size_, can_seek_);
+  });
 }
 
 void HttpReader::ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
                         ReadAtCallback callback) {
-  ready_.When([this, position, buffer, bytes_to_read, callback]() {
+  ready_.When([this, position, buffer, bytes_to_read,
+               callback = std::move(callback)]() mutable {
     if (result_ != Result::kOk) {
       callback(result_, 0);
       return;
@@ -112,7 +114,7 @@
     }
 
     read_at_bytes_remaining_ = read_at_bytes_to_read_;
-    read_at_callback_ = callback;
+    read_at_callback_ = std::move(callback);
 
     if (!socket_ || socket_position_ != read_at_position_) {
       socket_.reset();
@@ -211,7 +213,7 @@
     return;
   }
 
-  network::URLRequest request;
+  http::URLRequest request;
   request.url = url_;
   request.method = "GET";
 
@@ -219,13 +221,13 @@
     std::ostringstream value;
     value << kAcceptRangesHeaderBytesValue << "=" << read_at_position_ << "-";
 
-    network::HttpHeader header;
+    http::HttpHeader header;
     header.name = kRangeHeaderName;
     header.value = value.str();
     request.headers.push_back(std::move(header));
   }
 
-  url_loader_->Start(std::move(request), [this](network::URLResponse response) {
+  url_loader_->Start(std::move(request), [this](http::URLResponse response) {
     if (response.status_code != kStatusOk &&
         response.status_code != kStatusPartialContent) {
       FXL_LOG(WARNING) << "GET response status code " << response.status_code;
diff --git a/bin/media/media_player/demux/http_reader.h b/bin/media/media_player/demux/http_reader.h
index 395a3b8..8f91780 100644
--- a/bin/media/media_player/demux/http_reader.h
+++ b/bin/media/media_player/demux/http_reader.h
@@ -7,8 +7,8 @@
 
 #include <string>
 
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 #include <lib/async/cpp/wait.h>
-#include <network/cpp/fidl.h>
 
 #include "garnet/bin/media/media_player/demux/reader.h"
 #include "garnet/bin/media/media_player/util/incident.h"
@@ -50,7 +50,7 @@
   void LoadAndReadFromSocket();
 
   std::string url_;
-  network::URLLoaderPtr url_loader_;
+  ::fuchsia::net::oldhttp::URLLoaderPtr url_loader_;
   Result result_ = Result::kOk;
   uint64_t size_ = kUnknownSize;
   bool can_seek_ = false;
diff --git a/bin/media/media_player/demux/reader.h b/bin/media/media_player/demux/reader.h
index 1e58fab..7e60449 100644
--- a/bin/media/media_player/demux/reader.h
+++ b/bin/media/media_player/demux/reader.h
@@ -5,10 +5,11 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_DEMUX_READER_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_DEMUX_READER_H_
 
-#include <functional>
 #include <limits>
 #include <memory>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/framework/result.h"
 
 namespace media_player {
@@ -17,8 +18,8 @@
 class Reader {
  public:
   using DescribeCallback =
-      std::function<void(Result result, size_t size, bool can_seek)>;
-  using ReadAtCallback = std::function<void(Result result, size_t bytes_read)>;
+      fit::function<void(Result result, size_t size, bool can_seek)>;
+  using ReadAtCallback = fit::function<void(Result result, size_t bytes_read)>;
 
   static constexpr size_t kUnknownSize = std::numeric_limits<size_t>::max();
 
@@ -32,9 +33,7 @@
   // Reads the specified number of bytes into the buffer from the specified
   // position and returns a result and the number of bytes read via the
   // callback.
-  virtual void ReadAt(size_t position,
-                      uint8_t* buffer,
-                      size_t bytes_to_read,
+  virtual void ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
                       ReadAtCallback callback) = 0;
 };
 
diff --git a/bin/media/media_player/demux/reader_cache.cc b/bin/media/media_player/demux/reader_cache.cc
index 7607b6a..f14f652 100644
--- a/bin/media/media_player/demux/reader_cache.cc
+++ b/bin/media/media_player/demux/reader_cache.cc
@@ -30,30 +30,27 @@
 ReaderCache::~ReaderCache() {}
 
 void ReaderCache::Describe(DescribeCallback callback) {
-  describe_is_complete_.When([this, callback]() { store_.Describe(callback); });
+  describe_is_complete_.When([this, callback = std::move(callback)]() mutable {
+    store_.Describe(std::move(callback));
+  });
 }
 
-void ReaderCache::ReadAt(size_t position,
-                         uint8_t* buffer,
-                         size_t bytes_to_read,
+void ReaderCache::ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
                          ReadAtCallback callback) {
   FXL_DCHECK(buffer);
   FXL_DCHECK(bytes_to_read > 0);
 
-  read_at_request_.Start(position, buffer, bytes_to_read, callback);
+  read_at_request_.Start(position, buffer, bytes_to_read, std::move(callback));
 
   describe_is_complete_.When(
       [this]() { store_.SetReadAtRequest(&read_at_request_); });
 }
 
-ReaderCache::ReadAtRequest::ReadAtRequest() {
-  in_progress_ = false;
-}
+ReaderCache::ReadAtRequest::ReadAtRequest() { in_progress_ = false; }
 
 ReaderCache::ReadAtRequest::~ReadAtRequest() {}
 
-void ReaderCache::ReadAtRequest::Start(size_t position,
-                                       uint8_t* buffer,
+void ReaderCache::ReadAtRequest::Start(size_t position, uint8_t* buffer,
                                        size_t bytes_to_read,
                                        ReadAtCallback callback) {
   FXL_DCHECK(!in_progress_) << "concurrent calls to ReadAt are not allowed";
@@ -62,7 +59,7 @@
   buffer_ = buffer;
   original_bytes_to_read_ = bytes_to_read;
   remaining_bytes_to_read_ = bytes_to_read;
-  callback_ = callback;
+  callback_ = std::move(callback);
 }
 
 void ReaderCache::ReadAtRequest::CopyFrom(uint8_t* source, size_t byte_count) {
diff --git a/bin/media/media_player/demux/reader_cache.h b/bin/media/media_player/demux/reader_cache.h
index 7f76673..5a08605 100644
--- a/bin/media/media_player/demux/reader_cache.h
+++ b/bin/media/media_player/demux/reader_cache.h
@@ -51,9 +51,7 @@
   // Reader implementation.
   void Describe(DescribeCallback callback) override;
 
-  void ReadAt(size_t position,
-              uint8_t* buffer,
-              size_t bytes_to_read,
+  void ReadAt(size_t position, uint8_t* buffer, size_t bytes_to_read,
               ReadAtCallback callback) override;
 
  private:
@@ -68,9 +66,7 @@
     ~ReadAtRequest();
 
     // Initializes the request.
-    void Start(size_t position,
-               uint8_t* buffer,
-               size_t bytes_to_read,
+    void Start(size_t position, uint8_t* buffer, size_t bytes_to_read,
                ReadAtCallback callback);
 
     // Gets the current read position.
diff --git a/bin/media/media_player/demux/test/sparse_byte_buffer_test.cc b/bin/media/media_player/demux/test/sparse_byte_buffer_test.cc
index 191bd86..caa4215 100644
--- a/bin/media/media_player/demux/test/sparse_byte_buffer_test.cc
+++ b/bin/media/media_player/demux/test/sparse_byte_buffer_test.cc
@@ -21,9 +21,7 @@
                               (position >> 24));
 }
 
-void ExpectRegion(SparseByteBuffer* under_test,
-                  size_t position,
-                  size_t size,
+void ExpectRegion(SparseByteBuffer* under_test, size_t position, size_t size,
                   SparseByteBuffer::Region region) {
   EXPECT_NE(under_test->null_region(), region);
   EXPECT_EQ(position, region.position());
@@ -39,9 +37,7 @@
   EXPECT_EQ(under_test->null_hole(), hole);
 }
 
-void ExpectHole(SparseByteBuffer* under_test,
-                size_t position,
-                size_t size,
+void ExpectHole(SparseByteBuffer* under_test, size_t position, size_t size,
                 SparseByteBuffer::Hole hole) {
   EXPECT_NE(under_test->null_hole(), hole);
   EXPECT_EQ(position, hole.position());
diff --git a/bin/media/media_player/ffmpeg/BUILD.gn b/bin/media/media_player/ffmpeg/BUILD.gn
index 2e4e956..6e4101b 100644
--- a/bin/media/media_player/ffmpeg/BUILD.gn
+++ b/bin/media/media_player/ffmpeg/BUILD.gn
@@ -35,7 +35,6 @@
     "//garnet/bin/media/media_player/decode",
     "//garnet/bin/media/media_player/demux",
     "//garnet/bin/media/media_player/framework",
-    "//garnet/bin/media/media_player/metrics",
     "//garnet/bin/media/media_player/util",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
diff --git a/bin/media/media_player/ffmpeg/av_codec_context.cc b/bin/media/media_player/ffmpeg/av_codec_context.cc
index 1add6dd..dd6d456 100644
--- a/bin/media/media_player/ffmpeg/av_codec_context.cc
+++ b/bin/media/media_player/ffmpeg/av_codec_context.cc
@@ -141,8 +141,7 @@
 
 // Converts AVColorSpace and AVColorRange to ColorSpace.
 VideoStreamType::ColorSpace ColorSpaceFromAVColorSpaceAndRange(
-    AVColorSpace color_space,
-    AVColorRange color_range) {
+    AVColorSpace color_space, AVColorRange color_range) {
   // TODO(dalesat): Blindly copied from Chromium.
   if (color_range == AVCOL_RANGE_JPEG) {
     return VideoStreamType::ColorSpace::kJpeg;
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.cc b/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.cc
index ab363d2..1b969e9 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.cc
+++ b/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.cc
@@ -50,17 +50,17 @@
   }
 }
 
-int FfmpegAudioDecoder::BuildAVFrame(const AVCodecContext& av_codec_context,
-                                     AVFrame* av_frame,
-                                     PayloadAllocator* allocator) {
+int FfmpegAudioDecoder::BuildAVFrame(
+    const AVCodecContext& av_codec_context, AVFrame* av_frame,
+    const std::shared_ptr<PayloadAllocator>& allocator) {
   FXL_DCHECK(av_frame);
   FXL_DCHECK(allocator);
 
   // Use the provided allocator unless we intend to interleave later, in which
   // case use the default allocator. We'll interleave into a buffer from the
   // provided allocator in CreateOutputPacket.
-  PayloadAllocator* allocator_to_use =
-      (lpcm_util_ == nullptr) ? allocator : default_allocator_.get();
+  const std::shared_ptr<PayloadAllocator>& allocator_to_use =
+      (lpcm_util_ == nullptr) ? allocator : default_allocator_;
   FXL_DCHECK(allocator_to_use);
 
   AVSampleFormat av_sample_format =
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.h b/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.h
index 6cd39fd..f5d2e5e 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.h
+++ b/bin/media/media_player/ffmpeg/ffmpeg_audio_decoder.h
@@ -26,9 +26,8 @@
   // FfmpegDecoderBase overrides.
   void OnNewInputPacket(const PacketPtr& packet) override;
 
-  int BuildAVFrame(const AVCodecContext& av_codec_context,
-                   AVFrame* av_frame,
-                   PayloadAllocator* allocator) override;
+  int BuildAVFrame(const AVCodecContext& av_codec_context, AVFrame* av_frame,
+                   const std::shared_ptr<PayloadAllocator>& allocator) override;
 
   PacketPtr CreateOutputPacket(
       const AVFrame& av_frame,
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.cc b/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.cc
index 7654abe..06aa101 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.cc
+++ b/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.cc
@@ -10,7 +10,6 @@
 #include "garnet/bin/media/media_player/ffmpeg/av_codec_context.h"
 #include "garnet/bin/media/media_player/framework/formatting.h"
 #include "lib/fxl/logging.h"
-#include "lib/media/timeline/timeline.h"
 
 namespace media_player {
 
@@ -19,13 +18,9 @@
       av_frame_ptr_(ffmpeg::AvFrame::Create()) {
   FXL_DCHECK(av_codec_context_);
 
-  state_ = State::kIdle;
-
   av_codec_context_->opaque = this;
   av_codec_context_->get_buffer2 = AllocateBufferForAvFrame;
   av_codec_context_->refcounted_frames = 1;
-
-  worker_loop_.StartThread();
 }
 
 FfmpegDecoderBase::~FfmpegDecoderBase() {}
@@ -34,190 +29,131 @@
   return AvCodecContext::GetStreamType(*av_codec_context_);
 }
 
-void FfmpegDecoderBase::GetConfiguration(size_t* input_count,
-                                         size_t* output_count) {
-  FXL_DCHECK(input_count);
-  FXL_DCHECK(output_count);
-  *input_count = 1;
-  *output_count = 1;
+void FfmpegDecoderBase::Flush() {
+  FXL_DCHECK(is_worker_thread());
+  avcodec_flush_buffers(av_codec_context_.get());
+  next_pts_ = Packet::kUnknownPts;
 }
 
-void FfmpegDecoderBase::FlushInput(bool hold_frame, size_t input_index,
-                                   fxl::Closure callback) {
-  FXL_DCHECK(input_index == 0);
-  FXL_DCHECK(callback);
-
-  flushing_ = true;
-
-  callback();
-}
-
-void FfmpegDecoderBase::FlushOutput(size_t output_index,
-                                    fxl::Closure callback) {
-  FXL_DCHECK(output_index == 0);
-  FXL_DCHECK(callback);
-
-  flushing_ = true;
-
-  async::PostTask(worker_loop_.async(), [this, callback] {
-    FXL_DCHECK(av_codec_context_);
-    avcodec_flush_buffers(av_codec_context_.get());
-    next_pts_ = Packet::kUnknownPts;
-    state_ = State::kIdle;
-    callback();
-  });
-}
-
-std::shared_ptr<PayloadAllocator> FfmpegDecoderBase::allocator_for_input(
-    size_t input_index) {
-  FXL_DCHECK(input_index == 0);
-  return nullptr;
-}
-
-void FfmpegDecoderBase::PutInputPacket(PacketPtr packet, size_t input_index) {
-  FXL_DCHECK(input_index == 0);
-  async::PostTask(worker_loop_.async(),
-                  [this, packet] { TransformPacket(packet); });
-}
-
-bool FfmpegDecoderBase::can_accept_allocator_for_output(
-    size_t output_index) const {
-  FXL_DCHECK(output_index == 0);
-  return true;
-}
-
-void FfmpegDecoderBase::SetAllocatorForOutput(
-    std::shared_ptr<PayloadAllocator> allocator, size_t output_index) {
-  FXL_DCHECK(output_index == 0);
-  allocator_ = allocator;
-}
-
-void FfmpegDecoderBase::RequestOutputPacket() {
-  flushing_ = false;
-
-  State expected = State::kIdle;
-  if (state_.compare_exchange_strong(expected, State::kOutputPacketRequested)) {
-    stage()->RequestInputPacket();
-  }
-}
-
-void FfmpegDecoderBase::TransformPacket(PacketPtr input) {
-  if (flushing_) {
-    // We got a flush request. Throw away the packet.
-    return;
-  }
-
-  if (input->end_of_stream()) {
-    state_ = State::kEndOfStream;
-  }
-
-  TRACE_DURATION("motown", (av_codec_context_->codec_type == AVMEDIA_TYPE_VIDEO
-                                ? "DecodeVideoPacket"
-                                : "DecodeAudioPacket"));
+bool FfmpegDecoderBase::TransformPacket(const PacketPtr& input, bool new_input,
+                                        PacketPtr* output) {
+  FXL_DCHECK(is_worker_thread());
   FXL_DCHECK(input);
-  FXL_DCHECK(allocator_);
+  FXL_DCHECK(output);
 
-  if (input->size() == 0 && !input->end_of_stream()) {
-    // Throw away empty packets that aren't end-of-stream packets. The
-    // underlying decoder interprets an empty packet as end-of-stream.
-    stage()->RequestInputPacket();
-    return;
+  TRACE_DURATION(
+      "motown", "DecodePacket", "type",
+      (av_codec_context_->codec_type == AVMEDIA_TYPE_VIDEO ? "video"
+                                                           : "audio"));
+
+  *output = nullptr;
+
+  if (new_input) {
+    if (input->size() == 0 && !input->end_of_stream()) {
+      // This packet isn't end-of-stream, but it has size zero. The underlying
+      // decoder interprets an empty input packet as end-of-stream, so we
+      // we refrain from decoding this packet and return true to indicate we're
+      // done with it..
+      //
+      // The underlying decoder gets its end-of-stream indication in one of
+      // two ways:
+      // 1) If the end-of-stream packet is empty, it will get past this check
+      //    and be submitted to the decoder, indicating end-of-stream.
+      // 2) If the end-of-stream packet is not empty, we let it through and
+      //    follow it with an empty end-of-stream packet that we create for
+      //    that purpose.
+      return true;
+    }
+
+    OnNewInputPacket(input);
+
+    // Send the packet to the ffmpeg decoder. If it fails, return true to
+    // indicate we're done with the packet.
+    if (SendPacket(input) != 0) {
+      if (input->end_of_stream()) {
+        // The input packet was end-of-stream. We won't get called again before
+        // a flush, so make sure the output gets an end-of-stream packet.
+        *output = CreateEndOfStreamPacket();
+      }
+
+      return true;
+    }
   }
 
-  OnNewInputPacket(input);
+  int result =
+      avcodec_receive_frame(av_codec_context_.get(), av_frame_ptr_.get());
+
+  switch (result) {
+    case 0:
+      // Succeeded, frame produced. We're not done with the input packet.
+      *output = CreateOutputPacket(*av_frame_ptr_, allocator());
+      av_frame_unref(av_frame_ptr_.get());
+      return false;
+
+    case AVERROR(EAGAIN):
+      // Succeeded, no frame produced.
+      if (input->end_of_stream() && input->size() != 0) {
+        // The input packet is an end-of-stream packet, and it has payload. The
+        // underlying decoder interprets an empty packet as end-of-stream, so
+        // we need to send it an empty packet.
+        if (SendPacket(CreateEndOfStreamPacket()) == 0) {
+          // |SendPacket| succeeded. We return false to indicate we're not done
+          // with the original end-of-stream packet. We'll get called again with
+          // the same end-of-stream packet and |new_input| set to false. That
+          // will continue until we've extracted all the output packets the
+          // decoder has to give us. Note that we won't end up here again,
+          // because |avcodec_receive_frame| will return either 0 or
+          // |AVERROR_EOF|, not |AVERROR(EAGAIN)|.
+          return false;
+        }
+
+        // |SendPacket| failed. We return true to indicate we're done with the
+        // input packet. We also output an end-of-stream packet to terminate
+        // the output stream.
+        *output = CreateEndOfStreamPacket();
+      }
+
+      // Indicate we're done with the input packet.
+      return true;
+
+    case AVERROR_EOF:
+      // Succeeded, no frame produced, end-of-stream sequence complete.
+      // Produce an end-of-stream packet.
+      FXL_DCHECK(input->end_of_stream());
+      *output = CreateEndOfStreamPacket();
+      return true;
+
+    default:
+      FXL_DLOG(ERROR) << "avcodec_receive_frame failed " << result;
+      if (input->end_of_stream()) {
+        // The input packet was end-of-stream. We won't get called again before
+        // a flush, so make sure the output gets an end-of-stream packet.
+        *output = CreateEndOfStreamPacket();
+      }
+
+      return true;
+  }
+}
+
+int FfmpegDecoderBase::SendPacket(const PacketPtr& input) {
+  FXL_DCHECK(input);
 
   AVPacket av_packet;
   av_init_packet(&av_packet);
   av_packet.data = reinterpret_cast<uint8_t*>(input->payload());
   av_packet.size = input->size();
   av_packet.pts = input->pts();
-
   if (input->keyframe()) {
     av_packet.flags |= AV_PKT_FLAG_KEY;
   }
 
-  int64_t start_time = media::Timeline::local_now();
-
   int result = avcodec_send_packet(av_codec_context_.get(), &av_packet);
 
   if (result != 0) {
     FXL_DLOG(ERROR) << "avcodec_send_packet failed " << result;
-    if (input->end_of_stream()) {
-      // The input packet was end-of-stream. We won't get called again before
-      // a flush, so make sure the output gets an end-of-stream packet.
-      stage()->PutOutputPacket(CreateEndOfStreamPacket());
-    }
-
-    return;
   }
 
-  while (true) {
-    int result =
-        avcodec_receive_frame(av_codec_context_.get(), av_frame_ptr_.get());
-
-    if (result != 0) {
-      decode_duration_.AddSample(media::Timeline::local_now() - start_time);
-    }
-
-    switch (result) {
-      case 0:
-        // Succeeded, frame produced.
-        {
-          PacketPtr packet = CreateOutputPacket(*av_frame_ptr_, allocator_);
-          av_frame_unref(av_frame_ptr_.get());
-
-          // If the state is still |kOutputPacketRequested|, set it to |kIdle|.
-          // It could be |kIdle| already if a flush occurred or |kEndOfStream|
-          // if we got an end-of-stream packet. In either of those cases, we
-          // want to leave the state unchanged.
-          State expected = State::kOutputPacketRequested;
-          state_.compare_exchange_strong(expected, State::kIdle);
-
-          stage()->PutOutputPacket(packet);
-        }
-
-        // Loop around to call avcodec_receive_frame again.
-        break;
-
-      case AVERROR(EAGAIN):
-        // Succeeded, no frame produced, need another input packet.
-        FXL_DCHECK(input->size() != 0);
-
-        if (!input->end_of_stream()) {
-          if (state_ == State::kOutputPacketRequested) {
-            stage()->RequestInputPacket();
-          }
-
-          return;
-        }
-
-        // The input packet is an end-of-stream packet, but it has payload. The
-        // underlying decoder interprets an empty packet as end-of-stream, so
-        // we need to send it an empty packet. We do this by reentering
-        // |TransformPacket|. This is safe, because we get |AVERROR_EOF|, not
-        // |AVERROR(EAGAIN)| when the decoder is drained following an empty
-        // input packet.
-        TransformPacket(CreateEndOfStreamPacket());
-        return;
-
-      case AVERROR_EOF:
-        // Succeeded, no frame produced, end-of-stream sequence complete.
-        FXL_DCHECK(input->end_of_stream());
-        stage()->PutOutputPacket(CreateEndOfStreamPacket());
-        return;
-
-      default:
-        FXL_DLOG(ERROR) << "avcodec_receive_frame failed " << result;
-        if (input->end_of_stream()) {
-          // The input packet was end-of-stream. We won't get called again
-          // before a flush, so make sure the output gets an end-of-stream
-          // packet.
-          stage()->PutOutputPacket(CreateEndOfStreamPacket());
-        }
-
-        return;
-    }
-  }
+  return result;
 }
 
 void FfmpegDecoderBase::OnNewInputPacket(const PacketPtr& packet) {}
@@ -236,10 +172,8 @@
   FfmpegDecoderBase* self =
       reinterpret_cast<FfmpegDecoderBase*>(av_codec_context->opaque);
   FXL_DCHECK(self);
-  FXL_DCHECK(self->allocator_);
 
-  return self->BuildAVFrame(*av_codec_context, av_frame,
-                            self->allocator_.get());
+  return self->BuildAVFrame(*av_codec_context, av_frame, self->allocator());
 }
 
 // static
@@ -256,41 +190,16 @@
 
 FfmpegDecoderBase::DecoderPacket::~DecoderPacket() {
   FXL_DCHECK(owner_);
-  async::PostTask(owner_->worker_loop_.async(),
-                  [av_buffer_ref = av_buffer_ref_]() mutable {
-                    av_buffer_unref(&av_buffer_ref);
-                  });
+  owner_->PostTaskToWorkerThread([av_buffer_ref = av_buffer_ref_]() mutable {
+    av_buffer_unref(&av_buffer_ref);
+  });
 }
 
 void FfmpegDecoderBase::Dump(std::ostream& os) const {
-  os << label() << indent;
-  stage()->Dump(os);
-  os << newl << "output stream type:" << output_stream_type();
-  os << newl << "state:             ";
+  SoftwareDecoder::Dump(os);
 
-  switch (state_) {
-    case State::kIdle:
-      os << "idle";
-      break;
-    case State::kOutputPacketRequested:
-      os << "output packet requested";
-      break;
-    case State::kEndOfStream:
-      os << "end of stream";
-      break;
-  }
-
-  os << newl << "flushing:          " << flushing_;
+  os << indent;
   os << newl << "next pts:          " << AsNs(next_pts_) << "@" << pts_rate_;
-
-  if (decode_duration_.count() != 0) {
-    os << newl << "decodes:           " << decode_duration_.count();
-    os << newl << "decode durations:";
-    os << newl << "    minimum        " << AsNs(decode_duration_.min());
-    os << newl << "    average        " << AsNs(decode_duration_.average());
-    os << newl << "    maximum        " << AsNs(decode_duration_.max());
-  }
-
   os << outdent;
 }
 
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.h b/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.h
index 73b0b73..be4f9e9 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.h
+++ b/bin/media/media_player/ffmpeg/ffmpeg_decoder_base.h
@@ -5,16 +5,14 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_FFMPEG_FFMPEG_DECODER_BASE_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_FFMPEG_FFMPEG_DECODER_BASE_H_
 
-#include <atomic>
 #include <limits>
 
 #include <lib/async-loop/cpp/loop.h>
 
-#include "garnet/bin/media/media_player/decode/decoder.h"
+#include "garnet/bin/media/media_player/decode/software_decoder.h"
 #include "garnet/bin/media/media_player/ffmpeg/av_codec_context.h"
 #include "garnet/bin/media/media_player/ffmpeg/av_frame.h"
 #include "garnet/bin/media/media_player/ffmpeg/av_packet.h"
-#include "garnet/bin/media/media_player/metrics/value_tracker.h"
 extern "C" {
 #include "third_party/ffmpeg/libavcodec/avcodec.h"
 }
@@ -22,7 +20,7 @@
 namespace media_player {
 
 // Abstract base class for ffmpeg-based decoders.
-class FfmpegDecoderBase : public Decoder {
+class FfmpegDecoderBase : public SoftwareDecoder {
  public:
   FfmpegDecoderBase(AvCodecContextPtr av_codec_context);
 
@@ -34,25 +32,6 @@
   // AsyncNode implementation.
   void Dump(std::ostream& os) const override;
 
-  void GetConfiguration(size_t* input_count, size_t* output_count) override;
-
-  void FlushInput(bool hold_frame, size_t input_index,
-                  fxl::Closure callback) override;
-
-  void FlushOutput(size_t output_index, fxl::Closure callback) override;
-
-  std::shared_ptr<PayloadAllocator> allocator_for_input(
-      size_t input_index) override;
-
-  void PutInputPacket(PacketPtr packet, size_t input_index) override;
-
-  bool can_accept_allocator_for_output(size_t output_index) const override;
-
-  void SetAllocatorForOutput(std::shared_ptr<PayloadAllocator> allocator,
-                             size_t output_index) override;
-
-  void RequestOutputPacket() override;
-
  protected:
   class DecoderPacket : public Packet {
    public:
@@ -79,6 +58,12 @@
     FfmpegDecoderBase* owner_;
   };
 
+  // SoftwareDecoder overrides.
+  void Flush() override;
+
+  bool TransformPacket(const PacketPtr& input, bool new_input,
+                       PacketPtr* output) override;
+
   // Called when a new input packet is about to be processed. The default
   // implementation does nothing.
   virtual void OnNewInputPacket(const PacketPtr& packet);
@@ -86,8 +71,9 @@
   // Fills in |av_frame|, probably using an |AVBuffer| allocated via
   // CreateAVBuffer. |av_codec_context| may be distinct from context() and
   // should be used when a codec context is required.
-  virtual int BuildAVFrame(const AVCodecContext& av_codec_context,
-                           AVFrame* av_frame, PayloadAllocator* allocator) = 0;
+  virtual int BuildAVFrame(
+      const AVCodecContext& av_codec_context, AVFrame* av_frame,
+      const std::shared_ptr<PayloadAllocator>& allocator) = 0;
 
   // Creates a Packet from av_frame.
   virtual PacketPtr CreateOutputPacket(
@@ -111,19 +97,17 @@
   void set_pts_rate(media::TimelineRate value) { pts_rate_ = value; }
 
   // Creates an AVBuffer.
-  AVBufferRef* CreateAVBuffer(uint8_t* payload_buffer,
-                              size_t payload_buffer_size,
-                              PayloadAllocator* allocator) {
+  AVBufferRef* CreateAVBuffer(
+      uint8_t* payload_buffer, size_t payload_buffer_size,
+      const std::shared_ptr<PayloadAllocator>& allocator) {
     FXL_DCHECK(payload_buffer_size <=
                static_cast<size_t>(std::numeric_limits<int>::max()));
-    return av_buffer_create(payload_buffer,
-                            static_cast<int>(payload_buffer_size),
-                            ReleaseBufferForAvFrame, allocator, /* flags */ 0);
+    return av_buffer_create(
+        payload_buffer, static_cast<int>(payload_buffer_size),
+        ReleaseBufferForAvFrame, allocator.get(), /* flags */ 0);
   }
 
  private:
-  enum class State { kIdle, kOutputPacketRequested, kEndOfStream };
-
   // Callback used by the ffmpeg decoder to acquire a buffer.
   static int AllocateBufferForAvFrame(AVCodecContext* av_codec_context,
                                       AVFrame* av_frame, int flags);
@@ -131,25 +115,17 @@
   // Callback used by the ffmpeg decoder to release a buffer.
   static void ReleaseBufferForAvFrame(void* opaque, uint8_t* buffer);
 
-  // Transforms an input packet. Called on the worker thread.
-  void TransformPacket(PacketPtr packet);
+  // Sends |input| to the ffmpeg decoder and returns the result of
+  // |avcodec_send_packet|. A return value of 0 indicates success.
+  int SendPacket(const PacketPtr& input);
 
   // Creates an end-of-stream packet.
   PacketPtr CreateEndOfStreamPacket();
 
   AvCodecContextPtr av_codec_context_;
-  async::Loop worker_loop_;
   ffmpeg::AvFramePtr av_frame_ptr_;
   int64_t next_pts_ = Packet::kUnknownPts;
   media::TimelineRate pts_rate_;
-  std::atomic<State> state_;
-  bool flushing_ = false;
-
-  // The allocator used by avcodec_send_packet and avcodec_receive_frame to
-  // provide context for AllocateBufferForAvFrame.
-  std::shared_ptr<PayloadAllocator> allocator_;
-
-  ValueTracker<int64_t> decode_duration_;
 };
 
 }  // namespace media_player
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_demux.cc b/bin/media/media_player/ffmpeg/ffmpeg_demux.cc
index 6d2b5e3..0f54ac3 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_demux.cc
+++ b/bin/media/media_player/ffmpeg/ffmpeg_demux.cc
@@ -6,10 +6,10 @@
 #include <map>
 #include <thread>
 
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
 
 #include "garnet/bin/media/media_player/ffmpeg/av_codec_context.h"
 #include "garnet/bin/media/media_player/ffmpeg/av_format_context.h"
@@ -35,7 +35,7 @@
   // Demux implementation.
   void SetStatusCallback(StatusCallback callback) override;
 
-  void WhenInitialized(std::function<void(Result)> callback) override;
+  void WhenInitialized(fit::function<void(Result)> callback) override;
 
   const std::vector<std::unique_ptr<DemuxStream>>& streams() const override;
 
@@ -48,7 +48,7 @@
 
   void GetConfiguration(size_t* input_count, size_t* output_count) override;
 
-  void FlushOutput(size_t output_index, fxl::Closure callback) override;
+  void FlushOutput(size_t output_index, fit::closure callback) override;
 
   void RequestOutputPacket() override;
 
@@ -175,11 +175,12 @@
 }
 
 void FfmpegDemuxImpl::SetStatusCallback(StatusCallback callback) {
-  status_callback_ = callback;
+  status_callback_ = std::move(callback);
 }
 
-void FfmpegDemuxImpl::WhenInitialized(std::function<void(Result)> callback) {
-  init_complete_.When([this, callback]() { callback(result_); });
+void FfmpegDemuxImpl::WhenInitialized(fit::function<void(Result)> callback) {
+  init_complete_.When(
+      [this, callback = std::move(callback)]() { callback(result_); });
 }
 
 const std::vector<std::unique_ptr<Demux::DemuxStream>>&
@@ -189,8 +190,8 @@
 
 void FfmpegDemuxImpl::Seek(int64_t position, SeekCallback callback) {
   std::lock_guard<std::mutex> locker(mutex_);
-  seek_position_ = position;
-  seek_callback_ = callback;
+  seek_position_ = std::move(position);
+  seek_callback_ = std::move(callback);
   condition_variable_.notify_all();
 }
 
@@ -220,7 +221,7 @@
   *output_count = streams_.size();
 }
 
-void FfmpegDemuxImpl::FlushOutput(size_t output_index, fxl::Closure callback) {
+void FfmpegDemuxImpl::FlushOutput(size_t output_index, fit::closure callback) {
   callback();
 }
 
@@ -237,9 +238,10 @@
   if (result_ != Result::kOk) {
     FXL_LOG(ERROR) << "AvIoContext::Create failed, result "
                    << static_cast<int>(result_);
-    ReportProblem(
-        result_ == Result::kNotFound ? kProblemAssetNotFound : kProblemInternal,
-        "");
+    ReportProblem(result_ == Result::kNotFound
+                      ? fuchsia::mediaplayer::kProblemAssetNotFound
+                      : fuchsia::mediaplayer::kProblemInternal,
+                  "");
     init_complete_.Occur();
     return;
   }
@@ -250,7 +252,7 @@
   if (!format_context_) {
     FXL_LOG(ERROR) << "AvFormatContext::OpenInput failed";
     result_ = Result::kUnsupportedOperation;
-    ReportProblem(kProblemContainerNotSupported, "");
+    ReportProblem(fuchsia::mediaplayer::kProblemContainerNotSupported, "");
     init_complete_.Occur();
     return;
   }
@@ -259,7 +261,8 @@
   if (r < 0) {
     FXL_LOG(ERROR) << "avformat_find_stream_info failed, result " << r;
     result_ = Result::kInternalError;
-    ReportProblem(kProblemInternal, "avformat_find_stream_info failed");
+    ReportProblem(fuchsia::mediaplayer::kProblemInternal,
+                  "avformat_find_stream_info failed");
     init_complete_.Occur();
     return;
   }
@@ -308,7 +311,7 @@
       }
 
       next_stream_to_end_ = -1;
-      async::PostTask(async_, [seek_callback]() { seek_callback(); });
+      async::PostTask(async_, std::move(seek_callback));
     }
 
     if (packet_requested) {
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_formatting.cc b/bin/media/media_player/ffmpeg/ffmpeg_formatting.cc
index 49f0260..4dc8a30 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_formatting.cc
+++ b/bin/media/media_player/ffmpeg/ffmpeg_formatting.cc
@@ -14,9 +14,7 @@
 
 namespace media_player {
 
-const char* safe(const char* s) {
-  return s == nullptr ? "<nullptr>" : s;
-}
+const char* safe(const char* s) { return s == nullptr ? "<nullptr>" : s; }
 
 std::ostream& operator<<(std::ostream& os,
                          const struct AVCodecTag* const* value) {
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.cc b/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.cc
index d5f114c..a2493b3 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.cc
+++ b/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.cc
@@ -53,9 +53,9 @@
   context()->reordered_opaque = packet->pts();
 }
 
-int FfmpegVideoDecoder::BuildAVFrame(const AVCodecContext& av_codec_context,
-                                     AVFrame* av_frame,
-                                     PayloadAllocator* allocator) {
+int FfmpegVideoDecoder::BuildAVFrame(
+    const AVCodecContext& av_codec_context, AVFrame* av_frame,
+    const std::shared_ptr<PayloadAllocator>& allocator) {
   FXL_DCHECK(av_frame);
   FXL_DCHECK(allocator);
 
diff --git a/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.h b/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.h
index 7ada9c4..2754a22 100644
--- a/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.h
+++ b/bin/media/media_player/ffmpeg/ffmpeg_video_decoder.h
@@ -24,9 +24,8 @@
   // FfmpegDecoderBase overrides.
   void OnNewInputPacket(const PacketPtr& packet) override;
 
-  int BuildAVFrame(const AVCodecContext& av_codec_context,
-                   AVFrame* av_frame,
-                   PayloadAllocator* allocator) override;
+  int BuildAVFrame(const AVCodecContext& av_codec_context, AVFrame* av_frame,
+                   const std::shared_ptr<PayloadAllocator>& allocator) override;
 
   PacketPtr CreateOutputPacket(
       const AVFrame& av_frame,
diff --git a/bin/media/media_player/ffmpeg/lpcm_util.cc b/bin/media/media_player/ffmpeg/lpcm_util.cc
index 25817a7..50873a8 100644
--- a/bin/media/media_player/ffmpeg/lpcm_util.cc
+++ b/bin/media/media_player/ffmpeg/lpcm_util.cc
@@ -21,9 +21,7 @@
 
   void Mix(const void* in, void* out, size_t frame_count) const override;
 
-  void Interleave(const void* in,
-                  size_t in_byte_count,
-                  void* out,
+  void Interleave(const void* in, size_t in_byte_count, void* out,
                   size_t frame_count) const override;
 
  private:
@@ -92,8 +90,7 @@
 }
 
 template <typename T>
-void LpcmUtilImpl<T>::Copy(const void* in,
-                           void* out,
+void LpcmUtilImpl<T>::Copy(const void* in, void* out,
                            size_t frame_count) const {
   std::memcpy(out, in, stream_type_.min_buffer_size(frame_count));
 }
@@ -111,8 +108,7 @@
 }
 
 template <>
-void LpcmUtilImpl<uint8_t>::Mix(const void* in,
-                                void* out,
+void LpcmUtilImpl<uint8_t>::Mix(const void* in, void* out,
                                 size_t frame_count) const {
   const uint8_t* in_sample = reinterpret_cast<const uint8_t*>(in);
   uint8_t* out_sample = reinterpret_cast<uint8_t*>(out);
@@ -126,10 +122,8 @@
 }
 
 template <typename T>
-void LpcmUtilImpl<T>::Interleave(const void* in,
-                                 size_t in_byte_count,
-                                 void* out,
-                                 size_t frame_count) const {
+void LpcmUtilImpl<T>::Interleave(const void* in, size_t in_byte_count,
+                                 void* out, size_t frame_count) const {
   FXL_DCHECK(in);
   FXL_DCHECK(in_byte_count);
   FXL_DCHECK(out);
diff --git a/bin/media/media_player/ffmpeg/lpcm_util.h b/bin/media/media_player/ffmpeg/lpcm_util.h
index a57f344..9505e9d 100644
--- a/bin/media/media_player/ffmpeg/lpcm_util.h
+++ b/bin/media/media_player/ffmpeg/lpcm_util.h
@@ -32,9 +32,7 @@
   // channel buffer per channel. The samples for each channel are contiguous
   // in the respective channel buffer with possible empty space at the end
   // (hence the in_type_count and the frame_count).
-  virtual void Interleave(const void* in,
-                          size_t in_byte_count,
-                          void* out,
+  virtual void Interleave(const void* in, size_t in_byte_count, void* out,
                           size_t frame_count) const = 0;
 };
 
diff --git a/bin/media/media_player/fidl/fidl_type_conversions.cc b/bin/media/media_player/fidl/fidl_type_conversions.cc
index 74509c7..e68e248 100644
--- a/bin/media/media_player/fidl/fidl_type_conversions.cc
+++ b/bin/media/media_player/fidl/fidl_type_conversions.cc
@@ -9,80 +9,77 @@
 #include "garnet/bin/media/media_player/framework/types/text_stream_type.h"
 #include "garnet/bin/media/media_player/framework/types/video_stream_type.h"
 
-using media_player::MediaMetadata;
-using media_player::MediaMetadataPtr;
-
 namespace fxl {
 
 namespace {
 
 bool KnownEncodingsMatch() {
   return !strcmp(media_player::StreamType::kAudioEncodingAac,
-                 media::kAudioEncodingAac) &&
+                 fuchsia::media::kAudioEncodingAac) &&
          !strcmp(media_player::StreamType::kAudioEncodingAmrNb,
-                 media::kAudioEncodingAmrNb) &&
+                 fuchsia::media::kAudioEncodingAmrNb) &&
          !strcmp(media_player::StreamType::kAudioEncodingAmrWb,
-                 media::kAudioEncodingAmrWb) &&
+                 fuchsia::media::kAudioEncodingAmrWb) &&
          !strcmp(media_player::StreamType::kAudioEncodingFlac,
-                 media::kAudioEncodingFlac) &&
+                 fuchsia::media::kAudioEncodingFlac) &&
          !strcmp(media_player::StreamType::kAudioEncodingGsmMs,
-                 media::kAudioEncodingGsmMs) &&
+                 fuchsia::media::kAudioEncodingGsmMs) &&
          !strcmp(media_player::StreamType::kAudioEncodingLpcm,
-                 media::kAudioEncodingLpcm) &&
+                 fuchsia::media::kAudioEncodingLpcm) &&
          !strcmp(media_player::StreamType::kAudioEncodingMp3,
-                 media::kAudioEncodingMp3) &&
+                 fuchsia::media::kAudioEncodingMp3) &&
          !strcmp(media_player::StreamType::kAudioEncodingPcmALaw,
-                 media::kAudioEncodingPcmALaw) &&
+                 fuchsia::media::kAudioEncodingPcmALaw) &&
          !strcmp(media_player::StreamType::kAudioEncodingPcmMuLaw,
-                 media::kAudioEncodingPcmMuLaw) &&
+                 fuchsia::media::kAudioEncodingPcmMuLaw) &&
          !strcmp(media_player::StreamType::kAudioEncodingVorbis,
-                 media::kAudioEncodingVorbis) &&
+                 fuchsia::media::kAudioEncodingVorbis) &&
          !strcmp(media_player::StreamType::kVideoEncodingH263,
-                 media::kVideoEncodingH263) &&
+                 fuchsia::media::kVideoEncodingH263) &&
          !strcmp(media_player::StreamType::kVideoEncodingH264,
-                 media::kVideoEncodingH264) &&
+                 fuchsia::media::kVideoEncodingH264) &&
          !strcmp(media_player::StreamType::kVideoEncodingMpeg4,
-                 media::kVideoEncodingMpeg4) &&
+                 fuchsia::media::kVideoEncodingMpeg4) &&
          !strcmp(media_player::StreamType::kVideoEncodingTheora,
-                 media::kVideoEncodingTheora) &&
+                 fuchsia::media::kVideoEncodingTheora) &&
          !strcmp(media_player::StreamType::kVideoEncodingUncompressed,
-                 media::kVideoEncodingUncompressed) &&
+                 fuchsia::media::kVideoEncodingUncompressed) &&
          !strcmp(media_player::StreamType::kVideoEncodingVp3,
-                 media::kVideoEncodingVp3) &&
+                 fuchsia::media::kVideoEncodingVp3) &&
          !strcmp(media_player::StreamType::kVideoEncodingVp8,
-                 media::kVideoEncodingVp8) &&
+                 fuchsia::media::kVideoEncodingVp8) &&
          !strcmp(media_player::StreamType::kVideoEncodingVp9,
-                 media::kVideoEncodingVp9);
+                 fuchsia::media::kVideoEncodingVp9);
 }
 
 }  // namespace
 
 media_player::Result
-TypeConverter<media_player::Result, media::MediaResult>::Convert(
-    media::MediaResult media_result) {
+TypeConverter<media_player::Result, fuchsia::media::MediaResult>::Convert(
+    fuchsia::media::MediaResult media_result) {
   switch (media_result) {
-    case media::MediaResult::OK:
+    case fuchsia::media::MediaResult::OK:
       return media_player::Result::kOk;
-    case media::MediaResult::INTERNAL_ERROR:
+    case fuchsia::media::MediaResult::INTERNAL_ERROR:
       return media_player::Result::kInternalError;
-    case media::MediaResult::UNSUPPORTED_OPERATION:
-    case media::MediaResult::NOT_IMPLEMENTED:
+    case fuchsia::media::MediaResult::UNSUPPORTED_OPERATION:
+    case fuchsia::media::MediaResult::NOT_IMPLEMENTED:
       return media_player::Result::kUnsupportedOperation;
-    case media::MediaResult::INVALID_ARGUMENT:
+    case fuchsia::media::MediaResult::INVALID_ARGUMENT:
       return media_player::Result::kInvalidArgument;
-    case media::MediaResult::NOT_FOUND:
+    case fuchsia::media::MediaResult::NOT_FOUND:
       return media_player::Result::kNotFound;
-    case media::MediaResult::UNKNOWN_ERROR:
-    case media::MediaResult::UNSUPPORTED_CONFIG:
-    case media::MediaResult::INSUFFICIENT_RESOURCES:
-    case media::MediaResult::BAD_STATE:
-    case media::MediaResult::BUF_OVERFLOW:
-    case media::MediaResult::FLUSHED:
-    case media::MediaResult::BUSY:
-    case media::MediaResult::PROTOCOL_ERROR:
-    case media::MediaResult::ALREADY_EXISTS:
-    case media::MediaResult::SHUTTING_DOWN:
-    case media::MediaResult::CONNECTION_LOST:
+    case fuchsia::media::MediaResult::UNKNOWN_ERROR:
+    case fuchsia::media::MediaResult::UNSUPPORTED_CONFIG:
+    case fuchsia::media::MediaResult::INSUFFICIENT_RESOURCES:
+    case fuchsia::media::MediaResult::BAD_STATE:
+    case fuchsia::media::MediaResult::BUF_OVERFLOW:
+    case fuchsia::media::MediaResult::FLUSHED:
+    case fuchsia::media::MediaResult::BUSY:
+    case fuchsia::media::MediaResult::PROTOCOL_ERROR:
+    case fuchsia::media::MediaResult::ALREADY_EXISTS:
+    case fuchsia::media::MediaResult::SHUTTING_DOWN:
+    case fuchsia::media::MediaResult::CONNECTION_LOST:
       break;
   }
 
@@ -91,15 +88,16 @@
 
 media_player::StreamType::Medium TypeConverter<
     media_player::StreamType::Medium,
-    media::MediaTypeMedium>::Convert(media::MediaTypeMedium media_type_medium) {
+    fuchsia::media::MediaTypeMedium>::Convert(fuchsia::media::MediaTypeMedium
+                                                  media_type_medium) {
   switch (media_type_medium) {
-    case media::MediaTypeMedium::AUDIO:
+    case fuchsia::media::MediaTypeMedium::AUDIO:
       return media_player::StreamType::Medium::kAudio;
-    case media::MediaTypeMedium::VIDEO:
+    case fuchsia::media::MediaTypeMedium::VIDEO:
       return media_player::StreamType::Medium::kVideo;
-    case media::MediaTypeMedium::TEXT:
+    case fuchsia::media::MediaTypeMedium::TEXT:
       return media_player::StreamType::Medium::kText;
-    case media::MediaTypeMedium::SUBPICTURE:
+    case fuchsia::media::MediaTypeMedium::SUBPICTURE:
       return media_player::StreamType::Medium::kSubpicture;
   }
 
@@ -109,20 +107,20 @@
 
 media_player::AudioStreamType::SampleFormat
 TypeConverter<media_player::AudioStreamType::SampleFormat,
-              media::AudioSampleFormat>::Convert(media::AudioSampleFormat
-                                                     audio_sample_format) {
+              fuchsia::media::AudioSampleFormat>::
+    Convert(fuchsia::media::AudioSampleFormat audio_sample_format) {
   switch (audio_sample_format) {
-    case media::AudioSampleFormat::NONE:
+    case fuchsia::media::AudioSampleFormat::NONE:
       return media_player::AudioStreamType::SampleFormat::kNone;
-    case media::AudioSampleFormat::ANY:
+    case fuchsia::media::AudioSampleFormat::ANY:
       return media_player::AudioStreamType::SampleFormat::kAny;
-    case media::AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return media_player::AudioStreamType::SampleFormat::kUnsigned8;
-    case media::AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return media_player::AudioStreamType::SampleFormat::kSigned16;
-    case media::AudioSampleFormat::SIGNED_24_IN_32:
+    case fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32:
       return media_player::AudioStreamType::SampleFormat::kSigned24In32;
-    case media::AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return media_player::AudioStreamType::SampleFormat::kFloat;
   }
 
@@ -130,36 +128,37 @@
   abort();
 }
 
-media_player::VideoStreamType::VideoProfile
-TypeConverter<media_player::VideoStreamType::VideoProfile,
-              media::VideoProfile>::Convert(media::VideoProfile video_profile) {
+media_player::VideoStreamType::VideoProfile TypeConverter<
+    media_player::VideoStreamType::VideoProfile,
+    fuchsia::media::VideoProfile>::Convert(fuchsia::media::VideoProfile
+                                               video_profile) {
   switch (video_profile) {
-    case media::VideoProfile::UNKNOWN:
+    case fuchsia::media::VideoProfile::UNKNOWN:
       return media_player::VideoStreamType::VideoProfile::kUnknown;
-    case media::VideoProfile::NOT_APPLICABLE:
+    case fuchsia::media::VideoProfile::NOT_APPLICABLE:
       return media_player::VideoStreamType::VideoProfile::kNotApplicable;
-    case media::VideoProfile::H264_BASELINE:
+    case fuchsia::media::VideoProfile::H264_BASELINE:
       return media_player::VideoStreamType::VideoProfile::kH264Baseline;
-    case media::VideoProfile::H264_MAIN:
+    case fuchsia::media::VideoProfile::H264_MAIN:
       return media_player::VideoStreamType::VideoProfile::kH264Main;
-    case media::VideoProfile::H264_EXTENDED:
+    case fuchsia::media::VideoProfile::H264_EXTENDED:
       return media_player::VideoStreamType::VideoProfile::kH264Extended;
-    case media::VideoProfile::H264_HIGH:
+    case fuchsia::media::VideoProfile::H264_HIGH:
       return media_player::VideoStreamType::VideoProfile::kH264High;
-    case media::VideoProfile::H264_HIGH10:
+    case fuchsia::media::VideoProfile::H264_HIGH10:
       return media_player::VideoStreamType::VideoProfile::kH264High10;
-    case media::VideoProfile::H264_HIGH422:
+    case fuchsia::media::VideoProfile::H264_HIGH422:
       return media_player::VideoStreamType::VideoProfile::kH264High422;
-    case media::VideoProfile::H264_HIGH444_PREDICTIVE:
+    case fuchsia::media::VideoProfile::H264_HIGH444_PREDICTIVE:
       return media_player::VideoStreamType::VideoProfile::
           kH264High444Predictive;
-    case media::VideoProfile::H264_SCALABLE_BASELINE:
+    case fuchsia::media::VideoProfile::H264_SCALABLE_BASELINE:
       return media_player::VideoStreamType::VideoProfile::kH264ScalableBaseline;
-    case media::VideoProfile::H264_SCALABLE_HIGH:
+    case fuchsia::media::VideoProfile::H264_SCALABLE_HIGH:
       return media_player::VideoStreamType::VideoProfile::kH264ScalableHigh;
-    case media::VideoProfile::H264_STEREO_HIGH:
+    case fuchsia::media::VideoProfile::H264_STEREO_HIGH:
       return media_player::VideoStreamType::VideoProfile::kH264StereoHigh;
-    case media::VideoProfile::H264_MULTIVIEW_HIGH:
+    case fuchsia::media::VideoProfile::H264_MULTIVIEW_HIGH:
       return media_player::VideoStreamType::VideoProfile::kH264MultiviewHigh;
   }
 
@@ -169,39 +168,40 @@
 
 media_player::VideoStreamType::PixelFormat
 TypeConverter<media_player::VideoStreamType::PixelFormat,
-              media::PixelFormat>::Convert(media::PixelFormat pixel_format) {
+              fuchsia::media::PixelFormat>::Convert(fuchsia::media::PixelFormat
+                                                        pixel_format) {
   switch (pixel_format) {
-    case media::PixelFormat::UNKNOWN:
+    case fuchsia::media::PixelFormat::UNKNOWN:
       return media_player::VideoStreamType::PixelFormat::kUnknown;
-    case media::PixelFormat::I420:
+    case fuchsia::media::PixelFormat::I420:
       return media_player::VideoStreamType::PixelFormat::kI420;
-    case media::PixelFormat::YV12:
+    case fuchsia::media::PixelFormat::YV12:
       return media_player::VideoStreamType::PixelFormat::kYv12;
-    case media::PixelFormat::YV16:
+    case fuchsia::media::PixelFormat::YV16:
       return media_player::VideoStreamType::PixelFormat::kYv16;
-    case media::PixelFormat::YV12A:
+    case fuchsia::media::PixelFormat::YV12A:
       return media_player::VideoStreamType::PixelFormat::kYv12A;
-    case media::PixelFormat::YV24:
+    case fuchsia::media::PixelFormat::YV24:
       return media_player::VideoStreamType::PixelFormat::kYv24;
-    case media::PixelFormat::NV12:
+    case fuchsia::media::PixelFormat::NV12:
       return media_player::VideoStreamType::PixelFormat::kNv12;
-    case media::PixelFormat::NV21:
+    case fuchsia::media::PixelFormat::NV21:
       return media_player::VideoStreamType::PixelFormat::kNv21;
-    case media::PixelFormat::UYVY:
+    case fuchsia::media::PixelFormat::UYVY:
       return media_player::VideoStreamType::PixelFormat::kUyvy;
-    case media::PixelFormat::YUY2:
+    case fuchsia::media::PixelFormat::YUY2:
       return media_player::VideoStreamType::PixelFormat::kYuy2;
-    case media::PixelFormat::ARGB:
+    case fuchsia::media::PixelFormat::ARGB:
       return media_player::VideoStreamType::PixelFormat::kArgb;
-    case media::PixelFormat::XRGB:
+    case fuchsia::media::PixelFormat::XRGB:
       return media_player::VideoStreamType::PixelFormat::kXrgb;
-    case media::PixelFormat::RGB24:
+    case fuchsia::media::PixelFormat::RGB24:
       return media_player::VideoStreamType::PixelFormat::kRgb24;
-    case media::PixelFormat::RGB32:
+    case fuchsia::media::PixelFormat::RGB32:
       return media_player::VideoStreamType::PixelFormat::kRgb32;
-    case media::PixelFormat::MJPEG:
+    case fuchsia::media::PixelFormat::MJPEG:
       return media_player::VideoStreamType::PixelFormat::kMjpeg;
-    case media::PixelFormat::MT21:
+    case fuchsia::media::PixelFormat::MT21:
       return media_player::VideoStreamType::PixelFormat::kMt21;
   }
 
@@ -210,178 +210,180 @@
 
 media_player::VideoStreamType::ColorSpace
 TypeConverter<media_player::VideoStreamType::ColorSpace,
-              media::ColorSpace>::Convert(media::ColorSpace color_space) {
+              fuchsia::media::ColorSpace>::Convert(fuchsia::media::ColorSpace
+                                                       color_space) {
   switch (color_space) {
-    case media::ColorSpace::UNKNOWN:
+    case fuchsia::media::ColorSpace::UNKNOWN:
       return media_player::VideoStreamType::ColorSpace::kUnknown;
-    case media::ColorSpace::NOT_APPLICABLE:
+    case fuchsia::media::ColorSpace::NOT_APPLICABLE:
       return media_player::VideoStreamType::ColorSpace::kNotApplicable;
-    case media::ColorSpace::JPEG:
+    case fuchsia::media::ColorSpace::JPEG:
       return media_player::VideoStreamType::ColorSpace::kJpeg;
-    case media::ColorSpace::HD_REC709:
+    case fuchsia::media::ColorSpace::HD_REC709:
       return media_player::VideoStreamType::ColorSpace::kHdRec709;
-    case media::ColorSpace::SD_REC601:
+    case fuchsia::media::ColorSpace::SD_REC601:
       return media_player::VideoStreamType::ColorSpace::kSdRec601;
   }
 
   return media_player::VideoStreamType::ColorSpace::kUnknown;
 }
 
-media::MediaTypeMedium
-TypeConverter<media::MediaTypeMedium, media_player::StreamType::Medium>::
-    Convert(media_player::StreamType::Medium medium) {
+fuchsia::media::MediaTypeMedium TypeConverter<
+    fuchsia::media::MediaTypeMedium,
+    media_player::StreamType::Medium>::Convert(media_player::StreamType::Medium
+                                                   medium) {
   switch (medium) {
     case media_player::StreamType::Medium::kAudio:
-      return media::MediaTypeMedium::AUDIO;
+      return fuchsia::media::MediaTypeMedium::AUDIO;
     case media_player::StreamType::Medium::kVideo:
-      return media::MediaTypeMedium::VIDEO;
+      return fuchsia::media::MediaTypeMedium::VIDEO;
     case media_player::StreamType::Medium::kText:
-      return media::MediaTypeMedium::TEXT;
+      return fuchsia::media::MediaTypeMedium::TEXT;
     case media_player::StreamType::Medium::kSubpicture:
-      return media::MediaTypeMedium::SUBPICTURE;
+      return fuchsia::media::MediaTypeMedium::SUBPICTURE;
   }
 
   FXL_LOG(ERROR) << "unrecognized medium";
   abort();
 }
 
-media::AudioSampleFormat
-TypeConverter<media::AudioSampleFormat,
+fuchsia::media::AudioSampleFormat
+TypeConverter<fuchsia::media::AudioSampleFormat,
               media_player::AudioStreamType::SampleFormat>::
     Convert(media_player::AudioStreamType::SampleFormat sample_format) {
   switch (sample_format) {
     case media_player::AudioStreamType::SampleFormat::kNone:
-      return media::AudioSampleFormat::NONE;
+      return fuchsia::media::AudioSampleFormat::NONE;
     case media_player::AudioStreamType::SampleFormat::kAny:
-      return media::AudioSampleFormat::ANY;
+      return fuchsia::media::AudioSampleFormat::ANY;
     case media_player::AudioStreamType::SampleFormat::kUnsigned8:
-      return media::AudioSampleFormat::UNSIGNED_8;
+      return fuchsia::media::AudioSampleFormat::UNSIGNED_8;
     case media_player::AudioStreamType::SampleFormat::kSigned16:
-      return media::AudioSampleFormat::SIGNED_16;
+      return fuchsia::media::AudioSampleFormat::SIGNED_16;
     case media_player::AudioStreamType::SampleFormat::kSigned24In32:
-      return media::AudioSampleFormat::SIGNED_24_IN_32;
+      return fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32;
     case media_player::AudioStreamType::SampleFormat::kFloat:
-      return media::AudioSampleFormat::FLOAT;
+      return fuchsia::media::AudioSampleFormat::FLOAT;
   }
 
   FXL_LOG(ERROR) << "unrecognized sample format";
   abort();
 }
 
-media::VideoProfile TypeConverter<media::VideoProfile,
-                                  media_player::VideoStreamType::VideoProfile>::
+fuchsia::media::VideoProfile TypeConverter<
+    fuchsia::media::VideoProfile, media_player::VideoStreamType::VideoProfile>::
     Convert(media_player::VideoStreamType::VideoProfile video_profile) {
   switch (video_profile) {
     case media_player::VideoStreamType::VideoProfile::kUnknown:
-      return media::VideoProfile::UNKNOWN;
+      return fuchsia::media::VideoProfile::UNKNOWN;
     case media_player::VideoStreamType::VideoProfile::kNotApplicable:
-      return media::VideoProfile::NOT_APPLICABLE;
+      return fuchsia::media::VideoProfile::NOT_APPLICABLE;
     case media_player::VideoStreamType::VideoProfile::kH264Baseline:
-      return media::VideoProfile::H264_BASELINE;
+      return fuchsia::media::VideoProfile::H264_BASELINE;
     case media_player::VideoStreamType::VideoProfile::kH264Main:
-      return media::VideoProfile::H264_MAIN;
+      return fuchsia::media::VideoProfile::H264_MAIN;
     case media_player::VideoStreamType::VideoProfile::kH264Extended:
-      return media::VideoProfile::H264_EXTENDED;
+      return fuchsia::media::VideoProfile::H264_EXTENDED;
     case media_player::VideoStreamType::VideoProfile::kH264High:
-      return media::VideoProfile::H264_HIGH;
+      return fuchsia::media::VideoProfile::H264_HIGH;
     case media_player::VideoStreamType::VideoProfile::kH264High10:
-      return media::VideoProfile::H264_HIGH10;
+      return fuchsia::media::VideoProfile::H264_HIGH10;
     case media_player::VideoStreamType::VideoProfile::kH264High422:
-      return media::VideoProfile::H264_HIGH422;
+      return fuchsia::media::VideoProfile::H264_HIGH422;
     case media_player::VideoStreamType::VideoProfile::kH264High444Predictive:
-      return media::VideoProfile::H264_HIGH444_PREDICTIVE;
+      return fuchsia::media::VideoProfile::H264_HIGH444_PREDICTIVE;
     case media_player::VideoStreamType::VideoProfile::kH264ScalableBaseline:
-      return media::VideoProfile::H264_SCALABLE_BASELINE;
+      return fuchsia::media::VideoProfile::H264_SCALABLE_BASELINE;
     case media_player::VideoStreamType::VideoProfile::kH264ScalableHigh:
-      return media::VideoProfile::H264_SCALABLE_HIGH;
+      return fuchsia::media::VideoProfile::H264_SCALABLE_HIGH;
     case media_player::VideoStreamType::VideoProfile::kH264StereoHigh:
-      return media::VideoProfile::H264_STEREO_HIGH;
+      return fuchsia::media::VideoProfile::H264_STEREO_HIGH;
     case media_player::VideoStreamType::VideoProfile::kH264MultiviewHigh:
-      return media::VideoProfile::H264_MULTIVIEW_HIGH;
+      return fuchsia::media::VideoProfile::H264_MULTIVIEW_HIGH;
   }
 
   FXL_LOG(ERROR) << "unrecognized video profile";
   abort();
 }
 
-media::PixelFormat
-TypeConverter<media::PixelFormat, media_player::VideoStreamType::PixelFormat>::
+fuchsia::media::PixelFormat TypeConverter<
+    fuchsia::media::PixelFormat, media_player::VideoStreamType::PixelFormat>::
     Convert(media_player::VideoStreamType::PixelFormat pixel_format) {
   switch (pixel_format) {
     case media_player::VideoStreamType::PixelFormat::kUnknown:
-      return media::PixelFormat::UNKNOWN;
+      return fuchsia::media::PixelFormat::UNKNOWN;
     case media_player::VideoStreamType::PixelFormat::kI420:
-      return media::PixelFormat::I420;
+      return fuchsia::media::PixelFormat::I420;
     case media_player::VideoStreamType::PixelFormat::kYv12:
-      return media::PixelFormat::YV12;
+      return fuchsia::media::PixelFormat::YV12;
     case media_player::VideoStreamType::PixelFormat::kYv16:
-      return media::PixelFormat::YV16;
+      return fuchsia::media::PixelFormat::YV16;
     case media_player::VideoStreamType::PixelFormat::kYv12A:
-      return media::PixelFormat::YV12A;
+      return fuchsia::media::PixelFormat::YV12A;
     case media_player::VideoStreamType::PixelFormat::kYv24:
-      return media::PixelFormat::YV24;
+      return fuchsia::media::PixelFormat::YV24;
     case media_player::VideoStreamType::PixelFormat::kNv12:
-      return media::PixelFormat::NV12;
+      return fuchsia::media::PixelFormat::NV12;
     case media_player::VideoStreamType::PixelFormat::kNv21:
-      return media::PixelFormat::NV21;
+      return fuchsia::media::PixelFormat::NV21;
     case media_player::VideoStreamType::PixelFormat::kUyvy:
-      return media::PixelFormat::UYVY;
+      return fuchsia::media::PixelFormat::UYVY;
     case media_player::VideoStreamType::PixelFormat::kYuy2:
-      return media::PixelFormat::YUY2;
+      return fuchsia::media::PixelFormat::YUY2;
     case media_player::VideoStreamType::PixelFormat::kArgb:
-      return media::PixelFormat::ARGB;
+      return fuchsia::media::PixelFormat::ARGB;
     case media_player::VideoStreamType::PixelFormat::kXrgb:
-      return media::PixelFormat::XRGB;
+      return fuchsia::media::PixelFormat::XRGB;
     case media_player::VideoStreamType::PixelFormat::kRgb24:
-      return media::PixelFormat::RGB24;
+      return fuchsia::media::PixelFormat::RGB24;
     case media_player::VideoStreamType::PixelFormat::kRgb32:
-      return media::PixelFormat::RGB32;
+      return fuchsia::media::PixelFormat::RGB32;
     case media_player::VideoStreamType::PixelFormat::kMjpeg:
-      return media::PixelFormat::MJPEG;
+      return fuchsia::media::PixelFormat::MJPEG;
     case media_player::VideoStreamType::PixelFormat::kMt21:
-      return media::PixelFormat::MT21;
+      return fuchsia::media::PixelFormat::MT21;
   }
 
   FXL_LOG(ERROR) << "unrecognized pixel format";
   abort();
 }
 
-media::ColorSpace
-TypeConverter<media::ColorSpace, media_player::VideoStreamType::ColorSpace>::
+fuchsia::media::ColorSpace TypeConverter<
+    fuchsia::media::ColorSpace, media_player::VideoStreamType::ColorSpace>::
     Convert(media_player::VideoStreamType::ColorSpace color_space) {
   switch (color_space) {
     case media_player::VideoStreamType::ColorSpace::kUnknown:
-      return media::ColorSpace::UNKNOWN;
+      return fuchsia::media::ColorSpace::UNKNOWN;
     case media_player::VideoStreamType::ColorSpace::kNotApplicable:
-      return media::ColorSpace::NOT_APPLICABLE;
+      return fuchsia::media::ColorSpace::NOT_APPLICABLE;
     case media_player::VideoStreamType::ColorSpace::kJpeg:
-      return media::ColorSpace::JPEG;
+      return fuchsia::media::ColorSpace::JPEG;
     case media_player::VideoStreamType::ColorSpace::kHdRec709:
-      return media::ColorSpace::HD_REC709;
+      return fuchsia::media::ColorSpace::HD_REC709;
     case media_player::VideoStreamType::ColorSpace::kSdRec601:
-      return media::ColorSpace::SD_REC601;
+      return fuchsia::media::ColorSpace::SD_REC601;
   }
 
   FXL_LOG(ERROR) << "unrecognized color space";
   abort();
 }
 
-media::MediaType
-TypeConverter<media::MediaType, media_player::StreamType>::Convert(
+fuchsia::media::MediaType
+TypeConverter<fuchsia::media::MediaType, media_player::StreamType>::Convert(
     const media_player::StreamType& input) {
   FXL_DCHECK(KnownEncodingsMatch());
 
   switch (input.medium()) {
     case media_player::StreamType::Medium::kAudio: {
-      media::AudioMediaTypeDetails audio_details;
+      fuchsia::media::AudioMediaTypeDetails audio_details;
       audio_details.sample_format =
-          To<media::AudioSampleFormat>(input.audio()->sample_format());
+          To<fuchsia::media::AudioSampleFormat>(input.audio()->sample_format());
       audio_details.channels = input.audio()->channels();
       audio_details.frames_per_second = input.audio()->frames_per_second();
-      media::MediaTypeDetails details;
+      fuchsia::media::MediaTypeDetails details;
       details.set_audio(std::move(audio_details));
-      media::MediaType media_type;
-      media_type.medium = media::MediaTypeMedium::AUDIO;
+      fuchsia::media::MediaType media_type;
+      media_type.medium = fuchsia::media::MediaTypeMedium::AUDIO;
       media_type.details = std::move(details);
       media_type.encoding = input.encoding();
       media_type.encoding_parameters =
@@ -389,12 +391,13 @@
       return media_type;
     }
     case media_player::StreamType::Medium::kVideo: {
-      media::VideoMediaTypeDetails video_details;
-      video_details.profile = To<media::VideoProfile>(input.video()->profile());
+      fuchsia::media::VideoMediaTypeDetails video_details;
+      video_details.profile =
+          To<fuchsia::media::VideoProfile>(input.video()->profile());
       video_details.pixel_format =
-          To<media::PixelFormat>(input.video()->pixel_format());
+          To<fuchsia::media::PixelFormat>(input.video()->pixel_format());
       video_details.color_space =
-          To<media::ColorSpace>(input.video()->color_space());
+          To<fuchsia::media::ColorSpace>(input.video()->color_space());
       video_details.width = input.video()->width();
       video_details.height = input.video()->height();
       video_details.coded_width = input.video()->coded_width();
@@ -407,10 +410,10 @@
           To<fidl::VectorPtr<uint32_t>>(input.video()->line_stride());
       video_details.plane_offset =
           To<fidl::VectorPtr<uint32_t>>(input.video()->plane_offset());
-      media::MediaTypeDetails details;
+      fuchsia::media::MediaTypeDetails details;
       details.set_video(std::move(video_details));
-      media::MediaType media_type;
-      media_type.medium = media::MediaTypeMedium::VIDEO;
+      fuchsia::media::MediaType media_type;
+      media_type.medium = fuchsia::media::MediaTypeMedium::VIDEO;
       media_type.details = std::move(details);
       media_type.encoding = input.encoding();
       media_type.encoding_parameters =
@@ -418,10 +421,10 @@
       return media_type;
     }
     case media_player::StreamType::Medium::kText: {
-      media::MediaTypeDetails details;
-      details.set_text(media::TextMediaTypeDetails());
-      media::MediaType media_type;
-      media_type.medium = media::MediaTypeMedium::TEXT;
+      fuchsia::media::MediaTypeDetails details;
+      details.set_text(fuchsia::media::TextMediaTypeDetails());
+      fuchsia::media::MediaType media_type;
+      media_type.medium = fuchsia::media::MediaTypeMedium::TEXT;
       media_type.details = std::move(details);
       media_type.encoding = input.encoding();
       media_type.encoding_parameters =
@@ -429,10 +432,10 @@
       return media_type;
     }
     case media_player::StreamType::Medium::kSubpicture: {
-      media::MediaTypeDetails details;
-      details.set_subpicture(media::SubpictureMediaTypeDetails());
-      media::MediaType media_type;
-      media_type.medium = media::MediaTypeMedium::SUBPICTURE;
+      fuchsia::media::MediaTypeDetails details;
+      details.set_subpicture(fuchsia::media::SubpictureMediaTypeDetails());
+      fuchsia::media::MediaType media_type;
+      media_type.medium = fuchsia::media::MediaTypeMedium::SUBPICTURE;
       media_type.details = std::move(details);
       media_type.encoding = input.encoding();
       media_type.encoding_parameters =
@@ -445,13 +448,14 @@
   abort();
 }
 
-std::unique_ptr<media_player::StreamType>
-TypeConverter<std::unique_ptr<media_player::StreamType>,
-              media::MediaType>::Convert(const media::MediaType& input) {
+std::unique_ptr<media_player::StreamType> TypeConverter<
+    std::unique_ptr<media_player::StreamType>,
+    fuchsia::media::MediaType>::Convert(const fuchsia::media::MediaType&
+                                            input) {
   FXL_DCHECK(KnownEncodingsMatch());
 
   switch (input.medium) {
-    case media::MediaTypeMedium::AUDIO:
+    case fuchsia::media::MediaTypeMedium::AUDIO:
       return media_player::AudioStreamType::Create(
           input.encoding,
           To<std::unique_ptr<media_player::Bytes>>(input.encoding_parameters),
@@ -459,7 +463,7 @@
               input.details.audio().sample_format),
           input.details.audio().channels,
           input.details.audio().frames_per_second);
-    case media::MediaTypeMedium::VIDEO:
+    case fuchsia::media::MediaTypeMedium::VIDEO:
       return media_player::VideoStreamType::Create(
           input.encoding,
           To<std::unique_ptr<media_player::Bytes>>(input.encoding_parameters),
@@ -475,11 +479,11 @@
           input.details.video().pixel_aspect_ratio_height,
           input.details.video().line_stride,
           input.details.video().plane_offset);
-    case media::MediaTypeMedium::TEXT:
+    case fuchsia::media::MediaTypeMedium::TEXT:
       return media_player::TextStreamType::Create(
           input.encoding,
           To<std::unique_ptr<media_player::Bytes>>(input.encoding_parameters));
-    case media::MediaTypeMedium::SUBPICTURE:
+    case fuchsia::media::MediaTypeMedium::SUBPICTURE:
       return media_player::SubpictureStreamType::Create(
           input.encoding,
           To<std::unique_ptr<media_player::Bytes>>(input.encoding_parameters));
@@ -488,66 +492,66 @@
   return nullptr;
 }
 
-media::MediaTypeSet
-TypeConverter<media::MediaTypeSet,
+fuchsia::media::MediaTypeSet
+TypeConverter<fuchsia::media::MediaTypeSet,
               std::unique_ptr<media_player::StreamTypeSet>>::
     Convert(const std::unique_ptr<media_player::StreamTypeSet>& input) {
   FXL_DCHECK(KnownEncodingsMatch());
 
   if (input == nullptr) {
-    return media::MediaTypeSet();
+    return fuchsia::media::MediaTypeSet();
   }
 
   switch (input->medium()) {
     case media_player::StreamType::Medium::kAudio: {
-      media::AudioMediaTypeSetDetails audio_details;
-      audio_details.sample_format =
-          To<media::AudioSampleFormat>(input->audio()->sample_format());
+      fuchsia::media::AudioMediaTypeSetDetails audio_details;
+      audio_details.sample_format = To<fuchsia::media::AudioSampleFormat>(
+          input->audio()->sample_format());
       audio_details.min_channels = input->audio()->channels().min;
       audio_details.max_channels = input->audio()->channels().max;
       audio_details.min_frames_per_second =
           input->audio()->frames_per_second().min;
       audio_details.max_frames_per_second =
           input->audio()->frames_per_second().max;
-      media::MediaTypeSetDetails details;
+      fuchsia::media::MediaTypeSetDetails details;
       details.set_audio(std::move(audio_details));
-      media::MediaTypeSet media_type_set;
-      media_type_set.medium = media::MediaTypeMedium::AUDIO;
+      fuchsia::media::MediaTypeSet media_type_set;
+      media_type_set.medium = fuchsia::media::MediaTypeMedium::AUDIO;
       media_type_set.details = std::move(details);
       media_type_set.encodings =
           To<fidl::VectorPtr<fidl::StringPtr>>(input->encodings());
       return media_type_set;
     }
     case media_player::StreamType::Medium::kVideo: {
-      media::VideoMediaTypeSetDetails video_details;
+      fuchsia::media::VideoMediaTypeSetDetails video_details;
       video_details.min_width = input->video()->width().min;
       video_details.max_width = input->video()->width().max;
       video_details.min_height = input->video()->height().min;
       video_details.max_height = input->video()->height().max;
-      media::MediaTypeSetDetails details;
+      fuchsia::media::MediaTypeSetDetails details;
       details.set_video(std::move(video_details));
-      media::MediaTypeSet media_type_set;
-      media_type_set.medium = media::MediaTypeMedium::VIDEO;
+      fuchsia::media::MediaTypeSet media_type_set;
+      media_type_set.medium = fuchsia::media::MediaTypeMedium::VIDEO;
       media_type_set.details = std::move(details);
       media_type_set.encodings =
           To<fidl::VectorPtr<fidl::StringPtr>>(input->encodings());
       return media_type_set;
     }
     case media_player::StreamType::Medium::kText: {
-      media::MediaTypeSetDetails details;
-      details.set_text(media::TextMediaTypeSetDetails());
-      media::MediaTypeSet media_type_set;
-      media_type_set.medium = media::MediaTypeMedium::TEXT;
+      fuchsia::media::MediaTypeSetDetails details;
+      details.set_text(fuchsia::media::TextMediaTypeSetDetails());
+      fuchsia::media::MediaTypeSet media_type_set;
+      media_type_set.medium = fuchsia::media::MediaTypeMedium::TEXT;
       media_type_set.details = std::move(details);
       media_type_set.encodings =
           To<fidl::VectorPtr<fidl::StringPtr>>(input->encodings());
       return media_type_set;
     }
     case media_player::StreamType::Medium::kSubpicture: {
-      media::MediaTypeSetDetails details;
-      details.set_subpicture(media::SubpictureMediaTypeSetDetails());
-      media::MediaTypeSet media_type_set;
-      media_type_set.medium = media::MediaTypeMedium::SUBPICTURE;
+      fuchsia::media::MediaTypeSetDetails details;
+      details.set_subpicture(fuchsia::media::SubpictureMediaTypeSetDetails());
+      fuchsia::media::MediaTypeSet media_type_set;
+      media_type_set.medium = fuchsia::media::MediaTypeMedium::SUBPICTURE;
       media_type_set.details = std::move(details);
       media_type_set.encodings =
           To<fidl::VectorPtr<fidl::StringPtr>>(input->encodings());
@@ -559,13 +563,14 @@
   abort();
 }
 
-std::unique_ptr<media_player::StreamTypeSet>
-TypeConverter<std::unique_ptr<media_player::StreamTypeSet>,
-              media::MediaTypeSet>::Convert(const media::MediaTypeSet& input) {
+std::unique_ptr<media_player::StreamTypeSet> TypeConverter<
+    std::unique_ptr<media_player::StreamTypeSet>,
+    fuchsia::media::MediaTypeSet>::Convert(const fuchsia::media::MediaTypeSet&
+                                               input) {
   FXL_DCHECK(KnownEncodingsMatch());
 
   switch (input.medium) {
-    case media::MediaTypeMedium::AUDIO:
+    case fuchsia::media::MediaTypeMedium::AUDIO:
       return media_player::AudioStreamTypeSet::Create(
           To<std::vector<std::string>>(input.encodings),
           To<media_player::AudioStreamType::SampleFormat>(
@@ -575,17 +580,17 @@
           media_player::Range<uint32_t>(
               input.details.audio().min_frames_per_second,
               input.details.audio().max_frames_per_second));
-    case media::MediaTypeMedium::VIDEO:
+    case fuchsia::media::MediaTypeMedium::VIDEO:
       return media_player::VideoStreamTypeSet::Create(
           To<std::vector<std::string>>(input.encodings),
           media_player::Range<uint32_t>(input.details.video().min_width,
                                         input.details.video().max_width),
           media_player::Range<uint32_t>(input.details.video().min_height,
                                         input.details.video().max_height));
-    case media::MediaTypeMedium::TEXT:
+    case fuchsia::media::MediaTypeMedium::TEXT:
       return media_player::TextStreamTypeSet::Create(
           To<std::vector<std::string>>(input.encodings));
-    case media::MediaTypeMedium::SUBPICTURE:
+    case fuchsia::media::MediaTypeMedium::SUBPICTURE:
       return media_player::SubpictureStreamTypeSet::Create(
           To<std::vector<std::string>>(input.encodings));
   }
@@ -593,22 +598,28 @@
   return nullptr;
 }
 
-MediaMetadataPtr
-TypeConverter<MediaMetadataPtr, std::unique_ptr<media_player::Metadata>>::
+fuchsia::mediaplayer::MediaMetadataPtr
+TypeConverter<fuchsia::mediaplayer::MediaMetadataPtr,
+              std::unique_ptr<media_player::Metadata>>::
     Convert(const std::unique_ptr<media_player::Metadata>& input) {
-  return input == nullptr ? nullptr : fxl::To<MediaMetadataPtr>(*input);
+  return input == nullptr
+             ? nullptr
+             : fxl::To<fuchsia::mediaplayer::MediaMetadataPtr>(*input);
 }
 
-MediaMetadataPtr
-TypeConverter<MediaMetadataPtr, const media_player::Metadata*>::Convert(
-    const media_player::Metadata* input) {
-  return input == nullptr ? nullptr : fxl::To<MediaMetadataPtr>(*input);
+fuchsia::mediaplayer::MediaMetadataPtr TypeConverter<
+    fuchsia::mediaplayer::MediaMetadataPtr,
+    const media_player::Metadata*>::Convert(const media_player::Metadata*
+                                                input) {
+  return input == nullptr
+             ? nullptr
+             : fxl::To<fuchsia::mediaplayer::MediaMetadataPtr>(*input);
 }
 
-MediaMetadataPtr
-TypeConverter<MediaMetadataPtr, media_player::Metadata>::Convert(
-    const media_player::Metadata& input) {
-  auto result = media_player::MediaMetadata::New();
+fuchsia::mediaplayer::MediaMetadataPtr TypeConverter<
+    fuchsia::mediaplayer::MediaMetadataPtr,
+    media_player::Metadata>::Convert(const media_player::Metadata& input) {
+  auto result = fuchsia::mediaplayer::MediaMetadata::New();
   result->duration = input.duration_ns();
   result->title = input.title().empty() ? fidl::StringPtr()
                                         : fidl::StringPtr(input.title());
@@ -629,7 +640,8 @@
 
 std::unique_ptr<media_player::Metadata>
 TypeConverter<std::unique_ptr<media_player::Metadata>,
-              MediaMetadataPtr>::Convert(const MediaMetadataPtr& input) {
+              fuchsia::mediaplayer::MediaMetadataPtr>::
+    Convert(const fuchsia::mediaplayer::MediaMetadataPtr& input) {
   if (!input) {
     return nullptr;
   }
diff --git a/bin/media/media_player/fidl/fidl_type_conversions.h b/bin/media/media_player/fidl/fidl_type_conversions.h
index e6d3375..57d4670 100644
--- a/bin/media/media_player/fidl/fidl_type_conversions.h
+++ b/bin/media/media_player/fidl/fidl_type_conversions.h
@@ -5,8 +5,8 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_FIDL_FIDL_TYPE_CONVERSIONS_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_FIDL_FIDL_TYPE_CONVERSIONS_H_
 
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 
 #include "garnet/bin/media/media_player/framework/metadata.h"
 #include "garnet/bin/media/media_player/framework/result.h"
@@ -20,116 +20,119 @@
 namespace fxl {
 
 template <>
-struct TypeConverter<media_player::Result, media::MediaResult> {
-  static media_player::Result Convert(media::MediaResult media_result);
+struct TypeConverter<media_player::Result, fuchsia::media::MediaResult> {
+  static media_player::Result Convert(fuchsia::media::MediaResult media_result);
 };
 
 template <>
-struct TypeConverter<media_player::StreamType::Medium, media::MediaTypeMedium> {
+struct TypeConverter<media_player::StreamType::Medium,
+                     fuchsia::media::MediaTypeMedium> {
   static media_player::StreamType::Medium Convert(
-      media::MediaTypeMedium media_type_medium);
+      fuchsia::media::MediaTypeMedium media_type_medium);
 };
 
 template <>
 struct TypeConverter<media_player::AudioStreamType::SampleFormat,
-                     media::AudioSampleFormat> {
+                     fuchsia::media::AudioSampleFormat> {
   static media_player::AudioStreamType::SampleFormat Convert(
-      media::AudioSampleFormat audio_sample_format);
+      fuchsia::media::AudioSampleFormat audio_sample_format);
 };
 
 template <>
 struct TypeConverter<media_player::VideoStreamType::VideoProfile,
-                     media::VideoProfile> {
+                     fuchsia::media::VideoProfile> {
   static media_player::VideoStreamType::VideoProfile Convert(
-      media::VideoProfile video_profile);
+      fuchsia::media::VideoProfile video_profile);
 };
 
 template <>
 struct TypeConverter<media_player::VideoStreamType::PixelFormat,
-                     media::PixelFormat> {
+                     fuchsia::media::PixelFormat> {
   static media_player::VideoStreamType::PixelFormat Convert(
-      media::PixelFormat pixel_format);
+      fuchsia::media::PixelFormat pixel_format);
 };
 
 template <>
 struct TypeConverter<media_player::VideoStreamType::ColorSpace,
-                     media::ColorSpace> {
+                     fuchsia::media::ColorSpace> {
   static media_player::VideoStreamType::ColorSpace Convert(
-      media::ColorSpace color_space);
+      fuchsia::media::ColorSpace color_space);
 };
 
 template <>
-struct TypeConverter<media::MediaTypeMedium, media_player::StreamType::Medium> {
-  static media::MediaTypeMedium Convert(
+struct TypeConverter<fuchsia::media::MediaTypeMedium,
+                     media_player::StreamType::Medium> {
+  static fuchsia::media::MediaTypeMedium Convert(
       media_player::StreamType::Medium medium);
 };
 
 template <>
-struct TypeConverter<media::AudioSampleFormat,
+struct TypeConverter<fuchsia::media::AudioSampleFormat,
                      media_player::AudioStreamType::SampleFormat> {
-  static media::AudioSampleFormat Convert(
+  static fuchsia::media::AudioSampleFormat Convert(
       media_player::AudioStreamType::SampleFormat sample_format);
 };
 
 template <>
-struct TypeConverter<media::VideoProfile,
+struct TypeConverter<fuchsia::media::VideoProfile,
                      media_player::VideoStreamType::VideoProfile> {
-  static media::VideoProfile Convert(
+  static fuchsia::media::VideoProfile Convert(
       media_player::VideoStreamType::VideoProfile video_profile);
 };
 
 template <>
-struct TypeConverter<media::PixelFormat,
+struct TypeConverter<fuchsia::media::PixelFormat,
                      media_player::VideoStreamType::PixelFormat> {
-  static media::PixelFormat Convert(
+  static fuchsia::media::PixelFormat Convert(
       media_player::VideoStreamType::PixelFormat pixel_format);
 };
 
 template <>
-struct TypeConverter<media::ColorSpace,
+struct TypeConverter<fuchsia::media::ColorSpace,
                      media_player::VideoStreamType::ColorSpace> {
-  static media::ColorSpace Convert(
+  static fuchsia::media::ColorSpace Convert(
       media_player::VideoStreamType::ColorSpace color_space);
 };
 
 template <>
-struct TypeConverter<media::MediaType, media_player::StreamType> {
-  static media::MediaType Convert(const media_player::StreamType& input);
+struct TypeConverter<fuchsia::media::MediaType, media_player::StreamType> {
+  static fuchsia::media::MediaType Convert(
+      const media_player::StreamType& input);
 };
 
 template <>
-struct TypeConverter<media::MediaType,
+struct TypeConverter<fuchsia::media::MediaType,
                      std::unique_ptr<media_player::StreamType>> {
-  static media::MediaType Convert(
+  static fuchsia::media::MediaType Convert(
       const std::unique_ptr<media_player::StreamType>& input) {
     FXL_DCHECK(input);
-    return fxl::To<media::MediaType>(*input);
+    return fxl::To<fuchsia::media::MediaType>(*input);
   }
 };
 
 template <>
-struct TypeConverter<media::MediaTypePtr,
+struct TypeConverter<fuchsia::media::MediaTypePtr,
                      std::unique_ptr<media_player::StreamType>> {
-  static media::MediaTypePtr Convert(
+  static fuchsia::media::MediaTypePtr Convert(
       const std::unique_ptr<media_player::StreamType>& input) {
     if (!input)
       return nullptr;
-    return fidl::MakeOptional(fxl::To<media::MediaType>(*input));
+    return fidl::MakeOptional(fxl::To<fuchsia::media::MediaType>(*input));
   }
 };
 
 template <>
 struct TypeConverter<std::unique_ptr<media_player::StreamType>,
-                     media::MediaType> {
+                     fuchsia::media::MediaType> {
   static std::unique_ptr<media_player::StreamType> Convert(
-      const media::MediaType& input);
+      const fuchsia::media::MediaType& input);
 };
 
 template <>
 struct TypeConverter<std::unique_ptr<media_player::StreamType>,
-                     media::MediaTypePtr> {
+                     fuchsia::media::MediaTypePtr> {
   static std::unique_ptr<media_player::StreamType> Convert(
-      const media::MediaTypePtr& input) {
+      const fuchsia::media::MediaTypePtr& input) {
     if (!input)
       return nullptr;
     return To<std::unique_ptr<media_player::StreamType>>(*input);
@@ -137,44 +140,45 @@
 };
 
 template <>
-struct TypeConverter<media::MediaTypeSet,
+struct TypeConverter<fuchsia::media::MediaTypeSet,
                      std::unique_ptr<media_player::StreamTypeSet>> {
-  static media::MediaTypeSet Convert(
+  static fuchsia::media::MediaTypeSet Convert(
       const std::unique_ptr<media_player::StreamTypeSet>& input);
 };
 
 template <>
 struct TypeConverter<std::unique_ptr<media_player::StreamTypeSet>,
-                     media::MediaTypeSet> {
+                     fuchsia::media::MediaTypeSet> {
   static std::unique_ptr<media_player::StreamTypeSet> Convert(
-      const media::MediaTypeSet& input);
+      const fuchsia::media::MediaTypeSet& input);
 };
 
 template <>
-struct TypeConverter<media_player::MediaMetadataPtr,
+struct TypeConverter<fuchsia::mediaplayer::MediaMetadataPtr,
                      std::unique_ptr<media_player::Metadata>> {
-  static media_player::MediaMetadataPtr Convert(
+  static fuchsia::mediaplayer::MediaMetadataPtr Convert(
       const std::unique_ptr<media_player::Metadata>& input);
 };
 
 template <>
-struct TypeConverter<media_player::MediaMetadataPtr,
+struct TypeConverter<fuchsia::mediaplayer::MediaMetadataPtr,
                      const media_player::Metadata*> {
-  static media_player::MediaMetadataPtr Convert(
+  static fuchsia::mediaplayer::MediaMetadataPtr Convert(
       const media_player::Metadata* input);
 };
 
 template <>
-struct TypeConverter<media_player::MediaMetadataPtr, media_player::Metadata> {
-  static media_player::MediaMetadataPtr Convert(
+struct TypeConverter<fuchsia::mediaplayer::MediaMetadataPtr,
+                     media_player::Metadata> {
+  static fuchsia::mediaplayer::MediaMetadataPtr Convert(
       const media_player::Metadata& input);
 };
 
 template <>
 struct TypeConverter<std::unique_ptr<media_player::Metadata>,
-                     media_player::MediaMetadataPtr> {
+                     fuchsia::mediaplayer::MediaMetadataPtr> {
   static std::unique_ptr<media_player::Metadata> Convert(
-      const media_player::MediaMetadataPtr& input);
+      const fuchsia::mediaplayer::MediaMetadataPtr& input);
 };
 
 template <>
diff --git a/bin/media/media_player/framework/BUILD.gn b/bin/media/media_player/framework/BUILD.gn
index 8c15141..7e8e597 100644
--- a/bin/media/media_player/framework/BUILD.gn
+++ b/bin/media/media_player/framework/BUILD.gn
@@ -46,6 +46,7 @@
   public_deps = [
     "//garnet/public/lib/media/timeline",
     "//zircon/public/lib/async",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/bin/media/media_player/framework/formatting.cc b/bin/media/media_player/framework/formatting.cc
index 22f8dfc..be7026c 100644
--- a/bin/media/media_player/framework/formatting.cc
+++ b/bin/media/media_player/framework/formatting.cc
@@ -26,13 +26,13 @@
 
 std::ostream& newl(std::ostream& os) { return os << "\n" << begl; }
 
-// Prints an ns value in 0.124,456,789 format.
+// Prints an ns value in 0.123,456,789 format.
 std::ostream& operator<<(std::ostream& os, AsNs value) {
-  if (value.value_ == media::kUnspecifiedTime) {
+  if (value.value_ == fuchsia::media::kUnspecifiedTime) {
     return os << "<unspecified>";
   }
 
-  if (value.value_ == media::kMaxTime) {
+  if (value.value_ == fuchsia::media::kMaxTime) {
     return os << "<maximum>";
   }
 
diff --git a/bin/media/media_player/framework/graph.cc b/bin/media/media_player/framework/graph.cc
index d345d9a..1f12437 100644
--- a/bin/media/media_player/framework/graph.cc
+++ b/bin/media/media_player/framework/graph.cc
@@ -218,15 +218,15 @@
 }
 
 void Graph::FlushOutput(const OutputRef& output, bool hold_frame,
-                        fxl::Closure callback) {
+                        fit::closure callback) {
   FXL_DCHECK(output);
   std::queue<Output*> backlog;
   backlog.push(output.actual());
-  FlushOutputs(&backlog, hold_frame, callback);
+  FlushOutputs(&backlog, hold_frame, std::move(callback));
 }
 
 void Graph::FlushAllOutputs(NodeRef node, bool hold_frame,
-                            fxl::Closure callback) {
+                            fit::closure callback) {
   FXL_DCHECK(node);
 
   std::queue<Output*> backlog;
@@ -235,11 +235,10 @@
     backlog.push(node.output(output_index).actual());
   }
 
-  FlushOutputs(&backlog, hold_frame, callback);
+  FlushOutputs(&backlog, hold_frame, std::move(callback));
 }
 
-void Graph::PostTask(const fxl::Closure& task,
-                     std::initializer_list<NodeRef> nodes) {
+void Graph::PostTask(fit::closure task, std::initializer_list<NodeRef> nodes) {
   auto joiner = ThreadsafeCallbackJoiner::Create();
 
   std::vector<StageImpl*> stages;
@@ -248,12 +247,13 @@
     stages.push_back(node.stage_);
   }
 
-  joiner->WhenJoined(async_, [task, stages = std::move(stages)]() {
-    task();
-    for (auto stage : stages) {
-      stage->Release();
-    }
-  });
+  joiner->WhenJoined(async_,
+                     [task = std::move(task), stages = std::move(stages)]() {
+                       task();
+                       for (auto stage : stages) {
+                         stage->Release();
+                       }
+                     });
 }
 
 NodeRef Graph::AddStage(std::shared_ptr<StageImpl> stage) {
@@ -275,7 +275,7 @@
 }
 
 void Graph::FlushOutputs(std::queue<Output*>* backlog, bool hold_frame,
-                         fxl::Closure callback) {
+                         fit::closure callback) {
   FXL_DCHECK(backlog);
 
   auto callback_joiner = CallbackJoiner::Create();
@@ -313,7 +313,7 @@
     }
   }
 
-  callback_joiner->WhenJoined(callback);
+  callback_joiner->WhenJoined(std::move(callback));
 }
 
 void Graph::PrepareInput(Input* input) {
diff --git a/bin/media/media_player/framework/graph.h b/bin/media/media_player/framework/graph.h
index f53fac7..dfcfff8 100644
--- a/bin/media/media_player/framework/graph.h
+++ b/bin/media/media_player/framework/graph.h
@@ -7,10 +7,11 @@
 
 #include <list>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/framework/refs.h"
 #include "garnet/bin/media/media_player/framework/stages/async_node_stage.h"
 #include "garnet/bin/media/media_player/framework/stages/stage_impl.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace media_player {
 
@@ -146,19 +147,19 @@
   // indicates whether a video renderer should hold and display the newest
   // frame. |callback| is called when all flushes are complete.
   void FlushOutput(const OutputRef& output, bool hold_frame,
-                   fxl::Closure callback);
+                   fit::closure callback);
 
   // Flushes the node and the subgraph downstream of it. |hold_frame|
   // indicates whether a video renderer should hold and display the newest
   // frame. |callback| is called when all flushes are complete.
-  void FlushAllOutputs(NodeRef node, bool hold_frame, fxl::Closure callback);
+  void FlushAllOutputs(NodeRef node, bool hold_frame, fit::closure callback);
 
   // Executes |task| after having acquired |nodes|. No update or other
   // task will touch any of the nodes while |task| is executing.
-  void PostTask(const fxl::Closure& task, std::initializer_list<NodeRef> nodes);
+  void PostTask(fit::closure task, std::initializer_list<NodeRef> nodes);
 
  private:
-  using Visitor = std::function<void(Input* input, Output* output)>;
+  using Visitor = fit::function<void(Input* input, Output* output)>;
 
   // Adds a stage to the graph.
   NodeRef AddStage(std::shared_ptr<StageImpl> stage);
@@ -167,7 +168,7 @@
   // and calls |callback| when all flush operations are complete. |backlog| is
   // empty when this method returns.
   void FlushOutputs(std::queue<Output*>* backlog, bool hold_frame,
-                    fxl::Closure callback);
+                    fit::closure callback);
 
   // Prepares the input and the subgraph upstream of it.
   void PrepareInput(Input* input);
@@ -178,7 +179,7 @@
   // Flushes the output and the subgraph downstream of it. |hold_frame|
   // indicates whether a video renderer should hold and display the newest
   // frame. |callback| is used to signal completion.
-  void FlushOutput(Output* output, bool hold_frame, fxl::Closure callback);
+  void FlushOutput(Output* output, bool hold_frame, fit::closure callback);
 
   // Visits |input| and all inputs upstream of it (breadth first), calling
   // |visitor| for each connected input.
diff --git a/bin/media/media_player/framework/metadata.cc b/bin/media/media_player/framework/metadata.cc
index a18f181..151d4b1 100644
--- a/bin/media/media_player/framework/metadata.cc
+++ b/bin/media/media_player/framework/metadata.cc
@@ -7,23 +7,17 @@
 namespace media_player {
 
 // static
-std::unique_ptr<Metadata> Metadata::Create(uint64_t duration_ns,
-                                           const std::string& title,
-                                           const std::string& artist,
-                                           const std::string& album,
-                                           const std::string& publisher,
-                                           const std::string& genre,
-                                           const std::string& composer) {
+std::unique_ptr<Metadata> Metadata::Create(
+    uint64_t duration_ns, const std::string& title, const std::string& artist,
+    const std::string& album, const std::string& publisher,
+    const std::string& genre, const std::string& composer) {
   return std::unique_ptr<Metadata>(new Metadata(
       duration_ns, title, artist, album, publisher, genre, composer));
 }
 
-Metadata::Metadata(uint64_t duration_ns,
-                   const std::string& title,
-                   const std::string& artist,
-                   const std::string& album,
-                   const std::string& publisher,
-                   const std::string& genre,
+Metadata::Metadata(uint64_t duration_ns, const std::string& title,
+                   const std::string& artist, const std::string& album,
+                   const std::string& publisher, const std::string& genre,
                    const std::string& composer)
     : duration_ns_(duration_ns),
       title_(title),
diff --git a/bin/media/media_player/framework/metadata.h b/bin/media/media_player/framework/metadata.h
index e443f56..592a6b1 100644
--- a/bin/media/media_player/framework/metadata.h
+++ b/bin/media/media_player/framework/metadata.h
@@ -19,13 +19,10 @@
 // TODO(dalesat): Probably needs to be extensible. Consider using map-like.
 class Metadata {
  public:
-  static std::unique_ptr<Metadata> Create(uint64_t duration_ns,
-                                          const std::string& title,
-                                          const std::string& artist,
-                                          const std::string& album,
-                                          const std::string& publisher,
-                                          const std::string& genre,
-                                          const std::string& composer);
+  static std::unique_ptr<Metadata> Create(
+      uint64_t duration_ns, const std::string& title, const std::string& artist,
+      const std::string& album, const std::string& publisher,
+      const std::string& genre, const std::string& composer);
 
   ~Metadata();
 
@@ -49,12 +46,9 @@
   }
 
  private:
-  Metadata(uint64_t duration_ns,
-           const std::string& title,
-           const std::string& artist,
-           const std::string& album,
-           const std::string& publisher,
-           const std::string& genre,
+  Metadata(uint64_t duration_ns, const std::string& title,
+           const std::string& artist, const std::string& album,
+           const std::string& publisher, const std::string& genre,
            const std::string& composer);
 
   uint64_t duration_ns_;
diff --git a/bin/media/media_player/framework/models/async_node.h b/bin/media/media_player/framework/models/async_node.h
index 16517cb..182d40d 100644
--- a/bin/media/media_player/framework/models/async_node.h
+++ b/bin/media/media_player/framework/models/async_node.h
@@ -70,7 +70,7 @@
   //
   // This method will be called on the graph's thread.
   virtual void FlushInput(bool hold_frame, size_t input_index,
-                          fxl::Closure callback) {
+                          fit::closure callback) {
     FXL_CHECK(false) << "FlushInput not implemented.";
   }
 
@@ -108,7 +108,7 @@
   // converse it not true.
   //
   // This method will be called on the graph's thread.
-  virtual void FlushOutput(size_t output_index, fxl::Closure callback) {
+  virtual void FlushOutput(size_t output_index, fit::closure callback) {
     FXL_CHECK(false) << "FlushOutput not implemented.";
   }
 
diff --git a/bin/media/media_player/framework/models/node.cc b/bin/media/media_player/framework/models/node.cc
index 640a4b5..f08b805 100644
--- a/bin/media/media_player/framework/models/node.cc
+++ b/bin/media/media_player/framework/models/node.cc
@@ -15,10 +15,10 @@
   generic_stage_.load()->Dump(os);
 }
 
-void GenericNode::PostTask(const fxl::Closure& task) {
+void GenericNode::PostTask(fit::closure task) {
   Stage* generic_stage = generic_stage_;
   if (generic_stage) {
-    generic_stage->PostTask(task);
+    generic_stage->PostTask(std::move(task));
   }
 }
 
diff --git a/bin/media/media_player/framework/models/node.h b/bin/media/media_player/framework/models/node.h
index b9c9331..8cc784b 100644
--- a/bin/media/media_player/framework/models/node.h
+++ b/bin/media/media_player/framework/models/node.h
@@ -7,11 +7,12 @@
 
 #include <atomic>
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/framework/models/stage.h"
 #include "garnet/bin/media/media_player/framework/packet.h"
 #include "garnet/bin/media/media_player/framework/payload_allocator.h"
 #include "garnet/bin/media/media_player/framework/refs.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace media_player {
 
@@ -34,7 +35,7 @@
  protected:
   // Posts a task to run as soon as possible. A task posted with this method is
   // run exclusive of any other such tasks.
-  void PostTask(const fxl::Closure& task);
+  void PostTask(fit::closure task);
 
  private:
   std::atomic<Stage*> generic_stage_;
diff --git a/bin/media/media_player/framework/models/stage.h b/bin/media/media_player/framework/models/stage.h
index 6cba492..9365745 100644
--- a/bin/media/media_player/framework/models/stage.h
+++ b/bin/media/media_player/framework/models/stage.h
@@ -5,7 +5,7 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_FRAMEWORK_MODELS_STAGE_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_FRAMEWORK_MODELS_STAGE_H_
 
-#include "lib/fxl/functional/closure.h"
+#include <lib/fit/function.h>
 
 namespace media_player {
 
@@ -16,7 +16,7 @@
 
   // Posts a task to run as soon as possible. A Task posted with this method is
   // run exclusive of any other such tasks.
-  virtual void PostTask(const fxl::Closure& task) = 0;
+  virtual void PostTask(fit::closure task) = 0;
 
   virtual void Dump(std::ostream& os) const {}
 };
diff --git a/bin/media/media_player/framework/packet.cc b/bin/media/media_player/framework/packet.cc
index b3ad1df..5bf12ef 100644
--- a/bin/media/media_player/framework/packet.cc
+++ b/bin/media/media_player/framework/packet.cc
@@ -9,12 +9,8 @@
 
 namespace media_player {
 
-Packet::Packet(int64_t pts,
-               media::TimelineRate pts_rate,
-               bool keyframe,
-               bool end_of_stream,
-               size_t size,
-               void* payload)
+Packet::Packet(int64_t pts, media::TimelineRate pts_rate, bool keyframe,
+               bool end_of_stream, size_t size, void* payload)
     : pts_(pts),
       pts_rate_(pts_rate),
       keyframe_(keyframe),
@@ -38,9 +34,7 @@
                             pts_rate, pts_rate_.Inverse(), false));
 }
 
-uint64_t Packet::GetLabel() {
-  return 0;
-}
+uint64_t Packet::GetLabel() { return 0; }
 
 void Packet::SetPtsRate(media::TimelineRate pts_rate) {
   if (pts_rate == pts_rate_) {
@@ -53,12 +47,8 @@
 
 class PacketImpl : public Packet {
  public:
-  PacketImpl(int64_t pts,
-             media::TimelineRate pts_rate,
-             bool keyframe,
-             bool end_of_stream,
-             size_t size,
-             void* payload,
+  PacketImpl(int64_t pts, media::TimelineRate pts_rate, bool keyframe,
+             bool end_of_stream, size_t size, void* payload,
              std::shared_ptr<PayloadAllocator> allocator)
       : Packet(pts, pts_rate, keyframe, end_of_stream, size, payload),
         allocator_(allocator) {}
@@ -77,11 +67,8 @@
 };
 
 // static
-PacketPtr Packet::Create(int64_t pts,
-                         media::TimelineRate pts_rate,
-                         bool keyframe,
-                         bool end_of_stream,
-                         size_t size,
+PacketPtr Packet::Create(int64_t pts, media::TimelineRate pts_rate,
+                         bool keyframe, bool end_of_stream, size_t size,
                          void* payload,
                          std::shared_ptr<PayloadAllocator> allocator) {
   FXL_DCHECK(payload == nullptr || allocator != nullptr);
@@ -90,12 +77,9 @@
 }
 
 // static
-PacketPtr Packet::CreateNoAllocator(int64_t pts,
-                                    media::TimelineRate pts_rate,
-                                    bool keyframe,
-                                    bool end_of_stream,
-                                    size_t size,
-                                    void* payload) {
+PacketPtr Packet::CreateNoAllocator(int64_t pts, media::TimelineRate pts_rate,
+                                    bool keyframe, bool end_of_stream,
+                                    size_t size, void* payload) {
   return std::make_shared<PacketImpl>(pts, pts_rate, keyframe, end_of_stream,
                                       size, payload, nullptr);
 }
diff --git a/bin/media/media_player/framework/packet.h b/bin/media/media_player/framework/packet.h
index 6ca8c91..f16e729 100644
--- a/bin/media/media_player/framework/packet.h
+++ b/bin/media/media_player/framework/packet.h
@@ -32,23 +32,17 @@
 
   // Creates a packet. If size is 0, payload must be nullptr and vice-versa.
   // If payload is not nullptr, an allocator must be provided.
-  static PacketPtr Create(int64_t pts,
-                          media::TimelineRate pts_rate,
-                          bool keyframe,
-                          bool end_of_stream,
-                          size_t size,
+  static PacketPtr Create(int64_t pts, media::TimelineRate pts_rate,
+                          bool keyframe, bool end_of_stream, size_t size,
                           void* payload,
                           std::shared_ptr<PayloadAllocator> allocator);
 
   // Creates a packet. If size is 0, payload must be nullptr and vice-versa.
   // No allocator is provided, and the payload will not be released when the
   // packet is released.
-  static PacketPtr CreateNoAllocator(int64_t pts,
-                                     media::TimelineRate pts_rate,
-                                     bool keyframe,
-                                     bool end_of_stream,
-                                     size_t size,
-                                     void* payload);
+  static PacketPtr CreateNoAllocator(int64_t pts, media::TimelineRate pts_rate,
+                                     bool keyframe, bool end_of_stream,
+                                     size_t size, void* payload);
 
   // Creates an end-of-stream packet with no payload.
   static PacketPtr CreateEndOfStream(int64_t pts, media::TimelineRate pts_rate);
@@ -103,12 +97,8 @@
   virtual uint64_t GetLabel();
 
  protected:
-  Packet(int64_t pts,
-         media::TimelineRate pts_rate,
-         bool keyframe,
-         bool end_of_stream,
-         size_t size,
-         void* payload);
+  Packet(int64_t pts, media::TimelineRate pts_rate, bool keyframe,
+         bool end_of_stream, size_t size, void* payload);
 
  private:
   int64_t pts_;
diff --git a/bin/media/media_player/framework/payload_allocator.h b/bin/media/media_player/framework/payload_allocator.h
index 607ed28..d9b9c08 100644
--- a/bin/media/media_player/framework/payload_allocator.h
+++ b/bin/media/media_player/framework/payload_allocator.h
@@ -5,10 +5,10 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_FRAMEWORK_PAYLOAD_ALLOCATOR_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_FRAMEWORK_PAYLOAD_ALLOCATOR_H_
 
-#include <stddef.h>
-
 #include <memory>
 
+#include <stddef.h>
+
 namespace media_player {
 
 // Abstract base class for objects that allocate buffers for packets.
diff --git a/bin/media/media_player/framework/stages/async_node_stage.cc b/bin/media/media_player/framework/stages/async_node_stage.cc
index 4169175..08bcb04 100644
--- a/bin/media/media_player/framework/stages/async_node_stage.cc
+++ b/bin/media/media_player/framework/stages/async_node_stage.cc
@@ -211,20 +211,23 @@
 }
 
 void AsyncNodeStageImpl::FlushInput(size_t input_index, bool hold_frame,
-                                    fxl::Closure callback) {
+                                    fit::closure callback) {
   FXL_DCHECK(input_index < inputs_.size());
 
   inputs_[input_index].Flush();
 
   node_->FlushInput(hold_frame, input_index,
-                    [this, callback]() { PostTask(callback); });
+                    [this, callback = std::move(callback)]() mutable {
+                      PostTask(std::move(callback));
+                    });
 }
 
 void AsyncNodeStageImpl::FlushOutput(size_t output_index,
-                                     fxl::Closure callback) {
+                                     fit::closure callback) {
   FXL_DCHECK(output_index < outputs_.size());
 
-  node_->FlushOutput(output_index, [this, output_index, callback]() {
+  node_->FlushOutput(output_index, [this, output_index,
+                                    callback = std::move(callback)]() mutable {
     {
       std::lock_guard<std::mutex> locker(packets_per_output_mutex_);
       auto& packets = packets_per_output_[output_index];
@@ -233,13 +236,13 @@
       }
     }
 
-    PostTask(callback);
+    PostTask(std::move(callback));
   });
 }
 
-void AsyncNodeStageImpl::PostTask(const fxl::Closure& task) {
+void AsyncNodeStageImpl::PostTask(fit::closure task) {
   // This method runs on an arbitrary thread.
-  StageImpl::PostTask(task);
+  StageImpl::PostTask(std::move(task));
 }
 
 void AsyncNodeStageImpl::RequestInputPacket(size_t input_index) {
diff --git a/bin/media/media_player/framework/stages/async_node_stage.h b/bin/media/media_player/framework/stages/async_node_stage.h
index 91d5b5a..cdd0fb7 100644
--- a/bin/media/media_player/framework/stages/async_node_stage.h
+++ b/bin/media/media_player/framework/stages/async_node_stage.h
@@ -40,9 +40,9 @@
   void UnprepareOutput(size_t output_index) override;
 
   void FlushInput(size_t input_index, bool hold_frame,
-                  fxl::Closure callback) override;
+                  fit::closure callback) override;
 
-  void FlushOutput(size_t output_index, fxl::Closure callback) override;
+  void FlushOutput(size_t output_index, fit::closure callback) override;
 
  protected:
   // StageImpl implementation.
@@ -52,7 +52,7 @@
 
  private:
   // AsyncNodeStage implementation.
-  void PostTask(const fxl::Closure& task) override;
+  void PostTask(fit::closure task) override;
 
   void Dump(std::ostream& os) const override;
 
diff --git a/bin/media/media_player/framework/stages/stage_impl.cc b/bin/media/media_player/framework/stages/stage_impl.cc
index 557e52f..7cb5b13 100644
--- a/bin/media/media_player/framework/stages/stage_impl.cc
+++ b/bin/media/media_player/framework/stages/stage_impl.cc
@@ -63,8 +63,8 @@
   }
 }
 
-void StageImpl::Acquire(const fxl::Closure& callback) {
-  PostTask([this, callback]() {
+void StageImpl::Acquire(fit::closure callback) {
+  PostTask([this, callback = std::move(callback)]() {
     {
       std::lock_guard<std::mutex> locker(tasks_mutex_);
       tasks_suspended_ = true;
@@ -95,12 +95,12 @@
   async_ = async;
 }
 
-void StageImpl::PostTask(const fxl::Closure& task) {
+void StageImpl::PostTask(fit::closure task) {
   FXL_DCHECK(task);
 
   {
     std::lock_guard<std::mutex> locker(tasks_mutex_);
-    tasks_.push(task);
+    tasks_.push(std::move(task));
     if (tasks_.size() != 1 || tasks_suspended_) {
       // Don't need to run tasks, either because there were already tasks in
       // the queue or because task execution is suspended.
@@ -114,17 +114,17 @@
   });
 }
 
-void StageImpl::PostShutdownTask(fxl::Closure task) {
+void StageImpl::PostShutdownTask(fit::closure task) {
   FXL_DCHECK(async_);
-  async::PostTask(async_,
-                  [shared_this = shared_from_this(), task]() { task(); });
+  async::PostTask(async_, [shared_this = shared_from_this(),
+                           task = std::move(task)]() { task(); });
 }
 
 void StageImpl::RunTasks() {
   tasks_mutex_.lock();
 
   while (!tasks_.empty() && !tasks_suspended_) {
-    fxl::Closure& task = tasks_.front();
+    fit::closure task = std::move(tasks_.front());
     tasks_mutex_.unlock();
     task();
     // The closure may be keeping objects alive. Destroy it here so those
diff --git a/bin/media/media_player/framework/stages/stage_impl.h b/bin/media/media_player/framework/stages/stage_impl.h
index fb08665..24e0269 100644
--- a/bin/media/media_player/framework/stages/stage_impl.h
+++ b/bin/media/media_player/framework/stages/stage_impl.h
@@ -10,6 +10,7 @@
 #include <queue>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/framework/models/node.h"
 #include "garnet/bin/media/media_player/framework/models/stage.h"
@@ -17,7 +18,6 @@
 #include "garnet/bin/media/media_player/framework/payload_allocator.h"
 #include "garnet/bin/media/media_player/framework/stages/input.h"
 #include "garnet/bin/media/media_player/framework/stages/output.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/synchronization/thread_annotations.h"
 
 namespace media_player {
@@ -79,7 +79,7 @@
   // input's need for a packet. The callback is provided in case the node
   // has additional flushing business that can't be completed synchronously.
   virtual void FlushInput(size_t index, bool hold_frame,
-                          fxl::Closure callback) = 0;
+                          fit::closure callback) = 0;
 
   // Flushes an output. The callback is used to indicate that the flush
   // operation is complete. It must be called on the graph's thread and may be
@@ -88,7 +88,7 @@
   //
   // The output in question must not produce any packets after this method is
   // called and before the need for a packet is signalled.
-  virtual void FlushOutput(size_t index, fxl::Closure callback) = 0;
+  virtual void FlushOutput(size_t index, fit::closure callback) = 0;
 
   // Gets the generic node.
   virtual GenericNode* GetGenericNode() const = 0;
@@ -105,7 +105,7 @@
 
   // Acquires the stage, preventing posted tasks from running until the stage
   // is released. |callback| is called when the stage is acquired.
-  void Acquire(const fxl::Closure& callback);
+  void Acquire(fit::closure callback);
 
   // Releases the stage previously acquired via |Acquire|.
   void Release();
@@ -113,14 +113,14 @@
   // Sets an |async_t| for running tasks .
   void SetAsync(async_t* async);
 
-  void PostTask(const fxl::Closure& task);
+  void PostTask(fit::closure task);
 
  protected:
   // Updates packet supply and demand.
   virtual void Update() = 0;
 
   // Post a task that will run even if the stage has been shut down.
-  void PostShutdownTask(fxl::Closure task);
+  void PostShutdownTask(fit::closure task);
 
  private:
   // Runs tasks in the task queue. This method is always called from
@@ -146,7 +146,7 @@
 
   mutable std::mutex tasks_mutex_;
   // Pending tasks. Only |RunTasks| may pop from this queue.
-  std::queue<fxl::Closure> tasks_ FXL_GUARDED_BY(tasks_mutex_);
+  std::queue<fit::closure> tasks_ FXL_GUARDED_BY(tasks_mutex_);
   // Set to true to suspend task execution.
   bool tasks_suspended_ FXL_GUARDED_BY(tasks_mutex_) = false;
 };
diff --git a/bin/media/media_player/framework/types/audio_stream_type.cc b/bin/media/media_player/framework/types/audio_stream_type.cc
index 6d43c16..db0a332 100644
--- a/bin/media/media_player/framework/types/audio_stream_type.cc
+++ b/bin/media/media_player/framework/types/audio_stream_type.cc
@@ -11,11 +11,9 @@
 
 AudioStreamType::AudioStreamType(const std::string& encoding,
                                  std::unique_ptr<Bytes> encoding_parameters,
-                                 SampleFormat sample_format,
-                                 uint32_t channels,
+                                 SampleFormat sample_format, uint32_t channels,
                                  uint32_t frames_per_second)
-    : StreamType(StreamType::Medium::kAudio,
-                 encoding,
+    : StreamType(StreamType::Medium::kAudio, encoding,
                  std::move(encoding_parameters)),
       sample_format_(sample_format),
       channels_(channels),
@@ -23,17 +21,13 @@
       sample_size_(SampleSizeFromFormat(sample_format)) {}
 
 AudioStreamType::AudioStreamType(const AudioStreamType& other)
-    : AudioStreamType(other.encoding(),
-                      SafeClone(other.encoding_parameters()),
-                      other.sample_format(),
-                      other.channels(),
+    : AudioStreamType(other.encoding(), SafeClone(other.encoding_parameters()),
+                      other.sample_format(), other.channels(),
                       other.frames_per_second()) {}
 
 AudioStreamType::~AudioStreamType() {}
 
-const AudioStreamType* AudioStreamType::audio() const {
-  return this;
-}
+const AudioStreamType* AudioStreamType::audio() const { return this; }
 
 // static
 uint32_t AudioStreamType::SampleSizeFromFormat(SampleFormat sample_format) {
@@ -63,8 +57,7 @@
 
 AudioStreamTypeSet::AudioStreamTypeSet(
     const std::vector<std::string>& encodings,
-    AudioStreamType::SampleFormat sample_format,
-    Range<uint32_t> channels,
+    AudioStreamType::SampleFormat sample_format, Range<uint32_t> channels,
     Range<uint32_t> frames_per_second)
     : StreamTypeSet(StreamType::Medium::kAudio, encodings),
       sample_format_(sample_format),
@@ -73,9 +66,7 @@
 
 AudioStreamTypeSet::~AudioStreamTypeSet() {}
 
-const AudioStreamTypeSet* AudioStreamTypeSet::audio() const {
-  return this;
-}
+const AudioStreamTypeSet* AudioStreamTypeSet::audio() const { return this; }
 
 std::unique_ptr<StreamTypeSet> AudioStreamTypeSet::Clone() const {
   return Create(encodings(), sample_format(), channels(), frames_per_second());
diff --git a/bin/media/media_player/framework/types/audio_stream_type.h b/bin/media/media_player/framework/types/audio_stream_type.h
index 6d00a1e..c6532d3 100644
--- a/bin/media/media_player/framework/types/audio_stream_type.h
+++ b/bin/media/media_player/framework/types/audio_stream_type.h
@@ -27,10 +27,8 @@
   };
 
   static std::unique_ptr<StreamType> Create(
-      const std::string& encoding,
-      std::unique_ptr<Bytes> encoding_parameters,
-      SampleFormat sample_format,
-      uint32_t channels,
+      const std::string& encoding, std::unique_ptr<Bytes> encoding_parameters,
+      SampleFormat sample_format, uint32_t channels,
       uint32_t frames_per_second) {
     return std::unique_ptr<StreamType>(
         new AudioStreamType(encoding, std::move(encoding_parameters),
@@ -39,8 +37,7 @@
 
   AudioStreamType(const std::string& encoding,
                   std::unique_ptr<Bytes> encoding_parameters,
-                  SampleFormat sample_format,
-                  uint32_t channels,
+                  SampleFormat sample_format, uint32_t channels,
                   uint32_t frames_per_second);
 
   AudioStreamType(const AudioStreamType& other);
@@ -85,8 +82,7 @@
  public:
   static std::unique_ptr<StreamTypeSet> Create(
       const std::vector<std::string>& encodings,
-      AudioStreamType::SampleFormat sample_format,
-      Range<uint32_t> channels,
+      AudioStreamType::SampleFormat sample_format, Range<uint32_t> channels,
       Range<uint32_t> frames_per_second) {
     return std::unique_ptr<StreamTypeSet>(new AudioStreamTypeSet(
         encodings, sample_format, channels, frames_per_second));
diff --git a/bin/media/media_player/framework/types/stream_type.cc b/bin/media/media_player/framework/types/stream_type.cc
index 7c7d3a5..83416d1 100644
--- a/bin/media/media_player/framework/types/stream_type.cc
+++ b/bin/media/media_player/framework/types/stream_type.cc
@@ -34,8 +34,7 @@
 const char StreamType::kVideoEncodingVp8[] = "vp8";
 const char StreamType::kVideoEncodingVp9[] = "vp9";
 
-StreamType::StreamType(Medium medium,
-                       const std::string& encoding,
+StreamType::StreamType(Medium medium, const std::string& encoding,
                        std::unique_ptr<Bytes> encoding_parameters)
     : medium_(medium),
       encoding_(encoding),
diff --git a/bin/media/media_player/framework/types/stream_type.h b/bin/media/media_player/framework/types/stream_type.h
index 116c722..465b6c4 100644
--- a/bin/media/media_player/framework/types/stream_type.h
+++ b/bin/media/media_player/framework/types/stream_type.h
@@ -49,15 +49,13 @@
   static const char kVideoEncodingVp9[];
 
   static std::unique_ptr<StreamType> Create(
-      Medium medium,
-      const std::string& encoding,
+      Medium medium, const std::string& encoding,
       std::unique_ptr<Bytes> encoding_parameters) {
     return std::unique_ptr<StreamType>(
         new StreamType(medium, encoding, std::move(encoding_parameters)));
   }
 
-  StreamType(Medium medium,
-             const std::string& encoding,
+  StreamType(Medium medium, const std::string& encoding,
              std::unique_ptr<Bytes> encoding_parameters);
 
   virtual ~StreamType();
@@ -105,8 +103,7 @@
 class StreamTypeSet {
  public:
   static std::unique_ptr<StreamTypeSet> Create(
-      StreamType::Medium medium,
-      const std::vector<std::string>& encodings) {
+      StreamType::Medium medium, const std::vector<std::string>& encodings) {
     return std::unique_ptr<StreamTypeSet>(new StreamTypeSet(medium, encodings));
   }
 
diff --git a/bin/media/media_player/framework/types/subpicture_stream_type.cc b/bin/media/media_player/framework/types/subpicture_stream_type.cc
index cefb8f4..6f4a754 100644
--- a/bin/media/media_player/framework/types/subpicture_stream_type.cc
+++ b/bin/media/media_player/framework/types/subpicture_stream_type.cc
@@ -9,10 +9,8 @@
 namespace media_player {
 
 SubpictureStreamType::SubpictureStreamType(
-    const std::string& encoding,
-    std::unique_ptr<Bytes> encoding_parameters)
-    : StreamType(StreamType::Medium::kSubpicture,
-                 encoding,
+    const std::string& encoding, std::unique_ptr<Bytes> encoding_parameters)
+    : StreamType(StreamType::Medium::kSubpicture, encoding,
                  std::move(encoding_parameters)) {}
 
 SubpictureStreamType::~SubpictureStreamType() {}
diff --git a/bin/media/media_player/framework/types/subpicture_stream_type.h b/bin/media/media_player/framework/types/subpicture_stream_type.h
index 68cedb5..7a41eff 100644
--- a/bin/media/media_player/framework/types/subpicture_stream_type.h
+++ b/bin/media/media_player/framework/types/subpicture_stream_type.h
@@ -15,8 +15,7 @@
 class SubpictureStreamType : public StreamType {
  public:
   static std::unique_ptr<StreamType> Create(
-      const std::string& encoding,
-      std::unique_ptr<Bytes> encoding_parameters) {
+      const std::string& encoding, std::unique_ptr<Bytes> encoding_parameters) {
     return std::unique_ptr<StreamType>(
         new SubpictureStreamType(encoding, std::move(encoding_parameters)));
   }
diff --git a/bin/media/media_player/framework/types/text_stream_type.cc b/bin/media/media_player/framework/types/text_stream_type.cc
index 2179684..08e4c55 100644
--- a/bin/media/media_player/framework/types/text_stream_type.cc
+++ b/bin/media/media_player/framework/types/text_stream_type.cc
@@ -11,15 +11,12 @@
 
 TextStreamType::TextStreamType(const std::string& encoding,
                                std::unique_ptr<Bytes> encoding_parameters)
-    : StreamType(StreamType::Medium::kText,
-                 encoding,
+    : StreamType(StreamType::Medium::kText, encoding,
                  std::move(encoding_parameters)) {}
 
 TextStreamType::~TextStreamType() {}
 
-const TextStreamType* TextStreamType::text() const {
-  return this;
-}
+const TextStreamType* TextStreamType::text() const { return this; }
 
 std::unique_ptr<StreamType> TextStreamType::Clone() const {
   return Create(encoding(), SafeClone(encoding_parameters()));
@@ -30,9 +27,7 @@
 
 TextStreamTypeSet::~TextStreamTypeSet() {}
 
-const TextStreamTypeSet* TextStreamTypeSet::text() const {
-  return this;
-}
+const TextStreamTypeSet* TextStreamTypeSet::text() const { return this; }
 
 std::unique_ptr<StreamTypeSet> TextStreamTypeSet::Clone() const {
   return Create(encodings());
diff --git a/bin/media/media_player/framework/types/text_stream_type.h b/bin/media/media_player/framework/types/text_stream_type.h
index 7ba46d0..65a823d 100644
--- a/bin/media/media_player/framework/types/text_stream_type.h
+++ b/bin/media/media_player/framework/types/text_stream_type.h
@@ -15,8 +15,7 @@
 class TextStreamType : public StreamType {
  public:
   static std::unique_ptr<StreamType> Create(
-      const std::string& encoding,
-      std::unique_ptr<Bytes> encoding_parameters) {
+      const std::string& encoding, std::unique_ptr<Bytes> encoding_parameters) {
     return std::unique_ptr<StreamType>(
         new TextStreamType(encoding, std::move(encoding_parameters)));
   }
diff --git a/bin/media/media_player/framework/types/video_stream_type.cc b/bin/media/media_player/framework/types/video_stream_type.cc
index 14fd96e..3937c56 100644
--- a/bin/media/media_player/framework/types/video_stream_type.cc
+++ b/bin/media/media_player/framework/types/video_stream_type.cc
@@ -82,21 +82,14 @@
   return bytes_per_element_for_plane(plane) * ColumnCount(plane, width);
 }
 
-VideoStreamType::VideoStreamType(const std::string& encoding,
-                                 std::unique_ptr<Bytes> encoding_parameters,
-                                 VideoProfile profile,
-                                 PixelFormat pixel_format,
-                                 ColorSpace color_space,
-                                 uint32_t width,
-                                 uint32_t height,
-                                 uint32_t coded_width,
-                                 uint32_t coded_height,
-                                 uint32_t pixel_aspect_ratio_width,
-                                 uint32_t pixel_aspect_ratio_height,
-                                 const std::vector<uint32_t> line_stride,
-                                 const std::vector<uint32_t> plane_offset)
-    : StreamType(StreamType::Medium::kVideo,
-                 encoding,
+VideoStreamType::VideoStreamType(
+    const std::string& encoding, std::unique_ptr<Bytes> encoding_parameters,
+    VideoProfile profile, PixelFormat pixel_format, ColorSpace color_space,
+    uint32_t width, uint32_t height, uint32_t coded_width,
+    uint32_t coded_height, uint32_t pixel_aspect_ratio_width,
+    uint32_t pixel_aspect_ratio_height, const std::vector<uint32_t> line_stride,
+    const std::vector<uint32_t> plane_offset)
+    : StreamType(StreamType::Medium::kVideo, encoding,
                  std::move(encoding_parameters)),
       profile_(profile),
       pixel_format_(pixel_format),
@@ -113,9 +106,7 @@
 
 VideoStreamType::~VideoStreamType() {}
 
-const VideoStreamType* VideoStreamType::video() const {
-  return this;
-}
+const VideoStreamType* VideoStreamType::video() const { return this; }
 
 std::unique_ptr<StreamType> VideoStreamType::Clone() const {
   return Create(encoding(), SafeClone(encoding_parameters()), profile(),
@@ -125,8 +116,7 @@
 }
 
 VideoStreamTypeSet::VideoStreamTypeSet(
-    const std::vector<std::string>& encodings,
-    Range<uint32_t> width,
+    const std::vector<std::string>& encodings, Range<uint32_t> width,
     Range<uint32_t> height)
     : StreamTypeSet(StreamType::Medium::kVideo, encodings),
       width_(width),
@@ -134,9 +124,7 @@
 
 VideoStreamTypeSet::~VideoStreamTypeSet() {}
 
-const VideoStreamTypeSet* VideoStreamTypeSet::video() const {
-  return this;
-}
+const VideoStreamTypeSet* VideoStreamTypeSet::video() const { return this; }
 
 std::unique_ptr<StreamTypeSet> VideoStreamTypeSet::Clone() const {
   return Create(encodings(), width(), height());
diff --git a/bin/media/media_player/framework/types/video_stream_type.h b/bin/media/media_player/framework/types/video_stream_type.h
index be81456..9690aee 100644
--- a/bin/media/media_player/framework/types/video_stream_type.h
+++ b/bin/media/media_player/framework/types/video_stream_type.h
@@ -120,16 +120,10 @@
 
   // Creates a VideoStreamType.
   static std::unique_ptr<StreamType> Create(
-      const std::string& encoding,
-      std::unique_ptr<Bytes> encoding_parameters,
-      VideoProfile profile,
-      PixelFormat pixel_format,
-      ColorSpace color_space,
-      uint32_t width,
-      uint32_t height,
-      uint32_t coded_width,
-      uint32_t coded_height,
-      uint32_t pixel_aspect_ratio_width,
+      const std::string& encoding, std::unique_ptr<Bytes> encoding_parameters,
+      VideoProfile profile, PixelFormat pixel_format, ColorSpace color_space,
+      uint32_t width, uint32_t height, uint32_t coded_width,
+      uint32_t coded_height, uint32_t pixel_aspect_ratio_width,
       uint32_t pixel_aspect_ratio_height,
       const std::vector<uint32_t> line_stride,
       const std::vector<uint32_t> plane_offset) {
@@ -142,13 +136,9 @@
 
   VideoStreamType(const std::string& encoding,
                   std::unique_ptr<Bytes> encoding_parameters,
-                  VideoProfile profile,
-                  PixelFormat pixel_format,
-                  ColorSpace color_space,
-                  uint32_t width,
-                  uint32_t height,
-                  uint32_t coded_width,
-                  uint32_t coded_height,
+                  VideoProfile profile, PixelFormat pixel_format,
+                  ColorSpace color_space, uint32_t width, uint32_t height,
+                  uint32_t coded_width, uint32_t coded_height,
                   uint32_t pixel_aspect_ratio_width,
                   uint32_t pixel_aspect_ratio_height,
                   const std::vector<uint32_t> line_stride,
@@ -289,16 +279,14 @@
 class VideoStreamTypeSet : public StreamTypeSet {
  public:
   static std::unique_ptr<StreamTypeSet> Create(
-      const std::vector<std::string>& encodings,
-      Range<uint32_t> width,
+      const std::vector<std::string>& encodings, Range<uint32_t> width,
       Range<uint32_t> height) {
     return std::unique_ptr<StreamTypeSet>(
         new VideoStreamTypeSet(encodings, width, height));
   }
 
   VideoStreamTypeSet(const std::vector<std::string>& encodings,
-                     Range<uint32_t> width,
-                     Range<uint32_t> height);
+                     Range<uint32_t> width, Range<uint32_t> height);
 
   ~VideoStreamTypeSet() override;
 
diff --git a/bin/media/media_player/framework_create/decoder.cc b/bin/media/media_player/framework_create/decoder.cc
index 6aa4430..bb51e07 100644
--- a/bin/media/media_player/framework_create/decoder.cc
+++ b/bin/media/media_player/framework_create/decoder.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/media_player/decode/decoder.h"
+
 #include "garnet/bin/media/media_player/ffmpeg/ffmpeg_decoder.h"
 
 namespace media_player {
diff --git a/bin/media/media_player/framework_create/demux.cc b/bin/media/media_player/framework_create/demux.cc
index 887dad5..268ee96 100644
--- a/bin/media/media_player/framework_create/demux.cc
+++ b/bin/media/media_player/framework_create/demux.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/media_player/demux/demux.h"
+
 #include "garnet/bin/media/media_player/ffmpeg/ffmpeg_demux.h"
 
 namespace media_player {
diff --git a/bin/media/media_player/main.cc b/bin/media/media_player/main.cc
index 077af01..2aa51d0 100644
--- a/bin/media/media_player/main.cc
+++ b/bin/media/media_player/main.cc
@@ -5,10 +5,10 @@
 #include <string>
 
 #include <fs/pseudo-file.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
 #include <trace-provider/provider.h>
 
 #include "garnet/bin/media/media_player/media_player_impl.h"
@@ -53,25 +53,30 @@
 
   if (transient) {
     std::unique_ptr<media_player::MediaPlayerImpl> player;
-    startup_context->outgoing().AddPublicService<media_player::MediaPlayer>(
-        [startup_context = startup_context.get(), &player,
-         &loop](fidl::InterfaceRequest<media_player::MediaPlayer> request) {
-          player = media_player::MediaPlayerImpl::Create(
-              std::move(request), startup_context, [&loop]() {
-                async::PostTask(loop.async(), [&loop]() { loop.Quit(); });
-              });
-        });
+    startup_context->outgoing()
+        .AddPublicService<fuchsia::mediaplayer::MediaPlayer>(
+            [startup_context = startup_context.get(), &player,
+             &loop](fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer>
+                        request) {
+              player = media_player::MediaPlayerImpl::Create(
+                  std::move(request), startup_context, [&loop]() {
+                    async::PostTask(loop.async(), [&loop]() { loop.Quit(); });
+                  });
+            });
 
     loop.Run();
   } else {
     fuchsia::sys::LauncherPtr launcher;
     startup_context->environment()->GetLauncher(launcher.NewRequest());
 
-    startup_context->outgoing().AddPublicService<media_player::MediaPlayer>(
-        [&launcher](fidl::InterfaceRequest<media_player::MediaPlayer> request) {
-          ConnectToIsolate<media_player::MediaPlayer>(std::move(request),
-                                                      launcher.get());
-        });
+    startup_context->outgoing()
+        .AddPublicService<fuchsia::mediaplayer::MediaPlayer>(
+            [&launcher](
+                fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer>
+                    request) {
+              ConnectToIsolate<fuchsia::mediaplayer::MediaPlayer>(
+                  std::move(request), launcher.get());
+            });
 
     loop.Run();
   }
diff --git a/bin/media/media_player/media_player_impl.cc b/bin/media/media_player/media_player_impl.cc
index 93a7c54..255fa4b 100644
--- a/bin/media/media_player/media_player_impl.cc
+++ b/bin/media/media_player/media_player_impl.cc
@@ -7,10 +7,11 @@
 #include <sstream>
 
 #include <fs/pseudo-file.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/demux/fidl_reader.h"
 #include "garnet/bin/media/media_player/demux/file_reader.h"
@@ -37,18 +38,18 @@
 
 // static
 std::unique_ptr<MediaPlayerImpl> MediaPlayerImpl::Create(
-    fidl::InterfaceRequest<MediaPlayer> request,
-    fuchsia::sys::StartupContext* startup_context, fxl::Closure quit_callback) {
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+    fuchsia::sys::StartupContext* startup_context, fit::closure quit_callback) {
   return std::make_unique<MediaPlayerImpl>(std::move(request), startup_context,
-                                           quit_callback);
+                                           std::move(quit_callback));
 }
 
-MediaPlayerImpl::MediaPlayerImpl(fidl::InterfaceRequest<MediaPlayer> request,
-                                 fuchsia::sys::StartupContext* startup_context,
-                                 fxl::Closure quit_callback)
+MediaPlayerImpl::MediaPlayerImpl(
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+    fuchsia::sys::StartupContext* startup_context, fit::closure quit_callback)
     : async_(async_get_default()),
       startup_context_(startup_context),
-      quit_callback_(quit_callback),
+      quit_callback_(std::move(quit_callback)),
       player_(async_) {
   FXL_DCHECK(request);
   FXL_DCHECK(startup_context_);
@@ -97,7 +98,7 @@
           os << newl << "transitioning to:   " << ToString(target_state_);
         }
 
-        if (target_position_ != media::kUnspecifiedTime) {
+        if (target_position_ != fuchsia::media::kUnspecifiedTime) {
           os << newl << "pending seek to:    " << AsNs(target_position_);
         }
 
@@ -138,8 +139,9 @@
     case StreamType::Medium::kAudio:
       if (!audio_renderer_) {
         auto audio_server =
-            startup_context_->ConnectToEnvironmentService<media::AudioServer>();
-        media::AudioRenderer2Ptr audio_renderer;
+            startup_context_
+                ->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
+        fuchsia::media::AudioRenderer2Ptr audio_renderer;
         audio_server->CreateRendererV2(audio_renderer.NewRequest());
         audio_renderer_ = FidlAudioRenderer::Create(std::move(audio_renderer));
         if (gain_ != 1.0f) {
@@ -220,7 +222,7 @@
 
         // Presentation time is not progressing, and the pipeline is clear of
         // packets.
-        if (target_position_ != media::kUnspecifiedTime) {
+        if (target_position_ != fuchsia::media::kUnspecifiedTime) {
           // We want to seek. Enter |kWaiting| state until the operation is
           // complete.
           state_ = State::kWaiting;
@@ -231,7 +233,7 @@
           // seeking the source, we'll notice that and do those things
           // again.
           int64_t target_position = target_position_;
-          target_position_ = media::kUnspecifiedTime;
+          target_position_ = fuchsia::media::kUnspecifiedTime;
 
           // |program_range_min_pts_| will be delivered in the
           // |SetProgramRange| call, ensuring that the renderers discard
@@ -244,8 +246,9 @@
               0.0f, media::Timeline::local_now(), [this, target_position]() {
                 if (target_position_ == target_position) {
                   // We've had a rendundant seek request. Ignore it.
-                  target_position_ = media::kUnspecifiedTime;
-                } else if (target_position_ != media::kUnspecifiedTime) {
+                  target_position_ = fuchsia::media::kUnspecifiedTime;
+                } else if (target_position_ !=
+                           fuchsia::media::kUnspecifiedTime) {
                   // We've had a seek request to a new position. Refrain from
                   // seeking the source and re-enter this sequence.
                   state_ = State::kFlushed;
@@ -273,7 +276,8 @@
           // when the operation is complete.
           state_ = State::kWaiting;
           waiting_reason_ = "for priming to complete";
-          player_.SetProgramRange(0, program_range_min_pts_, media::kMaxTime);
+          player_.SetProgramRange(0, program_range_min_pts_,
+                                  fuchsia::media::kMaxTime);
 
           player_.Prime([this]() {
             state_ = State::kPrimed;
@@ -366,12 +370,12 @@
 }
 
 void MediaPlayerImpl::SetTimelineFunction(float rate, int64_t reference_time,
-                                          fxl::Closure callback) {
+                                          fit::closure callback) {
   player_.SetTimelineFunction(
       media::TimelineFunction(transform_subject_time_, reference_time,
                               media::TimelineRate(rate)),
-      callback);
-  transform_subject_time_ = media::kUnspecifiedTime;
+      std::move(callback));
+  transform_subject_time_ = fuchsia::media::kUnspecifiedTime;
   SendStatusUpdates();
 }
 
@@ -384,7 +388,7 @@
 }
 
 void MediaPlayerImpl::SetReaderSource(
-    fidl::InterfaceHandle<SeekingReader> reader_handle) {
+    fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader> reader_handle) {
   if (!reader_handle) {
     BeginSetReader(nullptr);
     return;
@@ -473,7 +477,7 @@
 }
 
 void MediaPlayerImpl::SetAudioRenderer(
-    fidl::InterfaceHandle<media::AudioRenderer2> audio_renderer) {
+    fidl::InterfaceHandle<fuchsia::media::AudioRenderer2> audio_renderer) {
   if (audio_renderer_) {
     return;
   }
@@ -487,7 +491,8 @@
                          StreamType::Medium::kAudio);
 }
 
-void MediaPlayerImpl::AddBinding(fidl::InterfaceRequest<MediaPlayer> request) {
+void MediaPlayerImpl::AddBinding(
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request) {
   FXL_DCHECK(request);
   bindings_.AddBinding(this, std::move(request));
 
@@ -516,7 +521,8 @@
   status_.video_connected =
       player_.medium_connected(StreamType::Medium::kVideo);
 
-  status_.metadata = fxl::To<MediaMetadataPtr>(player_.metadata());
+  status_.metadata =
+      fxl::To<fuchsia::mediaplayer::MediaMetadataPtr>(player_.metadata());
 
   if (video_renderer_) {
     status_.video_size = SafeClone(video_renderer_->video_size());
diff --git a/bin/media/media_player/media_player_impl.h b/bin/media/media_player/media_player_impl.h
index b9f33a5..01c2754 100644
--- a/bin/media/media_player/media_player_impl.h
+++ b/bin/media/media_player/media_player_impl.h
@@ -7,8 +7,9 @@
 
 #include <unordered_map>
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async/default.h>
-#include <media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/demux/reader.h"
 #include "garnet/bin/media/media_player/player/player.h"
@@ -16,22 +17,23 @@
 #include "garnet/bin/media/media_player/render/fidl_video_renderer.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/media/timeline/timeline.h"
 #include "lib/media/timeline/timeline_function.h"
 
 namespace media_player {
 
 // Fidl agent that renders streams.
-class MediaPlayerImpl : public MediaPlayer {
+class MediaPlayerImpl : public fuchsia::mediaplayer::MediaPlayer {
  public:
   static std::unique_ptr<MediaPlayerImpl> Create(
-      fidl::InterfaceRequest<MediaPlayer> request,
-      fuchsia::sys::StartupContext* startup_context, fxl::Closure quit_callback);
+      fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+      fuchsia::sys::StartupContext* startup_context,
+      fit::closure quit_callback);
 
-  MediaPlayerImpl(fidl::InterfaceRequest<MediaPlayer> request,
-                  fuchsia::sys::StartupContext* startup_context,
-                  fxl::Closure quit_callback);
+  MediaPlayerImpl(
+      fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+      fuchsia::sys::StartupContext* startup_context,
+      fit::closure quit_callback);
 
   ~MediaPlayerImpl() override;
 
@@ -41,7 +43,8 @@
   void SetFileSource(zx::channel file_channel) override;
 
   void SetReaderSource(
-      fidl::InterfaceHandle<SeekingReader> reader_handle) override;
+      fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader> reader_handle)
+      override;
 
   void Play() override;
 
@@ -56,10 +59,11 @@
       fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
           view_owner_request) override;
 
-  void SetAudioRenderer(
-      fidl::InterfaceHandle<media::AudioRenderer2> audio_renderer) override;
+  void SetAudioRenderer(fidl::InterfaceHandle<fuchsia::media::AudioRenderer2>
+                            audio_renderer) override;
 
-  void AddBinding(fidl::InterfaceRequest<MediaPlayer> request) override;
+  void AddBinding(fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer>
+                      request) override;
 
  private:
   static constexpr int64_t kMinimumLeadTime = media::Timeline::ns_from_ms(30);
@@ -88,16 +92,13 @@
   // Creates sinks as needed and connects enabled streams.
   void ConnectSinks();
 
-  // Prepares a stream.
-  void PrepareStream(size_t index, const media::MediaType& input_media_type,
-                     const std::function<void()>& callback);
-
   // Takes action based on current state.
   void Update();
 
   // Determines whether we need to flush.
   bool NeedToFlush() const {
-    return setting_reader_ || target_position_ != media::kUnspecifiedTime ||
+    return setting_reader_ ||
+           target_position_ != fuchsia::media::kUnspecifiedTime ||
            target_state_ == State::kFlushed;
   }
 
@@ -108,7 +109,7 @@
 
   // Sets the timeline function.
   void SetTimelineFunction(float rate, int64_t reference_time,
-                           fxl::Closure callback);
+                           fit::closure callback);
 
   // Sends status updates to clients.
   void SendStatusUpdates();
@@ -118,8 +119,8 @@
 
   async_t* async_;
   fuchsia::sys::StartupContext* startup_context_;
-  fxl::Closure quit_callback_;
-  fidl::BindingSet<MediaPlayer> bindings_;
+  fit::closure quit_callback_;
+  fidl::BindingSet<fuchsia::mediaplayer::MediaPlayer> bindings_;
   Player player_;
 
   float gain_ = 1.0f;
@@ -135,16 +136,16 @@
   State target_state_ = State::kFlushed;
 
   // The position we want to seek to (because the client called Seek) or
-  // media::kUnspecifiedTime, which indicates there's no desire to seek.
-  int64_t target_position_ = media::kUnspecifiedTime;
+  // kUnspecifiedTime, which indicates there's no desire to seek.
+  int64_t target_position_ = fuchsia::media::kUnspecifiedTime;
 
   // The subject time to be used for SetTimelineFunction. The value is
-  // media::kUnspecifiedTime if there's no need to seek or the position we want
+  // kUnspecifiedTime if there's no need to seek or the position we want
   // to seek to if there is.
-  int64_t transform_subject_time_ = media::kUnspecifiedTime;
+  int64_t transform_subject_time_ = fuchsia::media::kUnspecifiedTime;
 
   // The minimum program range PTS to be used for SetProgramRange.
-  int64_t program_range_min_pts_ = media::kMinTime;
+  int64_t program_range_min_pts_ = fuchsia::media::kMinTime;
 
   // Whether we need to set the reader, possibly with nothing. When this is
   // true, the state machine will transition to |kIdle|, removing an existing
@@ -157,7 +158,7 @@
   // reader and transition to kInactive.
   std::shared_ptr<Reader> new_reader_;
 
-  MediaPlayerStatus status_;
+  fuchsia::mediaplayer::MediaPlayerStatus status_;
 };
 
 }  // namespace media_player
diff --git a/bin/media/media_player/metrics/packet_timing_tracker.cc b/bin/media/media_player/metrics/packet_timing_tracker.cc
index b464dd6..33986b6 100644
--- a/bin/media/media_player/metrics/packet_timing_tracker.cc
+++ b/bin/media/media_player/metrics/packet_timing_tracker.cc
@@ -15,10 +15,8 @@
 
 PacketTimingTracker::~PacketTimingTracker() {}
 
-void PacketTimingTracker::AddSample(int64_t now,
-                                    int64_t presentation_time,
-                                    int64_t packet_pts_ns,
-                                    bool progressing) {
+void PacketTimingTracker::AddSample(int64_t now, int64_t presentation_time,
+                                    int64_t packet_pts_ns, bool progressing) {
   if (!progressing) {
     ++not_progressing_count_;
   } else if (packet_pts_ns == Packet::kUnknownPts) {
diff --git a/bin/media/media_player/metrics/packet_timing_tracker.h b/bin/media/media_player/metrics/packet_timing_tracker.h
index a87e7ac..a698ac8 100644
--- a/bin/media/media_player/metrics/packet_timing_tracker.h
+++ b/bin/media/media_player/metrics/packet_timing_tracker.h
@@ -18,9 +18,7 @@
 
   // Adds a sample to the tracker. If |packet_pts_ns| is |Packet::kUnknownPts|,
   // the sample is counted as a 'no packet' case.
-  void AddSample(int64_t now,
-                 int64_t presentation_time,
-                 int64_t packet_pts_ns,
+  void AddSample(int64_t now, int64_t presentation_time, int64_t packet_pts_ns,
                  bool progressing);
 
   // Resets the tracker to its initial state.
diff --git a/bin/media/media_player/metrics/rate_tracker.cc b/bin/media/media_player/metrics/rate_tracker.cc
index 4f44ac8..6c70e54 100644
--- a/bin/media/media_player/metrics/rate_tracker.cc
+++ b/bin/media/media_player/metrics/rate_tracker.cc
@@ -9,9 +9,7 @@
 
 namespace media_player {
 
-RateTracker::RateTracker() {
-  Reset();
-}
+RateTracker::RateTracker() { Reset(); }
 
 RateTracker::~RateTracker() {}
 
diff --git a/bin/media/media_player/player/conversion_pipeline_builder.cc b/bin/media/media_player/player/conversion_pipeline_builder.cc
index 0ebe729..a8a0413 100644
--- a/bin/media/media_player/player/conversion_pipeline_builder.cc
+++ b/bin/media/media_player/player/conversion_pipeline_builder.cc
@@ -97,9 +97,7 @@
 AddResult AddTransformsForCompressedAudio(
     const AudioStreamType& in_type,
     const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets,
-    Graph* graph,
-    OutputRef* output,
-    std::unique_ptr<StreamType>* out_type) {
+    Graph* graph, OutputRef* output, std::unique_ptr<StreamType>* out_type) {
   FXL_DCHECK(out_type);
   FXL_DCHECK(graph);
 
@@ -150,9 +148,7 @@
 AddResult AddTransformsForCompressedVideo(
     const VideoStreamType& in_type,
     const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets,
-    Graph* graph,
-    OutputRef* output,
-    std::unique_ptr<StreamType>* out_type) {
+    Graph* graph, OutputRef* output, std::unique_ptr<StreamType>* out_type) {
   FXL_DCHECK(out_type);
   FXL_DCHECK(graph);
 
@@ -179,8 +175,7 @@
 // output type. Otherwise, *out_type is set to nullptr.
 AddResult AddTransformsForLpcm(const AudioStreamType& in_type,
                                const AudioStreamTypeSet& out_type_set,
-                               Graph* graph,
-                               OutputRef* output,
+                               Graph* graph, OutputRef* output,
                                std::unique_ptr<StreamType>* out_type) {
   FXL_DCHECK(graph);
   FXL_DCHECK(out_type);
@@ -227,9 +222,7 @@
 AddResult AddTransformsForLpcm(
     const AudioStreamType& in_type,
     const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets,
-    Graph* graph,
-    OutputRef* output,
-    std::unique_ptr<StreamType>* out_type) {
+    Graph* graph, OutputRef* output, std::unique_ptr<StreamType>* out_type) {
   FXL_DCHECK(graph);
   FXL_DCHECK(out_type);
 
@@ -255,9 +248,7 @@
 AddResult AddTransforms(
     const StreamType& in_type,
     const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets,
-    Graph* graph,
-    OutputRef* output,
-    std::unique_ptr<StreamType>* out_type) {
+    Graph* graph, OutputRef* output, std::unique_ptr<StreamType>* out_type) {
   FXL_DCHECK(graph);
   FXL_DCHECK(out_type);
 
@@ -291,9 +282,7 @@
 bool BuildConversionPipeline(
     const StreamType& in_type,
     const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets,
-    Graph* graph,
-    OutputRef* output,
-    std::unique_ptr<StreamType>* out_type) {
+    Graph* graph, OutputRef* output, std::unique_ptr<StreamType>* out_type) {
   FXL_DCHECK(graph);
   FXL_DCHECK(output);
   FXL_DCHECK(out_type);
diff --git a/bin/media/media_player/player/conversion_pipeline_builder.h b/bin/media/media_player/player/conversion_pipeline_builder.h
index 0c7ea03..31f03c7 100644
--- a/bin/media/media_player/player/conversion_pipeline_builder.h
+++ b/bin/media/media_player/player/conversion_pipeline_builder.h
@@ -18,9 +18,7 @@
 bool BuildConversionPipeline(
     const StreamType& in_type,
     const std::vector<std::unique_ptr<StreamTypeSet>>& out_type_sets,
-    Graph* graph,
-    OutputRef* output,
-    std::unique_ptr<StreamType>* out_type);
+    Graph* graph, OutputRef* output, std::unique_ptr<StreamType>* out_type);
 
 }  // namespace media_player
 
diff --git a/bin/media/media_player/player/demux_source_segment.cc b/bin/media/media_player/player/demux_source_segment.cc
index 57ce5bb..e570698 100644
--- a/bin/media/media_player/player/demux_source_segment.cc
+++ b/bin/media/media_player/player/demux_source_segment.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/bin/media/media_player/player/demux_source_segment.h"
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 
 #include "garnet/bin/media/media_player/util/safe_clone.h"
@@ -76,14 +76,14 @@
   }
 }
 
-void DemuxSourceSegment::Flush(bool hold_frame, fxl::Closure callback) {
+void DemuxSourceSegment::Flush(bool hold_frame, fit::closure callback) {
   FXL_DCHECK(demux_initialized_.occurred());
-  graph().FlushAllOutputs(demux_node_, hold_frame, callback);
+  graph().FlushAllOutputs(demux_node_, hold_frame, std::move(callback));
 }
 
-void DemuxSourceSegment::Seek(int64_t position, fxl::Closure callback) {
+void DemuxSourceSegment::Seek(int64_t position, fit::closure callback) {
   FXL_DCHECK(demux_initialized_.occurred());
-  demux_->Seek(position, callback);
+  demux_->Seek(position, std::move(callback));
 }
 
 }  // namespace media_player
diff --git a/bin/media/media_player/player/demux_source_segment.h b/bin/media/media_player/player/demux_source_segment.h
index 137192a..9814608 100644
--- a/bin/media/media_player/player/demux_source_segment.h
+++ b/bin/media/media_player/player/demux_source_segment.h
@@ -32,9 +32,9 @@
 
   const Metadata* metadata() const override { return metadata_.get(); }
 
-  void Flush(bool hold_frame, fxl::Closure callback) override;
+  void Flush(bool hold_frame, fit::closure callback) override;
 
-  void Seek(int64_t position, fxl::Closure callback) override;
+  void Seek(int64_t position, fit::closure callback) override;
 
   NodeRef source_node() const override { return demux_node_; }
 
diff --git a/bin/media/media_player/player/player.cc b/bin/media/media_player/player/player.cc
index 108ab94..341564a 100644
--- a/bin/media/media_player/player/player.cc
+++ b/bin/media/media_player/player/player.cc
@@ -21,7 +21,7 @@
 Player::~Player() {}
 
 void Player::SetSourceSegment(std::unique_ptr<SourceSegment> source_segment,
-                              fxl::Closure callback) {
+                              fit::closure callback) {
   if (source_segment_) {
     while (!streams_.empty()) {
       OnStreamRemoval(streams_.size() - 1);
@@ -39,7 +39,7 @@
     return;
   }
 
-  set_source_segment_callback_ = callback;
+  set_source_segment_callback_ = std::move(callback);
   set_source_segment_countdown_ = 1;
 
   source_segment_->Provision(&graph_, async_,
@@ -97,7 +97,7 @@
   parked_sink_segments_[medium] = std::move(sink_segment);
 }
 
-void Player::Prime(fxl::Closure callback) {
+void Player::Prime(fit::closure callback) {
   auto callback_joiner = CallbackJoiner::Create();
 
   for (auto& stream : streams_) {
@@ -106,30 +106,33 @@
     }
   }
 
-  callback_joiner->WhenJoined(
-      [this, callback]() { async::PostTask(async_, callback); });
+  callback_joiner->WhenJoined([this, callback = std::move(callback)]() mutable {
+    async::PostTask(async_, std::move(callback));
+  });
 }
 
-void Player::Flush(bool hold_frame, fxl::Closure callback) {
+void Player::Flush(bool hold_frame, fit::closure callback) {
   if (source_segment_) {
-    source_segment_->Flush(
-        hold_frame, [this, callback]() { async::PostTask(async_, callback); });
+    source_segment_->Flush(hold_frame,
+                           [this, callback = std::move(callback)]() mutable {
+                             async::PostTask(async_, std::move(callback));
+                           });
   } else {
-    async::PostTask(async_, callback);
+    async::PostTask(async_, std::move(callback));
   }
 }
 
 void Player::SetTimelineFunction(media::TimelineFunction timeline_function,
-                                 fxl::Closure callback) {
+                                 fit::closure callback) {
   FXL_DCHECK(timeline_function.reference_delta() != 0);
 
   int64_t reference_time = timeline_function.reference_time();
-  if (reference_time == media::kUnspecifiedTime) {
+  if (reference_time == fuchsia::media::kUnspecifiedTime) {
     reference_time = media::Timeline::local_now() + kMinimumLeadTime;
   }
 
   int64_t subject_time = timeline_function.subject_time();
-  if (subject_time == media::kUnspecifiedTime) {
+  if (subject_time == fuchsia::media::kUnspecifiedTime) {
     subject_time = timeline_function_(reference_time);
   }
 
@@ -145,8 +148,9 @@
     }
   }
 
-  callback_joiner->WhenJoined(
-      [this, callback]() { async::PostTask(async_, callback); });
+  callback_joiner->WhenJoined([this, callback = std::move(callback)]() mutable {
+    async::PostTask(async_, std::move(callback));
+  });
 }
 
 void Player::SetProgramRange(uint64_t program, int64_t min_pts,
@@ -158,12 +162,14 @@
   }
 }
 
-void Player::Seek(int64_t position, fxl::Closure callback) {
+void Player::Seek(int64_t position, fit::closure callback) {
   if (source_segment_) {
-    source_segment_->Seek(
-        position, [this, callback]() { async::PostTask(async_, callback); });
+    source_segment_->Seek(position,
+                          [this, callback = std::move(callback)]() mutable {
+                            async::PostTask(async_, std::move(callback));
+                          });
   } else {
-    async::PostTask(async_, callback);
+    async::PostTask(async_, std::move(callback));
   }
 }
 
@@ -191,7 +197,7 @@
   return nullptr;
 }
 
-const Problem* Player::problem() const {
+const fuchsia::mediaplayer::Problem* Player::problem() const {
   // First, see if the source segment has a problem to report.
   if (source_segment_ && source_segment_->problem()) {
     return source_segment_->problem();
@@ -303,8 +309,7 @@
   }
 
   if (--set_source_segment_countdown_ == 0) {
-    fxl::Closure callback = set_source_segment_callback_;
-    set_source_segment_callback_ = nullptr;
+    fit::closure callback = std::move(set_source_segment_callback_);
     callback();
   }
 }
diff --git a/bin/media/media_player/player/player.h b/bin/media/media_player/player/player.h
index 0ae6f39..7e3fa35 100644
--- a/bin/media/media_player/player/player.h
+++ b/bin/media/media_player/player/player.h
@@ -8,8 +8,8 @@
 #include <unordered_map>
 #include <vector>
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async/dispatcher.h>
-#include <media/cpp/fidl.h>
 
 #include "garnet/bin/media/media_player/framework/graph.h"
 #include "garnet/bin/media/media_player/framework/metadata.h"
@@ -30,8 +30,8 @@
   // Sets the callback to be called when the status of the player is updated.
   // This callback notifies of changes to end_of_stream(), metadata() and/or
   // problem().
-  void SetUpdateCallback(fxl::Closure update_callback) {
-    update_callback_ = update_callback;
+  void SetUpdateCallback(fit::closure update_callback) {
+    update_callback_ = std::move(update_callback);
   }
 
   // Sets the current source segment. |source_segment| may be null, indicating
@@ -39,7 +39,7 @@
   // of streams supplied by the segment have been connected and prepared to the
   // extent possible. |callback| may be null.
   void SetSourceSegment(std::unique_ptr<SourceSegment> source_segment,
-                        fxl::Closure callback);
+                        fit::closure callback);
 
   // Sets the current sink segment for the specified medium. |sink_segment| may
   // be null, indicating there is no sink segment for the specified medium.
@@ -76,15 +76,15 @@
 
   // Prepares the graph for playback by satisfying initial renderer demand.
   // |callback| will never be called synchronously.
-  void Prime(fxl::Closure callback);
+  void Prime(fit::closure callback);
 
   // Flushes packets from the graph. |callback| will never be called
   // synchronously.
-  void Flush(bool hold_frame, fxl::Closure callback);
+  void Flush(bool hold_frame, fit::closure callback);
 
   // Sets the timeline function. |callback| will never be called synchronously.
   void SetTimelineFunction(media::TimelineFunction timeline_function,
-                           fxl::Closure callback);
+                           fit::closure callback);
 
   const media::TimelineFunction& timeline_function() {
     return timeline_function_;
@@ -95,7 +95,7 @@
 
   // Seeks to the specified position. |callback| will never be called
   // synchronously.
-  void Seek(int64_t position, fxl::Closure callback);
+  void Seek(int64_t position, fit::closure callback);
 
   // Indicates whether the player has reached end of stream.
   bool end_of_stream() const;
@@ -107,7 +107,7 @@
 
   // Returns the current problem preventing intended operation or nullptr if
   // there is no such problem.
-  const Problem* problem() const;
+  const fuchsia::mediaplayer::Problem* problem() const;
 
   // Test only.
   // Returns a pointer to the graph.
@@ -171,8 +171,8 @@
 
   Graph graph_;
   async_t* async_;
-  fxl::Closure update_callback_;
-  fxl::Closure set_source_segment_callback_;
+  fit::closure update_callback_;
+  fit::closure set_source_segment_callback_;
   size_t set_source_segment_countdown_;
   std::unique_ptr<SourceSegment> source_segment_;
   std::vector<Stream> streams_;
diff --git a/bin/media/media_player/player/renderer_sink_segment.cc b/bin/media/media_player/player/renderer_sink_segment.cc
index f025008..cb908e7 100644
--- a/bin/media/media_player/player/renderer_sink_segment.cc
+++ b/bin/media/media_player/player/renderer_sink_segment.cc
@@ -52,8 +52,8 @@
   if (!BuildConversionPipeline(type, supported_stream_types, &graph(),
                                &output_in_out, &out_type)) {
     ReportProblem(type.medium() == StreamType::Medium::kAudio
-                      ? kProblemAudioEncodingNotSupported
-                      : kProblemVideoEncodingNotSupported,
+                      ? fuchsia::mediaplayer::kProblemAudioEncodingNotSupported
+                      : fuchsia::mediaplayer::kProblemVideoEncodingNotSupported,
                   "");
     callback(Result::kUnsupportedOperation);
     return;
@@ -98,20 +98,18 @@
   }
 }
 
-void RendererSinkSegment::Prime(fxl::Closure callback) {
+void RendererSinkSegment::Prime(fit::closure callback) {
   FXL_DCHECK(renderer_);
-  renderer_->Prime(callback);
+  renderer_->Prime(std::move(callback));
 }
 
 void RendererSinkSegment::SetTimelineFunction(
-    media::TimelineFunction timeline_function,
-    fxl::Closure callback) {
+    media::TimelineFunction timeline_function, fit::closure callback) {
   FXL_DCHECK(renderer_);
-  renderer_->SetTimelineFunction(timeline_function, callback);
+  renderer_->SetTimelineFunction(timeline_function, std::move(callback));
 }
 
-void RendererSinkSegment::SetProgramRange(uint64_t program,
-                                          int64_t min_pts,
+void RendererSinkSegment::SetProgramRange(uint64_t program, int64_t min_pts,
                                           int64_t max_pts) {
   FXL_DCHECK(renderer_);
   renderer_->SetProgramRange(program, min_pts, max_pts);
diff --git a/bin/media/media_player/player/renderer_sink_segment.h b/bin/media/media_player/player/renderer_sink_segment.h
index 93b8a2f..9f54410 100644
--- a/bin/media/media_player/player/renderer_sink_segment.h
+++ b/bin/media/media_player/player/renderer_sink_segment.h
@@ -36,10 +36,10 @@
 
   void Unprepare() override;
 
-  void Prime(fxl::Closure callback) override;
+  void Prime(fit::closure callback) override;
 
   void SetTimelineFunction(media::TimelineFunction timeline_function,
-                           fxl::Closure callback) override;
+                           fit::closure callback) override;
 
   void SetProgramRange(uint64_t program, int64_t min_pts,
                        int64_t max_pts) override;
diff --git a/bin/media/media_player/player/segment.cc b/bin/media/media_player/player/segment.cc
index 13416c1..375187e 100644
--- a/bin/media/media_player/player/segment.cc
+++ b/bin/media/media_player/player/segment.cc
@@ -14,12 +14,11 @@
 
 Segment::~Segment() {}
 
-void Segment::Provision(Graph* graph,
-                        async_t* async,
-                        fxl::Closure update_callback) {
+void Segment::Provision(Graph* graph, async_t* async,
+                        fit::closure update_callback) {
   graph_ = graph;
   async_ = async;
-  update_callback_ = update_callback;
+  update_callback_ = std::move(update_callback);
   DidProvision();
 }
 
@@ -43,7 +42,7 @@
     return;
   }
 
-  problem_ = Problem::New();
+  problem_ = fuchsia::mediaplayer::Problem::New();
   problem_->type = type;
   problem_->details = details;
   NotifyUpdate();
diff --git a/bin/media/media_player/player/segment.h b/bin/media/media_player/player/segment.h
index 29f4307..b69fcab 100644
--- a/bin/media/media_player/player/segment.h
+++ b/bin/media/media_player/player/segment.h
@@ -5,13 +5,13 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_SEGMENT_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_SEGMENT_H_
 
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/framework/graph.h"
 #include "garnet/bin/media/media_player/framework/metadata.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 
 namespace media_player {
@@ -35,7 +35,7 @@
   // changes. The update callback is used to notify of changes to the value
   // returned by problem(). Subclasses of Segment may use this callback to
   // signal additional changes.
-  void Provision(Graph* graph, async_t* async, fxl::Closure update_callback);
+  void Provision(Graph* graph, async_t* async, fit::closure update_callback);
 
   // Revokes the graph, task runner and update callback provided in a previous
   // call to |Provision|.
@@ -43,7 +43,9 @@
 
   // Returns the current problem preventing intended operation or nullptr if
   // there is no such problem.
-  const Problem* problem() const { return problem_.get(); }
+  const fuchsia::mediaplayer::Problem* problem() const {
+    return problem_.get();
+  }
 
  protected:
   Graph& graph() {
@@ -79,8 +81,8 @@
  private:
   Graph* graph_ = nullptr;
   async_t* async_ = nullptr;
-  fxl::Closure update_callback_;
-  ProblemPtr problem_;
+  fit::closure update_callback_;
+  fuchsia::mediaplayer::ProblemPtr problem_;
 };
 
 }  // namespace media_player
diff --git a/bin/media/media_player/player/sink_segment.h b/bin/media/media_player/player/sink_segment.h
index 8951877..f9886e3 100644
--- a/bin/media/media_player/player/sink_segment.h
+++ b/bin/media/media_player/player/sink_segment.h
@@ -5,6 +5,8 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_SINK_SEGMENT_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_SINK_SEGMENT_H_
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/framework/graph.h"
 #include "garnet/bin/media/media_player/framework/result.h"
 #include "garnet/bin/media/media_player/framework/types/stream_type.h"
@@ -20,7 +22,7 @@
 // notify of changes to the value returned by end_of_stream().
 class SinkSegment : public Segment {
  public:
-  using ConnectCallback = std::function<void(Result)>;
+  using ConnectCallback = fit::function<void(Result)>;
 
   SinkSegment();
 
@@ -49,11 +51,11 @@
 
   // Prepares the sink segment for playback by satisfying initial renderer
   // demand.
-  virtual void Prime(fxl::Closure callback) = 0;
+  virtual void Prime(fit::closure callback) = 0;
 
   // Sets the timeline function.
   virtual void SetTimelineFunction(media::TimelineFunction timeline_function,
-                                   fxl::Closure callback) = 0;
+                                   fit::closure callback) = 0;
 
   // Sets a program range for this sink segment.
   virtual void SetProgramRange(uint64_t program, int64_t min_pts,
diff --git a/bin/media/media_player/player/source_segment.cc b/bin/media/media_player/player/source_segment.cc
index 625a1cc..697acff 100644
--- a/bin/media/media_player/player/source_segment.cc
+++ b/bin/media/media_player/player/source_segment.cc
@@ -14,12 +14,11 @@
 
 SourceSegment::~SourceSegment() {}
 
-void SourceSegment::Provision(Graph* graph,
-                              async_t* async,
-                              fxl::Closure updateCallback,
+void SourceSegment::Provision(Graph* graph, async_t* async,
+                              fit::closure updateCallback,
                               StreamUpdateCallback stream_update_callback) {
-  stream_update_callback_ = stream_update_callback;
-  Segment::Provision(graph, async, updateCallback);
+  stream_update_callback_ = std::move(stream_update_callback);
+  Segment::Provision(graph, async, std::move(updateCallback));
 }
 
 void SourceSegment::Deprovision() {
@@ -27,10 +26,8 @@
   stream_update_callback_ = nullptr;
 }
 
-void SourceSegment::OnStreamUpdated(size_t index,
-                                    const StreamType& type,
-                                    OutputRef output,
-                                    bool more) {
+void SourceSegment::OnStreamUpdated(size_t index, const StreamType& type,
+                                    OutputRef output, bool more) {
   FXL_DCHECK(stream_update_callback_)
       << "OnStreamUpdated() called on unprovisioned segment.";
 
diff --git a/bin/media/media_player/player/source_segment.h b/bin/media/media_player/player/source_segment.h
index 32f9416..b6e3289 100644
--- a/bin/media/media_player/player/source_segment.h
+++ b/bin/media/media_player/player/source_segment.h
@@ -6,10 +6,10 @@
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_SOURCE_SEGMENT_H_
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/framework/graph.h"
 #include "garnet/bin/media/media_player/player/segment.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace media_player {
 
@@ -22,8 +22,8 @@
 // concerned with metadata.
 class SourceSegment : public Segment {
  public:
-  using StreamUpdateCallback = std::function<
-      void(size_t index, const StreamType* type, OutputRef output, bool more)>;
+  using StreamUpdateCallback = fit::function<void(
+      size_t index, const StreamType* type, OutputRef output, bool more)>;
 
   SourceSegment();
 
@@ -32,9 +32,7 @@
   // Provides the graph, async and callbacks for this source segment.
   // The player expects stream updates shortly after this method is called,
   // the last of which should have a |more| value of false.
-  void Provision(Graph* graph,
-                 async_t* async,
-                 fxl::Closure updateCallback,
+  void Provision(Graph* graph, async_t* async, fit::closure updateCallback,
                  StreamUpdateCallback stream_update_callback);
 
   // Revokes the graph, task runner and callbacks provided in a previous call to
@@ -46,10 +44,10 @@
   virtual const Metadata* metadata() const = 0;
 
   // Flushes the source.
-  virtual void Flush(bool hold_frame, fxl::Closure callback) = 0;
+  virtual void Flush(bool hold_frame, fit::closure callback) = 0;
 
   // Seeks to the specified position.
-  virtual void Seek(int64_t position, fxl::Closure callback) = 0;
+  virtual void Seek(int64_t position, fit::closure callback) = 0;
 
   // Test only.
   // Returns a reference to the source node.
@@ -57,9 +55,7 @@
 
  protected:
   // Called by subclasses when a stream is updated.
-  void OnStreamUpdated(size_t index,
-                       const StreamType& type,
-                       OutputRef output,
+  void OnStreamUpdated(size_t index, const StreamType& type, OutputRef output,
                        bool more);
 
   // Called by subclasses when a stream is removed.
diff --git a/bin/media/media_player/player/test/fake_audio_renderer.cc b/bin/media/media_player/player/test/fake_audio_renderer.cc
index fdbe0bf..5deb938 100644
--- a/bin/media/media_player/player/test/fake_audio_renderer.cc
+++ b/bin/media/media_player/player/test/fake_audio_renderer.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/bin/media/media_player/player/test/fake_audio_renderer.h"
+
 #include "garnet/bin/media/media_player/framework/types/audio_stream_type.h"
 
 namespace media_player {
diff --git a/bin/media/media_player/player/test/fake_audio_renderer.h b/bin/media/media_player/player/test/fake_audio_renderer.h
index 041af1f..3103efa 100644
--- a/bin/media/media_player/player/test/fake_audio_renderer.h
+++ b/bin/media/media_player/player/test/fake_audio_renderer.h
@@ -23,7 +23,7 @@
 
   // Renderer implementation.
   void FlushInput(bool hold_frame, size_t input_index,
-                  fxl::Closure callback) override {
+                  fit::closure callback) override {
     FXL_DCHECK(input_index == 0);
     FXL_DCHECK(callback);
     callback();
@@ -46,10 +46,10 @@
     stream_type_ = stream_type.Clone();
   }
 
-  void Prime(fxl::Closure callback) override { callback(); }
+  void Prime(fit::closure callback) override { callback(); }
 
   void SetTimelineFunction(media::TimelineFunction timeline_function,
-                           fxl::Closure callback) override {
+                           fit::closure callback) override {
     callback();
   }
 
diff --git a/bin/media/media_player/player/test/fake_decoder.h b/bin/media/media_player/player/test/fake_decoder.h
index 64ef86bc..ffe5a72 100644
--- a/bin/media/media_player/player/test/fake_decoder.h
+++ b/bin/media/media_player/player/test/fake_decoder.h
@@ -31,11 +31,11 @@
   }
 
   void FlushInput(bool hold_frame, size_t input_index,
-                  fxl::Closure callback) override {
+                  fit::closure callback) override {
     callback();
   }
 
-  void FlushOutput(size_t output_index, fxl::Closure callback) override {
+  void FlushOutput(size_t output_index, fit::closure callback) override {
     callback();
   }
 
diff --git a/bin/media/media_player/player/test/fake_demux.h b/bin/media/media_player/player/test/fake_demux.h
index c23f1c9..315731f 100644
--- a/bin/media/media_player/player/test/fake_demux.h
+++ b/bin/media/media_player/player/test/fake_demux.h
@@ -7,6 +7,8 @@
 
 #include "garnet/bin/media/media_player/demux/demux.h"
 
+#include <lib/fit/function.h>
+
 namespace media_player {
 namespace test {
 
@@ -28,17 +30,17 @@
     *output_count = streams_.size();
   }
 
-  void FlushOutput(size_t output_index, fxl::Closure callback) override {
+  void FlushOutput(size_t output_index, fit::closure callback) override {
     callback();
   }
 
   void RequestOutputPacket() override {}
 
   void SetStatusCallback(StatusCallback callback) override {
-    status_callback_ = callback;
+    status_callback_ = std::move(callback);
   }
 
-  void WhenInitialized(std::function<void(Result)> callback) override {
+  void WhenInitialized(fit::function<void(Result)> callback) override {
     callback(Result::kOk);
   }
 
diff --git a/bin/media/media_player/player/test/fake_sink_segment.h b/bin/media/media_player/player/test/fake_sink_segment.h
index 11d96f4..81d4d38 100644
--- a/bin/media/media_player/player/test/fake_sink_segment.h
+++ b/bin/media/media_player/player/test/fake_sink_segment.h
@@ -5,6 +5,8 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_TEST_FAKE_SINK_SEGMENT_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_TEST_FAKE_SINK_SEGMENT_H_
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/player/sink_segment.h"
 
 namespace media_player {
@@ -13,12 +15,12 @@
 class FakeSinkSegment : public SinkSegment {
  public:
   static std::unique_ptr<FakeSinkSegment> Create(
-      std::function<void(FakeSinkSegment*)> destroy_callback) {
-    return std::make_unique<FakeSinkSegment>(destroy_callback);
+      fit::function<void(FakeSinkSegment*)> destroy_callback) {
+    return std::make_unique<FakeSinkSegment>(std::move(destroy_callback));
   }
 
-  FakeSinkSegment(std::function<void(FakeSinkSegment*)> destroy_callback)
-      : destroy_callback_(destroy_callback) {
+  FakeSinkSegment(fit::function<void(FakeSinkSegment*)> destroy_callback)
+      : destroy_callback_(std::move(destroy_callback)) {
     FXL_DCHECK(destroy_callback_);
   }
 
@@ -34,7 +36,7 @@
     connect_called_ = true;
     connect_call_param_type_ = &type;
     connect_call_param_output_ = output;
-    connect_call_param_callback_ = callback;
+    connect_call_param_callback_ = std::move(callback);
   }
 
   void Disconnect() override { disconnect_called_ = true; }
@@ -45,16 +47,16 @@
 
   void Unprepare() override { unprepare_called_ = true; }
 
-  void Prime(fxl::Closure callback) override {
+  void Prime(fit::closure callback) override {
     prime_called_ = true;
-    prime_call_param_callback_ = callback;
+    prime_call_param_callback_ = std::move(callback);
   }
 
   void SetTimelineFunction(media::TimelineFunction timeline_function,
-                           fxl::Closure callback) override {
+                           fit::closure callback) override {
     set_timeline_function_called_ = true;
     set_timeline_function_call_param_timeline_function_ = timeline_function;
-    set_timeline_function_call_param_callback_ = callback;
+    set_timeline_function_call_param_callback_ = std::move(callback);
   }
 
   void SetProgramRange(uint64_t program, int64_t min_pts,
@@ -85,7 +87,7 @@
 
  public:
   // Instrumentation for test.
-  std::function<void(FakeSinkSegment*)> destroy_callback_;
+  fit::function<void(FakeSinkSegment*)> destroy_callback_;
 
   bool did_provision_called_ = false;
   bool will_deprovision_called_ = false;
@@ -104,11 +106,11 @@
   bool unprepare_called_ = false;
 
   bool prime_called_ = false;
-  fxl::Closure prime_call_param_callback_;
+  fit::closure prime_call_param_callback_;
 
   bool set_timeline_function_called_ = false;
   media::TimelineFunction set_timeline_function_call_param_timeline_function_;
-  fxl::Closure set_timeline_function_call_param_callback_;
+  fit::closure set_timeline_function_call_param_callback_;
 
   bool set_program_range_called_ = false;
   uint64_t set_program_range_call_param_program_;
diff --git a/bin/media/media_player/player/test/fake_source_segment.h b/bin/media/media_player/player/test/fake_source_segment.h
index 154cf4e..2cd8c53 100644
--- a/bin/media/media_player/player/test/fake_source_segment.h
+++ b/bin/media/media_player/player/test/fake_source_segment.h
@@ -5,6 +5,8 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_TEST_FAKE_SOURCE_SEGMENT_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_PLAYER_TEST_FAKE_SOURCE_SEGMENT_H_
 
+#include <lib/fit/function.h>
+
 #include "garnet/bin/media/media_player/player/source_segment.h"
 
 namespace media_player {
@@ -13,12 +15,12 @@
 class FakeSourceSegment : public SourceSegment {
  public:
   static std::unique_ptr<FakeSourceSegment> Create(
-      std::function<void(FakeSourceSegment*)> destroy_callback) {
-    return std::make_unique<FakeSourceSegment>(destroy_callback);
+      fit::function<void(FakeSourceSegment*)> destroy_callback) {
+    return std::make_unique<FakeSourceSegment>(std::move(destroy_callback));
   }
 
-  FakeSourceSegment(std::function<void(FakeSourceSegment*)> destroy_callback)
-      : destroy_callback_(destroy_callback) {
+  FakeSourceSegment(fit::function<void(FakeSourceSegment*)> destroy_callback)
+      : destroy_callback_(std::move(destroy_callback)) {
     FXL_DCHECK(destroy_callback_);
   }
 
@@ -31,16 +33,16 @@
 
   const Metadata* metadata() const override { return metadata_; }
 
-  void Flush(bool hold_frame, fxl::Closure callback) override {
+  void Flush(bool hold_frame, fit::closure callback) override {
     flush_called_ = true;
     flush_call_param_hold_frame_ = hold_frame;
     callback();
   }
 
-  void Seek(int64_t position, fxl::Closure callback) override {
+  void Seek(int64_t position, fit::closure callback) override {
     seek_called_ = true;
     seek_call_param_position_ = position;
-    seek_call_param_callback_ = callback;
+    seek_call_param_callback_ = std::move(callback);
   }
 
   NodeRef source_node() const override { return NodeRef(); }
@@ -61,10 +63,8 @@
 
   bool TEST_provisioned() { return provisioned(); }
 
-  void TEST_OnStreamUpdated(size_t index,
-                            const StreamType& type,
-                            OutputRef output,
-                            bool more) {
+  void TEST_OnStreamUpdated(size_t index, const StreamType& type,
+                            OutputRef output, bool more) {
     OnStreamUpdated(index, type, output, more);
   }
 
@@ -74,7 +74,7 @@
 
  public:
   // Instrumentation for test.
-  std::function<void(FakeSourceSegment*)> destroy_callback_;
+  fit::function<void(FakeSourceSegment*)> destroy_callback_;
 
   bool did_provision_called_ = false;
   bool will_deprovision_called_ = false;
@@ -86,7 +86,7 @@
 
   bool seek_called_ = false;
   int64_t seek_call_param_position_;
-  fxl::Closure seek_call_param_callback_;
+  fit::closure seek_call_param_callback_;
 };
 
 }  // namespace media_player
diff --git a/bin/media/media_player/player/test/fake_video_renderer.h b/bin/media/media_player/player/test/fake_video_renderer.h
index 040ecb4..8dfbedb 100644
--- a/bin/media/media_player/player/test/fake_video_renderer.h
+++ b/bin/media/media_player/player/test/fake_video_renderer.h
@@ -23,7 +23,7 @@
 
   // Renderer implementation.
   void FlushInput(bool hold_frame, size_t input_index,
-                  fxl::Closure callback) override {
+                  fit::closure callback) override {
     FXL_DCHECK(input_index == 0);
     FXL_DCHECK(callback);
     callback();
@@ -44,10 +44,10 @@
     stream_type_ = stream_type.Clone();
   }
 
-  void Prime(fxl::Closure callback) override { callback(); }
+  void Prime(fit::closure callback) override { callback(); }
 
   void SetTimelineFunction(media::TimelineFunction timeline_function,
-                           fxl::Closure callback) override {
+                           fit::closure callback) override {
     callback();
   }
 
diff --git a/bin/media/media_player/render/fidl_audio_renderer.cc b/bin/media/media_player/render/fidl_audio_renderer.cc
index 0ce8d9a..32eed79 100644
--- a/bin/media/media_player/render/fidl_audio_renderer.cc
+++ b/bin/media/media_player/render/fidl_audio_renderer.cc
@@ -7,12 +7,12 @@
 #include <lib/async/default.h>
 
 #include "garnet/bin/media/media_player/fidl/fidl_type_conversions.h"
+#include "garnet/bin/media/media_player/framework/formatting.h"
+#include "lib/fxl/functional/make_copyable.h"
 #include "lib/fxl/logging.h"
 #include "lib/media/timeline/timeline.h"
 #include "lib/media/timeline/timeline_rate.h"
 
-#include "garnet/bin/media/media_player/framework/formatting.h"
-
 namespace media_player {
 namespace {
 
@@ -22,11 +22,12 @@
 
 // static
 std::shared_ptr<FidlAudioRenderer> FidlAudioRenderer::Create(
-    media::AudioRenderer2Ptr audio_renderer) {
+    fuchsia::media::AudioRenderer2Ptr audio_renderer) {
   return std::make_shared<FidlAudioRenderer>(std::move(audio_renderer));
 }
 
-FidlAudioRenderer::FidlAudioRenderer(media::AudioRenderer2Ptr audio_renderer)
+FidlAudioRenderer::FidlAudioRenderer(
+    fuchsia::media::AudioRenderer2Ptr audio_renderer)
     : audio_renderer_(std::move(audio_renderer)),
       allocator_(0),
       arrivals_(true),
@@ -52,19 +53,25 @@
   supported_stream_types_.push_back(AudioStreamTypeSet::Create(
       {StreamType::kAudioEncodingLpcm},
       AudioStreamType::SampleFormat::kUnsigned8,
-      Range<uint32_t>(media::kMinChannelCount, media::kMaxChannelCount),
-      Range<uint32_t>(media::kMinFramesPerSecond, media::kMaxFramesPerSecond)));
+      Range<uint32_t>(fuchsia::media::kMinChannelCount,
+                      fuchsia::media::kMaxChannelCount),
+      Range<uint32_t>(fuchsia::media::kMinFramesPerSecond,
+                      fuchsia::media::kMaxFramesPerSecond)));
 
   supported_stream_types_.push_back(AudioStreamTypeSet::Create(
       {StreamType::kAudioEncodingLpcm},
       AudioStreamType::SampleFormat::kSigned16,
-      Range<uint32_t>(media::kMinChannelCount, media::kMaxChannelCount),
-      Range<uint32_t>(media::kMinFramesPerSecond, media::kMaxFramesPerSecond)));
+      Range<uint32_t>(fuchsia::media::kMinChannelCount,
+                      fuchsia::media::kMaxChannelCount),
+      Range<uint32_t>(fuchsia::media::kMinFramesPerSecond,
+                      fuchsia::media::kMaxFramesPerSecond)));
 
   supported_stream_types_.push_back(AudioStreamTypeSet::Create(
       {StreamType::kAudioEncodingLpcm}, AudioStreamType::SampleFormat::kFloat,
-      Range<uint32_t>(media::kMinChannelCount, media::kMaxChannelCount),
-      Range<uint32_t>(media::kMinFramesPerSecond, media::kMaxFramesPerSecond)));
+      Range<uint32_t>(fuchsia::media::kMinChannelCount,
+                      fuchsia::media::kMaxChannelCount),
+      Range<uint32_t>(fuchsia::media::kMinFramesPerSecond,
+                      fuchsia::media::kMaxFramesPerSecond)));
 }
 
 FidlAudioRenderer::~FidlAudioRenderer() {
@@ -100,19 +107,20 @@
 }
 
 void FidlAudioRenderer::FlushInput(bool hold_frame_not_used, size_t input_index,
-                                   fxl::Closure callback) {
+                                   fit::closure callback) {
   FXL_DCHECK(async_get_default() == async());
   FXL_DCHECK(input_index == 0);
   FXL_DCHECK(callback);
 
   flushed_ = true;
-  SetEndOfStreamPts(media::kUnspecifiedTime);
+  SetEndOfStreamPts(fuchsia::media::kUnspecifiedTime);
 
-  audio_renderer_->Flush([this, callback]() {
-    last_supplied_pts_ns_ = 0;
-    last_departed_pts_ns_ = media::kUnspecifiedTime;
-    callback();
-  });
+  audio_renderer_->Flush(
+      fxl::MakeCopyable([this, callback = std::move(callback)]() {
+        last_supplied_pts_ns_ = 0;
+        last_departed_pts_ns_ = fuchsia::media::kUnspecifiedTime;
+        callback();
+      }));
 }
 
 void FidlAudioRenderer::PutInputPacket(PacketPtr packet, size_t input_index) {
@@ -138,7 +146,7 @@
                       Progressing());
 
   last_supplied_pts_ns_ = end_pts_ns;
-  if (last_departed_pts_ns_ == media::kUnspecifiedTime) {
+  if (last_departed_pts_ns_ == fuchsia::media::kUnspecifiedTime) {
     last_departed_pts_ns_ = start_pts_ns;
   }
 
@@ -161,7 +169,7 @@
     packet.reset();
     UpdateTimeline(media::Timeline::local_now());
   } else {
-    media::AudioPacket audioPacket;
+    fuchsia::media::AudioPacket audioPacket;
     audioPacket.timestamp = start_pts;
     audioPacket.payload_size = packet->size();
 
@@ -201,9 +209,9 @@
   FXL_DCHECK(async_get_default() == async());
   FXL_DCHECK(stream_type.audio());
 
-  media::AudioPcmFormat format;
-  format.sample_format =
-      fxl::To<media::AudioSampleFormat>(stream_type.audio()->sample_format());
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = fxl::To<fuchsia::media::AudioSampleFormat>(
+      stream_type.audio()->sample_format());
   format.channels = stream_type.audio()->channels();
   format.frames_per_second = stream_type.audio()->frames_per_second();
 
@@ -232,7 +240,7 @@
   bytes_per_frame_ = stream_type.audio()->bytes_per_frame();
 }
 
-void FidlAudioRenderer::Prime(fxl::Closure callback) {
+void FidlAudioRenderer::Prime(fit::closure callback) {
   FXL_DCHECK(async_get_default() == async());
 
   if (prime_callback_) {
@@ -248,12 +256,12 @@
     return;
   }
 
-  prime_callback_ = callback;
+  prime_callback_ = std::move(callback);
   SignalCurrentDemand();
 }
 
 void FidlAudioRenderer::SetTimelineFunction(
-    media::TimelineFunction timeline_function, fxl::Closure callback) {
+    media::TimelineFunction timeline_function, fit::closure callback) {
   FXL_DCHECK(async_get_default() == async());
   // AudioRenderer2 only supports 0/1 (paused) or 1/1 (normal playback rate).
   // TODO(dalesat): Remove this DCHECK when AudioRenderer2 supports other rates,
@@ -262,7 +270,7 @@
              (timeline_function.subject_delta() == 1 &&
               timeline_function.reference_delta() == 1));
 
-  Renderer::SetTimelineFunction(timeline_function, callback);
+  Renderer::SetTimelineFunction(timeline_function, std::move(callback));
 
   if (timeline_function.subject_delta() == 0) {
     audio_renderer_->PauseNoReply();
@@ -318,7 +326,7 @@
 
   if (presentation_time_ns + min_lead_time_ns_ > last_supplied_pts_ns_) {
     // We need more packets to meet lead time commitments.
-    if (last_departed_pts_ns_ != media::kUnspecifiedTime &&
+    if (last_departed_pts_ns_ != fuchsia::media::kUnspecifiedTime &&
         last_supplied_pts_ns_ - last_departed_pts_ns_ > kWarnThresholdNs) {
       FXL_LOG(WARNING) << "Audio renderer holding too much content:";
       FXL_LOG(WARNING) << "    total content "
diff --git a/bin/media/media_player/render/fidl_audio_renderer.h b/bin/media/media_player/render/fidl_audio_renderer.h
index 1880693..572dcf9 100644
--- a/bin/media/media_player/render/fidl_audio_renderer.h
+++ b/bin/media/media_player/render/fidl_audio_renderer.h
@@ -5,7 +5,7 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_RENDER_FIDL_AUDIO_RENDERER_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_RENDER_FIDL_AUDIO_RENDERER_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 
 #include "garnet/bin/media/media_player/metrics/packet_timing_tracker.h"
@@ -26,9 +26,9 @@
       public std::enable_shared_from_this<FidlAudioRenderer> {
  public:
   static std::shared_ptr<FidlAudioRenderer> Create(
-      media::AudioRenderer2Ptr audio_renderer);
+      fuchsia::media::AudioRenderer2Ptr audio_renderer);
 
-  FidlAudioRenderer(media::AudioRenderer2Ptr audio_renderer);
+  FidlAudioRenderer(fuchsia::media::AudioRenderer2Ptr audio_renderer);
 
   ~FidlAudioRenderer() override;
 
@@ -38,7 +38,7 @@
   void Dump(std::ostream& os) const override;
 
   void FlushInput(bool hold_frame, size_t input_index,
-                  fxl::Closure callback) override;
+                  fit::closure callback) override;
 
   std::shared_ptr<PayloadAllocator> allocator_for_input(
       size_t input_index) override {
@@ -55,10 +55,10 @@
 
   void SetStreamType(const StreamType& stream_type) override;
 
-  void Prime(fxl::Closure callback) override;
+  void Prime(fit::closure callback) override;
 
   void SetTimelineFunction(media::TimelineFunction timeline_function,
-                           fxl::Closure callback) override;
+                           fit::closure callback) override;
 
   void SetGain(float gain) override;
 
@@ -90,11 +90,11 @@
   }
 
   std::vector<std::unique_ptr<StreamTypeSet>> supported_stream_types_;
-  media::AudioRenderer2Ptr audio_renderer_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer_;
   media::TimelineRate pts_rate_;
   int64_t last_supplied_pts_ns_ = 0;
   int64_t last_departed_pts_ns_ = 0;
-  fxl::Closure prime_callback_;
+  fit::closure prime_callback_;
   uint32_t bytes_per_frame_;
   bool flushed_ = true;
   int64_t min_lead_time_ns_ = ZX_MSEC(100);
diff --git a/bin/media/media_player/render/fidl_video_renderer.cc b/bin/media/media_player/render/fidl_video_renderer.cc
index 28d6a62..2164fb8 100644
--- a/bin/media/media_player/render/fidl_video_renderer.cc
+++ b/bin/media/media_player/render/fidl_video_renderer.cc
@@ -78,7 +78,7 @@
 }
 
 void FidlVideoRenderer::FlushInput(bool hold_frame, size_t input_index,
-                                   fxl::Closure callback) {
+                                   fit::closure callback) {
   FXL_DCHECK(input_index == 0);
   FXL_DCHECK(callback);
 
@@ -98,7 +98,7 @@
     held_packet_.reset();
   }
 
-  SetEndOfStreamPts(media::kUnspecifiedTime);
+  SetEndOfStreamPts(fuchsia::media::kUnspecifiedTime);
 
   InvalidateViews();
 
@@ -172,7 +172,7 @@
   converter_.SetStreamType(stream_type.Clone());
 }
 
-void FidlVideoRenderer::Prime(fxl::Closure callback) {
+void FidlVideoRenderer::Prime(fit::closure callback) {
   flushed_ = false;
 
   if (packet_queue_.size() >= kPacketDemand || end_of_stream_pending()) {
@@ -180,7 +180,7 @@
     return;
   }
 
-  prime_callback_ = callback;
+  prime_callback_ = std::move(callback);
   stage()->RequestInputPacket();
 }
 
@@ -192,13 +192,14 @@
   return converter_.GetPixelAspectRatio();
 }
 
-void FidlVideoRenderer::SetGeometryUpdateCallback(fxl::Closure callback) {
-  geometry_update_callback_ = callback;
+void FidlVideoRenderer::SetGeometryUpdateCallback(fit::closure callback) {
+  geometry_update_callback_ = std::move(callback);
 }
 
 void FidlVideoRenderer::CreateView(
     fidl::InterfacePtr<::fuchsia::ui::views_v1::ViewManager> view_manager,
-    fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request) {
+    fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+        view_owner_request) {
   auto view =
       std::make_unique<View>(std::move(view_manager),
                              std::move(view_owner_request), shared_from_this());
@@ -296,7 +297,8 @@
 
 FidlVideoRenderer::View::View(
     ::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
-    fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request,
+    fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+        view_owner_request,
     std::shared_ptr<FidlVideoRenderer> renderer)
     : mozart::BaseView(std::move(view_manager), std::move(view_owner_request),
                        "Video Renderer"),
diff --git a/bin/media/media_player/render/fidl_video_renderer.h b/bin/media/media_player/render/fidl_video_renderer.h
index 15e41bb..cb8a7e3 100644
--- a/bin/media/media_player/render/fidl_video_renderer.h
+++ b/bin/media/media_player/render/fidl_video_renderer.h
@@ -8,7 +8,7 @@
 #include <deque>
 #include <unordered_map>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 
 #include "garnet/bin/media/media_player/metrics/packet_timing_tracker.h"
 #include "garnet/bin/media/media_player/metrics/rate_tracker.h"
@@ -37,7 +37,7 @@
   void Dump(std::ostream& os) const override;
 
   void FlushInput(bool hold_frame, size_t input_index,
-                  fxl::Closure callback) override;
+                  fit::closure callback) override;
 
   void PutInputPacket(PacketPtr packet, size_t input_index) override;
 
@@ -48,7 +48,7 @@
 
   void SetStreamType(const StreamType& stream_type) override;
 
-  void Prime(fxl::Closure callback) override;
+  void Prime(fit::closure callback) override;
 
   fuchsia::math::Size video_size() const override;
 
@@ -56,12 +56,13 @@
 
   // Registers a callback that's called when the values returned by |video_size|
   // or |pixel_aspect_ratio| change.
-  void SetGeometryUpdateCallback(fxl::Closure callback);
+  void SetGeometryUpdateCallback(fit::closure callback);
 
   // Creates a view.
   void CreateView(
       fidl::InterfacePtr<::fuchsia::ui::views_v1::ViewManager> view_manager,
-      fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request);
+      fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+          view_owner_request);
 
  protected:
   void OnProgressStarted() override;
@@ -72,7 +73,8 @@
   class View : public mozart::BaseView {
    public:
     View(::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
-         fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request,
+         fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+             view_owner_request,
          std::shared_ptr<FidlVideoRenderer> renderer);
 
     ~View() override;
@@ -121,8 +123,8 @@
   int64_t pts_ns_ = Packet::kUnknownPts;
   VideoConverter converter_;
   std::unordered_map<View*, std::unique_ptr<View>> views_;
-  fxl::Closure prime_callback_;
-  fxl::Closure geometry_update_callback_;
+  fit::closure prime_callback_;
+  fit::closure geometry_update_callback_;
 
   PacketTimingTracker arrivals_;
   PacketTimingTracker draws_;
diff --git a/bin/media/media_player/render/renderer.cc b/bin/media/media_player/render/renderer.cc
index f8669df..db891f5 100644
--- a/bin/media/media_player/render/renderer.cc
+++ b/bin/media/media_player/render/renderer.cc
@@ -15,9 +15,9 @@
 
 Renderer::~Renderer() {}
 
-void Renderer::Provision(async_t* async, fxl::Closure update_callback) {
+void Renderer::Provision(async_t* async, fit::closure update_callback) {
   async_ = async;
-  update_callback_ = update_callback;
+  update_callback_ = std::move(update_callback);
 }
 
 void Renderer::Deprovision() {
@@ -51,9 +51,11 @@
 }
 
 void Renderer::SetTimelineFunction(media::TimelineFunction timeline_function,
-                                   fxl::Closure callback) {
-  FXL_DCHECK(timeline_function.subject_time() != media::kUnspecifiedTime);
-  FXL_DCHECK(timeline_function.reference_time() != media::kUnspecifiedTime);
+                                   fit::closure callback) {
+  FXL_DCHECK(timeline_function.subject_time() !=
+             fuchsia::media::kUnspecifiedTime);
+  FXL_DCHECK(timeline_function.reference_time() !=
+             fuchsia::media::kUnspecifiedTime);
   FXL_DCHECK(timeline_function.reference_delta() != 0);
 
   bool was_progressing = Progressing();
@@ -63,7 +65,7 @@
 
   // Queue up the new pending change.
   pending_timeline_function_ = timeline_function;
-  set_timeline_function_callback_ = callback;
+  set_timeline_function_callback_ = std::move(callback);
 
   if (!was_progressing && Progressing()) {
     OnProgressStarted();
@@ -73,7 +75,7 @@
 }
 
 bool Renderer::end_of_stream() const {
-  return end_of_stream_pts_ != media::kUnspecifiedTime &&
+  return end_of_stream_pts_ != fuchsia::media::kUnspecifiedTime &&
          current_timeline_function_(media::Timeline::local_now()) >=
              end_of_stream_pts_;
 }
@@ -127,11 +129,10 @@
 
 void Renderer::ClearPendingTimelineFunction() {
   pending_timeline_function_ = media::TimelineFunction(
-      media::kUnspecifiedTime, media::kUnspecifiedTime, 0, 1);
+      fuchsia::media::kUnspecifiedTime, fuchsia::media::kUnspecifiedTime, 0, 1);
 
   if (set_timeline_function_callback_) {
-    fxl::Closure callback = set_timeline_function_callback_;
-    set_timeline_function_callback_ = nullptr;
+    fit::closure callback = std::move(set_timeline_function_callback_);
     callback();
   }
 }
diff --git a/bin/media/media_player/render/renderer.h b/bin/media/media_player/render/renderer.h
index df425ef..baca51f 100644
--- a/bin/media/media_player/render/renderer.h
+++ b/bin/media/media_player/render/renderer.h
@@ -24,7 +24,7 @@
   // should be called to notify of changes in the value returned by
   // end_of_stream(). Subclasses of Renderer may use this callback to signal
   // additional changes.
-  void Provision(async_t* async, fxl::Closure update_callback);
+  void Provision(async_t* async, fit::closure update_callback);
 
   // Revokes the task runner and update callback provided in a previous call to
   // |Provision|.
@@ -44,11 +44,11 @@
   virtual void SetStreamType(const StreamType& stream_type) = 0;
 
   // Prepares renderer for playback by satisfying initial demand.
-  virtual void Prime(fxl::Closure callback) = 0;
+  virtual void Prime(fit::closure callback) = 0;
 
   // Sets the timeline function.
   virtual void SetTimelineFunction(media::TimelineFunction timeline_function,
-                                   fxl::Closure callback);
+                                   fit::closure callback);
 
   // Sets a program range for this renderer.
   virtual void SetProgramRange(uint64_t program, int64_t min_pts,
@@ -74,8 +74,8 @@
   // cause it to progress.
   bool Progressing();
 
-  // Sets the PTS at which end of stream will occur. Passing
-  // media::kUnspecifiedTime indicates that end-of-stream PTS isn't known.
+  // Sets the PTS at which end of stream will occur. Passing kUnspecifiedTime
+  // indicates that end-of-stream PTS isn't known.
   void SetEndOfStreamPts(int64_t end_of_stream_pts);
 
   // Checks for timeline transitions or end-of-stream. |reference_time| is the
@@ -97,7 +97,7 @@
 
   // Indicates whether the end of stream packet has been encountered.
   bool end_of_stream_pending() const {
-    return end_of_stream_pts_ != media::kUnspecifiedTime;
+    return end_of_stream_pts_ != fuchsia::media::kUnspecifiedTime;
   }
 
   // PTS at which end-of-stream is to occur or |kUnspecifiedTime| if an end-
@@ -127,16 +127,16 @@
   // Determines if an unrealized timeline function is currently pending.
   bool TimelineFunctionPending() {
     return pending_timeline_function_.reference_time() !=
-           media::kUnspecifiedTime;
+           fuchsia::media::kUnspecifiedTime;
   }
 
   async_t* async_;
-  fxl::Closure update_callback_;
+  fit::closure update_callback_;
   media::TimelineFunction current_timeline_function_;
   media::TimelineFunction pending_timeline_function_;
-  int64_t end_of_stream_pts_ = media::kUnspecifiedTime;
+  int64_t end_of_stream_pts_ = fuchsia::media::kUnspecifiedTime;
   bool end_of_stream_published_ = false;
-  fxl::Closure set_timeline_function_callback_;
+  fit::closure set_timeline_function_callback_;
   int64_t program_0_min_pts_ = std::numeric_limits<int64_t>::min();
   int64_t program_0_max_pts_ = std::numeric_limits<int64_t>::max();
 };
diff --git a/bin/media/media_player/render/video_converter.cc b/bin/media/media_player/render/video_converter.cc
index 2661264..a5dfe74 100644
--- a/bin/media/media_player/render/video_converter.cc
+++ b/bin/media/media_player/render/video_converter.cc
@@ -8,9 +8,7 @@
 
 namespace media_player {
 
-VideoConverter::VideoConverter() {
-  BuildColorspaceTable();
-}
+VideoConverter::VideoConverter() { BuildColorspaceTable(); }
 
 VideoConverter::~VideoConverter() {}
 
@@ -102,10 +100,8 @@
   return pixel_aspect_ratio;
 }
 
-void VideoConverter::ConvertFrame(uint8_t* rgba_buffer,
-                                  uint32_t view_width,
-                                  uint32_t view_height,
-                                  void* payload,
+void VideoConverter::ConvertFrame(uint8_t* rgba_buffer, uint32_t view_width,
+                                  uint32_t view_height, void* payload,
                                   uint64_t payload_size) {
   TRACE_DURATION("motown", "ConvertFrame");
   FXL_DCHECK(rgba_buffer != nullptr);
@@ -160,10 +156,8 @@
   }
 }
 
-void VideoConverter::ConvertLine(uint32_t* dest_pixel,
-                                 uint8_t* y_pixel,
-                                 uint8_t* u_pixel,
-                                 uint8_t* v_pixel,
+void VideoConverter::ConvertLine(uint32_t* dest_pixel, uint8_t* y_pixel,
+                                 uint8_t* u_pixel, uint8_t* v_pixel,
                                  uint32_t width) {
   for (uint32_t pixel = 0; pixel < width; ++pixel) {
     *dest_pixel =
diff --git a/bin/media/media_player/render/video_converter.h b/bin/media/media_player/render/video_converter.h
index 09da853..e8965fa 100644
--- a/bin/media/media_player/render/video_converter.h
+++ b/bin/media/media_player/render/video_converter.h
@@ -8,7 +8,8 @@
 #include <memory>
 
 #include <fuchsia/math/cpp/fidl.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/media_player/framework/types/video_stream_type.h"
 
 namespace media_player {
@@ -30,22 +31,16 @@
   fuchsia::math::Size GetPixelAspectRatio() const;
 
   // Converts the frame in the payload into the provided RGBA buffer.
-  void ConvertFrame(uint8_t* rgba_buffer,
-                    uint32_t view_width,
-                    uint32_t view_height,
-                    void* payload,
-                    uint64_t payload_size);
+  void ConvertFrame(uint8_t* rgba_buffer, uint32_t view_width,
+                    uint32_t view_height, void* payload, uint64_t payload_size);
 
  private:
   // Builds the YUV-RGBA colorspace table.
   void BuildColorspaceTable();
 
   // Converts one line.
-  void ConvertLine(uint32_t* dest_pixel,
-                   uint8_t* y_pixel,
-                   uint8_t* u_pixel,
-                   uint8_t* v_pixel,
-                   uint32_t width);
+  void ConvertLine(uint32_t* dest_pixel, uint8_t* y_pixel, uint8_t* u_pixel,
+                   uint8_t* v_pixel, uint32_t width);
 
   std::unique_ptr<StreamType> stream_type_;
   const VideoStreamType* video_stream_type_ = nullptr;
diff --git a/bin/media/media_player/test/fake_audio_renderer.cc b/bin/media/media_player/test/fake_audio_renderer.cc
index 2ee6b9e..f87e9d7 100644
--- a/bin/media/media_player/test/fake_audio_renderer.cc
+++ b/bin/media/media_player/test/fake_audio_renderer.cc
@@ -8,10 +8,14 @@
 #include <iostream>
 #include <limits>
 
+#include <lib/async/cpp/task.h>
+#include <lib/async/default.h>
+
 #include "lib/fxl/logging.h"
 #include "lib/media/timeline/timeline.h"
 
 namespace media_player {
+namespace test {
 
 namespace {
 
@@ -28,16 +32,17 @@
 
 }  // namespace
 
-FakeAudioRenderer::FakeAudioRenderer() : binding_(this) {}
+FakeAudioRenderer::FakeAudioRenderer()
+    : async_(async_get_default()), binding_(this) {}
 
 FakeAudioRenderer::~FakeAudioRenderer() {}
 
 void FakeAudioRenderer::Bind(
-    fidl::InterfaceRequest<media::AudioRenderer2> renderer) {
+    fidl::InterfaceRequest<fuchsia::media::AudioRenderer2> renderer) {
   binding_.Bind(std::move(renderer));
 }
 
-void FakeAudioRenderer::SetPcmFormat(media::AudioPcmFormat format) {
+void FakeAudioRenderer::SetPcmFormat(fuchsia::media::AudioPcmFormat format) {
   format_ = format;
 }
 
@@ -47,8 +52,8 @@
 
 void FakeAudioRenderer::SetPtsUnits(uint32_t tick_per_second_numerator,
                                     uint32_t tick_per_second_denominator) {
-  tick_per_second_numerator_ = tick_per_second_numerator;
-  tick_per_second_denominator_ = tick_per_second_denominator;
+  pts_rate_ = media::TimelineRate(tick_per_second_numerator,
+                                  tick_per_second_denominator);
 }
 
 void FakeAudioRenderer::SetPtsContinuityThreshold(float threshold_seconds) {
@@ -59,7 +64,7 @@
   FXL_NOTIMPLEMENTED();
 }
 
-void FakeAudioRenderer::SendPacket(media::AudioPacket packet,
+void FakeAudioRenderer::SendPacket(fuchsia::media::AudioPacket packet,
                                    SendPacketCallback callback) {
   if (dump_packets_) {
     std::cerr << "{ " << packet.timestamp << ", " << packet.payload_size
@@ -87,21 +92,21 @@
     ++expected_packets_info_iter_;
   }
 
-  if (playing_) {
-    callback();
-  } else {
-    packet_callback_queue_.push(callback);
+  packet_queue_.push(std::make_pair(packet, callback));
+
+  if (packet_queue_.size() == 1) {
+    MaybeScheduleRetirement();
   }
 }
 
-void FakeAudioRenderer::SendPacketNoReply(media::AudioPacket packet) {
+void FakeAudioRenderer::SendPacketNoReply(fuchsia::media::AudioPacket packet) {
   SendPacket(std::move(packet), []() {});
 }
 
 void FakeAudioRenderer::Flush(FlushCallback callback) {
-  while (!packet_callback_queue_.empty()) {
-    packet_callback_queue_.front()();
-    packet_callback_queue_.pop();
+  while (!packet_queue_.empty()) {
+    packet_queue_.front().second();
+    packet_queue_.pop();
   }
 
   callback();
@@ -111,16 +116,28 @@
   Flush([]() {});
 }
 
-void FakeAudioRenderer::Play(int64_t reference_time,
-                             int64_t media_time,
+void FakeAudioRenderer::Play(int64_t reference_time, int64_t media_time,
                              PlayCallback callback) {
-  playing_ = true;
-  callback(0, 0);
-
-  while (!packet_callback_queue_.empty()) {
-    packet_callback_queue_.front()();
-    packet_callback_queue_.pop();
+  if (reference_time == fuchsia::media::kNoTimestamp) {
+    reference_time = media::Timeline::local_now();
   }
+
+  if (media_time == fuchsia::media::kNoTimestamp) {
+    if (restart_media_time_ != fuchsia::media::kNoTimestamp) {
+      media_time = restart_media_time_;
+    } else if (packet_queue_.empty()) {
+      media_time = 0;
+    } else {
+      media_time = to_ns(packet_queue_.front().first.timestamp);
+    }
+  }
+
+  callback(reference_time, media_time);
+
+  timeline_function_ =
+      media::TimelineFunction(media_time, reference_time, 1, 1);
+
+  MaybeScheduleRetirement();
 }
 
 void FakeAudioRenderer::PlayNoReply(int64_t reference_time,
@@ -130,17 +147,18 @@
 }
 
 void FakeAudioRenderer::Pause(PauseCallback callback) {
-  playing_ = false;
-  callback(0, 0);
+  int64_t reference_time = media::Timeline::local_now();
+  int64_t media_time = timeline_function_(reference_time);
+  timeline_function_ =
+      media::TimelineFunction(media_time, reference_time, 0, 1);
+  callback(reference_time, media_time);
 }
 
 void FakeAudioRenderer::PauseNoReply() {
   Pause([](int64_t reference_time, int64_t media_time) {});
 }
 
-void FakeAudioRenderer::SetGainMute(float gain,
-                                    bool mute,
-                                    uint32_t flags,
+void FakeAudioRenderer::SetGainMute(float gain, bool mute, uint32_t flags,
                                     SetGainMuteCallback callback) {
   gain_ = gain;
   mute_ = mute;
@@ -148,14 +166,14 @@
   callback(gain, mute);
 }
 
-void FakeAudioRenderer::SetGainMuteNoReply(float gain,
-                                           bool mute,
+void FakeAudioRenderer::SetGainMuteNoReply(float gain, bool mute,
                                            uint32_t flags) {
   SetGainMute(gain, mute, flags, [](float gain, bool mute) {});
 }
 
 void FakeAudioRenderer::DuplicateGainControlInterface(
-    ::fidl::InterfaceRequest<media::AudioRendererGainControl> request) {
+    ::fidl::InterfaceRequest<fuchsia::media::AudioRendererGainControl>
+        request) {
   FXL_NOTIMPLEMENTED();
 }
 
@@ -169,4 +187,33 @@
   callback(min_lead_time_ns_);
 }
 
+void FakeAudioRenderer::MaybeScheduleRetirement() {
+  if (!progressing() || packet_queue_.empty()) {
+    return;
+  }
+
+  int64_t reference_time = timeline_function_.ApplyInverse(
+      to_ns(packet_queue_.front().first.timestamp));
+
+  async::PostTaskForTime(
+      async_,
+      [this]() {
+        if (!progressing() || packet_queue_.empty()) {
+          return;
+        }
+
+        int64_t reference_time = timeline_function_.ApplyInverse(
+            to_ns(packet_queue_.front().first.timestamp));
+
+        if (reference_time <= media::Timeline::local_now()) {
+          packet_queue_.front().second();
+          packet_queue_.pop();
+        }
+
+        MaybeScheduleRetirement();
+      },
+      zx::time(reference_time));
+}
+
+}  // namespace test
 }  // namespace media_player
diff --git a/bin/media/media_player/test/fake_audio_renderer.h b/bin/media/media_player/test/fake_audio_renderer.h
index 65c2868..e776d22 100644
--- a/bin/media/media_player/test/fake_audio_renderer.h
+++ b/bin/media/media_player/test/fake_audio_renderer.h
@@ -2,22 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_FAKE_RENDERER_H_
-#define GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_FAKE_RENDERER_H_
+#ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_FAKE_AUDIO_RENDERER_H_
+#define GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_FAKE_AUDIO_RENDERER_H_
 
 #include <memory>
 #include <queue>
 #include <vector>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/async/dispatcher.h>
 
 #include "lib/fidl/cpp/binding.h"
+#include "lib/media/timeline/timeline_function.h"
 #include "lib/media/transport/mapped_shared_buffer.h"
 
 namespace media_player {
+namespace test {
 
 // Implements AudioRenderer2 for testing.
-class FakeAudioRenderer : public media::AudioRenderer2 {
+class FakeAudioRenderer : public fuchsia::media::AudioRenderer2 {
  public:
   class PacketInfo {
    public:
@@ -39,7 +42,7 @@
   ~FakeAudioRenderer() override;
 
   // Binds the renderer.
-  void Bind(fidl::InterfaceRequest<media::AudioRenderer2> request);
+  void Bind(fidl::InterfaceRequest<fuchsia::media::AudioRenderer2> request);
 
   // Indicates that the renderer should print out supplied packet info.
   void DumpPackets() { dump_packets_ = true; }
@@ -55,7 +58,7 @@
   bool expected() { return expected_; }
 
   // AudioRenderer2 implementation.
-  void SetPcmFormat(media::AudioPcmFormat format) override;
+  void SetPcmFormat(fuchsia::media::AudioPcmFormat format) override;
 
   void SetPayloadBuffer(::zx::vmo payload_buffer) override;
 
@@ -66,17 +69,16 @@
 
   void SetReferenceClock(::zx::handle ref_clock) override;
 
-  void SendPacket(media::AudioPacket packet,
+  void SendPacket(fuchsia::media::AudioPacket packet,
                   SendPacketCallback callback) override;
 
-  void SendPacketNoReply(media::AudioPacket packet) override;
+  void SendPacketNoReply(fuchsia::media::AudioPacket packet) override;
 
   void Flush(FlushCallback callback) override;
 
   void FlushNoReply() override;
 
-  void Play(int64_t reference_time,
-            int64_t media_time,
+  void Play(int64_t reference_time, int64_t media_time,
             PlayCallback callback) override;
 
   void PlayNoReply(int64_t reference_time, int64_t media_time) override;
@@ -85,44 +87,62 @@
 
   void PauseNoReply() override;
 
-  void SetGainMute(float gain,
-                   bool mute,
-                   uint32_t flags,
+  void SetGainMute(float gain, bool mute, uint32_t flags,
                    SetGainMuteCallback callback) override;
 
   void SetGainMuteNoReply(float gain, bool mute, uint32_t flags) override;
 
   void DuplicateGainControlInterface(
-      ::fidl::InterfaceRequest<media::AudioRendererGainControl> request)
-      override;
+      ::fidl::InterfaceRequest<fuchsia::media::AudioRendererGainControl>
+          request) override;
 
   void EnableMinLeadTimeEvents(bool enabled) override;
 
   void GetMinLeadTime(GetMinLeadTimeCallback callback) override;
 
  private:
-  fidl::Binding<media::AudioRenderer2> binding_;
+  // Converts a pts in |pts_rate_| units to ns.
+  int64_t to_ns(int64_t pts) {
+    return pts * (media::TimelineRate::NsPerSecond / pts_rate_);
+  }
 
-  media::AudioPcmFormat format_;
+  // Converts a pts in ns to |pts_rate_| units.
+  int64_t from_ns(int64_t pts) {
+    return pts * (pts_rate_ / media::TimelineRate::NsPerSecond);
+  }
+
+  // Determines if we care currently playing.
+  bool progressing() { return timeline_function_.invertable(); }
+
+  // Schedules the retirement of the oldest queued packet if there are any
+  // packets and if we're playing.
+  void MaybeScheduleRetirement();
+
+  async_t* async_;
+  fidl::Binding<fuchsia::media::AudioRenderer2> binding_;
+
+  fuchsia::media::AudioPcmFormat format_;
   media::MappedSharedBuffer mapped_buffer_;
-  uint32_t tick_per_second_numerator_ = 1'000'000'000;
-  uint32_t tick_per_second_denominator_ = 1;
   float threshold_seconds_ = 0.0f;
   float gain_ = 1.0f;
   bool mute_ = false;
   uint32_t gain_mute_flags_ = 0;
-  const int64_t min_lead_time_ns_ = 100'000'000;
-  bool playing_ = false;
+  const int64_t min_lead_time_ns_ = ZX_MSEC(100);
+  media::TimelineRate pts_rate_ = media::TimelineRate::NsPerSecond;
+  media::TimelineFunction timeline_function_;
+  int64_t restart_media_time_ = fuchsia::media::kNoTimestamp;
 
   bool dump_packets_ = false;
   std::vector<PacketInfo> expected_packets_info_;
   std::vector<PacketInfo>::iterator expected_packets_info_iter_;
 
-  std::queue<SendPacketCallback> packet_callback_queue_;
+  std::queue<std::pair<fuchsia::media::AudioPacket, SendPacketCallback>>
+      packet_queue_;
 
   bool expected_ = true;
 };
 
+}  // namespace test
 }  // namespace media_player
 
-#endif  // GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_FAKE_RENDERER_H_
+#endif  // GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_FAKE_AUDIO_RENDERER_H_
diff --git a/bin/media/media_player/test/fake_wav_reader.cc b/bin/media/media_player/test/fake_wav_reader.cc
index d767c84..94e8321 100644
--- a/bin/media/media_player/test/fake_wav_reader.cc
+++ b/bin/media/media_player/test/fake_wav_reader.cc
@@ -9,9 +9,7 @@
 
 namespace media_player {
 
-FakeWavReader::FakeWavReader() : binding_(this) {
-  WriteHeader();
-}
+FakeWavReader::FakeWavReader() : binding_(this) { WriteHeader(); }
 
 void FakeWavReader::WriteHeader() {
   header_.clear();
@@ -45,12 +43,13 @@
 
 FakeWavReader::~FakeWavReader() {}
 
-void FakeWavReader::Bind(fidl::InterfaceRequest<SeekingReader> request) {
+void FakeWavReader::Bind(
+    fidl::InterfaceRequest<fuchsia::mediaplayer::SeekingReader> request) {
   binding_.Bind(std::move(request));
 }
 
 void FakeWavReader::Describe(DescribeCallback callback) {
-  callback(media::MediaResult::OK, size_, true);
+  callback(fuchsia::media::MediaResult::OK, size_, true);
 }
 
 void FakeWavReader::ReadAt(uint64_t position, ReadAtCallback callback) {
@@ -61,7 +60,7 @@
   zx::socket other_socket;
   zx_status_t status = zx::socket::create(0u, &socket_, &other_socket);
   FXL_DCHECK(status == ZX_OK);
-  callback(media::MediaResult::OK, std::move(other_socket));
+  callback(fuchsia::media::MediaResult::OK, std::move(other_socket));
 
   position_ = position;
 
diff --git a/bin/media/media_player/test/fake_wav_reader.h b/bin/media/media_player/test/fake_wav_reader.h
index 16e8ac0..4f69f28 100644
--- a/bin/media/media_player/test/fake_wav_reader.h
+++ b/bin/media/media_player/test/fake_wav_reader.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/zx/socket.h>
 
@@ -17,7 +17,7 @@
 namespace media_player {
 
 // Fake SeekingReader that 'reads' a synthetic wav file.
-class FakeWavReader : public SeekingReader {
+class FakeWavReader : public fuchsia::mediaplayer::SeekingReader {
  public:
   // Constructs a FakeWavReader that produces a file of |size| bytes total.
   FakeWavReader();
@@ -32,7 +32,8 @@
   }
 
   // Binds the reader.
-  void Bind(fidl::InterfaceRequest<SeekingReader> request);
+  void Bind(
+      fidl::InterfaceRequest<fuchsia::mediaplayer::SeekingReader> request);
 
   // SeekingReader implementation.
   void Describe(DescribeCallback callback) override;
@@ -69,7 +70,7 @@
   // Gets the positionth byte of the file.
   uint8_t GetByte(size_t position);
 
-  fidl::Binding<SeekingReader> binding_;
+  fidl::Binding<fuchsia::mediaplayer::SeekingReader> binding_;
   std::vector<uint8_t> header_;
   uint64_t size_ = kDefaultSize;
   zx::socket socket_;
diff --git a/bin/media/media_player/test/media_player_test_params.h b/bin/media/media_player/test/media_player_test_params.h
index 9591f37..a880381 100644
--- a/bin/media/media_player/test/media_player_test_params.h
+++ b/bin/media/media_player/test/media_player_test_params.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_MEDIA_PLAYER_TEST_PARAMS_H_
+#define GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_MEDIA_PLAYER_TEST_PARAMS_H_
 
 #include <string>
 #include <vector>
@@ -43,3 +44,5 @@
 
 }  // namespace test
 }  // namespace media_player
+
+#endif  // GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_MEDIA_PLAYER_TEST_PARAMS_H_
diff --git a/bin/media/media_player/test/media_player_test_unattended.cc b/bin/media/media_player/test/media_player_test_unattended.cc
index d59258c..d0a6a36 100644
--- a/bin/media/media_player/test/media_player_test_unattended.cc
+++ b/bin/media/media_player/test/media_player_test_unattended.cc
@@ -6,16 +6,16 @@
 
 #include <iostream>
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
-#include <media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/test/fake_audio_renderer.h"
 #include "garnet/bin/media/media_player/test/fake_wav_reader.h"
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/optional.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/media/timeline/timeline_rate.h"
 
@@ -23,22 +23,25 @@
 namespace test {
 
 MediaPlayerTestUnattended::MediaPlayerTestUnattended(
-    std::function<void(int)> quit_callback)
+    fit::function<void(int)> quit_callback)
     : startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
-      quit_callback_(quit_callback) {
+      quit_callback_(std::move(quit_callback)) {
   FXL_DCHECK(quit_callback_);
   std::cerr << "MediaPlayerTest starting\n";
 
   std::cerr << "creating player\n";
-  media_player_ = startup_context_->ConnectToEnvironmentService<MediaPlayer>();
-  media_player_.events().StatusChanged = [this](MediaPlayerStatus status) {
-    if (status.end_of_stream) {
-      FXL_LOG(INFO) << "MediaPlayerTest "
-                    << (fake_audio_renderer_.expected() ? "SUCCEEDED"
-                                                        : "FAILED");
-      quit_callback_(fake_audio_renderer_.expected() ? 0 : 1);
-    }
-  };
+  media_player_ =
+      startup_context_
+          ->ConnectToEnvironmentService<fuchsia::mediaplayer::MediaPlayer>();
+  media_player_.events().StatusChanged =
+      [this](fuchsia::mediaplayer::MediaPlayerStatus status) {
+        if (status.end_of_stream) {
+          FXL_LOG(INFO) << "MediaPlayerTest "
+                        << (fake_audio_renderer_.expected() ? "SUCCEEDED"
+                                                            : "FAILED");
+          quit_callback_(fake_audio_renderer_.expected() ? 0 : 1);
+        }
+      };
 
   fake_audio_renderer_.SetPtsUnits(48000, 1);
 
@@ -59,12 +62,12 @@
                                       {14336, 4096, 0xf7960542f1991800},
                                       {15360, 4052, 0x7308a9824acbd5ea}});
 
-  SeekingReaderPtr fake_reader_ptr;
-  fidl::InterfaceRequest<SeekingReader> reader_request =
+  fuchsia::mediaplayer::SeekingReaderPtr fake_reader_ptr;
+  fidl::InterfaceRequest<fuchsia::mediaplayer::SeekingReader> reader_request =
       fake_reader_ptr.NewRequest();
   fake_reader_.Bind(std::move(reader_request));
 
-  media::AudioRenderer2Ptr fake_audio_renderer_ptr;
+  fuchsia::media::AudioRenderer2Ptr fake_audio_renderer_ptr;
   fake_audio_renderer_.Bind(fake_audio_renderer_ptr.NewRequest());
 
   media_player_->SetAudioRenderer(std::move(fake_audio_renderer_ptr));
diff --git a/bin/media/media_player/test/media_player_test_unattended.h b/bin/media/media_player/test/media_player_test_unattended.h
index 4942375..08fde0f 100644
--- a/bin/media/media_player/test/media_player_test_unattended.h
+++ b/bin/media/media_player/test/media_player_test_unattended.h
@@ -5,16 +5,16 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_MEDIA_PLAYER_TEST_UNATTENDED_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_TEST_MEDIA_PLAYER_TEST_UNATTENDED_H_
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
-#include <media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/test/fake_audio_renderer.h"
 #include "garnet/bin/media/media_player/test/fake_wav_reader.h"
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/optional.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/media/timeline/timeline_rate.h"
 
@@ -23,14 +23,14 @@
 
 class MediaPlayerTestUnattended {
  public:
-  MediaPlayerTestUnattended(std::function<void(int)> quit_callback);
+  MediaPlayerTestUnattended(fit::function<void(int)> quit_callback);
 
  private:
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
-  std::function<void(int)> quit_callback_;
+  fit::function<void(int)> quit_callback_;
   FakeWavReader fake_reader_;
   FakeAudioRenderer fake_audio_renderer_;
-  MediaPlayerPtr media_player_;
+  fuchsia::mediaplayer::MediaPlayerPtr media_player_;
 };
 
 }  // namespace test
diff --git a/bin/media/media_player/test/media_player_test_view.cc b/bin/media/media_player/test/media_player_test_view.cc
index cccb820..7e8f180 100644
--- a/bin/media/media_player/test/media_player_test_view.cc
+++ b/bin/media/media_player/test/media_player_test_view.cc
@@ -47,7 +47,7 @@
 }  // namespace
 
 MediaPlayerTestView::MediaPlayerTestView(
-    std::function<void(int)> quit_callback,
+    fit::function<void(int)> quit_callback,
     ::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
     fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
         view_owner_request,
@@ -55,12 +55,12 @@
     const MediaPlayerTestParams& params)
     : mozart::BaseView(std::move(view_manager), std::move(view_owner_request),
                        "Media Player"),
-      quit_callback_(quit_callback),
+      quit_callback_(std::move(quit_callback)),
       params_(params),
       background_node_(session()),
       progress_bar_node_(session()),
       progress_bar_slider_node_(session()) {
-  FXL_DCHECK(quit_callback);
+  FXL_DCHECK(quit_callback_);
   FXL_DCHECK(params_.is_valid());
   FXL_DCHECK(!params_.urls().empty());
 
@@ -87,11 +87,14 @@
   pixel_aspect_ratio_.height = 1;
 
   // Create a player from all that stuff.
-  media_player_ = startup_context->ConnectToEnvironmentService<MediaPlayer>();
+  media_player_ =
+      startup_context
+          ->ConnectToEnvironmentService<fuchsia::mediaplayer::MediaPlayer>();
 
-  media_player_.events().StatusChanged = [this](MediaPlayerStatus status) {
-    HandleStatusChanged(status);
-  };
+  media_player_.events().StatusChanged =
+      [this](fuchsia::mediaplayer::MediaPlayerStatus status) {
+        HandleStatusChanged(status);
+      };
 
   ::fuchsia::ui::views_v1_token::ViewOwnerPtr video_view_owner;
   media_player_->CreateView(
@@ -301,12 +304,12 @@
 }
 
 void MediaPlayerTestView::HandleStatusChanged(
-    const media_player::MediaPlayerStatus& status) {
+    const fuchsia::mediaplayer::MediaPlayerStatus& status) {
   // Process status received from the player.
   if (status.timeline_transform) {
     timeline_function_ = media::TimelineFunction(*status.timeline_transform);
 
-    if (seek_interval_start_ != media::kUnspecifiedTime &&
+    if (seek_interval_start_ != fuchsia::media::kUnspecifiedTime &&
         !in_current_seek_interval_ &&
         timeline_function_.subject_time() == seek_interval_start_) {
       // The seek issued in |StartNewSeekInterval| is now reflected in the
@@ -426,7 +429,7 @@
     // We have no duration yet. Just start over at the start of the file.
     media_player_->Seek(0);
     media_player_->Play();
-    seek_interval_end_ = media::kUnspecifiedTime;
+    seek_interval_end_ = fuchsia::media::kUnspecifiedTime;
   }
 
   int64_t duration = metadata_->duration;
diff --git a/bin/media/media_player/test/media_player_test_view.h b/bin/media/media_player/test/media_player_test_view.h
index e4cb6e6..58e5573 100644
--- a/bin/media/media_player/test/media_player_test_view.h
+++ b/bin/media/media_player/test/media_player_test_view.h
@@ -8,9 +8,10 @@
 #include <memory>
 #include <queue>
 
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/media/media_player/test/media_player_test_params.h"
 #include "lib/app/cpp/startup_context.h"
@@ -24,7 +25,7 @@
 class MediaPlayerTestView : public mozart::BaseView {
  public:
   MediaPlayerTestView(
-      std::function<void(int)> quit_callback,
+      fit::function<void(int)> quit_callback,
       ::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
       fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
           view_owner_request,
@@ -54,7 +55,8 @@
   void Layout();
 
   // Handles a status changed event from the player.
-  void HandleStatusChanged(const media_player::MediaPlayerStatus& status);
+  void HandleStatusChanged(
+      const fuchsia::mediaplayer::MediaPlayerStatus& status);
 
   // Handle transition to end-of-stream.
   void OnEndOfStream();
@@ -71,7 +73,7 @@
   // Seeks to a new position and sets |seek_interval_end_|.
   void StartNewSeekInterval();
 
-  std::function<void(int)> quit_callback_;
+  fit::function<void(int)> quit_callback_;
   const MediaPlayerTestParams& params_;
   size_t current_url_index_ = 0;
 
@@ -80,19 +82,19 @@
   scenic_lib::ShapeNode progress_bar_slider_node_;
   std::unique_ptr<scenic_lib::EntityNode> video_host_node_;
 
-  media_player::MediaPlayerPtr media_player_;
+  fuchsia::mediaplayer::MediaPlayerPtr media_player_;
   fuchsia::math::Size video_size_;
   fuchsia::math::Size pixel_aspect_ratio_;
   State state_ = State::kPaused;
   media::TimelineFunction timeline_function_;
-  media_player::MediaMetadataPtr metadata_;
+  fuchsia::mediaplayer::MediaMetadataPtr metadata_;
   fuchsia::math::RectF content_rect_;
   fuchsia::math::RectF controls_rect_;
   bool problem_shown_ = false;
   bool was_at_end_of_stream_ = false;
 
-  int64_t seek_interval_start_ = media::kUnspecifiedTime;
-  int64_t seek_interval_end_ = media::kUnspecifiedTime;
+  int64_t seek_interval_start_ = fuchsia::media::kUnspecifiedTime;
+  int64_t seek_interval_end_ = fuchsia::media::kUnspecifiedTime;
   bool in_current_seek_interval_ = false;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(MediaPlayerTestView);
diff --git a/bin/media/media_player/util/BUILD.gn b/bin/media/media_player/util/BUILD.gn
index fe04cb5..de2d39c 100644
--- a/bin/media/media_player/util/BUILD.gn
+++ b/bin/media/media_player/util/BUILD.gn
@@ -17,6 +17,7 @@
 
   public_deps = [
     "//garnet/public/lib/fxl",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/bin/media/media_player/util/callback_joiner.cc b/bin/media/media_player/util/callback_joiner.cc
index ac24f3e..681cd90 100644
--- a/bin/media/media_player/util/callback_joiner.cc
+++ b/bin/media/media_player/util/callback_joiner.cc
@@ -19,14 +19,12 @@
   FXL_DCHECK(counter_ != 0);
   --counter_;
   if (counter_ == 0 && join_callback_) {
-    std::function<void()> join_callback;
-    join_callback = join_callback_;
-    join_callback_ = nullptr;
+    fit::closure join_callback = std::move(join_callback_);
     join_callback();
   }
 }
 
-std::function<void()> CallbackJoiner::NewCallback() {
+fit::closure CallbackJoiner::NewCallback() {
   Spawn();
   std::shared_ptr<CallbackJoiner> this_ptr = shared_from_this();
   FXL_DCHECK(!this_ptr.unique());
@@ -36,13 +34,13 @@
   };
 }
 
-void CallbackJoiner::WhenJoined(const std::function<void()>& join_callback) {
+void CallbackJoiner::WhenJoined(fit::closure join_callback) {
   FXL_DCHECK(join_callback);
   FXL_DCHECK(!join_callback_);
   if (counter_ == 0) {
     join_callback();
   } else {
-    join_callback_ = join_callback;
+    join_callback_ = std::move(join_callback);
   }
 }
 
diff --git a/bin/media/media_player/util/callback_joiner.h b/bin/media/media_player/util/callback_joiner.h
index 986cf64..6607788 100644
--- a/bin/media/media_player/util/callback_joiner.h
+++ b/bin/media/media_player/util/callback_joiner.h
@@ -7,6 +7,8 @@
 
 #include <memory>
 
+#include <lib/fit/function.h>
+
 #include "lib/fxl/logging.h"
 
 namespace media_player {
@@ -70,14 +72,14 @@
 
   // Calls Spawn and returns a new callback, which calls Complete. THIS METHOD
   // WILL ONLY WORK IF THERE IS ALREADY A SHARED POINTER TO THIS OBJECT.
-  std::function<void()> NewCallback();
+  fit::closure NewCallback();
 
   // Specifies a callback to be called when all child operations have completed.
   // If no child operations are currently pending, the callback is called
   // immediately. If child operations are pending, the callback is copied. The
   // copy called later (and reset) when all child operations have completed.
   // Only one callback at a time can be registered with WhenJoined.
-  void WhenJoined(const std::function<void()>& join_callback);
+  void WhenJoined(fit::closure join_callback);
 
   // Cancels a callback registered with WhenJoined if it hasn't run yet. The
   // return value indicates whether a callback was cancelled.
@@ -85,7 +87,7 @@
 
  private:
   size_t counter_ = 0;
-  std::function<void()> join_callback_;
+  fit::closure join_callback_;
 };
 
 }  // namespace media_player
diff --git a/bin/media/media_player/util/incident.cc b/bin/media/media_player/util/incident.cc
index e7da096..96875f2 100644
--- a/bin/media/media_player/util/incident.cc
+++ b/bin/media/media_player/util/incident.cc
@@ -16,10 +16,10 @@
   occurred_ = true;
 
   // Swap out consequences_ in case one of the callbacks deletes this.
-  std::vector<std::function<void()>> consequences;
+  std::vector<fit::closure> consequences;
   consequences_.swap(consequences);
 
-  for (const std::function<void()>& consequence : consequences) {
+  for (auto& consequence : consequences) {
     consequence();
   }
 }
@@ -29,7 +29,7 @@
 ThreadsafeIncident::~ThreadsafeIncident() {}
 
 void ThreadsafeIncident::Occur() {
-  std::vector<std::function<void()>> consequences;
+  std::vector<fit::closure> consequences;
 
   {
     std::lock_guard<std::mutex> locker(mutex_);
@@ -42,7 +42,7 @@
     consequences_.swap(consequences);
   }
 
-  for (const std::function<void()>& consequence : consequences) {
+  for (auto& consequence : consequences) {
     consequence();
   }
 }
diff --git a/bin/media/media_player/util/incident.h b/bin/media/media_player/util/incident.h
index 79b1761..4f5fae5 100644
--- a/bin/media/media_player/util/incident.h
+++ b/bin/media/media_player/util/incident.h
@@ -5,10 +5,11 @@
 #ifndef GARNET_BIN_MEDIA_MEDIA_PLAYER_UTIL_INCIDENT_H_
 #define GARNET_BIN_MEDIA_MEDIA_PLAYER_UTIL_INCIDENT_H_
 
-#include <functional>
 #include <mutex>
 #include <vector>
 
+#include <lib/fit/function.h>
+
 #include "lib/fxl/synchronization/thread_annotations.h"
 
 // The Incident class provides a facility for executing code as the consequence
@@ -18,7 +19,7 @@
 // Incident is not a thread-safe class and has no ability to make a thread wait
 // or to execute code on a particular thread.
 //
-// Incidents rely heavily on std::function, so they shouldn't be used in
+// Incidents rely heavily on fit::function, so they shouldn't be used in
 // enormous numbers.
 //
 // An Incident can be in one of two states: initial state or occurred state.
@@ -55,11 +56,11 @@
   // until this Incident occurs or is reset. If this Incident has occurred when
   // this method is called, the consequence is executed immediately and no copy
   // of the consequence is held.
-  void When(const std::function<void()>& consequence) {
+  void When(fit::closure consequence) {
     if (occurred_) {
       consequence();
     } else {
-      consequences_.push_back(consequence);
+      consequences_.push_back(std::move(consequence));
     }
   }
 
@@ -76,7 +77,7 @@
 
  private:
   bool occurred_ = false;
-  std::vector<std::function<void()>> consequences_;
+  std::vector<fit::closure> consequences_;
 };
 
 // Like Incident, but threadsafe.
@@ -104,11 +105,11 @@
   // consequence is called. It's therefore possible for this ThreadsafeIncident
   // to be reset between the time the decision is made to run the consequence
   // and when the consequence is actually run.
-  void When(const std::function<void()>& consequence) {
+  void When(fit::closure consequence) {
     {
       std::lock_guard<std::mutex> locker(mutex_);
       if (!occurred_) {
-        consequences_.push_back(consequence);
+        consequences_.push_back(std::move(consequence));
         return;
       }
     }
@@ -132,7 +133,7 @@
  private:
   mutable std::mutex mutex_;
   bool occurred_ FXL_GUARDED_BY(mutex_) = false;
-  std::vector<std::function<void()>> consequences_ FXL_GUARDED_BY(mutex_);
+  std::vector<fit::closure> consequences_ FXL_GUARDED_BY(mutex_);
 };
 
 #endif  // GARNET_BIN_MEDIA_MEDIA_PLAYER_UTIL_INCIDENT_H_
diff --git a/bin/media/media_player/util/threadsafe_callback_joiner.cc b/bin/media/media_player/util/threadsafe_callback_joiner.cc
index 6bb9537..b51beb1 100644
--- a/bin/media/media_player/util/threadsafe_callback_joiner.cc
+++ b/bin/media/media_player/util/threadsafe_callback_joiner.cc
@@ -27,7 +27,7 @@
 }
 
 void ThreadsafeCallbackJoiner::Complete() {
-  fxl::Closure callback;
+  fit::closure callback;
   async_t* async;
 
   {
@@ -42,11 +42,11 @@
     std::swap(async, join_callback_async_);
   }
 
-  async::PostTask(
-      async, [shared_this = shared_from_this(), callback]() { callback(); });
+  async::PostTask(async, [shared_this = shared_from_this(),
+                          callback = std::move(callback)]() { callback(); });
 }
 
-fxl::Closure ThreadsafeCallbackJoiner::NewCallback() {
+fit::closure ThreadsafeCallbackJoiner::NewCallback() {
   Spawn();
   std::shared_ptr<ThreadsafeCallbackJoiner> this_ptr = shared_from_this();
   FXL_DCHECK(!this_ptr.unique());
@@ -57,7 +57,7 @@
 }
 
 void ThreadsafeCallbackJoiner::WhenJoined(async_t* async,
-                                          const fxl::Closure& join_callback) {
+                                          fit::closure join_callback) {
   FXL_DCHECK(async);
   FXL_DCHECK(join_callback);
 
@@ -65,15 +65,15 @@
     std::lock_guard<std::mutex> locker(mutex_);
     FXL_DCHECK(!join_callback_);
     if (counter_ != 0) {
-      join_callback_ = join_callback;
+      join_callback_ = std::move(join_callback);
       join_callback_async_ = async;
       return;
     }
   }
 
-  async::PostTask(async, [shared_this = shared_from_this(), join_callback]() {
-    join_callback();
-  });
+  async::PostTask(
+      async, [shared_this = shared_from_this(),
+              join_callback = std::move(join_callback)]() { join_callback(); });
 }
 
 bool ThreadsafeCallbackJoiner::Cancel() {
diff --git a/bin/media/media_player/util/threadsafe_callback_joiner.h b/bin/media/media_player/util/threadsafe_callback_joiner.h
index 1ad5c43..bb7dd3f 100644
--- a/bin/media/media_player/util/threadsafe_callback_joiner.h
+++ b/bin/media/media_player/util/threadsafe_callback_joiner.h
@@ -9,8 +9,8 @@
 #include <mutex>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 
 namespace media_player {
@@ -46,7 +46,7 @@
 
   // Calls Spawn and returns a new callback, which calls Complete. THIS METHOD
   // WILL ONLY WORK IF THERE IS ALREADY A SHARED POINTER TO THIS OBJECT.
-  fxl::Closure NewCallback();
+  fit::closure NewCallback();
 
   // Specifies a callback to be called when all child operations have completed.
   // |async| specifies the task runner on which to call |join_callback|.
@@ -54,7 +54,7 @@
   // immediately. If child operations are pending, the callback is posted when
   // all child operations have completed. Only one callback at a time can be
   // registered with WhenJoined.
-  void WhenJoined(async_t* async, const fxl::Closure& join_callback);
+  void WhenJoined(async_t* async, fit::closure join_callback);
 
   // Cancels a callback registered with WhenJoined if it hasn't run yet. The
   // return value indicates whether a callback was cancelled.
@@ -63,7 +63,7 @@
  private:
   std::mutex mutex_;
   size_t counter_ = 0;
-  fxl::Closure join_callback_;
+  fit::closure join_callback_;
   async_t* join_callback_async_;
 };
 
diff --git a/bin/media/net_media_service/BUILD.gn b/bin/media/net_media_service/BUILD.gn
index 64e2f97..5dc92aa 100644
--- a/bin/media/net_media_service/BUILD.gn
+++ b/bin/media/net_media_service/BUILD.gn
@@ -42,7 +42,6 @@
     "//garnet/public/lib/media/timeline",
     "//garnet/public/lib/netconnector/cpp",
     "//garnet/public/lib/netconnector/fidl",
-    "//garnet/public/lib/network/fidl",
     "//garnet/public/lib/url",
   ]
 }
diff --git a/bin/media/net_media_service/factory_service_base.h b/bin/media/net_media_service/factory_service_base.h
index ee0b9c7..d06a656 100644
--- a/bin/media/net_media_service/factory_service_base.h
+++ b/bin/media/net_media_service/factory_service_base.h
@@ -146,7 +146,8 @@
     fidl::BindingSet<Interface> bindings_;
   };
 
-  FactoryServiceBase(std::unique_ptr<fuchsia::sys::StartupContext> startup_context)
+  FactoryServiceBase(
+      std::unique_ptr<fuchsia::sys::StartupContext> startup_context)
       : startup_context_(std::move(startup_context)),
         async_(async_get_default()) {}
 
diff --git a/bin/media/net_media_service/media_player_messages.cc b/bin/media/net_media_service/media_player_messages.cc
index 9b03b66..87d5b2b 100644
--- a/bin/media/net_media_service/media_player_messages.cc
+++ b/bin/media/net_media_service/media_player_messages.cc
@@ -72,8 +72,7 @@
 
 // static
 std::unique_ptr<MediaPlayerOutMessage> MediaPlayerOutMessage::TimeCheckResponse(
-    int64_t requestor_time,
-    int64_t responder_time) {
+    int64_t requestor_time, int64_t responder_time) {
   std::unique_ptr<MediaPlayerOutMessage> message =
       std::make_unique<MediaPlayerOutMessage>();
   message->type_ = MediaPlayerOutMessageType::kTimeCheckResponse;
@@ -86,7 +85,8 @@
 
 // static
 std::unique_ptr<MediaPlayerOutMessage>
-MediaPlayerOutMessage::StatusNotification(MediaPlayerStatusPtr status) {
+MediaPlayerOutMessage::StatusNotification(
+    fuchsia::mediaplayer::MediaPlayerStatusPtr status) {
   std::unique_ptr<MediaPlayerOutMessage> message =
       std::make_unique<MediaPlayerOutMessage>();
   message->type_ = MediaPlayerOutMessageType::kStatusNotification;
@@ -152,8 +152,9 @@
   return serializer << value->status_;
 }
 
-Serializer& operator<<(Serializer& serializer,
-                       const MediaPlayerStatusPtr& value) {
+Serializer& operator<<(
+    Serializer& serializer,
+    const fuchsia::mediaplayer::MediaPlayerStatusPtr& value) {
   FXL_DCHECK(value);
   return serializer << Optional(value->timeline_transform)
                     << value->end_of_stream << value->content_has_audio
@@ -163,13 +164,14 @@
 }
 
 Serializer& operator<<(Serializer& serializer,
-                       const media::TimelineTransformPtr& value) {
+                       const fuchsia::media::TimelineTransformPtr& value) {
   FXL_DCHECK(value);
   return serializer << value->reference_time << value->subject_time
                     << value->reference_delta << value->subject_delta;
 }
 
-Serializer& operator<<(Serializer& serializer, const MediaMetadataPtr& value) {
+Serializer& operator<<(Serializer& serializer,
+                       const fuchsia::mediaplayer::MediaMetadataPtr& value) {
   FXL_DCHECK(value);
   return serializer << value->duration << Optional(value->title)
                     << Optional(value->artist) << Optional(value->album)
@@ -177,7 +179,8 @@
                     << Optional(value->composer);
 }
 
-Serializer& operator<<(Serializer& serializer, const ProblemPtr& value) {
+Serializer& operator<<(Serializer& serializer,
+                       const fuchsia::mediaplayer::ProblemPtr& value) {
   FXL_DCHECK(value);
   return serializer << value->type << Optional(value->details);
 }
@@ -312,8 +315,8 @@
 }
 
 Deserializer& operator>>(Deserializer& deserializer,
-                         MediaPlayerStatusPtr& value) {
-  value = MediaPlayerStatus::New();
+                         fuchsia::mediaplayer::MediaPlayerStatusPtr& value) {
+  value = fuchsia::mediaplayer::MediaPlayerStatus::New();
   deserializer >> Optional(value->timeline_transform) >> value->end_of_stream >>
       value->content_has_audio >> value->content_has_video >>
       value->audio_connected >> value->video_connected >>
@@ -325,8 +328,8 @@
 }
 
 Deserializer& operator>>(Deserializer& deserializer,
-                         media::TimelineTransformPtr& value) {
-  value = media::TimelineTransform::New();
+                         fuchsia::media::TimelineTransformPtr& value) {
+  value = fuchsia::media::TimelineTransform::New();
   deserializer >> value->reference_time >> value->subject_time >>
       value->reference_delta >> value->subject_delta;
   if (!deserializer.healthy()) {
@@ -335,8 +338,9 @@
   return deserializer;
 }
 
-Deserializer& operator>>(Deserializer& deserializer, MediaMetadataPtr& value) {
-  value = MediaMetadata::New();
+Deserializer& operator>>(Deserializer& deserializer,
+                         fuchsia::mediaplayer::MediaMetadataPtr& value) {
+  value = fuchsia::mediaplayer::MediaMetadata::New();
   deserializer >> value->duration >> Optional(value->title) >>
       Optional(value->artist) >> Optional(value->album) >>
       Optional(value->publisher) >> Optional(value->genre) >>
@@ -347,8 +351,9 @@
   return deserializer;
 }
 
-Deserializer& operator>>(Deserializer& deserializer, ProblemPtr& value) {
-  value = Problem::New();
+Deserializer& operator>>(Deserializer& deserializer,
+                         fuchsia::mediaplayer::ProblemPtr& value) {
+  value = fuchsia::mediaplayer::Problem::New();
   deserializer >> value->type >> Optional(value->details);
   if (!deserializer.healthy()) {
     value.reset();
diff --git a/bin/media/net_media_service/media_player_messages.h b/bin/media/net_media_service/media_player_messages.h
index 539a04c..6970f5a 100644
--- a/bin/media/net_media_service/media_player_messages.h
+++ b/bin/media/net_media_service/media_player_messages.h
@@ -7,7 +7,8 @@
 
 #include <memory>
 
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
+
 #include "garnet/bin/media/net_media_service/serialization.h"
 
 namespace media_player {
@@ -65,7 +66,7 @@
 
 // Sent by the stub to notify the proxy of a change in status.
 struct MediaPlayerStatusNotification {
-  MediaPlayerStatusPtr status_;
+  fuchsia::mediaplayer::MediaPlayerStatusPtr status_;
 };
 
 // Union-like of all possible messages sent by the proxy and handled
@@ -93,10 +94,9 @@
 // by the proxy.
 struct MediaPlayerOutMessage {
   static std::unique_ptr<MediaPlayerOutMessage> TimeCheckResponse(
-      int64_t requestor_time,
-      int64_t responder_time);
+      int64_t requestor_time, int64_t responder_time);
   static std::unique_ptr<MediaPlayerOutMessage> StatusNotification(
-      MediaPlayerStatusPtr status);
+      fuchsia::mediaplayer::MediaPlayerStatusPtr status);
 
   MediaPlayerOutMessageType type_;
   std::unique_ptr<MediaPlayerTimeCheckResponse> time_check_response_;
@@ -124,11 +124,13 @@
     Serializer& serializer,
     const std::unique_ptr<MediaPlayerStatusNotification>& value);
 Serializer& operator<<(Serializer& serializer,
-                       const MediaPlayerStatusPtr& value);
+                       const fuchsia::mediaplayer::MediaPlayerStatusPtr& value);
 Serializer& operator<<(Serializer& serializer,
-                       const media::TimelineTransformPtr& value);
-Serializer& operator<<(Serializer& serializer, const MediaMetadataPtr& value);
-Serializer& operator<<(Serializer& serializer, const ProblemPtr& value);
+                       const fuchsia::media::TimelineTransformPtr& value);
+Serializer& operator<<(Serializer& serializer,
+                       const fuchsia::mediaplayer::MediaMetadataPtr& value);
+Serializer& operator<<(Serializer& serializer,
+                       const fuchsia::mediaplayer::ProblemPtr& value);
 Serializer& operator<<(Serializer& serializer,
                        const std::unique_ptr<MediaPlayerInMessage>& value);
 Serializer& operator<<(Serializer& serializer,
@@ -154,11 +156,13 @@
 Deserializer& operator>>(Deserializer& deserializer,
                          std::unique_ptr<MediaPlayerStatusNotification>& value);
 Deserializer& operator>>(Deserializer& deserializer,
-                         MediaPlayerStatusPtr& value);
+                         fuchsia::mediaplayer::MediaPlayerStatusPtr& value);
 Deserializer& operator>>(Deserializer& deserializer,
-                         media::TimelineTransformPtr& value);
-Deserializer& operator>>(Deserializer& deserializer, MediaMetadataPtr& value);
-Deserializer& operator>>(Deserializer& deserializer, ProblemPtr& value);
+                         fuchsia::media::TimelineTransformPtr& value);
+Deserializer& operator>>(Deserializer& deserializer,
+                         fuchsia::mediaplayer::MediaMetadataPtr& value);
+Deserializer& operator>>(Deserializer& deserializer,
+                         fuchsia::mediaplayer::ProblemPtr& value);
 Deserializer& operator>>(Deserializer& deserializer,
                          std::unique_ptr<MediaPlayerInMessage>& value);
 Deserializer& operator>>(Deserializer& deserializer,
diff --git a/bin/media/net_media_service/media_player_net_proxy.cc b/bin/media/net_media_service/media_player_net_proxy.cc
index 298f340..4dbeec8 100644
--- a/bin/media/net_media_service/media_player_net_proxy.cc
+++ b/bin/media/net_media_service/media_player_net_proxy.cc
@@ -6,31 +6,31 @@
 
 #include <vector>
 
-#include <netconnector/cpp/fidl.h>
 #include <lib/zx/channel.h>
+#include <netconnector/cpp/fidl.h>
 
 #include "lib/fidl/cpp/clone.h"
 #include "lib/fxl/logging.h"
 #include "lib/media/timeline/timeline.h"
 
-using media::Timeline;
-
 namespace media_player {
 
 // static
 std::shared_ptr<MediaPlayerNetProxy> MediaPlayerNetProxy::Create(
     fidl::StringPtr device_name, fidl::StringPtr service_name,
-    fidl::InterfaceRequest<MediaPlayer> request, NetMediaServiceImpl* owner) {
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+    NetMediaServiceImpl* owner) {
   return std::shared_ptr<MediaPlayerNetProxy>(new MediaPlayerNetProxy(
       device_name, service_name, std::move(request), owner));
 }
 
 MediaPlayerNetProxy::MediaPlayerNetProxy(
     fidl::StringPtr device_name, fidl::StringPtr service_name,
-    fidl::InterfaceRequest<MediaPlayer> request, NetMediaServiceImpl* owner)
-    : NetMediaServiceImpl::MultiClientProduct<MediaPlayer>(
-          this, std::move(request), owner),
-      status_(MediaPlayerStatus::New()) {
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+    NetMediaServiceImpl* owner)
+    : NetMediaServiceImpl::MultiClientProduct<
+          fuchsia::mediaplayer::MediaPlayer>(this, std::move(request), owner),
+      status_(fuchsia::mediaplayer::MediaPlayerStatus::New()) {
   FXL_DCHECK(owner);
 
   // Fire |StatusChanged| event for the new client.
@@ -79,7 +79,7 @@
 }
 
 void MediaPlayerNetProxy::SetReaderSource(
-    fidl::InterfaceHandle<SeekingReader> reader_handle) {
+    fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader> reader_handle) {
   FXL_LOG(ERROR)
       << "SetReaderSource called on MediaPlayer proxy - not supported.";
   UnbindAndReleaseFromOwner();
@@ -107,20 +107,21 @@
 
 void MediaPlayerNetProxy::CreateView(
     fidl::InterfaceHandle<::fuchsia::ui::views_v1::ViewManager> view_manager,
-    fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request) {
+    fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+        view_owner_request) {
   FXL_LOG(ERROR) << "CreateView called on MediaPlayer proxy - not supported.";
   UnbindAndReleaseFromOwner();
 }
 
 void MediaPlayerNetProxy::SetAudioRenderer(
-    fidl::InterfaceHandle<media::AudioRenderer2> audio_renderer) {
+    fidl::InterfaceHandle<fuchsia::media::AudioRenderer2> audio_renderer) {
   FXL_LOG(ERROR)
       << "SetAudioRenderer called on MediaPlayer proxy - not supported.";
   UnbindAndReleaseFromOwner();
 }
 
 void MediaPlayerNetProxy::AddBinding(
-    fidl::InterfaceRequest<MediaPlayer> request) {
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request) {
   MultiClientProduct::AddBinding(std::move(request));
 
   // Fire |StatusChanged| event for the new client.
@@ -129,7 +130,7 @@
 
 void MediaPlayerNetProxy::SendTimeCheckMessage() {
   message_relay_.SendMessage(Serializer::Serialize(
-      MediaPlayerInMessage::TimeCheckRequest(Timeline::local_now())));
+      MediaPlayerInMessage::TimeCheckRequest(media::Timeline::local_now())));
 }
 
 void MediaPlayerNetProxy::HandleReceivedMessage(
@@ -157,7 +158,7 @@
       // calculate the average of two values with (a + b) / 2. We use
       // a + (b - a) / 2, because it's less likely to overflow.
       int64_t local_then = message->time_check_response_->requestor_time_ +
-                           (Timeline::local_now() -
+                           (media::Timeline::local_now() -
                             message->time_check_response_->requestor_time_) /
                                2;
 
diff --git a/bin/media/net_media_service/media_player_net_proxy.h b/bin/media/net_media_service/media_player_net_proxy.h
index 53cee6b..15545ba 100644
--- a/bin/media/net_media_service/media_player_net_proxy.h
+++ b/bin/media/net_media_service/media_player_net_proxy.h
@@ -16,13 +16,14 @@
 namespace media_player {
 
 // Proxy that allows a client to control a remote media player.
-class MediaPlayerNetProxy
-    : public NetMediaServiceImpl::MultiClientProduct<MediaPlayer>,
-      public MediaPlayer {
+class MediaPlayerNetProxy : public NetMediaServiceImpl::MultiClientProduct<
+                                fuchsia::mediaplayer::MediaPlayer>,
+                            public fuchsia::mediaplayer::MediaPlayer {
  public:
   static std::shared_ptr<MediaPlayerNetProxy> Create(
       fidl::StringPtr device_name, fidl::StringPtr service_name,
-      fidl::InterfaceRequest<MediaPlayer> request, NetMediaServiceImpl* owner);
+      fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+      NetMediaServiceImpl* owner);
 
   ~MediaPlayerNetProxy() override;
 
@@ -32,7 +33,8 @@
   void SetFileSource(zx::channel file_channel) override;
 
   void SetReaderSource(
-      fidl::InterfaceHandle<SeekingReader> reader_handle) override;
+      fidl::InterfaceHandle<fuchsia::mediaplayer::SeekingReader> reader_handle)
+      override;
 
   void Play() override;
 
@@ -42,19 +44,22 @@
 
   void SetGain(float gain) override;
 
-  void CreateView(fidl::InterfaceHandle<::fuchsia::ui::views_v1::ViewManager> view_manager,
-                  fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
-                      view_owner_request) override;
+  void CreateView(
+      fidl::InterfaceHandle<::fuchsia::ui::views_v1::ViewManager> view_manager,
+      fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
+          view_owner_request) override;
 
-  void SetAudioRenderer(
-      fidl::InterfaceHandle<media::AudioRenderer2> audio_renderer) override;
+  void SetAudioRenderer(fidl::InterfaceHandle<fuchsia::media::AudioRenderer2>
+                            audio_renderer) override;
 
-  void AddBinding(fidl::InterfaceRequest<MediaPlayer> request) override;
+  void AddBinding(fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer>
+                      request) override;
 
  private:
-  MediaPlayerNetProxy(fidl::StringPtr device_name, fidl::StringPtr service_name,
-                      fidl::InterfaceRequest<MediaPlayer> request,
-                      NetMediaServiceImpl* owner);
+  MediaPlayerNetProxy(
+      fidl::StringPtr device_name, fidl::StringPtr service_name,
+      fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer> request,
+      NetMediaServiceImpl* owner);
 
   void SendTimeCheckMessage();
 
@@ -63,7 +68,7 @@
   void SendStatusUpdates();
 
   netconnector::MessageRelay message_relay_;
-  MediaPlayerStatusPtr status_;
+  fuchsia::mediaplayer::MediaPlayerStatusPtr status_;
   media::TimelineFunction remote_to_local_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(MediaPlayerNetProxy);
diff --git a/bin/media/net_media_service/media_player_net_publisher.cc b/bin/media/net_media_service/media_player_net_publisher.cc
index a3a0dc8..4a79d76 100644
--- a/bin/media/net_media_service/media_player_net_publisher.cc
+++ b/bin/media/net_media_service/media_player_net_publisher.cc
@@ -5,7 +5,7 @@
 #include "garnet/bin/media/net_media_service/media_player_net_publisher.h"
 
 #include <fcntl.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 
 #include "lib/fxl/logging.h"
 #include "lib/url/gurl.h"
@@ -15,7 +15,7 @@
 // static
 std::shared_ptr<MediaPlayerNetPublisher> MediaPlayerNetPublisher::Create(
     fidl::StringPtr service_name,
-    fidl::InterfaceHandle<MediaPlayer> media_player,
+    fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer> media_player,
     NetMediaServiceImpl* owner) {
   return std::shared_ptr<MediaPlayerNetPublisher>(new MediaPlayerNetPublisher(
       service_name, std::move(media_player), owner));
@@ -23,7 +23,8 @@
 
 MediaPlayerNetPublisher::MediaPlayerNetPublisher(
     fidl::StringPtr service_name,
-    fidl::InterfaceHandle<MediaPlayer> media_player, NetMediaServiceImpl* owner)
+    fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer> media_player,
+    NetMediaServiceImpl* owner)
     : NetMediaServiceImpl::ProductBase(owner),
       media_player_(media_player.Bind()),
       responder_(media_player_, service_name, owner->startup_context()) {
diff --git a/bin/media/net_media_service/media_player_net_publisher.h b/bin/media/net_media_service/media_player_net_publisher.h
index 7250217..8fb44e3 100644
--- a/bin/media/net_media_service/media_player_net_publisher.h
+++ b/bin/media/net_media_service/media_player_net_publisher.h
@@ -5,7 +5,8 @@
 #ifndef GARNET_BIN_MEDIA_NET_MEDIA_SERVICE_MEDIA_PLAYER_NET_PUBLISHER_H_
 #define GARNET_BIN_MEDIA_NET_MEDIA_SERVICE_MEDIA_PLAYER_NET_PUBLISHER_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "garnet/bin/media/net_media_service/media_player_net_stub.h"
 #include "garnet/bin/media/net_media_service/net_media_service_impl.h"
 #include "lib/fxl/macros.h"
@@ -21,18 +22,21 @@
  public:
   static std::shared_ptr<MediaPlayerNetPublisher> Create(
       fidl::StringPtr service_name,
-      fidl::InterfaceHandle<MediaPlayer> media_player,
+      fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer> media_player,
       NetMediaServiceImpl* owner);
 
   ~MediaPlayerNetPublisher() override;
 
  private:
-  MediaPlayerNetPublisher(fidl::StringPtr service_name,
-                          fidl::InterfaceHandle<MediaPlayer> media_player,
-                          NetMediaServiceImpl* owner);
+  MediaPlayerNetPublisher(
+      fidl::StringPtr service_name,
+      fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer> media_player,
+      NetMediaServiceImpl* owner);
 
-  MediaPlayerPtr media_player_;
-  netconnector::NetStubResponder<MediaPlayer, MediaPlayerNetStub> responder_;
+  fuchsia::mediaplayer::MediaPlayerPtr media_player_;
+  netconnector::NetStubResponder<fuchsia::mediaplayer::MediaPlayer,
+                                 MediaPlayerNetStub>
+      responder_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(MediaPlayerNetPublisher);
 };
diff --git a/bin/media/net_media_service/media_player_net_stub.cc b/bin/media/net_media_service/media_player_net_stub.cc
index 610e3dd..67c9d84 100644
--- a/bin/media/net_media_service/media_player_net_stub.cc
+++ b/bin/media/net_media_service/media_player_net_stub.cc
@@ -17,15 +17,18 @@
 namespace media_player {
 
 MediaPlayerNetStub::MediaPlayerNetStub(
-    const fidl::InterfacePtr<MediaPlayer>& player, zx::channel channel,
-    netconnector::NetStubResponder<MediaPlayer, MediaPlayerNetStub>* responder)
+    const fidl::InterfacePtr<fuchsia::mediaplayer::MediaPlayer>& player,
+    zx::channel channel,
+    netconnector::NetStubResponder<fuchsia::mediaplayer::MediaPlayer,
+                                   MediaPlayerNetStub>* responder)
     : player_(player), responder_(responder) {
   FXL_DCHECK(player_);
   FXL_DCHECK(responder_);
 
-  player_.events().StatusChanged = [this](MediaPlayerStatus status) {
-    HandleStatusChanged(status);
-  };
+  player_.events().StatusChanged =
+      [this](fuchsia::mediaplayer::MediaPlayerStatus status) {
+        HandleStatusChanged(status);
+      };
 
   message_relay_.SetMessageReceivedCallback(
       [this](std::vector<uint8_t> message) { HandleReceivedMessage(message); });
@@ -92,7 +95,8 @@
   }
 }
 
-void MediaPlayerNetStub::HandleStatusChanged(const MediaPlayerStatus& status) {
+void MediaPlayerNetStub::HandleStatusChanged(
+    const fuchsia::mediaplayer::MediaPlayerStatus& status) {
   if (!time_check_received_) {
     cached_status_ = fidl::MakeOptional(fidl::Clone(status));
     return;
diff --git a/bin/media/net_media_service/media_player_net_stub.h b/bin/media/net_media_service/media_player_net_stub.h
index 6af6418..b1dcb6b 100644
--- a/bin/media/net_media_service/media_player_net_stub.h
+++ b/bin/media/net_media_service/media_player_net_stub.h
@@ -8,9 +8,9 @@
 #include <memory>
 
 #include <endian.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/zx/channel.h>
 
-#include <media/cpp/fidl.h>
 #include "garnet/bin/media/net_media_service/media_player_messages.h"
 #include "lib/fxl/macros.h"
 #include "lib/netconnector/cpp/message_relay.h"
@@ -23,10 +23,10 @@
     : public std::enable_shared_from_this<MediaPlayerNetStub> {
  public:
   MediaPlayerNetStub(
-      const fidl::InterfacePtr<MediaPlayer>& player,
+      const fidl::InterfacePtr<fuchsia::mediaplayer::MediaPlayer>& player,
       zx::channel channel,
-      netconnector::NetStubResponder<MediaPlayer, MediaPlayerNetStub>*
-          responder);
+      netconnector::NetStubResponder<fuchsia::mediaplayer::MediaPlayer,
+                                     MediaPlayerNetStub>* responder);
 
   ~MediaPlayerNetStub();
 
@@ -35,12 +35,14 @@
   void HandleReceivedMessage(std::vector<uint8_t> message);
 
   // Handles a status change from the player.
-  void HandleStatusChanged(const MediaPlayerStatus& status);
+  void HandleStatusChanged(
+      const fuchsia::mediaplayer::MediaPlayerStatus& status);
 
-  const fidl::InterfacePtr<MediaPlayer>& player_;
+  const fidl::InterfacePtr<fuchsia::mediaplayer::MediaPlayer>& player_;
   netconnector::MessageRelay message_relay_;
-  netconnector::NetStubResponder<MediaPlayer, MediaPlayerNetStub>* responder_;
-  MediaPlayerStatusPtr cached_status_;
+  netconnector::NetStubResponder<fuchsia::mediaplayer::MediaPlayer,
+                                 MediaPlayerNetStub>* responder_;
+  fuchsia::mediaplayer::MediaPlayerStatusPtr cached_status_;
   bool time_check_received_ = false;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(MediaPlayerNetStub);
diff --git a/bin/media/net_media_service/net_media_service_impl.cc b/bin/media/net_media_service/net_media_service_impl.cc
index 068c9c7..afdc352 100644
--- a/bin/media/net_media_service/net_media_service_impl.cc
+++ b/bin/media/net_media_service/net_media_service_impl.cc
@@ -12,24 +12,28 @@
 NetMediaServiceImpl::NetMediaServiceImpl(
     std::unique_ptr<fuchsia::sys::StartupContext> startup_context)
     : FactoryServiceBase(std::move(startup_context)) {
-  this->startup_context()->outgoing().AddPublicService<NetMediaService>(
-      [this](fidl::InterfaceRequest<NetMediaService> request) {
-        bindings_.AddBinding(this, std::move(request));
-      });
+  this->startup_context()
+      ->outgoing()
+      .AddPublicService<fuchsia::mediaplayer::NetMediaService>(
+          [this](fidl::InterfaceRequest<fuchsia::mediaplayer::NetMediaService>
+                     request) {
+            bindings_.AddBinding(this, std::move(request));
+          });
 }
 
 NetMediaServiceImpl::~NetMediaServiceImpl() {}
 
 void NetMediaServiceImpl::PublishMediaPlayer(
     fidl::StringPtr service_name,
-    fidl::InterfaceHandle<MediaPlayer> media_player) {
+    fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer> media_player) {
   AddProduct(MediaPlayerNetPublisher::Create(service_name,
                                              std::move(media_player), this));
 }
 
 void NetMediaServiceImpl::CreateMediaPlayerProxy(
     fidl::StringPtr device_name, fidl::StringPtr service_name,
-    fidl::InterfaceRequest<MediaPlayer> media_player_request) {
+    fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer>
+        media_player_request) {
   AddProduct(MediaPlayerNetProxy::Create(
       device_name, service_name, std::move(media_player_request), this));
 }
diff --git a/bin/media/net_media_service/net_media_service_impl.h b/bin/media/net_media_service/net_media_service_impl.h
index fcfd067..c2fc933 100644
--- a/bin/media/net_media_service/net_media_service_impl.h
+++ b/bin/media/net_media_service/net_media_service_impl.h
@@ -5,7 +5,8 @@
 #ifndef GARNET_BIN_MEDIA_NET_MEDIA_SERVICE_NET_MEDIA_SERVICE_IMPL_H_
 #define GARNET_BIN_MEDIA_NET_MEDIA_SERVICE_NET_MEDIA_SERVICE_IMPL_H_
 
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
+
 #include "garnet/bin/media/net_media_service/factory_service_base.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
@@ -14,7 +15,7 @@
 namespace media_player {
 
 class NetMediaServiceImpl : public FactoryServiceBase<NetMediaServiceImpl>,
-                            public NetMediaService {
+                            public fuchsia::mediaplayer::NetMediaService {
  public:
   NetMediaServiceImpl(
       std::unique_ptr<fuchsia::sys::StartupContext> startup_context);
@@ -23,14 +24,16 @@
   // NetMediaService implementation.
   void PublishMediaPlayer(
       fidl::StringPtr service_name,
-      fidl::InterfaceHandle<MediaPlayer> media_player) override;
+      fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer> media_player)
+      override;
 
   void CreateMediaPlayerProxy(
       fidl::StringPtr device_name, fidl::StringPtr service_name,
-      fidl::InterfaceRequest<MediaPlayer> media_player_request) override;
+      fidl::InterfaceRequest<fuchsia::mediaplayer::MediaPlayer>
+          media_player_request) override;
 
  private:
-  fidl::BindingSet<NetMediaService> bindings_;
+  fidl::BindingSet<fuchsia::mediaplayer::NetMediaService> bindings_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(NetMediaServiceImpl);
 };
diff --git a/bin/media/util/BUILD.gn b/bin/media/util/BUILD.gn
index de6b222..b2304cf 100644
--- a/bin/media/util/BUILD.gn
+++ b/bin/media/util/BUILD.gn
@@ -13,4 +13,8 @@
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
diff --git a/bin/media/util/fidl_publisher.h b/bin/media/util/fidl_publisher.h
index 4808fda..6bea2f5 100644
--- a/bin/media/util/fidl_publisher.h
+++ b/bin/media/util/fidl_publisher.h
@@ -5,9 +5,10 @@
 #ifndef GARNET_BIN_MEDIA_UTIL_FIDL_PUBLISHER_H_
 #define GARNET_BIN_MEDIA_UTIL_FIDL_PUBLISHER_H_
 
-#include <functional>
 #include <vector>
 
+#include <lib/fit/function.h>
+
 #include "lib/fxl/logging.h"
 
 namespace media {
@@ -16,14 +17,14 @@
 template <typename TCallback>
 class FidlPublisher {
  public:
-  using CallbackRunner = std::function<void(TCallback, uint64_t)>;
+  using CallbackRunner = fit::function<void(TCallback, uint64_t)>;
 
   // Sets the callback runner. This method must be called before calling Get
   // or Updated. The callback runner calls a single callback using current
   // information.
-  void SetCallbackRunner(const CallbackRunner& callback_runner) {
+  void SetCallbackRunner(CallbackRunner callback_runner) {
     FXL_DCHECK(callback_runner);
-    callback_runner_ = callback_runner;
+    callback_runner_ = std::move(callback_runner);
   }
 
   // Handles a get request from the client. This method should be called from
@@ -32,7 +33,7 @@
     FXL_DCHECK(callback_runner_);
 
     if (version_last_seen < version_) {
-      callback_runner_(callback, version_);
+      callback_runner_(std::move(callback), version_);
     } else {
       pending_callbacks_.push_back(callback);
     }
diff --git a/bin/media/vol/vol_app.cc b/bin/media/vol/vol_app.cc
index 76778de..33ed5b6 100644
--- a/bin/media/vol/vol_app.cc
+++ b/bin/media/vol/vol_app.cc
@@ -9,12 +9,12 @@
 #include <audio_policy/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
+#include <lib/fit/function.h>
 
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/optional.h"
 #include "lib/fsl/tasks/fd_waiter.h"
 #include "lib/fxl/command_line.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/media/audio/perceived_level.h"
 
 using audio_policy::AudioPolicyStatus;
@@ -37,7 +37,7 @@
 
   os << std::string(level, '=') << "|" << std::string(kLevelMax - level, '-');
 
-  if (value.system_audio_gain_db == kMutedGain) {
+  if (value.system_audio_gain_db == fuchsia::media::kMutedGain) {
     os << " -infinity db";
   } else if (value.system_audio_gain_db == kUnityGain) {
     os << " 0.0 db";
@@ -55,10 +55,10 @@
 
 class VolApp {
  public:
-  VolApp(int argc, const char** argv, fxl::Closure quit_callback)
+  VolApp(int argc, const char** argv, fit::closure quit_callback)
       : startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
-        quit_callback_(quit_callback) {
-    FXL_DCHECK(quit_callback);
+        quit_callback_(std::move(quit_callback)) {
+    FXL_DCHECK(quit_callback_);
 
     fxl::CommandLine command_line = fxl::CommandLineFromArgcArgv(argc, argv);
 
@@ -118,7 +118,8 @@
 
     HandleStatus();
     audio_policy_service_->GetStatus(
-        kInitialStatus, [this](uint64_t version, AudioPolicyStatus status) {});
+        fuchsia::media::kInitialStatus,
+        [this](uint64_t version, AudioPolicyStatus status) {});
 
     if (interactive_) {
       std::cout << "\ninteractive mode:\n";
@@ -156,7 +157,7 @@
     return (istream >> *float_out) && istream.eof();
   }
 
-  void HandleStatus(uint64_t version = kInitialStatus,
+  void HandleStatus(uint64_t version = fuchsia::media::kInitialStatus,
                     audio_policy::AudioPolicyStatusPtr status = nullptr) {
     if (status) {
       system_audio_gain_db_ = status->system_audio_gain_db;
@@ -226,7 +227,7 @@
   }
 
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   audio_policy::AudioPolicyPtr audio_policy_service_;
   bool interactive_ = true;
   bool mute_ = false;
diff --git a/bin/netcfg/src/main.rs b/bin/netcfg/src/main.rs
index b54b4c8..bfd9fc8 100644
--- a/bin/netcfg/src/main.rs
+++ b/bin/netcfg/src/main.rs
@@ -9,16 +9,16 @@
 extern crate serde_derive;
 extern crate serde_json;
 extern crate fidl;
-extern crate fidl_device_settings;
-extern crate fidl_netstack;
+extern crate fidl_fuchsia_devicesettings;
+extern crate fidl_fuchsia_netstack as netstack;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
 extern crate futures;
 
 use failure::{Error, ResultExt};
-use fidl_device_settings::{DeviceSettingsManagerMarker};
-use fidl_netstack::{NetstackMarker, NetInterface, NetstackEvent, INTERFACE_FEATURE_SYNTH, INTERFACE_FEATURE_LOOPBACK};
+use fidl_fuchsia_devicesettings::{DeviceSettingsManagerMarker};
+use netstack::{NetstackMarker, NetInterface, NetstackEvent, INTERFACE_FEATURE_SYNTH, INTERFACE_FEATURE_LOOPBACK};
 use std::fs;
 use std::io::Read;
 use futures::{future, FutureExt, StreamExt};
diff --git a/bin/netconnector/BUILD.gn b/bin/netconnector/BUILD.gn
index 231807e..8819790 100644
--- a/bin/netconnector/BUILD.gn
+++ b/bin/netconnector/BUILD.gn
@@ -48,6 +48,7 @@
     "//garnet/public/lib/netstack/fidl",
     "//garnet/public/lib/svc/cpp",
     "//third_party/rapidjson",
+    "//zircon/public/lib/fit",
   ]
 }
 
@@ -58,8 +59,10 @@
 
   binary = "netconnector"
 
-  resources = [ {
-        path = rebase_path("netconnector.config")
-        dest = "netconnector.config"
-      } ]
+  resources = [
+    {
+      path = rebase_path("netconnector.config")
+      dest = "netconnector.config"
+    },
+  ]
 }
diff --git a/bin/netconnector/device_service_provider.h b/bin/netconnector/device_service_provider.h
index d328308..b4c3232 100644
--- a/bin/netconnector/device_service_provider.h
+++ b/bin/netconnector/device_service_provider.h
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_DEVICE_SERVICE_PROVIDER_H_
+#define GARNET_BIN_NETCONNECTOR_DEVICE_SERVICE_PROVIDER_H_
 
 #include <memory>
 #include <string>
 
-#include "garnet/bin/netconnector/socket_address.h"
 #include <fuchsia/sys/cpp/fidl.h>
+
+#include "garnet/bin/netconnector/socket_address.h"
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
 
@@ -44,3 +46,5 @@
 };
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_DEVICE_SERVICE_PROVIDER_H_
diff --git a/bin/netconnector/host_name.cc b/bin/netconnector/host_name.cc
index f3d3149..f0af239 100644
--- a/bin/netconnector/host_name.cc
+++ b/bin/netconnector/host_name.cc
@@ -4,10 +4,10 @@
 
 #include "garnet/bin/netconnector/host_name.h"
 
+#include <fuchsia/netstack/cpp/fidl.h>
 #include <limits.h>
 #include <unistd.h>
 
-#include <netstack/cpp/fidl.h>
 #include "garnet/bin/netconnector/socket_address.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/files/unique_fd.h"
@@ -21,10 +21,11 @@
 class NetstackClient {
  public:
   static void GetInterfaces(
-      const netstack::Netstack::GetInterfacesCallback& callback) {
+      const fuchsia::netstack::Netstack::GetInterfacesCallback& callback) {
     NetstackClient* client = new NetstackClient();
     client->netstack_->GetInterfaces(
-        [client, callback](fidl::VectorPtr<netstack::NetInterface> interfaces) {
+        [client, callback](
+            fidl::VectorPtr<fuchsia::netstack::NetInterface> interfaces) {
           callback(std::move(interfaces));
           delete client;
         });
@@ -34,12 +35,13 @@
   NetstackClient()
       : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
     FXL_DCHECK(context_);
-    netstack_ = context_->ConnectToEnvironmentService<netstack::Netstack>();
+    netstack_ =
+        context_->ConnectToEnvironmentService<fuchsia::netstack::Netstack>();
     FXL_DCHECK(netstack_);
   }
 
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
-  netstack::NetstackPtr netstack_;
+  fuchsia::netstack::NetstackPtr netstack_;
 };
 
 // Returns a host address, preferably V4. Returns an invalid address if no
@@ -51,13 +53,15 @@
     return ip_address;
 
   NetstackClient::GetInterfaces(
-      [](const fidl::VectorPtr<netstack::NetInterface>& interfaces) {
+      [](const fidl::VectorPtr<fuchsia::netstack::NetInterface>& interfaces) {
         for (const auto& interface : *interfaces) {
-          if (interface.addr.family == netstack::NetAddressFamily::IPV4) {
+          if (interface.addr.family ==
+              fuchsia::netstack::NetAddressFamily::IPV4) {
             ip_address = IpAddress(&interface.addr);
             break;
           }
-          if (interface.addr.family == netstack::NetAddressFamily::IPV6) {
+          if (interface.addr.family ==
+              fuchsia::netstack::NetAddressFamily::IPV6) {
             ip_address = IpAddress(&interface.addr);
             // Keep looking...v4 is preferred.
           }
diff --git a/bin/netconnector/host_name.h b/bin/netconnector/host_name.h
index 3f1ff8f..5d2531f 100644
--- a/bin/netconnector/host_name.h
+++ b/bin/netconnector/host_name.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_HOST_NAME_H_
+#define GARNET_BIN_NETCONNECTOR_HOST_NAME_H_
 
 #include <string>
 
@@ -15,3 +16,5 @@
 std::string GetHostName();
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_HOST_NAME_H_
diff --git a/bin/netconnector/ip_address.cc b/bin/netconnector/ip_address.cc
index a64fd00..c30e7f3 100644
--- a/bin/netconnector/ip_address.cc
+++ b/bin/netconnector/ip_address.cc
@@ -2,16 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/netconnector/ip_address.h"
+
 #include <sstream>
 
 #include <arpa/inet.h>
 #include <endian.h>
+#include <fuchsia/netstack/cpp/fidl.h>
 #include <netdb.h>
 #include <sys/socket.h>
 
-#include "garnet/bin/netconnector/ip_address.h"
-#include <netstack/cpp/fidl.h>
-
 namespace netconnector {
 
 // static
@@ -79,14 +79,8 @@
   v4_ = addr;
 }
 
-IpAddress::IpAddress(uint16_t w0,
-                     uint16_t w1,
-                     uint16_t w2,
-                     uint16_t w3,
-                     uint16_t w4,
-                     uint16_t w5,
-                     uint16_t w6,
-                     uint16_t w7) {
+IpAddress::IpAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3,
+                     uint16_t w4, uint16_t w5, uint16_t w6, uint16_t w7) {
   family_ = AF_INET;
   uint16_t* words = v6_.s6_addr16;
   words[0] = htobe16(w0);
@@ -123,14 +117,14 @@
   }
 }
 
-IpAddress::IpAddress(const netstack::NetAddress* addr) {
+IpAddress::IpAddress(const fuchsia::netstack::NetAddress* addr) {
   FXL_DCHECK(addr != nullptr);
   switch (addr->family) {
-    case netstack::NetAddressFamily::IPV4:
+    case fuchsia::netstack::NetAddressFamily::IPV4:
       family_ = AF_INET;
       memcpy(&v4_, addr->ipv4->addr.data(), 4);
       break;
-    case netstack::NetAddressFamily::IPV6:
+    case fuchsia::netstack::NetAddressFamily::IPV6:
       family_ = AF_INET6;
       memcpy(&v6_, addr->ipv6->addr.data(), 16);
       break;
diff --git a/bin/netconnector/ip_address.h b/bin/netconnector/ip_address.h
index 4bcb812..97742aa 100644
--- a/bin/netconnector/ip_address.h
+++ b/bin/netconnector/ip_address.h
@@ -2,15 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_IP_ADDRESS_H_
+#define GARNET_BIN_NETCONNECTOR_IP_ADDRESS_H_
 
 #include <arpa/inet.h>
 
 #include "lib/fxl/logging.h"
 
+namespace fuchsia {
 namespace netstack {
 class NetAddress;
 }
+}  // namespace fuchsia
 
 namespace netconnector {
 
@@ -39,14 +42,8 @@
   explicit IpAddress(const in_addr& addr);
 
   // Creates an IPV6 address from eight address words.
-  IpAddress(uint16_t w0,
-            uint16_t w1,
-            uint16_t w2,
-            uint16_t w3,
-            uint16_t w4,
-            uint16_t w5,
-            uint16_t w6,
-            uint16_t w7);
+  IpAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4,
+            uint16_t w5, uint16_t w6, uint16_t w7);
 
   // Creates an IPV6 address from two address words (first and last).
   IpAddress(uint16_t w0, uint16_t w7);
@@ -58,7 +55,7 @@
   explicit IpAddress(const sockaddr* addr);
 
   // Creates an address from a NetAddress struct.
-  explicit IpAddress(const netstack::NetAddress* addr);
+  explicit IpAddress(const fuchsia::netstack::NetAddress* addr);
 
   bool is_valid() const { return family_ != AF_UNSPEC; }
 
@@ -117,3 +114,5 @@
 std::ostream& operator<<(std::ostream& os, const IpAddress& value);
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_IP_ADDRESS_H_
diff --git a/bin/netconnector/ip_port.h b/bin/netconnector/ip_port.h
index ed9574c..3c9c580 100644
--- a/bin/netconnector/ip_port.h
+++ b/bin/netconnector/ip_port.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_IP_PORT_H_
+#define GARNET_BIN_NETCONNECTOR_IP_PORT_H_
 
 #include <ostream>
 
@@ -80,3 +81,5 @@
 std::ostream& operator<<(std::ostream& os, IpPort value);
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_IP_PORT_H_
diff --git a/bin/netconnector/listener.cc b/bin/netconnector/listener.cc
index bd88e92..5b1c637 100644
--- a/bin/netconnector/listener.cc
+++ b/bin/netconnector/listener.cc
@@ -19,13 +19,10 @@
 
 Listener::Listener() : async_(async_get_default()) {}
 
-Listener::~Listener() {
-  Stop();
-}
+Listener::~Listener() { Stop(); }
 
 void Listener::Start(
-    IpPort port,
-    std::function<void(fxl::UniqueFD)> new_connection_callback) {
+    IpPort port, fit::function<void(fxl::UniqueFD)> new_connection_callback) {
   FXL_DCHECK(!socket_fd_.is_valid()) << "Started when already listening";
 
   socket_fd_ = fxl::UniqueFD(socket(AF_INET, SOCK_STREAM, 0));
@@ -53,7 +50,7 @@
     return;
   }
 
-  new_connection_callback_ = new_connection_callback;
+  new_connection_callback_ = std::move(new_connection_callback);
 
   worker_thread_ = std::thread([this]() { Worker(); });
 }
diff --git a/bin/netconnector/listener.h b/bin/netconnector/listener.h
index 8462cdc..fd3fab5 100644
--- a/bin/netconnector/listener.h
+++ b/bin/netconnector/listener.h
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_LISTENER_H_
+#define GARNET_BIN_NETCONNECTOR_LISTENER_H_
 
 #include <memory>
 #include <thread>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/bin/netconnector/ip_port.h"
 #include "lib/fxl/files/unique_fd.h"
@@ -28,7 +30,7 @@
   // Starts listening on |port|. |new_connection_callback| is called when a new
   // connection is requested.
   void Start(IpPort port,
-             std::function<void(fxl::UniqueFD)> new_connection_callback);
+             fit::function<void(fxl::UniqueFD)> new_connection_callback);
 
   // Stops the listener.
   void Stop();
@@ -39,7 +41,7 @@
   void Worker();
 
   async_t* async_;
-  std::function<void(fxl::UniqueFD)> new_connection_callback_;
+  fit::function<void(fxl::UniqueFD)> new_connection_callback_;
   fxl::UniqueFD socket_fd_;
   std::thread worker_thread_;
 
@@ -47,3 +49,5 @@
 };
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_LISTENER_H_
diff --git a/bin/netconnector/message_transceiver.cc b/bin/netconnector/message_transceiver.cc
index cd4fa1e..2b3f90e 100644
--- a/bin/netconnector/message_transceiver.cc
+++ b/bin/netconnector/message_transceiver.cc
@@ -35,9 +35,7 @@
   WaitToReceive();
 }
 
-MessageTransceiver::~MessageTransceiver() {
-  CancelWaiters();
-}
+MessageTransceiver::~MessageTransceiver() { CancelWaiters(); }
 
 void MessageTransceiver::SetChannel(zx::channel channel) {
   FXL_DCHECK(channel);
@@ -104,9 +102,9 @@
   });
 }
 
-void MessageTransceiver::PostSendTask(std::function<void()> task) {
+void MessageTransceiver::PostSendTask(fit::closure task) {
   FXL_DCHECK(socket_fd_.is_valid()) << "PostSendTask with invalid socket.";
-  send_tasks_.push(task);
+  send_tasks_.push(std::move(task));
   if (send_tasks_.size() == 1) {
     MaybeWaitToSend();
   }
@@ -120,7 +118,7 @@
   if (!fd_send_waiter_.Wait(
           [this](zx_status_t status, uint32_t events) {
             FXL_DCHECK(!send_tasks_.empty());
-            auto task = send_tasks_.front();
+            auto task = std::move(send_tasks_.front());
             send_tasks_.pop();
             task();
           },
@@ -128,14 +126,13 @@
     // Wait failed because the fd is no longer valid. We need to clear
     // |send_tasks_| before we proceeed, because a non-empty send_tasks_
     // implies the need to cancel the wait.
-    std::queue<std::function<void()>> doomed;
+    std::queue<fit::closure> doomed;
     send_tasks_.swap(doomed);
     CloseConnection();
   }
 }
 
-void MessageTransceiver::SendPacket(PacketType type,
-                                    const void* payload,
+void MessageTransceiver::SendPacket(PacketType type, const void* payload,
                                     size_t payload_size) {
   FXL_DCHECK(payload_size == 0 || payload != nullptr);
 
@@ -276,10 +273,8 @@
   }
 }
 
-bool MessageTransceiver::CopyReceivedBytes(uint8_t** bytes,
-                                           size_t* byte_count,
-                                           uint8_t* dest,
-                                           size_t dest_size,
+bool MessageTransceiver::CopyReceivedBytes(uint8_t** bytes, size_t* byte_count,
+                                           uint8_t* dest, size_t dest_size,
                                            size_t dest_packet_offset) {
   FXL_DCHECK(bytes != nullptr);
   FXL_DCHECK(*bytes != nullptr);
@@ -328,7 +323,7 @@
         return;
       }
 
-      async::PostTask(async_,[this, version = version_]() {
+      async::PostTask(async_, [this, version = version_]() {
         OnVersionReceived(version);
         if (socket_fd_.is_valid() && channel_) {
           // We've postponed setting the channel on the relay until now, because
@@ -359,7 +354,7 @@
         return;
       }
 
-      async::PostTask(async_,[this, service_name = ParsePayloadString()]() {
+      async::PostTask(async_, [this, service_name = ParsePayloadString()]() {
         OnServiceNameReceived(service_name);
       });
       break;
@@ -372,7 +367,8 @@
         return;
       }
 
-      async::PostTask(async_,
+      async::PostTask(
+          async_,
           [this, payload = std::move(receive_packet_payload_)]() mutable {
             OnMessageReceived(std::move(payload));
           });
@@ -400,7 +396,7 @@
 void MessageTransceiver::CancelWaiters() {
   if (!send_tasks_.empty()) {
     fd_send_waiter_.Cancel();
-    std::queue<std::function<void()>> doomed;
+    std::queue<fit::closure> doomed;
     send_tasks_.swap(doomed);
   }
 
diff --git a/bin/netconnector/message_transceiver.h b/bin/netconnector/message_transceiver.h
index f49d335..aab3dc3 100644
--- a/bin/netconnector/message_transceiver.h
+++ b/bin/netconnector/message_transceiver.h
@@ -2,12 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_MESSAGE_TRANSCEIVER_H_
+#define GARNET_BIN_NETCONNECTOR_MESSAGE_TRANSCEIVER_H_
 
 #include <queue>
 #include <vector>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
 #include "lib/fsl/tasks/fd_waiter.h"
@@ -120,7 +122,7 @@
 
   // Queues up a task that calls |SendPacket| to be run when the socket is
   // ready.
-  void PostSendTask(std::function<void()> task);
+  void PostSendTask(fit::closure task);
 
   // Waits (using |fd_send_waiter_|) for the socket to be ready to send if there
   // are send tasks pending.
@@ -157,11 +159,8 @@
   // at least |dest_packet_offset| and less than the sum of |dest_packet_offset|
   // and |dest_size|. |receive_packet_offset_| is also increased to reflect the
   // number of bytes actually copied.
-  bool CopyReceivedBytes(uint8_t** bytes,
-                         size_t* byte_count,
-                         uint8_t* dest,
-                         size_t dest_size,
-                         size_t dest_packet_offset);
+  bool CopyReceivedBytes(uint8_t** bytes, size_t* byte_count, uint8_t* dest,
+                         size_t dest_size, size_t dest_packet_offset);
 
   // Parses a uint32 out of receive_buffer_.
   uint32_t ParsePayloadUint32();
@@ -187,9 +186,11 @@
   // empty. The only exception to this is in the code that actually does the
   // sending (the waiter callback, |SendPacket| and the send tasks).
   fsl::FDWaiter fd_send_waiter_;
-  std::queue<std::function<void()>> send_tasks_;
+  std::queue<fit::closure> send_tasks_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(MessageTransceiver);
 };
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_MESSAGE_TRANSCEIVER_H_
diff --git a/bin/netconnector/netconnector_impl.cc b/bin/netconnector/netconnector_impl.cc
index 1d1f437..f1e0743 100644
--- a/bin/netconnector/netconnector_impl.cc
+++ b/bin/netconnector/netconnector_impl.cc
@@ -8,6 +8,7 @@
 
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
+#include <lib/fit/function.h>
 #include <zx/time.h>
 
 #include "garnet/bin/netconnector/device_service_provider.h"
@@ -26,9 +27,9 @@
 const std::string NetConnectorImpl::kLocalDeviceName = "local";
 
 NetConnectorImpl::NetConnectorImpl(NetConnectorParams* params,
-                                   fxl::Closure quit_callback)
+                                   fit::closure quit_callback)
     : params_(params),
-      quit_callback_(quit_callback),
+      quit_callback_(std::move(quit_callback)),
       startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
       // TODO(dalesat): Create a new RespondingServiceHost per user.
       // Requestors should provide user credentials allowing a ServiceAgent
diff --git a/bin/netconnector/netconnector_impl.h b/bin/netconnector/netconnector_impl.h
index 4027c9d..b3d285c 100644
--- a/bin/netconnector/netconnector_impl.h
+++ b/bin/netconnector/netconnector_impl.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include <fuchsia/sys/cpp/fidl.h>
+#include <lib/fit/function.h>
 #include <mdns/cpp/fidl.h>
 #include <netconnector/cpp/fidl.h>
 
@@ -24,7 +25,6 @@
 #include "garnet/bin/netconnector/service_agent.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/mdns/cpp/service_subscriber.h"
 
@@ -32,7 +32,7 @@
 
 class NetConnectorImpl : public NetConnector {
  public:
-  NetConnectorImpl(NetConnectorParams* params, fxl::Closure quit_callback);
+  NetConnectorImpl(NetConnectorParams* params, fit::closure quit_callback);
 
   ~NetConnectorImpl() override;
 
@@ -56,9 +56,10 @@
   void ReleaseServiceAgent(ServiceAgent* service_agent);
 
   // NetConnector implementation.
-  void RegisterServiceProvider(fidl::StringPtr name,
-                               fidl::InterfaceHandle<fuchsia::sys::ServiceProvider>
-                                   service_provider) override;
+  void RegisterServiceProvider(
+      fidl::StringPtr name,
+      fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> service_provider)
+      override;
 
   void GetDeviceServiceProvider(
       fidl::StringPtr device_name,
@@ -81,7 +82,7 @@
   void AddServiceAgent(std::unique_ptr<ServiceAgent> service_agent);
 
   NetConnectorParams* params_;
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
   std::string host_name_;
   fidl::BindingSet<NetConnector> bindings_;
diff --git a/bin/netconnector/netconnector_params.cc b/bin/netconnector/netconnector_params.cc
index 4219b9b..d7822e1 100644
--- a/bin/netconnector/netconnector_params.cc
+++ b/bin/netconnector/netconnector_params.cc
@@ -4,10 +4,10 @@
 
 #include "garnet/bin/netconnector/netconnector_params.h"
 
+#include <fuchsia/sys/cpp/fidl.h>
 #include <rapidjson/document.h>
 
 #include "garnet/bin/netconnector/ip_address.h"
-#include <fuchsia/sys/cpp/fidl.h>
 #include "lib/fxl/files/file.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/strings/split_string.h"
@@ -17,8 +17,7 @@
 
 constexpr char kConfigServices[] = "services";
 constexpr char kConfigDevices[] = "devices";
-constexpr char kDefaultConfigFileName[] =
-    "/pkg/data/netconnector.config";
+constexpr char kDefaultConfigFileName[] = "/pkg/data/netconnector.config";
 }  // namespace
 
 NetConnectorParams::NetConnectorParams(const fxl::CommandLine& command_line) {
diff --git a/bin/netconnector/netconnector_params.h b/bin/netconnector/netconnector_params.h
index a4f986c..80ddba1 100644
--- a/bin/netconnector/netconnector_params.h
+++ b/bin/netconnector/netconnector_params.h
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_NETCONNECTOR_PARAMS_H_
+#define GARNET_BIN_NETCONNECTOR_NETCONNECTOR_PARAMS_H_
 
 #include <string>
 #include <unordered_map>
 
-#include "garnet/bin/netconnector/ip_address.h"
 #include <fuchsia/sys/cpp/fidl.h>
+
+#include "garnet/bin/netconnector/ip_address.h"
 #include "lib/fxl/command_line.h"
 #include "lib/fxl/macros.h"
 
@@ -25,8 +27,7 @@
   bool show_devices() const { return show_devices_; }
   bool mdns_verbose() const { return mdns_verbose_; }
 
-  std::unordered_map<std::string, fuchsia::sys::LaunchInfoPtr>
-  MoveServices() {
+  std::unordered_map<std::string, fuchsia::sys::LaunchInfoPtr> MoveServices() {
     return std::move(launch_infos_by_service_name_);
   }
 
@@ -60,3 +61,5 @@
 };
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_NETCONNECTOR_PARAMS_H_
diff --git a/bin/netconnector/requestor_agent.cc b/bin/netconnector/requestor_agent.cc
index 88fd14d..7b5d0e4 100644
--- a/bin/netconnector/requestor_agent.cc
+++ b/bin/netconnector/requestor_agent.cc
@@ -15,10 +15,8 @@
 
 // static
 std::unique_ptr<RequestorAgent> RequestorAgent::Create(
-    const SocketAddress& address,
-    const std::string& service_name,
-    zx::channel local_channel,
-    NetConnectorImpl* owner) {
+    const SocketAddress& address, const std::string& service_name,
+    zx::channel local_channel, NetConnectorImpl* owner) {
   FXL_DCHECK(address.is_valid());
   FXL_DCHECK(!service_name.empty());
   FXL_DCHECK(local_channel);
diff --git a/bin/netconnector/requestor_agent.h b/bin/netconnector/requestor_agent.h
index 984cff7..977fdfa 100644
--- a/bin/netconnector/requestor_agent.h
+++ b/bin/netconnector/requestor_agent.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_REQUESTOR_AGENT_H_
+#define GARNET_BIN_NETCONNECTOR_REQUESTOR_AGENT_H_
 
 #include <arpa/inet.h>
 
@@ -34,10 +35,8 @@
   void OnConnectionClosed() override;
 
  private:
-  RequestorAgent(fxl::UniqueFD socket_fd,
-                 const std::string& service_name,
-                 zx::channel local_channel,
-                 NetConnectorImpl* owner);
+  RequestorAgent(fxl::UniqueFD socket_fd, const std::string& service_name,
+                 zx::channel local_channel, NetConnectorImpl* owner);
 
   std::string service_name_;
   zx::channel local_channel_;
@@ -47,3 +46,5 @@
 };
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_REQUESTOR_AGENT_H_
diff --git a/bin/netconnector/responding_service_host.h b/bin/netconnector/responding_service_host.h
index 213633a..4051332 100644
--- a/bin/netconnector/responding_service_host.h
+++ b/bin/netconnector/responding_service_host.h
@@ -8,6 +8,7 @@
 #include <unordered_map>
 
 #include <fuchsia/sys/cpp/fidl.h>
+
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/macros.h"
 #include "lib/svc/cpp/service_namespace.h"
diff --git a/bin/netconnector/service_agent.h b/bin/netconnector/service_agent.h
index f888f77..d6d465e 100644
--- a/bin/netconnector/service_agent.h
+++ b/bin/netconnector/service_agent.h
@@ -2,13 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_SERVICE_AGENT_H_
+#define GARNET_BIN_NETCONNECTOR_SERVICE_AGENT_H_
 
 #include <memory>
 
+#include <netconnector/cpp/fidl.h>
+
 #include "garnet/bin/netconnector/message_transceiver.h"
 #include "lib/fxl/files/unique_fd.h"
-#include <netconnector/cpp/fidl.h>
 
 namespace netconnector {
 
@@ -38,3 +40,5 @@
 };
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_SERVICE_AGENT_H_
diff --git a/bin/netconnector/socket_address.cc b/bin/netconnector/socket_address.cc
index 3066f70..a880025 100644
--- a/bin/netconnector/socket_address.cc
+++ b/bin/netconnector/socket_address.cc
@@ -7,22 +7,16 @@
 #include <sstream>
 
 #include <endian.h>
-
-#include <netstack/cpp/fidl.h>
+#include <fuchsia/netstack/cpp/fidl.h>
 
 namespace netconnector {
 
 // static
 const SocketAddress SocketAddress::kInvalid;
 
-SocketAddress::SocketAddress() {
-  std::memset(&v6_, 0, sizeof(v6_));
-}
+SocketAddress::SocketAddress() { std::memset(&v6_, 0, sizeof(v6_)); }
 
-SocketAddress::SocketAddress(uint8_t b0,
-                             uint8_t b1,
-                             uint8_t b2,
-                             uint8_t b3,
+SocketAddress::SocketAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3,
                              IpPort port) {
   std::memset(&v4_, 0, sizeof(v4_));
   v4_.sin_family = AF_INET;
@@ -46,14 +40,8 @@
   v4_ = addr;
 }
 
-SocketAddress::SocketAddress(uint16_t w0,
-                             uint16_t w1,
-                             uint16_t w2,
-                             uint16_t w3,
-                             uint16_t w4,
-                             uint16_t w5,
-                             uint16_t w6,
-                             uint16_t w7,
+SocketAddress::SocketAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3,
+                             uint16_t w4, uint16_t w5, uint16_t w6, uint16_t w7,
                              IpPort port) {
   std::memset(&v6_, 0, sizeof(v6_));
   v6_.sin6_family = AF_INET6;
@@ -118,9 +106,8 @@
   }
 }
 
-SocketAddress::SocketAddress(const netstack::SocketAddress* addr)
-    : SocketAddress(IpAddress(&addr->addr),
-                    IpPort::From_uint16_t(addr->port)) {
+SocketAddress::SocketAddress(const fuchsia::netstack::SocketAddress* addr)
+    : SocketAddress(IpAddress(&addr->addr), IpPort::From_uint16_t(addr->port)) {
   FXL_DCHECK(addr != nullptr);
 }
 
diff --git a/bin/netconnector/socket_address.h b/bin/netconnector/socket_address.h
index 4813e00..e104c65 100644
--- a/bin/netconnector/socket_address.h
+++ b/bin/netconnector/socket_address.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_BIN_NETCONNECTOR_SOCKET_ADDRESS_H_
+#define GARNET_BIN_NETCONNECTOR_SOCKET_ADDRESS_H_
 
 #include <ostream>
 
@@ -13,9 +14,11 @@
 #include "garnet/bin/netconnector/ip_port.h"
 #include "lib/fxl/logging.h"
 
+namespace fuchsia {
 namespace netstack {
 class SocketAddress;
 }
+}  // namespace fuchsia
 
 namespace netconnector {
 
@@ -37,15 +40,8 @@
   explicit SocketAddress(const sockaddr_in& addr);
 
   // Creates an IPV6 socket address from eight address words and an IpPort.
-  SocketAddress(uint16_t w0,
-                uint16_t w1,
-                uint16_t w2,
-                uint16_t w3,
-                uint16_t w4,
-                uint16_t w5,
-                uint16_t w6,
-                uint16_t w7,
-                IpPort port);
+  SocketAddress(uint16_t w0, uint16_t w1, uint16_t w2, uint16_t w3, uint16_t w4,
+                uint16_t w5, uint16_t w6, uint16_t w7, IpPort port);
 
   // Creates an IPV6 socket address from two address words and an IpPort.
   SocketAddress(uint16_t w0, uint16_t w7, IpPort port);
@@ -63,7 +59,7 @@
   explicit SocketAddress(const sockaddr_storage& addr);
 
   // Creates a socket address from a SocketAddress struct.
-  explicit SocketAddress(const netstack::SocketAddress* addr);
+  explicit SocketAddress(const fuchsia::netstack::SocketAddress* addr);
 
   bool is_valid() const { return family() != AF_UNSPEC; }
 
@@ -118,3 +114,5 @@
 std::ostream& operator<<(std::ostream& os, const SocketAddress& value);
 
 }  // namespace netconnector
+
+#endif  // GARNET_BIN_NETCONNECTOR_SOCKET_ADDRESS_H_
diff --git a/bin/network/net_adapters.cc b/bin/network/net_adapters.cc
deleted file mode 100644
index cb3379d..0000000
--- a/bin/network/net_adapters.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "garnet/bin/network/net_adapters.h"
-#include "garnet/bin/network/net_errors.h"
-
-namespace network {
-
-NetworkErrorPtr MakeNetworkError(int error_code) {
-  NetworkErrorPtr error = NetworkError::New();
-  error->code = error_code;
-  if (error_code <= 0)
-    error->description = network::ErrorToString(error_code);
-  return error;
-}
-
-}  // namespace network
diff --git a/bin/network/net_adapters.h b/bin/network/net_adapters.h
deleted file mode 100644
index 28cae48..0000000
--- a/bin/network/net_adapters.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GARNET_BIN_NETWORK_NET_ADAPTERS_H_
-#define GARNET_BIN_NETWORK_NET_ADAPTERS_H_
-
-#include <network/cpp/fidl.h>
-
-namespace network {
-
-// Creates a new network error object from a net error code.
-NetworkErrorPtr MakeNetworkError(int error_code);
-
-}  // namespace network
-
-#endif  // GARNET_BIN_NETWORK_NET_ADAPTERS_H_
diff --git a/bin/network/net_errors.h b/bin/network/net_errors.h
deleted file mode 100644
index 5c26a80..0000000
--- a/bin/network/net_errors.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GARNET_BIN_NETWORK_NET_ERRORS_H_
-#define GARNET_BIN_NETWORK_NET_ERRORS_H_
-
-#include <string>
-
-namespace network {
-
-enum Error {
-  // No error.
-  OK = 0,
-
-#define NET_ERROR(label, value) NETWORK_ERR_##label = value,
-#include "garnet/bin/network/net_error_list.h"
-#undef NET_ERROR
-};
-
-// Returns a textual representation of the error code for logging purposes.
-std::string ErrorToString(int error);
-
-// Same as above, but leaves off the leading "network::".
-std::string ErrorToShortString(int error);
-
-}  // namespace network
-
-#endif  // GARNET_BIN_NETWORK_NET_ERRORS_H_
diff --git a/bin/network/network_service_delegate.cc b/bin/network/network_service_delegate.cc
deleted file mode 100644
index d9d8df0..0000000
--- a/bin/network/network_service_delegate.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "garnet/bin/network/network_service_delegate.h"
-
-namespace network {
-
-NetworkServiceDelegate::NetworkServiceDelegate(async_t* dispatcher)
-    : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
-      network_provider_(dispatcher) {
-  FXL_DCHECK(dispatcher),
-      context_->outgoing().AddPublicService<NetworkService>(
-          [this](fidl::InterfaceRequest<NetworkService> request) {
-            network_provider_.AddBinding(std::move(request));
-          });
-}
-
-NetworkServiceDelegate::~NetworkServiceDelegate() {}
-
-}  // namespace network
diff --git a/bin/network/network_service_delegate.h b/bin/network/network_service_delegate.h
deleted file mode 100644
index c7e008c..0000000
--- a/bin/network/network_service_delegate.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GARNET_BIN_NETWORK_NETWORK_SERVICE_DELEGATE_H_
-#define GARNET_BIN_NETWORK_NETWORK_SERVICE_DELEGATE_H_
-
-#include <memory>
-
-#include "garnet/bin/network/network_service_impl.h"
-#include "lib/app/cpp/startup_context.h"
-
-namespace network {
-
-class NetworkServiceDelegate {
- public:
-  NetworkServiceDelegate(async_t* dispatcher);
-  ~NetworkServiceDelegate();
-
- private:
-  std::unique_ptr<fuchsia::sys::StartupContext> context_;
-  network::NetworkServiceImpl network_provider_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(NetworkServiceDelegate);
-};
-
-}  // namespace network
-
-#endif  // GARNET_BIN_NETWORK_NETWORK_SERVICE_DELEGATE_H_
diff --git a/bin/network/network_service_impl.h b/bin/network/network_service_impl.h
deleted file mode 100644
index 2f717f0..0000000
--- a/bin/network/network_service_impl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GARNET_BIN_NETWORK_NETWORK_SERVICE_IMPL_H_
-#define GARNET_BIN_NETWORK_NETWORK_SERVICE_IMPL_H_
-
-#include <list>
-#include <queue>
-
-#include <network/cpp/fidl.h>
-#include <lib/async/dispatcher.h>
-#include <lib/zx/channel.h>
-
-#include "garnet/bin/network/url_loader_impl.h"
-#include "lib/fidl/cpp/binding_set.h"
-#include "lib/fidl/cpp/interface_request.h"
-#include "lib/fxl/functional/closure.h"
-
-namespace network {
-
-class NetworkServiceImpl : public NetworkService,
-                           public URLLoaderImpl::Coordinator {
- public:
-  NetworkServiceImpl(async_t* dispatcher);
-  ~NetworkServiceImpl() override;
-
-  void AddBinding(fidl::InterfaceRequest<NetworkService> request);
-
-  // NetworkService methods:
-  void CreateURLLoader(fidl::InterfaceRequest<URLLoader> request) override;
-  void GetCookieStore(zx::channel cookie_store) override;
-  void CreateWebSocket(zx::channel socket) override;
-
- private:
-  class UrlLoaderContainer;
-
-  // URLLoaderImpl::Coordinator:
-  void RequestNetworkSlot(
-      std::function<void(fxl::Closure)> slot_request) override;
-
-  void OnSlotReturned();
-
-  async_t* const dispatcher_;
-  size_t available_slots_;
-  fidl::BindingSet<NetworkService> bindings_;
-  std::list<UrlLoaderContainer> loaders_;
-  std::queue<std::function<void(fxl::Closure)>> slot_requests_;
-};
-
-}  // namespace network
-
-#endif  // GARNET_BIN_NETWORK_NETWORK_SERVICE_IMPL_H_
diff --git a/bin/network/url_loader_impl.h b/bin/network/url_loader_impl.h
deleted file mode 100644
index 3ce78e3..0000000
--- a/bin/network/url_loader_impl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GARNET_BIN_NETWORK_URL_LOADER_IMPL_H_
-#define GARNET_BIN_NETWORK_URL_LOADER_IMPL_H_
-
-#include <network/cpp/fidl.h>
-
-#include "lib/fxl/functional/closure.h"
-#include "lib/fidl/cpp/binding.h"
-#include "lib/url/gurl.h"
-
-namespace network {
-
-class URLLoaderImpl : public URLLoader {
- public:
-  // Coordinates requests to limit the number of concurrent active requests.
-  class Coordinator {
-   public:
-    virtual ~Coordinator() {}
-    virtual void RequestNetworkSlot(
-        std::function<void(fxl::Closure)> slot_request) = 0;
-  };
-
-  URLLoaderImpl(Coordinator* coordinator);
-  ~URLLoaderImpl() override;
-
- private:
-  template <typename T>
-  class HTTPClient;
-
-  using Callback = std::function<void(network::URLResponse)>;
-
-  // URLLoader methods:
-  void Start(URLRequest request, Callback callback) override;
-  void FollowRedirect(Callback callback) override;
-  void QueryStatus(QueryStatusCallback callback) override;
-
-  void SendError(int error_code);
-  void FollowRedirectInternal();
-  void SendResponse(URLResponse response);
-  void StartInternal(URLRequest request);
-
-  Coordinator* coordinator_;
-  Callback callback_;
-  ResponseBodyMode response_body_mode_;
-  // bool auto_follow_redirects_;
-  url::GURL current_url_;
-  URLLoaderStatus last_status_;
-};
-
-}  // namespace network
-
-#endif  // GARNET_BIN_NETWORK_URL_LOADER_IMPL_H_
diff --git a/bin/network_loader/BUILD.gn b/bin/network_loader/BUILD.gn
index 887c90d..74e6e5a 100644
--- a/bin/network_loader/BUILD.gn
+++ b/bin/network_loader/BUILD.gn
@@ -16,7 +16,7 @@
     "//garnet/public/lib/app/fidl",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
-    "//garnet/public/lib/network/fidl",
+    "//garnet/public/lib/net/oldhttp/fidl",
   ]
 }
 
diff --git a/bin/network_loader/main.cc b/bin/network_loader/main.cc
index 450c400..46a7a59 100644
--- a/bin/network_loader/main.cc
+++ b/bin/network_loader/main.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include <fuchsia/sys/cpp/fidl.h>
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 
 #include <unordered_map>
 
@@ -15,16 +15,17 @@
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
 #include "lib/fidl/cpp/optional.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/functional/make_copyable.h"
 #include "lib/fxl/memory/weak_ptr.h"
 #include "lib/fxl/time/time_delta.h"
 
 namespace {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 class RetryingLoader {
  public:
-  RetryingLoader(network::URLLoaderPtr url_loader, const std::string& url,
+  RetryingLoader(http::URLLoaderPtr url_loader, const std::string& url,
                  const fuchsia::sys::Loader::LoadComponentCallback& callback)
       : url_loader_(std::move(url_loader)),
         url_(url),
@@ -38,28 +39,28 @@
   void Attempt() {
     url_loader_->Start(NewRequest(),
                        [weak_this = weak_ptr_factory_.GetWeakPtr()](
-                           const network::URLResponse& response) {
+                           const http::URLResponse& response) {
                          if (weak_this) {
                            weak_this->ProcessResponse(response);
                          }
                        });
   }
 
-  void SetDeleter(const fxl::Closure& fn) { deleter_ = fn; }
+  void SetDeleter(fit::closure fn) { deleter_ = std::move(fn); }
 
  private:
   // Need to create a new request each time because a URLRequest's body can
   // potentially contain a VMO handle and so can't be cloned.
-  network::URLRequest NewRequest() const {
-    network::URLRequest request;
+  http::URLRequest NewRequest() const {
+    http::URLRequest request;
     request.method = "GET";
     request.url = url_;
     request.auto_follow_redirects = true;
-    request.response_body_mode = network::ResponseBodyMode::SIZED_BUFFER;
+    request.response_body_mode = http::ResponseBodyMode::SIZED_BUFFER;
     return request;
   }
 
-  void ProcessResponse(const network::URLResponse& response) {
+  void ProcessResponse(const http::URLResponse& response) {
     if (response.status_code == 200) {
       auto package = fuchsia::sys::Package::New();
       package->data =
@@ -76,7 +77,7 @@
     }
   }
 
-  void Retry(const network::URLResponse& response) {
+  void Retry(const http::URLResponse& response) {
     async::PostDelayedTask(async_get_default(),
                            [weak_this = weak_ptr_factory_.GetWeakPtr()] {
                              if (weak_this) {
@@ -110,10 +111,10 @@
     deleter_();
   }
 
-  const network::URLLoaderPtr url_loader_;
+  const http::URLLoaderPtr url_loader_;
   const std::string url_;
   const fuchsia::sys::Loader::LoadComponentCallback callback_;
-  fxl::Closure deleter_;
+  fit::closure deleter_;
   // Tries before an error is printed. No errors will be printed afterwards
   // either.
   int quiet_tries_;
@@ -131,13 +132,13 @@
           bindings_.AddBinding(this, std::move(request));
         });
 
-    context_->ConnectToEnvironmentService(net_.NewRequest());
+    context_->ConnectToEnvironmentService(http_.NewRequest());
   }
 
   void LoadComponent(fidl::StringPtr url,
                      LoadComponentCallback callback) override {
-    network::URLLoaderPtr loader;
-    net_->CreateURLLoader(loader.NewRequest());
+    http::URLLoaderPtr loader;
+    http_->CreateURLLoader(loader.NewRequest());
 
     auto retrying_loader =
         std::make_unique<RetryingLoader>(std::move(loader), url, callback);
@@ -151,7 +152,7 @@
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
   fidl::BindingSet<fuchsia::sys::Loader> bindings_;
 
-  network::NetworkServicePtr net_;
+  http::HttpServicePtr http_;
   std::unordered_map<RetryingLoader*, std::unique_ptr<RetryingLoader>> loaders_;
 };
 
diff --git a/bin/network_time/roughtime_server.cc b/bin/network_time/roughtime_server.cc
index 5d62bdf..be24b80 100644
--- a/bin/network_time/roughtime_server.cc
+++ b/bin/network_time/roughtime_server.cc
@@ -12,7 +12,6 @@
 #include <zircon/syscalls.h>
 #include <zircon/types.h>
 
-#include <functional>
 #include <string>
 
 #include <client.h>
diff --git a/bin/power_manager/src/main.rs b/bin/power_manager/src/main.rs
index f2f5c02..5bc2c2e 100644
--- a/bin/power_manager/src/main.rs
+++ b/bin/power_manager/src/main.rs
@@ -35,8 +35,8 @@
 use std::path::PathBuf;
 use std::sync::Arc;
 
-extern crate fidl_power_manager;
-use fidl_power_manager::{BatteryStatus, PowerManager, PowerManagerImpl, PowerManagerMarker,
+extern crate fidl_fuchsia_power;
+use fidl_fuchsia_power::{BatteryStatus, PowerManager, PowerManagerImpl, PowerManagerMarker,
                          PowerManagerWatcherProxy, Status as power_status};
 
 static POWER_DEVICE: &str = "/dev/class/power";
diff --git a/bin/recovery_netstack/BUILD.gn b/bin/recovery_netstack/BUILD.gn
index f0cfc98..ab5a2e4 100644
--- a/bin/recovery_netstack/BUILD.gn
+++ b/bin/recovery_netstack/BUILD.gn
@@ -10,6 +10,7 @@
   with_unit_tests = true
 
   deps = [
+    "//garnet/public/rust/crates/zerocopy",
     "//third_party/rust-crates/rustc_deps:byteorder"
   ]
 }
diff --git a/bin/recovery_netstack/src/device/ethernet.rs b/bin/recovery_netstack/src/device/ethernet.rs
new file mode 100644
index 0000000..fdc805e
--- /dev/null
+++ b/bin/recovery_netstack/src/device/ethernet.rs
@@ -0,0 +1,62 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! The Ethernet protocol.
+
+/// The broadcast MAC address.
+///
+/// The broadcast MAC address, FF:FF:FF:FF:FF:FF, indicates that a frame should
+/// be received by all receivers regardless of their local MAC address.
+pub const BROADCAST_MAC: Mac = Mac([0xFF; 6]);
+
+/// A media access control (MAC) address.
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub struct Mac([u8; 6]);
+
+impl Mac {
+    /// Construct a new MAC address.
+    pub const fn new(bytes: [u8; 6]) -> Mac {
+        Mac(bytes)
+    }
+
+    /// Get the bytes of the MAC address.
+    pub fn bytes(&self) -> [u8; 6] {
+        self.0
+    }
+
+    /// Is this a unicast MAC address?
+    ///
+    /// Returns true if the least significant bit of the first byte of the
+    /// address is 0.
+    pub fn is_unicast(&self) -> bool {
+        // https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
+        self.0[0] & 1 == 0
+    }
+
+    /// Is this a multicast MAC address?
+    ///
+    /// Returns true if the least significant bit of the first byte of the
+    /// address is 1.
+    pub fn is_multicast(&self) -> bool {
+        // https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
+        self.0[0] & 1 == 1
+    }
+
+    /// Is this the broadcast MAC address?
+    ///
+    /// Returns true if this is the broadcast MAC address, FF:FF:FF:FF:FF:FF.
+    pub fn is_broadcast(&self) -> bool {
+        // https://en.wikipedia.org/wiki/MAC_address#Unicast_vs._multicast
+        *self == BROADCAST_MAC
+    }
+}
+
+/// An EtherType number.
+#[allow(missing_docs)]
+#[repr(u16)]
+pub enum EtherType {
+    Ipv4 = 0x0800,
+    Arp = 0x0806,
+    Ipv6 = 0x86DD,
+}
diff --git a/bin/recovery_netstack/src/device/mod.rs b/bin/recovery_netstack/src/device/mod.rs
new file mode 100644
index 0000000..b00d58b
--- /dev/null
+++ b/bin/recovery_netstack/src/device/mod.rs
@@ -0,0 +1,7 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! The device layer.
+
+pub mod ethernet;
diff --git a/bin/recovery_netstack/src/ip/address.rs b/bin/recovery_netstack/src/ip/address.rs
index 9890355..ec6b0a9 100644
--- a/bin/recovery_netstack/src/ip/address.rs
+++ b/bin/recovery_netstack/src/ip/address.rs
@@ -7,6 +7,7 @@
 use byteorder::{BigEndian, ByteOrder};
 
 /// An IP protocol version.
+#[allow(missing_docs)]
 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
 pub enum IpVersion {
     V4,
@@ -14,18 +15,36 @@
 }
 
 impl IpVersion {
+    /// The number for this IP protocol version.
+    ///
+    /// 4 for `V4` and 6 for `V6`.
     pub fn version_number(&self) -> u8 {
         match self {
             IpVersion::V4 => 4,
             IpVersion::V6 => 6,
         }
     }
+
+    /// Is this IPv4?
+    pub fn is_v4(&self) -> bool {
+        *self == IpVersion::V4
+    }
+
+    /// Is this IPv6?
+    pub fn is_v6(&self) -> bool {
+        *self == IpVersion::V6
+    }
 }
 
 mod sealed {
     // Ensure that only Ipv4 and Ipv6 can implement IpVersion and that only
     // Ipv4Addr and Ipv6Addr can implement IpAddr.
     pub trait Sealed {}
+
+    impl Sealed for super::Ipv4 {}
+    impl Sealed for super::Ipv6 {}
+    impl Sealed for super::Ipv4Addr {}
+    impl Sealed for super::Ipv6Addr {}
 }
 
 /// An trait for IP protocol versions.
@@ -74,8 +93,6 @@
     type Addr = Ipv4Addr;
 }
 
-impl self::sealed::Sealed for Ipv4 {}
-
 /// IPv6.
 ///
 /// `Ipv6` implements `Ip` for IPv6.
@@ -84,7 +101,8 @@
 
 impl Ip for Ipv6 {
     const VERSION: IpVersion = IpVersion::V6;
-    const LOOPBACK_ADDRESS: Ipv6Addr = Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+    const LOOPBACK_ADDRESS: Ipv6Addr =
+        Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
     const LOOPBACK_SUBNET: Subnet<Ipv6Addr> = Subnet {
         network: Ipv6Addr::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]),
         prefix: 128,
@@ -92,8 +110,6 @@
     type Addr = Ipv6Addr;
 }
 
-impl self::sealed::Sealed for Ipv6 {}
-
 /// An IPv4 or IPv6 address.
 pub trait IpAddr
 where
@@ -128,6 +144,7 @@
         Ipv4Addr(bytes)
     }
 
+    /// Get the bytes of the IPv4 address.
     pub const fn ipv4_bytes(&self) -> [u8; 4] {
         self.0
     }
@@ -157,8 +174,6 @@
     }
 }
 
-impl self::sealed::Sealed for Ipv4Addr {}
-
 impl Display for Ipv4Addr {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
         write!(f, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3])
@@ -181,6 +196,7 @@
         Ipv6Addr(bytes)
     }
 
+    /// Get the bytes of the IPv6 address.
     pub const fn ipv6_bytes(&self) -> [u8; 16] {
         self.0
     }
@@ -210,8 +226,6 @@
     }
 }
 
-impl self::sealed::Sealed for Ipv6Addr {}
-
 impl Display for Ipv6Addr {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
         // TODO(joshlf): Replace longest run of zeros with ::.
@@ -295,4 +309,4 @@
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
         write!(f, "{}/{}", self.network, self.prefix)
     }
-}
\ No newline at end of file
+}
diff --git a/bin/recovery_netstack/src/ip/mod.rs b/bin/recovery_netstack/src/ip/mod.rs
index 56b6c33..789b943 100644
--- a/bin/recovery_netstack/src/ip/mod.rs
+++ b/bin/recovery_netstack/src/ip/mod.rs
@@ -2,6 +2,19 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+//! The Internet Protocol, versions 4 and 6.
+
 mod address;
 
 pub use self::address::*;
+
+/// An IP protocol or next header number.
+///
+/// For IPv4, this is the protocol number. For IPv6, this is the next header
+/// number.
+#[allow(missing_docs)]
+#[repr(u8)]
+pub enum IpProto {
+    Tcp = 6,
+    Udp = 17,
+}
diff --git a/bin/recovery_netstack/src/main.rs b/bin/recovery_netstack/src/main.rs
index fda6fa3..0767e7f 100644
--- a/bin/recovery_netstack/src/main.rs
+++ b/bin/recovery_netstack/src/main.rs
@@ -5,11 +5,23 @@
 //! A networking stack.
 
 #![feature(const_fn)]
-
+#![feature(nonzero)]
+// In case we roll the toolchain and something we're using as a feature has been
+// stabilized.
+#![allow(stable_features)]
+// We use repr(packed) in some places (particularly in the wire module) to
+// create structs whose layout matches the layout of network packets on the
+// wire. This ensures that the compiler will stop us from using repr(packed) in
+// an unsound manner without using unsafe code.
+#![deny(safe_packed_borrows)]
 #![deny(missing_docs)]
 
 extern crate byteorder;
+extern crate zerocopy;
 
-mod ip;
+// mark all modules as public so that deny(missing_docs) will be more powerful
+pub mod device;
+pub mod ip;
+pub mod wire;
 
 fn main() {}
diff --git a/bin/recovery_netstack/src/wire/ethernet.rs b/bin/recovery_netstack/src/wire/ethernet.rs
new file mode 100644
index 0000000..edf6003
--- /dev/null
+++ b/bin/recovery_netstack/src/wire/ethernet.rs
@@ -0,0 +1,340 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use std::ops::RangeBounds;
+
+use byteorder::{BigEndian, ByteOrder};
+use zerocopy::{AsBytes, ByteSlice, FromBytes, LayoutVerified, Unaligned};
+
+use device::ethernet::{EtherType, Mac};
+use wire::util::extract_slice_range;
+use wire::{Err, ParseErr};
+
+// HeaderPrefix has the same memory layout (thanks to repr(C, packed)) as an
+// Ethernet header prefix. Thus, we can simply reinterpret the bytes of the
+// Ethernet header prefix as a HeaderPrefix and then safely access its fields.
+// Note the following caveats:
+// - We cannot make any guarantees about the alignment of an instance of this
+//   struct in memory or of any of its fields. This is true both because
+//   repr(packed) removes the padding that would be used to ensure the alignment
+//   of individual fields, but also because we are given no guarantees about
+//   where within a given memory buffer a particular packet (and thus its
+//   header) will be located.
+// - Individual fields are all either u8 or [u8; N] rather than u16, u32, etc.
+//   This is for two reasons:
+//   - u16 and larger have larger-than-1 alignments, which are forbidden as
+//     described above
+//   - We are not guaranteed that the local platform has the same endianness as
+//     network byte order (big endian), so simply treating a sequence of bytes
+//     as a u16 or other multi-byte number would not necessarily be correct.
+//     Instead, we use the BigEndian type and its reader and writer methods to
+//     correctly access these fields.
+#[repr(C, packed)]
+struct HeaderPrefix {
+    dst_mac: [u8; 6],
+    src_mac: [u8; 6],
+}
+
+unsafe impl FromBytes for HeaderPrefix {}
+unsafe impl AsBytes for HeaderPrefix {}
+unsafe impl Unaligned for HeaderPrefix {}
+
+const TPID_8021Q: u16 = 0x8100;
+const TPID_8021AD: u16 = 0x88a8;
+
+/// The maximum length of an Ethernet header in bytes.
+///
+/// When calling `EthernetFrame::create`, provide at least `MAX_HEADER_LEN`
+/// bytes for the header in order to guarantee that `create` will not panic.
+pub const MAX_HEADER_LEN: usize = 18;
+
+// NOTE(joshlf): MIN_BODY_LEN assumes no 802.1Q or 802.1ad tag. We don't support
+// creating new packets with these tags at the moment, so this is a reasonable
+// assumption. If we support tags in the future, this minimum will only go down,
+// so it is forwards-compatible.
+
+/// The minimum length of an Ethernet body in bytes.
+///
+/// When calling `EthernetFrame::create`, provide at least `MIN_BODY_LEN` bytes
+/// for the body in order to guarantee that `create` will not panic.
+pub const MIN_BODY_LEN: usize = 46;
+
+/// An Ethernet frame.
+///
+/// An `EthernetFrame` shares its underlying memory with the byte slice it was
+/// parsed from or serialized to, meaning that no copying or extra allocation is
+/// necessary.
+pub struct EthernetFrame<B> {
+    hdr_prefix: LayoutVerified<B, HeaderPrefix>,
+    tag: Option<LayoutVerified<B, [u8; 4]>>,
+    ethertype: LayoutVerified<B, [u8; 2]>,
+    body: B,
+}
+
+impl<B: ByteSlice> EthernetFrame<B> {
+    /// Parse an Ethernet frame.
+    ///
+    /// `parse` parses `bytes` as an Ethernet frame. It is assumed that the
+    /// Frame Check Sequence (FCS) footer has already been removed.
+    pub fn parse(bytes: B) -> Result<EthernetFrame<B>, impl ParseErr> {
+        // See for details: https://en.wikipedia.org/wiki/Ethernet_frame#Frame_%E2%80%93_data_link_layer
+
+        let (hdr_prefix, rest) =
+            LayoutVerified::<B, HeaderPrefix>::new_unaligned_from_prefix(bytes).ok_or(Err::Format)?;
+        if rest.len() < 48 {
+            // The minimum frame size (not including the Frame Check Sequence
+            // (FCS) footer, which we do not handle in this code) is 60 bytes.
+            // We've already consumed 12 bytes for the header prefix, so we must
+            // have at least 48 bytes left.
+            return Err(Err::Format);
+        }
+
+        // The tag (either IEEE 802.1Q or 802.1ad) is an optional four-byte
+        // field. If present, it precedes the ethertype, and its first two bytes
+        // (where the ethertype bytes are normally) are called the Tag Protocol
+        // Identifier (TPID). A TPID of TPID_8021Q implies an 802.1Q tag, a TPID
+        // of TPID_8021AD implies an 802.1ad tag, and anything else implies that
+        // there is no tag - it's a normal ethertype field.
+        let ethertype_or_tpid = BigEndian::read_u16(&rest);
+        let (tag, ethertype, body) = match ethertype_or_tpid {
+            self::TPID_8021Q | self::TPID_8021AD => {
+                let (tag, rest) =
+                    LayoutVerified::<B, [u8; 4]>::new_unaligned_from_prefix(rest).unwrap();
+                let (ethertype, body) =
+                    LayoutVerified::<B, [u8; 2]>::new_unaligned_from_prefix(rest).unwrap();
+                (Some(tag), ethertype, body)
+            }
+            _ => {
+                let (ethertype, body) =
+                    LayoutVerified::<B, [u8; 2]>::new_unaligned_from_prefix(rest).unwrap();
+                (None, ethertype, body)
+            }
+        };
+
+        let frame = EthernetFrame {
+            hdr_prefix,
+            tag,
+            ethertype,
+            body,
+        };
+
+        let et = frame.ethertype();
+        if (et > 1500 && et < 1536) || (et <= 1500 && et as usize != frame.body.len()) {
+            // EtherType values between 1500 and 1536 are disallowed, and values
+            // of 1500 and below are used to indicate the body size.
+            return Err(Err::Format);
+        }
+        Ok(frame)
+    }
+
+    /// The frame body.
+    pub fn body(&self) -> &[u8] {
+        &self.body
+    }
+
+    /// The source MAC address.
+    pub fn src_mac(&self) -> Mac {
+        Mac::new(self.hdr_prefix.src_mac)
+    }
+
+    /// The destination MAC address.
+    pub fn dst_mac(&self) -> Mac {
+        Mac::new(self.hdr_prefix.dst_mac)
+    }
+
+    /// The numerical EtherType code.
+    pub fn ethertype(&self) -> u16 {
+        BigEndian::read_u16(&self.ethertype[..])
+    }
+}
+
+impl<'a> EthernetFrame<&'a mut [u8]> {
+    /// Serialize an Ethernet frame in an existing buffer.
+    ///
+    /// `create` creates an `EthernetFrame` which uses the provided `buffer` for
+    /// its storage, initializing all header fields. It treats the range
+    /// identified by `body` as being the frame body. It uses the last bytes of
+    /// `buffer` before the body to store the header, and returns the number of
+    /// remaining prefix bytes to the caller for use in adding other headers.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut buffer = [0u8; 1024];
+    /// (&mut buffer[512..]).copy_from_slice(body);
+    /// let (frame, prefix_bytes) =
+    ///     EthernetFrame::create(&mut buffer, 512.., src_mac, dst_mac, ethertype);
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// `create` panics if there is insufficient room preceding the body to
+    /// store the Ethernet header, or if `body` is not in range of `buffer`. The
+    /// caller can guarantee that there will be enough room by providing at
+    /// least `MAX_HEADER_LEN` pre-body bytes.
+    ///
+    /// `create` also panics if the total frame length is less than the minimum
+    /// of 60 bytes. The caller can guarantee that the frame will be large
+    /// enough by providing a body of at least `MIN_BODY_LEN` bytes.
+    pub fn create<R: RangeBounds<usize>>(
+        buffer: &'a mut [u8], body: R, src_mac: Mac, dst_mac: Mac, ethertype: EtherType,
+    ) -> (EthernetFrame<&'a mut [u8]>, usize) {
+        // NOTE: EtherType values of 1500 and below are used to indicate the
+        // length of the body in bytes. We don't need to validate this because
+        // the EtherType enum has no variants with values in that range.
+
+        let (header, body, _) =
+            extract_slice_range(buffer, body).expect("body range is out of bounds of buffer");
+        let (mut frame, prefix_len) = {
+            let (ethertype, prefix) = LayoutVerified::<_, [u8; 2]>::new_unaligned_from_suffix(
+                header,
+            ).expect("too few bytes for Ethernet header");
+            let (hdr_prefix, prefix) = LayoutVerified::<_, HeaderPrefix>::new_unaligned_from_suffix(
+                prefix,
+            ).expect("too few bytes for Ethernet header");
+            (
+                EthernetFrame {
+                    hdr_prefix,
+                    tag: None,
+                    ethertype,
+                    body,
+                },
+                prefix.len(),
+            )
+        };
+
+        let total_len =
+            frame.hdr_prefix.bytes().len() + frame.ethertype.bytes().len() + frame.body.len();
+        if total_len < 60 {
+            panic!(
+                "total frame size of {} bytes is below minimum frame size of 60",
+                total_len
+            );
+        }
+
+        frame.hdr_prefix.src_mac = src_mac.bytes();
+        frame.hdr_prefix.dst_mac = dst_mac.bytes();
+        BigEndian::write_u16(&mut frame.ethertype[..], ethertype as u16);
+        (frame, prefix_len)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    // return a test buffer with values 0..60
+    fn new_buf() -> [u8; 60] {
+        let mut buf = [0u8; 60];
+        for i in 0..60 {
+            buf[i] = i as u8;
+        }
+        buf
+    }
+
+    #[test]
+    fn test_parse() {
+        let buf = new_buf();
+        let frame = EthernetFrame::parse(&buf[..]).unwrap();
+        assert_eq!(frame.hdr_prefix.dst_mac, [0, 1, 2, 3, 4, 5]);
+        assert_eq!(frame.hdr_prefix.src_mac, [6, 7, 8, 9, 10, 11]);
+        assert!(frame.tag.is_none());
+        // help out with type inference
+        let ethertype: &[u8; 2] = &frame.ethertype;
+        assert_eq!(ethertype, &[12, 13]);
+        assert_eq!(frame.body, &buf[14..]);
+
+        // For both of the TPIDs that imply the existence of a tag, make sure
+        // that the tag is present and correct (and that all of the normal
+        // checks succeed).
+        for tpid in [TPID_8021Q, TPID_8021AD].iter() {
+            let mut buf = new_buf();
+
+            const TPID_OFFSET: usize = 12;
+            BigEndian::write_u16(&mut buf[TPID_OFFSET..], *tpid);
+
+            let frame = EthernetFrame::parse(&buf[..]).unwrap();
+            assert_eq!(frame.hdr_prefix.dst_mac, [0, 1, 2, 3, 4, 5]);
+            assert_eq!(frame.hdr_prefix.src_mac, [6, 7, 8, 9, 10, 11]);
+
+            // help out with type inference
+            let tag: &[u8; 4] = &frame.tag.unwrap();
+            let got_tag = BigEndian::read_u32(tag);
+            let want_tag =
+                (*tpid as u32) << 16 | ((TPID_OFFSET as u32 + 2) << 8) | (TPID_OFFSET as u32 + 3);
+            assert_eq!(got_tag, want_tag);
+            // help out with type inference
+            let ethertype: &[u8; 2] = &frame.ethertype;
+            assert_eq!(ethertype, &[16, 17]);
+            assert_eq!(frame.body, &buf[18..]);
+        }
+    }
+
+    #[test]
+    fn test_ethertype_body_len() {
+        // ethertypes of 1500 and below must match the body length
+        let mut buf = [0u8; 1014];
+        // an incorrect length results in error
+        BigEndian::write_u16(&mut buf[12..], 1001);
+        assert!(EthernetFrame::parse(&buf[..]).is_err());
+        // a correct length results in success
+        BigEndian::write_u16(&mut buf[12..], 1000);
+        assert!(EthernetFrame::parse(&buf[..]).is_ok());
+    }
+
+    #[test]
+    fn test_create() {
+        let mut buf = new_buf();
+        {
+            let (_, prefix_len) = EthernetFrame::create(
+                &mut buf,
+                (MAX_HEADER_LEN - 4)..,
+                Mac::new([0, 1, 2, 3, 4, 5]),
+                Mac::new([6, 7, 8, 9, 10, 11]),
+                EtherType::Arp,
+            );
+            assert_eq!(prefix_len, 0);
+        }
+        assert_eq!(
+            &buf[..MAX_HEADER_LEN - 4],
+            [6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 0x08, 0x06]
+        );
+    }
+
+    #[test]
+    fn test_parse_error() {
+        // 1 byte shorter than the minimum
+        let buf = [0u8; 59];
+        assert!(EthernetFrame::parse(&buf[..]).is_err());
+
+        // an ethertype of 1500 should be validated as the length of the body
+        let mut buf = [0u8; 60];
+        BigEndian::write_u16(&mut buf[12..], 1500);
+        assert!(EthernetFrame::parse(&buf[..]).is_err());
+
+        // an ethertype of 1501 is illegal
+        let mut buf = [0u8; 60];
+        BigEndian::write_u16(&mut buf[12..], 1501);
+        assert!(EthernetFrame::parse(&buf[..]).is_err());
+
+        // an ethertype of 1535 is illegal
+        let mut buf = [0u8; 60];
+        BigEndian::write_u16(&mut buf[12..], 1535);
+        assert!(EthernetFrame::parse(&buf[..]).is_err());
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_create_panic() {
+        // create with a body which is below the minimum length
+        let mut buf = [0u8; 60];
+        EthernetFrame::create(
+            &mut buf,
+            (60 - (MIN_BODY_LEN - 1))..,
+            Mac::new([0, 1, 2, 3, 4, 5]),
+            Mac::new([6, 7, 8, 9, 10, 11]),
+            EtherType::Arp,
+        );
+    }
+}
diff --git a/bin/recovery_netstack/src/wire/mod.rs b/bin/recovery_netstack/src/wire/mod.rs
new file mode 100644
index 0000000..9a12e12
--- /dev/null
+++ b/bin/recovery_netstack/src/wire/mod.rs
@@ -0,0 +1,50 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! Serialization and deserialization of wire formats.
+//!
+//! This module provides efficient serialization and deserialization of the
+//! various wire formats used by this program. Where possible, it uses lifetimes
+//! and immutability to allow for safe zero-copy parsing.
+//!
+//! # Endianness
+//!
+//! All values exposed or consumed by this crate are in host byte order, so the
+//! caller does not need to worry about it. Any necessary conversions are
+//! performed under the hood.
+
+mod ethernet;
+mod udp;
+mod util;
+
+pub use self::ethernet::*;
+pub use self::udp::*;
+
+use std::fmt::Debug;
+
+// We use a trait rather than a concrete type (such as the enum Err below) so
+// that we are free to change what error type we use in the future. We may
+// eventually switch from returning 'impl ParseErr' to using a concrete type
+// once we get enough experience with this.
+
+/// Parsing errors.
+///
+/// All errors returned from parsing functions in this module implement
+/// `ParseErr`.
+pub trait ParseErr: Debug {
+    /// Is this a checksum-related error?
+    fn is_checksum(&self) -> bool;
+}
+
+#[derive(Eq, PartialEq, Debug)]
+enum Err {
+    Format,
+    Checksum,
+}
+
+impl ParseErr for Err {
+    fn is_checksum(&self) -> bool {
+        *self == Err::Checksum
+    }
+}
diff --git a/bin/recovery_netstack/src/wire/udp.rs b/bin/recovery_netstack/src/wire/udp.rs
new file mode 100644
index 0000000..301cb05
--- /dev/null
+++ b/bin/recovery_netstack/src/wire/udp.rs
@@ -0,0 +1,449 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#[cfg(test)]
+use std::fmt::{self, Debug, Formatter};
+use std::num::NonZeroU16;
+use std::ops::RangeBounds;
+
+use byteorder::{BigEndian, ByteOrder};
+use zerocopy::{AsBytes, ByteSlice, FromBytes, LayoutVerified, Unaligned};
+
+use ip::{Ip, IpAddr, IpProto};
+use wire::util::{extract_slice_range, fits_in_u16, fits_in_u32, Checksum};
+use wire::{Err, ParseErr};
+
+const HEADER_SIZE: usize = 8;
+
+// Header has the same memory layout (thanks to repr(C, packed)) as a UDP
+// header. Thus, we can simply reinterpret the bytes of the UDP header as a
+// Header and then safely access its fields. Note the following caveats:
+// - We cannot make any guarantees about the alignment of an instance of this
+//   struct in memory or of any of its fields. This is true both because
+//   repr(packed) removes the padding that would be used to ensure the alignment
+//   of individual fields, but also because we are given no guarantees about
+//   where within a given memory buffer a particular packet (and thus its
+//   header) will be located.
+// - Individual fields are all either u8 or [u8; N] rather than u16, u32, etc.
+//   This is for two reasons:
+//   - u16 and larger have larger-than-1 alignments, which are forbidden as
+//     described above
+//   - We are not guaranteed that the local platform has the same endianness as
+//     network byte order (big endian), so simply treating a sequence of bytes
+//     as a u16 or other multi-byte number would not necessarily be correct.
+//     Instead, we use the BigEndian type and its reader and writer methods to
+//     correctly access these fields.
+#[repr(C, packed)]
+struct Header {
+    src_port: [u8; 2],
+    dst_port: [u8; 2],
+    length: [u8; 2],
+    checksum: [u8; 2],
+}
+
+/// The length of a UDP header in bytes.
+///
+/// When calling `UdpPacket::create`, provide at least `HEADER_LEN` bytes for
+/// the header in order to guarantee that `create` will not panic.
+pub const HEADER_LEN: usize = 8;
+
+unsafe impl FromBytes for Header {}
+unsafe impl AsBytes for Header {}
+unsafe impl Unaligned for Header {}
+
+impl Header {
+    fn src_port(&self) -> u16 {
+        BigEndian::read_u16(&self.src_port)
+    }
+
+    fn set_src_port(&mut self, src_port: u16) {
+        BigEndian::write_u16(&mut self.src_port, src_port);
+    }
+
+    fn dst_port(&self) -> u16 {
+        BigEndian::read_u16(&self.dst_port)
+    }
+
+    fn set_dst_port(&mut self, dst_port: u16) {
+        BigEndian::write_u16(&mut self.dst_port, dst_port);
+    }
+
+    fn length(&self) -> u16 {
+        BigEndian::read_u16(&self.length)
+    }
+
+    fn checksum(&self) -> u16 {
+        BigEndian::read_u16(&self.checksum)
+    }
+}
+
+/// A UDP packet.
+///
+/// A `UdpPacket` shares its underlying memory with the byte slice it was parsed
+/// from or serialized to, meaning that no copying or extra allocation is
+/// necessary.
+pub struct UdpPacket<B> {
+    header: LayoutVerified<B, Header>,
+    body: B,
+}
+
+impl<B: ByteSlice> UdpPacket<B> {
+    /// Parse a UDP packet.
+    ///
+    /// `parse` parses `bytes` as a UDP packet and validates the checksum.
+    ///
+    /// `src_ip` is the source address in the IP header. In IPv4, `dst_ip` is
+    /// the destination address in the IPv4 header. In IPv6, it's more
+    /// complicated:
+    /// - If there's no routing header, the destination is the one in the IPv6
+    ///   header.
+    /// - If there is a routing header, then the sender will compute the
+    ///   checksum using the last address in the routing header, while the
+    ///   receiver will compute the checksum using the destination address in
+    ///   the IPv6 header.
+    pub fn parse<A: IpAddr>(bytes: B, src_ip: A, dst_ip: A) -> Result<UdpPacket<B>, impl ParseErr> {
+        // See for details: https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
+
+        let bytes_len = bytes.len();
+        let (header, body) =
+            LayoutVerified::<B, Header>::new_unaligned_from_prefix(bytes).ok_or(Err::Format)?;
+        let packet = UdpPacket { header, body };
+        let len = if packet.header.length() == 0 && A::Version::VERSION.is_v6() {
+            // IPv6 supports jumbograms, so a UDP packet may be greater than
+            // 2^16 bytes in size. In this case, the size doesn't fit in the
+            // 16-bit length field in the header, and so the length field is set
+            // to zero to indicate this.
+            bytes_len
+        } else {
+            packet.header.length() as usize
+        };
+        if len != bytes_len {
+            return Err(Err::Format);
+        }
+        if packet.header.dst_port() == 0 {
+            return Err(Err::Format);
+        }
+
+        // A 0 checksum indicates that the checksum wasn't computed. In IPv4,
+        // this means that it shouldn't be validated. In IPv6, the checksum is
+        // mandatory, so this is an error.
+        if packet.header.checksum != [0, 0] {
+            // When computing the checksum, a checksum of 0 is sent as 0xFFFF.
+            let target = if packet.header.checksum == [0xFF, 0xFF] {
+                0
+            } else {
+                BigEndian::read_u16(&packet.header.checksum)
+            };
+            if packet.compute_checksum(src_ip, dst_ip).ok_or(Err::Format)? != target {
+                return Err(Err::Checksum);
+            }
+        } else if A::Version::VERSION.is_v6() {
+            return Err(Err::Checksum);
+        }
+
+        Ok(packet)
+    }
+}
+
+impl<B: ByteSlice> UdpPacket<B> {
+    // Compute the UDP checksum, skipping the checksum field itself. Returns
+    // None if the packet size is too large.
+    fn compute_checksum<A: IpAddr>(&self, src_ip: A, dst_ip: A) -> Option<u16> {
+        // See for details: https://en.wikipedia.org/wiki/User_Datagram_Protocol#Checksum_computation
+        let mut c = Checksum::new();
+        c.add_bytes(src_ip.bytes());
+        c.add_bytes(dst_ip.bytes());
+        if A::Version::VERSION.is_v4() {
+            c.add_bytes(&[0]);
+            c.add_bytes(&[IpProto::Udp as u8]);
+            c.add_bytes(&self.header.length);
+        } else {
+            let len = self.header.bytes().len() + self.body.len();
+            if !fits_in_u32(len) {
+                return None;
+            }
+            let mut len_bytes = [0; 4];
+            BigEndian::write_u32(&mut len_bytes, len as u32);
+            c.add_bytes(&len_bytes);
+            c.add_bytes(&[0; 3]);
+            c.add_bytes(&[IpProto::Udp as u8]);
+        }
+        c.add_bytes(&self.header.src_port);
+        c.add_bytes(&self.header.dst_port);
+        c.add_bytes(&self.header.length);
+        c.add_bytes(&self.body);
+        Some(c.sum())
+    }
+
+    /// The packet body.
+    pub fn body(&self) -> &[u8] {
+        self.body.deref()
+    }
+
+    /// The source UDP port, if any.
+    ///
+    /// The source port is optional, and may have been omitted by the sender.
+    pub fn src_port(&self) -> Option<NonZeroU16> {
+        NonZeroU16::new(self.header.src_port())
+    }
+
+    /// The destination UDP port.
+    pub fn dst_port(&self) -> NonZeroU16 {
+        NonZeroU16::new(self.header.dst_port()).unwrap()
+    }
+
+    /// Did this packet have a checksum?
+    ///
+    /// On IPv4, the sender may optionally omit the checksum. If this function
+    /// returns false, the sender ommitted the checksum, and `parse` will not
+    /// have validated it.
+    ///
+    /// On IPv6, it is guaranteed that `checksummed` will return true because
+    /// IPv6 requires a checksum, and so any UDP packet missing one will fail
+    /// validation in `parse`.
+    pub fn checksummed(&self) -> bool {
+        self.header.checksum() != 0
+    }
+}
+
+// NOTE(joshlf): In order to ensure that the checksum is always valid, we don't
+// expose any setters for the fields of the UDP packet; the only way to set them
+// is via UdpPacket::create. This, combined with checksum validation performed
+// in UdpPacket::parse, provides the invariant that a UdpPacket always has a
+// valid checksum.
+
+impl<'a> UdpPacket<&'a mut [u8]> {
+    /// Serialize a UDP packet in an existing buffer.
+    ///
+    /// `create` creates a `UdpPacket` which uses the provided `buffer` for its
+    /// storage, initializing all header fields and calculating the checksum. It
+    /// treats the range identified by `body` as being the frame body. It uses
+    /// the last bytes of `header` before the body to store the header, and
+    /// returns the number of remaining prefix bytes to the caller for use in
+    /// adding other headers.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// let mut buffer = [0u8; 1024];
+    /// (&mut buffer[512..]).copy_from_slice(body);
+    /// let frame = UdpPacket::create(&mut buffer, 512.., src_ip, dst_ip, src_port, dst_port);
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// `create` panics if there is insufficient room preceding the body to
+    /// store the UDP header, or if `body` is not in range of `buffer`. The
+    /// caller can guarantee that there will be enough room by providing at
+    /// least `HEADER_LEN` pre-body bytes.
+    ///
+    /// When encapsulating in IPv4,
+    pub fn create<R: RangeBounds<usize>, A: IpAddr>(
+        buffer: &'a mut [u8], body: R, src_ip: A, dst_ip: A, src_port: Option<NonZeroU16>,
+        dst_port: NonZeroU16,
+    ) -> (UdpPacket<&'a mut [u8]>, usize) {
+        // See for details: https://en.wikipedia.org/wiki/User_Datagram_Protocol#Packet_structure
+
+        let (header, body, _) =
+            extract_slice_range(buffer, body).expect("body range is out of bounds of buffer");
+        let (header, prefix) = LayoutVerified::<_, Header>::new_unaligned_from_suffix(header)
+            .expect("too few bytes for UDP header");
+        let mut packet = UdpPacket { header, body };
+
+        packet
+            .header
+            .set_src_port(src_port.map(|port| port.get()).unwrap_or(0));
+        packet.header.set_dst_port(dst_port.get());
+        let total_len = HEADER_LEN + packet.body.len();
+        let len_field = if fits_in_u16(total_len) {
+            total_len as u16
+        } else if A::Version::VERSION.is_v6() {
+            // IPv6 supports jumbograms, so a UDP packet may be greater than
+            // 2^16 bytes in size. In this case, the size doesn't fit in the
+            // 16-bit length field in the header, and so the length field is set
+            // to zero to indicate this.
+            0u16
+        } else {
+            panic!(
+                "total UDP packet length of {} bytes overflows 16-bit length field of UDP header",
+                total_len
+            );
+        };
+        BigEndian::write_u16(&mut packet.header.length, len_field);
+
+        // This ignores the checksum field in the header, so it's fine that we
+        // haven't set it yet, and so it could be filled with arbitrary bytes.
+        let c = packet.compute_checksum(src_ip, dst_ip).expect(&format!(
+            "total UDP packet length of {} bytes overflow 32-bit length field of pseudo-header",
+            total_len
+        ));
+        BigEndian::write_u16(
+            &mut packet.header.checksum,
+            if c == 0 {
+                // When computing the checksum, a checksum of 0 is sent as 0xFFFF.
+                0xFFFF
+            } else {
+                c
+            },
+        );
+        (packet, prefix.len())
+    }
+}
+
+// needed by Result::unwrap_err in the tests below
+#[cfg(test)]
+impl<B> Debug for UdpPacket<B> {
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        write!(fmt, "UdpPacket")
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use ip::{Ipv4Addr, Ipv6Addr};
+
+    use super::*;
+
+    const TEST_SRC_IPV4: Ipv4Addr = Ipv4Addr::new([1, 2, 3, 4]);
+    const TEST_DST_IPV4: Ipv4Addr = Ipv4Addr::new([5, 6, 7, 8]);
+    const TEST_SRC_IPV6: Ipv6Addr =
+        Ipv6Addr::new([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
+    const TEST_DST_IPV6: Ipv6Addr = Ipv6Addr::new([
+        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+    ]);
+
+    #[test]
+    fn test_parse() {
+        // source port of 0 (meaning none) is allowed, as is a missing checksum
+        let buf = [0, 0, 1, 2, 0, 8, 0, 0];
+        let packet = UdpPacket::parse(&buf[..], TEST_SRC_IPV4, TEST_DST_IPV4).unwrap();
+        assert!(packet.src_port().is_none());
+        assert_eq!(packet.dst_port().get(), BigEndian::read_u16(&[1, 2]));
+        assert!(!packet.checksummed());
+        assert!(packet.body().is_empty());
+
+        // length of 0 is allowed in IPv6
+        let buf = [0, 0, 1, 2, 0, 0, 0xFF, 0xE4];
+        let packet = UdpPacket::parse(&buf[..], TEST_SRC_IPV6, TEST_DST_IPV6).unwrap();
+        assert!(packet.src_port().is_none());
+        assert_eq!(packet.dst_port().get(), BigEndian::read_u16(&[1, 2]));
+        assert!(packet.checksummed());
+        assert!(packet.body().is_empty());
+    }
+
+    #[test]
+    fn test_create() {
+        let mut buf = [0; 8];
+        {
+            let (packet, prefix_len) = UdpPacket::create(
+                &mut buf,
+                8..,
+                TEST_SRC_IPV4,
+                TEST_DST_IPV4,
+                NonZeroU16::new(1),
+                NonZeroU16::new(2).unwrap(),
+            );
+            assert_eq!(prefix_len, 0);
+            assert_eq!(packet.src_port().unwrap().get(), 1);
+            assert_eq!(packet.dst_port().get(), 2);
+            assert!(packet.checksummed());
+        }
+        assert_eq!(buf, [0, 1, 0, 2, 0, 8, 222, 216]);
+    }
+
+    #[test]
+    fn test_parse_fail() {
+        // Test that while a given byte pattern optionally succeeds, zeroing out
+        // certain bytes causes failure. `zero` is a list of byte indices to
+        // zero out that should cause failure.
+        fn test_zero<I: IpAddr>(
+            src: I, dst: I, succeeds: bool, zero: &[usize], err_is_checksum: bool,
+        ) {
+            // Set checksum to zero so that, in IPV4, it will be ignored. In
+            // IPv6, this /is/ the test.
+            let mut buf = [1, 2, 3, 4, 0, 8, 0, 0];
+            if succeeds {
+                assert!(UdpPacket::parse(&buf[..], src, dst).is_ok());
+            }
+            for idx in zero {
+                buf[*idx] = 0;
+            }
+            assert_eq!(
+                UdpPacket::parse(&buf[..], src, dst)
+                    .unwrap_err()
+                    .is_checksum(),
+                err_is_checksum
+            );
+        }
+
+        // destination port of 0 is disallowed
+        test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[2, 3], false);
+        // length of 0 is disallowed in IPv4
+        test_zero(TEST_SRC_IPV4, TEST_DST_IPV4, true, &[4, 5], false);
+        // missing checksum is disallowed in IPv6; this won't succeed ahead of
+        // time because the checksum bytes are already zero
+        test_zero(TEST_SRC_IPV6, TEST_DST_IPV6, false, &[], true);
+
+        // Total length of 2^32 or greater is disallowed in IPv6. If we created
+        // a 4 gigabyte buffer, this test would take a very long time to run.
+        // Instead, we allocate enough space for the header (which may actually
+        // be read before the length check fails), and then /very unsafely/
+        // pretend that it's 2^32 bytes long.
+        let buf = vec![0, 0, 1, 2, 0, 0, 0xFF, 0xE4];
+        let buf = unsafe { ::std::slice::from_raw_parts(buf.as_ptr(), 1 << 32) };
+        assert!(
+            !UdpPacket::parse(&buf[..], TEST_SRC_IPV6, TEST_DST_IPV6)
+                .unwrap_err()
+                .is_checksum()
+        );
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_create_fail_header_too_short() {
+        let mut buf = [0; 7];
+        UdpPacket::create(
+            &mut buf,
+            7..,
+            TEST_SRC_IPV4,
+            TEST_DST_IPV4,
+            None,
+            NonZeroU16::new(1).unwrap(),
+        );
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_create_fail_packet_too_long_ipv4() {
+        let mut buf = [0; 1 << 16];
+        UdpPacket::create(
+            &mut buf,
+            8..,
+            TEST_SRC_IPV4,
+            TEST_DST_IPV4,
+            None,
+            NonZeroU16::new(1).unwrap(),
+        );
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_create_fail_packet_too_long_ipv6() {
+        // Total length of 2^32 or greater is disallowed in IPv6. If we created
+        // a 4 gigabyte buffer, this test would take a very long time to run.
+        // Instead, we allocate enough space for the header (which may actually
+        // be written before the length check fails), and then /very unsafely/
+        // pretend that it's 2^32 bytes long.
+        let mut buf = vec![0, 0, 0, 0, 0, 0, 0, 0];
+        let mut buf = unsafe { ::std::slice::from_raw_parts_mut(buf.as_mut_ptr(), 1 << 32) };
+        UdpPacket::create(
+            &mut buf,
+            8..,
+            TEST_SRC_IPV4,
+            TEST_DST_IPV4,
+            None,
+            NonZeroU16::new(1).unwrap(),
+        );
+    }
+}
diff --git a/bin/recovery_netstack/src/wire/util.rs b/bin/recovery_netstack/src/wire/util.rs
new file mode 100644
index 0000000..5ecf628
--- /dev/null
+++ b/bin/recovery_netstack/src/wire/util.rs
@@ -0,0 +1,126 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+pub use self::checksum::*;
+pub use self::range::*;
+
+/// Whether `size` fits in a `u16`.
+pub fn fits_in_u16(size: usize) -> bool {
+    size < 1 << 16
+}
+
+/// Whether `size` fits in a `u32`.
+pub fn fits_in_u32(size: usize) -> bool {
+    // trivially true when usize is 32 bits wide
+    cfg!(target_pointer_width = "32") || size < 1 << 32
+}
+
+mod checksum {
+    use byteorder::{BigEndian, ByteOrder};
+
+    /// A checksum used by IPv4, TCP, and UDP.
+    ///
+    /// This checksum operates by computing the 1s complement of the 1s
+    /// complement sum of successive 16-bit words of the input.
+    pub struct Checksum(u32);
+
+    impl Checksum {
+        /// Initialize a new checksum.
+        pub fn new() -> Self {
+            Checksum(0)
+        }
+
+        /// Add bytes to the checksum.
+        ///
+        /// If `bytes` does not contain an even number of bytes, a single zero byte
+        /// will be added to the end before updating the checksum.
+        pub fn add_bytes(&mut self, mut bytes: &[u8]) {
+            while bytes.len() > 1 {
+                self.0 += u32::from(BigEndian::read_u16(bytes));
+                bytes = &bytes[2..];
+            }
+            if bytes.len() == 1 {
+                self.0 += u32::from(BigEndian::read_u16(&[bytes[0], 0]));
+            }
+        }
+
+        /// Compute the checksum.
+        ///
+        /// `sum` returns the checksum of all data added using `add_bytes` so far.
+        /// Calling `sum` does *not* reset the checksum. More bytes may be added
+        /// after calling `sum`, and they will be added to the checksum as expected.
+        pub fn sum(&self) -> u16 {
+            let mut sum = self.0;
+            while (sum >> 16) != 0 {
+                sum = (sum >> 16) + (sum & 0xFF);
+            }
+            !sum as u16
+        }
+    }
+
+    /// Checksum bytes.
+    ///
+    /// `checksum` is a shorthand for
+    ///
+    /// ```rust
+    /// let mut c = Checksum::new();
+    /// c.add_bytes(bytes);
+    /// c.sum()
+    /// ```
+    pub fn checksum(bytes: &[u8]) -> u16 {
+        let mut c = Checksum::new();
+        c.add_bytes(bytes);
+        c.sum()
+    }
+}
+
+mod range {
+    use std::ops::{Bound, RangeBounds};
+
+    use zerocopy::ByteSlice;
+
+    /// Extract a range from a slice of bytes.
+    ///
+    /// `extract_slice_range` extracts the given range from the given slice of
+    /// bytes. It also returns the byte slices before and after the range.
+    ///
+    /// If the provided range is out of bounds of the slice, or if the range
+    /// itself is nonsensical (if the upper bound precedes the lower bound),
+    /// `extract_slice_range` returns `None`.
+    pub fn extract_slice_range<B: ByteSlice, R: RangeBounds<usize>>(
+        bytes: B, range: R,
+    ) -> Option<(B, B, B)> {
+        let lower = resolve_lower_bound(range.start_bound());
+        let upper = resolve_upper_bound(bytes.len(), range.end_bound())?;
+        if lower > upper {
+            return None;
+        }
+        let (a, rest) = bytes.split_at(lower);
+        let (b, c) = rest.split_at(upper - lower);
+        Some((a, b, c))
+    }
+
+    // return the inclusive equivalent of the bound
+    fn resolve_lower_bound(bound: Bound<&usize>) -> usize {
+        match bound {
+            Bound::Included(x) => *x,
+            Bound::Excluded(x) => *x + 1,
+            Bound::Unbounded => 0,
+        }
+    }
+
+    // return the exclusive equivalent of the bound, verifying that it is in
+    // range of len
+    fn resolve_upper_bound(len: usize, bound: Bound<&usize>) -> Option<usize> {
+        let bound = match bound {
+            Bound::Included(x) => *x + 1,
+            Bound::Excluded(x) => *x,
+            Bound::Unbounded => len,
+        };
+        if bound > len {
+            return None;
+        }
+        Some(bound)
+    }
+}
diff --git a/bin/run/main.cc b/bin/run/main.cc
index 2cad163..6397ca2 100644
--- a/bin/run/main.cc
+++ b/bin/run/main.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fdio/limits.h>
-#include <fdio/util.h>
+#include <lib/fdio/limits.h>
+#include <lib/fdio/util.h>
 #include <stdio.h>
 
 #include <fuchsia/sys/cpp/fidl.h>
diff --git a/bin/runmany/src/runmany.c b/bin/runmany/src/runmany.c
index 488d8b2..1e18ba5 100644
--- a/bin/runmany/src/runmany.c
+++ b/bin/runmany/src/runmany.c
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD - style license that can be
 // found in the LICENSE file.
 
-#include <fdio/io.h>
-#include <fdio/private.h>
-#include <fdio/spawn.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/private.h>
+#include <lib/fdio/spawn.h>
 #include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,7 +30,7 @@
   char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
   zx_status_t status = fdio_spawn_etc(
       job,
-      FDIO_SPAWN_SHARE_JOB | FDIO_SPAWN_CLONE_LDSVC |
+      FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC |
           FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_ENVIRON,
       argv[0], argv, NULL, actions_count, actions, &process, err_msg);
   if (status != ZX_OK) {
diff --git a/bin/sysmgr/app.cc b/bin/sysmgr/app.cc
index ebc1968..9c543a2 100644
--- a/bin/sysmgr/app.cc
+++ b/bin/sysmgr/app.cc
@@ -2,17 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <dirent.h>
-#include <sys/types.h>
-
 #include "garnet/bin/sysmgr/app.h"
 
 #include <zircon/process.h>
 #include <zircon/processargs.h>
 
-#include <fdio/util.h>
 #include <fs/managed-vfs.h>
 #include <lib/async/default.h>
+#include <lib/fdio/util.h>
 #include "lib/app/cpp/connect.h"
 #include "lib/fidl/cpp/clone.h"
 #include "lib/fxl/functional/make_copyable.h"
@@ -21,40 +18,13 @@
 namespace sysmgr {
 
 constexpr char kDefaultLabel[] = "sys";
-constexpr char kConfigDir[] = "/system/data/sysmgr/";
 
-App::App()
+App::App(Config config)
     : startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
       vfs_(async_get_default()),
       svc_root_(fbl::AdoptRef(new fs::PseudoDir())) {
   FXL_DCHECK(startup_context_);
 
-  Config config;
-  char buf[PATH_MAX];
-  if (strlcpy(buf, kConfigDir, PATH_MAX) >= PATH_MAX) {
-    FXL_LOG(ERROR) << "Config directory path too long";
-  } else {
-    const size_t dir_len = strlen(buf);
-    DIR* cfg_dir = opendir(kConfigDir);
-    if (cfg_dir != NULL) {
-      for (dirent* cfg = readdir(cfg_dir); cfg != NULL;
-           cfg = readdir(cfg_dir)) {
-        if (strcmp(".", cfg->d_name) == 0 || strcmp("..", cfg->d_name) == 0) {
-          continue;
-        }
-        if (strlcat(buf, cfg->d_name, PATH_MAX) >= PATH_MAX) {
-          FXL_LOG(WARNING) << "Could not read config file, path too long";
-          continue;
-        }
-        config.ReadFrom(buf);
-        buf[dir_len] = '\0';
-      }
-      closedir(cfg_dir);
-    } else {
-      FXL_LOG(WARNING) << "Could not open config directory" << kConfigDir;
-    }
-  }
-
   // Set up environment for the programs we will run.
   startup_context_->environment()->CreateNestedEnvironment(
       OpenAsDirectory(), env_.NewRequest(), env_controller_.NewRequest(),
@@ -74,11 +44,6 @@
   // Launch startup applications.
   for (auto& launch_info : config.TakeApps())
     LaunchApplication(std::move(*launch_info));
-
-  // TODO(abarth): Remove this hard-coded mention of netstack once netstack is
-  // fully converted to using service namespaces.
-  LaunchNetstack();
-  LaunchWlanstack();
 }
 
 App::~App() {}
@@ -118,7 +83,7 @@
 void App::LaunchWlanstack() {
   zx::channel h1, h2;
   zx::channel::create(0, &h1, &h2);
-  ConnectToService("wlan_service.Wlan", std::move(h1));
+  ConnectToService("fuchsia.wlan.service.Wlan", std::move(h1));
 }
 
 void App::RegisterSingleton(std::string service_name,
diff --git a/bin/sysmgr/app.h b/bin/sysmgr/app.h
index f82c931..0b6e89c 100644
--- a/bin/sysmgr/app.h
+++ b/bin/sysmgr/app.h
@@ -27,14 +27,15 @@
 // of the environment.
 class App {
  public:
-  App();
+  explicit App(Config config);
   ~App();
 
+  void LaunchNetstack();
+  void LaunchWlanstack();
+
  private:
   zx::channel OpenAsDirectory();
   void ConnectToService(const std::string& service_name, zx::channel channel);
-  void LaunchNetstack();
-  void LaunchWlanstack();
 
   void RegisterSingleton(std::string service_name,
                          fuchsia::sys::LaunchInfoPtr launch_info);
diff --git a/bin/sysmgr/config.cc b/bin/sysmgr/config.cc
index d8e781f..02c9fcf 100644
--- a/bin/sysmgr/config.cc
+++ b/bin/sysmgr/config.cc
@@ -38,8 +38,7 @@
 }
 
 bool ParseServiceMap(const rapidjson::Document& document,
-                     const std::string& key,
-                     Config::ServiceMap* services) {
+                     const std::string& key, Config::ServiceMap* services) {
   auto it = document.FindMember(key);
   if (it != document.MemberEnd()) {
     const auto& value = it->value;
@@ -62,6 +61,10 @@
 
 Config::Config() = default;
 
+Config::Config(Config&& other) = default;
+
+Config& Config::operator=(Config&& other) = default;
+
 Config::~Config() = default;
 
 bool Config::ReadFrom(const std::string& config_file) {
diff --git a/bin/sysmgr/config.h b/bin/sysmgr/config.h
index d934808..f76fe60 100644
--- a/bin/sysmgr/config.h
+++ b/bin/sysmgr/config.h
@@ -24,6 +24,10 @@
   using AppVector = std::vector<fuchsia::sys::LaunchInfoPtr>;
 
   Config();
+
+  Config(Config&& other);
+  Config& operator=(Config&& other);
+
   ~Config();
 
   bool ReadFrom(const std::string& config_file);
diff --git a/bin/sysmgr/config/services.config b/bin/sysmgr/config/services.config
index b3b8bf1..9a78c73 100644
--- a/bin/sysmgr/config/services.config
+++ b/bin/sysmgr/config/services.config
@@ -6,35 +6,35 @@
     "bluetooth_low_energy.Central":  [ "bt-gap" ],
     "bluetooth_low_energy.Peripheral":  [ "bt-gap" ],
     "cobalt.CobaltEncoderFactory": "cobalt",
-    "device_settings.DeviceSettingsManager": "device_settings_manager",
     "fonts.FontProvider": "fonts",
+    "fuchsia.devicesettings.DeviceSettingsManager": "device_settings_manager",
     "fuchsia.examples.shadertoy.ShadertoyFactory": "shadertoy_service",
     "fuchsia.gralloc.Gralloc": "gralloc",
     "fuchsia.guest.GuestManager": "guestmgr",
+    "fuchsia.media.AudioServer": "audio_server",
+    "fuchsia.mediaplayer.MediaPlayer": "media_player",
+    "fuchsia.mediaplayer.NetMediaService": "net_media_service",
     "fuchsia.modular.DeviceRunnerMonitor": "device_runner_monitor",
+    "fuchsia.net.oldhttp.HttpService": "http",
+    "fuchsia.netstack.Netstack": "netstack",
     "fuchsia.tracelink.Registry": "trace_manager",
     "fuchsia.ui.input.ImeService": "ime_service",
     "fuchsia.ui.input.InputDeviceRegistry": "root_presenter",
+    "fuchsia.ui.policy.Presenter": "root_presenter",
     "fuchsia.ui.scenic.Scenic": "scenic",
     "fuchsia.ui.sketchy.Canvas": "sketchy_service",
     "fuchsia.ui.views_v1.ViewManager": "view_manager",
+    "fuchsia.wlan.device.service.DeviceService": "wlanstack2",
+    "fuchsia.wlan.service.Wlan": "wlanstack",
     "icu_data.ICUDataProvider": "icu_data",
-    "logger.Log": "logger",
-    "logger.LogSink": "logger",
+    "fuchsia.logger.Log": "logger",
+    "fuchsia.logger.LogSink": "logger",
     "mdns.MdnsService": "mdns_service",
-    "media_player.MediaPlayer": "media_player",
-    "media_player.NetMediaService": "net_media_service",
-    "media.AudioServer": "audio_server",
     "net.Netstack": "netstack",
     "netconnector.NetConnector": [ "netconnector", "--listen" ],
-    "netstack.Netstack": "netstack",
-    "network.NetworkService": "network",
-    "power_manager.PowerManager": "power_manager",
-    "presentation.Presenter": "root_presenter",
+    "fuchsia.power.PowerManager": "power_manager",
     "time_zone.Timezone": "timezone",
     "tracing.TraceController": "trace_manager",
-    "tts.TtsService": "tts_service",
-    "wlan_device_service.DeviceService": "wlanstack2",
-    "wlan_service.Wlan": "wlanstack"
+    "tts.TtsService": "tts_service"
   }
 }
diff --git a/bin/sysmgr/integration_tests/BUILD.gn b/bin/sysmgr/integration_tests/BUILD.gn
new file mode 100644
index 0000000..0e771ba
--- /dev/null
+++ b/bin/sysmgr/integration_tests/BUILD.gn
@@ -0,0 +1,71 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/fidl/fidl.gni")
+import("//build/package.gni")
+
+fidl("interface") {
+  name = "sysmgr.test"
+  cpp_legacy_callbacks = true
+  sources = [
+    "interface.fidl",
+  ]
+}
+
+executable("service") {
+  testonly = true
+  output_name = "test_sysmgr_service_startup"
+
+  sources = [
+    "service.cc",
+  ]
+
+  deps = [
+    ":interface",
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/fidl/cpp",
+    "//garnet/public/lib/fxl",
+    "//zircon/public/lib/async-default",
+    "//zircon/public/lib/async-loop-cpp",
+  ]
+}
+
+executable("service_startup_test") {
+  testonly = true
+
+  sources = [
+    "service_startup_test.cc",
+  ]
+
+  deps = [
+    ":interface",
+    "//garnet/bin/appmgr:appmgr_for_test",
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/fxl",
+    "//garnet/public/lib/fxl/test:gtest_main",
+    "//garnet/public/lib/gtest",
+  ]
+}
+
+package("integration_tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  deps = [
+    ":service",
+    ":service_startup_test",
+  ]
+
+  binaries = [
+    {
+      name = "test_sysmgr_service_startup"
+    },
+  ]
+
+  tests = [
+    {
+      name = "service_startup_test"
+    },
+  ]
+}
diff --git a/bin/sysmgr/integration_tests/interface.fidl b/bin/sysmgr/integration_tests/interface.fidl
new file mode 100644
index 0000000..8f2e6a3
--- /dev/null
+++ b/bin/sysmgr/integration_tests/interface.fidl
@@ -0,0 +1,10 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library sysmgr.test;
+
+[Discoverable]
+interface Interface {
+  1: Ping() -> (string magic);
+};
diff --git a/bin/sysmgr/integration_tests/service.cc b/bin/sysmgr/integration_tests/service.cc
new file mode 100644
index 0000000..a934f6c
--- /dev/null
+++ b/bin/sysmgr/integration_tests/service.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/zx/channel.h>
+#include <sysmgr/test/cpp/fidl.h>
+
+#include "lib/app/cpp/startup_context.h"
+
+namespace sysmgr {
+namespace test {
+namespace {
+
+class Service : public Interface {
+ public:
+  Service() : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
+    context_->outgoing().AddPublicService<Interface>(
+        [this](fidl::InterfaceRequest<Interface> request) {
+          bindings_.AddBinding(this, std::move(request));
+        });
+  }
+
+  ~Service() = default;
+
+  void Ping(PingCallback callback) override {
+    callback("test_sysmgr_service_startup");
+  }
+
+ private:
+  std::unique_ptr<fuchsia::sys::StartupContext> context_;
+  fidl::BindingSet<Interface> bindings_;
+};
+
+}  // namespace
+}  // namespace test
+}  // namespace sysmgr
+
+int main(int argc, const char** argv) {
+  async::Loop loop(&kAsyncLoopConfigMakeDefault);
+
+  sysmgr::test::Service service;
+  loop.Run();
+  return 0;
+}
diff --git a/bin/sysmgr/integration_tests/service_startup_test.cc b/bin/sysmgr/integration_tests/service_startup_test.cc
new file mode 100644
index 0000000..815680a
--- /dev/null
+++ b/bin/sysmgr/integration_tests/service_startup_test.cc
@@ -0,0 +1,62 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <lib/fdio/util.h>
+#include <lib/gtest/test_with_message_loop.h>
+#include <sysmgr/test/cpp/fidl.h>
+
+#include "garnet/bin/appmgr/appmgr.h"
+#include "gtest/gtest.h"
+#include "lib/fidl/cpp/interface_ptr.h"
+#include "lib/fxl/logging.h"
+
+namespace sysmgr {
+namespace test {
+namespace {
+
+class TestSysmgr : public gtest::TestWithMessageLoop {};
+
+TEST_F(TestSysmgr, ServiceStartup) {
+  zx::channel h1, h2;
+  ASSERT_EQ(ZX_OK, zx::channel::create(0, &h1, &h2));
+
+  fidl::VectorPtr<fidl::StringPtr> sysmgr_args;
+  sysmgr_args.push_back(
+      "--config={\"services\": { \"sysmgr.test.Interface\": "
+      "\"test_sysmgr_service_startup\" } }");
+  sysmgr_args.push_back("--test");
+  fuchsia::sys::AppmgrArgs args{.pa_directory_request = h2.release(),
+                                .sysmgr_url = "sysmgr",
+                                .sysmgr_args = std::move(sysmgr_args),
+                                .run_virtual_console = false,
+                                .retry_sysmgr_crash = false};
+  fuchsia::sys::Appmgr appmgr(message_loop_.async(), std::move(args));
+
+  zx::channel svc_client, svc_server;
+  ASSERT_EQ(ZX_OK, zx::channel::create(0, &svc_client, &svc_server));
+  ASSERT_EQ(ZX_OK,
+            fdio_service_connect_at(h1.get(), "svc", svc_server.release()));
+
+  sysmgr::test::InterfacePtr interface_ptr;
+  ASSERT_EQ(ZX_OK, fdio_service_connect_at(
+                       svc_client.get(), sysmgr::test::Interface::Name_,
+                       interface_ptr.NewRequest(message_loop_.async())
+                           .TakeChannel()
+                           .release()));
+
+  bool received_response = false;
+  std::string response;
+  interface_ptr->Ping([&received_response, &response](fidl::StringPtr r) {
+    received_response = true;
+    response = r;
+  });
+
+  RunLoopUntilWithTimeout([&received_response] { return received_response; },
+                          fxl::TimeDelta::FromSeconds(10));
+  EXPECT_EQ("test_sysmgr_service_startup", response);
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace sysmgr
diff --git a/bin/sysmgr/main.cc b/bin/sysmgr/main.cc
index 5427206..70003d9 100644
--- a/bin/sysmgr/main.cc
+++ b/bin/sysmgr/main.cc
@@ -2,19 +2,63 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <dirent.h>
 #include <lib/async-loop/cpp/loop.h>
+#include <sys/types.h>
 
 #include "garnet/bin/sysmgr/app.h"
 #include "lib/fxl/command_line.h"
 #include "lib/fxl/log_settings_command_line.h"
 
+constexpr char kConfigDir[] = "/system/data/sysmgr/";
+
 int main(int argc, const char** argv) {
   auto command_line = fxl::CommandLineFromArgcArgv(argc, argv);
   if (!fxl::SetLogSettingsFromCommandLine(command_line))
     return 1;
 
+  sysmgr::Config config;
+
+  if (command_line.HasOption("config")) {
+    std::string unparsed_config;
+    command_line.GetOptionValue("config", &unparsed_config);
+    config.Parse(unparsed_config, "command line");
+  } else {
+    char buf[PATH_MAX];
+    if (strlcpy(buf, kConfigDir, PATH_MAX) >= PATH_MAX) {
+      FXL_LOG(FATAL) << "Config directory path too long";
+    } else {
+      const size_t dir_len = strlen(buf);
+      DIR* cfg_dir = opendir(kConfigDir);
+      if (cfg_dir != NULL) {
+        for (dirent* cfg = readdir(cfg_dir); cfg != NULL;
+             cfg = readdir(cfg_dir)) {
+          if (strcmp(".", cfg->d_name) == 0 || strcmp("..", cfg->d_name) == 0) {
+            continue;
+          }
+          if (strlcat(buf, cfg->d_name, PATH_MAX) >= PATH_MAX) {
+            FXL_LOG(WARNING) << "Could not read config file, path too long";
+            continue;
+          }
+          config.ReadFrom(buf);
+          buf[dir_len] = '\0';
+        }
+        closedir(cfg_dir);
+      } else {
+        FXL_LOG(WARNING) << "Could not open config directory" << kConfigDir;
+      }
+    }
+  }
+
   async::Loop loop(&kAsyncLoopConfigMakeDefault);
-  sysmgr::App app;
+  sysmgr::App app(std::move(config));
+
+  // TODO(abarth): Remove this hard-coded mention of netstack once netstack is
+  // // fully converted to using service namespaces.
+  if (!command_line.HasOption("test")) {
+    app.LaunchNetstack();
+    app.LaunchWlanstack();
+  }
   loop.Run();
   return 0;
 }
diff --git a/bin/sysmgr/test/BUILD.gn b/bin/sysmgr/test/BUILD.gn
new file mode 100644
index 0000000..4edf979
--- /dev/null
+++ b/bin/sysmgr/test/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2017 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+
+copy("ls_svc_test") {
+  sources = [
+    "ls_svc_test",
+  ]
+
+  outputs = [
+    "$root_out_dir/ls_svc_test",
+  ]
+}
+
+package("sysmgr_tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  deps = [
+    ":ls_svc_test",
+  ]
+
+  tests = [
+    {
+      name = "ls_svc_test"
+    },
+  ]
+}
\ No newline at end of file
diff --git a/bin/sysmgr/test/ls_svc_test b/bin/sysmgr/test/ls_svc_test
new file mode 100644
index 0000000..ae5eace
--- /dev/null
+++ b/bin/sysmgr/test/ls_svc_test
@@ -0,0 +1,27 @@
+#!/boot/bin/sh
+
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This script runs `ls /svc` and looks for default services. It then attempts
+# to ensure we can run `ls /svc` again, as we would expect.
+
+ls_svc_output="$(ls /svc)"
+grep__output="$(echo $ls_svc_output | grep logger)"
+if [ -z "$grep__output" ];
+then
+    echo "FAIL, expected logger output on ls /svc, but was:"
+    echo $ls_svc_output
+    exit 1
+fi
+
+ls_svc_output_2="$(ls /svc)"
+if [ $? -ne 0 ];
+then
+    echo "FAIL, expected ls /svc to be able to run multiple times"
+    exit 1
+fi
+
+echo "PASS"
+exit 0
diff --git a/bin/test_runner/report_result/BUILD.gn b/bin/test_runner/report_result/BUILD.gn
index 155d388..6f8c6e6 100644
--- a/bin/test_runner/report_result/BUILD.gn
+++ b/bin/test_runner/report_result/BUILD.gn
@@ -12,6 +12,6 @@
   deps = [
     "//garnet/public/lib/test_runner/cpp",
     "//garnet/public/lib/test_runner/fidl",
-    "//zircon/public/lib/launchpad",
+    "//zircon/public/lib/fdio",
   ]
 }
diff --git a/bin/test_runner/report_result/report_result.cc b/bin/test_runner/report_result/report_result.cc
index 07fe132..55aa8ea 100644
--- a/bin/test_runner/report_result/report_result.cc
+++ b/bin/test_runner/report_result/report_result.cc
@@ -7,7 +7,8 @@
 #include <iostream>
 #include <sstream>
 
-#include <launchpad/launchpad.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/spawn.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <test_runner/cpp/fidl.h>
 #include <zircon/processargs.h>
@@ -16,6 +17,17 @@
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/time/stopwatch.h"
 
+static zx_status_t AddPipe(int target_fd, int* local_fd,
+                           fdio_spawn_action_t* action) {
+  zx_status_t status = fdio_pipe_half(&action->h.handle, &action->h.id);
+  if (status < 0)
+    return status;
+  *local_fd = status;
+  action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
+  action->h.id = PA_HND(PA_HND_TYPE(action->h.id), target_fd);
+  return ZX_OK;
+}
+
 class Reporter {
  public:
   Reporter(async::Loop* loop, const std::string& name,
@@ -82,21 +94,29 @@
     return 1;
   }
 
-  launchpad_t* launchpad;
-  int stdout_pipe;
-  int stderr_pipe;
-  launchpad_create(0, argv[1], &launchpad);
-  launchpad_load_from_file(launchpad, argv[1]);
-  launchpad_clone(launchpad, LP_CLONE_FDIO_NAMESPACE);
-  launchpad_add_pipe(launchpad, &stdout_pipe, 1);
-  launchpad_add_pipe(launchpad, &stderr_pipe, 2);
-  launchpad_set_args(launchpad, argc - 1, argv + 1);
+  int stdout_pipe = -1;
+  int stderr_pipe = -1;
+  fdio_spawn_action_t actions[2] = {};
+
+  if (AddPipe(STDOUT_FILENO, &stdout_pipe, &actions[0]) != ZX_OK) {
+    reporter.Start();
+    reporter.Finish(true, "Failed to create stdout pipe");
+    return 1;
+  }
+
+  if (AddPipe(STDERR_FILENO, &stderr_pipe, &actions[1]) != ZX_OK) {
+    reporter.Start();
+    reporter.Finish(true, "Failed to create stderr pipe");
+    return 1;
+  }
 
   reporter.Start();
 
-  const char* error;
-  zx_handle_t handle;
-  zx_status_t status = launchpad_go(launchpad, &handle, &error);
+  char error[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
+  zx_handle_t handle = ZX_HANDLE_INVALID;
+  zx_status_t status = fdio_spawn_etc(
+      ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL & ~FDIO_SPAWN_CLONE_STDIO,
+      argv[1], argv + 1, nullptr, countof(actions), actions, &handle, error);
   if (status < 0) {
     reporter.Finish(true, error);
     return 1;
diff --git a/bin/test_runner/server/BUILD.gn b/bin/test_runner/server/BUILD.gn
index d3681d8..00d11cd 100644
--- a/bin/test_runner/server/BUILD.gn
+++ b/bin/test_runner/server/BUILD.gn
@@ -13,4 +13,8 @@
     "//garnet/public/lib/test_runner/cpp",
     "//garnet/public/lib/test_runner/fidl",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
diff --git a/bin/test_runner/server/test_runner_server.cc b/bin/test_runner/server/test_runner_server.cc
index 18625ff..bb67b20 100644
--- a/bin/test_runner/server/test_runner_server.cc
+++ b/bin/test_runner/server/test_runner_server.cc
@@ -28,7 +28,6 @@
 // runner environment, without teardown; useful for testing modules, which may
 // not need to tear down device_runner.
 
-#include <functional>
 #include <string>
 #include <vector>
 
@@ -39,6 +38,7 @@
 
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
+#include <lib/fit/function.h>
 #include <lib/zx/time.h>
 #include <test_runner/cpp/fidl.h>
 
@@ -233,7 +233,7 @@
     auto* runner = server.AcceptConnection();
     async::PostTask(
         loop.async(),
-        std::bind(&test_runner::TestRunnerConnection::Start, runner));
+        fit::bind_member(runner, &test_runner::TestRunnerConnection::Start));
     loop.Run();
   }
   return 0;
diff --git a/bin/thermd/thermd.cc b/bin/thermd/thermd.cc
index 816e044..378fff1 100644
--- a/bin/thermd/thermd.cc
+++ b/bin/thermd/thermd.cc
@@ -9,7 +9,7 @@
 
 #include <lib/async-loop/cpp/loop.h>
 
-#include <fdio/watcher.h>
+#include <lib/fdio/watcher.h>
 #include <trace-provider/provider.h>
 #include <trace/event.h>
 
diff --git a/bin/thermd/thermd_arm.cc b/bin/thermd/thermd_arm.cc
index 1159006..5d87d40 100644
--- a/bin/thermd/thermd_arm.cc
+++ b/bin/thermd/thermd_arm.cc
@@ -7,7 +7,7 @@
 #include <zircon/syscalls/system.h>
 #include <zircon/syscalls.h>
 #include <zircon/syscalls/port.h>
-#include <fdio/watcher.h>
+#include <lib/fdio/watcher.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
diff --git a/bin/time/time.c b/bin/time/time.c
index 180f20e..e80cbea 100644
--- a/bin/time/time.c
+++ b/bin/time/time.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fdio/spawn.h>
+#include <lib/fdio/spawn.h>
 #include <stdio.h>
 #include <zircon/status.h>
 #include <zircon/syscalls.h>
diff --git a/bin/trace/BUILD.gn b/bin/trace/BUILD.gn
index f9dc4fd..e79485e 100644
--- a/bin/trace/BUILD.gn
+++ b/bin/trace/BUILD.gn
@@ -44,6 +44,7 @@
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/tracing/fidl",
     "//zircon/public/lib/fdio",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/trace-reader",
   ]
 
diff --git a/bin/trace/app.h b/bin/trace/app.h
index 0a295c1..06669f7 100644
--- a/bin/trace/app.h
+++ b/bin/trace/app.h
@@ -5,7 +5,6 @@
 #ifndef GARNET_BIN_TRACE_APP_H_
 #define GARNET_BIN_TRACE_APP_H_
 
-#include <functional>
 #include <map>
 #include <memory>
 #include <string>
diff --git a/bin/trace/command.h b/bin/trace/command.h
index 2c7e25f..c18b203 100644
--- a/bin/trace/command.h
+++ b/bin/trace/command.h
@@ -5,17 +5,16 @@
 #ifndef GARNET_BIN_TRACE_COMMAND_H_
 #define GARNET_BIN_TRACE_COMMAND_H_
 
-#include <functional>
 #include <iosfwd>
 #include <map>
 #include <memory>
 #include <string>
 
+#include <lib/fit/function.h>
 #include <tracing/cpp/fidl.h>
 
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/command_line.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
 namespace tracing {
@@ -24,10 +23,10 @@
  public:
   // OnDoneCallback is the callback type invoked when a command finished
   // running. It takes as argument the return code to exit the process with.
-  using OnDoneCallback = std::function<void(int32_t)>;
+  using OnDoneCallback = fit::function<void(int32_t)>;
   struct Info {
     using CommandFactory =
-        std::function<std::unique_ptr<Command>(fuchsia::sys::StartupContext*)>;
+        fit::function<std::unique_ptr<Command>(fuchsia::sys::StartupContext*)>;
 
     CommandFactory factory;
     std::string name;
diff --git a/bin/trace/commands/record.cc b/bin/trace/commands/record.cc
index cfd1fb9..7646f53 100644
--- a/bin/trace/commands/record.cc
+++ b/bin/trace/commands/record.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fdio/spawn.h>
+#include <lib/fdio/spawn.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
 #include <zx/time.h>
diff --git a/bin/trace/tracer.cc b/bin/trace/tracer.cc
index 1395565..da0b817 100644
--- a/bin/trace/tracer.cc
+++ b/bin/trace/tracer.cc
@@ -35,8 +35,8 @@
 void Tracer::Start(TraceOptions options,
                    RecordConsumer record_consumer,
                    ErrorHandler error_handler,
-                   fxl::Closure start_callback,
-                   fxl::Closure done_callback) {
+                   fit::closure start_callback,
+                   fit::closure done_callback) {
   FXL_DCHECK(state_ == State::kStopped);
 
   state_ = State::kStarted;
diff --git a/bin/trace/tracer.h b/bin/trace/tracer.h
index 3a9bc8d..6ec428a 100644
--- a/bin/trace/tracer.h
+++ b/bin/trace/tracer.h
@@ -5,16 +5,15 @@
 #ifndef GARNET_BIN_TRACE_TRACER_H_
 #define GARNET_BIN_TRACE_TRACER_H_
 
-#include <functional>
 #include <string>
 #include <vector>
 
 #include <tracing/cpp/fidl.h>
 #include <lib/async/cpp/wait.h>
+#include <lib/fit/function.h>
 #include <lib/zx/socket.h>
 #include <trace-reader/reader.h>
 
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
 namespace tracing {
@@ -34,8 +33,8 @@
   void Start(TraceOptions options,
              RecordConsumer record_consumer,
              ErrorHandler error_handler,
-             fxl::Closure start_callback,
-             fxl::Closure done_callback);
+             fit::closure start_callback,
+             fit::closure done_callback);
 
   // Stops the trace.
   // Does nothing if not started or if already stopping.
@@ -57,8 +56,8 @@
   enum class State { kStopped, kStarted, kStopping };
 
   State state_ = State::kStopped;
-  fxl::Closure start_callback_;
-  fxl::Closure done_callback_;
+  fit::closure start_callback_;
+  fit::closure done_callback_;
   zx::socket socket_;
   async_t* async_;
   async::WaitMethod<Tracer, &Tracer::OnHandleReady> wait_;
diff --git a/bin/trace_manager/BUILD.gn b/bin/trace_manager/BUILD.gn
index 3d7544b..ed67953 100644
--- a/bin/trace_manager/BUILD.gn
+++ b/bin/trace_manager/BUILD.gn
@@ -22,6 +22,7 @@
     "tracee.cc",
     "tracee.h",
   ]
+
   deps = [
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fxl",
@@ -31,6 +32,10 @@
     "//zircon/public/lib/async-loop-cpp",
     "//zircon/public/lib/trace-provider",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
 
 package("trace_manager") {
diff --git a/bin/trace_manager/trace_session.cc b/bin/trace_manager/trace_session.cc
index f4deb05..3064e65 100644
--- a/bin/trace_manager/trace_session.cc
+++ b/bin/trace_manager/trace_session.cc
@@ -14,7 +14,7 @@
 
 TraceSession::TraceSession(zx::socket destination,
                            fidl::VectorPtr<fidl::StringPtr> categories,
-                           size_t trace_buffer_size, fxl::Closure abort_handler)
+                           size_t trace_buffer_size, fit::closure abort_handler)
     : destination_(std::move(destination)),
       categories_(std::move(categories)),
       trace_buffer_size_(trace_buffer_size),
@@ -27,7 +27,7 @@
   destination_.reset();
 }
 
-void TraceSession::WaitForProvidersToStart(fxl::Closure callback,
+void TraceSession::WaitForProvidersToStart(fit::closure callback,
                                            zx::duration timeout) {
   start_callback_ = std::move(callback);
   session_start_timeout_.PostDelayed(async_get_default(), timeout);
@@ -67,7 +67,7 @@
   FinishProvider(bundle);
 }
 
-void TraceSession::Stop(fxl::Closure done_callback, zx::duration timeout) {
+void TraceSession::Stop(fit::closure done_callback, zx::duration timeout) {
   if (!(state_ == State::kReady || state_ == State::kStarted))
     return;
 
diff --git a/bin/trace_manager/trace_session.h b/bin/trace_manager/trace_session.h
index 0091295..fef2f4f 100644
--- a/bin/trace_manager/trace_session.h
+++ b/bin/trace_manager/trace_session.h
@@ -5,13 +5,13 @@
 #ifndef GARNET_BIN_TRACE_MANAGER_TRACE_SESSION_H_
 #define GARNET_BIN_TRACE_MANAGER_TRACE_SESSION_H_
 
-#include <functional>
 #include <iosfwd>
 #include <list>
 #include <vector>
 
 #include <fuchsia/tracelink/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
+#include <lib/fit/function.h>
 #include <lib/zx/socket.h>
 #include <lib/zx/time.h>
 #include <lib/zx/vmo.h>
@@ -20,7 +20,6 @@
 #include "garnet/bin/trace_manager/tracee.h"
 #include "lib/fidl/cpp/string.h"
 #include "lib/fidl/cpp/vector.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_counted.h"
 #include "lib/fxl/memory/ref_ptr.h"
@@ -41,14 +40,14 @@
   // unrecoverable errors that render the session dead.
   explicit TraceSession(zx::socket destination,
                         fidl::VectorPtr<fidl::StringPtr> categories,
-                        size_t trace_buffer_size, fxl::Closure abort_handler);
+                        size_t trace_buffer_size, fit::closure abort_handler);
   // Frees all allocated resources and closes the outgoing
   // connection.
   ~TraceSession();
 
   // Invokes |callback| when all providers in this session have acknowledged
   // the start request, or after |timeout| has elapsed.
-  void WaitForProvidersToStart(fxl::Closure callback, zx::duration timeout);
+  void WaitForProvidersToStart(fit::closure callback, zx::duration timeout);
 
   // Starts |provider| and adds it to this session.
   void AddProvider(TraceProviderBundle* provider);
@@ -59,7 +58,7 @@
   //
   // If stopping providers takes longer than |timeout|, we forcefully
   // shutdown operations and invoke |done_callback|.
-  void Stop(fxl::Closure done_callback, zx::duration timeout);
+  void Stop(fit::closure done_callback, zx::duration timeout);
 
  private:
   enum class State { kReady, kStarted, kStopping, kStopped };
@@ -89,9 +88,9 @@
       session_start_timeout_{this};
   async::TaskMethod<TraceSession, &TraceSession::SessionFinalizeTimeout>
       session_finalize_timeout_{this};
-  fxl::Closure start_callback_;
-  fxl::Closure done_callback_;
-  fxl::Closure abort_handler_;
+  fit::closure start_callback_;
+  fit::closure done_callback_;
+  fit::closure abort_handler_;
 
   fxl::WeakPtrFactory<TraceSession> weak_ptr_factory_;
   FXL_DISALLOW_COPY_AND_ASSIGN(TraceSession);
diff --git a/bin/trace_manager/tracee.cc b/bin/trace_manager/tracee.cc
index b33dd64..31c606f 100644
--- a/bin/trace_manager/tracee.cc
+++ b/bin/trace_manager/tracee.cc
@@ -72,8 +72,8 @@
 
 bool Tracee::Start(size_t buffer_size,
                    fidl::VectorPtr<fidl::StringPtr> categories,
-                   fxl::Closure started_callback,
-                   fxl::Closure stopped_callback) {
+                   fit::closure started_callback,
+                   fit::closure stopped_callback) {
   FXL_DCHECK(state_ == State::kReady);
   FXL_DCHECK(!buffer_vmo_);
   FXL_DCHECK(started_callback);
@@ -168,7 +168,7 @@
     // The provider should only be signalling us when it has finished startup.
     if (state_ == State::kStartPending) {
       TransitionToState(State::kStarted);
-      fxl::Closure started_callback = std::move(started_callback_);
+      fit::closure started_callback = std::move(started_callback_);
       FXL_DCHECK(started_callback);
       started_callback();
     } else {
@@ -198,7 +198,7 @@
     wait_.set_object(ZX_HANDLE_INVALID);
     async_ = nullptr;
     TransitionToState(State::kStopped);
-    fxl::Closure stopped_callback = std::move(stopped_callback_);
+    fit::closure stopped_callback = std::move(stopped_callback_);
     FXL_DCHECK(stopped_callback);
     stopped_callback();
     return;
diff --git a/bin/trace_manager/tracee.h b/bin/trace_manager/tracee.h
index 666c304..5432aaa 100644
--- a/bin/trace_manager/tracee.h
+++ b/bin/trace_manager/tracee.h
@@ -6,16 +6,15 @@
 #define GARNET_BIN_TRACE_MANAGER_TRACEE_H_
 
 #include <lib/async/cpp/wait.h>
+#include <lib/fit/function.h>
 #include <lib/zx/socket.h>
 #include <lib/zx/vmo.h>
 
-#include <functional>
 #include <iosfwd>
 
 #include "garnet/bin/trace_manager/trace_provider_bundle.h"
 #include "lib/fidl/cpp/string.h"
 #include "lib/fidl/cpp/vector.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/weak_ptr.h"
 
@@ -53,8 +52,8 @@
   bool operator==(TraceProviderBundle* bundle) const;
   bool Start(size_t buffer_size,
              fidl::VectorPtr<fidl::StringPtr> categories,
-             fxl::Closure started_callback,
-             fxl::Closure stopped_callback);
+             fit::closure started_callback,
+             fit::closure stopped_callback);
   void Stop();
   TransferStatus TransferRecords(const zx::socket& socket) const;
 
@@ -78,8 +77,8 @@
   zx::vmo buffer_vmo_;
   size_t buffer_vmo_size_ = 0u;
   zx::eventpair fence_;
-  fxl::Closure started_callback_;
-  fxl::Closure stopped_callback_;
+  fit::closure started_callback_;
+  fit::closure stopped_callback_;
   async_t* async_ = nullptr;
   async::WaitMethod<Tracee, &Tracee::OnHandleReady> wait_;
   bool buffer_overflow_ = false;
diff --git a/bin/tts/BUILD.gn b/bin/tts/BUILD.gn
index b6ee5f3..81d5b67 100644
--- a/bin/tts/BUILD.gn
+++ b/bin/tts/BUILD.gn
@@ -20,6 +20,7 @@
     "//garnet/public/lib/tts/fidl",
     "//third_party/flite",
     "//zircon/public/lib/zx",
+    "//zircon/public/lib/vmo-utils",
   ]
 }
 
diff --git a/bin/tts/tts_service_impl.cc b/bin/tts/tts_service_impl.cc
index b07b5d0..ef2fb0f 100644
--- a/bin/tts/tts_service_impl.cc
+++ b/bin/tts/tts_service_impl.cc
@@ -15,8 +15,8 @@
     : startup_context_(std::move(startup_context)) {
   FXL_DCHECK(startup_context_);
 
-  startup_context_->outgoing().AddPublicService<TtsService>(
-      [this](fidl::InterfaceRequest<TtsService> request) {
+  startup_context_->outgoing().AddPublicService<fuchsia::tts::TtsService>(
+      [this](fidl::InterfaceRequest<fuchsia::tts::TtsService> request) {
         clients_.insert(new Client(this, std::move(request)));
       });
 
@@ -67,7 +67,7 @@
     return;
   }
 
-  fxl::Closure on_speak_complete = [this, speaker, token,
+  fit::closure on_speak_complete = [this, speaker, token,
                                     say_callback = std::move(cbk)]() {
     OnSpeakComplete(std::move(speaker), token, std::move(say_callback));
   };
diff --git a/bin/tts/tts_service_impl.h b/bin/tts/tts_service_impl.h
index a83abea..cedf5a7 100644
--- a/bin/tts/tts_service_impl.h
+++ b/bin/tts/tts_service_impl.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <set>
 
-#include <tts/cpp/fidl.h>
+#include <fuchsia/tts/cpp/fidl.h>
 
 #include "lib/app/cpp/startup_context.h"
 
@@ -24,9 +24,10 @@
   zx_status_t Init();
 
  private:
-  class Client : public TtsService {
+  class Client : public fuchsia::tts::TtsService {
    public:
-    Client(TtsServiceImpl* owner, fidl::InterfaceRequest<TtsService> request);
+    Client(TtsServiceImpl* owner,
+           fidl::InterfaceRequest<fuchsia::tts::TtsService> request);
     ~Client();
 
     void Shutdown();
diff --git a/bin/tts/tts_speaker.cc b/bin/tts/tts_speaker.cc
index 7d2b58c..1940d27 100644
--- a/bin/tts/tts_speaker.cc
+++ b/bin/tts/tts_speaker.cc
@@ -14,7 +14,8 @@
 
 static constexpr uint32_t kFliteChannelCount = 1;
 static constexpr uint32_t kFliteFrameRate = 16000;
-static constexpr auto kFliteSampleFormat = media::AudioSampleFormat::SIGNED_16;
+static constexpr auto kFliteSampleFormat =
+    fuchsia::media::AudioSampleFormat::SIGNED_16;
 static constexpr uint32_t kFliteBytesPerFrame = 2;
 static constexpr uint32_t kLowWaterBytes =
     (kFliteFrameRate * kLowWaterMsec * kFliteBytesPerFrame) / 1000;
@@ -25,7 +26,7 @@
 }
 
 zx_status_t TtsSpeaker::Speak(fidl::StringPtr words,
-                              const fxl::Closure& speak_complete_cbk) {
+                              fit::closure speak_complete_cbk) {
   words_ = std::move(words);
   speak_complete_cbk_ = std::move(speak_complete_cbk);
 
@@ -62,11 +63,12 @@
 
   FXL_DCHECK(startup_context != nullptr);
   auto audio_server =
-      startup_context->ConnectToEnvironmentService<media::AudioServer>();
+      startup_context
+          ->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   audio_server->CreateRendererV2(audio_renderer_.NewRequest());
 
-  media::AudioPcmFormat format;
+  fuchsia::media::AudioPcmFormat format;
   format.sample_format = kFliteSampleFormat;
   format.channels = kFliteChannelCount;
   format.frames_per_second = kFliteFrameRate;
@@ -126,7 +128,7 @@
       todo = bytes_till_low_water;
     }
 
-    media::AudioPacket pkt;
+    fuchsia::media::AudioPacket pkt;
     pkt.payload_offset = tx_ptr_;
     pkt.payload_size = todo;
 
@@ -139,10 +141,10 @@
 
     if (eos && (todo == bytes_to_send)) {
       audio_renderer_->SendPacket(
-          std::move(pkt),
-          [speak_complete_cbk = std::move(speak_complete_cbk_)]() {
+          std::move(pkt), fxl::MakeCopyable([speak_complete_cbk = std::move(
+                                                 speak_complete_cbk_)]() {
             speak_complete_cbk();
-          });
+          }));
     } else if (todo == bytes_till_low_water) {
       audio_renderer_->SendPacket(
           std::move(pkt), [thiz = shared_from_this(), new_rd_pos = tx_ptr_]() {
@@ -161,7 +163,8 @@
   }
 
   if (!clock_started_) {
-    audio_renderer_->PlayNoReply(::media::kNoTimestamp, ::media::kNoTimestamp);
+    audio_renderer_->PlayNoReply(fuchsia::media::kNoTimestamp,
+                                 fuchsia::media::kNoTimestamp);
     clock_started_ = true;
   }
 }
diff --git a/bin/tts/tts_speaker.h b/bin/tts/tts_speaker.h
index 9d84183..433eda1 100644
--- a/bin/tts/tts_speaker.h
+++ b/bin/tts/tts_speaker.h
@@ -8,15 +8,15 @@
 #include <mutex>
 #include <thread>
 
-#include <fbl/vmo_mapper.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <fuchsia/tts/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
-#include <media/cpp/fidl.h>
-#include <tts/cpp/fidl.h>
+#include <lib/vmo-utils/vmo_mapper.h>
+#include <lib/fit/function.h>
 #include <zircon/types.h>
 
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/string.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/synchronization/thread_annotations.h"
 #include "third_party/flite/include/flite_fuchsia.h"
@@ -31,8 +31,7 @@
   zx_status_t Init(
       const std::unique_ptr<fuchsia::sys::StartupContext>& startup_context);
 
-  zx_status_t Speak(fidl::StringPtr words,
-                    const fxl::Closure& speak_complete_cbk);
+  zx_status_t Speak(fidl::StringPtr words, fit::closure speak_complete_cbk);
   void Shutdown();
 
  private:
@@ -71,8 +70,8 @@
   async::Loop engine_loop_;
   async_t* master_async_;
 
-  media::AudioRenderer2Ptr audio_renderer_;
-  fbl::VmoMapper shared_buf_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer_;
+  vmo_utils::VmoMapper shared_buf_;
 
   std::mutex ring_buffer_lock_;
   uint64_t wr_ptr_ FXL_GUARDED_BY(ring_buffer_lock_) = 0;
@@ -81,7 +80,7 @@
   zx::event wakeup_event_;
 
   fidl::StringPtr words_;
-  fxl::Closure speak_complete_cbk_;
+  fit::closure speak_complete_cbk_;
   std::atomic<bool> abort_playback_;
   std::atomic<bool> synthesis_complete_;
 
diff --git a/bin/ui/input_reader/input_interpreter.h b/bin/ui/input_reader/input_interpreter.h
index f248626..75b822a 100644
--- a/bin/ui/input_reader/input_interpreter.h
+++ b/bin/ui/input_reader/input_interpreter.h
@@ -36,8 +36,6 @@
     kTouchscreen,
   };
 
-  using OnReportCallback = std::function<void(ReportType type)>;
-
   static std::unique_ptr<InputInterpreter> Open(
       int dirfd, std::string filename,
       fuchsia::ui::input::InputDeviceRegistry* registry);
diff --git a/bin/ui/presentation_mode/BUILD.gn b/bin/ui/presentation_mode/BUILD.gn
index 578123f..4ea2308 100644
--- a/bin/ui/presentation_mode/BUILD.gn
+++ b/bin/ui/presentation_mode/BUILD.gn
@@ -17,6 +17,6 @@
 
   public_deps = [
     "//garnet/public/lib/ui/input/fidl",
-    "//garnet/public/lib/ui/presentation/fidl",
+    "//garnet/public/lib/ui/policy/fidl",
   ]
 }
diff --git a/bin/ui/presentation_mode/detector.cc b/bin/ui/presentation_mode/detector.cc
index a3af5f3..c8a41e7 100644
--- a/bin/ui/presentation_mode/detector.cc
+++ b/bin/ui/presentation_mode/detector.cc
@@ -19,7 +19,7 @@
   FXL_CHECK(history_size > 0);
 }
 
-std::pair<bool, presentation::PresentationMode> Detector::Update(
+std::pair<bool, fuchsia::ui::policy::PresentationMode> Detector::Update(
     const fuchsia::ui::input::SensorDescriptor& sensor,
     fuchsia::ui::input::InputReport event) {
   FXL_CHECK(sensor.type == fuchsia::ui::input::SensorType::ACCELEROMETER);
@@ -41,21 +41,21 @@
   AccelerometerData base_avg = base_accelerometer_->Average();
   AccelerometerData lid_avg = lid_accelerometer_->Average();
 
-  std::pair<bool, presentation::PresentationMode> result;
+  std::pair<bool, fuchsia::ui::policy::PresentationMode> result;
   result.first = false;
 
   if (base_avg[2] > kZPosLimit && lid_avg[2] < kZNegLimit) {
     result.first = true;
-    result.second = presentation::PresentationMode::CLOSED;
+    result.second = fuchsia::ui::policy::PresentationMode::CLOSED;
   } else if (base_avg[2] > kZPosLimit && lid_avg[1] > kYPosLimit) {
     result.first = true;
-    result.second = presentation::PresentationMode::LAPTOP;
+    result.second = fuchsia::ui::policy::PresentationMode::LAPTOP;
   } else if (base_avg[2] < kZNegLimit && lid_avg[2] > kZPosLimit) {
     result.first = true;
-    result.second = presentation::PresentationMode::TABLET;
+    result.second = fuchsia::ui::policy::PresentationMode::TABLET;
   } else if (base_avg[1] > kYPosLimit && lid_avg[1] < kYNegLimit) {
     result.first = true;
-    result.second = presentation::PresentationMode::TENT;
+    result.second = fuchsia::ui::policy::PresentationMode::TENT;
   }
 
   if (result.first)
diff --git a/bin/ui/presentation_mode/detector.h b/bin/ui/presentation_mode/detector.h
index 0cc3c36..f40f972 100644
--- a/bin/ui/presentation_mode/detector.h
+++ b/bin/ui/presentation_mode/detector.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include <fuchsia/ui/input/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 
 namespace presentation_mode {
 
@@ -41,7 +41,7 @@
 
   // Return <true,mode> if a mode was recognized and stable.
   // Otherwise return <false,_>, where the second value is undefined.
-  std::pair<bool, presentation::PresentationMode> Update(
+  std::pair<bool, fuchsia::ui::policy::PresentationMode> Update(
       const fuchsia::ui::input::SensorDescriptor& sensor,
       fuchsia::ui::input::InputReport event);
 
diff --git a/bin/ui/presentation_mode/tests/detector_unittest.cc b/bin/ui/presentation_mode/tests/detector_unittest.cc
index 6ded9f5..f216c61 100644
--- a/bin/ui/presentation_mode/tests/detector_unittest.cc
+++ b/bin/ui/presentation_mode/tests/detector_unittest.cc
@@ -82,14 +82,14 @@
   Detector detector(/*history*/ 2);
 
   fuchsia::ui::input::InputReport base_report = CreateVector(0, 0, kMaxVal);
-  std::pair<bool, presentation::PresentationMode> result =
+  std::pair<bool, fuchsia::ui::policy::PresentationMode> result =
       detector.Update(kBaseSensor, std::move(base_report));
   EXPECT_FALSE(result.first);
 
   fuchsia::ui::input::InputReport lid_report = CreateVector(0, 0, kMinVal);
   result = detector.Update(kLidSensor, std::move(lid_report));
   EXPECT_TRUE(result.first);
-  EXPECT_EQ(result.second, presentation::PresentationMode::CLOSED);
+  EXPECT_EQ(result.second, fuchsia::ui::policy::PresentationMode::CLOSED);
 
   fuchsia::ui::input::InputReport base_shift = CreateVector(0, 0, kMinVal);
   result = detector.Update(kBaseSensor, std::move(base_shift));
@@ -100,14 +100,14 @@
   Detector detector(/*history*/ 2);
 
   fuchsia::ui::input::InputReport base_report = CreateVector(0, 0, kMaxVal);
-  std::pair<bool, presentation::PresentationMode> result =
+  std::pair<bool, fuchsia::ui::policy::PresentationMode> result =
       detector.Update(kBaseSensor, std::move(base_report));
   EXPECT_FALSE(result.first);
 
   fuchsia::ui::input::InputReport lid_report = CreateVector(0, kMaxVal, 0);
   result = detector.Update(kLidSensor, std::move(lid_report));
   EXPECT_TRUE(result.first);
-  EXPECT_EQ(result.second, presentation::PresentationMode::LAPTOP);
+  EXPECT_EQ(result.second, fuchsia::ui::policy::PresentationMode::LAPTOP);
 
   fuchsia::ui::input::InputReport base_shift = CreateVector(0, 0, kMinVal);
   result = detector.Update(kBaseSensor, std::move(base_shift));
@@ -118,14 +118,14 @@
   Detector detector(/*history*/ 2);
 
   fuchsia::ui::input::InputReport base_report = CreateVector(0, 0, kMinVal);
-  std::pair<bool, presentation::PresentationMode> result =
+  std::pair<bool, fuchsia::ui::policy::PresentationMode> result =
       detector.Update(kBaseSensor, std::move(base_report));
   EXPECT_FALSE(result.first);
 
   fuchsia::ui::input::InputReport lid_report = CreateVector(0, 0, kMaxVal);
   result = detector.Update(kLidSensor, std::move(lid_report));
   EXPECT_TRUE(result.first);
-  EXPECT_EQ(result.second, presentation::PresentationMode::TABLET);
+  EXPECT_EQ(result.second, fuchsia::ui::policy::PresentationMode::TABLET);
 
   fuchsia::ui::input::InputReport base_shift = CreateVector(0, 0, kMaxVal);
   result = detector.Update(kBaseSensor, std::move(base_shift));
@@ -136,14 +136,14 @@
   Detector detector(/*history*/ 2);
 
   fuchsia::ui::input::InputReport base_report = CreateVector(0, kMaxVal, 0);
-  std::pair<bool, presentation::PresentationMode> result =
+  std::pair<bool, fuchsia::ui::policy::PresentationMode> result =
       detector.Update(kBaseSensor, std::move(base_report));
   EXPECT_FALSE(result.first);
 
   fuchsia::ui::input::InputReport lid_report = CreateVector(0, kMinVal, 0);
   result = detector.Update(kLidSensor, std::move(lid_report));
   EXPECT_TRUE(result.first);
-  EXPECT_EQ(result.second, presentation::PresentationMode::TENT);
+  EXPECT_EQ(result.second, fuchsia::ui::policy::PresentationMode::TENT);
 
   fuchsia::ui::input::InputReport base_shift = CreateVector(0, kMinVal, 0);
   result = detector.Update(kBaseSensor, std::move(base_shift));
diff --git a/bin/ui/print_input/main.cc b/bin/ui/print_input/main.cc
index 9d06166..8f939db 100644
--- a/bin/ui/print_input/main.cc
+++ b/bin/ui/print_input/main.cc
@@ -68,9 +68,9 @@
     std::unique_ptr<mozart::DeviceState> state =
         std::make_unique<mozart::DeviceState>(
             input_device->id(), input_device->descriptor(),
-            [this](fuchsia::ui::input::InputEvent event) {
+            mozart::OnEventCallback([this](fuchsia::ui::input::InputEvent event) {
               OnEvent(std::move(event));
-            });
+            }));
     mozart::DeviceState* state_ptr = state.get();
     auto device_pair =
         std::make_pair(std::move(input_device), std::move(state));
diff --git a/bin/ui/root_presenter/BUILD.gn b/bin/ui/root_presenter/BUILD.gn
index 4da167b..0d8b60c 100644
--- a/bin/ui/root_presenter/BUILD.gn
+++ b/bin/ui/root_presenter/BUILD.gn
@@ -39,11 +39,12 @@
     "//garnet/public/lib/ui/input",
     "//garnet/public/lib/ui/input/cpp",
     "//garnet/public/lib/ui/input/fidl",
-    "//garnet/public/lib/ui/presentation/fidl",
+    "//garnet/public/lib/ui/policy/fidl",
     "//garnet/public/lib/ui/scenic:client",
     "//garnet/public/lib/ui/views/cpp",
     "//garnet/public/lib/ui/views/fidl:v1",
     "//zircon/public/lib/async-loop-cpp",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/hid",
     "//zircon/public/lib/trace-provider",
   ]
diff --git a/bin/ui/root_presenter/app.cc b/bin/ui/root_presenter/app.cc
index d3876c0..3fe489d 100644
--- a/bin/ui/root_presenter/app.cc
+++ b/bin/ui/root_presenter/app.cc
@@ -10,6 +10,7 @@
 #include "lib/app/cpp/connect.h"
 #include "lib/fidl/cpp/clone.h"
 #include "lib/fxl/logging.h"
+#include "lib/fxl/functional/make_copyable.h"
 #include "lib/ui/input/cpp/formatting.h"
 
 namespace root_presenter {
@@ -21,8 +22,8 @@
 
   input_reader_.Start();
 
-  startup_context_->outgoing().AddPublicService<presentation::Presenter>(
-      [this](fidl::InterfaceRequest<presentation::Presenter> request) {
+  startup_context_->outgoing().AddPublicService<fuchsia::ui::policy::Presenter>(
+      [this](fidl::InterfaceRequest<fuchsia::ui::policy::Presenter> request) {
         presenter_bindings_.AddBinding(this, std::move(request));
       });
 
@@ -39,7 +40,7 @@
 void App::Present(
     fidl::InterfaceHandle<::fuchsia::ui::views_v1_token::ViewOwner>
         view_owner_handle,
-    fidl::InterfaceRequest<presentation::Presentation> presentation_request) {
+    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation_request) {
   InitializeServices();
 
   auto presentation = std::make_unique<Presentation>(
@@ -82,8 +83,9 @@
       };
 
   presentation->Present(view_owner_handle.Bind(),
-                        std::move(presentation_request), yield_callback,
-                        shutdown_callback);
+                        std::move(presentation_request),
+                        fxl::MakeCopyable(std::move(yield_callback)),
+                        fxl::MakeCopyable(std::move(shutdown_callback)));
 
   for (auto& it : devices_by_id_) {
     presentation->OnDeviceAdded(it.second.get());
diff --git a/bin/ui/root_presenter/app.h b/bin/ui/root_presenter/app.h
index 11f3c3b..34df262 100644
--- a/bin/ui/root_presenter/app.h
+++ b/bin/ui/root_presenter/app.h
@@ -11,7 +11,7 @@
 
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include "garnet/bin/ui/input_reader/input_reader.h"
 #include "garnet/bin/ui/root_presenter/presentation.h"
 #include "lib/app/cpp/startup_context.h"
@@ -25,13 +25,13 @@
 
 class Presentation;
 
-// The presenter provides a |presentation::Presenter| service which displays
+// The presenter provides a |fuchsia::ui::policy::Presenter| service which displays
 // UI by attaching the provided view to the root of a new view tree
 // associated with a new renderer.
 //
 // Any number of view trees can be created, although multi-display support
 // and input routing is not fully supported (TODO).
-class App : public presentation::Presenter,
+class App : public fuchsia::ui::policy::Presenter,
             public fuchsia::ui::input::InputDeviceRegistry,
             public mozart::InputDeviceImpl::Listener {
  public:
@@ -47,7 +47,7 @@
   // |Presenter|:
   void Present(fidl::InterfaceHandle<::fuchsia::ui::views_v1_token::ViewOwner>
                    view_owner,
-               fidl::InterfaceRequest<presentation::Presentation>
+               fidl::InterfaceRequest<fuchsia::ui::policy::Presentation>
                    presentation_request) override;
 
   void HACK_SetRendererParams(
@@ -67,7 +67,7 @@
   void SwitchToPreviousPresentation();
 
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
-  fidl::BindingSet<presentation::Presenter> presenter_bindings_;
+  fidl::BindingSet<fuchsia::ui::policy::Presenter> presenter_bindings_;
   fidl::BindingSet<fuchsia::ui::input::InputDeviceRegistry>
       input_receiver_bindings_;
   mozart::InputReader input_reader_;
diff --git a/bin/ui/root_presenter/display_usage_switcher.cc b/bin/ui/root_presenter/display_usage_switcher.cc
index 28c3b51..ac6c6dd 100644
--- a/bin/ui/root_presenter/display_usage_switcher.cc
+++ b/bin/ui/root_presenter/display_usage_switcher.cc
@@ -15,25 +15,25 @@
 const uint32_t kGlobalShortcutKeyCodePoint = 61;  // '=' key
 const uint32_t kGlobalShortcutKeyHidUsage = 46;   // '=' key
 
-static const std::array<presentation::DisplayUsage, 5> kDisplayUsages = {
-    presentation::DisplayUsage::kHandheld, presentation::DisplayUsage::kClose,
-    presentation::DisplayUsage::kNear, presentation::DisplayUsage::kMidrange,
-    presentation::DisplayUsage::kFar};
+static const std::array<fuchsia::ui::policy::DisplayUsage, 5> kDisplayUsages = {
+    fuchsia::ui::policy::DisplayUsage::kHandheld, fuchsia::ui::policy::DisplayUsage::kClose,
+    fuchsia::ui::policy::DisplayUsage::kNear, fuchsia::ui::policy::DisplayUsage::kMidrange,
+    fuchsia::ui::policy::DisplayUsage::kFar};
 }  // namespace
 
-std::string GetDisplayUsageAsString(presentation::DisplayUsage usage) {
+std::string GetDisplayUsageAsString(fuchsia::ui::policy::DisplayUsage usage) {
   switch (usage) {
-    case presentation::DisplayUsage::kUnknown:
+    case fuchsia::ui::policy::DisplayUsage::kUnknown:
       return "kUnknown";
-    case presentation::DisplayUsage::kHandheld:
+    case fuchsia::ui::policy::DisplayUsage::kHandheld:
       return "kHandheld";
-    case presentation::DisplayUsage::kClose:
+    case fuchsia::ui::policy::DisplayUsage::kClose:
       return "kClose";
-    case presentation::DisplayUsage::kNear:
+    case fuchsia::ui::policy::DisplayUsage::kNear:
       return "kNear";
-    case presentation::DisplayUsage::kMidrange:
+    case fuchsia::ui::policy::DisplayUsage::kMidrange:
       return "kMidrange";
-    case presentation::DisplayUsage::kFar:
+    case fuchsia::ui::policy::DisplayUsage::kFar:
       return "kFar";
   }
 }
diff --git a/bin/ui/root_presenter/display_usage_switcher.h b/bin/ui/root_presenter/display_usage_switcher.h
index 8136c62..47d21bf 100644
--- a/bin/ui/root_presenter/display_usage_switcher.h
+++ b/bin/ui/root_presenter/display_usage_switcher.h
@@ -6,7 +6,7 @@
 #define GARNET_BIN_UI_ROOT_PRESENTER_DISPLAY_USAGE_SWITCHER_H_
 
 #include <fuchsia/ui/input/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include "lib/fxl/macros.h"
 #include "lib/ui/scenic/client/resources.h"
 
@@ -16,7 +16,7 @@
 
 class Presentation;
 
-std::string GetDisplayUsageAsString(presentation::DisplayUsage usage);
+std::string GetDisplayUsageAsString(fuchsia::ui::policy::DisplayUsage usage);
 
 // This class hooks into Presenter to provide the following behavior: when
 // Alt-Equals is pressed, the current display usage is toggled.
diff --git a/bin/ui/root_presenter/displays/display_configuration.cc b/bin/ui/root_presenter/displays/display_configuration.cc
index d14eff1..d5c099d 100644
--- a/bin/ui/root_presenter/displays/display_configuration.cc
+++ b/bin/ui/root_presenter/displays/display_configuration.cc
@@ -12,7 +12,7 @@
 void LogDisplayMetrics(const DisplayMetrics& metrics);
 
 float LookupPixelDensityForDisplay(uint32_t width_in_px, uint32_t height_in_px);
-presentation::DisplayUsage LookupDisplayUsageForDisplay(uint32_t width_in_px,
+fuchsia::ui::policy::DisplayUsage LookupDisplayUsageForDisplay(uint32_t width_in_px,
                                                         uint32_t height_in_px);
 
 void InitializeModelForDisplay(uint32_t width_in_px, uint32_t height_in_px,
@@ -31,7 +31,7 @@
 
   FXL_DCHECK(model->display_info().density_in_px_per_mm != 0.f);
   FXL_DCHECK(model->environment_info().usage !=
-             presentation::DisplayUsage::kUnknown);
+             fuchsia::ui::policy::DisplayUsage::kUnknown);
 }
 
 // Returns density_in_px_per_mm. This will be replaced by something that
@@ -60,22 +60,22 @@
   }
 }
 
-presentation::DisplayUsage LookupDisplayUsageForDisplay(uint32_t width_in_px,
+fuchsia::ui::policy::DisplayUsage LookupDisplayUsageForDisplay(uint32_t width_in_px,
                                                         uint32_t height_in_px) {
   // TODO(MZ-16): Need to have a database of devices and a more robust way
   // of identifying and classifying them.
   if (width_in_px == 2160 && height_in_px == 1440) {
     // Assume that the device is an Acer Switch 12 Alpha.
-    return presentation::DisplayUsage::kClose;
+    return fuchsia::ui::policy::DisplayUsage::kClose;
   } else if (width_in_px == 2400 && height_in_px == 1600) {
     // Assume that the device is a Google Pixelbook.
-    return presentation::DisplayUsage::kClose;
+    return fuchsia::ui::policy::DisplayUsage::kClose;
   } else if (width_in_px == 3840 && height_in_px == 2160) {
     // Assume the display is a 24in 4K monitor.
-    return presentation::DisplayUsage::kNear;
+    return fuchsia::ui::policy::DisplayUsage::kNear;
   } else {
     // TODO(MZ-384): Don't lie.
-    return presentation::DisplayUsage::kClose;
+    return fuchsia::ui::policy::DisplayUsage::kClose;
   }
 }
 
diff --git a/bin/ui/root_presenter/displays/display_model.cc b/bin/ui/root_presenter/displays/display_model.cc
index b647eb1..26da250 100644
--- a/bin/ui/root_presenter/displays/display_model.cc
+++ b/bin/ui/root_presenter/displays/display_model.cc
@@ -38,20 +38,20 @@
 constexpr float kIdealPipVisualAngleDegrees = 0.0255;
 
 constexpr float GetDefaultViewingDistanceInMm(
-    presentation::DisplayUsage usage) {
+    fuchsia::ui::policy::DisplayUsage usage) {
   switch (usage) {
-    case presentation::DisplayUsage::kHandheld:
+    case fuchsia::ui::policy::DisplayUsage::kHandheld:
       return 360.f;
-    case presentation::DisplayUsage::kClose:
+    case fuchsia::ui::policy::DisplayUsage::kClose:
       return 500.f;
-    case presentation::DisplayUsage::kNear:
+    case fuchsia::ui::policy::DisplayUsage::kNear:
       return 720.f;
-    case presentation::DisplayUsage::kMidrange:
+    case fuchsia::ui::policy::DisplayUsage::kMidrange:
       return 1200.f;
-    case presentation::DisplayUsage::kFar:
+    case fuchsia::ui::policy::DisplayUsage::kFar:
       return 3000.f;
     default:
-    case presentation::DisplayUsage::kUnknown:
+    case fuchsia::ui::policy::DisplayUsage::kUnknown:
       return 0.f;
   }
 }
diff --git a/bin/ui/root_presenter/displays/display_model.h b/bin/ui/root_presenter/displays/display_model.h
index 23afda1..9501e18 100644
--- a/bin/ui/root_presenter/displays/display_model.h
+++ b/bin/ui/root_presenter/displays/display_model.h
@@ -9,7 +9,7 @@
 
 #include "garnet/bin/ui/root_presenter/displays/display_metrics.h"
 
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include "lib/fxl/macros.h"
 
 namespace root_presenter {
@@ -50,7 +50,7 @@
   struct EnvironmentInfo {
     // The intended usage of the display.
     // Value is |kUnknown| if unknown.
-    presentation::DisplayUsage usage = presentation::DisplayUsage::kUnknown;
+    fuchsia::ui::policy::DisplayUsage usage = fuchsia::ui::policy::DisplayUsage::kUnknown;
 
     // The nominal apparent viewing distance in millimeters.
     // Value is 0.0 if unknown.
diff --git a/bin/ui/root_presenter/presentation.cc b/bin/ui/root_presenter/presentation.cc
index 2df06fd..25bfdcd 100644
--- a/bin/ui/root_presenter/presentation.cc
+++ b/bin/ui/root_presenter/presentation.cc
@@ -112,7 +112,8 @@
 
 void Presentation::Present(
     ::fuchsia::ui::views_v1_token::ViewOwnerPtr view_owner,
-    fidl::InterfaceRequest<presentation::Presentation> presentation_request,
+    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation>
+        presentation_request,
     YieldCallback yield_callback, ShutdownCallback shutdown_callback) {
   FXL_DCHECK(view_owner);
   FXL_DCHECK(!display_model_initialized_);
@@ -133,7 +134,8 @@
 
 void Presentation::CreateViewTree(
     ::fuchsia::ui::views_v1_token::ViewOwnerPtr view_owner,
-    fidl::InterfaceRequest<presentation::Presentation> presentation_request,
+    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation>
+        presentation_request,
     fuchsia::ui::gfx::DisplayInfo display_info) {
   if (presentation_request) {
     presentation_binding_.Bind(std::move(presentation_request));
@@ -174,7 +176,8 @@
   });
 
   // Create root view.
-  fidl::InterfaceHandle<::fuchsia::ui::views_v1_token::ViewOwner> root_view_owner;
+  fidl::InterfaceHandle<::fuchsia::ui::views_v1_token::ViewOwner>
+      root_view_owner;
   auto root_view_owner_request = root_view_owner.NewRequest();
   ::fuchsia::ui::views_v1::ViewListenerPtr root_view_listener;
   view_listener_binding_.Bind(root_view_listener.NewRequest());
@@ -197,8 +200,8 @@
   root_container_->SetListener(std::move(view_container_listener));
   root_container_->AddChild(kContentViewKey, std::move(view_owner),
                             std::move(content_view_host_import_token_));
-  root_container_->SetChildProperties(kContentViewKey,
-                                      ::fuchsia::ui::views_v1::ViewProperties::New());
+  root_container_->SetChildProperties(
+      kContentViewKey, ::fuchsia::ui::views_v1::ViewProperties::New());
 
   PresentScene();
 }
@@ -318,8 +321,8 @@
   return true;
 }
 
-void Presentation::SetDisplayUsage(presentation::DisplayUsage usage) {
-  presentation::DisplayUsage old_usage =
+void Presentation::SetDisplayUsage(fuchsia::ui::policy::DisplayUsage usage) {
+  fuchsia::ui::policy::DisplayUsage old_usage =
       display_model_simulated_.environment_info().usage;
   SetDisplayUsageWithoutApplyingChanges(usage);
   if (display_model_simulated_.environment_info().usage == old_usage) {
@@ -337,9 +340,9 @@
 }
 
 void Presentation::SetDisplayUsageWithoutApplyingChanges(
-    presentation::DisplayUsage usage) {
+    fuchsia::ui::policy::DisplayUsage usage) {
   display_model_simulated_.environment_info().usage =
-      (usage == presentation::DisplayUsage::kUnknown)
+      (usage == fuchsia::ui::policy::DisplayUsage::kUnknown)
           ? display_model_actual_.environment_info().usage
           : usage;
 }
@@ -362,13 +365,7 @@
   display_rotation_current_ = display_rotation_desired_;
 
   auto root_properties = ::fuchsia::ui::views_v1::ViewProperties::New();
-  root_properties->display_metrics = ::fuchsia::ui::views_v1::DisplayMetrics::New();
 
-  // TODO(MZ-411): Handle densities that differ in x and y.
-  FXL_DCHECK(display_metrics_.x_scale_in_px_per_pp() ==
-             display_metrics_.y_scale_in_px_per_pp());
-  root_properties->display_metrics->device_pixel_ratio =
-      display_metrics_.x_scale_in_px_per_pp();
   root_properties->view_layout = ::fuchsia::ui::views_v1::ViewLayout::New();
   root_properties->view_layout->size.width = display_metrics_.width_in_pp();
   root_properties->view_layout->size.height = display_metrics_.height_in_pp();
@@ -418,14 +415,14 @@
           OnSensorEvent(device_id, std::move(event));
         };
     state = std::make_unique<mozart::DeviceState>(
-        input_device->id(), input_device->descriptor(), callback);
+        input_device->id(), input_device->descriptor(), std::move(callback));
   } else {
     mozart::OnEventCallback callback =
         [this](fuchsia::ui::input::InputEvent event) {
           OnEvent(std::move(event));
         };
     state = std::make_unique<mozart::DeviceState>(
-        input_device->id(), input_device->descriptor(), callback);
+        input_device->id(), input_device->descriptor(), std::move(callback));
   }
 
   mozart::DeviceState* state_ptr = state.get();
@@ -471,9 +468,9 @@
 
 void Presentation::CaptureKeyboardEventHACK(
     fuchsia::ui::input::KeyboardEvent event_to_capture,
-    fidl::InterfaceHandle<presentation::KeyboardCaptureListenerHACK>
+    fidl::InterfaceHandle<fuchsia::ui::policy::KeyboardCaptureListenerHACK>
         listener_handle) {
-  presentation::KeyboardCaptureListenerHACKPtr listener;
+  fuchsia::ui::policy::KeyboardCaptureListenerHACKPtr listener;
   listener.Bind(std::move(listener_handle));
   // Auto-remove listeners if the interface closes.
   listener.set_error_handler([this, listener = listener.get()] {
@@ -491,9 +488,9 @@
 }
 
 void Presentation::CapturePointerEventsHACK(
-    fidl::InterfaceHandle<presentation::PointerCaptureListenerHACK>
+    fidl::InterfaceHandle<fuchsia::ui::policy::PointerCaptureListenerHACK>
         listener_handle) {
-  presentation::PointerCaptureListenerHACKPtr listener;
+  fuchsia::ui::policy::PointerCaptureListenerHACKPtr listener;
   listener.Bind(std::move(listener_handle));
   // Auto-remove listeners if the interface closes.
   listener.set_error_handler([this, listener = listener.get()] {
@@ -514,7 +511,8 @@
 }
 
 void Presentation::SetPresentationModeListener(
-    fidl::InterfaceHandle<presentation::PresentationModeListener> listener) {
+    fidl::InterfaceHandle<fuchsia::ui::policy::PresentationModeListener>
+        listener) {
   if (presentation_mode_listener_) {
     FXL_LOG(ERROR) << "Cannot listen to presentation mode; already listening.";
     return;
@@ -639,7 +637,7 @@
   if (presentation_mode_listener_) {
     const fuchsia::ui::input::SensorDescriptor* sensor_descriptor =
         device_states_by_id_[device_id].first->descriptor()->sensor.get();
-    std::pair<bool, presentation::PresentationMode> update =
+    std::pair<bool, fuchsia::ui::policy::PresentationMode> update =
         presentation_mode_detector_->Update(*sensor_descriptor,
                                             std::move(event));
     if (update.first && update.second != presentation_mode_) {
@@ -649,9 +647,9 @@
   }
 }
 
-void Presentation::OnChildAttached(uint32_t child_key,
-                                   ::fuchsia::ui::views_v1::ViewInfo child_view_info,
-                                   OnChildAttachedCallback callback) {
+void Presentation::OnChildAttached(
+    uint32_t child_key, ::fuchsia::ui::views_v1::ViewInfo child_view_info,
+    OnChildAttachedCallback callback) {
   if (kContentViewKey == child_key) {
     FXL_VLOG(1) << "OnChildAttached(content): child_view_info="
                 << child_view_info;
@@ -671,8 +669,9 @@
   callback();
 }
 
-void Presentation::OnPropertiesChanged(::fuchsia::ui::views_v1::ViewProperties properties,
-                                       OnPropertiesChangedCallback callback) {
+void Presentation::OnPropertiesChanged(
+    ::fuchsia::ui::views_v1::ViewProperties properties,
+    OnPropertiesChangedCallback callback) {
   // Nothing to do right now.
   callback();
 }
diff --git a/bin/ui/root_presenter/presentation.h b/bin/ui/root_presenter/presentation.h
index a38826e..cb6716e 100644
--- a/bin/ui/root_presenter/presentation.h
+++ b/bin/ui/root_presenter/presentation.h
@@ -10,7 +10,8 @@
 
 #include <fuchsia/math/cpp/fidl.h>
 #include <fuchsia/ui/input/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <lib/fit/function.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
 
 #include "garnet/bin/ui/presentation_mode/detector.h"
@@ -64,12 +65,12 @@
 class Presentation : private ::fuchsia::ui::views_v1::ViewTreeListener,
                      private ::fuchsia::ui::views_v1::ViewListener,
                      private ::fuchsia::ui::views_v1::ViewContainerListener,
-                     private presentation::Presentation {
+                     private fuchsia::ui::policy::Presentation {
  public:
   // Callback when the presentation yields to the next/previous one.
-  using YieldCallback = std::function<void(bool yield_to_next)>;
+  using YieldCallback = fit::function<void(bool yield_to_next)>;
   // Callback when the presentation is shut down.
-  using ShutdownCallback = std::function<void()>;
+  using ShutdownCallback = fit::closure;
 
   Presentation(::fuchsia::ui::views_v1::ViewManager* view_manager,
                fuchsia::ui::scenic::Scenic* scenic,
@@ -83,7 +84,7 @@
   // presentation.
   void Present(
       ::fuchsia::ui::views_v1_token::ViewOwnerPtr view_owner,
-      fidl::InterfaceRequest<presentation::Presentation> presentation_request,
+      fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation_request,
       YieldCallback yield_callback, ShutdownCallback shutdown_callback);
 
   void OnReport(uint32_t device_id, fuchsia::ui::input::InputReport report);
@@ -135,9 +136,9 @@
   void InitializeDisplayModel(fuchsia::ui::gfx::DisplayInfo display_info);
 
   // |Presentation|
-  void SetDisplayUsage(presentation::DisplayUsage usage) override;
+  void SetDisplayUsage(fuchsia::ui::policy::DisplayUsage usage) override;
 
-  void SetDisplayUsageWithoutApplyingChanges(presentation::DisplayUsage usage_);
+  void SetDisplayUsageWithoutApplyingChanges(fuchsia::ui::policy::DisplayUsage usage_);
 
   // |Presentation|
   void SetDisplaySizeInMm(float width_in_mm, float height_in_mm) override;
@@ -155,12 +156,12 @@
   // |Presentation|
   void CaptureKeyboardEventHACK(
       fuchsia::ui::input::KeyboardEvent event_to_capture,
-      fidl::InterfaceHandle<presentation::KeyboardCaptureListenerHACK> listener)
+      fidl::InterfaceHandle<fuchsia::ui::policy::KeyboardCaptureListenerHACK> listener)
       override;
 
   // |Presentation|
   void CapturePointerEventsHACK(
-      fidl::InterfaceHandle<presentation::PointerCaptureListenerHACK> listener)
+      fidl::InterfaceHandle<fuchsia::ui::policy::PointerCaptureListenerHACK> listener)
       override;
 
   // |Presentation|
@@ -168,12 +169,12 @@
 
   // |Presentation|
   void SetPresentationModeListener(
-      fidl::InterfaceHandle<presentation::PresentationModeListener> listener)
+      fidl::InterfaceHandle<fuchsia::ui::policy::PresentationModeListener> listener)
       override;
 
   void CreateViewTree(
       ::fuchsia::ui::views_v1_token::ViewOwnerPtr view_owner,
-      fidl::InterfaceRequest<presentation::Presentation> presentation_request,
+      fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation_request,
       fuchsia::ui::gfx::DisplayInfo display_info);
 
   // Returns true if the event was consumed and the scene is to be invalidated.
@@ -233,7 +234,7 @@
 
   fuchsia::math::PointF mouse_coordinates_;
 
-  fidl::Binding<presentation::Presentation> presentation_binding_;
+  fidl::Binding<fuchsia::ui::policy::Presentation> presentation_binding_;
   fidl::Binding<::fuchsia::ui::views_v1::ViewTreeListener> tree_listener_binding_;
   fidl::Binding<::fuchsia::ui::views_v1::ViewContainerListener>
       tree_container_listener_binding_;
@@ -279,20 +280,20 @@
   // event happens.
   struct KeyboardCaptureItem {
     fuchsia::ui::input::KeyboardEvent event;
-    presentation::KeyboardCaptureListenerHACKPtr listener;
+    fuchsia::ui::policy::KeyboardCaptureListenerHACKPtr listener;
   };
   std::vector<KeyboardCaptureItem> captured_keybindings_;
 
   // A registry of listeners who want to be notified when pointer event happens.
   struct PointerCaptureItem {
-    presentation::PointerCaptureListenerHACKPtr listener;
+    fuchsia::ui::policy::PointerCaptureListenerHACKPtr listener;
   };
   std::vector<PointerCaptureItem> captured_pointerbindings_;
 
   // Listener for changes in presentation mode.
-  presentation::PresentationModeListenerPtr presentation_mode_listener_;
+  fuchsia::ui::policy::PresentationModeListenerPtr presentation_mode_listener_;
   // Presentation mode, based on last N measurements
-  presentation::PresentationMode presentation_mode_;
+  fuchsia::ui::policy::PresentationMode presentation_mode_;
   std::unique_ptr<presentation_mode::Detector> presentation_mode_detector_;
 
   fxl::WeakPtrFactory<Presentation> weak_factory_;
diff --git a/bin/ui/set_renderer_params_HACK/BUILD.gn b/bin/ui/set_renderer_params_HACK/BUILD.gn
index 2204c7b..336635b 100644
--- a/bin/ui/set_renderer_params_HACK/BUILD.gn
+++ b/bin/ui/set_renderer_params_HACK/BUILD.gn
@@ -12,6 +12,6 @@
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/ui/gfx/fidl",
-    "//garnet/public/lib/ui/presentation/fidl",
+    "//garnet/public/lib/ui/policy/fidl",
   ]
 }
diff --git a/bin/ui/set_renderer_params_HACK/main.cc b/bin/ui/set_renderer_params_HACK/main.cc
index dbd9dde..95d833b 100644
--- a/bin/ui/set_renderer_params_HACK/main.cc
+++ b/bin/ui/set_renderer_params_HACK/main.cc
@@ -6,7 +6,7 @@
 #include <lib/zx/channel.h>
 
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include "garnet/bin/ui/root_presenter/renderer_params.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/command_line.h"
@@ -19,8 +19,9 @@
   if (!fxl::SetLogSettingsFromCommandLine(command_line))
     return 1;
 
-  FXL_LOG(ERROR) << "This tool is intended for testing and debugging purposes "
-                    "only and may cause problems if invoked incorrectly.";
+  FXL_LOG(WARNING)
+      << "This tool is intended for testing and debugging purposes "
+         "only and may cause problems if invoked incorrectly.";
 
   root_presenter::RendererParams presenter_renderer_params =
       root_presenter::RendererParams::FromCommandLine(command_line);
@@ -49,7 +50,7 @@
 
   // Ask the presenter to change renderer params.
   auto presenter =
-      startup_context_->ConnectToEnvironmentService<presentation::Presenter>();
+      startup_context_->ConnectToEnvironmentService<fuchsia::ui::policy::Presenter>();
   presenter->HACK_SetRendererParams(clipping_enabled,
                                     std::move(renderer_params));
 
diff --git a/bin/ui/set_root_view/BUILD.gn b/bin/ui/set_root_view/BUILD.gn
index bab2c85..3dc0559 100644
--- a/bin/ui/set_root_view/BUILD.gn
+++ b/bin/ui/set_root_view/BUILD.gn
@@ -12,7 +12,7 @@
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/svc/cpp",
-    "//garnet/public/lib/ui/presentation/fidl",
+    "//garnet/public/lib/ui/policy/fidl",
     "//garnet/public/lib/ui/views/fidl:v1",
   ]
 }
diff --git a/bin/ui/set_root_view/main.cc b/bin/ui/set_root_view/main.cc
index 081c6c3..ec6897d 100644
--- a/bin/ui/set_root_view/main.cc
+++ b/bin/ui/set_root_view/main.cc
@@ -5,8 +5,8 @@
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/zx/channel.h>
 
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/command_line.h"
 #include "lib/fxl/log_settings_command_line.h"
@@ -18,16 +18,19 @@
   if (!fxl::SetLogSettingsFromCommandLine(command_line))
     return 1;
 
-  FXL_LOG(ERROR) << "BE ADVISED: The set_root_view tool takes the URL to an "
-                    "app that provided the ViewProvider interface and makes "
-                    "it's view the root view.";
-  FXL_LOG(ERROR) << "This tool is intended for testing and debugging purposes "
-                    "only and may cause problems if invoked incorrectly.";
-  FXL_LOG(ERROR) << "Do not invoke set_root_view if a view tree already exists "
-                    "(i.e. if any process that creates a view is already "
-                    "running).";
-  FXL_LOG(ERROR) << "If scene_manager is already running on your system you "
-                    "will probably want to kill it before invoking this tool.";
+  FXL_LOG(WARNING) << "BE ADVISED: The set_root_view tool takes the URL to an "
+                      "app that provided the ViewProvider interface and makes "
+                      "it's view the root view.";
+  FXL_LOG(WARNING)
+      << "This tool is intended for testing and debugging purposes "
+         "only and may cause problems if invoked incorrectly.";
+  FXL_LOG(WARNING)
+      << "Do not invoke set_root_view if a view tree already exists "
+         "(i.e. if any process that creates a view is already "
+         "running).";
+  FXL_LOG(WARNING)
+      << "If scenic is already running on your system you "
+         "will probably want to kill it before invoking this tool.";
 
   const auto& positional_args = command_line.positional_args();
   if (positional_args.empty()) {
@@ -63,7 +66,8 @@
 
   // Ask the presenter to display it.
   auto presenter =
-      startup_context_->ConnectToEnvironmentService<presentation::Presenter>();
+      startup_context_
+          ->ConnectToEnvironmentService<fuchsia::ui::policy::Presenter>();
   presenter->Present(std::move(view_owner), nullptr);
 
   // Done!
diff --git a/bin/ui/sketchy/canvas.cc b/bin/ui/sketchy/canvas.cc
index 64ba3ba..b873260 100644
--- a/bin/ui/sketchy/canvas.cc
+++ b/bin/ui/sketchy/canvas.cc
@@ -18,12 +18,14 @@
       shared_buffer_pool_(session, escher),
       stroke_manager_(escher) {}
 
-void CanvasImpl::Init(fidl::InterfaceHandle<::fuchsia::ui::sketchy::CanvasListener> listener) {
+void CanvasImpl::Init(
+    fidl::InterfaceHandle<::fuchsia::ui::sketchy::CanvasListener> listener) {
   // TODO(MZ-269): unimplemented.
   FXL_LOG(ERROR) << "Init: unimplemented.";
 }
 
-void CanvasImpl::Enqueue(fidl::VectorPtr<::fuchsia::ui::sketchy::Command> commands) {
+void CanvasImpl::Enqueue(
+    fidl::VectorPtr<::fuchsia::ui::sketchy::Command> commands) {
   // TODO: Use `AddAll()` when fidl::VectorPtr supports it.
   for (size_t i = 0; i < commands->size(); ++i) {
     commands_.push_back(std::move(commands->at(i)));
@@ -77,28 +79,28 @@
 bool CanvasImpl::ApplyCommand(::fuchsia::ui::sketchy::Command command) {
   switch (command.Which()) {
     case ::fuchsia::ui::sketchy::Command::Tag::kCreateResource:
-      return ApplyCreateResourceCommand(std::move(command.create_resource()));
+      return ApplyCreateResourceCmd(std::move(command.create_resource()));
     case ::fuchsia::ui::sketchy::Command::Tag::kReleaseResource:
-      return ApplyReleaseResourceCommand(std::move(command.release_resource()));
+      return ApplyReleaseResourceCmd(std::move(command.release_resource()));
     case ::fuchsia::ui::sketchy::Command::Tag::kSetPath:
-      return ApplySetPathCommand(std::move(command.set_path()));
+      return ApplySetPathCmd(std::move(command.set_path()));
     case ::fuchsia::ui::sketchy::Command::Tag::kAddStroke:
-      return ApplyAddStrokeCommand(std::move(command.add_stroke()));
+      return ApplyAddStrokeCmd(std::move(command.add_stroke()));
     case ::fuchsia::ui::sketchy::Command::Tag::kRemoveStroke:
-      return ApplyRemoveStrokeCommand(std::move(command.remove_stroke()));
+      return ApplyRemoveStrokeCmd(std::move(command.remove_stroke()));
     case ::fuchsia::ui::sketchy::Command::Tag::kBeginStroke:
-      return ApplyBeginStrokeCommand(std::move(command.begin_stroke()));
+      return ApplyBeginStrokeCmd(std::move(command.begin_stroke()));
     case ::fuchsia::ui::sketchy::Command::Tag::kExtendStroke:
-      return ApplyExtendStrokeCommand(std::move(command.extend_stroke()));
+      return ApplyExtendStrokeCmd(std::move(command.extend_stroke()));
     case ::fuchsia::ui::sketchy::Command::Tag::kFinishStroke:
-      return ApplyFinishStrokeCommand(std::move(command.finish_stroke()));
+      return ApplyFinishStrokeCmd(std::move(command.finish_stroke()));
     case ::fuchsia::ui::sketchy::Command::Tag::kClearGroup:
-      return ApplyClearGroupCommand(std::move(command.clear_group()));
+      return ApplyClearGroupCmd(std::move(command.clear_group()));
     case ::fuchsia::ui::sketchy::Command::Tag::kScenicImportResource:
-      return ApplyScenicImportResourceCommand(
+      return ApplyScenicImportResourceCmd(
           std::move(command.scenic_import_resource()));
     case ::fuchsia::ui::sketchy::Command::Tag::kScenicAddChild:
-      return ApplyScenicAddChildCommand(std::move(command.scenic_add_child()));
+      return ApplyScenicAddChildCmd(std::move(command.scenic_add_child()));
     default:
       FXL_DCHECK(false) << "Unsupported op: "
                         << static_cast<uint32_t>(command.Which());
@@ -106,8 +108,8 @@
   }
 }
 
-bool CanvasImpl::ApplyCreateResourceCommand(
-    ::fuchsia::ui::sketchy::CreateResourceCommand create_resource) {
+bool CanvasImpl::ApplyCreateResourceCmd(
+    ::fuchsia::ui::sketchy::CreateResourceCmd create_resource) {
   switch (create_resource.args.Which()) {
     case ::fuchsia::ui::sketchy::ResourceArgs::Tag::kStroke:
       return CreateStroke(create_resource.id, create_resource.args.stroke());
@@ -121,24 +123,26 @@
   }
 }
 
-bool CanvasImpl::CreateStroke(ResourceId id, ::fuchsia::ui::sketchy::Stroke stroke) {
+bool CanvasImpl::CreateStroke(ResourceId id,
+                              ::fuchsia::ui::sketchy::Stroke stroke) {
   return resource_map_.AddResource(
       id, fxl::MakeRefCounted<Stroke>(stroke_manager_.stroke_tessellator(),
                                       shared_buffer_pool_.factory()));
 }
 
-bool CanvasImpl::CreateStrokeGroup(ResourceId id,
-                                   ::fuchsia::ui::sketchy::StrokeGroup stroke_group) {
+bool CanvasImpl::CreateStrokeGroup(
+    ResourceId id, ::fuchsia::ui::sketchy::StrokeGroup stroke_group) {
   return resource_map_.AddResource(id,
                                    fxl::MakeRefCounted<StrokeGroup>(session_));
 }
 
-bool CanvasImpl::ApplyReleaseResourceCommand(
-    ::fuchsia::ui::sketchy::ReleaseResourceCommand command) {
+bool CanvasImpl::ApplyReleaseResourceCmd(
+    ::fuchsia::ui::sketchy::ReleaseResourceCmd command) {
   return resource_map_.RemoveResource(command.id);
 }
 
-bool CanvasImpl::ApplySetPathCommand(::fuchsia::ui::sketchy::SetStrokePathCommand command) {
+bool CanvasImpl::ApplySetPathCmd(
+    ::fuchsia::ui::sketchy::SetStrokePathCmd command) {
   auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
   if (!stroke) {
     FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
@@ -148,7 +152,8 @@
       stroke, std::make_unique<StrokePath>(std::move(command.path)));
 }
 
-bool CanvasImpl::ApplyAddStrokeCommand(::fuchsia::ui::sketchy::AddStrokeCommand command) {
+bool CanvasImpl::ApplyAddStrokeCmd(
+    ::fuchsia::ui::sketchy::AddStrokeCmd command) {
   auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
   if (!stroke) {
     FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
@@ -163,8 +168,8 @@
   return stroke_manager_.AddStrokeToGroup(stroke, group);
 }
 
-bool CanvasImpl::ApplyRemoveStrokeCommand(
-    ::fuchsia::ui::sketchy::RemoveStrokeCommand command) {
+bool CanvasImpl::ApplyRemoveStrokeCmd(
+    ::fuchsia::ui::sketchy::RemoveStrokeCmd command) {
   auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
   if (!stroke) {
     FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
@@ -179,7 +184,8 @@
   return stroke_manager_.RemoveStrokeFromGroup(stroke, group);
 }
 
-bool CanvasImpl::ApplyBeginStrokeCommand(::fuchsia::ui::sketchy::BeginStrokeCommand command) {
+bool CanvasImpl::ApplyBeginStrokeCmd(
+    ::fuchsia::ui::sketchy::BeginStrokeCmd command) {
   auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
   if (!stroke) {
     FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
@@ -189,8 +195,8 @@
   return stroke_manager_.BeginStroke(stroke, {pos.x, pos.y});
 }
 
-bool CanvasImpl::ApplyExtendStrokeCommand(
-    ::fuchsia::ui::sketchy::ExtendStrokeCommand command) {
+bool CanvasImpl::ApplyExtendStrokeCmd(
+    ::fuchsia::ui::sketchy::ExtendStrokeCmd command) {
   auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
   if (!stroke) {
     FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
@@ -204,8 +210,8 @@
   return stroke_manager_.ExtendStroke(stroke, std::move(pts));
 }
 
-bool CanvasImpl::ApplyFinishStrokeCommand(
-    ::fuchsia::ui::sketchy::FinishStrokeCommand command) {
+bool CanvasImpl::ApplyFinishStrokeCmd(
+    ::fuchsia::ui::sketchy::FinishStrokeCmd command) {
   auto stroke = resource_map_.FindResource<Stroke>(command.stroke_id);
   if (!stroke) {
     FXL_LOG(ERROR) << "No Stroke of id " << command.stroke_id << " was found!";
@@ -214,7 +220,8 @@
   return stroke_manager_.FinishStroke(stroke);
 }
 
-bool CanvasImpl::ApplyClearGroupCommand(::fuchsia::ui::sketchy::ClearGroupCommand command) {
+bool CanvasImpl::ApplyClearGroupCmd(
+    ::fuchsia::ui::sketchy::ClearGroupCmd command) {
   auto group = resource_map_.FindResource<StrokeGroup>(command.group_id);
   if (!group) {
     FXL_LOG(ERROR) << "No Group of id " << command.group_id << " was found!";
@@ -223,8 +230,8 @@
   return stroke_manager_.ClearGroup(group);
 }
 
-bool CanvasImpl::ApplyScenicImportResourceCommand(
-    fuchsia::ui::gfx::ImportResourceCommand import_resource) {
+bool CanvasImpl::ApplyScenicImportResourceCmd(
+    fuchsia::ui::gfx::ImportResourceCmd import_resource) {
   switch (import_resource.spec) {
     case fuchsia::ui::gfx::ImportSpec::NODE:
       return ScenicImportNode(import_resource.id,
@@ -239,8 +246,8 @@
   return true;
 }
 
-bool CanvasImpl::ApplyScenicAddChildCommand(
-    fuchsia::ui::gfx::AddChildCommand add_child) {
+bool CanvasImpl::ApplyScenicAddChildCmd(
+    fuchsia::ui::gfx::AddChildCmd add_child) {
   auto import_node = resource_map_.FindResource<ImportNode>(add_child.node_id);
   auto stroke_group =
       resource_map_.FindResource<StrokeGroup>(add_child.child_id);
diff --git a/bin/ui/sketchy/canvas.h b/bin/ui/sketchy/canvas.h
index d51922e..e59763c 100644
--- a/bin/ui/sketchy/canvas.h
+++ b/bin/ui/sketchy/canvas.h
@@ -37,32 +37,32 @@
   bool ApplyCommand(::fuchsia::ui::sketchy::Command command);
   void RequestScenicPresent(uint64_t presentation_time);
 
-  bool ApplyCreateResourceCommand(
-      ::fuchsia::ui::sketchy::CreateResourceCommand command);
-  bool ApplyReleaseResourceCommand(
-      ::fuchsia::ui::sketchy::ReleaseResourceCommand command);
+  bool ApplyCreateResourceCmd(
+      ::fuchsia::ui::sketchy::CreateResourceCmd command);
+  bool ApplyReleaseResourceCmd(
+      ::fuchsia::ui::sketchy::ReleaseResourceCmd command);
   bool CreateStroke(ResourceId id, ::fuchsia::ui::sketchy::Stroke stroke);
   bool CreateStrokeGroup(ResourceId id,
                          ::fuchsia::ui::sketchy::StrokeGroup stroke_group);
 
-  bool ApplySetPathCommand(
-      ::fuchsia::ui::sketchy::SetStrokePathCommand command);
-  bool ApplyAddStrokeCommand(::fuchsia::ui::sketchy::AddStrokeCommand command);
-  bool ApplyRemoveStrokeCommand(
-      ::fuchsia::ui::sketchy::RemoveStrokeCommand command);
+  bool ApplySetPathCmd(
+      ::fuchsia::ui::sketchy::SetStrokePathCmd command);
+  bool ApplyAddStrokeCmd(::fuchsia::ui::sketchy::AddStrokeCmd command);
+  bool ApplyRemoveStrokeCmd(
+      ::fuchsia::ui::sketchy::RemoveStrokeCmd command);
 
-  bool ApplyBeginStrokeCommand(
-      ::fuchsia::ui::sketchy::BeginStrokeCommand command);
-  bool ApplyExtendStrokeCommand(
-      ::fuchsia::ui::sketchy::ExtendStrokeCommand command);
-  bool ApplyFinishStrokeCommand(
-      ::fuchsia::ui::sketchy::FinishStrokeCommand command);
+  bool ApplyBeginStrokeCmd(
+      ::fuchsia::ui::sketchy::BeginStrokeCmd command);
+  bool ApplyExtendStrokeCmd(
+      ::fuchsia::ui::sketchy::ExtendStrokeCmd command);
+  bool ApplyFinishStrokeCmd(
+      ::fuchsia::ui::sketchy::FinishStrokeCmd command);
 
-  bool ApplyClearGroupCommand(
-      ::fuchsia::ui::sketchy::ClearGroupCommand command);
+  bool ApplyClearGroupCmd(
+      ::fuchsia::ui::sketchy::ClearGroupCmd command);
 
-  bool ApplyScenicImportResourceCommand(
-      fuchsia::ui::gfx::ImportResourceCommand import_resource);
+  bool ApplyScenicImportResourceCmd(
+      fuchsia::ui::gfx::ImportResourceCmd import_resource);
 
   // Imports an exported ScenicNode that can be used as an
   // attachment point for a StrokeGroup.
@@ -73,7 +73,7 @@
   //     to the SceneManager to import the node.
   bool ScenicImportNode(ResourceId id, zx::eventpair token);
 
-  bool ApplyScenicAddChildCommand(fuchsia::ui::gfx::AddChildCommand add_child);
+  bool ApplyScenicAddChildCmd(fuchsia::ui::gfx::AddChildCmd add_child);
 
   async::Loop* const loop_;
   scenic_lib::Session* const session_;
diff --git a/bin/ui/tests/performance/BUILD.gn b/bin/ui/tests/performance/BUILD.gn
new file mode 100644
index 0000000..4c9ec65
--- /dev/null
+++ b/bin/ui/tests/performance/BUILD.gn
@@ -0,0 +1,40 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/go/go_binary.gni")
+import("//build/go/toolchain.gni")
+import("//build/package.gni")
+
+package("scenic_benchmarks") {
+  testonly = true
+  deprecated_system_image = true
+
+  deps = [
+    ":process_scenic_trace",
+  ]
+  binaries = [
+    {
+      name = "process_scenic_trace"
+    },
+  ]
+
+  resources = [
+    {
+      path = rebase_path("hello_scenic_benchmark.sh")
+      dest = "scenic_benchmarks/hello_scenic_benchmark.sh"
+    },
+  ]
+}
+
+go_binary("process_scenic_trace") {
+  output_name = "process_scenic_trace"
+
+  gopackage = "process_scenic_trace"
+
+  go_dependencies = [
+    {
+      package = "process_scenic_trace"
+    },
+  ]
+}
diff --git a/bin/ui/tests/performance/README.md b/bin/ui/tests/performance/README.md
new file mode 100644
index 0000000..abe36a3
--- /dev/null
+++ b/bin/ui/tests/performance/README.md
@@ -0,0 +1,19 @@
+# Scenic Benchmarks
+
+We collect benchmarks first by tracing a given process, and then by post-processing
+the trace to output benchmark information.
+
+There is only one benchmark here currently but more will be added.
+
+## hello_scenic_benchmark.sh
+
+This script collects a trace of hello_scenic. It takes one parameter, which is
+where the outputted benchmarks JSON file should be written.
+
+## process_scenic_trace.go
+
+A Go program that takes the following parameters in this order:
+* test label
+* trace file name
+* output filename for benchmarks
+The output is a JSON file with the benchmark output.
diff --git a/bin/ui/tests/performance/hello_scenic_benchmark.sh b/bin/ui/tests/performance/hello_scenic_benchmark.sh
new file mode 100755
index 0000000..ffa52ca
--- /dev/null
+++ b/bin/ui/tests/performance/hello_scenic_benchmark.sh
@@ -0,0 +1,14 @@
+#!/boot/bin/sh
+OUT_DIR=$1
+OUT_FILE=$2
+echo "== Killing processes..."
+killall root_presenter; killall scenic; killall device_runner; killall view_manager; killall flutter*; killall set_root_view
+echo "== Configuring scenic renderer params..."
+set_renderer_params --clipping_enabled --render_continuously --screen_space_shadows
+echo "== Tracing..."
+DATE=`date +%Y-%m-%dT%H:%M:%S`
+TRACE_FILE=$OUT_DIR/trace.$DATE.json
+echo $TRACE_FILE
+trace record --duration=10 --output-file=$TRACE_FILE hello_scenic
+echo "== Processing trace..."
+process_scenic_trace hello_scenic_benchmark $TRACE_FILE $OUT_FILE
diff --git a/bin/ui/tests/performance/process_scenic_trace.go b/bin/ui/tests/performance/process_scenic_trace.go
new file mode 100644
index 0000000..29101cb
--- /dev/null
+++ b/bin/ui/tests/performance/process_scenic_trace.go
@@ -0,0 +1,310 @@
+package main
+
+import (
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"sort"
+	"strings"
+)
+
+const OneSecInUsecs float64 = 1000000
+const OneMsecInUsecs float64 = 1000
+
+var (
+	verbose = false
+)
+
+func check(e error) {
+	if e != nil {
+		panic(e)
+	}
+}
+
+type Trace struct {
+	TraceEvents     []TraceEvent
+	DisplayTimeUnit string
+}
+
+type TraceEvent struct {
+	Cat  string
+	Name string
+	Ph   string
+	Pid  int
+	Tid  int
+	Ts   float64
+	Id   int
+	Dur  float64
+	Args map[string]interface{}
+}
+
+type Thread struct {
+	pid int
+	tid int
+}
+
+type CatAndId struct {
+	cat string
+	id  int
+}
+
+func printTraceEvent(e TraceEvent) {
+	fmt.Printf(
+		"ph=%s  %.2f %-15s %-20s\tpid=%-8d\ttid=%-8d\tid=%-8d\tDur=%.4g\t%s\n",
+		e.Ph, e.Ts, e.Cat, e.Name, e.Pid, e.Tid, e.Id, e.Dur, e.Args)
+}
+
+// Returns a list with only one event per duration event.
+// The |Dur| member is populated with duration.
+func calculateEventDurations(events []TraceEvent) []TraceEvent {
+	durations := make([]TraceEvent, 0)
+	eventStacks := make(map[Thread][]TraceEvent)
+	asyncEvents := make(map[CatAndId]TraceEvent)
+	for _, event := range events {
+		ph := event.Ph
+		thread := Thread{event.Pid, event.Tid}
+
+		if verbose {
+			printTraceEvent(event)
+		}
+		if ph == "X" {
+			// Complete event
+			durations = append(durations, event)
+		} else if ph == "b" {
+			// Async begin duration event
+			asyncEvents[CatAndId{event.Cat, event.Id}] = event
+		} else if ph == "e" {
+			// Async end duration event
+			beginEvent, ok := asyncEvents[CatAndId{event.Cat, event.Id}]
+			if ok {
+				if beginEvent.Cat != event.Cat {
+					panic("Category for begin and end event does not match")
+				}
+				if beginEvent.Id != event.Id {
+					panic("Id for begin and end event does not match")
+				}
+				// Set duration on the end event.
+				event.Dur = event.Ts - beginEvent.Ts
+				mergeArgs(&beginEvent, &event)
+				durations = append(durations, event)
+			}
+		} else if ph == "B" {
+			// Begin duration event.
+			eventStacks[thread] = append(eventStacks[thread], event)
+		} else if ph == "E" {
+			// End duration event.
+			eventStack := eventStacks[thread]
+			if eventStack != nil && len(eventStack) > 0 {
+				// Peek at last event
+				beginEvent := eventStack[len(eventStack)-1]
+
+				if beginEvent.Cat != event.Cat || beginEvent.Name != event.Name {
+					// This is possible since events are not necessarily in
+					// chronological order; they are grouped by source. So, when
+					// processing a new batch of events, it's possible that we
+					// get an end event that didn't have a begin event because
+					// we started tracing mid-event.
+					eventStacks[thread] = nil
+					continue
+				}
+
+				// Pop last event from event stack.
+				eventStacks[thread] = eventStack[:len(eventStack)-1]
+
+				// Set duration on the end event.
+				event.Dur = event.Ts - beginEvent.Ts
+
+				mergeArgs(&beginEvent, &event)
+				durations = append(durations, event)
+			}
+		}
+	}
+
+	return durations
+}
+
+func mergeArgs(event1 *TraceEvent, event2 *TraceEvent) {
+	// Merge 'Args' maps of both events.
+	if event1.Args != nil && event2.Args == nil {
+		event2.Args = event1.Args
+	} else if event1.Args != nil && event2.Args != nil {
+		for k, v := range event2.Args {
+			event1.Args[k] = v
+		}
+		event2.Args = event1.Args
+	}
+
+}
+
+func calculateFps(sortedEvents []TraceEvent) (fps float64, fpsPerWindow []float64) {
+	baseTime := sortedEvents[0].Ts
+	lastEventTime := sortedEvents[len(sortedEvents)-1].Ts
+
+	// window = one-second time window
+	const WindowLength float64 = OneSecInUsecs
+	fpsPerWindow = make([]float64, 0)
+	windowEndTime := baseTime + WindowLength
+
+	numFramesInWindow := 0.0
+	numFrames := 0.0
+
+	for _, event := range sortedEvents {
+		name := event.Name
+		if name == "FramePresented" {
+			if event.Ts < windowEndTime {
+				numFramesInWindow++
+				numFrames++
+			} else {
+				for windowEndTime < event.Ts {
+					fpsPerWindow = append(fpsPerWindow, numFramesInWindow)
+					windowEndTime += WindowLength
+					numFramesInWindow = 0
+				}
+			}
+		}
+	}
+	for windowEndTime < lastEventTime {
+		fpsPerWindow = append(fpsPerWindow, numFramesInWindow)
+		windowEndTime += WindowLength
+		numFramesInWindow = 0
+	}
+	fps = float64(numFrames) / ((lastEventTime - baseTime) / OneSecInUsecs)
+	return fps, fpsPerWindow
+}
+
+func avgDuration(events []TraceEvent, cat string, name string) float64 {
+
+	totalTime := 0.0
+	numEvents := 0.0
+
+	for _, e := range events {
+		if e.Cat == cat && e.Name == name {
+			totalTime += e.Dur
+			numEvents += 1
+		}
+	}
+	return totalTime / numEvents
+
+}
+
+func avgDurationBetween(events []TraceEvent, cat1 string, name1 string, cat2 string, name2 string) float64 {
+	lastEventEndTs := 0.0
+	totalTime := 0.0
+	numEvents := 0.0
+
+	for _, e := range events {
+		if e.Cat == cat2 && e.Name == name2 &&
+			lastEventEndTs != 0.0 && e.Ph != "E" && e.Ph != "e" {
+			totalTime += e.Ts - lastEventEndTs
+			lastEventEndTs = 0.0
+			numEvents += 1
+		} else if e.Cat == cat1 && e.Name == name1 {
+			if e.Ph == "E" || e.Ph == "e" {
+				lastEventEndTs = e.Ts
+			} else {
+				lastEventEndTs = e.Ts + e.Dur
+			}
+		}
+
+	}
+	return totalTime / numEvents
+}
+
+type ByTimestamp []TraceEvent
+
+func (a ByTimestamp) Len() int           { return len(a) }
+func (a ByTimestamp) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a ByTimestamp) Less(i, j int) bool { return a[i].Ts < a[j].Ts }
+
+type Benchmark struct {
+	Label  string    `json:"label"`
+	Values []float64 `json:"values"`
+}
+
+type BenchmarkOut struct {
+	Label   string      `json:"label"`
+	Unit    string      `json:"unit"`
+	Samples []Benchmark `json:"samples"`
+}
+
+func main() {
+
+	verbosePtr := flag.Bool("v", false, "verbose mode")
+	flag.Parse()
+
+	verbose = *verbosePtr
+
+	if len(flag.Args()) < 3 {
+		log.Fatal("Usage: process_scenic_trace benchmark_label trace_file benchmark_out_file_name")
+	}
+	benchmarkLabel := flag.Args()[0]
+	inputFilename := flag.Args()[1]
+	outputFilename := flag.Args()[2]
+	traceFile, err := ioutil.ReadFile(inputFilename)
+	check(err)
+
+	benchmarkValues := BenchmarkOut{
+		Label:   benchmarkLabel,
+		Unit:    "ms",
+		Samples: []Benchmark{}}
+
+	var trace Trace
+	err = json.Unmarshal([]byte(traceFile), &trace)
+	check(err)
+
+	events := trace.TraceEvents
+	if events == nil || len(events) == 0 {
+		panic("No events found")
+	}
+
+	// Get a list of the duration events. |events| must be in its original order
+	// before calling this; sorting can cause the ordering requirements to be
+	// violated.
+	durations := calculateEventDurations(events)
+
+	// Sort in order of increasing timestamp.
+	sort.Sort(ByTimestamp(events))
+
+	fmt.Printf("== FPS ==\n")
+	// Requires sorted list of events.
+	fps, fpsPerTimeWindow := calculateFps(events)
+	fmt.Printf("%.4gfps\nfps per one-second window: %v\n", fps, fpsPerTimeWindow)
+
+	benchmarkValues.Samples = append(
+		benchmarkValues.Samples, Benchmark{"fps", []float64{fps}})
+	benchmarkValues.Samples = append(benchmarkValues.Samples,
+		Benchmark{"fps_per_one_second_window", fpsPerTimeWindow})
+	fmt.Printf("\n== Average times ==\n")
+	type AverageEvent struct {
+		IndentLevel int
+		Name        string
+		Label       string
+	}
+	averageEvents := []AverageEvent{
+		{0, "RenderFrame", "RenderFrame"},
+		{1, "ApplyScheduledSessionUpdates", "ApplyScheduledSessionUpdates"},
+		{1, "UpdateAndDeliverMetrics", "UpdateAndDeliverMetrics"},
+		{1, "Compositor::DrawFrame", "Compositor::DrawFrame"},
+		{0, "Scenic Compositor", "Escher GPU time"},
+	}
+	for _, e := range averageEvents {
+		fmt.Printf("%-35s %.4gms\n", strings.Repeat("  ", e.IndentLevel)+e.Label,
+			avgDuration(durations, "gfx", e.Name)/OneMsecInUsecs)
+		benchmarkValues.Samples = append(benchmarkValues.Samples,
+			Benchmark{e.Label,
+				[]float64{avgDuration(durations, "gfx", e.Name) / OneMsecInUsecs}})
+	}
+	fmt.Printf("%-35s %.4gms", "unaccounted (mostly gfx driver)",
+		avgDurationBetween(
+			events, "gfx", "RenderFrame", "gfx", "Scenic Compositor")/OneMsecInUsecs)
+
+	benchmarkValuesJson, _ := json.Marshal(benchmarkValues)
+
+	// 0644 permissions = -rw-r--r--
+	err = ioutil.WriteFile(outputFilename, benchmarkValuesJson, 0644)
+	check(err)
+
+	fmt.Printf("\n\nWrote benchmark values to file '%s'.\n", outputFilename)
+}
diff --git a/bin/ui/tests/performance/trace_from_host.sh b/bin/ui/tests/performance/trace_from_host.sh
new file mode 100755
index 0000000..7d2d308
--- /dev/null
+++ b/bin/ui/tests/performance/trace_from_host.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+#
+# Usage:
+# trace_from_host.sh base_file_name [renderer_params...]
+#
+# example: trace_from_host.sh trace_clipping_shadows --clipping_enabled --screen_space_shadows
+#
+# See renderer_params.cc for more arguments
+#
+OUT=$1
+shift # swallow first argument
+echo "Killing processes and setting renderer params: $@"
+(set -x; fx shell "killall root_presenter; killall scenic; killall device_runner; killall view_manager; killall flutter*; killall set_root_view")
+(set -x; fx shell "set_renderer_params --render_continuously $@")
+echo "Press control-C after device_runner starts..."
+(set -x; fx shell "run device_runner")
+echo "Press 'return' to start tracing..."
+read
+DATE=`date +%Y-%m-%dT%H:%M:%S`
+echo "Tracing..."
+(set -x; fx shell trace record --duration=10 --output-file=/tmp/trace-$OUT.json)
+(set -x; fx scp [$(fx netaddr --fuchsia)]:/tmp/trace-$OUT.json trace-$OUT.json)
+(set -x; go run $FUCHSIA_ROOT/garnet/bin/ui/tests/performance/process_scenic_trace.go trace-$OUT.json benchmarks-$OUT.json)
+
diff --git a/bin/ui/view_manager/BUILD.gn b/bin/ui/view_manager/BUILD.gn
index a11a4ab..dbfdf41 100644
--- a/bin/ui/view_manager/BUILD.gn
+++ b/bin/ui/view_manager/BUILD.gn
@@ -43,6 +43,7 @@
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fidl/cpp",
     "//garnet/public/lib/fxl",
+    "//garnet/public/lib/ui/a11y/fidl",
     "//garnet/public/lib/ui/geometry/cpp",
     "//garnet/public/lib/ui/gfx/fidl",
     "//garnet/public/lib/ui/input/cpp",
diff --git a/bin/ui/view_manager/input/BUILD.gn b/bin/ui/view_manager/input/BUILD.gn
index bd2b11e..664aeee 100644
--- a/bin/ui/view_manager/input/BUILD.gn
+++ b/bin/ui/view_manager/input/BUILD.gn
@@ -25,6 +25,7 @@
     "//garnet/public/lib/ui/input/fidl",
     "//garnet/public/lib/ui/views/cpp",
     "//garnet/public/lib/ui/views/fidl:v1",
+    "//zircon/public/lib/fit",
   ]
 
   public_configs = [ ":common_include_dirs" ]
diff --git a/bin/ui/view_manager/input/input_connection_impl.cc b/bin/ui/view_manager/input/input_connection_impl.cc
index a5f8f8f..740fb52 100644
--- a/bin/ui/view_manager/input/input_connection_impl.cc
+++ b/bin/ui/view_manager/input/input_connection_impl.cc
@@ -43,7 +43,7 @@
     InjectInput(std::move(event_clone));
   }
 
-  event_listener_->OnEvent(std::move(event), callback);
+  event_listener_->OnEvent(std::move(event), fxl::MakeCopyable(std::move(callback)));
 }
 
 void InputConnectionImpl::SetEventListener(
diff --git a/bin/ui/view_manager/input/input_connection_impl.h b/bin/ui/view_manager/input/input_connection_impl.h
index 3505766..d70fd1f 100644
--- a/bin/ui/view_manager/input/input_connection_impl.h
+++ b/bin/ui/view_manager/input/input_connection_impl.h
@@ -7,6 +7,8 @@
 
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
+#include <lib/fit/function.h>
+
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fidl/cpp/interface_request.h"
 #include "lib/fxl/macros.h"
@@ -16,7 +18,7 @@
 class ViewInspector;
 class InputOwner;
 
-using OnEventDelivered = std::function<void(bool handled)>;
+using OnEventDelivered = fit::function<void(bool handled)>;
 
 // InputConnection implementation.
 // Binds incoming requests to the relevant view token.
diff --git a/bin/ui/view_manager/input/input_dispatcher_impl.cc b/bin/ui/view_manager/input/input_dispatcher_impl.cc
index da8fb8c..0866bf2 100644
--- a/bin/ui/view_manager/input/input_dispatcher_impl.cc
+++ b/bin/ui/view_manager/input/input_dispatcher_impl.cc
@@ -161,7 +161,7 @@
               if (weak)
                 weak->OnHitTestResult(point, std::move(view_hits));
             };
-        inspector_->HitTest(view_tree_token_, ray.first, ray.second, callback);
+        inspector_->HitTest(view_tree_token_, ray.first, ray.second, std::move(callback));
         return;
       }
     } else if (event->is_keyboard()) {
diff --git a/bin/ui/view_manager/internal/BUILD.gn b/bin/ui/view_manager/internal/BUILD.gn
index dcfbff2..16ac465 100644
--- a/bin/ui/view_manager/internal/BUILD.gn
+++ b/bin/ui/view_manager/internal/BUILD.gn
@@ -12,5 +12,6 @@
     "//garnet/public/lib/ui/input/fidl",
     "//garnet/public/lib/ui/views/cpp",
     "//garnet/public/lib/ui/views/fidl:v1",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/bin/ui/view_manager/internal/input_owner.h b/bin/ui/view_manager/internal/input_owner.h
index 1f320a6..b653c2c 100644
--- a/bin/ui/view_manager/internal/input_owner.h
+++ b/bin/ui/view_manager/internal/input_owner.h
@@ -7,6 +7,7 @@
 
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <fuchsia/ui/views_v1_token/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 namespace view_manager {
 
@@ -15,7 +16,7 @@
 
 class InputOwner {
  public:
-  using OnEventDelivered = std::function<void(bool handled)>;
+  using OnEventDelivered = fit::function<void(bool handled)>;
 
   virtual ~InputOwner() {}
 
diff --git a/bin/ui/view_manager/internal/view_inspector.h b/bin/ui/view_manager/internal/view_inspector.h
index aef4abd..f124fd6 100644
--- a/bin/ui/view_manager/internal/view_inspector.h
+++ b/bin/ui/view_manager/internal/view_inspector.h
@@ -5,13 +5,13 @@
 #ifndef GARNET_BIN_UI_VIEW_MANAGER_INTERNAL_VIEW_INSPECTOR_H_
 #define GARNET_BIN_UI_VIEW_MANAGER_INTERNAL_VIEW_INSPECTOR_H_
 
-#include <functional>
 #include <vector>
 
 #include <fuchsia/math/cpp/fidl.h>
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
 #include <fuchsia/ui/views_v1_token/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 namespace view_manager {
 class InputConnectionImpl;
@@ -52,13 +52,13 @@
 // on the contents of views and view trees.
 class ViewInspector {
  public:
-  using HitTestCallback = std::function<void(fidl::VectorPtr<ViewHit>)>;
+  using HitTestCallback = fit::function<void(fidl::VectorPtr<ViewHit>)>;
   using ResolveFocusChainCallback =
-      std::function<void(std::unique_ptr<FocusChain>)>;
+      fit::function<void(std::unique_ptr<FocusChain>)>;
   using ActivateFocusChainCallback =
-      std::function<void(std::unique_ptr<FocusChain>)>;
-  using HasFocusCallback = std::function<void(bool)>;
-  using OnEventDelivered = std::function<void(bool handled)>;
+      fit::function<void(std::unique_ptr<FocusChain>)>;
+  using HasFocusCallback = fit::function<void(bool)>;
+  using OnEventDelivered = fit::function<void(bool handled)>;
 
   virtual ~ViewInspector() {}
 
@@ -73,7 +73,7 @@
   // this view tree.
   virtual void ResolveFocusChain(
       ::fuchsia::ui::views_v1::ViewTreeToken view_tree_token,
-      const ResolveFocusChainCallback& callback) = 0;
+      ResolveFocusChainCallback callback) = 0;
 
   // TODO(jpoichet) Move this
   // Set the current input focus to the provided |view_token|.
@@ -81,11 +81,11 @@
   // on touch down events. This logic should be moved in the future
   virtual void ActivateFocusChain(
       ::fuchsia::ui::views_v1_token::ViewToken view_token,
-      const ActivateFocusChainCallback& callback) = 0;
+      ActivateFocusChainCallback callback) = 0;
 
   // Returns whether view has focus
   virtual void HasFocus(::fuchsia::ui::views_v1_token::ViewToken view_token,
-                        const HasFocusCallback& callback) = 0;
+                        HasFocusCallback callback) = 0;
 
   // Retrieve the SoftKeyboardContainer that is the closest to the ViewToken
   // in the associated ViewTree
diff --git a/bin/ui/view_manager/tests/test_helpers.h b/bin/ui/view_manager/tests/test_helpers.h
index 283dc87..0494267 100644
--- a/bin/ui/view_manager/tests/test_helpers.h
+++ b/bin/ui/view_manager/tests/test_helpers.h
@@ -7,12 +7,12 @@
 
 #include <utility>
 
-#include "lib/fxl/functional/closure.h"
+#include <lib/fit/function.h>
 
 namespace test {
 
 template <typename T>
-void Capture(const fxl::Closure& quit, T* out, T value) {
+void Capture(fit::closure quit, T* out, T value) {
   *out = std::move(value);
   quit();
 }
diff --git a/bin/ui/view_manager/tests/view_manager_test.cc b/bin/ui/view_manager/tests/view_manager_test.cc
index 45a419c..f088fcd 100644
--- a/bin/ui/view_manager/tests/view_manager_test.cc
+++ b/bin/ui/view_manager/tests/view_manager_test.cc
@@ -174,9 +174,6 @@
   tree_container->AddChild(parent_key, std::move(parent_view_owner));
 
   auto parent_view_properties = ::fuchsia::ui::views_v1::ViewProperties::New();
-  parent_view_properties->display_metrics =
-      ::fuchsia::ui::views_v1::DisplayMetrics::New();
-  parent_view_properties->display_metrics->device_pixel_ratio = 1.0;
   parent_view_properties->view_layout =
       ::fuchsia::ui::views_v1::ViewLayout::New();
   parent_view_properties->view_layout->size = fuchsia::math::Size::New();
@@ -217,9 +214,6 @@
 
   auto view_properties = ::fuchsia::ui::views_v1::ViewProperties::New();
   view_properties->view_layout = ::fuchsia::ui::views_v1::ViewLayout::New();
-  view_properties->display_metrics =
-      ::fuchsia::ui::views_v1::DisplayMetrics::New();
-  view_properties->display_metrics->device_pixel_ratio = 1.0;
   view_properties->view_layout->size = fuchsia::math::Size::New();
   view_properties->view_layout->size->width = child_view_width;
   view_properties->view_layout->size->height = child_view_height;
diff --git a/bin/ui/view_manager/view_registry.cc b/bin/ui/view_manager/view_registry.cc
index 6dddd1a..5321b52 100644
--- a/bin/ui/view_manager/view_registry.cc
+++ b/bin/ui/view_manager/view_registry.cc
@@ -8,6 +8,7 @@
 #include <cmath>
 #include <utility>
 
+#include <fuchsia/ui/a11y/cpp/fidl.h>
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
@@ -27,18 +28,11 @@
 namespace view_manager {
 namespace {
 
-bool Validate(const ::fuchsia::ui::views_v1::DisplayMetrics& value) {
-  return std::isnormal(value.device_pixel_ratio) &&
-         value.device_pixel_ratio > 0.f;
-}
-
 bool Validate(const ::fuchsia::ui::views_v1::ViewLayout& value) {
   return value.size.width >= 0 && value.size.height >= 0;
 }
 
 bool Validate(const ::fuchsia::ui::views_v1::ViewProperties& value) {
-  if (value.display_metrics && !Validate(*value.display_metrics))
-    return false;
   if (value.view_layout && !Validate(*value.view_layout))
     return false;
   return true;
@@ -47,15 +41,13 @@
 // Returns true if the properties are valid and are sufficient for
 // operating the view tree.
 bool IsComplete(const ::fuchsia::ui::views_v1::ViewProperties& value) {
-  return Validate(value) && value.view_layout && value.display_metrics;
+  return Validate(value) && value.view_layout;
 }
 
 void ApplyOverrides(::fuchsia::ui::views_v1::ViewProperties* value,
                     const ::fuchsia::ui::views_v1::ViewProperties* overrides) {
   if (!overrides)
     return;
-  if (overrides->display_metrics)
-    *value->display_metrics = *overrides->display_metrics;
   if (overrides->view_layout)
     *value->view_layout = *overrides->view_layout;
 }
@@ -739,26 +731,27 @@
   session_.HitTestDeviceRay(
       (float[3]){ray_origin.x, ray_origin.y, ray_origin.z},
       (float[3]){ray_direction.x, ray_direction.y, ray_direction.z},
-      [this, callback = std::move(callback), ray_origin,
-       ray_direction](fidl::VectorPtr<fuchsia::ui::gfx::Hit> hits) {
-        auto view_hits = fidl::VectorPtr<ViewHit>::New(0);
-        for (auto& hit : *hits) {
-          auto it = views_by_token_.find(hit.tag_value);
-          if (it != views_by_token_.end()) {
-            ViewState* view_state = it->second;
+      fxl::MakeCopyable(
+          [this, callback = std::move(callback), ray_origin,
+           ray_direction](fidl::VectorPtr<fuchsia::ui::gfx::Hit> hits) {
+            auto view_hits = fidl::VectorPtr<ViewHit>::New(0);
+            for (auto& hit : *hits) {
+              auto it = views_by_token_.find(hit.tag_value);
+              if (it != views_by_token_.end()) {
+                ViewState* view_state = it->second;
 
-            view_hits->emplace_back(
-                ViewHit{view_state->view_token(), ray_origin, ray_direction,
-                        hit.distance, ToTransform(hit.inverse_transform)});
-          }
-        }
-        callback(std::move(view_hits));
-      });
+                view_hits->emplace_back(
+                    ViewHit{view_state->view_token(), ray_origin, ray_direction,
+                            hit.distance, ToTransform(hit.inverse_transform)});
+              }
+            }
+            callback(std::move(view_hits));
+          }));
 }
 
 void ViewRegistry::ResolveFocusChain(
     ::fuchsia::ui::views_v1::ViewTreeToken view_tree_token,
-    const ResolveFocusChainCallback& callback) {
+    ResolveFocusChainCallback callback) {
   FXL_VLOG(1) << "ResolveFocusChain: view_tree_token=" << view_tree_token;
 
   auto it = view_trees_by_token_.find(view_tree_token.value);
@@ -771,7 +764,7 @@
 
 void ViewRegistry::ActivateFocusChain(
     ::fuchsia::ui::views_v1_token::ViewToken view_token,
-    const ActivateFocusChainCallback& callback) {
+    ActivateFocusChainCallback callback) {
   FXL_VLOG(1) << "ActivateFocusChain: view_token=" << view_token;
 
   ViewState* view = FindView(view_token.value);
@@ -788,7 +781,7 @@
 }
 
 void ViewRegistry::HasFocus(::fuchsia::ui::views_v1_token::ViewToken view_token,
-                            const HasFocusCallback& callback) {
+                            HasFocusCallback callback) {
   FXL_VLOG(1) << "HasFocus: view_token=" << view_token;
   ViewState* view = FindView(view_token.value);
   if (!view) {
@@ -921,6 +914,14 @@
   FXL_VLOG(1) << "DeliverEvent: view_token=" << view_token
               << ", event=" << event;
 
+  // TODO(SCN-743) Remove this stub code once there is a proper design for A11y
+  // integration with Scenic.
+  if (event.is_pointer()
+      && event.pointer().type == fuchsia::ui::input::PointerEventType::TOUCH
+      && event.pointer().phase == fuchsia::ui::input::PointerEventPhase::DOWN) {
+    A11yNotifyViewSelected(view_token);
+  }
+
   auto it = input_connections_by_view_token_.find(view_token.value);
   if (it == input_connections_by_view_token_.end()) {
     FXL_VLOG(1)
@@ -930,10 +931,12 @@
     return;
   }
 
-  it->second->DeliverEvent(std::move(event), [callback](bool handled) {
-    if (callback)
-      callback(handled);
-  });
+  it->second->DeliverEvent(
+      std::move(event),
+      fxl::MakeCopyable([callback = std::move(callback)](bool handled) {
+        if (callback)
+          callback(handled);
+      }));
 }
 
 void ViewRegistry::CreateInputConnection(
@@ -998,4 +1001,18 @@
   return it != view_trees_by_token_.end() ? it->second : nullptr;
 }
 
+void ViewRegistry::A11yNotifyViewSelected(
+    ::fuchsia::ui::views_v1_token::ViewToken view_token){
+  auto view_elem = views_by_token_.find(view_token.value);
+  if (view_elem != views_by_token_.end()) {
+    fuchsia::sys::ServiceProvider* a11y_provider = view_elem->second->
+        GetServiceProviderIfSupports(fuchsia::ui::a11y::A11yClient::Name_);
+    if (a11y_provider != nullptr) {
+      auto a11y_client = fuchsia::sys::ConnectToService
+          <fuchsia::ui::a11y::A11yClient>(a11y_provider);
+      a11y_client->NotifyViewSelected();
+    }
+  }
+}
+
 }  // namespace view_manager
diff --git a/bin/ui/view_manager/view_registry.h b/bin/ui/view_manager/view_registry.h
index 99d5b1a..6b623bc 100644
--- a/bin/ui/view_manager/view_registry.h
+++ b/bin/ui/view_manager/view_registry.h
@@ -117,11 +117,11 @@
                const fuchsia::math::Point3F& ray_direction,
                HitTestCallback callback) override;
   void ResolveFocusChain(::fuchsia::ui::views_v1::ViewTreeToken view_tree_token,
-                         const ResolveFocusChainCallback& callback) override;
+                         ResolveFocusChainCallback callback) override;
   void ActivateFocusChain(::fuchsia::ui::views_v1_token::ViewToken view_token,
-                          const ActivateFocusChainCallback& callback) override;
+                          ActivateFocusChainCallback callback) override;
   void HasFocus(::fuchsia::ui::views_v1_token::ViewToken view_token,
-                const HasFocusCallback& callback) override;
+                HasFocusCallback callback) override;
   void GetSoftKeyboardContainer(
       ::fuchsia::ui::views_v1_token::ViewToken view_token,
       fidl::InterfaceRequest<fuchsia::ui::input::SoftKeyboardContainer>
@@ -231,6 +231,12 @@
             IsViewTreeStateRegisteredDebug(container_state->AsViewTreeState()));
   }
 
+  // A11Y CLIENTS
+
+  // Calls a view's accessibility service if it exists.
+  void A11yNotifyViewSelected(
+      ::fuchsia::ui::views_v1_token::ViewToken view_token);
+
   fuchsia::sys::StartupContext* startup_context_;
   fuchsia::ui::scenic::ScenicPtr scenic_;
   scenic_lib::Session session_;
diff --git a/bin/wlan-hw-sim/src/main.rs b/bin/wlan-hw-sim/src/main.rs
index 04a537b..23f8ba0 100644
--- a/bin/wlan-hw-sim/src/main.rs
+++ b/bin/wlan-hw-sim/src/main.rs
@@ -11,9 +11,9 @@
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
 extern crate wlantap_client;
-extern crate fidl_wlan_device;
-extern crate fidl_wlan_service;
-extern crate fidl_wlantap;
+extern crate fidl_fuchsia_wlan_device as wlan_device;
+extern crate fidl_fuchsia_wlan_service as fidl_wlan_service;
+extern crate fidl_fuchsia_wlan_tap as wlantap;
 extern crate futures;
 
 use futures::prelude::*;
@@ -26,10 +26,10 @@
 #[cfg(test)]
 mod test_utils;
 
-fn create_2_4_ghz_band_info() -> fidl_wlan_device::BandInfo {
-    fidl_wlan_device::BandInfo{
+fn create_2_4_ghz_band_info() -> wlan_device::BandInfo {
+    wlan_device::BandInfo{
         description: String::from("2.4 GHz"),
-        ht_caps: fidl_wlan_device::HtCapabilities{
+        ht_caps: wlan_device::HtCapabilities{
             ht_capability_info: 0x01fe,
             ampdu_params: 0,
             supported_mcs_set: [
@@ -42,17 +42,17 @@
         },
         vht_caps: None,
         basic_rates: vec![2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108],
-        supported_channels: fidl_wlan_device::ChannelList{
+        supported_channels: wlan_device::ChannelList{
             base_freq: 2407,
             channels: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
         }
     }
 }
 
-fn create_wlantap_config() -> fidl_wlantap::WlantapPhyConfig {
-    use fidl_wlan_device::SupportedPhy;
-    fidl_wlantap::WlantapPhyConfig {
-        phy_info: fidl_wlan_device::PhyInfo{
+fn create_wlantap_config() -> wlantap::WlantapPhyConfig {
+    use wlan_device::SupportedPhy;
+    wlantap::WlantapPhyConfig {
+        phy_info: wlan_device::PhyInfo{
             id: 0,
             dev_path: None,
             hw_mac_address: [ 0x67, 0x62, 0x6f, 0x6e, 0x69, 0x6b ],
@@ -60,7 +60,7 @@
                 SupportedPhy::Dsss, SupportedPhy::Cck, SupportedPhy::Ofdm, SupportedPhy::Ht
             ],
             driver_features: vec![],
-            mac_roles: vec![fidl_wlan_device::MacRole::Client],
+            mac_roles: vec![wlan_device::MacRole::Client],
             caps: vec![],
             bands: vec![
                 create_2_4_ghz_band_info()
@@ -71,14 +71,14 @@
 }
 
 struct State {
-    current_channel: fidl_wlan_device::Channel,
+    current_channel: wlan_device::Channel,
     frame_buf: Vec<u8>,
 }
 
 impl State {
     fn new() -> Self {
         Self {
-            current_channel: fidl_wlan_device::Channel {
+            current_channel: wlan_device::Channel {
                 primary: 0,
                 cbw: 0,
                 secondary80: 0
@@ -88,8 +88,8 @@
     }
 }
 
-fn send_beacon(frame_buf: &mut Vec<u8>, channel: &fidl_wlan_device::Channel, bss_id: &[u8; 6],
-               ssid: &str, proxy: &fidl_wlantap::WlantapPhyProxy)
+fn send_beacon(frame_buf: &mut Vec<u8>, channel: &wlan_device::Channel, bss_id: &[u8; 6],
+               ssid: &str, proxy: &wlantap::WlantapPhyProxy)
     -> Result<(), failure::Error>
 {
     frame_buf.clear();
@@ -116,12 +116,12 @@
         .supported_rates(&[0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24])?
         .dsss_parameter_set(channel.primary)?;
 
-    let rx_info = &mut fidl_wlantap::WlanRxInfo {
+    let rx_info = &mut wlantap::WlanRxInfo {
         rx_flags: 0,
         valid_fields: 0,
         phy: 0,
         data_rate: 0,
-        chan: fidl_wlan_device::Channel { // TODO(FIDL-54): use clone()
+        chan: wlan_device::Channel { // TODO(FIDL-54): use clone()
             primary: channel.primary,
             cbw: channel.cbw,
             secondary80: channel.secondary80
@@ -144,7 +144,7 @@
         let state = state.clone();
         proxy.take_event_stream().for_each(move |event| {
             match event {
-                fidl_wlantap::WlantapPhyEvent::SetChannel{ args } => {
+                wlantap::WlantapPhyEvent::SetChannel{ args } => {
                     let mut state = state.lock().unwrap();
                     state.current_channel = args.chan;
                     println!("setting channel to {:?}", state.current_channel);
@@ -214,14 +214,14 @@
 
     fn scan(exec: &mut async::Executor,
             wlan_service: &fidl_wlan_service::WlanProxy,
-            phy: &fidl_wlantap::WlantapPhyProxy,
+            phy: &wlantap::WlantapPhyProxy,
             helper: &mut test_utils::TestHelper) -> fidl_wlan_service::ScanResult {
         let mut wlanstack_retry = test_utils::RetryWithBackoff::new(1.seconds());
         loop {
             let scan_result = helper.run(exec, 10.seconds(), "receive a scan response",
                |event| {
                    match event {
-                       fidl_wlantap::WlantapPhyEvent::SetChannel { args } => {
+                       wlantap::WlantapPhyEvent::SetChannel { args } => {
                            println!("set channel to {:?}", args.chan);
                            if args.chan.primary == 1 {
                                send_beacon(&mut vec![], &args.chan, &BSS_FOO, SSID_FOO, &phy)
diff --git a/bin/wlan-hw-sim/src/test_utils.rs b/bin/wlan-hw-sim/src/test_utils.rs
index 1591383..f73bdb0 100644
--- a/bin/wlan-hw-sim/src/test_utils.rs
+++ b/bin/wlan-hw-sim/src/test_utils.rs
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 use async::{self, TimeoutExt};
-use fidl_wlantap;
+use wlantap;
 use futures::prelude::*;
 use futures::channel::mpsc;
 use std::sync::Arc;
@@ -11,16 +11,16 @@
 use zx::{self, prelude::*};
 use futures::task::Context;
 
-type EventStream = fidl_wlantap::WlantapPhyEventStream;
+type EventStream = wlantap::WlantapPhyEventStream;
 
 pub struct TestHelper {
     _wlantap: Wlantap,
-    proxy: Arc<fidl_wlantap::WlantapPhyProxy>,
+    proxy: Arc<wlantap::WlantapPhyProxy>,
     event_stream: Option<EventStream>,
 }
 
 struct TestHelperFuture<F: Future, H>
-    where H: FnMut(fidl_wlantap::WlantapPhyEvent) -> ()
+    where H: FnMut(wlantap::WlantapPhyEvent) -> ()
 {
     event_stream: Option<EventStream>,
     event_handler: H,
@@ -28,7 +28,7 @@
 }
 
 impl<F: Future, H> Future for TestHelperFuture<F, H>
-    where H: FnMut(fidl_wlantap::WlantapPhyEvent) -> ()
+    where H: FnMut(wlantap::WlantapPhyEvent) -> ()
 {
     type Item = (F::Item, EventStream);
     type Error = (F::Error, EventStream);
@@ -54,7 +54,7 @@
 
 impl TestHelper {
     pub fn begin_test(exec: &mut async::Executor,
-                      config: fidl_wlantap::WlantapPhyConfig) -> Self {
+                      config: wlantap::WlantapPhyConfig) -> Self {
         let wlantap = Wlantap::open().expect("Failed to open wlantapctl");
         let proxy = wlantap.create_phy(config).expect("Failed to create wlantap PHY");
         let event_stream = Some(proxy.take_event_stream());
@@ -72,7 +72,7 @@
         self.run(exec, 2.seconds(), "receive a WlanmacStart event",
             move |event| {
                 match event {
-                    fidl_wlantap::WlantapPhyEvent::WlanmacStart{ .. } => {
+                    wlantap::WlantapPhyEvent::WlanmacStart{ .. } => {
                         sender.try_send(()).unwrap();
                     },
                     _ => {}
@@ -82,14 +82,14 @@
         ).unwrap();
     }
 
-    pub fn proxy(&self) -> Arc<fidl_wlantap::WlantapPhyProxy> {
+    pub fn proxy(&self) -> Arc<wlantap::WlantapPhyProxy> {
         self.proxy.clone()
     }
 
     pub fn run<F: Future, H>(&mut self, exec: &mut async::Executor, timeout: zx::Duration,
                              context: &str, event_handler: H, future: F)
         -> Result<F::Item, F::Error>
-        where H: FnMut(fidl_wlantap::WlantapPhyEvent) -> ()
+        where H: FnMut(wlantap::WlantapPhyEvent) -> ()
     {
         let res = exec.run_singlethreaded(
             TestHelperFuture{
diff --git a/bin/wlan/wlan-smoke.sh b/bin/wlan/wlan-smoke.sh
index 0cbbbd9..9d3ba1d 100755
--- a/bin/wlan/wlan-smoke.sh
+++ b/bin/wlan/wlan-smoke.sh
@@ -34,7 +34,6 @@
 
 ping_dst() {
   dst="$1"
-  shift
   cmd="ping -c 2 ${dst}"
   ${cmd} > /dev/null 2>&1
 
@@ -68,27 +67,29 @@
   echo "${filesize}"
 }
 
-wget_dst() {
-  tmp_file="/tmp/wlan_smoke_wget.tmp"
-  dst="$1"
-  bytes_want="$2"
+curl_md5sum() {
+  url="$1"
+  tmp_file="/tmp/wlan_smoke_md5sum.tmp"
+  md5_wanted="$2"
 
-  # Fuchsia Dash's pipe and redirection is funky when used in $(..)
-  cmd="wget ${dst} > ${tmp_file}"
-  wget "${dst}" > "${tmp_file}"
+  speed=$(curl -sw "%{speed_download}" -o "${tmp_file}" "${url}" | cut -f 1 -d ".")
+  speed=$((speed/1024))
+  md5_download=$(md5sum "${tmp_file}" | cut -f 1 -d " ")
 
-  bytes_got=$(get_file_size "${tmp_file}")
-  if [ "${bytes_got}" -lt "${bytes_want}" ]; then
-    log_fail "${cmd}"
+  msg="curl_md5sum ${speed}kB/s ${url}"
+  if [ "${md5_download}" = "${md5_wanted}" ]; then
+    log_pass "${msg}"
   else
-    log_pass "${cmd}"
+    log_fail "${msg}"
   fi
 }
 
-
-test_wget() {
-  wget_dst www.google.com 40000
-  wget_dst example.com 1400
+test_curl_md5sum() {
+  curl_md5sum http://ovh.net/files/1Mb.dat 62501d556539559fb422943553cd235a
+  # curl_md5sum http://ovh.net/files/1Mio.dat 6cb91af4ed4c60c11613b75cd1fc6116
+  # curl_md5sum http://ovh.net/files/10Mb.dat 241cead4562ebf274f76f2e991750b9d
+  # curl_md5sum http://ovh.net/files/10Mio.dat ecf2a421f46ab33f277fa2aaaf141780
+  # curl_md5sum http://ipv4.download.thinkbroadband.com/5MB.zip b3215c06647bc550406a9c8ccc378756
 }
 
 check_wlan_status() {
@@ -119,7 +120,6 @@
   WLAN_STATUS_QUERY_RETRY_MAX=10
 
   ssid=$1
-  shift
   for i in $(seq 1 ${WLAN_STATUS_QUERY_RETRY_MAX}); do
     status=$(check_wlan_status)
     if [ "${status}" = "associated" ]; then
@@ -164,7 +164,6 @@
 
 run() {
   cmd="$*"
-  shift
   ${cmd}
   if [ "$?" -ne 0 ]; then
     log_fail "failed in ${cmd}"
@@ -176,15 +175,15 @@
   log "Start"
   eth_iface_list=$(get_eth_iface_list)
   run test_setup "${eth_iface_list}"
-  run wlan_disconnect "${eth_iface_list}"
-  run wlan_connect GoogleGuest "${eth_iface_list}"
+  run wlan_disconnect
+  run wlan_connect GoogleGuest
   run wait_for_dhcp
   log "Starting traffic tests"
-  run test_ping "${eth_iface_list}"
+  run test_ping
   run test_dns
-  run test_wget
+  run test_curl_md5sum
   log "Ending traffic tests"
-  run wlan_disconnect "${eth_iface_list}"
+  run wlan_disconnect
   run test_teardown "${eth_iface_list}"
   log "End"
 }
diff --git a/bin/wlancfg/src/device.rs b/bin/wlancfg/src/device.rs
index f9cc8d0..d050821 100644
--- a/bin/wlancfg/src/device.rs
+++ b/bin/wlancfg/src/device.rs
@@ -8,7 +8,7 @@
 use futures::{future, stream};
 use std::sync::Arc;
 use wlan;
-use wlan_service::{self, DeviceServiceEvent, DeviceServiceProxyInterface};
+use wlan_service::{self, DeviceWatcherEvent, DeviceServiceProxyInterface};
 use zx;
 
 #[derive(Debug)]
@@ -21,29 +21,29 @@
 }
 
 pub fn handle_event<Proxy>(
-    listener: &Arc<Listener<Proxy>>, evt: DeviceServiceEvent,
+    listener: &Arc<Listener<Proxy>>, evt: DeviceWatcherEvent,
 ) -> impl Future<Item = (), Error = fidl::Error>
 where Proxy: DeviceServiceProxyInterface,
 {
     println!("wlancfg got event: {:?}", evt);
     match evt {
-        DeviceServiceEvent::OnPhyAdded { id } => on_phy_added(
-            listener, id,
+        DeviceWatcherEvent::OnPhyAdded { phy_id } => on_phy_added(
+            listener, phy_id,
             ).map_err(|e| e.never_into())
             .left_future()
             .left_future(),
-        DeviceServiceEvent::OnPhyRemoved { id } => on_phy_removed(
-            listener, id,
+        DeviceWatcherEvent::OnPhyRemoved { phy_id } => on_phy_removed(
+            listener, phy_id,
             ).map_err(|e| e.never_into())
             .right_future()
             .left_future(),
-        DeviceServiceEvent::OnIfaceAdded { id } => on_iface_added(
-            listener, id,
+        DeviceWatcherEvent::OnIfaceAdded { iface_id } => on_iface_added(
+            listener, iface_id,
             ).map_err(|e| e.never_into())
             .left_future()
             .right_future(),
-        DeviceServiceEvent::OnIfaceRemoved { id } => on_iface_removed(
-            listener, id,
+        DeviceWatcherEvent::OnIfaceRemoved { iface_id } => on_iface_removed(
+            listener, iface_id,
             ).map_err(|e| e.never_into())
             .right_future()
             .right_future(),
diff --git a/bin/wlancfg/src/main.rs b/bin/wlancfg/src/main.rs
index 6f3d763..95bbd69 100644
--- a/bin/wlancfg/src/main.rs
+++ b/bin/wlancfg/src/main.rs
@@ -6,8 +6,8 @@
 
 extern crate failure;
 extern crate fidl;
-extern crate fidl_wlan_device as wlan;
-extern crate fidl_wlan_device_service as wlan_service;
+extern crate fidl_fuchsia_wlan_device as wlan;
+extern crate fidl_fuchsia_wlan_device_service as wlan_service;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
@@ -32,9 +32,10 @@
     let wlan_svc = app::client::connect_to_service::<DeviceServiceMarker>()
         .context("failed to connect to device service")?;
 
-    let event_stream = wlan_svc.take_event_stream();
+    let (watcher_proxy, watcher_server_end) = fidl::endpoints2::create_endpoints()?;
+    wlan_svc.watch_devices(watcher_server_end)?;
     let listener = device::Listener::new(wlan_svc, cfg);
-    let fut = event_stream
+    let fut = watcher_proxy.take_event_stream()
         .for_each(move |evt| device::handle_event(&listener, evt))
         .err_into();
 
diff --git a/bin/wlanstack/BUILD.gn b/bin/wlanstack/BUILD.gn
index 7f28061..f9d228c 100644
--- a/bin/wlanstack/BUILD.gn
+++ b/bin/wlanstack/BUILD.gn
@@ -12,9 +12,11 @@
   deps = [
     "//garnet/lib/rust/crates/fuchsia-wlan-dev",
     "//garnet/lib/rust/crates/wlan-sme",
+    "//garnet/lib/rust/crates/wlantap-client",
     "//garnet/lib/wlan/fidl:fidl-rustc",
     "//garnet/lib/wlan/fidl:service-rustc",
     "//garnet/lib/wlan/fidl:sme-rustc",
+    "//garnet/lib/wlan/fidl:wlantap-rustc",
     "//garnet/public/lib/fidl/rust/fidl",
     "//garnet/public/lib/wlan/fidl:mlme-rustc",
     "//garnet/public/rust/crates/fuchsia-app",
@@ -46,3 +48,19 @@
     },
   ]
 }
+
+package("wlanstack2-tests") {
+  deprecated_system_image = true
+  testonly = true
+
+  deps = [
+    ":bin"
+  ]
+
+  tests = [
+    {
+      name = "wlanstack2_bin_test_rustc"
+      dest =  "wlanstack2_bin_test_rustc"
+    }
+  ]
+}
diff --git a/bin/wlanstack/src/device.rs b/bin/wlanstack/src/device.rs
index 5c31161..91345e0 100644
--- a/bin/wlanstack/src/device.rs
+++ b/bin/wlanstack/src/device.rs
@@ -2,54 +2,34 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use async;
+use device_watch;
 use failure::Error;
-use fidl_mlme;
 use futures::prelude::*;
 use futures::{future, stream};
 use futures::channel::mpsc;
 use parking_lot::Mutex;
-use vfs_watcher;
+use watchable_map::{MapWatcher, WatchableMap, WatcherResult};
 use wlan;
 use wlan_dev;
+use wlan_service;
 use zx;
 
-use std::collections::HashMap;
-use std::fs::File;
-use std::path::Path;
-use std::str::FromStr;
 use std::sync::Arc;
-use std::{thread, time};
 
 struct PhyDevice {
-    id: u16,
     proxy: wlan::PhyProxy,
-    dev: wlan_dev::Device,
+    device: wlan_dev::Device,
 }
 
-impl PhyDevice {
-    fn new<P: AsRef<Path>>(id: u16, path: P) -> Result<Self, zx::Status> {
-        let dev = wlan_dev::Device::new(path)?;
-        let proxy = wlan_dev::connect_wlan_phy(&dev)?;
-        Ok(PhyDevice { id, proxy, dev })
-    }
-}
-
-pub type ClientSmeServer = mpsc::UnboundedSender<async::Channel>;
+pub type ClientSmeServer = mpsc::UnboundedSender<super::station::ClientSmeEndpoint>;
 
 struct IfaceDevice {
     client_sme_server: Option<ClientSmeServer>,
-    _dev: wlan_dev::Device,
-}
-
-fn open_iface_device<P: AsRef<Path>>(path: P) -> Result<(async::Channel, wlan_dev::Device), zx::Status> {
-    let dev = wlan_dev::Device::new(path)?;
-    let channel = wlan_dev::connect_wlan_iface(&dev)?;
-    Ok((channel, dev))
+    _device: wlan_dev::Device,
 }
 
 /// Called by the `DeviceManager` in response to device events.
-pub trait EventListener: Send {
+pub trait EventListener: Send + Sync {
     /// Called when a phy device is added. On error, the listener is removed from the
     /// `DeviceManager`.
     fn on_phy_added(&self, id: u16) -> Result<(), Error>;
@@ -69,77 +49,90 @@
 
 pub type DevMgrRef = Arc<Mutex<DeviceManager>>;
 
+struct PhyWatcher(Arc<EventListener>);
+impl MapWatcher<u16> for PhyWatcher {
+    fn on_add_key(&self, key: &u16) -> WatcherResult {
+        handle_notification_error("on_phy_added", self.0.on_phy_added(*key))
+    }
+    fn on_remove_key(&self, key: &u16) -> WatcherResult {
+        handle_notification_error("on_phy_removed", self.0.on_phy_removed(*key))
+    }
+}
+
+struct IfaceWatcher(Arc<EventListener>);
+impl MapWatcher<u16> for IfaceWatcher {
+    fn on_add_key(&self, key: &u16) -> WatcherResult {
+        handle_notification_error("on_iface_added", self.0.on_iface_added(*key))
+    }
+    fn on_remove_key(&self, key: &u16) -> WatcherResult {
+        handle_notification_error("on_iface_removed", self.0.on_iface_removed(*key))
+    }
+}
+
+fn handle_notification_error(event_name: &str, r: Result<(), Error>) -> WatcherResult {
+    match r {
+        Ok(()) => WatcherResult::KeepWatching,
+        Err(e) => {
+            eprintln!("Failed to notify a watcher of {} event: {}", event_name, e);
+            WatcherResult::StopWatching
+        }
+    }
+}
+
 /// Manages the wlan devices used by the wlanstack.
 pub struct DeviceManager {
-    phys: HashMap<u16, PhyDevice>,
-    ifaces: HashMap<u16, IfaceDevice>,
-    listeners: Vec<Box<EventListener>>,
+    phys: WatchableMap<u16, PhyDevice, PhyWatcher>,
+    ifaces: WatchableMap<u16, IfaceDevice, IfaceWatcher>,
 }
 
 impl DeviceManager {
     /// Create a new `DeviceManager`.
     pub fn new() -> Self {
         DeviceManager {
-            phys: HashMap::new(),
-            ifaces: HashMap::new(),
-            listeners: Vec::new(),
+            phys: WatchableMap::new(),
+            ifaces: WatchableMap::new(),
         }
     }
 
-    fn add_phy(&mut self, phy: PhyDevice) {
-        let id = phy.id;
-        self.phys.insert(phy.id, phy);
-        self.listeners
-            .retain(|listener| listener.on_phy_added(id).is_ok());
+    fn add_phy(&mut self, id: u16, phy: PhyDevice) {
+
+        self.phys.insert(id, phy);
     }
 
     fn rm_phy(&mut self, id: u16) {
         self.phys.remove(&id);
-        self.listeners
-            .retain(|listener| listener.on_phy_removed(id).is_ok());
     }
 
-    fn add_iface(&mut self, id: u16, channel: async::Channel, device: wlan_dev::Device) {
-        let proxy = fidl_mlme::MlmeProxy::new(channel);
+    fn add_iface(&mut self, new_iface: device_watch::NewIfaceDevice)
+        -> impl Future<Item = (), Error = Never>
+    {
         // TODO(gbonik): move this code outside of DeviceManager
         let (sender, receiver) = mpsc::unbounded();
         // TODO(gbonik): check the role of the interface instead of assuming it is a station
-        async::spawn(super::station::serve_client_sme(proxy, receiver).recover::<Never, _>(|e| {
-            eprintln!("Error serving client station: {:?}", e);
-        }));
-        self.ifaces.insert(id, IfaceDevice {
+        self.ifaces.insert(new_iface.id, IfaceDevice {
             client_sme_server: Some(sender),
-            _dev: device,
+            _device: new_iface.device,
         });
-        self.listeners
-            .retain(|listener| listener.on_iface_added(id).is_ok());
+        super::station::serve_client_sme(new_iface.proxy, receiver).recover::<Never, _>(|e| {
+            eprintln!("Error serving client station: {:?}", e);
+        })
     }
 
     fn rm_iface(&mut self, id: u16) {
         self.ifaces.remove(&id);
-        self.listeners
-            .retain(|listener| listener.on_iface_removed(id).is_ok());
     }
 
     /// Retrieves information about all the phy devices managed by this `DeviceManager`.
-    // TODO(tkilbourn): this should return a simplified view of the Phy compared to query_phy. For
-    // now we just return the whole PhyInfo for each device.
-    pub fn list_phys(&self) -> impl Stream<Item = wlan::PhyInfo, Error = ()> {
+    pub fn list_phys(&self) -> Vec<wlan_service::PhyListItem> {
         self.phys
-            .values()
-            .map(|phy| {
-                let phy_id = phy.id;
-                let phy_path = phy.dev.path().to_string_lossy().into_owned();
-                // For now we query each device for every call to `list_phys`. We will need to
-                // decide how to handle queries for static vs dynamic data, caching response, etc.
-                phy.proxy.query().map_err(|_| ()).map(move |response| {
-                    let mut info = response.info;
-                    info.id = phy_id;
-                    info.dev_path = Some(phy_path);
-                    info
-                })
+            .iter()
+            .map(|(phy_id, phy)| {
+                wlan_service::PhyListItem {
+                    phy_id: *phy_id,
+                    path: phy.device.path().to_string_lossy().into_owned(),
+                }
             })
-            .collect::<stream::FuturesUnordered<_>>()
+            .collect()
     }
 
     pub fn query_phy(&self, id: u16) -> impl Future<Item = wlan::PhyInfo, Error = zx::Status> {
@@ -147,8 +140,7 @@
             Some(p) => p,
             None => return future::err(zx::Status::NOT_FOUND).left_future(),
         };
-        let phy_id = phy.id;
-        let phy_path = phy.dev.path().to_string_lossy().into_owned();
+        let phy_path = phy.device.path().to_string_lossy().into_owned();
         phy.proxy
             .query()
             .map_err(|_| zx::Status::INTERNAL)
@@ -157,7 +149,7 @@
                     .into_future()
                     .map(move |()| {
                         let mut info = response.info;
-                        info.id = phy_id;
+                        info.id = id;
                         info.dev_path = Some(phy_path);
                         info
                     })
@@ -205,13 +197,9 @@
 
     /// Adds an `EventListener`. The event methods will be called for each existing object tracked
     /// by this device manager.
-    pub fn add_listener(&mut self, listener: Box<EventListener>) {
-        if self.phys
-            .values()
-            .all(|phy| listener.on_phy_added(phy.id).is_ok())
-        {
-            self.listeners.push(listener);
-        }
+    pub fn add_listener(&mut self, listener: Arc<EventListener>) {
+        self.phys.add_watcher(PhyWatcher(listener.clone()));
+        self.ifaces.add_watcher(IfaceWatcher(listener));
     }
 
     pub fn get_client_sme(&mut self, iface_id: u16) -> Option<ClientSmeServer> {
@@ -219,100 +207,50 @@
     }
 }
 
-fn new_watcher<P, OnAdd, OnRm>(
-    path: P, devmgr: DevMgrRef, on_add: OnAdd, on_rm: OnRm,
-) -> impl Future<Item = (), Error = Error>
-where
-    OnAdd: Fn(DevMgrRef, &Path),
-    OnRm: Fn(DevMgrRef, &Path),
-    P: AsRef<Path>,
+pub fn serve_phys(devmgr: DevMgrRef)
+    -> Result<impl Future<Item = (), Error = Error>, Error>
 {
-    File::open(&path)
-        .into_future()
+    Ok(device_watch::watch_phy_devices()?
         .err_into()
-        .and_then(|dev| vfs_watcher::Watcher::new(&dev).map_err(Into::into))
-        .and_then(|watcher| {
-            watcher
-                .for_each(move |msg| {
-                    let full_path = path.as_ref().join(msg.filename);
-                    match msg.event {
-                        vfs_watcher::WatchEvent::EXISTING | vfs_watcher::WatchEvent::ADD_FILE => {
-                            on_add(devmgr.clone(), &full_path);
-                        }
-                        vfs_watcher::WatchEvent::REMOVE_FILE => {
-                            on_rm(devmgr.clone(), &full_path);
-                        }
-                        vfs_watcher::WatchEvent::IDLE => debug!("device watcher idle"),
-                        e => warn!("unknown watch event: {:?}", e),
-                    }
-                    Ok(())
+        .chain(stream::once(Err(format_err!("phy watcher stream unexpectedly finished"))))
+        .for_each_concurrent(move |new_phy| {
+            println!("new phy #{}: {}", new_phy.id, new_phy.device.path().to_string_lossy());
+            let id = new_phy.id;
+            let event_stream = new_phy.proxy.take_event_stream();
+            devmgr.lock().add_phy(id, PhyDevice {
+                proxy: new_phy.proxy,
+                device: new_phy.device,
+            });
+            let devmgr = devmgr.clone();
+            event_stream
+                .for_each(|_| Ok(()))
+                .then(move |r| {
+                    println!("phy removed: {}", id);
+                    devmgr.lock().rm_phy(id);
+                    r.map(|_| ()).map_err(|e| e.into())
                 })
-                .map(|_s| ())
-                .err_into()
         })
+        .map(|_| ()))
 }
 
-/// Creates a `futures::Stream` that adds phy devices to the `DeviceManager` as they appear at the
-/// given path.
-pub fn new_phy_watcher<P: AsRef<Path>>(
-    path: P, devmgr: DevMgrRef,
-) -> impl Future<Item = (), Error = Error> {
-    new_watcher(
-        path,
-        devmgr,
-        |devmgr, path| {
-            info!("found phy at {}", path.to_string_lossy());
-            // The path was constructed in the new_watcher closure, so filename should not be
-            // empty. The file_name comes from devmgr and is an integer, so from_str should not
-            // fail.
-            let id = u16::from_str(&path.file_name().unwrap().to_string_lossy()).unwrap();
-            // This could fail if the device were to go away in between our receiving the watcher
-            // message and here. TODO(tkilbourn): handle this case more cleanly.
-            let phy = PhyDevice::new(id, path).expect("Failed to open phy device");
-            devmgr.lock().add_phy(phy);
-        },
-        |devmgr, path| {
-            info!("removing phy at {}", path.to_string_lossy());
-            // The path was constructed in the new_watcher closure, so filename should not be
-            // empty. The file_name comes from devmgr and is an integer, so from_str should not
-            // fail.
-            let id = u16::from_str(&path.file_name().unwrap().to_string_lossy()).unwrap();
-            devmgr.lock().rm_phy(id);
-        },
-    )
-}
-
-/// Creates a `futures::Stream` that adds iface devices to the `DeviceManager` as they appear at
-/// the given path.
-/// TODO(tkilbourn): add the iface to `DeviceManager`
-pub fn new_iface_watcher<P: AsRef<Path>>(
-    path: P, devmgr: DevMgrRef,
-) -> impl Future<Item = (), Error = Error> {
-    new_watcher(
-        path,
-        devmgr,
-        |devmgr, path| {
-            info!("found iface at {}", path.to_string_lossy());
-            let id = u16::from_str(&path.file_name().unwrap().to_string_lossy()).unwrap();
-
-            // Temporarily delay opening the iface since only one service may open a channel to a
-            // device at a time. If the legacy wlantack is running, it should take priority. For
-            // development of wlanstack2, kill the wlanstack process first to let wlanstack2 take
-            // over.
-            debug!("sleeping 100ms...");
-            let open_delay = time::Duration::from_millis(100);
-            thread::sleep(open_delay);
-
-            match open_iface_device(path) {
-                Ok((channel, dev)) => devmgr.lock().add_iface(id, channel, dev),
-                Err(zx::Status::ALREADY_BOUND) => info!("iface already open, deferring"),
-                Err(e) => error!("could not open iface: {:?}", e),
-            }
-        },
-        |devmgr, path| {
-            info!("removing iface at {}", path.to_string_lossy());
-            let id = u16::from_str(&path.file_name().unwrap().to_string_lossy()).unwrap();
-            devmgr.lock().rm_iface(id);
-        },
-    )
+pub fn serve_ifaces(devmgr: DevMgrRef)
+    -> Result<impl Future<Item = (), Error = Error>, Error>
+{
+    Ok(device_watch::watch_iface_devices()?
+        .err_into()
+        .chain(stream::once(Err(format_err!("iface watcher stream unexpectedly finished"))))
+        .for_each_concurrent(move |new_iface| {
+            println!("new iface #{}: {}", new_iface.id, new_iface.device.path().to_string_lossy());
+            let id = new_iface.id;
+            let devmgr_ref = devmgr.clone();
+            let mut devmgr = devmgr.lock();
+            devmgr.add_iface(new_iface)
+                .then(move |r| {
+                    println!("iface removed: {}", id);
+                    devmgr_ref.lock().rm_iface(id);
+                    r
+                })
+                .map_err(|e| e.never_into())
+        })
+        .map(|_| ()))
 }
diff --git a/bin/wlanstack/src/device_watch.rs b/bin/wlanstack/src/device_watch.rs
new file mode 100644
index 0000000..2792bd0
--- /dev/null
+++ b/bin/wlanstack/src/device_watch.rs
@@ -0,0 +1,165 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![allow(dead_code)]
+
+use failure;
+use fidl_mlme;
+use futures::prelude::*;
+use std::{io, thread, time};
+use std::fs::File;
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+use vfs_watcher::{Watcher, WatchEvent};
+use wlan;
+use wlan_dev;
+
+const PHY_PATH: &str = "/dev/class/wlanphy";
+const IFACE_PATH: &str = "/dev/class/wlanif";
+
+pub struct NewPhyDevice {
+    pub id: u16,
+    pub proxy: wlan::PhyProxy,
+    pub device: wlan_dev::Device,
+}
+
+pub struct NewIfaceDevice {
+    pub id: u16,
+    pub proxy: fidl_mlme::MlmeProxy,
+    pub device: wlan_dev::Device,
+}
+
+pub fn watch_phy_devices()
+    -> Result<impl Stream<Item = NewPhyDevice, Error = io::Error>, io::Error>
+{
+    Ok(watch_new_devices(PHY_PATH)?
+        .filter_map(|path| Ok(handle_open_error(&path, new_phy(&path)))))
+}
+
+pub fn watch_iface_devices()
+    -> Result<impl Stream<Item = NewIfaceDevice, Error = io::Error>, io::Error>
+{
+    Ok(watch_new_devices(IFACE_PATH)?
+        .filter_map(|path| {
+            // Temporarily delay opening the iface since only one service may open a channel to a
+            // device at a time. If the legacy wlantack is running, it should take priority. For
+            // development of wlanstack2, kill the wlanstack process first to let wlanstack2 take
+            // over.
+            debug!("sleeping 100ms...");
+            let open_delay = time::Duration::from_millis(100);
+            thread::sleep(open_delay);
+            Ok(handle_open_error(&path, new_iface(&path)))
+        }))
+}
+
+fn handle_open_error<T>(path: &PathBuf, r: Result<T, failure::Error>) -> Option<T> {
+    if let Err(ref e) = &r {
+        eprintln!("Error opening device '{}': {}", path.display(), e);
+    }
+    r.ok()
+}
+
+fn watch_new_devices<P: AsRef<Path>>(path: P)
+    -> Result<impl Stream<Item = PathBuf, Error = io::Error>, io::Error>
+{
+    let dir = File::open(&path)?;
+    let watcher = Watcher::new(&dir)?;
+    Ok(watcher.filter_map(move |msg| {
+        Ok(match msg.event {
+            WatchEvent::EXISTING | WatchEvent::ADD_FILE => Some(path.as_ref().join(msg.filename)),
+            _ => None
+        })
+    }))
+}
+
+fn new_phy(path: &PathBuf) -> Result<NewPhyDevice, failure::Error> {
+    let id = id_from_path(path)?;
+    let device = wlan_dev::Device::new(path)?;
+    let proxy = wlan_dev::connect_wlan_phy(&device)?;
+    Ok(NewPhyDevice{ id, proxy, device })
+}
+
+fn new_iface(path: &PathBuf) -> Result<NewIfaceDevice, failure::Error> {
+    let id = id_from_path(path)?;
+    let device = wlan_dev::Device::new(path)?;
+    let proxy = fidl_mlme::MlmeProxy::new(wlan_dev::connect_wlan_iface(&device)?);
+    Ok(NewIfaceDevice{ id, proxy, device })
+}
+
+fn id_from_path(path: &PathBuf) -> Result<u16, failure::Error> {
+    let file_name = path.file_name().ok_or_else(
+        || format_err!("Invalid device path"))?;
+    let file_name_str = file_name.to_str().ok_or_else(
+        || format_err!("Filename is not valid UTF-8"))?;
+    let id = u16::from_str(&file_name_str).map_err(
+        |e| format_err!("Failed to parse device filename as a numeric ID: {}", e))?;
+    Ok(id)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use async::{self, TimeoutExt};
+    use fidl_wlantap;
+    use wlantap_client;
+    use zx::prelude::*;
+
+    #[test]
+    fn watch_phys() {
+        let mut exec = async::Executor::new().expect("Failed to create an executor");
+        let new_phy_stream = watch_phy_devices().expect("watch_phy_devices() failed");
+        let wlantap = wlantap_client::Wlantap::open().expect("Failed to connect to wlantapctl");
+        let _tap_phy = wlantap.create_phy(create_wlantap_config(*b"wtchph"));
+        let (new_phy, _new_phy_stream) = exec.run_singlethreaded(
+            new_phy_stream.next().on_timeout(2.seconds().after_now(),
+                || panic!("Didn't get a new phy in time")).unwrap()
+            )
+            .map_err(|(e, _s)| e)
+            .expect("new_phy_stream returned an error");
+        let new_phy = new_phy.expect("new_phy_stream ended without yielding a phy");
+        let query_resp = exec.run_singlethreaded(new_phy.proxy.query()).expect("phy query failed");
+        assert_eq!(*b"wtchph", query_resp.info.hw_mac_address);
+    }
+
+    fn create_wlantap_config(mac_addr: [u8; 6]) -> fidl_wlantap::WlantapPhyConfig {
+        use wlan::SupportedPhy;
+        fidl_wlantap::WlantapPhyConfig {
+            phy_info: wlan::PhyInfo {
+                id: 0,
+                dev_path: None,
+                hw_mac_address: mac_addr,
+                supported_phys: vec![
+                    SupportedPhy::Dsss, SupportedPhy::Cck, SupportedPhy::Ofdm, SupportedPhy::Ht
+                ],
+                driver_features: vec![],
+                mac_roles: vec![wlan::MacRole::Client],
+                caps: vec![],
+                bands: vec![create_2_4_ghz_band_info()]
+            },
+            name: String::from("devwatchtap")
+        }
+    }
+
+    fn create_2_4_ghz_band_info() -> wlan::BandInfo {
+        wlan::BandInfo{
+            description: String::from("2.4 GHz"),
+            ht_caps: wlan::HtCapabilities {
+                ht_capability_info: 0x01fe,
+                ampdu_params: 0,
+                supported_mcs_set: [
+                    0xff, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0, 0, 0
+                ],
+                ht_ext_capabilities: 0,
+                tx_beamforming_capabilities: 0,
+                asel_capabilities: 0
+            },
+            vht_caps: None,
+            basic_rates: vec![2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108],
+            supported_channels: wlan::ChannelList {
+                base_freq: 2407,
+                channels: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
+            }
+        }
+    }
+}
diff --git a/bin/wlanstack/src/main.rs b/bin/wlanstack/src/main.rs
index 806719d..46198c2 100644
--- a/bin/wlanstack/src/main.rs
+++ b/bin/wlanstack/src/main.rs
@@ -10,12 +10,12 @@
 #![deny(warnings)]
 #![deny(missing_docs)]
 
-extern crate failure;
+#[macro_use] extern crate failure;
 extern crate fidl;
-extern crate fidl_wlan_mlme as fidl_mlme;
-extern crate fidl_wlan_device as wlan;
-extern crate fidl_wlan_device_service as wlan_service;
-extern crate fidl_wlan_sme as fidl_sme;
+extern crate fidl_fuchsia_wlan_mlme as fidl_mlme;
+extern crate fidl_fuchsia_wlan_device as wlan;
+extern crate fidl_fuchsia_wlan_device_service as wlan_service;
+extern crate fidl_fuchsia_wlan_sme as fidl_sme;
 extern crate fuchsia_app as component;
 extern crate fuchsia_async as async;
 extern crate fuchsia_vfs_watcher as vfs_watcher;
@@ -27,10 +27,15 @@
 extern crate parking_lot;
 extern crate wlan_sme;
 
+#[cfg(test)] extern crate fidl_fuchsia_wlan_tap as fidl_wlantap;
+#[cfg(test)] extern crate wlantap_client;
+
 mod device;
+mod device_watch;
 mod logger;
 mod service;
 mod station;
+mod watchable_map;
 
 use component::server::ServicesServer;
 use failure::{Error, ResultExt};
@@ -42,9 +47,6 @@
 
 const MAX_LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info;
 
-const PHY_PATH: &str = "/dev/class/wlanphy";
-const IFACE_PATH: &str = "/dev/class/wlanif";
-
 static LOGGER: logger::Logger = logger::Logger;
 
 fn main() -> Result<(), Error> {
@@ -57,8 +59,10 @@
 
     let devmgr = Arc::new(Mutex::new(device::DeviceManager::new()));
 
-    let phy_watcher = device::new_phy_watcher(PHY_PATH, devmgr.clone());
-    let iface_watcher = device::new_iface_watcher(IFACE_PATH, devmgr.clone());
+    let phy_server = device::serve_phys(devmgr.clone())?
+        .and_then(|()| Err(format_err!("Phy server exited unexpectedly")));
+    let iface_server = device::serve_ifaces(devmgr.clone())?
+        .and_then(|()| Err(format_err!("Iface server exited unexpectedly")));
 
     let services_server = ServicesServer::new()
         .add_service((DeviceServiceMarker::NAME, move |channel| {
@@ -67,6 +71,6 @@
         .start()
         .context("error configuring device service")?;
 
-    exec.run_singlethreaded(services_server.join3(phy_watcher, iface_watcher))
-        .map(|_| ())
+    exec.run_singlethreaded(services_server.join3(phy_server, iface_server))
+        .map(|((), (), ())| ())
 }
diff --git a/bin/wlanstack/src/service.rs b/bin/wlanstack/src/service.rs
index 6553f32..faa2e07 100644
--- a/bin/wlanstack/src/service.rs
+++ b/bin/wlanstack/src/service.rs
@@ -7,9 +7,11 @@
 use failure::Error;
 use fidl;
 use fidl::encoding2::OutOfLine;
+use fidl::endpoints2::RequestStream;
 use futures::future::{self, FutureResult};
-use futures::{Future, FutureExt, Never, StreamExt};
-use wlan_service::{self, DeviceService, DeviceServiceControlHandle, DeviceServiceImpl};
+use futures::{Future, FutureExt, Never};
+use std::sync::Arc;
+use wlan_service::{self, DeviceService, DeviceServiceImpl, DeviceWatcherControlHandle};
 use zx;
 
 fn catch_and_log_err<F>(ctx: &'static str, f: F) -> FutureResult<(), Never>
@@ -29,27 +31,14 @@
 
     DeviceServiceImpl {
         state: devmgr,
-        on_open: |state, control_handle| {
-            debug!("on_open");
-            state.lock().add_listener(Box::new(control_handle));
-            future::ok(())
-        },
+        on_open: |_, _| future::ok(()),
 
         list_phys: |state, c| {
             debug!("list_phys");
-            state
-                .lock()
-                .list_phys()
-                .collect()
-                .then(move |phys| match phys {
-                    Ok(p) => catch_and_log_err("list_phys", || {
-                        c.send(&mut wlan_service::ListPhysResponse { phys: p })
-                    }),
-                    Err(e) => {
-                        error!("could not query phys: {:?}", e);
-                        future::ok(())
-                    }
-                })
+            let list = state.lock().list_phys();
+            c.send_or_shutdown(&mut wlan_service::ListPhysResponse { phys: list })
+                .unwrap_or_else(|e| eprintln!("list_phys: Failed to send response: {}", e));
+            future::ok(())
         },
 
         query_phy: |state, req, c| {
@@ -106,29 +95,36 @@
 
         get_client_sme: |state, iface_id, server_end, c| {
             let server = state.lock().get_client_sme(iface_id);
-            if let Err(e) = connect_client_sme(server, server_end.into_channel(), &c) {
+            if let Err(e) = connect_client_sme(server, server_end, &c) {
                 eprintln!("get_client_sme: unexpected error: {:?}", e);
                 c.control_handle().shutdown();
             }
             future::ok(())
-        }
+        },
+
+        watch_devices: |state, watcher, _c| catch_and_log_err("watch_devices", || {
+            let control_handle = watcher.into_stream()?.control_handle();
+            state.lock().add_listener(Arc::new(control_handle));
+            Ok(())
+        }),
 
     }.serve(channel)
         .recover(|e| eprintln!("error running wlan device service: {:?}", e))
 }
 
-fn connect_client_sme(server: Option<super::device::ClientSmeServer>, channel: zx::Channel,
+fn connect_client_sme(server: Option<super::device::ClientSmeServer>,
+                      endpoint: super::station::ClientSmeEndpoint,
                       c: &wlan_service::DeviceServiceGetClientSmeResponder)
     -> Result<(), Error>
 {
     if let Some(ref s) = &server {
-        s.unbounded_send(async::Channel::from_channel(channel)?)?;
+        s.unbounded_send(endpoint)?;
     }
     c.send(server.is_some())?;
     Ok(())
 }
 
-impl device::EventListener for DeviceServiceControlHandle {
+impl device::EventListener for DeviceWatcherControlHandle {
     fn on_phy_added(&self, id: u16) -> Result<(), Error> {
         self.send_on_phy_added(id).map_err(Into::into)
     }
diff --git a/bin/wlanstack/src/station.rs b/bin/wlanstack/src/station.rs
index f148b26..8ae5fa0 100644
--- a/bin/wlanstack/src/station.rs
+++ b/bin/wlanstack/src/station.rs
@@ -5,16 +5,15 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-use fidl;
+use fidl::{self, endpoints2::RequestStream};
 use wlan_sme::{client, Station, MlmeRequest, MlmeStream};
 use wlan_sme::client::{DiscoveryError, DiscoveryResult, DiscoveredEss};
 use fidl_mlme::MlmeProxy;
-use fidl_sme::{self, ClientSme, ScanTransaction};
+use fidl_sme::{self, ClientSmeRequest};
 use std::sync::{Arc, Mutex};
 use failure;
-use futures::{future, prelude::*};
+use futures::{prelude::*, stream};
 use futures::channel::mpsc;
-use async;
 use zx;
 
 struct ClientTokens;
@@ -23,39 +22,59 @@
     type ScanToken = fidl_sme::ScanTransactionControlHandle;
 }
 
+pub type ClientSmeEndpoint = fidl::endpoints2::ServerEnd<fidl_sme::ClientSmeMarker>;
 type Client = client::ClientSme<ClientTokens>;
 
-pub fn serve_client_sme(proxy: MlmeProxy, new_fidl_clients: mpsc::UnboundedReceiver<async::Channel>)
-    -> impl Future<Item = (), Error = ::fidl::Error>
+pub fn serve_client_sme(proxy: MlmeProxy,
+                        new_fidl_clients: mpsc::UnboundedReceiver<ClientSmeEndpoint>)
+    -> impl Future<Item = (), Error = failure::Error>
 {
     let (client, mlme_stream, user_stream) = Client::new();
     let client_arc = Arc::new(Mutex::new(client));
-
     // A future that handles MLME interactions
-    let station_server = serve_station(proxy, client_arc.clone(), mlme_stream);
-    // A future that forwards user events from the station to connected FIDL clients
-    let user_stream_server = serve_user_stream(user_stream)
-        // Map 'Never' to 'fidl::Error'
-        .map_err(|_| panic!("'Never' should never happen"));
-    // A future that handles requests from FIDL clients
-    let wlan_server = new_fidl_clients.for_each_concurrent(move |channel| {
-        new_client_service(client_arc.clone(), channel).recover(
-            |e| eprintln!("Error handling a FIDL request from user: {:?}", e)
-        )
-    }).map_err(|e| e.never_into());
-    station_server.join3(user_stream_server, wlan_server).map(|_| ())
+    let mlme_sme_fut = serve_mlme_sme(proxy, client_arc.clone(), mlme_stream);
+    let sme_fidl_fut = serve_client_sme_fidl(client_arc, new_fidl_clients, user_stream)
+        .map(|x| x.never_into::<()>());
+    mlme_sme_fut.select(sme_fidl_fut)
+        .map(|_| ())
+        .map_err(|e| e.either(|(x, _)| x.context("MLME<->SME future").into(),
+                              |(x, _)| x.context("SME<->FIDL future").into()))
 }
 
-fn serve_station<S: Station>(proxy: MlmeProxy, station: Arc<Mutex<S>>, mlme_stream: MlmeStream)
-     -> impl Future<Item = (), Error = ::fidl::Error>
+fn serve_client_sme_fidl(client_arc: Arc<Mutex<Client>>,
+                         new_fidl_clients: mpsc::UnboundedReceiver<ClientSmeEndpoint>,
+                         user_stream: client::UserStream<ClientTokens>)
+    -> impl Future<Item = Never, Error = failure::Error>
 {
-    let event_handler = proxy.take_event_stream().for_each(move |e| {
+    // A future that forwards user events from the station to connected FIDL clients
+    let sme_to_fidl = serve_user_stream(user_stream)
+        // Map 'Never' to 'fidl::Error'
+        .map_err(|e| e.never_into())
+        .and_then(|()| Err(format_err!("SME->FIDL future unexpectedly finished")));
+    // A future that handles requests from FIDL clients
+    let fidl_to_sme = new_fidl_clients
+        .map_err(|e| e.never_into())
+        .chain(stream::once(Err(format_err!("new FIDL client stream unexpectedly ended"))))
+        .for_each_concurrent(move |channel| {
+            new_client_service(client_arc.clone(), channel).recover(
+                |e| eprintln!("Error handling a FIDL request from user: {:?}", e)
+            )
+        })
+        .and_then(|_| Err(format_err!("FIDL->SME future unexpectedly finished")));
+    sme_to_fidl.join(fidl_to_sme).map(|x: (Never, Never)| x.0)
+}
+
+// The returned future successfully terminates when MLME closes the channel
+fn serve_mlme_sme<S: Station>(proxy: MlmeProxy, station: Arc<Mutex<S>>, mlme_stream: MlmeStream)
+     -> impl Future<Item = (), Error = failure::Error>
+{
+    let sme_to_mlme_fut = proxy.take_event_stream().for_each(move |e| {
         station.lock().unwrap().on_mlme_event(e);
         Ok(())
-    });
-    let mlme_sender = mlme_stream
+    }).map(|_| ()).err_into::<failure::Error>();
+    let mlme_to_sme_fut = mlme_stream
         // Map 'Never' to 'fidl::Error'
-        .map_err(|_| panic!("'Never' should never happen"))
+        .map_err(|e| e.never_into())
         .for_each(move |e| {
             match e {
                 MlmeRequest::Scan(mut req) => proxy.scan_req(&mut req),
@@ -64,44 +83,48 @@
                 MlmeRequest::Associate(mut req) => proxy.associate_req(&mut req),
                 MlmeRequest::Deauthenticate(mut req) => proxy.deauthenticate_req(&mut req),
             }
-        });
-    event_handler.join(mlme_sender).map(|_| ())
-}
-
-fn new_client_service(client_arc: Arc<Mutex<Client>>, channel: async::Channel)
-    -> impl Future<Item = (), Error = ::fidl::Error>
-{
-    fidl_sme::ClientSmeImpl {
-        state: client_arc.clone(),
-        on_open: |_, _| {
-            future::ok(())
-        },
-        scan: |state, _req, txn, c| {
-            match new_scan_transaction(txn.into_channel()) {
-                Ok(token) => {
-                    state.lock().unwrap().on_scan_command(token);
-                },
-                Err(e) => {
-                    eprintln!("Error starting a scan transaction: {:?}", e);
+        })
+        .then(|r| match r {
+            Ok(_) => Err(format_err!("SME->MLME sender future unexpectedly finished")),
+            Err(fidl::Error::ClientWrite(status)) => {
+                if status == zx::Status::PEER_CLOSED {
+                    // Don't treat closed channel as error; terminate the future peacefully instead
+                    Ok(())
+                } else {
+                    Err(fidl::Error::ClientWrite(status).into())
                 }
             }
-            future::ok(())
-        },
-    }.serve(channel)
+            Err(other) => Err(other.into()),
+        });
+    // Select, not join: terminate as soon as one of the futures terminates
+    sme_to_mlme_fut.select(mlme_to_sme_fut)
+        .map(|_| ())
+        .map_err(|e| e.either(|(x, _)| x.context("MLME->SME").into(),
+                              |(x, _)| x.context("SME->MLME").into()))
 }
 
-
-fn new_scan_transaction(channel: zx::Channel)
-    -> Result<fidl_sme::ScanTransactionControlHandle, failure::Error>
+fn new_client_service(client: Arc<Mutex<Client>>, endpoint: ClientSmeEndpoint)
+    -> impl Future<Item = (), Error = ::fidl::Error>
 {
-    let local = async::Channel::from_channel(channel)?;
-    let server_future = fidl_sme::ScanTransactionImpl {
-        state: (),
-        on_open: |_, _| {
-            future::ok(())
-        }
-    }.serve(local);
-    Ok(server_future.control_handle())
+    endpoint.into_stream().into_future()
+        .and_then(|s| {
+            s.for_each_concurrent(move |request| match request {
+                ClientSmeRequest::Scan { req, txn, control_handle } => {
+                    Ok(scan(&client, txn)
+                        .unwrap_or_else(|e| eprintln!("Error starting a scan transaction: {:?}", e)))
+                },
+            })
+            .map(|_| ())
+        })
+}
+
+fn scan(client: &Arc<Mutex<Client>>,
+        txn: fidl::endpoints2::ServerEnd<fidl_sme::ScanTransactionMarker>)
+    -> Result<(), failure::Error>
+{
+    let handle = txn.into_stream()?.control_handle();
+    client.lock().unwrap().on_scan_command(handle);
+    Ok(())
 }
 
 fn serve_user_stream(stream: client::UserStream<ClientTokens>)
diff --git a/bin/wlanstack/src/watchable_map.rs b/bin/wlanstack/src/watchable_map.rs
new file mode 100644
index 0000000..dc23594
--- /dev/null
+++ b/bin/wlanstack/src/watchable_map.rs
@@ -0,0 +1,177 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#![allow(dead_code)]
+
+use std::collections::{hash_map, HashMap};
+use std::hash::Hash;
+
+pub enum WatcherResult {
+    KeepWatching,
+    StopWatching
+}
+
+impl WatcherResult {
+    fn should_keep_watching(self) -> bool {
+        match self {
+            WatcherResult::KeepWatching => true,
+            WatcherResult::StopWatching => false,
+        }
+    }
+}
+
+pub trait MapWatcher<K> {
+    fn on_add_key(&self, key: &K) -> WatcherResult;
+    fn on_remove_key(&self, key: &K) -> WatcherResult;
+}
+
+pub struct WatchableMap<K, V, W> {
+    map: HashMap<K, V>,
+    watchers: HashMap<u64, W>,
+    next_watcher_id: u64,
+}
+
+impl<K, V, W> WatchableMap<K, V, W>
+    where K: Clone + Hash + Eq, W: MapWatcher<K>
+{
+    pub fn new() -> Self {
+        WatchableMap {
+            map: HashMap::new(),
+            watchers: HashMap::new(),
+            next_watcher_id: 0,
+        }
+    }
+
+    pub fn insert(&mut self, key: K, value: V) {
+        self.map.insert(key.clone(), value);
+        self.watchers.retain(|_, w| w.on_add_key(&key).should_keep_watching());
+    }
+
+    pub fn remove(&mut self, key: &K) {
+        if self.map.remove(key).is_some() {
+            self.watchers.retain(|_, w| w.on_remove_key(&key).should_keep_watching());
+        }
+    }
+
+    pub fn add_watcher(&mut self, watcher: W) -> Option<u64> {
+        for key in self.map.keys() {
+            if !watcher.on_add_key(key).should_keep_watching() {
+                return None;
+            }
+        }
+        let watcher_id = self.next_watcher_id;
+        self.next_watcher_id += 1;
+        self.watchers.insert(watcher_id, watcher);
+        Some(watcher_id)
+    }
+
+    pub fn remove_watcher(&mut self, id: u64) {
+        self.watchers.remove(&id);
+    }
+
+    pub fn iter(&self) -> hash_map::Iter<K, V> {
+        self.map.iter()
+    }
+
+    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
+        where K: ::std::borrow::Borrow<Q>, Q: Hash + Eq
+    {
+        self.map.get(k)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::cell::RefCell;
+    use std::rc::Rc;
+
+    #[derive(Debug, Eq, PartialEq)]
+    enum Event {
+        Add(u16),
+        Remove(u16)
+    }
+
+    impl MapWatcher<u16> for Rc<RefCell<Vec<Event>>> {
+        fn on_add_key(&self, key: &u16) -> WatcherResult {
+            self.borrow_mut().push(Event::Add(*key));
+            return if key % 2 == 1 { WatcherResult::KeepWatching } else { WatcherResult::StopWatching };
+        }
+        fn on_remove_key(&self, key: &u16) -> WatcherResult {
+            self.borrow_mut().push(Event::Remove(*key));
+            return if key % 2 == 1 { WatcherResult::KeepWatching } else { WatcherResult::StopWatching };
+        }
+    }
+
+    #[test]
+    fn insert_get_remove() {
+        let mut map = WatchableMap::<_, _, Rc<RefCell<Vec<Event>>>>::new();
+        map.insert(3u16, "foo");
+        assert_eq!(Some(&"foo"), map.get(&3u16));
+        map.remove(&3u16);
+        assert_eq!(None, map.get(&3u16));
+    }
+
+    #[test]
+    fn notified_on_insert_and_remove() {
+        let mut map = WatchableMap::new();
+        let watcher = Rc::new(RefCell::new(Vec::<Event>::new()));
+        map.add_watcher(watcher.clone());
+        map.insert(3u16, "foo");
+        map.insert(7u16, "bar");
+        map.remove(&3u16);
+        assert_eq!(*watcher.borrow(), vec![Event::Add(3u16), Event::Add(7u16), Event::Remove(3u16)]);
+    }
+
+    #[test]
+    fn not_notified_after_returning_stop() {
+        let mut map = WatchableMap::new();
+        let watcher = Rc::new(RefCell::new(Vec::<Event>::new()));
+        map.add_watcher(watcher.clone());
+        map.insert(3u16, "foo");
+        // Our watcher returns 'StopWatching' for even numbers
+        map.insert(4u16, "bar");
+        map.insert(7u16, "baz");
+        // 7 should not be recorded
+        assert_eq!(*watcher.borrow(), vec![Event::Add(3u16), Event::Add(4u16)]);
+    }
+
+    #[test]
+    fn not_notified_after_removing_watcher() {
+        let mut map = WatchableMap::new();
+        let watcher = Rc::new(RefCell::new(Vec::<Event>::new()));
+        let watcher_id = map.add_watcher(watcher.clone()).expect("add_watcher returned None");
+        map.insert(3u16, "foo");
+        map.insert(5u16, "bar");
+        map.remove_watcher(watcher_id);
+        map.insert(7u16, "baz");
+        // 7 should not be recorded
+        assert_eq!(*watcher.borrow(), vec![Event::Add(3u16), Event::Add(5u16)]);
+    }
+
+    #[test]
+    fn notified_of_existing_keys() {
+        let mut map = WatchableMap::new();
+        map.insert(3u16, "foo");
+        map.insert(5u16, "bar");
+        let watcher = Rc::new(RefCell::new(Vec::<Event>::new()));
+        map.add_watcher(watcher.clone()).expect("add_watcher returned None");
+        let mut sorted = watcher.borrow().iter().map(|e| {
+            match e {
+                Event::Add(id) => *id,
+                Event::Remove(id) => panic!("Unexpected Remove event with id {}", id),
+            }
+        }).collect::<Vec<_>>();
+        sorted.sort();
+        assert_eq!(sorted, vec![3u16, 5u16]);
+    }
+
+    #[test]
+    fn watcher_not_added_if_returned_stop() {
+        let mut map = WatchableMap::new();
+        map.insert(4u16, "foo");
+        let watcher = Rc::new(RefCell::new(Vec::<Event>::new()));
+        assert_eq!(None, map.add_watcher(watcher.clone()));
+    }
+}
diff --git a/bin/wlantool/src/main.rs b/bin/wlantool/src/main.rs
index 98548b8..b9fe73a 100644
--- a/bin/wlantool/src/main.rs
+++ b/bin/wlantool/src/main.rs
@@ -10,9 +10,9 @@
 #[macro_use]
 extern crate failure;
 extern crate fidl;
-extern crate fidl_wlan_device as wlan;
-extern crate fidl_wlan_device_service as wlan_service;
-extern crate fidl_wlan_sme as fidl_sme;
+extern crate fidl_fuchsia_wlan_device as wlan;
+extern crate fidl_fuchsia_wlan_device_service as wlan_service;
+extern crate fidl_fuchsia_wlan_sme as fidl_sme;
 extern crate fuchsia_app as component;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
@@ -22,7 +22,7 @@
 
 use component::client::connect_to_service;
 use failure::{Error, Fail, ResultExt};
-use fidl::endpoints2::{ClientEnd, ServerEnd, ServiceMarker};
+use fidl::endpoints2;
 use fidl_sme::ScanTransactionEvent;
 use futures::prelude::*;
 use structopt::StructOpt;
@@ -113,7 +113,7 @@
     match cmd {
         opts::ClientCmd::Scan { iface_id } => get_client_sme(wlan_svc, iface_id)
             .and_then(|sme| {
-                let (local, remote) = create_endpoints()?;
+                let (local, remote) = endpoints2::create_endpoints()?;
                 let mut req = fidl_sme::ScanRequest {
                     timeout: 10
                 };
@@ -158,8 +158,9 @@
 fn get_client_sme(wlan_svc: WlanSvc, iface_id: u16)
     -> impl Future<Item = fidl_sme::ClientSmeProxy, Error = Error>
 {
-    create_endpoints()
+    endpoints2::create_endpoints()
         .into_future()
+        .map_err(|e| e.into())
         .and_then(move |(proxy, remote)| {
             wlan_svc.get_client_sme(iface_id, remote)
                 .map_err(|e| e.context("error sending GetClientSme request").into())
@@ -172,10 +173,3 @@
                 })
         })
 }
-
-// This should probably be in endpoints2
-fn create_endpoints<T: ServiceMarker>() -> Result<(T::Proxy, ServerEnd<T>), Error> {
-    let (client, server) = zx::Channel::create()?;
-    Ok((ClientEnd::<T>::new(client).into_proxy()?, ServerEnd::new(server)))
-}
-
diff --git a/bin/zircon_benchmarks/BUILD.gn b/bin/zircon_benchmarks/BUILD.gn
index a15ab28..d74aa90 100644
--- a/bin/zircon_benchmarks/BUILD.gn
+++ b/bin/zircon_benchmarks/BUILD.gn
@@ -70,7 +70,8 @@
 
 fidl("fidl_interface") {
   testonly = true
-  name = "zircon_benchmarks"
+  name = "fuchsia.zircon.benchmarks"
+  cpp_legacy_callbacks = true
   sources = [
     "round_trip_service.fidl",
   ]
diff --git a/bin/zircon_benchmarks/round_trip_service.fidl b/bin/zircon_benchmarks/round_trip_service.fidl
index f939e6c..daab61f 100644
--- a/bin/zircon_benchmarks/round_trip_service.fidl
+++ b/bin/zircon_benchmarks/round_trip_service.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library zircon_benchmarks;
+library fuchsia.zircon.benchmarks;
 
 // Example interface for testing performance of round trips.
 interface RoundTripService {
diff --git a/bin/zircon_benchmarks/round_trips.cc b/bin/zircon_benchmarks/round_trips.cc
index 620aa26..182bdd0 100644
--- a/bin/zircon_benchmarks/round_trips.cc
+++ b/bin/zircon_benchmarks/round_trips.cc
@@ -6,8 +6,9 @@
 #include <thread>
 #include <vector>
 
+#include <fuchsia/zircon/benchmarks/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
-#include <fdio/spawn.h>
+#include <lib/fdio/spawn.h>
 #include <zircon/process.h>
 #include <zircon/processargs.h>
 #include <zircon/syscalls.h>
@@ -16,7 +17,6 @@
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/logging.h"
 
-#include <zircon_benchmarks/cpp/fidl.h>
 #include "channels.h"
 #include "round_trips.h"
 #include "test_runner.h"
@@ -534,7 +534,7 @@
 };
 
 // Implementation of FIDL interface for testing round trip IPCs.
-class RoundTripServiceImpl : public zircon_benchmarks::RoundTripService {
+class RoundTripServiceImpl : public fuchsia::zircon::benchmarks::RoundTripService {
  public:
   void RoundTripTest(uint32_t arg, RoundTripTestCallback callback) override {
     FXL_CHECK(arg == 123);
@@ -557,7 +557,7 @@
 
     async::Loop loop (&kAsyncLoopConfigMakeDefault);
     RoundTripServiceImpl service_impl;
-    fidl::Binding<zircon_benchmarks::RoundTripService> binding(
+    fidl::Binding<fuchsia::zircon::benchmarks::RoundTripService> binding(
         &service_impl, std::move(channel));
     binding.set_error_handler([&loop] { loop.Quit(); });
     loop.Run();
@@ -571,7 +571,7 @@
 
  private:
   ThreadOrProcess thread_or_process_;
-  zircon_benchmarks::RoundTripServiceSyncPtr service_ptr_;
+  fuchsia::zircon::benchmarks::RoundTripServiceSyncPtr service_ptr_;
 };
 
 // Test the round trip time for waking up threads using Zircon futexes.
diff --git a/bin/zxdb/client/BUILD.gn b/bin/zxdb/client/BUILD.gn
index f23a357..56228d7 100644
--- a/bin/zxdb/client/BUILD.gn
+++ b/bin/zxdb/client/BUILD.gn
@@ -37,6 +37,10 @@
     "process.cc",
     "process_impl.cc",
     "process_impl.h",
+    "remote_api.cc",
+    "remote_api.h",
+    "remote_api_impl.cc",
+    "remote_api_impl.h",
     "session.cc",
     "system.cc",
     "system_impl.cc",
@@ -70,24 +74,36 @@
   public = [
     "client_object.h",
     "err.h",
-    "host_utils.h",
+    "file_util.h",
+    "host_util.h",
+    "string_util.h",
   ]
   sources = [
     "client_object.cc",
     "err.cc",
-    "host_utils.cc",
+    "file_util.cc",
+    "host_util.cc",
+    "string_util.cc",
+  ]
+
+  public_deps = [
+    "//garnet/public/lib/fxl",
   ]
 }
 
 source_set("tests") {
   testonly = true
   sources = [
+    "breakpoint_impl_unittest.cc",
     "disassembler_unittest.cc",
+    "file_util_unittest.cc",
     "memory_dump_unittest.cc",
+    "string_util_unittest.cc",
   ]
 
   deps = [
     ":client",
+    "symbols:test_support",
     "symbols:tests",
     "//third_party/googletest:gtest",
   ]
diff --git a/bin/zxdb/client/arch_info.cc b/bin/zxdb/client/arch_info.cc
index 6b481ba..317dcc7 100644
--- a/bin/zxdb/client/arch_info.cc
+++ b/bin/zxdb/client/arch_info.cc
@@ -10,8 +10,8 @@
 #include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 
 namespace zxdb {
diff --git a/bin/zxdb/client/breakpoint.h b/bin/zxdb/client/breakpoint.h
index 2bef9b6..73ee7d1 100644
--- a/bin/zxdb/client/breakpoint.h
+++ b/bin/zxdb/client/breakpoint.h
@@ -32,9 +32,6 @@
   virtual void SetSettings(const BreakpointSettings& settings,
                            std::function<void(const Err&)> callback) = 0;
 
-  // Returns the number of times this breakpoint has been hit.
-  virtual int GetHitCount() const = 0;
-
  protected:
   fxl::ObserverList<BreakpointObserver>& observers() { return observers_; }
 
diff --git a/bin/zxdb/client/breakpoint_impl.cc b/bin/zxdb/client/breakpoint_impl.cc
index 38009ea..aeea901 100644
--- a/bin/zxdb/client/breakpoint_impl.cc
+++ b/bin/zxdb/client/breakpoint_impl.cc
@@ -5,10 +5,14 @@
 #include "garnet/bin/zxdb/client/breakpoint_impl.h"
 
 #include <inttypes.h>
+#include <algorithm>
 
 #include "garnet/bin/zxdb/client/err.h"
 #include "garnet/bin/zxdb/client/process.h"
+#include "garnet/bin/zxdb/client/remote_api.h"
 #include "garnet/bin/zxdb/client/session.h"
+#include "garnet/bin/zxdb/client/symbols/loaded_module_symbols.h"
+#include "garnet/bin/zxdb/client/symbols/process_symbols.h"
 #include "garnet/bin/zxdb/client/system.h"
 #include "garnet/bin/zxdb/client/target.h"
 #include "garnet/bin/zxdb/client/thread.h"
@@ -21,13 +25,11 @@
 uint32_t next_breakpoint_id = 1;
 
 Err ValidateSettings(const BreakpointSettings& settings) {
-  // Validate scope.
   switch (settings.scope) {
     case BreakpointSettings::Scope::kSystem:
-      // TODO(brettw) implement this.
-      return Err(
-          "System scopes aren't supported since only address breakpoints"
-          " are supported now.");
+      if (settings.scope_thread || settings.scope_target)
+        return Err("System scopes can't take a thread or target.");
+      break;
     case BreakpointSettings::Scope::kTarget:
       if (!settings.scope_target)
         return Err(ErrType::kClientApi, "Target scopes require a target.");
@@ -58,24 +60,37 @@
 
 }  // namespace
 
+struct BreakpointImpl::ProcessRecord {
+  // Set when we're registered as an observer for this process.
+  bool observing = false;
+
+  // All resolved locations stored in sorted order.
+  std::vector<uint64_t> addresses;
+};
+
 BreakpointImpl::BreakpointImpl(Session* session)
-    : Breakpoint(session), weak_factory_(this) {}
+    : Breakpoint(session), weak_factory_(this) {
+  session->system().AddObserver(this);
+}
 
 BreakpointImpl::~BreakpointImpl() {
   if (backend_id_ && settings_.enabled && settings_.scope_target &&
       settings_.scope_target->GetProcess()) {
     // Breakpoint was installed and the process still exists.
     settings_.enabled = false;
-    SendBreakpointRemove(settings_.scope_target->GetProcess(),
-                         std::function<void(const Err&)>());
+    SendBackendRemove(std::function<void(const Err&)>());
   }
 
-  StopObserving();
+  session()->system().RemoveObserver(this);
+  for (auto& pair : procs_) {
+    if (pair.second.observing) {
+      pair.first->RemoveObserver(this);
+      pair.second.observing = false;
+    }
+  }
 }
 
-BreakpointSettings BreakpointImpl::GetSettings() const {
-  return settings_;
-}
+BreakpointSettings BreakpointImpl::GetSettings() const { return settings_; }
 
 void BreakpointImpl::SetSettings(const BreakpointSettings& settings,
                                  std::function<void(const Err&)> callback) {
@@ -86,22 +101,15 @@
     return;
   }
 
-  // It's cleaner to always unregister for existing notifications and
-  // re-register for the new ones.
-  StopObserving();
   settings_ = settings;
-  StartObserving();
 
-  // SendBackendUpdate() will issue the callback in the future.
-  err = SendBackendUpdate(callback);
-  if (err.has_error()) {
-    debug_ipc::MessageLoop::Current()->PostTask(
-        [callback, err]() { callback(err); });
+  for (Target* target : session()->system().GetTargets()) {
+    Process* process = target->GetProcess();
+    if (process && CouldApplyToProcess(process))
+      RegisterProcess(process);
   }
-}
 
-int BreakpointImpl::GetHitCount() const {
-  return hit_count_;
+  SyncBackend(std::move(callback));
 }
 
 void BreakpointImpl::WillDestroyThread(Process* process, Thread* thread) {
@@ -111,181 +119,237 @@
     // will preserve its state without us having to maintain some "defunct
     // thread" association. The user can associate it with a new thread and
     // re-enable as desired.
-    StopObserving();
     settings_.scope = BreakpointSettings::Scope::kTarget;
     settings_.scope_target = process->GetTarget();
     settings_.scope_thread = nullptr;
     settings_.enabled = false;
-    StartObserving();
   }
 }
 
-void BreakpointImpl::DidCreateProcess(Target* target, Process* process) {
-  // Register observer for thread changes.
-  process->AddObserver(this);
+void BreakpointImpl::DidLoadModuleSymbols(Process* process,
+                                          LoadedModuleSymbols* module) {
+  // Should only get this notification for relevant processes.
+  FXL_DCHECK(CouldApplyToProcess(process));
+
+  // Resolve addresses.
+  if (settings_.location_type == BreakpointSettings::LocationType::kSymbol) {
+    std::vector<uint64_t> new_addrs =
+        module->AddressesForFunction(settings_.location_symbol);
+    if (new_addrs.empty())
+      return;
+
+    // Merge in the new address(s).
+    ProcessRecord& record = procs_[process];
+    record.addresses.insert(record.addresses.end(), new_addrs.begin(),
+                            new_addrs.end());
+    std::sort(record.addresses.begin(), record.addresses.end());
+  } else if (settings_.location_type ==
+             BreakpointSettings::LocationType::kLine) {
+    printf("TODO(brettw) implement line-based breakpoints.\n");
+    return;
+  }
+
+  // If we get here, something has changed.
+  SyncBackend();
 }
 
-void BreakpointImpl::DidDestroyProcess(Target* target, DestroyReason reason,
-                                       int exit_code) {
-  // When the process exits, disable breakpoints that are address-based since
-  // the addresses will normally change when a process is loaded.
-  // TODO(brettw) when we have symbolic breakpoints, exclude them from this
-  // behavior.
-  if (settings_.location_address)
-    settings_.enabled = false;
-  backend_id_ = 0;
+void BreakpointImpl::WillUnloadModuleSymbols(Process* process,
+                                             LoadedModuleSymbols* module) {
+  // TODO(brettw) need to get the address range of this module and then
+  // remove all breakpoints in that range.
 }
 
 void BreakpointImpl::WillDestroyTarget(Target* target) {
   if (target == settings_.scope_target) {
+    // By the time the target is destroyed, the process should be gone, and
+    // all registrations for breakpoints.
+    FXL_DCHECK(!HasLocations());
+
     // As with threads going away, when the target goes away for a
     // target-scoped breakpoint, convert to a disabled system-wide breakpoint.
-    StopObserving();
     settings_.scope = BreakpointSettings::Scope::kSystem;
     settings_.scope_target = nullptr;
     settings_.scope_thread = nullptr;
     settings_.enabled = false;
-    StartObserving();
   }
 }
 
-Err BreakpointImpl::SendBackendUpdate(
-    std::function<void(const Err&)> callback) {
-  if (!settings_.scope_target)
-    return Err("TODO(brettw) need to support non-target breakpoints.");
-  Process* process = settings_.scope_target->GetProcess();
-  // TODO(brettw) does this need to be deleted???
-  if (!process)
-    return Err();  // Process not running, don't try to set any breakpoints.
+void BreakpointImpl::GlobalDidCreateProcess(Process* process) {
+  if (CouldApplyToProcess(process)) {
+    if (RegisterProcess(process))
+      SyncBackend();
+  }
+}
 
-  if (!backend_id_) {
-    if (!settings_.enabled) {
-      // The breakpoint isn't enabled and there's no backend breakpoint to
-      // clear, don't need to do anything.
+void BreakpointImpl::GlobalWillDestroyProcess(Process* process) {
+  auto found = procs_.find(process);
+  if (found == procs_.end())
+    return;
+
+  if (found->second.observing)
+    process->RemoveObserver(this);
+
+  // Only need to update the backend if there was an address associated with
+  // this process.
+  bool send_update = !found->second.addresses.empty();
+
+  // When the process exits, disable breakpoints that are address-based since
+  // the addresses will normally change when a process is loaded.
+  if (settings_.location_type == BreakpointSettings::LocationType::kAddress) {
+    // Should only have one process for address-based breakpoints.
+    FXL_DCHECK(procs_.size() == 1u);
+    FXL_DCHECK(process->GetTarget() == settings_.scope_target);
+    settings_.enabled = false;
+  }
+
+  procs_.erase(found);
+
+  // Needs to be done after the ProcessRecord is removed.
+  if (send_update)
+    SyncBackend();
+}
+
+void BreakpointImpl::SyncBackend(std::function<void(const Err&)> callback) {
+  bool has_locations = HasLocations();
+
+  if (backend_id_ && !has_locations) {
+    SendBackendRemove(std::move(callback));
+  } else if (has_locations) {
+    SendBackendAddOrChange(std::move(callback));
+  } else {
+    // Backend doesn't know about it and we don't require anything.
+    if (callback) {
       debug_ipc::MessageLoop::Current()->PostTask(
           [callback]() { callback(Err()); });
-      return Err();
     }
+  }
+}
 
-    // Assign a new ID.
+void BreakpointImpl::SendBackendAddOrChange(
+    std::function<void(const Err&)> callback) {
+  if (!backend_id_) {
     backend_id_ = next_breakpoint_id;
     next_breakpoint_id++;
-  } else {
-    // Backend breakpoint exists.
-    if (!settings_.enabled) {
-      // Disable the backend breakpoint.
-      SendBreakpointRemove(process, std::move(callback));
-      return Err();
-    }
   }
 
-  // New or changed breakpoint.
-  SendAddOrChange(process, callback);
-  return Err();
-}
-
-void BreakpointImpl::StopObserving() {
-  if (is_system_observer_) {
-    session()->system().RemoveObserver(this);
-    is_system_observer_ = false;
-  }
-  if (is_target_observer_) {
-    settings_.scope_target->RemoveObserver(this);
-    is_target_observer_ = false;
-  }
-  if (is_process_observer_) {
-    // We should be unregistered when the process is going away.
-    settings_.scope_target->GetProcess()->RemoveObserver(this);
-    is_process_observer_ = false;
-  }
-}
-
-void BreakpointImpl::StartObserving() {
-  // Nothing should be registered (call StopObserving first).
-  FXL_DCHECK(!is_system_observer_ && !is_target_observer_ &&
-             !is_process_observer_);
-
-  // Always watch the system.
-  session()->system().AddObserver(this);
-  is_system_observer_ = true;
-
-  if (settings_.scope == BreakpointSettings::Scope::kTarget ||
-      settings_.scope == BreakpointSettings::Scope::kThread) {
-    settings_.scope_target->AddObserver(this);
-    is_target_observer_ = true;
-  }
-  if (settings_.scope == BreakpointSettings::Scope::kThread) {
-    settings_.scope_thread->GetProcess()->AddObserver(this);
-    is_process_observer_ = true;
-  }
-}
-
-void BreakpointImpl::SendAddOrChange(Process* process,
-                                     std::function<void(const Err&)> callback) {
-  FXL_DCHECK(backend_id_); // ID should have been assigned by the caller.
-  FXL_DCHECK(settings_.enabled);  // Shouldn't add or change disabled ones.
-
   debug_ipc::AddOrChangeBreakpointRequest request;
   request.breakpoint.breakpoint_id = backend_id_;
   request.breakpoint.stop = SettingsStopToIpcStop(settings_.stop_mode);
 
-  request.breakpoint.locations.resize(1);
-  request.breakpoint.locations[0].process_koid = process->GetKoid();
-  request.breakpoint.locations[0].thread_koid =
-      settings_.scope_thread ? settings_.scope_thread->GetKoid() : 0;
-  request.breakpoint.locations[0].address = settings_.location_address;
+  for (const auto& proc : procs_) {
+    for (uint64_t addr : proc.second.addresses) {
+      debug_ipc::ProcessBreakpointSettings addition;
+      addition.process_koid = proc.first->GetKoid();
 
-  session()->Send<debug_ipc::AddOrChangeBreakpointRequest,
-                  debug_ipc::AddOrChangeBreakpointReply>(
-    request,
-    [callback, breakpoint = weak_factory_.GetWeakPtr()](
-        const Err& err, debug_ipc::AddOrChangeBreakpointReply reply) {
-      // Be sure to issue the callback even if the breakpoint no longer exists.
-      if (err.has_error()) {
-        // Transport error. We don't actually know what state the agent is in
-        // since it never got the message. In general this means things were
-        // disconnected and the agent no longer exists, so mark the breakpoint
-        // disabled.
-        if (breakpoint)
-          breakpoint->settings_.enabled = false;
-        if (callback)
-          callback(err);
-      } else if (reply.status != 0) {
-        // Backend error. The protocol specifies that errors adding or changing
-        // will result in any existing breakpoints with that ID being removed.
-        // So mark the breakpoint disabled but keep the settings to the user
-        // can fix the problem from the current state if desired.
-        if (breakpoint)
-          breakpoint->settings_.enabled = false;
-        if (callback)
-          callback(Err(ErrType::kGeneral, "Breakpoint set error."));
-      } else {
-        // Success.
-        if (callback)
-          callback(Err());
-      }
-    });
+      if (settings_.scope == BreakpointSettings::Scope::kThread)
+        addition.thread_koid = settings_.scope_thread->GetKoid();
+
+      addition.address = addr;
+      request.breakpoint.locations.push_back(addition);
+    }
+  }
+
+  if (settings_.scope == BreakpointSettings::Scope::kThread)
+    FXL_DCHECK(request.breakpoint.locations.size() == 1u);
+
+  session()->remote_api()->AddOrChangeBreakpoint(request, [
+    callback, breakpoint = weak_factory_.GetWeakPtr()
+  ](const Err& err, debug_ipc::AddOrChangeBreakpointReply reply) {
+    // Be sure to issue the callback even if the breakpoint no longer
+    // exists.
+    if (err.has_error()) {
+      // Transport error. We don't actually know what state the agent is in
+      // since it never got the message. In general this means things were
+      // disconnected and the agent no longer exists, so mark the breakpoint
+      // disabled.
+      if (breakpoint)
+        breakpoint->settings_.enabled = false;
+      if (callback)
+        callback(err);
+    } else if (reply.status != 0) {
+      // Backend error. The protocol specifies that errors adding or
+      // changing will result in any existing breakpoints with that ID
+      // being removed. So mark the breakpoint disabled but keep the
+      // settings to the user can fix the problem from the current state if
+      // desired.
+      if (breakpoint)
+        breakpoint->settings_.enabled = false;
+      if (callback)
+        callback(Err(ErrType::kGeneral, "Breakpoint set error."));
+    } else {
+      // Success.
+      if (callback)
+        callback(Err());
+    }
+  });
 }
 
-void BreakpointImpl::SendBreakpointRemove(
-    Process* process,
+void BreakpointImpl::SendBackendRemove(
     std::function<void(const Err&)> callback) {
-  FXL_DCHECK(!settings_.enabled);  // Caller should have disabled already.
   FXL_DCHECK(backend_id_);
 
   debug_ipc::RemoveBreakpointRequest request;
   request.breakpoint_id = backend_id_;
 
-  session()->Send<debug_ipc::RemoveBreakpointRequest,
-                  debug_ipc::RemoveBreakpointReply>(
-    request,
-    [callback](const Err& err, debug_ipc::RemoveBreakpointReply reply) {
-      if (callback)
-        callback(Err());
-    });
+  session()->remote_api()->RemoveBreakpoint(
+      request,
+      [callback](const Err& err, debug_ipc::RemoveBreakpointReply reply) {
+        if (callback)
+          callback(err);
+      });
 
   // Indicate the backend breakpoint is gone.
   backend_id_ = 0;
 }
 
+bool BreakpointImpl::CouldApplyToProcess(Process* process) const {
+  // When applied to all processes, we need all notifications.
+  if (settings_.scope == BreakpointSettings::Scope::kSystem)
+    return true;
+
+  // Target- and thread-specific breakpoints only watch their process.
+  return settings_.scope_target == process->GetTarget();
+}
+
+bool BreakpointImpl::HasLocations() const {
+  if (!settings_.enabled)
+    return false;
+
+  for (const auto& proc : procs_) {
+    if (!proc.second.addresses.empty())
+      return true;
+  }
+  return false;
+}
+
+bool BreakpointImpl::RegisterProcess(Process* process) {
+  bool changed = false;
+
+  if (!procs_[process].observing) {
+    procs_[process].observing = true;
+    process->AddObserver(this);
+  }
+
+  // Resolve addresses.
+  ProcessSymbols* symbols = process->GetSymbols();
+  if (settings_.location_type == BreakpointSettings::LocationType::kSymbol) {
+    std::vector<uint64_t> new_addrs =
+        symbols->GetAddressesForFunction(settings_.location_symbol);
+
+    // The ProcessRecord stores sorted addresses (this ensures the comparison
+    // below is valid).
+    std::sort(new_addrs.begin(), new_addrs.end());
+
+    ProcessRecord& record = procs_[process];
+    if (record.addresses != new_addrs) {
+      record.addresses = std::move(new_addrs);
+      changed = true;
+    }
+  } else if (settings_.location_type ==
+             BreakpointSettings::LocationType::kLine) {
+    printf("TODO(brettw) implement line-based breakpoints.\n");
+  }
+  return changed;
+}
+
 }  // namespace zxdb
diff --git a/bin/zxdb/client/breakpoint_impl.h b/bin/zxdb/client/breakpoint_impl.h
index 4ad1ed3..46b7ebe 100644
--- a/bin/zxdb/client/breakpoint_impl.h
+++ b/bin/zxdb/client/breakpoint_impl.h
@@ -4,66 +4,70 @@
 
 #pragma once
 
+#include <map>
+
 #include "garnet/bin/zxdb/client/breakpoint.h"
 #include "garnet/bin/zxdb/client/process_observer.h"
-#include "garnet/bin/zxdb/client/target_observer.h"
 #include "garnet/bin/zxdb/client/system_observer.h"
+#include "garnet/bin/zxdb/client/target_observer.h"
 #include "garnet/public/lib/fxl/memory/weak_ptr.h"
 
 namespace zxdb {
 
 class BreakpointImpl : public Breakpoint,
                        public ProcessObserver,
-                       public TargetObserver,
                        public SystemObserver {
  public:
-  BreakpointImpl(Session* session);
+  explicit BreakpointImpl(Session* session);
   ~BreakpointImpl() override;
 
   // Breakpoint implementation:
   BreakpointSettings GetSettings() const override;
   void SetSettings(const BreakpointSettings& settings,
                    std::function<void(const Err&)> callback) override;
-  int GetHitCount() const override;
 
  private:
-  // On failure, returns the error and doesn't do anything with the callback.
-  // On success, schedules the callback to run.
-  Err SendBackendUpdate(std::function<void(const Err&)> callback);
-
-  // Attaches and detaches from the events that this object observes.
-  void StopObserving();
-  void StartObserving();
+  struct ProcessRecord;
 
   // ProcessObserver.
   void WillDestroyThread(Process* process, Thread* thread) override;
-
-  // TargetObserver.
-  void DidCreateProcess(Target* target, Process* process) override;
-  void DidDestroyProcess(Target* target, DestroyReason reason,
-                         int exit_code) override;
+  void DidLoadModuleSymbols(Process* process,
+                            LoadedModuleSymbols* module) override;
+  void WillUnloadModuleSymbols(Process* process,
+                               LoadedModuleSymbols* module) override;
 
   // SystemObserver.
   void WillDestroyTarget(Target* target) override;
+  void GlobalDidCreateProcess(Process* process) override;
+  void GlobalWillDestroyProcess(Process* process) override;
 
-  void SendAddOrChange(Process* process,
-                       std::function<void(const Err&)> callback);
-  void SendBreakpointRemove(Process* process,
-                            std::function<void(const Err&)> callback);
+  void SyncBackend(std::function<void(const Err&)> callback =
+                       std::function<void(const Err&)>());
+  void SendBackendAddOrChange(std::function<void(const Err&)> callback);
+  void SendBackendRemove(std::function<void(const Err&)> callback);
+
+  // Returns true if the breakpoint could possibly apply to the given process
+  // (if things like symbols aren't found, it still may not necessarily apply).
+  bool CouldApplyToProcess(Process* process) const;
+
+  // Returns true if there are any enabled breakpoint locations that the
+  // backend needs to know about.
+  bool HasLocations() const;
+
+  // Given a process which is new or might apply to us for the first time,
+  // Returns true if any addresses were resolved.
+  bool RegisterProcess(Process* process);
 
   BreakpointSettings settings_;
 
-  // TODO(brettw) this assumes exactly one backend breakpoint in one process.
-  // A symbolic breakpoitn can have multiple locations and be in multiple
-  // processes. 0 means no current backend breakpoint.
+  // Every process which this breakpoint can apply to is in this map, even if
+  // there are no addresses assocaited with it.
+  std::map<Process*, ProcessRecord> procs_;
+
+  // ID used to refer to this in the backend. 0 means no current backend
+  // breakpoint.
   uint32_t backend_id_ = 0;
 
-  int hit_count_ = 0;
-
-  bool is_system_observer_ = false;
-  bool is_target_observer_ = false;
-  bool is_process_observer_ = false;
-
   fxl::WeakPtrFactory<BreakpointImpl> weak_factory_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(BreakpointImpl);
diff --git a/bin/zxdb/client/breakpoint_impl_unittest.cc b/bin/zxdb/client/breakpoint_impl_unittest.cc
new file mode 100644
index 0000000..2ed1a64
--- /dev/null
+++ b/bin/zxdb/client/breakpoint_impl_unittest.cc
@@ -0,0 +1,192 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "garnet/bin/zxdb/client/breakpoint_impl.h"
+#include "garnet/bin/zxdb/client/process_impl.h"
+#include "garnet/bin/zxdb/client/remote_api.h"
+#include "garnet/bin/zxdb/client/session.h"
+#include "garnet/bin/zxdb/client/symbols/mock_module_symbols.h"
+#include "garnet/bin/zxdb/client/target_impl.h"
+#include "garnet/lib/debug_ipc/helper/platform_message_loop.h"
+#include "garnet/lib/debug_ipc/helper/test_stream_buffer.h"
+#include "gtest/gtest.h"
+
+namespace zxdb {
+
+namespace {
+
+using debug_ipc::MessageLoop;
+
+class BreakpointSink : public RemoteAPI {
+ public:
+  using AddPair = std::pair<
+      debug_ipc::AddOrChangeBreakpointRequest,
+      std::function<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)>>;
+  using RemovePair = std::pair<
+      debug_ipc::RemoveBreakpointRequest,
+      std::function<void(const Err&, debug_ipc::RemoveBreakpointReply)>>;
+
+  void AddOrChangeBreakpoint(
+      const debug_ipc::AddOrChangeBreakpointRequest& request,
+      std::function<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)> cb)
+      override {
+    adds.push_back(std::make_pair(request, cb));
+  }
+
+  void RemoveBreakpoint(
+      const debug_ipc::RemoveBreakpointRequest& request,
+      std::function<void(const Err&, debug_ipc::RemoveBreakpointReply)> cb)
+      override {
+    removes.push_back(std::make_pair(request, cb));
+  }
+
+  std::vector<AddPair> adds;
+  std::vector<RemovePair> removes;
+};
+
+class BreakpointImplTest : public testing::Test {
+ public:
+  BreakpointImplTest() {
+    loop_.Init();
+    sink_ = new BreakpointSink;
+    session_ = std::make_unique<Session>(std::unique_ptr<RemoteAPI>(sink_));
+  }
+  ~BreakpointImplTest() {
+    session_.reset();
+    loop_.Cleanup();
+  }
+
+  // Emulates a synchronous call to SetSettings on a breakpoint.
+  Err SyncSetSettings(Breakpoint& bp, const BreakpointSettings& settings) {
+    Err out_err;
+    bp.SetSettings(settings, [&out_err](const Err& new_err) {
+      out_err = new_err;
+      MessageLoop::Current()->QuitNow();
+    });
+    loop().Run();
+    return out_err;
+  }
+
+  debug_ipc::PlatformMessageLoop& loop() { return loop_; }
+  debug_ipc::TestStreamBuffer& stream() { return stream_; }
+  BreakpointSink& sink() { return *sink_; }
+  Session& session() { return *session_; }
+
+ private:
+  debug_ipc::PlatformMessageLoop loop_;
+  debug_ipc::TestStreamBuffer stream_;
+
+  BreakpointSink* sink_;  // Owned by the session_.
+
+  std::unique_ptr<Session> session_;
+};
+
+}  // namespace
+
+TEST_F(BreakpointImplTest, DynamicLoading) {
+  BreakpointImpl bp(&session());
+
+  // Make a disabled symbolic breakpoint.
+  const std::string kFunctionName = "DoThings";
+  BreakpointSettings in;
+  in.enabled = false;
+  in.scope = BreakpointSettings::Scope::kSystem;
+  in.location_type = BreakpointSettings::LocationType::kSymbol;
+  in.location_symbol = kFunctionName;
+
+  // Setting the disabled settings shouldn't update the backend.
+  Err err = SyncSetSettings(bp, in);
+  EXPECT_FALSE(err.has_error());
+  ASSERT_TRUE(sink().adds.empty());
+
+  // Setting enabled settings with no processes should not update the backend.
+  in.enabled = true;
+  err = SyncSetSettings(bp, in);
+  EXPECT_FALSE(err.has_error());
+  ASSERT_TRUE(sink().adds.empty());
+
+  TargetImpl* target = session().system_impl().GetTargetImpls()[0];
+
+  // Create a process for it. Since the process doesn't resolve the symbol
+  // yet, no messages should be sent.
+  const uint64_t koid = 5678;
+  target->CreateProcessForTesting(koid, "test");
+  ASSERT_TRUE(sink().adds.empty());
+
+  // Make two fake modules. The first will resolve the function to two
+  // locations, the second will resolve nothing.
+  const uint64_t kRelAddress1 = 0x78456345;
+  const uint64_t kRelAddress2 = 0x12345678;
+  std::unique_ptr<MockModuleSymbols> module1 =
+      std::make_unique<MockModuleSymbols>("myfile1.so");
+  std::unique_ptr<MockModuleSymbols> module2 =
+      std::make_unique<MockModuleSymbols>("myfile2.so");
+  module1->AddSymbol(kFunctionName,
+                     std::vector<uint64_t>{kRelAddress1, kRelAddress2});
+
+  // Cause the process to load the module. We have to keep the module_ref
+  // alive for this to stay cached in the SystemSymbols.
+  const std::string kBuildID1 = "abcd";
+  const std::string kBuildID2 = "zyxw";
+  fxl::RefPtr<SystemSymbols::ModuleRef> module1_ref =
+      session().system_impl().symbols().InjectModuleForTesting(
+          kBuildID1, std::move(module1));
+  fxl::RefPtr<SystemSymbols::ModuleRef> module2_ref =
+      session().system_impl().symbols().InjectModuleForTesting(
+          kBuildID2, std::move(module2));
+
+  // Cause the process to load module 1.
+  const uint64_t kModule1Base = 0x1000000;
+  debug_ipc::Module load1;
+  load1.name = "test";
+  load1.base = kModule1Base;
+  load1.build_id = kBuildID1;
+  target->process()->NotifyModuleLoaded(load1);
+
+  // That should have notified the breakpoint which should have added the two
+  // addresses to the backend.
+  ASSERT_FALSE(sink().adds.empty());
+  debug_ipc::AddOrChangeBreakpointRequest out = sink().adds[0].first;
+  EXPECT_FALSE(out.breakpoint.one_shot);
+  EXPECT_EQ(debug_ipc::Stop::kAll, out.breakpoint.stop);
+
+  // Both locations should be for the same process, with no thread restriction.
+  ASSERT_EQ(2u, out.breakpoint.locations.size());
+  EXPECT_EQ(koid, out.breakpoint.locations[0].process_koid);
+  EXPECT_EQ(koid, out.breakpoint.locations[1].process_koid);
+  EXPECT_EQ(0u, out.breakpoint.locations[0].thread_koid);
+  EXPECT_EQ(0u, out.breakpoint.locations[1].thread_koid);
+
+  // Addresses could be in either order. They should be absolute.
+  const uint64_t kAddress1 = kModule1Base + kRelAddress1;
+  const uint64_t kAddress2 = kModule1Base + kRelAddress2;
+  EXPECT_TRUE((out.breakpoint.locations[0].address == kAddress1 &&
+               out.breakpoint.locations[1].address == kAddress2) ||
+              (out.breakpoint.locations[0].address == kAddress2 &&
+               out.breakpoint.locations[1].address == kAddress1));
+
+  // Adding another module with nothing to resolve should send no messages.
+  sink().adds.clear();
+  const uint64_t kModule2Base = 0x2000000;
+  debug_ipc::Module load2;
+  load2.name = "test2";
+  load2.base = kModule2Base;
+  load2.build_id = kBuildID2;
+  target->process()->NotifyModuleLoaded(load2);
+  ASSERT_TRUE(sink().adds.empty());
+
+  // Disabling should send the delete message.
+  ASSERT_TRUE(sink().removes.empty());  // Should have none so far.
+  in.enabled = false;
+  err = SyncSetSettings(bp, in);
+  EXPECT_FALSE(err.has_error());
+  ASSERT_TRUE(sink().adds.empty());
+  ASSERT_EQ(1u, sink().removes.size());
+  EXPECT_EQ(out.breakpoint.breakpoint_id,
+            sink().removes[0].first.breakpoint_id);
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/breakpoint_settings.h b/bin/zxdb/client/breakpoint_settings.h
index 2af5378..7d6f66e 100644
--- a/bin/zxdb/client/breakpoint_settings.h
+++ b/bin/zxdb/client/breakpoint_settings.h
@@ -28,12 +28,7 @@
   };
 
   // How this breakpoint's location was specified.
-  enum class LocationType {
-    kNone,
-    kLine,
-    kSymbol,
-    kAddress
-  };
+  enum class LocationType { kNone, kLine, kSymbol, kAddress };
 
   // What to stop when this breakpoint is hit.
   enum class StopMode {
diff --git a/bin/zxdb/client/disassembler.cc b/bin/zxdb/client/disassembler.cc
index 3f3c02d..2987e82 100644
--- a/bin/zxdb/client/disassembler.cc
+++ b/bin/zxdb/client/disassembler.cc
@@ -14,8 +14,8 @@
 #include "garnet/public/lib/fxl/strings/trim.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCInstPrinter.h"
 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCInstPrinter.h"
 #include "llvm/Support/TargetRegistry.h"
 
 namespace zxdb {
@@ -24,8 +24,7 @@
 
 // In-place replaces instances of ANY of the charcters in "search_for" with the
 // given replacement in the given string.
-void ReplaceAllInstancesOf(const char* search_for,
-                           char replace_with,
+void ReplaceAllInstancesOf(const char* search_for, char replace_with,
                            std::string* str) {
   size_t found_pos = 0;
   while ((found_pos = str->find_first_of(search_for, found_pos)) !=
@@ -34,10 +33,8 @@
   }
 }
 
-void GetInvalidInstructionStrs(const uint8_t* data,
-                               size_t len,
-                               std::string* instruction,
-                               std::string* params,
+void GetInvalidInstructionStrs(const uint8_t* data, size_t len,
+                               std::string* instruction, std::string* params,
                                std::string* comment) {
   *instruction = ".byte";
   params->clear();
@@ -77,13 +74,9 @@
 // Formats the asembly instruction and adds it to the row. Using this function
 // consistently ensures that there is always the same number of columns in
 // each output row.
-void WriteRow(const Disassembler::Options& options,
-              uint64_t address,
-              const uint8_t* bytes,
-              size_t bytes_len,
-              std::string instruction,
-              std::string params,
-              std::string comment,
+void WriteRow(const Disassembler::Options& options, uint64_t address,
+              const uint8_t* bytes, size_t bytes_len, std::string instruction,
+              std::string params, std::string comment,
               std::vector<std::string>* out) {
   out->clear();
 
@@ -131,10 +124,8 @@
   return Err();
 }
 
-size_t Disassembler::DisassembleOne(const uint8_t* data,
-                                    size_t data_len,
-                                    uint64_t address,
-                                    const Options& options,
+size_t Disassembler::DisassembleOne(const uint8_t* data, size_t data_len,
+                                    uint64_t address, const Options& options,
                                     std::vector<std::string>* out) const {
   out->clear();
 
@@ -185,11 +176,8 @@
 }
 
 size_t Disassembler::DisassembleMany(
-    const uint8_t* data,
-    size_t data_len,
-    uint64_t start_address,
-    const Options& in_options,
-    size_t max_instructions,
+    const uint8_t* data, size_t data_len, uint64_t start_address,
+    const Options& in_options, size_t max_instructions,
     std::vector<std::vector<std::string>>* out) const {
   if (max_instructions == 0)
     max_instructions = std::numeric_limits<size_t>::max();
@@ -213,9 +201,7 @@
 }
 
 size_t Disassembler::DisassembleDump(
-    const MemoryDump& dump,
-    const Options& options,
-    size_t max_instructions,
+    const MemoryDump& dump, const Options& options, size_t max_instructions,
     std::vector<std::vector<std::string>>* out) const {
   if (max_instructions == 0)
     max_instructions = std::numeric_limits<size_t>::max();
diff --git a/bin/zxdb/client/disassembler.h b/bin/zxdb/client/disassembler.h
index 53ab023..e0aa4d6 100644
--- a/bin/zxdb/client/disassembler.h
+++ b/bin/zxdb/client/disassembler.h
@@ -58,9 +58,7 @@
   // The number of bytes consumed will be returned.
   //
   // Be sure the input buffer always has enough data for any instruction.
-  size_t DisassembleOne(const uint8_t* data,
-                        size_t data_len,
-                        uint64_t address,
+  size_t DisassembleOne(const uint8_t* data, size_t data_len, uint64_t address,
                         const Options& options,
                         std::vector<std::string>* out) const;
 
@@ -74,10 +72,8 @@
   //
   // The output will be one vector of columns per line. See DisassembleOne for
   // row format.
-  size_t DisassembleMany(const uint8_t* data,
-                         size_t data_len,
-                         uint64_t start_address,
-                         const Options& options,
+  size_t DisassembleMany(const uint8_t* data, size_t data_len,
+                         uint64_t start_address, const Options& options,
                          size_t max_instructions,
                          std::vector<std::vector<std::string>>* out) const;
 
@@ -89,8 +85,7 @@
   // An unmapped range will be counted as one instruction. The memory
   // addresses for unmapped ranges will always be shown even if disabled in the
   // options.
-  size_t DisassembleDump(const MemoryDump& dump,
-                         const Options& options,
+  size_t DisassembleDump(const MemoryDump& dump, const Options& options,
                          size_t max_instructions,
                          std::vector<std::vector<std::string>>* out) const;
 
diff --git a/bin/zxdb/client/file_util.cc b/bin/zxdb/client/file_util.cc
new file mode 100644
index 0000000..9475e2b
--- /dev/null
+++ b/bin/zxdb/client/file_util.cc
@@ -0,0 +1,16 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/file_util.h"
+
+namespace zxdb {
+
+fxl::StringView ExtractLastFileComponent(fxl::StringView path) {
+  size_t last_slash = path.rfind('/');
+  if (last_slash == std::string::npos)
+    return path;
+  return path.substr(last_slash + 1);
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/file_util.h b/bin/zxdb/client/file_util.h
new file mode 100644
index 0000000..913b2c9
--- /dev/null
+++ b/bin/zxdb/client/file_util.h
@@ -0,0 +1,17 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include "garnet/public/lib/fxl/strings/string_view.h"
+
+namespace zxdb {
+
+// Extracts the substring into the given file path of the last path component
+// (the stuff following the last slash). If the path ends in a slash, it will
+// return an empty StringView. If the input has no slash, it will return the
+// whole thing.
+fxl::StringView ExtractLastFileComponent(fxl::StringView path);
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/file_util_unittest.cc b/bin/zxdb/client/file_util_unittest.cc
new file mode 100644
index 0000000..fbde44c
--- /dev/null
+++ b/bin/zxdb/client/file_util_unittest.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/file_util.h"
+#include "gtest/gtest.h"
+
+namespace zxdb {
+
+TEST(FileUtil, ExtractLastFileComponent) {
+  EXPECT_EQ("", ExtractLastFileComponent(""));
+  EXPECT_EQ("", ExtractLastFileComponent("foo/"));
+  EXPECT_EQ("foo.cpp", ExtractLastFileComponent("foo.cpp"));
+  EXPECT_EQ("foo.cpp", ExtractLastFileComponent("bar/foo.cpp"));
+  EXPECT_EQ("foo.cpp", ExtractLastFileComponent("baz/bar/foo.cpp"));
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/frame_impl.h b/bin/zxdb/client/frame_impl.h
index f1a23e4..fc412ff 100644
--- a/bin/zxdb/client/frame_impl.h
+++ b/bin/zxdb/client/frame_impl.h
@@ -15,8 +15,7 @@
 // A frame is lazily symbolized.
 class FrameImpl : public Frame {
  public:
-  FrameImpl(ThreadImpl* thread,
-            const debug_ipc::StackFrame& stack_frame,
+  FrameImpl(ThreadImpl* thread, const debug_ipc::StackFrame& stack_frame,
             Location location);
   ~FrameImpl() override;
 
diff --git a/bin/zxdb/client/host_utils.cc b/bin/zxdb/client/host_util.cc
similarity index 94%
rename from bin/zxdb/client/host_utils.cc
rename to bin/zxdb/client/host_util.cc
index 69b3a43..2cda83e 100644
--- a/bin/zxdb/client/host_utils.cc
+++ b/bin/zxdb/client/host_util.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "garnet/bin/zxdb/client/host_utils.h"
+#include "garnet/bin/zxdb/client/host_util.h"
 
 #include <limits.h>
 #include <unistd.h>
diff --git a/bin/zxdb/client/host_utils.h b/bin/zxdb/client/host_util.h
similarity index 100%
rename from bin/zxdb/client/host_utils.h
rename to bin/zxdb/client/host_util.h
diff --git a/bin/zxdb/client/process.h b/bin/zxdb/client/process.h
index 48c7755..78b2e0b 100644
--- a/bin/zxdb/client/process.h
+++ b/bin/zxdb/client/process.h
@@ -98,8 +98,7 @@
 
   // Reads memory from the debugged process.
   virtual void ReadMemory(
-      uint64_t address,
-      uint32_t size,
+      uint64_t address, uint32_t size,
       std::function<void(const Err&, MemoryDump)> callback) = 0;
 
  protected:
diff --git a/bin/zxdb/client/process_impl.cc b/bin/zxdb/client/process_impl.cc
index daf53fa..5ae8304 100644
--- a/bin/zxdb/client/process_impl.cc
+++ b/bin/zxdb/client/process_impl.cc
@@ -7,6 +7,7 @@
 #include <set>
 
 #include "garnet/bin/zxdb/client/memory_dump.h"
+#include "garnet/bin/zxdb/client/remote_api.h"
 #include "garnet/bin/zxdb/client/session.h"
 #include "garnet/bin/zxdb/client/target_impl.h"
 #include "garnet/bin/zxdb/client/thread_impl.h"
@@ -14,8 +15,7 @@
 
 namespace zxdb {
 
-ProcessImpl::ProcessImpl(TargetImpl* target,
-                         uint64_t koid,
+ProcessImpl::ProcessImpl(TargetImpl* target, uint64_t koid,
                          const std::string& name)
     : Process(target->session()),
       target_(target),
@@ -39,27 +39,19 @@
   return found->second.get();
 }
 
-Target* ProcessImpl::GetTarget() const {
-  return target_;
-}
+Target* ProcessImpl::GetTarget() const { return target_; }
 
-uint64_t ProcessImpl::GetKoid() const {
-  return koid_;
-}
+uint64_t ProcessImpl::GetKoid() const { return koid_; }
 
-const std::string& ProcessImpl::GetName() const {
-  return name_;
-}
+const std::string& ProcessImpl::GetName() const { return name_; }
 
-ProcessSymbols* ProcessImpl::GetSymbols() {
-  return &symbols_;
-}
+ProcessSymbols* ProcessImpl::GetSymbols() { return &symbols_; }
 
 void ProcessImpl::GetModules(
     std::function<void(const Err&, std::vector<debug_ipc::Module>)> callback) {
   debug_ipc::ModulesRequest request;
   request.process_koid = koid_;
-  session()->Send<debug_ipc::ModulesRequest, debug_ipc::ModulesReply>(
+  session()->remote_api()->Modules(
       request, [process = weak_factory_.GetWeakPtr(), callback](
                    const Err& err, debug_ipc::ModulesReply reply) {
         if (process)
@@ -76,7 +68,7 @@
   debug_ipc::AddressSpaceRequest request;
   request.process_koid = koid_;
   request.address = address;
-  session()->Send<debug_ipc::AddressSpaceRequest, debug_ipc::AddressSpaceReply>(
+  session()->remote_api()->AddressSpace(
       request, [callback](const Err& err, debug_ipc::AddressSpaceReply reply) {
         if (callback)
           callback(err, std::move(reply.map));
@@ -98,7 +90,7 @@
 void ProcessImpl::SyncThreads(std::function<void()> callback) {
   debug_ipc::ThreadsRequest request;
   request.process_koid = koid_;
-  session()->Send<debug_ipc::ThreadsRequest, debug_ipc::ThreadsReply>(
+  session()->remote_api()->Threads(
       request, [callback, process = weak_factory_.GetWeakPtr()](
                    const Err& err, debug_ipc::ThreadsReply reply) {
         if (process) {
@@ -113,8 +105,8 @@
   debug_ipc::PauseRequest request;
   request.process_koid = koid_;
   request.thread_koid = 0;  // 0 means all threads.
-  session()->Send<debug_ipc::PauseRequest, debug_ipc::PauseReply>(
-      request, [](const Err& err, debug_ipc::PauseReply) {});
+  session()->remote_api()->Pause(request,
+                                 [](const Err& err, debug_ipc::PauseReply) {});
 }
 
 void ProcessImpl::Continue() {
@@ -122,19 +114,18 @@
   request.process_koid = koid_;
   request.thread_koid = 0;  // 0 means all threads.
   request.how = debug_ipc::ResumeRequest::How::kContinue;
-  session()->Send<debug_ipc::ResumeRequest, debug_ipc::ResumeReply>(
+  session()->remote_api()->Resume(
       request, [](const Err& err, debug_ipc::ResumeReply) {});
 }
 
 void ProcessImpl::ReadMemory(
-    uint64_t address,
-    uint32_t size,
+    uint64_t address, uint32_t size,
     std::function<void(const Err&, MemoryDump)> callback) {
   debug_ipc::ReadMemoryRequest request;
   request.process_koid = koid_;
   request.address = address;
   request.size = size;
-  session()->Send<debug_ipc::ReadMemoryRequest, debug_ipc::ReadMemoryReply>(
+  session()->remote_api()->ReadMemory(
       request, [callback](const Err& err, debug_ipc::ReadMemoryReply reply) {
         callback(err, MemoryDump(std::move(reply.blocks)));
       });
@@ -170,6 +161,10 @@
   threads_.erase(found);
 }
 
+void ProcessImpl::NotifyModuleLoaded(const debug_ipc::Module& module) {
+  symbols_.AddModule(module, std::function<void(const std::string&)>());
+}
+
 void ProcessImpl::UpdateThreads(
     const std::vector<debug_ipc::ThreadRecord>& new_threads) {
   // Go through all new threads, checking to added ones and updating existing.
diff --git a/bin/zxdb/client/process_impl.h b/bin/zxdb/client/process_impl.h
index af474a8..d3dfc3f 100644
--- a/bin/zxdb/client/process_impl.h
+++ b/bin/zxdb/client/process_impl.h
@@ -44,14 +44,16 @@
   void Pause() override;
   void Continue() override;
   void ReadMemory(
-      uint64_t address,
-      uint32_t size,
+      uint64_t address, uint32_t size,
       std::function<void(const Err&, MemoryDump)> callback) override;
 
   // Notifications from the agent that a thread has started or exited.
   void OnThreadStarting(const debug_ipc::ThreadRecord& record);
   void OnThreadExiting(const debug_ipc::ThreadRecord& record);
 
+  // Notification that a module has been loaded.
+  void NotifyModuleLoaded(const debug_ipc::Module& module);
+
  private:
   // Syncs the threads_ list to the new list of threads passed in .
   void UpdateThreads(const std::vector<debug_ipc::ThreadRecord>& new_threads);
diff --git a/bin/zxdb/client/remote_api.cc b/bin/zxdb/client/remote_api.cc
new file mode 100644
index 0000000..0e4b7a9
--- /dev/null
+++ b/bin/zxdb/client/remote_api.cc
@@ -0,0 +1,101 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/remote_api.h"
+
+#include "garnet/bin/zxdb/client/session.h"
+#include "garnet/public/lib/fxl/logging.h"
+
+namespace zxdb {
+
+void RemoteAPI::Hello(
+    const debug_ipc::HelloRequest& request,
+    std::function<void(const Err&, debug_ipc::HelloReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Launch(
+    const debug_ipc::LaunchRequest& request,
+    std::function<void(const Err&, debug_ipc::LaunchReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Kill(const debug_ipc::KillRequest& request,
+                     std::function<void(const Err&, debug_ipc::KillReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Attach(
+    const debug_ipc::AttachRequest& request,
+    std::function<void(const Err&, debug_ipc::AttachReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Detach(
+    const debug_ipc::DetachRequest& request,
+    std::function<void(const Err&, debug_ipc::DetachReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Modules(
+    const debug_ipc::ModulesRequest& request,
+    std::function<void(const Err&, debug_ipc::ModulesReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Pause(
+    const debug_ipc::PauseRequest& request,
+    std::function<void(const Err&, debug_ipc::PauseReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Resume(
+    const debug_ipc::ResumeRequest& request,
+    std::function<void(const Err&, debug_ipc::ResumeReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::ProcessTree(
+    const debug_ipc::ProcessTreeRequest& request,
+    std::function<void(const Err&, debug_ipc::ProcessTreeReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Threads(
+    const debug_ipc::ThreadsRequest& request,
+    std::function<void(const Err&, debug_ipc::ThreadsReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::ReadMemory(
+    const debug_ipc::ReadMemoryRequest& request,
+    std::function<void(const Err&, debug_ipc::ReadMemoryReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::AddOrChangeBreakpoint(
+    const debug_ipc::AddOrChangeBreakpointRequest& request,
+    std::function<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::RemoveBreakpoint(
+    const debug_ipc::RemoveBreakpointRequest& request,
+    std::function<void(const Err&, debug_ipc::RemoveBreakpointReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::Backtrace(
+    const debug_ipc::BacktraceRequest& request,
+    std::function<void(const Err&, debug_ipc::BacktraceReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+void RemoteAPI::AddressSpace(
+    const debug_ipc::AddressSpaceRequest& request,
+    std::function<void(const Err&, debug_ipc::AddressSpaceReply)> cb) {
+  FXL_NOTREACHED();
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/remote_api.h b/bin/zxdb/client/remote_api.h
new file mode 100644
index 0000000..60fc624
--- /dev/null
+++ b/bin/zxdb/client/remote_api.h
@@ -0,0 +1,76 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <functional>
+
+#include "garnet/lib/debug_ipc/protocol.h"
+#include "garnet/public/lib/fxl/macros.h"
+
+namespace zxdb {
+
+class Err;
+
+// Abstracts the IPC layer for sending messages to the debug agent. This allows
+// mocking of the interface without dealing with the innards of the
+// serialization.
+//
+// The default implementations of each of these functions asserts. The Session
+// implements overrides that actually send and receive messages. Tests should
+// derive from this and implement the messages they expect.
+class RemoteAPI {
+ public:
+  RemoteAPI() = default;
+  virtual ~RemoteAPI() = default;
+
+  virtual void Hello(const debug_ipc::HelloRequest& request,
+                     std::function<void(const Err&, debug_ipc::HelloReply)> cb);
+  virtual void Launch(
+      const debug_ipc::LaunchRequest& request,
+      std::function<void(const Err&, debug_ipc::LaunchReply)> cb);
+  virtual void Kill(const debug_ipc::KillRequest& request,
+                    std::function<void(const Err&, debug_ipc::KillReply)> cb);
+  virtual void Attach(
+      const debug_ipc::AttachRequest& request,
+      std::function<void(const Err&, debug_ipc::AttachReply)> cb);
+  virtual void Detach(
+      const debug_ipc::DetachRequest& request,
+      std::function<void(const Err&, debug_ipc::DetachReply)> cb);
+  virtual void Modules(
+      const debug_ipc::ModulesRequest& request,
+      std::function<void(const Err&, debug_ipc::ModulesReply)> cb);
+  virtual void Pause(const debug_ipc::PauseRequest& request,
+                     std::function<void(const Err&, debug_ipc::PauseReply)> cb);
+  virtual void Resume(
+      const debug_ipc::ResumeRequest& request,
+      std::function<void(const Err&, debug_ipc::ResumeReply)> cb);
+  virtual void ProcessTree(
+      const debug_ipc::ProcessTreeRequest& request,
+      std::function<void(const Err&, debug_ipc::ProcessTreeReply)> cb);
+  virtual void Threads(
+      const debug_ipc::ThreadsRequest& request,
+      std::function<void(const Err&, debug_ipc::ThreadsReply)> cb);
+  virtual void ReadMemory(
+      const debug_ipc::ReadMemoryRequest& request,
+      std::function<void(const Err&, debug_ipc::ReadMemoryReply)> cb);
+  virtual void AddOrChangeBreakpoint(
+      const debug_ipc::AddOrChangeBreakpointRequest& request,
+      std::function<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)>
+          cb);
+  virtual void RemoveBreakpoint(
+      const debug_ipc::RemoveBreakpointRequest& request,
+      std::function<void(const Err&, debug_ipc::RemoveBreakpointReply)> cb);
+  virtual void Backtrace(
+      const debug_ipc::BacktraceRequest& request,
+      std::function<void(const Err&, debug_ipc::BacktraceReply)> cb);
+  virtual void AddressSpace(
+      const debug_ipc::AddressSpaceRequest& request,
+      std::function<void(const Err&, debug_ipc::AddressSpaceReply)> cb);
+
+ private:
+  FXL_DISALLOW_COPY_AND_ASSIGN(RemoteAPI);
+};
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/remote_api_impl.cc b/bin/zxdb/client/remote_api_impl.cc
new file mode 100644
index 0000000..7a8476e
--- /dev/null
+++ b/bin/zxdb/client/remote_api_impl.cc
@@ -0,0 +1,170 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/remote_api_impl.h"
+
+#include "garnet/bin/zxdb/client/session.h"
+#include "garnet/lib/debug_ipc/client_protocol.h"
+#include "garnet/lib/debug_ipc/helper/message_loop.h"
+#include "garnet/lib/debug_ipc/helper/stream_buffer.h"
+#include "garnet/lib/debug_ipc/message_reader.h"
+#include "garnet/lib/debug_ipc/message_writer.h"
+#include "garnet/public/lib/fxl/logging.h"
+#include "garnet/public/lib/fxl/strings/string_printf.h"
+//#include "garnet/lib/debug_ipc/helper/buffered_fd.h"
+
+namespace zxdb {
+
+RemoteAPIImpl::RemoteAPIImpl(Session* session) : session_(session) {}
+RemoteAPIImpl::~RemoteAPIImpl() = default;
+
+void RemoteAPIImpl::Hello(
+    const debug_ipc::HelloRequest& request,
+    std::function<void(const Err&, debug_ipc::HelloReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Launch(
+    const debug_ipc::LaunchRequest& request,
+    std::function<void(const Err&, debug_ipc::LaunchReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Kill(
+    const debug_ipc::KillRequest& request,
+    std::function<void(const Err&, debug_ipc::KillReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Attach(
+    const debug_ipc::AttachRequest& request,
+    std::function<void(const Err&, debug_ipc::AttachReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Detach(
+    const debug_ipc::DetachRequest& request,
+    std::function<void(const Err&, debug_ipc::DetachReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Modules(
+    const debug_ipc::ModulesRequest& request,
+    std::function<void(const Err&, debug_ipc::ModulesReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Pause(
+    const debug_ipc::PauseRequest& request,
+    std::function<void(const Err&, debug_ipc::PauseReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Resume(
+    const debug_ipc::ResumeRequest& request,
+    std::function<void(const Err&, debug_ipc::ResumeReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::ProcessTree(
+    const debug_ipc::ProcessTreeRequest& request,
+    std::function<void(const Err&, debug_ipc::ProcessTreeReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Threads(
+    const debug_ipc::ThreadsRequest& request,
+    std::function<void(const Err&, debug_ipc::ThreadsReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::ReadMemory(
+    const debug_ipc::ReadMemoryRequest& request,
+    std::function<void(const Err&, debug_ipc::ReadMemoryReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::AddOrChangeBreakpoint(
+    const debug_ipc::AddOrChangeBreakpointRequest& request,
+    std::function<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::RemoveBreakpoint(
+    const debug_ipc::RemoveBreakpointRequest& request,
+    std::function<void(const Err&, debug_ipc::RemoveBreakpointReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::Backtrace(
+    const debug_ipc::BacktraceRequest& request,
+    std::function<void(const Err&, debug_ipc::BacktraceReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+void RemoteAPIImpl::AddressSpace(
+    const debug_ipc::AddressSpaceRequest& request,
+    std::function<void(const Err&, debug_ipc::AddressSpaceReply)> cb) {
+  Send(request, std::move(cb));
+}
+
+template <typename SendMsgType, typename RecvMsgType>
+void RemoteAPIImpl::Send(
+    const SendMsgType& send_msg,
+    std::function<void(const Err&, RecvMsgType)> callback) {
+  uint32_t transaction_id = session_->next_transaction_id_;
+  session_->next_transaction_id_++;
+
+  if (!session_->stream_) {
+    // No connection, asynchronously issue the error.
+    if (callback) {
+      debug_ipc::MessageLoop::Current()->PostTask([callback]() {
+        callback(
+            Err(ErrType::kNoConnection, "No connection to debugged system."),
+            RecvMsgType());
+      });
+    }
+    return;
+  }
+
+  debug_ipc::MessageWriter writer(sizeof(SendMsgType));
+  debug_ipc::WriteRequest(send_msg, transaction_id, &writer);
+
+  std::vector<char> serialized = writer.MessageComplete();
+  session_->stream_->Write(std::move(serialized));
+
+  // This is the reply callback that unpacks the data in a vector, converts it
+  // to the requested RecvMsgType struct, and issues the callback.
+  Session::Callback dispatch_callback =
+      [callback = std::move(callback)](const Err& err, std::vector<char> data) {
+        RecvMsgType reply;
+        if (err.has_error()) {
+          // Forward the error and ignore all data.
+          if (callback)
+            callback(err, std::move(reply));
+          return;
+        }
+
+        debug_ipc::MessageReader reader(std::move(data));
+
+        uint32_t transaction_id = 0;
+        Err deserialization_err;
+        if (!debug_ipc::ReadReply(&reader, &reply, &transaction_id)) {
+          reply = RecvMsgType();  // Could be in a half-read state.
+          deserialization_err =
+              Err(ErrType::kCorruptMessage,
+                  fxl::StringPrintf("Corrupt reply message for transaction %u.",
+                                    transaction_id));
+        }
+
+        if (callback)
+          callback(deserialization_err, std::move(reply));
+      };
+
+  session_->pending_.emplace(
+      std::piecewise_construct, std::forward_as_tuple(transaction_id),
+      std::forward_as_tuple(std::move(dispatch_callback)));
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/remote_api_impl.h b/bin/zxdb/client/remote_api_impl.h
new file mode 100644
index 0000000..8beba6f
--- /dev/null
+++ b/bin/zxdb/client/remote_api_impl.h
@@ -0,0 +1,88 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include "garnet/bin/zxdb/client/remote_api.h"
+
+namespace zxdb {
+
+class Session;
+
+// An implementation of RemoteAPI for Session. This class is logically part of
+// the Session class (it's a friend) but is separated out for clarity.
+class RemoteAPIImpl : public RemoteAPI {
+ public:
+  // The session must outlive this object.
+  explicit RemoteAPIImpl(Session* session);
+  ~RemoteAPIImpl();
+
+  // RemoteAPI implementation.
+  void Hello(
+      const debug_ipc::HelloRequest& request,
+      std::function<void(const Err&, debug_ipc::HelloReply)> cb) override;
+  void Launch(
+      const debug_ipc::LaunchRequest& request,
+      std::function<void(const Err&, debug_ipc::LaunchReply)> cb) override;
+  void Kill(const debug_ipc::KillRequest& request,
+            std::function<void(const Err&, debug_ipc::KillReply)> cb) override;
+  void Attach(
+      const debug_ipc::AttachRequest& request,
+      std::function<void(const Err&, debug_ipc::AttachReply)> cb) override;
+  void Detach(
+      const debug_ipc::DetachRequest& request,
+      std::function<void(const Err&, debug_ipc::DetachReply)> cb) override;
+  void Modules(
+      const debug_ipc::ModulesRequest& request,
+      std::function<void(const Err&, debug_ipc::ModulesReply)> cb) override;
+  void Pause(
+      const debug_ipc::PauseRequest& request,
+      std::function<void(const Err&, debug_ipc::PauseReply)> cb) override;
+  void Resume(
+      const debug_ipc::ResumeRequest& request,
+      std::function<void(const Err&, debug_ipc::ResumeReply)> cb) override;
+  void ProcessTree(
+      const debug_ipc::ProcessTreeRequest& request,
+      std::function<void(const Err&, debug_ipc::ProcessTreeReply)> cb) override;
+  void Threads(
+      const debug_ipc::ThreadsRequest& request,
+      std::function<void(const Err&, debug_ipc::ThreadsReply)> cb) override;
+  void ReadMemory(
+      const debug_ipc::ReadMemoryRequest& request,
+      std::function<void(const Err&, debug_ipc::ReadMemoryReply)> cb) override;
+  void AddOrChangeBreakpoint(
+      const debug_ipc::AddOrChangeBreakpointRequest& request,
+      std::function<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)> cb)
+      override;
+  void RemoveBreakpoint(
+      const debug_ipc::RemoveBreakpointRequest& request,
+      std::function<void(const Err&, debug_ipc::RemoveBreakpointReply)> cb)
+      override;
+  void Backtrace(
+      const debug_ipc::BacktraceRequest& request,
+      std::function<void(const Err&, debug_ipc::BacktraceReply)> cb) override;
+  void AddressSpace(
+      const debug_ipc::AddressSpaceRequest& request,
+      std::function<void(const Err&, debug_ipc::AddressSpaceReply)> cb)
+      override;
+
+ private:
+  // Sends a message with an asynchronous reply.
+  //
+  // The callback will be issued with an Err struct. If the Err object
+  // indicates an error, the request has failed and the reply data will not be
+  // set (it will contain the default-constructed data).
+  //
+  // The callback will always be issued asynchronously (not from withing the
+  // Send() function itself).
+  template <typename SendMsgType, typename RecvMsgType>
+  void Send(const SendMsgType& send_msg,
+            std::function<void(const Err&, RecvMsgType)> callback);
+
+  Session* session_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(RemoteAPIImpl);
+};
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/session.cc b/bin/zxdb/client/session.cc
index e798960..3a32143 100644
--- a/bin/zxdb/client/session.cc
+++ b/bin/zxdb/client/session.cc
@@ -10,14 +10,19 @@
 #include <netdb.h>
 #include <stdio.h>
 #include <sys/socket.h>
-#include <thread>
 #include <unistd.h>
+#include <thread>
 
 #include "garnet/bin/zxdb/client/arch_info.h"
 #include "garnet/bin/zxdb/client/process_impl.h"
+#include "garnet/bin/zxdb/client/remote_api_impl.h"
 #include "garnet/bin/zxdb/client/thread_impl.h"
+#include "garnet/lib/debug_ipc/client_protocol.h"
 #include "garnet/lib/debug_ipc/helper/buffered_fd.h"
+#include "garnet/lib/debug_ipc/helper/message_loop.h"
 #include "garnet/lib/debug_ipc/helper/stream_buffer.h"
+#include "garnet/lib/debug_ipc/message_reader.h"
+#include "garnet/lib/debug_ipc/message_writer.h"
 #include "garnet/public/lib/fxl/logging.h"
 #include "garnet/public/lib/fxl/memory/ref_counted.h"
 #include "garnet/public/lib/fxl/strings/string_printf.h"
@@ -130,8 +135,7 @@
 };
 
 void Session::PendingConnection::Initiate(
-    fxl::WeakPtr<Session> session,
-    std::function<void(const Err&)> callback) {
+    fxl::WeakPtr<Session> session, std::function<void(const Err&)> callback) {
   FXL_DCHECK(!thread_.get());  // Duplicate Initiate() call.
 
   main_loop_ = debug_ipc::MessageLoop::Current();
@@ -140,9 +144,8 @@
 
   // Create the background thread, and run the background function. The
   // context will keep a ref to this class.
-  thread_ =
-      std::make_unique<std::thread>([owner = fxl::RefPtr<PendingConnection>(
-                                         this)]() {
+  thread_ = std::make_unique<std::thread>(
+      [owner = fxl::RefPtr<PendingConnection>(this)]() {
         owner->ConnectBackgroundThread(owner);
       });
 }
@@ -150,14 +153,13 @@
 void Session::PendingConnection::ConnectBackgroundThread(
     fxl::RefPtr<PendingConnection> owner) {
   Err err = DoConnectBackgroundThread();
-  main_loop_->PostTask([ owner = std::move(owner), err ]() {
+  main_loop_->PostTask([owner = std::move(owner), err]() {
     owner->ConnectCompleteMainThread(owner, err);
   });
 }
 
 void Session::PendingConnection::ConnectCompleteMainThread(
-    fxl::RefPtr<PendingConnection> owner,
-    const Err& err) {
+    fxl::RefPtr<PendingConnection> owner, const Err& err) {
   // The background thread function has now completed so the thread can be
   // destroyed. We do want to join with the thread here to ensure there are no
   // references to the PendingConnection on the background thread, which might
@@ -183,9 +185,8 @@
   std::vector<char> serialized = writer.MessageComplete();
   buffer_->stream().Write(std::move(serialized));
 
-  buffer_->set_data_available_callback([owner = std::move(owner)]() {
-    owner->DataAvailableMainThread(owner);
-  });
+  buffer_->set_data_available_callback(
+      [owner = std::move(owner)]() { owner->DataAvailableMainThread(owner); });
 }
 
 void Session::PendingConnection::DataAvailableMainThread(
@@ -222,8 +223,7 @@
 }
 
 void Session::PendingConnection::HelloCompleteMainThread(
-    fxl::RefPtr<PendingConnection> owner,
-    const Err& err,
+    fxl::RefPtr<PendingConnection> owner, const Err& err,
     const debug_ipc::HelloReply& reply) {
   if (session_) {
     // The buffer must be created here on the main thread since it will
@@ -270,7 +270,13 @@
 
 // Session ---------------------------------------------------------------------
 
-Session::Session() : system_(this), weak_factory_(this) {}
+Session::Session()
+    : remote_api_(std::make_unique<RemoteAPIImpl>(this)),
+      system_(this),
+      weak_factory_(this) {}
+
+Session::Session(std::unique_ptr<RemoteAPI> remote_api)
+    : remote_api_(std::move(remote_api)), system_(this), weak_factory_(this) {}
 
 Session::Session(debug_ipc::StreamBuffer* stream)
     : stream_(stream), system_(this), weak_factory_(this) {}
@@ -345,12 +351,9 @@
   }
 }
 
-bool Session::IsConnected() const {
-  return !!stream_;
-}
+bool Session::IsConnected() const { return !!stream_; }
 
-void Session::Connect(const std::string& host,
-                      uint16_t port,
+void Session::Connect(const std::string& host, uint16_t port,
                       std::function<void(const Err&)> callback) {
   Err err;
   if (IsConnected()) {
diff --git a/bin/zxdb/client/session.h b/bin/zxdb/client/session.h
index 8b32e8b..7ebf23b 100644
--- a/bin/zxdb/client/session.h
+++ b/bin/zxdb/client/session.h
@@ -11,26 +11,20 @@
 
 #include "garnet/bin/zxdb/client/err.h"
 #include "garnet/bin/zxdb/client/system_impl.h"
-#include "garnet/lib/debug_ipc/client_protocol.h"
-#include "garnet/lib/debug_ipc/helper/buffered_fd.h"
-#include "garnet/lib/debug_ipc/helper/message_loop.h"
-#include "garnet/lib/debug_ipc/helper/stream_buffer.h"
-#include "garnet/lib/debug_ipc/message_reader.h"
-#include "garnet/lib/debug_ipc/message_writer.h"
-#include "garnet/lib/debug_ipc/protocol.h"
-#include "garnet/public/lib/fxl/files/unique_fd.h"
 #include "garnet/public/lib/fxl/memory/ref_ptr.h"
 #include "garnet/public/lib/fxl/memory/weak_ptr.h"
-#include "garnet/public/lib/fxl/strings/string_printf.h"
 
 namespace debug_ipc {
 class BufferedFD;
+class StreamBuffer;
 }
 
 namespace zxdb {
 
 class ArchInfo;
 class ProcessImpl;
+class RemoteAPI;
+class RemoteAPIImpl;
 class ThreadImpl;
 
 // The session object manages the connection with the remote debug agent.
@@ -40,12 +34,19 @@
   // the callback associated with a Connect() call is issued.
   Session();
 
+  // Creates a session using a custom RemoteAPI implementation. Use for tests
+  // to mock out sending IPC messages.
+  explicit Session(std::unique_ptr<RemoteAPI> remote_api);
+
   // Creates with a previously-allocated connection. The pointer must outlive
   // this class. In this mode, the stream can not be disconnected.
   explicit Session(debug_ipc::StreamBuffer* stream);
 
   ~Session();
 
+  // The RempteAPI for sending messages to the debug_agent.
+  RemoteAPI* remote_api() { return remote_api_.get(); }
+
   // Notification that data is available to be read on the StreamBuffer.
   void OnStreamReadable();
 
@@ -54,8 +55,7 @@
 
   // Connects to a remote system. Calling when there is already a connection
   // will issue the callback with an error.
-  void Connect(const std::string& host,
-               uint16_t port,
+  void Connect(const std::string& host, uint16_t port,
                std::function<void(const Err&)> callback);
 
   // Disconnects from the remote system. Calling when there is no connection
@@ -70,6 +70,15 @@
   // Access to the singleton corresponding to the debugged system.
   System& system() { return system_; }
 
+  // Provide access to the underlying system implementation. This is needed
+  // for some client tests, but should not be used outside of the client
+  // directory.
+  //
+  // TODO(brettw) probably this class needs to be separated into Session and
+  // SessionImpl and which one of those you have controls which System object
+  // you can get.
+  SystemImpl& system_impl() { return system_; }
+
   // Architecture of the attached system. Will be "kUnknown" when not
   // connected.
   debug_ipc::Arch arch() const { return arch_; }
@@ -78,21 +87,10 @@
   // connected.
   const ArchInfo* arch_info() const { return arch_info_.get(); }
 
-  // Sends a message with an asynchronous reply.
-  //
-  // The callback will be issued with an Err struct. If the Err object
-  // indicates an error, the request has failed and the reply data will not be
-  // set (it will contain the default-constructed data).
-  //
-  // The callback will always be issued asynchronously (not from withing the
-  // Send() function itself).
-  template <typename SendMsgType, typename RecvMsgType>
-  void Send(const SendMsgType& send_msg,
-            std::function<void(const Err&, RecvMsgType)> callback);
-
  private:
   class PendingConnection;
   friend PendingConnection;
+  friend RemoteAPIImpl;
 
   // Nonspecific callback type. Implemented by SessionDispatchCallback (with
   // the type-specific parameter pre-bound). The uint32_t is the transaction
@@ -109,8 +107,7 @@
 
   // Callback when a connection has been successful or failed.
   void ConnectionResolved(fxl::RefPtr<PendingConnection> pending,
-                          const Err& err,
-                          const debug_ipc::HelloReply& reply,
+                          const Err& err, const debug_ipc::HelloReply& reply,
                           std::unique_ptr<debug_ipc::BufferedFD> buffer,
                           std::function<void(const Err&)> callback);
 
@@ -122,6 +119,8 @@
   // for the initial connection.
   debug_ipc::StreamBuffer* stream_ = nullptr;
 
+  std::unique_ptr<RemoteAPI> remote_api_;
+
   // When using non-persistent connections (no connection passed in via the
   // constructor), this will hold the underlying OS connection that is used
   // to back stream_.
@@ -144,61 +143,4 @@
   fxl::WeakPtrFactory<Session> weak_factory_;
 };
 
-template <typename SendMsgType, typename RecvMsgType>
-void Session::Send(const SendMsgType& send_msg,
-                   std::function<void(const Err&, RecvMsgType)> callback) {
-  uint32_t transaction_id = next_transaction_id_;
-  next_transaction_id_++;
-
-  if (!stream_) {
-    // No connection, asynchronously issue the error.
-    if (callback) {
-      debug_ipc::MessageLoop::Current()->PostTask([callback]() {
-        callback(
-            Err(ErrType::kNoConnection, "No connection to debugged system."),
-            RecvMsgType());
-      });
-    }
-    return;
-  }
-
-  debug_ipc::MessageWriter writer(sizeof(SendMsgType));
-  debug_ipc::WriteRequest(send_msg, transaction_id, &writer);
-
-  std::vector<char> serialized = writer.MessageComplete();
-  stream_->Write(std::move(serialized));
-
-  // This is the reply callback that unpacks the data in a vector, converts it
-  // to the requested RecvMsgType struct, and issues the callback.
-  Callback dispatch_callback = [callback = std::move(callback)](
-      const Err& err, std::vector<char> data) {
-    RecvMsgType reply;
-    if (err.has_error()) {
-      // Forward the error and ignore all data.
-      if (callback)
-        callback(err, std::move(reply));
-      return;
-    }
-
-    debug_ipc::MessageReader reader(std::move(data));
-
-    uint32_t transaction_id = 0;
-    Err deserialization_err;
-    if (!debug_ipc::ReadReply(&reader, &reply, &transaction_id)) {
-      reply = RecvMsgType();  // Could be in a half-read state.
-      deserialization_err =
-          Err(ErrType::kCorruptMessage,
-              fxl::StringPrintf("Corrupt reply message for transaction %u.",
-                                transaction_id));
-    }
-
-    if (callback)
-      callback(deserialization_err, std::move(reply));
-  };
-
-  pending_.emplace(std::piecewise_construct,
-                   std::forward_as_tuple(transaction_id),
-                   std::forward_as_tuple(std::move(dispatch_callback)));
-}
-
 }  // namespace zxdb
diff --git a/bin/zxdb/client/string_util.cc b/bin/zxdb/client/string_util.cc
new file mode 100644
index 0000000..e77cd25
--- /dev/null
+++ b/bin/zxdb/client/string_util.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/string_util.h"
+
+namespace zxdb {
+
+bool StringEndsWith(fxl::StringView str, fxl::StringView ends_with) {
+  if (ends_with.size() > str.size())
+    return false;
+
+  fxl::StringView source =
+      str.substr(str.size() - ends_with.size(), ends_with.size());
+  return source == ends_with;
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/string_util.h b/bin/zxdb/client/string_util.h
new file mode 100644
index 0000000..72413e7
--- /dev/null
+++ b/bin/zxdb/client/string_util.h
@@ -0,0 +1,14 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include "garnet/public/lib/fxl/strings/string_view.h"
+
+namespace zxdb {
+
+// Returns true if the first argument ends in exactly the second.
+bool StringEndsWith(fxl::StringView str, fxl::StringView ends_with);
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/string_util_unittest.cc b/bin/zxdb/client/string_util_unittest.cc
new file mode 100644
index 0000000..b9ad974
--- /dev/null
+++ b/bin/zxdb/client/string_util_unittest.cc
@@ -0,0 +1,20 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/string_util.h"
+#include "gtest/gtest.h"
+
+namespace zxdb {
+
+TEST(StringUtil, StringEndsWith) {
+  EXPECT_FALSE(StringEndsWith("short", "much too long"));
+  EXPECT_FALSE(StringEndsWith("a", "b"));
+  EXPECT_FALSE(StringEndsWith("aaa", "b"));
+  EXPECT_TRUE(StringEndsWith("aaab", "b"));
+  EXPECT_TRUE(StringEndsWith("aaabcde", "bcde"));
+  EXPECT_TRUE(StringEndsWith("bcde", "bcde"));
+  EXPECT_TRUE(StringEndsWith("aaab", ""));
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/BUILD.gn b/bin/zxdb/client/symbols/BUILD.gn
index 4fdc28d..518447d 100644
--- a/bin/zxdb/client/symbols/BUILD.gn
+++ b/bin/zxdb/client/symbols/BUILD.gn
@@ -57,6 +57,19 @@
   ]
 }
 
+static_library("test_support") {
+  testonly = true
+
+  sources = [
+    "mock_module_symbols.cc",
+    "mock_module_symbols.h",
+  ]
+
+  deps = [
+    ":symbols",
+  ]
+}
+
 source_set("tests") {
   testonly = true
 
@@ -71,6 +84,7 @@
 
   deps = [
     ":symbols",
+    ":test_support",
     "//third_party/googletest:gtest",
     "//third_party/llvm/lib/DebugInfo",
   ]
diff --git a/bin/zxdb/client/symbols/dwarf_die_decoder.cc b/bin/zxdb/client/symbols/dwarf_die_decoder.cc
index e0cd2ed..add3fba 100644
--- a/bin/zxdb/client/symbols/dwarf_die_decoder.cc
+++ b/bin/zxdb/client/symbols/dwarf_die_decoder.cc
@@ -59,7 +59,7 @@
                                    llvm::Optional<uint64_t>* unit_offset,
                                    llvm::Optional<uint64_t>* global_offset) {
   attrs_.emplace_back(attribute, [unit_offset, global_offset](
-      const llvm::DWARFFormValue& form) {
+                                     const llvm::DWARFFormValue& form) {
     switch (form.getForm()) {
       case llvm::dwarf::DW_FORM_ref1:
       case llvm::dwarf::DW_FORM_ref2:
diff --git a/bin/zxdb/client/symbols/dwarf_die_decoder.h b/bin/zxdb/client/symbols/dwarf_die_decoder.h
index 2bad4d5..9e73cba 100644
--- a/bin/zxdb/client/symbols/dwarf_die_decoder.h
+++ b/bin/zxdb/client/symbols/dwarf_die_decoder.h
@@ -43,8 +43,7 @@
   //
   // The output pointer must remain valid until the last call to Decode()
   // has returned.
-  void AddPresenceCheck(llvm::dwarf::Attribute attribute,
-                        bool* present);
+  void AddPresenceCheck(llvm::dwarf::Attribute attribute, bool* present);
 
   // These register for a given attribute, and call the similarly-named
   // function in llvm::DWARFFormValue to extract the attribute and place it
diff --git a/bin/zxdb/client/symbols/file_line.cc b/bin/zxdb/client/symbols/file_line.cc
index 09cf178..46c31be 100644
--- a/bin/zxdb/client/symbols/file_line.cc
+++ b/bin/zxdb/client/symbols/file_line.cc
@@ -4,6 +4,8 @@
 
 #include "garnet/bin/zxdb/client/symbols/file_line.h"
 
+#include "garnet/bin/zxdb/client/file_util.h"
+
 namespace zxdb {
 
 FileLine::FileLine() = default;
@@ -12,10 +14,7 @@
 FileLine::~FileLine() = default;
 
 std::string FileLine::GetFileNamePart() const {
-  size_t last_slash = file_.rfind('/');
-  if (last_slash == std::string::npos)
-    return file_;
-  return file_.substr(last_slash + 1);
+  return ExtractLastFileComponent(file_).ToString();
 }
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/loaded_module_symbols_impl.cc b/bin/zxdb/client/symbols/loaded_module_symbols_impl.cc
index 7b5186b..77e54b6 100644
--- a/bin/zxdb/client/symbols/loaded_module_symbols_impl.cc
+++ b/bin/zxdb/client/symbols/loaded_module_symbols_impl.cc
@@ -9,10 +9,8 @@
 namespace zxdb {
 
 LoadedModuleSymbolsImpl::LoadedModuleSymbolsImpl(
-    fxl::RefPtr<SystemSymbols::ModuleRef> module,
-    uint64_t load_address)
-    : module_(std::move(module)),
-      load_address_(load_address) {}
+    fxl::RefPtr<SystemSymbols::ModuleRef> module, uint64_t load_address)
+    : module_(std::move(module)), load_address_(load_address) {}
 LoadedModuleSymbolsImpl::~LoadedModuleSymbolsImpl() = default;
 
 ModuleSymbols* LoadedModuleSymbolsImpl::GetModuleSymbols() {
diff --git a/bin/zxdb/client/symbols/mock_module_symbols.cc b/bin/zxdb/client/symbols/mock_module_symbols.cc
new file mode 100644
index 0000000..da2b769
--- /dev/null
+++ b/bin/zxdb/client/symbols/mock_module_symbols.cc
@@ -0,0 +1,38 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/bin/zxdb/client/symbols/mock_module_symbols.h"
+
+#include "garnet/bin/zxdb/client/symbols/location.h"
+
+namespace zxdb {
+
+MockModuleSymbols::MockModuleSymbols(const std::string& local_file_name)
+    : local_file_name_(local_file_name) {}
+MockModuleSymbols::~MockModuleSymbols() = default;
+
+void MockModuleSymbols::AddSymbol(const std::string& name,
+                                  std::vector<uint64_t> addrs) {
+  symbols_[name] = std::move(addrs);
+}
+
+const std::string& MockModuleSymbols::GetLocalFileName() const {
+  return local_file_name_;
+}
+
+Location MockModuleSymbols::RelativeLocationForRelativeAddress(
+    uint64_t address) const {
+  // Currently only name -> address mappings are supported by this mock.
+  return Location(Location::State::kAddress, address);
+}
+
+std::vector<uint64_t> MockModuleSymbols::RelativeAddressesForFunction(
+    const std::string& name) const {
+  auto found = symbols_.find(name);
+  if (found == symbols_.end())
+    return std::vector<uint64_t>();
+  return found->second;
+}
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/mock_module_symbols.h b/bin/zxdb/client/symbols/mock_module_symbols.h
new file mode 100644
index 0000000..9237f70
--- /dev/null
+++ b/bin/zxdb/client/symbols/mock_module_symbols.h
@@ -0,0 +1,35 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <map>
+
+#include "garnet/bin/zxdb/client/symbols/module_symbols.h"
+
+namespace zxdb {
+
+// A mock for symbol lookup.
+class MockModuleSymbols : public ModuleSymbols {
+ public:
+  explicit MockModuleSymbols(const std::string& local_file_name);
+  ~MockModuleSymbols() override;
+
+  // Adds a mock mapping from the given name to the addresses.
+  void AddSymbol(const std::string& name, std::vector<uint64_t> addrs);
+
+  // ModuleSymbols implementation.
+  const std::string& GetLocalFileName() const override;
+  Location RelativeLocationForRelativeAddress(uint64_t address) const override;
+  std::vector<uint64_t> RelativeAddressesForFunction(
+      const std::string& name) const override;
+
+ private:
+  std::string local_file_name_;
+
+  // Maps manually-added symbols to their addresses.
+  std::map<std::string, std::vector<uint64_t>> symbols_;
+};
+
+}  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/module_symbol_index.cc b/bin/zxdb/client/symbols/module_symbol_index.cc
index b656722..6636b4c 100644
--- a/bin/zxdb/client/symbols/module_symbol_index.cc
+++ b/bin/zxdb/client/symbols/module_symbol_index.cc
@@ -6,16 +6,17 @@
 
 #include <limits>
 
+#include "garnet/bin/zxdb/client/file_util.h"
+#include "garnet/bin/zxdb/client/string_util.h"
 #include "garnet/bin/zxdb/client/symbols/dwarf_die_decoder.h"
 #include "garnet/bin/zxdb/client/symbols/module_symbol_index_node.h"
 #include "garnet/public/lib/fxl/logging.h"
 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 
 namespace zxdb {
 
-// Note: interesting file name extraction in dumpAttribute implementation in
-// DWARFDIE.cpp.
-
 namespace {
 
 // We want to index the things that can have software breakpoints attached to
@@ -88,8 +89,7 @@
 // unit (it will be exactly unit->getNumDIEs() long). The root node will have
 // kNoParent set.
 void ExtractUnitFunctionImplsAndParents(
-    llvm::DWARFContext* context,
-    llvm::DWARFCompileUnit* unit,
+    llvm::DWARFContext* context, llvm::DWARFCompileUnit* unit,
     std::vector<FunctionImpl>* function_impls,
     std::vector<unsigned>* parent_indices) {
   DwarfDieDecoder decoder(context, unit);
@@ -102,8 +102,8 @@
   // since probably we won't do any optimized lookups.
   llvm::Optional<uint64_t> decl_unit_offset;
   llvm::Optional<uint64_t> decl_global_offset;
-  decoder.AddReference(llvm::dwarf::DW_AT_specification,
-                       &decl_unit_offset, &decl_global_offset);
+  decoder.AddReference(llvm::dwarf::DW_AT_specification, &decl_unit_offset,
+                       &decl_global_offset);
 
   // Stores the index of the parent DIE for each one we encounter. The root
   // DIE with no parent will be set to kNoParent.
@@ -148,7 +148,8 @@
       // Found a function implementation.
       if (decl_unit_offset) {
         // Save the declaration for indexing.
-        function_impls->emplace_back(die, unit->getOffset() + *decl_unit_offset);
+        function_impls->emplace_back(die,
+                                     unit->getOffset() + *decl_unit_offset);
       } else if (decl_global_offset) {
         FXL_NOTREACHED() << "Implement DW_FORM_ref_addr for references.";
       } else {
@@ -185,11 +186,12 @@
 // ExtractUnitFunctionImplsAndParents for quickly finding parents.
 class FunctionImplIndexer {
  public:
-  FunctionImplIndexer(llvm::DWARFContext* context,
-                      llvm::DWARFCompileUnit* unit,
+  FunctionImplIndexer(llvm::DWARFContext* context, llvm::DWARFCompileUnit* unit,
                       const std::vector<unsigned>& parent_indices,
                       ModuleSymbolIndexNode* root)
-      : unit_(unit), parent_indices_(parent_indices), root_(root),
+      : unit_(unit),
+        parent_indices_(parent_indices),
+        root_(root),
         decoder_(context, unit) {
     decoder_.AddCString(llvm::dwarf::DW_AT_name, &name_);
   }
@@ -246,7 +248,7 @@
     ModuleSymbolIndexNode* cur = root_;
     for (int i = static_cast<int>(components.size()) - 1; i >= 0; i--)
       cur = cur->AddChild(std::move(components[i]));
-    cur->AddFunctionDie(llvm::DWARFDie(unit_, impl.entry));
+    cur->AddFunctionDie(ModuleSymbolIndexNode::DieRef(impl.entry->getOffset()));
   }
 
  private:
@@ -277,10 +279,21 @@
     llvm::DWARFUnitSection<llvm::DWARFCompileUnit>& units) {
   for (const std::unique_ptr<llvm::DWARFCompileUnit>& unit : units)
     IndexCompileUnit(context, unit.get());
+
+  IndexFileNames();
+
+  // TODO(brettw) LLVM creates a memory mapped file (the MemoryBuffer) to back
+  // the context. The indexing process pages it all in. We likely won't use
+  // most of it again so we could save substantial memory by somehow resetting
+  // the memory region so it will get paged back in as needed.
+  //
+  // The LLVM APIs don't seem to support exactly what we need. We may have to
+  // get creative in supplying our own MemoryBuffer to the llvm::object::Binary
+  // or closing and reopening everything (which may be slow).
 }
 
-const std::vector<llvm::DWARFDie>& ModuleSymbolIndex::FindFunctionExact(
-    const std::string& input) const {
+const std::vector<ModuleSymbolIndexNode::DieRef>&
+ModuleSymbolIndex::FindFunctionExact(const std::string& input) const {
   // Split the input on "::" which we'll traverse the tree with.
   //
   // TODO(brettw) this doesn't handle a lot of things like templates. By
@@ -305,7 +318,7 @@
 
     auto found = cur->sub().find(cur_name);
     if (found == cur->sub().end()) {
-      static std::vector<llvm::DWARFDie> empty_vector;
+      static std::vector<ModuleSymbolIndexNode::DieRef> empty_vector;
       return empty_vector;
     }
 
@@ -315,19 +328,106 @@
   return cur->function_dies();
 }
 
+std::vector<const ModuleSymbolIndex::FilePair*>
+ModuleSymbolIndex::FindFileMatches(const std::string& name) const {
+  fxl::StringView name_last_comp = ExtractLastFileComponent(name);
+
+  std::vector<const FilePair*> result;
+
+  // Search all files whose last component matches (the input may contain more
+  // than one component).
+  FileNameIndex::const_iterator iter =
+      file_name_index_.lower_bound(name_last_comp);
+  while (iter != file_name_index_.end() && iter->first == name_last_comp) {
+    const FilePair& pair = *iter->second;
+    if (StringEndsWith(pair.first, name) &&
+        (pair.first.size() == name.size() ||
+         pair.first[pair.first.size() - name.size() - 1] == '/')) {
+      result.push_back(&pair);
+    }
+    ++iter;
+  }
+
+  return result;
+}
+
+void ModuleSymbolIndex::DumpFileIndex(std::ostream& out) {
+  for (const auto& name_pair : file_name_index_) {
+    const FilePair& full_pair = *name_pair.second;
+    out << name_pair.first << " -> " << full_pair.first << " -> "
+        << full_pair.second.size() << " units\n";
+  }
+}
+
 void ModuleSymbolIndex::IndexCompileUnit(llvm::DWARFContext* context,
                                          llvm::DWARFCompileUnit* unit) {
   // Find the things to index.
   std::vector<FunctionImpl> function_impls;
   function_impls.reserve(256);
   std::vector<unsigned> parent_indices;
-  ExtractUnitFunctionImplsAndParents(
-      context, unit, &function_impls, &parent_indices);
+  ExtractUnitFunctionImplsAndParents(context, unit, &function_impls,
+                                     &parent_indices);
 
   // Index each one.
   FunctionImplIndexer indexer(context, unit, parent_indices, &root_);
   for (const FunctionImpl& impl : function_impls)
     indexer.AddFunction(impl);
+
+  IndexCompileUnitSourceFiles(context, unit);
+
+  // Clear the cached unit information. It will be holding a lot of parsed DIE
+  // information that likely isn't needed and it will get lazily repopulated if
+  // it is. This saves 7GB of memory for Chrome, for example.
+  //
+  // This is possible because the nodes store "DieRef" objects which contain
+  // the offset necessary to reconstitute the DIE, rather than references to
+  // any LLVM structures.
+  unit->clear();
+}
+
+void ModuleSymbolIndex::IndexCompileUnitSourceFiles(
+    llvm::DWARFContext* context, llvm::DWARFCompileUnit* unit) {
+  const llvm::DWARFDebugLine::LineTable* line_table =
+      context->getLineTableForUnit(unit);
+  const char* compilation_dir = unit->getCompilationDir();
+
+  // This table is the size of the file name table. Entries are set to 1 when
+  // we've added them to the index already.
+  std::vector<int> added_file;
+  added_file.resize(line_table->Prologue.FileNames.size(), 0);
+
+  // We don't want to just add all the files from the line table to the index.
+  // The line table will contain entries for every file referenced by the
+  // compilation unit, which includes declarations. We want only files that
+  // contribute code, which in practice is a tiny fraction of the total.
+  //
+  // To get this, iterate through the unit's row table and collect all
+  // referenced file names.
+  std::string file_name;
+  for (size_t i = 0; i < line_table->Rows.size(); i++) {
+    auto file_index = line_table->Rows[i].File;
+    // Watch out: file_index is 1-based.
+    if (!added_file[file_index - 1]) {
+      added_file[file_index - 1] = 1;
+      if (line_table->getFileNameByIndex(
+              file_index, compilation_dir,
+              llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+              file_name)) {
+        // TODO(brettw) the files here can contain relative components like
+        // "/foo/bar/../baz". We should canonicalize those (in a second pass
+        // once the unique names are known).
+        files_[file_name].push_back(unit);
+      }
+    }
+  }
+}
+
+void ModuleSymbolIndex::IndexFileNames() {
+  for (FileIndex::const_iterator iter = files_.begin(); iter != files_.end();
+       ++iter) {
+    fxl::StringView name = ExtractLastFileComponent(iter->first);
+    file_name_index_.insert(std::make_pair(name, iter));
+  }
 }
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/module_symbol_index.h b/bin/zxdb/client/symbols/module_symbol_index.h
index 2dfee0a..dc1dc3f 100644
--- a/bin/zxdb/client/symbols/module_symbol_index.h
+++ b/bin/zxdb/client/symbols/module_symbol_index.h
@@ -10,6 +10,7 @@
 
 #include "garnet/bin/zxdb/client/symbols/module_symbol_index_node.h"
 #include "garnet/public/lib/fxl/macros.h"
+#include "garnet/public/lib/fxl/strings/string_view.h"
 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
 
 namespace llvm {
@@ -23,6 +24,8 @@
 // Holds the index of symbols for a given module.
 class ModuleSymbolIndex {
  public:
+  using FilePair = std::pair<const std::string, std::vector<llvm::DWARFCompileUnit*>>;
+
   ModuleSymbolIndex();
   ~ModuleSymbolIndex();
 
@@ -33,15 +36,51 @@
 
   // Takes a fully-qualified name with namespaces and classes and template
   // parameters and returns the list of symbols which match exactly.
-  const std::vector<llvm::DWARFDie>& FindFunctionExact(
+  const std::vector<ModuleSymbolIndexNode::DieRef>& FindFunctionExact(
       const std::string& input) const;
 
+  // Looks up the name in the file index and returns the set of matches. The
+  // name is matched from the right side with a left boundary of either a slash
+  // or the beginning of the full path. This may match more than one file name,
+  // and the caller is left to decide which one(s) it wants.
+  //
+  // The returned pointers will point into the ModuleSymbolIndex.
+  std::vector<const FilePair*> FindFileMatches(const std::string& name) const;
+
+  // Dumps the file index to the stream for debugging.
+  void DumpFileIndex(std::ostream& out);
+
  private:
   void IndexCompileUnit(llvm::DWARFContext* context,
                         llvm::DWARFCompileUnit* unit);
 
+  void IndexCompileUnitSourceFiles(llvm::DWARFContext* context,
+                                   llvm::DWARFCompileUnit* unit);
+
+  // Populates the file_name_index_ given a now-unchanging files_ map.
+  void IndexFileNames();
+
   ModuleSymbolIndexNode root_;
 
+  // Maps full path names to compile units that reference them. This must not
+  // be mutated once the file_name_index_ is built.
+  //
+  // This is a map, not a multimap, because some files will appear in many
+  // compilation units. I suspect it's better to avoid duplicating the names
+  // (like a multimap would) and eating the cost of indirect heap allocations
+  // for vectors in the single-item case.
+  using FileIndex = std::map<std::string, std::vector<llvm::DWARFCompileUnit*>>;
+  FileIndex files_;
+
+  // Maps the last file name component (the part following the last slash) to
+  // the set of entries in the files_ index that have that name.
+  //
+  // This is a multimap because the name parts will generally be unique so we
+  // should get few duplicates. The cost of using a vector for most items
+  // containing one element becomes higher in that case.
+  using FileNameIndex = std::multimap<fxl::StringView, FileIndex::const_iterator>;
+  FileNameIndex file_name_index_;
+
   FXL_DISALLOW_COPY_AND_ASSIGN(ModuleSymbolIndex);
 };
 
diff --git a/bin/zxdb/client/symbols/module_symbol_index_node.cc b/bin/zxdb/client/symbols/module_symbol_index_node.cc
index c87d798..3418f43 100644
--- a/bin/zxdb/client/symbols/module_symbol_index_node.cc
+++ b/bin/zxdb/client/symbols/module_symbol_index_node.cc
@@ -7,14 +7,20 @@
 #include <sstream>
 
 #include "garnet/public/lib/fxl/strings/string_printf.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
 
 namespace zxdb {
 
+llvm::DWARFDie ModuleSymbolIndexNode::DieRef::ToDie(
+    llvm::DWARFContext* context) const {
+  return context->getDIEForOffset(offset_);
+}
+
 ModuleSymbolIndexNode::ModuleSymbolIndexNode() = default;
 
-ModuleSymbolIndexNode::ModuleSymbolIndexNode(const llvm::DWARFDie& die) {
-  function_dies_.push_back(die);
+ModuleSymbolIndexNode::ModuleSymbolIndexNode(const DieRef& ref) {
+  function_dies_.emplace_back(ref);
 }
 
 ModuleSymbolIndexNode::~ModuleSymbolIndexNode() = default;
@@ -41,15 +47,15 @@
   return out.str();
 }
 
-void ModuleSymbolIndexNode::AddFunctionDie(const llvm::DWARFDie& die) {
-  function_dies_.emplace_back(die);
+void ModuleSymbolIndexNode::AddFunctionDie(const DieRef& ref) {
+  function_dies_.emplace_back(ref);
 }
 
 ModuleSymbolIndexNode* ModuleSymbolIndexNode::AddChild(std::string&& name) {
-  return &sub_.emplace(
-      std::piecewise_construct,
-      std::forward_as_tuple(std::move(name)),
-      std::forward_as_tuple()).first->second;
+  return &sub_.emplace(std::piecewise_construct,
+                       std::forward_as_tuple(std::move(name)),
+                       std::forward_as_tuple())
+              .first->second;
 }
 
 void ModuleSymbolIndexNode::AddChild(
diff --git a/bin/zxdb/client/symbols/module_symbol_index_node.h b/bin/zxdb/client/symbols/module_symbol_index_node.h
index b4a564f..0965856 100644
--- a/bin/zxdb/client/symbols/module_symbol_index_node.h
+++ b/bin/zxdb/client/symbols/module_symbol_index_node.h
@@ -11,6 +11,10 @@
 
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
 
+namespace llvm {
+class DWARFContext;
+}
+
 namespace zxdb {
 
 // One node in the ModuleSymbolIndex tree. One node represents the set of things
@@ -20,10 +24,32 @@
 // many namespaces and functions.
 class ModuleSymbolIndexNode {
  public:
+  // A reference to a DIE that doesn't need the unit or the underlying
+  // llvm::DwarfDebugInfoEntry to be kept. This allows the discarding of the
+  // full parsed DIE structures after indexing. It can be converted back to a
+  // DIE, which will cause the DWARFUnit to be re-parsed.
+  //
+  // The offset stored in this structure is the offset from the beginning of
+  // the .debug_info section, which is the same as the offset stored in the
+  // llvm::DWARFDebugInfoEntry.
+  class DieRef {
+   public:
+    explicit DieRef() : offset_(0) {}
+    explicit DieRef(uint32_t offset) : offset_(offset) {}
+    explicit DieRef(const llvm::DWARFDie& die) : offset_(die.getOffset()) {}
+
+    uint32_t offset() const { return offset_; }
+
+    llvm::DWARFDie ToDie(llvm::DWARFContext* context) const;
+
+   private:
+    uint32_t offset_;
+  };
+
   ModuleSymbolIndexNode();
 
   // Makes a node pointing to one function.
-  ModuleSymbolIndexNode(const llvm::DWARFDie& die);
+  ModuleSymbolIndexNode(const DieRef& ref);
 
   ~ModuleSymbolIndexNode();
 
@@ -32,7 +58,7 @@
   const std::map<std::string, ModuleSymbolIndexNode>& sub() const {
     return sub_;
   }
-  const std::vector<llvm::DWARFDie>& function_dies() const {
+  const std::vector<DieRef>& function_dies() const {
     return function_dies_;
   }
 
@@ -48,7 +74,7 @@
   std::string AsString(int indent_level = 0) const;
 
   // Adds a DIE for a function with the name of this node.
-  void AddFunctionDie(const llvm::DWARFDie& die);
+  void AddFunctionDie(const DieRef& ref);
 
   // Adds a child node with the given name and returns it. If one already exits
   // with the name, returns the existing one.
@@ -71,7 +97,7 @@
   // For any functions matching this name, lists the DIEs that implement it.
   // If a function has the same name as a namespace, there could be sub_
   // entries as well as function_dies_.
-  std::vector<llvm::DWARFDie> function_dies_;
+  std::vector<DieRef> function_dies_;
 };
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/module_symbol_index_node_unittest.cc b/bin/zxdb/client/symbols/module_symbol_index_node_unittest.cc
index 2cccf3e..22d5ce6 100644
--- a/bin/zxdb/client/symbols/module_symbol_index_node_unittest.cc
+++ b/bin/zxdb/client/symbols/module_symbol_index_node_unittest.cc
@@ -9,43 +9,28 @@
 
 namespace zxdb {
 
-namespace {
-
-// You need a DWARFUnit to make a DWARFDie, but making a DWARFUnit is involved
-// and we don't actually need to dereferece anything. This function returns
-// a fake pointer that can be used.
-llvm::DWARFUnit* GetFakeUnitPtr() {
-  static int fake_value = 0;
-  return reinterpret_cast<llvm::DWARFUnit*>(&fake_value);
-}
-
-}  // namespace
-
 // Tests AddChild() and its merging capabilities when a duplicate is found.
 TEST(ModuleSymbolIndexNode, AddChildMerge) {
-  llvm::DWARFDebugInfoEntry entry1;
-  llvm::DWARFDebugInfoEntry entry2;
-  llvm::DWARFDebugInfoEntry entry3;
-  llvm::DWARFDebugInfoEntry entry4;
-
-  llvm::DWARFDie die1(GetFakeUnitPtr(), &entry1);
-  llvm::DWARFDie die2(GetFakeUnitPtr(), &entry2);
-  llvm::DWARFDie die3(GetFakeUnitPtr(), &entry3);
-  llvm::DWARFDie die4(GetFakeUnitPtr(), &entry4);
+  const uint32_t offset1 = 10;
+  const uint32_t offset2 = 20;
+  const uint32_t offset3 = 30;
+  const uint32_t offset4 = 40;
 
   const std::string foo("foo");
   const std::string bar("bar");
   const std::string bloop("bloop");
 
+  using DieRef = ModuleSymbolIndexNode::DieRef;
+
   // The root has the hierarchy:
   //   [root]
-  //     node1 = "foo" [1 function = die1]
-  //       node2 = "bar" [1 function = die2]
+  //     node1 = "foo" [1 function = #1]
+  //       node2 = "bar" [1 function = #2]
   ModuleSymbolIndexNode node2;
-  node2.AddFunctionDie(die2);
+  node2.AddFunctionDie(DieRef(offset2));
 
   ModuleSymbolIndexNode node1;
-  node1.AddFunctionDie(die1);
+  node1.AddFunctionDie(DieRef(offset1));
   node1.AddChild(std::make_pair(bar, std::move(node2)));
 
   ModuleSymbolIndexNode root;
@@ -54,13 +39,13 @@
   EXPECT_FALSE(root.empty());
 
   // The merged one has the hierarchy:
-  //   merge1 = "foo" [1 function = die3]
-  //     merge2 = "bloop" [1 function = die4]
+  //   merge1 = "foo" [1 function = #3]
+  //     merge2 = "bloop" [1 function = #4]
   ModuleSymbolIndexNode merge2;
-  merge2.AddFunctionDie(die4);
+  merge2.AddFunctionDie(DieRef(offset4));
 
   ModuleSymbolIndexNode merge1;
-  merge1.AddFunctionDie(die3);
+  merge1.AddFunctionDie(DieRef(offset3));
   merge1.AddChild(std::make_pair(bloop, std::move(merge2)));
 
   // Now merge in "merge1" as a child of the root.
@@ -68,9 +53,9 @@
 
   // This should merge the two to get:
   //   [root]
-  //     out1 = "foo" [2 functions = die1, die3]
-  //       out2 = "bar" [1 function = die2]
-  //       out3 = "bloop" [1 function = die4]
+  //     out1 = "foo" [2 functions = #1, #3]
+  //       out2 = "bar" [1 function = #2]
+  //       out3 = "bloop" [1 function = #4]
 
   // Check root.
   ASSERT_EQ(1u, root.sub().size());
@@ -81,8 +66,8 @@
   // Check out1.
   const ModuleSymbolIndexNode& out1 = root.sub().begin()->second;
   ASSERT_EQ(2u, out1.function_dies().size());
-  EXPECT_EQ(die1, out1.function_dies()[0]);
-  EXPECT_EQ(die3, out1.function_dies()[1]);
+  EXPECT_EQ(offset1, out1.function_dies()[0].offset());
+  EXPECT_EQ(offset3, out1.function_dies()[1].offset());
   ASSERT_EQ(2u, out1.sub().size());
   EXPECT_EQ(bar, out1.sub().begin()->first);
   EXPECT_EQ(bloop, (++out1.sub().begin())->first);
@@ -91,13 +76,13 @@
   const ModuleSymbolIndexNode& out2 = out1.sub().begin()->second;
   EXPECT_TRUE(out2.sub().empty());
   ASSERT_EQ(1u, out2.function_dies().size());
-  EXPECT_EQ(die2, out2.function_dies()[0]);
+  EXPECT_EQ(offset2, out2.function_dies()[0].offset());
 
   // Check out3.
   const ModuleSymbolIndexNode& out3 = (++out1.sub().begin())->second;
   EXPECT_TRUE(out3.sub().empty());
   ASSERT_EQ(1u, out3.function_dies().size());
-  EXPECT_EQ(die4, out3.function_dies()[0]);
+  EXPECT_EQ(offset4, out3.function_dies()[0].offset());
 }
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/module_symbol_index_unittest.cc b/bin/zxdb/client/symbols/module_symbol_index_unittest.cc
index 6d71fbb..3e1b7e5 100644
--- a/bin/zxdb/client/symbols/module_symbol_index_unittest.cc
+++ b/bin/zxdb/client/symbols/module_symbol_index_unittest.cc
@@ -2,8 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <inttypes.h>
 #include <ostream>
+#include <time.h>
 
+#include "garnet/bin/zxdb/client/string_util.h"
 #include "garnet/bin/zxdb/client/symbols/module_symbol_index.h"
 #include "garnet/bin/zxdb/client/symbols/test_symbol_module.h"
 #include "gtest/gtest.h"
@@ -22,6 +25,7 @@
   // Enable to dump the found index for debugging purposes.
   std::cout << "Index dump:\n";
   index.root().Dump(std::cout, 1);
+  index.DumpFileIndex(std::cout);
 #endif
 
   // Standalone function search.
@@ -45,4 +49,83 @@
   EXPECT_EQ(1u, result.size()) << "Symbol not found.";
 }
 
+TEST(ModuleSymbolIndex, FindFileMatches) {
+  TestSymbolModule module;
+  std::string err;
+  ASSERT_TRUE(module.Load(&err)) << err;
+
+  ModuleSymbolIndex index;
+  index.CreateIndex(module.context(), module.compile_units());
+
+  // Simple filename-only query that succeeds.
+  std::vector<const ModuleSymbolIndex::FilePair*> result =
+      index.FindFileMatches("zxdb_symbol_test.cc");
+  ASSERT_EQ(1u, result.size());
+  EXPECT_TRUE(StringEndsWith(result[0]->first, "client/test_data/zxdb_symbol_test.cc"));
+  EXPECT_EQ(1u, result[0]->second.size());
+
+  // Save the full path for later.
+  std::string full_path = result[0]->first;
+
+  // Simple filename-only query that fails.
+  result = index.FindFileMatches("nonexistant.cc");
+  EXPECT_EQ(0u, result.size());
+
+  // Multiple path components.
+  result = index.FindFileMatches("client/test_data/zxdb_symbol_test.cc");
+  EXPECT_EQ(1u, result.size());
+
+  // Ends-with match but doesn't start on a slash boundary.
+  result = index.FindFileMatches("nt/test_data/zxdb_symbol_test.cc");
+  EXPECT_EQ(0u, result.size());
+
+  // Full path match.
+  result = index.FindFileMatches(full_path);
+  EXPECT_EQ(1u, result.size());
+
+  // More-than-full path match.
+  result = index.FindFileMatches("/a" + full_path);
+  EXPECT_EQ(0u, result.size());
+}
+
+// Enable and substitute a path on your system for kFilename to run the
+// indexing benchmark.
+#if 0
+static int64_t GetTickMicroseconds() {
+  struct timespec ts;
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+
+  constexpr int64_t kMicrosecondsPerSecond = 1000000;
+  constexpr int64_t kNanosecondsPerMicrosecond = 1000;
+
+  int64_t result = ts.tv_sec * kMicrosecondsPerSecond;
+  result += (ts.tv_nsec / kNanosecondsPerMicrosecond);
+  return result;
+}
+
+TEST(ModuleSymbolIndex, BenchmarkIndexing) {
+  const char kFilename[] =
+      "/usr/local/google/home/brettw/prj/src/out/release/chrome";
+  int64_t begin_us = GetTickMicroseconds();
+
+  TestSymbolModule module;
+  std::string err;
+  ASSERT_TRUE(module.LoadSpecific(kFilename, &err)) << err;
+
+  int64_t load_complete_us = GetTickMicroseconds();
+
+  ModuleSymbolIndex index;
+  index.CreateIndex(module.context(), module.compile_units());
+
+  int64_t index_complete_us = GetTickMicroseconds();
+
+  printf("\nIndexing results for %s:\n   Load: %" PRId64
+         " µs\n  Index: %" PRId64 " µs\n\n",
+         kFilename, load_complete_us - begin_us,
+         index_complete_us - load_complete_us);
+
+  sleep(10);
+}
+#endif  // End indexing benchmark.
+
 }  // namespace
diff --git a/bin/zxdb/client/symbols/module_symbols_impl.cc b/bin/zxdb/client/symbols/module_symbols_impl.cc
index 69a53d7..b01cc25 100644
--- a/bin/zxdb/client/symbols/module_symbols_impl.cc
+++ b/bin/zxdb/client/symbols/module_symbols_impl.cc
@@ -18,17 +18,14 @@
 ModuleSymbolsImpl::ModuleSymbolsImpl(const std::string& name) : name_(name) {}
 ModuleSymbolsImpl::~ModuleSymbolsImpl() = default;
 
-const std::string& ModuleSymbolsImpl::GetLocalFileName() const {
-  return name_;
-}
+const std::string& ModuleSymbolsImpl::GetLocalFileName() const { return name_; }
 
 Err ModuleSymbolsImpl::Load() {
   llvm::Expected<llvm::object::OwningBinary<llvm::object::Binary>> bin_or_err =
       llvm::object::createBinary(name_);
   if (!bin_or_err) {
     auto err_str = llvm::toString(bin_or_err.takeError());
-    return Err("Error loading symbols for \"" + name_ + "\": " +
-               err_str);
+    return Err("Error loading symbols for \"" + name_ + "\": " + err_str);
   }
 
   auto binary_pair = bin_or_err->takeBinary();
@@ -65,11 +62,14 @@
 
 std::vector<uint64_t> ModuleSymbolsImpl::RelativeAddressesForFunction(
     const std::string& name) const {
-  const std::vector<llvm::DWARFDie>& entries = index_.FindFunctionExact(name);
+  const std::vector<ModuleSymbolIndexNode::DieRef>& entries =
+      index_.FindFunctionExact(name);
 
   std::vector<uint64_t> result;
   for (const auto& cur : entries) {
-    llvm::DWARFAddressRangesVector ranges = cur.getAddressRanges();
+    llvm::DWARFDie die = cur.ToDie(context_.get());
+
+    llvm::DWARFAddressRangesVector ranges = die.getAddressRanges();
     if (ranges.empty())
       continue;
 
diff --git a/bin/zxdb/client/symbols/module_symbols_impl.h b/bin/zxdb/client/symbols/module_symbols_impl.h
index ebbc5cc..74921fa 100644
--- a/bin/zxdb/client/symbols/module_symbols_impl.h
+++ b/bin/zxdb/client/symbols/module_symbols_impl.h
@@ -19,7 +19,7 @@
 
 namespace object {
 class Binary;
-} // namespace object
+}  // namespace object
 
 }  // namespace llvm
 
diff --git a/bin/zxdb/client/symbols/module_symbols_impl_unittest.cc b/bin/zxdb/client/symbols/module_symbols_impl_unittest.cc
index ef9e921..54a0d94 100644
--- a/bin/zxdb/client/symbols/module_symbols_impl_unittest.cc
+++ b/bin/zxdb/client/symbols/module_symbols_impl_unittest.cc
@@ -27,7 +27,8 @@
 
 // Trying to load a nonexistand file should error.
 TEST(ModuleSymbols, NonExistantFile) {
-  ModuleSymbolsImpl module(TestSymbolModule::GetTestFileName() + "_NONEXISTANT");
+  ModuleSymbolsImpl module(TestSymbolModule::GetTestFileName() +
+                           "_NONEXISTANT");
   Err err = module.Load();
   EXPECT_TRUE(err.has_error());
 }
@@ -43,7 +44,8 @@
   EXPECT_LT(0, write(fd, temp_name, strlen(temp_name)));
   close(fd);
 
-  ModuleSymbolsImpl module(TestSymbolModule::GetTestFileName() + "_NONEXISTANT");
+  ModuleSymbolsImpl module(TestSymbolModule::GetTestFileName() +
+                           "_NONEXISTANT");
   Err err = module.Load();
   EXPECT_TRUE(err.has_error());
 }
diff --git a/bin/zxdb/client/symbols/process_symbols.h b/bin/zxdb/client/symbols/process_symbols.h
index 4d00754..512348c 100644
--- a/bin/zxdb/client/symbols/process_symbols.h
+++ b/bin/zxdb/client/symbols/process_symbols.h
@@ -5,8 +5,8 @@
 #pragma once
 
 #include <stdint.h>
-#include <string>
 #include <functional>
+#include <string>
 
 #include "garnet/bin/zxdb/client/symbols/location.h"
 #include "garnet/public/lib/fxl/macros.h"
diff --git a/bin/zxdb/client/symbols/process_symbols_impl.cc b/bin/zxdb/client/symbols/process_symbols_impl.cc
index 1fc738b..553ee84 100644
--- a/bin/zxdb/client/symbols/process_symbols_impl.cc
+++ b/bin/zxdb/client/symbols/process_symbols_impl.cc
@@ -16,23 +16,29 @@
 
 // The vDSO doesn't have symbols and we don't want to give error messages for
 // it. Ignore failures for modules that this returns true for.
-bool ExpectSymbolsForName(const std::string& name) {
-  return name != "<vDSO>";
-}
+bool ExpectSymbolsForName(const std::string& name) { return name != "<vDSO>"; }
 
 }  // namespace
 
 ProcessSymbolsImpl::ProcessSymbolsImpl(Notifications* notifications,
                                        TargetSymbolsImpl* target_symbols)
-    : notifications_(notifications),
-      target_symbols_(target_symbols) {}
+    : notifications_(notifications), target_symbols_(target_symbols) {}
 
 ProcessSymbolsImpl::~ProcessSymbolsImpl() = default;
 
 void ProcessSymbolsImpl::AddModule(
     const debug_ipc::Module& module,
     std::function<void(const std::string&)> callback) {
-  // TODO(brettw) support run-time dynamic module loading notifications.
+  Err sym_load_err;
+  ModuleInfo* info = SaveModuleInfo(module, &sym_load_err);
+
+  // Send notifications.
+  if (sym_load_err.has_error()) {
+    notifications_->OnSymbolLoadFailure(sym_load_err);
+  } else {
+    target_symbols_->AddModule(info->symbols->module());
+    notifications_->DidLoadModuleSymbols(info->symbols.get());
+  }
 }
 
 void ProcessSymbolsImpl::SetModules(
@@ -71,29 +77,14 @@
 
   // Process the added ones.
   std::vector<LoadedModuleSymbols*> added_modules;
-  SystemSymbols* system_symbols = target_symbols_->system_symbols();
+  std::vector<Err> load_errors;
   for (const auto& added_index : new_module_indices) {
-    const debug_ipc::Module& module = modules[added_index];
-
-    ModuleInfo info;
-    info.name = module.name;
-    info.build_id = module.build_id;
-    info.base = module.base;
-
-    fxl::RefPtr<SystemSymbols::ModuleRef> module_symbols;
-    Err err = system_symbols->GetModule(
-        module.name, module.build_id, &module_symbols);
-    if (!err.has_error()) {
-      // Success, make the LoadedModuleSymbolsImpl.
-      info.symbols = std::make_unique<LoadedModuleSymbolsImpl>(
-          std::move(module_symbols), module.base);
-      added_modules.push_back(info.symbols.get());
-    } else if (ExpectSymbolsForName(module.name)) {
-      notifications_->OnSymbolLoadFailure(err);
-    }
-    modules_.emplace(std::piecewise_construct,
-                     std::forward_as_tuple(module.base),
-                     std::forward_as_tuple(std::move(info)));
+    Err sym_load_err;
+    ModuleInfo* info = SaveModuleInfo(modules[added_index], &sym_load_err);
+    if (sym_load_err.has_error())
+      load_errors.push_back(std::move(sym_load_err));
+    else if (info->symbols)
+      added_modules.push_back(info->symbols.get());
   }
 
   // Update the TargetSymbols.
@@ -103,16 +94,19 @@
       target_symbols_->AddModule(pair.second.symbols->module());
   }
 
-  // Send add notifications last so everything is in a consistent state.
+  // Send notifications last so everything is in a consistent state.
   for (auto& added_module : added_modules)
     notifications_->DidLoadModuleSymbols(added_module);
+  for (auto& err : load_errors)
+    notifications_->OnSymbolLoadFailure(err);
 }
 
 TargetSymbols* ProcessSymbolsImpl::GetTargetSymbols() {
   return target_symbols_;
 }
 
-std::vector<ProcessSymbols::ModuleStatus> ProcessSymbolsImpl::GetStatus() const {
+std::vector<ProcessSymbols::ModuleStatus> ProcessSymbolsImpl::GetStatus()
+    const {
   std::vector<ModuleStatus> result;
   for (const auto& pair : modules_) {
     ModuleStatus status;
@@ -150,6 +144,34 @@
   return result;
 }
 
+ProcessSymbolsImpl::ModuleInfo* ProcessSymbolsImpl::SaveModuleInfo(
+    const debug_ipc::Module& module, Err* symbol_load_err) {
+  ModuleInfo info;
+  info.name = module.name;
+  info.build_id = module.build_id;
+  info.base = module.base;
+
+  fxl::RefPtr<SystemSymbols::ModuleRef> module_symbols;
+  *symbol_load_err = target_symbols_->system_symbols()->GetModule(
+      module.name, module.build_id, &module_symbols);
+  if (symbol_load_err->has_error()) {
+    // Error, but it may be expected.
+    if (!ExpectSymbolsForName(module.name))
+      *symbol_load_err = Err();
+  } else {
+    // Success, make the LoadedModuleSymbolsImpl.
+    info.symbols = std::make_unique<LoadedModuleSymbolsImpl>(
+        std::move(module_symbols), module.base);
+  }
+
+  auto inserted_iter =
+      modules_
+          .emplace(std::piecewise_construct, std::forward_as_tuple(module.base),
+                   std::forward_as_tuple(std::move(info)))
+          .first;
+  return &inserted_iter->second;
+}
+
 // static
 bool ProcessSymbolsImpl::RefersToSameModule(const debug_ipc::Module& a,
                                             const ModuleInfo& b) {
@@ -158,8 +180,10 @@
 
 const ProcessSymbolsImpl::ModuleInfo* ProcessSymbolsImpl::InfoForAddress(
     uint64_t address) const {
+  if (modules_.empty())
+    return nullptr;
   auto found = modules_.lower_bound(address);
-  if (found->first > address) {
+  if (found == modules_.end() || found->first > address) {
     if (found == modules_.begin())
       return nullptr;  // Address below first module.
     // Move to previous item to get the module starting before this address.
diff --git a/bin/zxdb/client/symbols/process_symbols_impl.h b/bin/zxdb/client/symbols/process_symbols_impl.h
index d2f94f1..5252051 100644
--- a/bin/zxdb/client/symbols/process_symbols_impl.h
+++ b/bin/zxdb/client/symbols/process_symbols_impl.h
@@ -44,9 +44,7 @@
                      TargetSymbolsImpl* target_symbols);
   ~ProcessSymbolsImpl();
 
-  TargetSymbolsImpl* target_symbols() {
-    return target_symbols_;
-  }
+  TargetSymbolsImpl* target_symbols() { return target_symbols_; }
 
   // Adds the given module to the process. The callback will be executed with
   // the local path of the module if it is found, or the empty string if it is
@@ -74,6 +72,17 @@
     std::unique_ptr<LoadedModuleSymbolsImpl> symbols;
   };
 
+  // Creates the ModuleInfo structure, attempts to load the symbols, and
+  // updates the modules_ list for this process. *err will be filled with the
+  // success code of symbol loading (the function will save the ModuleInfo
+  // either way).
+  //
+  // This class issues no notifications, the caller needs to do that. Just
+  // because there's no error doesn't necessarily mean the symbols have been
+  // loaded, since some symbols might be expected to be not present.
+  ModuleInfo* SaveModuleInfo(const debug_ipc::Module& module,
+                             Err* symbol_load_err);
+
   // Equality comparison for the two types of modules. This compares load
   // address and build id.
   static bool RefersToSameModule(const debug_ipc::Module& a,
diff --git a/bin/zxdb/client/symbols/process_symbols_impl_unittest.cc b/bin/zxdb/client/symbols/process_symbols_impl_unittest.cc
index 9f12027..8936f2b 100644
--- a/bin/zxdb/client/symbols/process_symbols_impl_unittest.cc
+++ b/bin/zxdb/client/symbols/process_symbols_impl_unittest.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "garnet/bin/zxdb/client/symbols/process_symbols_impl.h"
 #include "garnet/bin/zxdb/client/symbols/loaded_module_symbols.h"
 #include "garnet/bin/zxdb/client/symbols/module_symbols.h"
-#include "garnet/bin/zxdb/client/symbols/process_symbols_impl.h"
 #include "garnet/bin/zxdb/client/symbols/system_symbols.h"
 #include "garnet/bin/zxdb/client/symbols/target_symbols_impl.h"
 #include "garnet/bin/zxdb/client/symbols/test_symbol_module.h"
@@ -49,9 +49,7 @@
   void WillUnloadModuleSymbols(LoadedModuleSymbols* module) override {
     unloaded_.push_back(module->GetLoadAddress());
   }
-  void OnSymbolLoadFailure(const Err& err) override {
-    err_count_++;
-  }
+  void OnSymbolLoadFailure(const Err& err) override { err_count_++; }
 
  private:
   std::vector<LoadedModuleSymbols*> loaded_;
diff --git a/bin/zxdb/client/symbols/system_symbols.cc b/bin/zxdb/client/symbols/system_symbols.cc
index 0b20548..c9c073a 100644
--- a/bin/zxdb/client/symbols/system_symbols.cc
+++ b/bin/zxdb/client/symbols/system_symbols.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/bin/zxdb/client/symbols/system_symbols.h"
 
-#include "garnet/bin/zxdb/client/host_utils.h"
+#include "garnet/bin/zxdb/client/host_util.h"
 #include "garnet/bin/zxdb/client/symbols/module_symbols_impl.h"
 #include "garnet/public/lib/fxl/strings/string_printf.h"
 #include "garnet/public/lib/fxl/strings/string_view.h"
@@ -45,7 +45,7 @@
 
 SystemSymbols::ModuleRef::ModuleRef(
     SystemSymbols* system_symbols,
-    std::unique_ptr<ModuleSymbolsImpl> module_symbols)
+    std::unique_ptr<ModuleSymbols> module_symbols)
     : system_symbols_(system_symbols),
       module_symbols_(std::move(module_symbols)) {}
 
@@ -107,6 +107,17 @@
   build_id_to_file_[build_id] = file;
 }
 
+fxl::RefPtr<SystemSymbols::ModuleRef> SystemSymbols::InjectModuleForTesting(
+    const std::string& build_id, std::unique_ptr<ModuleSymbols> module) {
+  // Can't inject a module that already exists.
+  FXL_DCHECK(modules_.find(build_id) == modules_.end());
+
+  fxl::RefPtr<ModuleRef> result =
+      fxl::MakeRefCounted<ModuleRef>(this, std::move(module));
+  modules_[build_id] = result.get();
+  return result;
+}
+
 Err SystemSymbols::GetModule(const std::string& name_for_msg,
                              const std::string& build_id,
                              fxl::RefPtr<ModuleRef>* module) {
diff --git a/bin/zxdb/client/symbols/system_symbols.h b/bin/zxdb/client/symbols/system_symbols.h
index f9c18bb..cbdb592 100644
--- a/bin/zxdb/client/symbols/system_symbols.h
+++ b/bin/zxdb/client/symbols/system_symbols.h
@@ -13,7 +13,7 @@
 
 namespace zxdb {
 
-class ModuleSymbolsImpl;
+class ModuleSymbols;
 
 // Tracks a global view of all ModuleSymbols objects. Since each object is
 // independent of load address, we can share these between processes that
@@ -29,10 +29,10 @@
   class ModuleRef : public fxl::RefCountedThreadSafe<ModuleRef> {
    public:
     ModuleRef(SystemSymbols* system_symbols,
-              std::unique_ptr<ModuleSymbolsImpl> module_symbols);
+              std::unique_ptr<ModuleSymbols> module_symbols);
 
-    ModuleSymbolsImpl* module_symbols() { return module_symbols_.get(); }
-    const ModuleSymbolsImpl* module_symbols() const {
+    ModuleSymbols* module_symbols() { return module_symbols_.get(); }
+    const ModuleSymbols* module_symbols() const {
       return module_symbols_.get();
     }
 
@@ -47,7 +47,7 @@
     // May be null to indicate teh SystemSymbols object is deleted.
     SystemSymbols* system_symbols_;
 
-    std::unique_ptr<ModuleSymbolsImpl> module_symbols_;
+    std::unique_ptr<ModuleSymbols> module_symbols_;
   };
 
   SystemSymbols();
@@ -62,14 +62,21 @@
   void AddBuildIDToFileMapping(const std::string& build_id,
                                const std::string& file);
 
+  // Injects a ModuleSymbols object for the given build ID. Used for testing.
+  // Normally the test would provide a dummy implementation for ModuleSymbols.
+  // Ownership of the symbols will be transferred to the returned refcounted
+  // ModuleRef. As long as this is alive, the build id -> module mapping will
+  // remain in the SystemSymbols object.
+  fxl::RefPtr<ModuleRef> InjectModuleForTesting(
+      const std::string& build_id, std::unique_ptr<ModuleSymbols> module);
+
   // Retrieves the symbols for the module with the given build ID. If the
   // module's symbols have already been loaded, just puts an owning reference
   // into the given out param. If not, the symbols will be loaded.
   //
   // This function uses the build_id for loading symbols. The name is only
   // used for generating informational messages.
-  Err GetModule(const std::string& name_for_msg,
-                const std::string& build_id,
+  Err GetModule(const std::string& name_for_msg, const std::string& build_id,
                 fxl::RefPtr<ModuleRef>* module);
 
   // Parses the BuildID-to-path mapping file contents. Returns a map from
diff --git a/bin/zxdb/client/symbols/target_symbols_impl.cc b/bin/zxdb/client/symbols/target_symbols_impl.cc
index 8281926..2c864f6 100644
--- a/bin/zxdb/client/symbols/target_symbols_impl.cc
+++ b/bin/zxdb/client/symbols/target_symbols_impl.cc
@@ -16,11 +16,11 @@
 TargetSymbolsImpl::TargetSymbolsImpl(SystemSymbols* system_symbols)
     : system_symbols_(system_symbols) {}
 TargetSymbolsImpl::TargetSymbolsImpl(const TargetSymbolsImpl& other)
-    : system_symbols_(other.system_symbols_),
-      modules_(other.modules_) {}
+    : system_symbols_(other.system_symbols_), modules_(other.modules_) {}
 TargetSymbolsImpl::~TargetSymbolsImpl() {}
 
-TargetSymbolsImpl& TargetSymbolsImpl::operator=(const TargetSymbolsImpl& other) {
+TargetSymbolsImpl& TargetSymbolsImpl::operator=(
+    const TargetSymbolsImpl& other) {
   modules_ = other.modules_;
   return *this;
 }
@@ -40,8 +40,6 @@
   modules_.erase(found);
 }
 
-void TargetSymbolsImpl::RemoveAllModules() {
-  modules_.clear();
-}
+void TargetSymbolsImpl::RemoveAllModules() { modules_.clear(); }
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/symbols/target_symbols_impl.h b/bin/zxdb/client/symbols/target_symbols_impl.h
index 66a5184..089bea2 100644
--- a/bin/zxdb/client/symbols/target_symbols_impl.h
+++ b/bin/zxdb/client/symbols/target_symbols_impl.h
@@ -34,9 +34,7 @@
 
   TargetSymbolsImpl& operator=(const TargetSymbolsImpl& other);
 
-  SystemSymbols* system_symbols() {
-    return system_symbols_;
-  }
+  SystemSymbols* system_symbols() { return system_symbols_; }
 
   // Notifications from ProcessSymbols to keep things in sync. Multiple add
   // notifications are allowed for the same module (this happens when
diff --git a/bin/zxdb/client/symbols/test_symbol_module.cc b/bin/zxdb/client/symbols/test_symbol_module.cc
index 56eebc3..5d11ded 100644
--- a/bin/zxdb/client/symbols/test_symbol_module.cc
+++ b/bin/zxdb/client/symbols/test_symbol_module.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/bin/zxdb/client/symbols/test_symbol_module.h"
 
-#include "garnet/bin/zxdb/client/host_utils.h"
+#include "garnet/bin/zxdb/client/host_util.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Object/Binary.h"
@@ -42,14 +42,17 @@
 }
 
 bool TestSymbolModule::Load(std::string* err_msg) {
-  std::string filename = GetTestFileName();
+  return LoadSpecific(GetTestFileName(), err_msg);
+}
 
+bool TestSymbolModule::LoadSpecific(const std::string& path,
+                                    std::string* err_msg) {
   llvm::Expected<llvm::object::OwningBinary<llvm::object::Binary>> bin_or_err =
-      llvm::object::createBinary(filename);
+      llvm::object::createBinary(path);
   if (!bin_or_err) {
     auto err_str = llvm::toString(bin_or_err.takeError());
     *err_msg =
-        "Error loading symbols for \"" + filename + "\", LLVM said: " + err_str;
+        "Error loading symbols for \"" + path + "\", LLVM said: " + err_str;
     return false;
   }
 
diff --git a/bin/zxdb/client/symbols/test_symbol_module.h b/bin/zxdb/client/symbols/test_symbol_module.h
index c623340..db36e08 100644
--- a/bin/zxdb/client/symbols/test_symbol_module.h
+++ b/bin/zxdb/client/symbols/test_symbol_module.h
@@ -18,7 +18,7 @@
 
 namespace object {
 class Binary;
-} // namespace object
+}  // namespace object
 
 }  // namespace llvm
 
@@ -47,6 +47,9 @@
   // message to be something helpful.
   bool Load(std::string* err_msg);
 
+  // Loads a file at the given path. See Load().
+  bool LoadSpecific(const std::string& path, std::string* err_msg);
+
   llvm::DWARFContext* context() { return context_.get(); }
   llvm::DWARFUnitSection<llvm::DWARFCompileUnit>& compile_units() {
     return compile_units_;
diff --git a/bin/zxdb/client/system.h b/bin/zxdb/client/system.h
index 704497d..1d156b6 100644
--- a/bin/zxdb/client/system.h
+++ b/bin/zxdb/client/system.h
@@ -23,8 +23,8 @@
 class System : public ClientObject {
  public:
   // Callback for requesting the process tree.
-  using ProcessTreeCallback = std::function<
-      void(const Err&, debug_ipc::ProcessTreeReply)>;
+  using ProcessTreeCallback =
+      std::function<void(const Err&, debug_ipc::ProcessTreeReply)>;
 
   System(Session* session);
   ~System() override;
diff --git a/bin/zxdb/client/system_impl.cc b/bin/zxdb/client/system_impl.cc
index 98d4749..e06c01b 100644
--- a/bin/zxdb/client/system_impl.cc
+++ b/bin/zxdb/client/system_impl.cc
@@ -6,9 +6,11 @@
 
 #include "garnet/bin/zxdb/client/breakpoint_impl.h"
 #include "garnet/bin/zxdb/client/process_impl.h"
+#include "garnet/bin/zxdb/client/remote_api.h"
 #include "garnet/bin/zxdb/client/session.h"
 #include "garnet/bin/zxdb/client/system_observer.h"
 #include "garnet/bin/zxdb/client/target_impl.h"
+#include "garnet/lib/debug_ipc/helper/message_loop.h"
 
 namespace zxdb {
 
@@ -21,7 +23,7 @@
   std::string symbol_msg;
   bool ids_loaded = symbols_.LoadBuildIDFile(&symbol_msg);
   debug_ipc::MessageLoop::Current()->PostTask(
-      [ weak_system = weak_factory_.GetWeakPtr(), ids_loaded, symbol_msg ]() {
+      [weak_system = weak_factory_.GetWeakPtr(), ids_loaded, symbol_msg]() {
         if (weak_system) {
           for (auto& observer : weak_system->observers())
             observer.DidTryToLoadSymbolMapping(ids_loaded, symbol_msg);
@@ -48,6 +50,23 @@
   return nullptr;
 }
 
+void SystemImpl::NotifyDidCreateProcess(Process* process) {
+  for (auto& observer : observers())
+    observer.GlobalDidCreateProcess(process);
+}
+
+void SystemImpl::NotifyWillDestroyProcess(Process* process) {
+  for (auto& observer : observers())
+    observer.GlobalWillDestroyProcess(process);
+}
+
+std::vector<TargetImpl*> SystemImpl::GetTargetImpls() const {
+  std::vector<TargetImpl*> result;
+  for (const auto& t : targets_)
+    result.push_back(t.get());
+  return result;
+}
+
 std::vector<Target*> SystemImpl::GetTargets() const {
   std::vector<Target*> result;
   result.reserve(targets_.size());
@@ -69,8 +88,8 @@
 }
 
 void SystemImpl::GetProcessTree(ProcessTreeCallback callback) {
-  session()->Send<debug_ipc::ProcessTreeRequest, debug_ipc::ProcessTreeReply>(
-      debug_ipc::ProcessTreeRequest(), std::move(callback));
+  session()->remote_api()->ProcessTree(debug_ipc::ProcessTreeRequest(),
+                                       std::move(callback));
 }
 
 Target* SystemImpl::CreateNewTarget(Target* clone) {
@@ -110,7 +129,7 @@
   debug_ipc::PauseRequest request;
   request.process_koid = 0;  // 0 means all processes.
   request.thread_koid = 0;   // 0 means all threads.
-  session()->Send<debug_ipc::PauseRequest, debug_ipc::PauseReply>(
+  session()->remote_api()->Pause(
       request, std::function<void(const Err&, debug_ipc::PauseReply)>());
 }
 
@@ -119,7 +138,7 @@
   request.process_koid = 0;  // 0 means all processes.
   request.thread_koid = 0;   // 0 means all threads.
   request.how = debug_ipc::ResumeRequest::How::kContinue;
-  session()->Send<debug_ipc::ResumeRequest, debug_ipc::ResumeReply>(
+  session()->remote_api()->Resume(
       request, std::function<void(const Err&, debug_ipc::ResumeReply)>());
 }
 
diff --git a/bin/zxdb/client/system_impl.h b/bin/zxdb/client/system_impl.h
index c921063..c1472a5 100644
--- a/bin/zxdb/client/system_impl.h
+++ b/bin/zxdb/client/system_impl.h
@@ -7,8 +7,8 @@
 #include <memory>
 #include <vector>
 
-#include "garnet/bin/zxdb/client/system.h"
 #include "garnet/bin/zxdb/client/symbols/system_symbols.h"
+#include "garnet/bin/zxdb/client/system.h"
 #include "garnet/public/lib/fxl/macros.h"
 #include "garnet/public/lib/fxl/memory/weak_ptr.h"
 
@@ -28,6 +28,12 @@
 
   SystemSymbols& symbols() { return symbols_; }
 
+  // Broadcasts the global process notifications.
+  void NotifyDidCreateProcess(Process* process);
+  void NotifyWillDestroyProcess(Process* process);
+
+  std::vector<TargetImpl*> GetTargetImpls() const;
+
   // System implementation:
   std::vector<Target*> GetTargets() const override;
   std::vector<Breakpoint*> GetBreakpoints() const override;
diff --git a/bin/zxdb/client/system_observer.h b/bin/zxdb/client/system_observer.h
index c106564..8346e50 100644
--- a/bin/zxdb/client/system_observer.h
+++ b/bin/zxdb/client/system_observer.h
@@ -17,6 +17,12 @@
   virtual void DidCreateTarget(Target* target) {}
   virtual void WillDestroyTarget(Target* target) {}
 
+  // It can be common to want to watch for all Process creation and destruction
+  // events. For convenience, these allow that without having to track each
+  // Target and register as an observer on them individually.
+  virtual void GlobalDidCreateProcess(Process* process) {}
+  virtual void GlobalWillDestroyProcess(Process* process) {}
+
   // Called immediately after creation / before destruction of a breakpoint.
   virtual void DidCreateBreakpoint(Breakpoint* breakpoint) {}
   virtual void WillDestroyBreakpoint(Breakpoint* breakpoint) {}
diff --git a/bin/zxdb/client/target.cc b/bin/zxdb/client/target.cc
index 7e088f8..f369c60 100644
--- a/bin/zxdb/client/target.cc
+++ b/bin/zxdb/client/target.cc
@@ -17,8 +17,6 @@
   observers_.RemoveObserver(observer);
 }
 
-fxl::WeakPtr<Target> Target::GetWeakPtr() {
-  return weak_factory_.GetWeakPtr();
-}
+fxl::WeakPtr<Target> Target::GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/target_impl.cc b/bin/zxdb/client/target_impl.cc
index dae9514..e9d7ce4 100644
--- a/bin/zxdb/client/target_impl.cc
+++ b/bin/zxdb/client/target_impl.cc
@@ -7,6 +7,7 @@
 #include <sstream>
 
 #include "garnet/bin/zxdb/client/process_impl.h"
+#include "garnet/bin/zxdb/client/remote_api.h"
 #include "garnet/bin/zxdb/client/session.h"
 #include "garnet/bin/zxdb/client/system_impl.h"
 #include "garnet/bin/zxdb/client/target_observer.h"
@@ -30,6 +31,17 @@
   return result;
 }
 
+void TargetImpl::CreateProcessForTesting(uint64_t koid,
+                                         const std::string& process_name) {
+  FXL_DCHECK(state_ == State::kNone);
+  state_ = State::kStarting;
+  OnLaunchOrAttachReply(Callback(), Err(), koid, 0, process_name);
+}
+
+void TargetImpl::DestroyProcessForTesting() {
+  OnKillOrDetachReply(Err(), 0, Callback());
+}
+
 Target::State TargetImpl::GetState() const { return state_; }
 
 Process* TargetImpl::GetProcess() const { return process_.get(); }
@@ -51,16 +63,17 @@
 
   if (err.has_error()) {
     // Avoid reentering caller to dispatch the error.
-    debug_ipc::MessageLoop::Current()->PostTask([
-      callback, err, weak_ptr = GetWeakPtr()
-    ]() { callback(std::move(weak_ptr), err); });
+    debug_ipc::MessageLoop::Current()->PostTask(
+        [callback, err, weak_ptr = GetWeakPtr()]() {
+          callback(std::move(weak_ptr), err);
+        });
     return;
   }
 
   debug_ipc::LaunchRequest request;
   request.argv = args_;
-  session()->Send<debug_ipc::LaunchRequest, debug_ipc::LaunchReply>(
-      request, [ callback, weak_target = impl_weak_factory_.GetWeakPtr() ](
+  session()->remote_api()->Launch(
+      request, [callback, weak_target = impl_weak_factory_.GetWeakPtr()](
                    const Err& err, debug_ipc::LaunchReply reply) {
         TargetImpl::OnLaunchOrAttachReplyThunk(weak_target, callback, err,
                                                reply.process_koid, reply.status,
@@ -71,7 +84,7 @@
 void TargetImpl::Kill(Callback callback) {
   if (!process_.get()) {
     debug_ipc::MessageLoop::Current()->PostTask(
-        [ callback, weak_ptr = GetWeakPtr() ]() {
+        [callback, weak_ptr = GetWeakPtr()]() {
           callback(std::move(weak_ptr), Err("Error detaching: No process."));
         });
     return;
@@ -79,34 +92,35 @@
 
   debug_ipc::KillRequest request;
   request.process_koid = process_->GetKoid();
-  session()->Send<debug_ipc::KillRequest, debug_ipc::KillReply>(request, [
-    callback, weak_target = impl_weak_factory_.GetWeakPtr()
-  ](const Err& err, debug_ipc::KillReply reply) {
-    if (weak_target) {
-      weak_target->OnKillOrDetachReply(err, reply.status, std::move(callback));
-    } else {
-      // The reply that the process was launched came after the local
-      // objects were destroyed. We're still OK to dispatch either way.
-      callback(weak_target, err);
-    }
-  });
+  session()->remote_api()->Kill(
+      request, [callback, weak_target = impl_weak_factory_.GetWeakPtr()](
+                   const Err& err, debug_ipc::KillReply reply) {
+        if (weak_target) {
+          weak_target->OnKillOrDetachReply(err, reply.status,
+                                           std::move(callback));
+        } else {
+          // The reply that the process was launched came after the local
+          // objects were destroyed. We're still OK to dispatch either way.
+          callback(weak_target, err);
+        }
+      });
 }
 
 void TargetImpl::Attach(uint64_t koid, Callback callback) {
   debug_ipc::AttachRequest request;
   request.koid = koid;
-  session()->Send<debug_ipc::AttachRequest, debug_ipc::AttachReply>(request, [
-    koid, callback, weak_target = impl_weak_factory_.GetWeakPtr()
-  ](const Err& err, debug_ipc::AttachReply reply) {
-    OnLaunchOrAttachReplyThunk(std::move(weak_target), std::move(callback), err,
-                               koid, reply.status, reply.process_name);
-  });
+  session()->remote_api()->Attach(
+      request, [koid, callback, weak_target = impl_weak_factory_.GetWeakPtr()](
+                   const Err& err, debug_ipc::AttachReply reply) {
+        OnLaunchOrAttachReplyThunk(std::move(weak_target), std::move(callback),
+                                   err, koid, reply.status, reply.process_name);
+      });
 }
 
 void TargetImpl::Detach(Callback callback) {
   if (!process_.get()) {
     debug_ipc::MessageLoop::Current()->PostTask(
-        [ callback, weak_ptr = GetWeakPtr() ]() {
+        [callback, weak_ptr = GetWeakPtr()]() {
           callback(std::move(weak_ptr), Err("Error detaching: No process."));
         });
     return;
@@ -114,28 +128,32 @@
 
   debug_ipc::DetachRequest request;
   request.process_koid = process_->GetKoid();
-  session()->Send<debug_ipc::DetachRequest, debug_ipc::DetachReply>(request, [
-    callback, weak_target = impl_weak_factory_.GetWeakPtr()
-  ](const Err& err, debug_ipc::DetachReply reply) {
-    if (weak_target) {
-      weak_target->OnKillOrDetachReply(err, reply.status, std::move(callback));
-    } else {
-      // The reply that the process was launched came after the local
-      // objects were destroyed. We're still OK to dispatch either way.
-      callback(weak_target, err);
-    }
-  });
+  session()->remote_api()->Detach(
+      request, [callback, weak_target = impl_weak_factory_.GetWeakPtr()](
+                   const Err& err, debug_ipc::DetachReply reply) {
+        if (weak_target) {
+          weak_target->OnKillOrDetachReply(err, reply.status,
+                                           std::move(callback));
+        } else {
+          // The reply that the process was launched came after the local
+          // objects were destroyed. We're still OK to dispatch either way.
+          callback(weak_target, err);
+        }
+      });
 }
 
 void TargetImpl::OnProcessExiting(int return_code) {
   FXL_DCHECK(state_ == State::kRunning);
-
   state_ = State::kNone;
-  process_.reset();
+
+  system_->NotifyWillDestroyProcess(process_.get());
   for (auto& observer : observers()) {
-    observer.DidDestroyProcess(this, TargetObserver::DestroyReason::kExit,
-                               return_code);
+    observer.WillDestroyProcess(this, process_.get(),
+                                TargetObserver::DestroyReason::kExit,
+                                return_code);
   }
+
+  process_.reset();
 }
 
 // static
@@ -184,6 +202,7 @@
     callback(GetWeakPtr(), issue_err);
 
   if (state_ == State::kRunning) {
+    system_->NotifyDidCreateProcess(process_.get());
     for (auto& observer : observers())
       observer.DidCreateProcess(this, process_.get());
   }
@@ -205,10 +224,14 @@
   } else {
     // Successfully detached.
     state_ = State::kNone;
-    process_.reset();
+    system_->NotifyWillDestroyProcess(process_.get());
+
+    // Keep the process alive for the observer call, but remove it from the
+    // target as per the observer specification.
+    std::unique_ptr<ProcessImpl> doomed_process = std::move(process_);
     for (auto& observer : observers()) {
-      observer.DidDestroyProcess(this, TargetObserver::DestroyReason::kDetach,
-                                 0);
+      observer.WillDestroyProcess(this, doomed_process.get(),
+                                  TargetObserver::DestroyReason::kDetach, 0);
     }
   }
 
diff --git a/bin/zxdb/client/target_impl.h b/bin/zxdb/client/target_impl.h
index 9aea306..fe720d8 100644
--- a/bin/zxdb/client/target_impl.h
+++ b/bin/zxdb/client/target_impl.h
@@ -4,8 +4,8 @@
 
 #pragma once
 
-#include "garnet/bin/zxdb/client/target.h"
 #include "garnet/bin/zxdb/client/symbols/target_symbols_impl.h"
+#include "garnet/bin/zxdb/client/target.h"
 #include "garnet/public/lib/fxl/macros.h"
 #include "garnet/public/lib/fxl/memory/weak_ptr.h"
 
@@ -28,6 +28,11 @@
   // a real copy, because any process information is not cloned.
   std::unique_ptr<TargetImpl> Clone(SystemImpl* system);
 
+  // Tests can use these functions to create and destroy targets for mocking
+  // purposes without making any IPC.
+  void CreateProcessForTesting(uint64_t koid, const std::string& process_name);
+  void DestroyProcessForTesting();
+
   // Target implementation:
   State GetState() const override;
   Process* GetProcess() const override;
@@ -42,16 +47,11 @@
 
  private:
   static void OnLaunchOrAttachReplyThunk(fxl::WeakPtr<TargetImpl> target,
-                                         Callback callback,
-                                         const Err& err,
-                                         uint64_t koid,
-                                         uint32_t status,
+                                         Callback callback, const Err& err,
+                                         uint64_t koid, uint32_t status,
                                          const std::string& process_name);
-  void OnLaunchOrAttachReply(Callback callback,
-                             const Err& err,
-                             uint64_t koid,
-                             uint32_t status,
-                             const std::string& process_name);
+  void OnLaunchOrAttachReply(Callback callback, const Err& err, uint64_t koid,
+                             uint32_t status, const std::string& process_name);
 
   void OnKillOrDetachReply(const Err& err, uint32_t status, Callback callback);
 
diff --git a/bin/zxdb/client/target_observer.h b/bin/zxdb/client/target_observer.h
index 4090fde..994c722 100644
--- a/bin/zxdb/client/target_observer.h
+++ b/bin/zxdb/client/target_observer.h
@@ -11,21 +11,18 @@
 class TargetObserver {
  public:
   // Reason for destroying a process object.
-  enum class DestroyReason {
-    kExit,
-    kDetach,
-    kKill
-  };
+  enum class DestroyReason { kExit, kDetach, kKill };
 
   // The process could have been newly launched or attached to an existing
   // process.
   virtual void DidCreateProcess(Target* target, Process* process) {}
 
   // Called after detaching from or destroying a process. The Process object
-  // will no longer exist. The exit code will only have meaning when reason ==
+  // will exist but the Target object will report there is no process
+  // currently running. The exit code will only have meaning when reason ==
   // kExit, otherwise it will be 0.
-  virtual void DidDestroyProcess(Target* target, DestroyReason reason,
-                                 int exit_code) {}
+  virtual void WillDestroyProcess(Target* target, Process* process,
+                                  DestroyReason reason, int exit_code) {}
 };
 
 }  // namespace zxdb
diff --git a/bin/zxdb/client/thread.h b/bin/zxdb/client/thread.h
index dec1200..48bab0b 100644
--- a/bin/zxdb/client/thread.h
+++ b/bin/zxdb/client/thread.h
@@ -4,8 +4,8 @@
 
 #pragma once
 
-#include <stdint.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <string>
 
 #include "garnet/bin/zxdb/client/client_object.h"
diff --git a/bin/zxdb/client/thread_impl.cc b/bin/zxdb/client/thread_impl.cc
index 6a5ca14..5e41567 100644
--- a/bin/zxdb/client/thread_impl.cc
+++ b/bin/zxdb/client/thread_impl.cc
@@ -6,6 +6,7 @@
 
 #include "garnet/bin/zxdb/client/frame_impl.h"
 #include "garnet/bin/zxdb/client/process_impl.h"
+#include "garnet/bin/zxdb/client/remote_api.h"
 #include "garnet/bin/zxdb/client/session.h"
 #include "garnet/public/lib/fxl/logging.h"
 
@@ -34,8 +35,8 @@
   debug_ipc::PauseRequest request;
   request.process_koid = process_->GetKoid();
   request.thread_koid = koid_;
-  session()->Send<debug_ipc::PauseRequest, debug_ipc::PauseReply>(
-      request, [](const Err& err, debug_ipc::PauseReply) {});
+  session()->remote_api()->Pause(request,
+                                 [](const Err& err, debug_ipc::PauseReply) {});
 }
 
 void ThreadImpl::Continue() {
@@ -43,7 +44,7 @@
   request.process_koid = process_->GetKoid();
   request.thread_koid = koid_;
   request.how = debug_ipc::ResumeRequest::How::kContinue;
-  session()->Send<debug_ipc::ResumeRequest, debug_ipc::ResumeReply>(
+  session()->remote_api()->Resume(
       request, [](const Err& err, debug_ipc::ResumeReply) {});
 }
 
@@ -52,7 +53,7 @@
   request.process_koid = process_->GetKoid();
   request.thread_koid = koid_;
   request.how = debug_ipc::ResumeRequest::How::kStepInstruction;
-  session()->Send<debug_ipc::ResumeRequest, debug_ipc::ResumeReply>(
+  session()->remote_api()->Resume(
       request, [](const Err& err, debug_ipc::ResumeReply) {});
 }
 
@@ -75,8 +76,8 @@
 
   ClearFrames();
 
-  session()->Send<debug_ipc::BacktraceRequest, debug_ipc::BacktraceReply>(
-      request, [ callback, thread = weak_factory_.GetWeakPtr() ](
+  session()->remote_api()->Backtrace(
+      request, [callback, thread = weak_factory_.GetWeakPtr()](
                    const Err& err, debug_ipc::BacktraceReply reply) {
         if (!thread)
           return;
@@ -114,7 +115,7 @@
   frame.push_back(notify.frame);
   // HaveFrames will only issue the callback if the ThreadImpl is still in
   // scope so we don't need a weak pointer here.
-  HaveFrames(frame, [ notify, thread = this ]() {
+  HaveFrames(frame, [notify, thread = this]() {
     thread->SetMetadata(notify.thread);
 
     // After an exception the thread should be blocked.
diff --git a/bin/zxdb/console/command.cc b/bin/zxdb/console/command.cc
index 9e553cb..9f0e3b9 100644
--- a/bin/zxdb/console/command.cc
+++ b/bin/zxdb/console/command.cc
@@ -16,8 +16,7 @@
 
 namespace {
 
-const char kFrameShortHelp[] =
-    "frame / f: Select or list stack frames.";
+const char kFrameShortHelp[] = "frame / f: Select or list stack frames.";
 const char kFrameHelp[] =
     R"(frame [ <id> [ <command> ... ] ]
 
@@ -48,8 +47,7 @@
     Selects the specified process, thread, and frame.
 )";
 
-const char kThreadShortHelp[] =
-    "thread / t: Select or list threads.";
+const char kThreadShortHelp[] = "thread / t: Select or list threads.";
 const char kThreadHelp[] =
     R"(thread [ <id> [ <command> ... ] ]
 
@@ -189,9 +187,10 @@
   for (const auto& pair : nouns_) {
     if (std::find(allowed_nouns.begin(), allowed_nouns.end(), pair.first) ==
         allowed_nouns.end()) {
-      return Err(ErrType::kInput, fxl::StringPrintf(
-          "\"%s\" may not be specified for this command.",
-          NounToString(pair.first).c_str()));
+      return Err(
+          ErrType::kInput,
+          fxl::StringPrintf("\"%s\" may not be specified for this command.",
+                            NounToString(pair.first).c_str()));
     }
   }
   return Err();
@@ -220,16 +219,14 @@
 
 NounRecord::NounRecord() = default;
 NounRecord::NounRecord(std::initializer_list<std::string> aliases,
-                       const char* short_help,
-                       const char* help)
+                       const char* short_help, const char* help)
     : aliases(aliases), short_help(short_help), help(help) {}
 NounRecord::~NounRecord() = default;
 
 VerbRecord::VerbRecord() = default;
 VerbRecord::VerbRecord(CommandExecutor exec,
                        std::initializer_list<std::string> aliases,
-                       const char* short_help,
-                       const char* help)
+                       const char* short_help, const char* help)
     : exec(exec), aliases(aliases), short_help(short_help), help(help) {}
 VerbRecord::~VerbRecord() = default;
 
@@ -318,8 +315,7 @@
   const auto& found = verbs.find(cmd.verb());
   if (found == verbs.end()) {
     return Err(ErrType::kInput,
-               "Invalid verb \"" + VerbToString(cmd.verb()) +
-               "\".");
+               "Invalid verb \"" + VerbToString(cmd.verb()) + "\".");
   }
   return found->second.exec(context, cmd);
 }
diff --git a/bin/zxdb/console/command.h b/bin/zxdb/console/command.h
index 87760c7..e1f01f8 100644
--- a/bin/zxdb/console/command.h
+++ b/bin/zxdb/console/command.h
@@ -144,7 +144,7 @@
   // will inherit the default.
   Target* target_ = nullptr;  // Guaranteed non-null for valid commands.
   Thread* thread_ = nullptr;  // Will be null if not running.
-  Frame* frame_ = nullptr;  // Will be null if no valid thread stopped.
+  Frame* frame_ = nullptr;    // Will be null if no valid thread stopped.
   Breakpoint* breakpoint_ = nullptr;  // May be null.
 
   Verb verb_ = Verb::kNone;
@@ -180,8 +180,7 @@
 
 struct NounRecord {
   NounRecord();
-  NounRecord(std::initializer_list<std::string> aliases,
-             const char* short_help,
+  NounRecord(std::initializer_list<std::string> aliases, const char* short_help,
              const char* help);
   ~NounRecord();
 
@@ -198,10 +197,8 @@
 
   // The help will be referenced by pointer. It is expected to be a static
   // string.
-  VerbRecord(CommandExecutor exec,
-             std::initializer_list<std::string> aliases,
-             const char* short_help,
-             const char* help);
+  VerbRecord(CommandExecutor exec, std::initializer_list<std::string> aliases,
+             const char* short_help, const char* help);
   ~VerbRecord();
 
   CommandExecutor exec = nullptr;
diff --git a/bin/zxdb/console/command_parser.cc b/bin/zxdb/console/command_parser.cc
index 1bf6307..85e94ba 100644
--- a/bin/zxdb/console/command_parser.cc
+++ b/bin/zxdb/console/command_parser.cc
@@ -4,9 +4,9 @@
 
 #include "garnet/bin/zxdb/console/command_parser.h"
 
+#include <stdio.h>
 #include <map>
 #include <set>
-#include <stdio.h>
 
 #include "garnet/bin/zxdb/client/err.h"
 #include "garnet/bin/zxdb/console/command.h"
@@ -45,12 +45,9 @@
       strings.insert(verb_pair.second.aliases[0]);
   }
   return strings;
-
 }
 
-bool IsTokenSeparator(char c) {
-  return c == ' ';
-}
+bool IsTokenSeparator(char c) { return c == ' '; }
 
 // Finds the record for the switch associated with long switch string (which
 // includes the two leading dashes), or null if there is no match.
@@ -117,10 +114,8 @@
 //
 // *consumed will be set if any nouns were consumed (to disambiguate the
 // "error parsing" case and the "the next thing wasn't a noun" case).
-Err ConsumeNoun(const std::vector<std::string>& tokens,
-                size_t* token_index,
-                Command* output,
-                bool* consumed) {
+Err ConsumeNoun(const std::vector<std::string>& tokens, size_t* token_index,
+                Command* output, bool* consumed) {
   *consumed = false;
 
   const auto& nouns = GetStringNounMap();
@@ -140,8 +135,8 @@
   size_t noun_index = Command::kNoIndex;
   if ((*token_index) < tokens.size() && IsIndexToken(tokens[*token_index])) {
     if (sscanf(tokens[*token_index].c_str(), "%zu", &noun_index) != 1) {
-      return Err("Invalid index \"" + tokens[*token_index] +
-                 "\" for \"" + NounToString(noun) + "\".");
+      return Err("Invalid index \"" + tokens[*token_index] + "\" for \"" +
+                 NounToString(noun) + "\".");
     }
     (*token_index)++;
   }
diff --git a/bin/zxdb/console/command_parser_unittest.cc b/bin/zxdb/console/command_parser_unittest.cc
index 1c4e01a..eb09488 100644
--- a/bin/zxdb/console/command_parser_unittest.cc
+++ b/bin/zxdb/console/command_parser_unittest.cc
@@ -15,7 +15,7 @@
 bool CompletionContains(const std::vector<std::string>& suggestions,
                         const std::string& contains) {
   return std::find(suggestions.begin(), suggestions.end(), contains) !=
-      suggestions.end();
+         suggestions.end();
 }
 
 }  // namespace
diff --git a/bin/zxdb/console/command_utils.cc b/bin/zxdb/console/command_utils.cc
index 2576ee6..3af5af4 100644
--- a/bin/zxdb/console/command_utils.cc
+++ b/bin/zxdb/console/command_utils.cc
@@ -196,11 +196,11 @@
       return "Global";
     case BreakpointSettings::Scope::kTarget:
       return fxl::StringPrintf("pr %d",
-          context->IdForTarget(settings.scope_target));
+                               context->IdForTarget(settings.scope_target));
     case BreakpointSettings::Scope::kThread:
       return fxl::StringPrintf(
-          "pr %d t %d",
-          context->IdForTarget(settings.scope_thread->GetProcess()->GetTarget()),
+          "pr %d t %d", context->IdForTarget(
+                            settings.scope_thread->GetProcess()->GetTarget()),
           context->IdForThread(settings.scope_thread));
   }
   FXL_NOTREACHED();
@@ -300,13 +300,26 @@
   std::string scope = BreakpointScopeToString(context, settings);
   std::string stop = BreakpointStopToString(settings.stop_mode);
   const char* enabled = BreakpointEnabledToString(settings.enabled);
-  std::string location =
-      fxl::StringPrintf("0x%" PRIx64, settings.location_address);
+  std::string location = DescribeBreakpointLocation(settings);
 
-  return fxl::StringPrintf("Breakpoint %d on %s, %s, stop=%s, hit=%d, @ %s",
+  return fxl::StringPrintf("Breakpoint %d on %s, %s, stop=%s, @ %s",
                            context->IdForBreakpoint(breakpoint), scope.c_str(),
-                           enabled, stop.c_str(), breakpoint->GetHitCount(),
-                           location.c_str());
+                           enabled, stop.c_str(), location.c_str());
+}
+
+std::string DescribeBreakpointLocation(const BreakpointSettings& settings) {
+  switch (settings.location_type) {
+    case BreakpointSettings::LocationType::kNone:
+      return "<no location>";
+    case BreakpointSettings::LocationType::kLine:
+      return DescribeFileLine(settings.location_line);
+    case BreakpointSettings::LocationType::kSymbol:
+      return settings.location_symbol;
+    case BreakpointSettings::LocationType::kAddress:
+      return fxl::StringPrintf("0x%" PRIx64, settings.location_address);
+  }
+  FXL_NOTREACHED();
+  return std::string();
 }
 
 std::string DescribeLocation(const Location& loc) {
@@ -314,9 +327,12 @@
     return "<invalid address>";
   if (!loc.has_symbols())
     return fxl::StringPrintf("0x%" PRIx64, loc.address());
-  return fxl::StringPrintf("0x%" PRIx64 " @ %s:%d", loc.address(),
-                           loc.file_line().GetFileNamePart().c_str(),
-                           loc.file_line().line());
+  return fxl::StringPrintf("0x%" PRIx64 " @ %s", loc.address(),
+                           DescribeFileLine(loc.file_line()).c_str());
+}
+
+std::string DescribeFileLine(const FileLine& file_line) {
+  return fxl::StringPrintf("%s:%d", file_line.file().c_str(), file_line.line());
 }
 
 void FormatColumns(const std::vector<ColSpec>& spec,
diff --git a/bin/zxdb/console/command_utils.h b/bin/zxdb/console/command_utils.h
index 0092e3c..f61cba2 100644
--- a/bin/zxdb/console/command_utils.h
+++ b/bin/zxdb/console/command_utils.h
@@ -26,8 +26,7 @@
 // Ensures the target is currently running (it has a current Process associated
 // with it. If not, generates an error of the form
 // "<command_name> requires a running target".
-Err AssertRunningTarget(ConsoleContext* context,
-                        const char* command_name,
+Err AssertRunningTarget(ConsoleContext* context, const char* command_name,
                         Target* target);
 
 [[nodiscard]] Err StringToUint64(const std::string& s, uint64_t* out);
@@ -36,20 +35,15 @@
 // if there are not enough args, or if the value isn't an int64.
 //
 // The param_desc will be used in the error string, for example "process koid".
-[[nodiscard]] Err ReadUint64Arg(const Command& cmd,
-                                size_t arg_index,
-                                const char* param_desc,
-                                uint64_t* out);
+[[nodiscard]] Err ReadUint64Arg(const Command& cmd, size_t arg_index,
+                                const char* param_desc, uint64_t* out);
 
 // Parses a host and port. The two-argument version assumes the host and
 // port are given separately. The one-argument version assumes they're
 // separated by a colon.
-Err ParseHostPort(const std::string& in_host,
-                  const std::string& in_port,
-                  std::string* out_host,
-                  uint16_t* out_port);
-Err ParseHostPort(const std::string& input,
-                  std::string* out_host,
+Err ParseHostPort(const std::string& in_host, const std::string& in_port,
+                  std::string* out_host, uint16_t* out_port);
+Err ParseHostPort(const std::string& input, std::string* out_host,
                   uint16_t* out_port);
 
 std::string TargetStateToString(Target::State state);
@@ -62,8 +56,7 @@
 
 std::string ExceptionTypeToString(debug_ipc::NotifyException::Type type);
 
-std::string DescribeTarget(const ConsoleContext* context,
-                           const Target* target);
+std::string DescribeTarget(const ConsoleContext* context, const Target* target);
 
 // Returns the process name of the given target, depending on the running
 // process or the current app name, as applicable.
@@ -74,15 +67,15 @@
 std::string DescribeBreakpoint(const ConsoleContext* context,
                                const Breakpoint* breakpoint);
 
+std::string DescribeBreakpointLocation(const BreakpointSettings& settings);
 std::string DescribeLocation(const Location& loc);
+std::string DescribeFileLine(const FileLine& file_line);
 
 enum class Align { kLeft, kRight };
 
 struct ColSpec {
-  explicit ColSpec(Align align = Align::kLeft,
-                   int max_width = 0,
-                   const std::string& head = std::string(),
-                   int pad_left = 0)
+  explicit ColSpec(Align align = Align::kLeft, int max_width = 0,
+                   const std::string& head = std::string(), int pad_left = 0)
       : align(align), max_width(max_width), head(head), pad_left(pad_left) {}
 
   Align align = Align::kLeft;
diff --git a/bin/zxdb/console/command_utils_unittest.cc b/bin/zxdb/console/command_utils_unittest.cc
index d26d14a..32fe4bb 100644
--- a/bin/zxdb/console/command_utils_unittest.cc
+++ b/bin/zxdb/console/command_utils_unittest.cc
@@ -131,7 +131,9 @@
 
   // Heading only.
   out = OutputBuffer();
-  FormatColumns({ColSpec(Align::kLeft, 0, "One"), ColSpec(Align::kLeft, 0, "Two")}, rows, &out);
+  FormatColumns(
+      {ColSpec(Align::kLeft, 0, "One"), ColSpec(Align::kLeft, 0, "Two")}, rows,
+      &out);
   EXPECT_EQ("One Two\n", out.AsString());
 
   // Two rows for all tests below.
@@ -145,17 +147,22 @@
 
   // Right align with padding.
   out = OutputBuffer();
-  FormatColumns({ColSpec(Align::kRight), ColSpec(Align::kRight, 0, std::string(), 2)}, rows, &out);
+  FormatColumns(
+      {ColSpec(Align::kRight), ColSpec(Align::kRight, 0, std::string(), 2)},
+      rows, &out);
   EXPECT_EQ("    0   Hello, world\n12345          Hello\n", out.AsString());
 
   // Max width + heading.
   out = OutputBuffer();
-  FormatColumns({ColSpec(Align::kRight, 3, "One"), ColSpec(Align::kLeft, 3, "Two")}, rows, &out);
+  FormatColumns(
+      {ColSpec(Align::kRight, 3, "One"), ColSpec(Align::kLeft, 3, "Two")}, rows,
+      &out);
   EXPECT_EQ("One Two\n  0 Hello, world\n12345 Hello\n", out.AsString());
 
   // Overflowing cells shouldn't force the whole column to max width.
   out = OutputBuffer();
-  FormatColumns({ColSpec(Align::kRight, 1), ColSpec(Align::kLeft, 0)}, rows, &out);
+  FormatColumns({ColSpec(Align::kRight, 1), ColSpec(Align::kLeft, 0)}, rows,
+                &out);
   EXPECT_EQ("0 Hello, world\n12345 Hello\n", out.AsString());
 }
 
diff --git a/bin/zxdb/console/console.cc b/bin/zxdb/console/console.cc
index 2008e4a..a8e2b99 100644
--- a/bin/zxdb/console/console.cc
+++ b/bin/zxdb/console/console.cc
@@ -7,7 +7,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "garnet/public/lib/fxl/logging.h"
 #include "garnet/bin/zxdb/client/err.h"
 #include "garnet/bin/zxdb/client/process.h"
 #include "garnet/bin/zxdb/client/target.h"
@@ -15,14 +14,14 @@
 #include "garnet/bin/zxdb/console/command.h"
 #include "garnet/bin/zxdb/console/command_parser.h"
 #include "garnet/bin/zxdb/console/output_buffer.h"
+#include "garnet/public/lib/fxl/logging.h"
 #include "garnet/public/lib/fxl/strings/string_printf.h"
 
 namespace zxdb {
 
 Console* Console::singleton_ = nullptr;
 
-Console::Console(Session* session)
-    : context_(session), line_input_("[zxdb] ") {
+Console::Console(Session* session) : context_(session), line_input_("[zxdb] ") {
   FXL_DCHECK(!singleton_);
   singleton_ = this;
 
diff --git a/bin/zxdb/console/console_context.cc b/bin/zxdb/console/console_context.cc
index 0615bc7..e56321f 100644
--- a/bin/zxdb/console/console_context.cc
+++ b/bin/zxdb/console/console_context.cc
@@ -101,9 +101,7 @@
   active_target_id_ = found->second;
 }
 
-int ConsoleContext::GetActiveTargetId() const {
-  return active_target_id_;
-}
+int ConsoleContext::GetActiveTargetId() const { return active_target_id_; }
 
 Target* ConsoleContext::GetActiveTarget() const {
   auto found = id_to_target_.find(active_target_id_);
@@ -151,9 +149,9 @@
   }
 
   // Should be a valid frame index in the thread.
-  FXL_DCHECK(
-      record->active_frame_id >= 0 &&
-      record->active_frame_id < static_cast<int>(thread->GetFrames().size()));
+  FXL_DCHECK(record->active_frame_id >= 0 &&
+             record->active_frame_id <
+                 static_cast<int>(thread->GetFrames().size()));
   return record->active_frame_id;
 }
 
@@ -277,8 +275,8 @@
   breakpoint_to_id_.erase(found_breakpoint);
 }
 
-void ConsoleContext::DidTryToLoadSymbolMapping(
-    bool ids_loaded, const std::string& msg) {
+void ConsoleContext::DidTryToLoadSymbolMapping(bool ids_loaded,
+                                               const std::string& msg) {
   Console* console = Console::get();
   console->Output(msg);
 }
@@ -297,8 +295,8 @@
   record->next_thread_id = 1;
 }
 
-void ConsoleContext::DidDestroyProcess(Target* target, DestroyReason reason,
-                                       int exit_code) {
+void ConsoleContext::WillDestroyProcess(Target* target, Process* process,
+                                        DestroyReason reason, int exit_code) {
   TargetRecord* record = GetTargetRecord(target);
   if (!record) {
     FXL_NOTREACHED();
@@ -423,8 +421,8 @@
     out.Append("\n");
   }
 
-  out.Append(fxl::StringPrintf(
-      "Stopped on %s exception\n", ExceptionTypeToString(type).c_str()));
+  out.Append(fxl::StringPrintf("Stopped on %s exception\n",
+                               ExceptionTypeToString(type).c_str()));
 
   // Frame (current position will always be frame 0).
   const auto& frames = thread->GetFrames();
@@ -472,8 +470,8 @@
 
 ConsoleContext::ThreadRecord* ConsoleContext::GetThreadRecord(
     const Thread* thread) {
-  TargetRecord* target_record = GetTargetRecord(
-      thread->GetProcess()->GetTarget());
+  TargetRecord* target_record =
+      GetTargetRecord(thread->GetProcess()->GetTarget());
   if (!target_record) {
     FXL_NOTREACHED();
     return nullptr;
@@ -495,8 +493,7 @@
 }
 
 Err ConsoleContext::FillOutTarget(
-    Command* cmd,
-    TargetRecord const** out_target_record) const {
+    Command* cmd, TargetRecord const** out_target_record) const {
   int target_id = cmd->GetNounIndex(Noun::kProcess);
   if (target_id == Command::kNoIndex) {
     // No index: use the active one (which should always exist).
@@ -513,8 +510,8 @@
   // Explicit index given, look it up.
   auto found_target = id_to_target_.find(target_id);
   if (found_target == id_to_target_.end()) {
-    return Err(ErrType::kInput, fxl::StringPrintf(
-        "There is no process %d.", target_id));
+    return Err(ErrType::kInput,
+               fxl::StringPrintf("There is no process %d.", target_id));
   }
   cmd->set_target(found_target->second.target);
   *out_target_record = GetTargetRecord(target_id);
@@ -522,8 +519,7 @@
 }
 
 Err ConsoleContext::FillOutThread(
-    Command* cmd,
-    const TargetRecord* target_record,
+    Command* cmd, const TargetRecord* target_record,
     ThreadRecord const** out_thread_record) const {
   int thread_id = cmd->GetNounIndex(Noun::kThread);
   const ThreadRecord* thread_record = nullptr;
@@ -549,8 +545,9 @@
     if (target_record->id_to_thread.empty()) {
       return Err(ErrType::kInput, "There are no threads in the process.");
     }
-    return Err(ErrType::kInput, fxl::StringPrintf(
-        "There is no thread %d in the process.", thread_id));
+    return Err(
+        ErrType::kInput,
+        fxl::StringPrintf("There is no thread %d in the process.", thread_id));
   }
 
   thread_record = &found_thread->second;
@@ -605,7 +602,8 @@
                "Use \"frame\" to list the frames before selecting one to "
                "populate the frame list.");
   }
-  return Err(ErrType::kInput, "Invalid frame index.\n"
+  return Err(ErrType::kInput,
+             "Invalid frame index.\n"
              "Use \"frame\" to list available ones.");
 }
 
diff --git a/bin/zxdb/console/console_context.h b/bin/zxdb/console/console_context.h
index 7b7ccb1..313be49 100644
--- a/bin/zxdb/console/console_context.h
+++ b/bin/zxdb/console/console_context.h
@@ -23,9 +23,11 @@
 // objects and watches for changes.
 //
 // This class maintains the mapping between objects and IDs.
-class ConsoleContext
-    : public ProcessObserver, public SystemObserver, public TargetObserver,
-      public ThreadObserver, public BreakpointObserver {
+class ConsoleContext : public ProcessObserver,
+                       public SystemObserver,
+                       public TargetObserver,
+                       public ThreadObserver,
+                       public BreakpointObserver {
  public:
   explicit ConsoleContext(Session* session);
   ~ConsoleContext();
@@ -95,8 +97,8 @@
 
   // TargetObserver implementation:
   void DidCreateProcess(Target* target, Process* process) override;
-  void DidDestroyProcess(Target* target, DestroyReason reason,
-                         int exit_code) override;
+  void WillDestroyProcess(Target* target, Process* process,
+                          DestroyReason reason, int exit_code) override;
 
   // ProcessObserver implementation:
   void DidCreateThread(Process* process, Thread* thread) override;
diff --git a/bin/zxdb/console/line_input.cc b/bin/zxdb/console/line_input.cc
index 599844f..f2ce4d7 100644
--- a/bin/zxdb/console/line_input.cc
+++ b/bin/zxdb/console/line_input.cc
@@ -8,8 +8,8 @@
 #include <unistd.h>
 
 #ifdef __Fuchsia__
+#include <lib/fdio/io.h>
 #include <zircon/device/pty.h>
-#include <fdio/io.h>
 #else
 #include <sys/ioctl.h>
 #include <termios.h>
@@ -60,9 +60,7 @@
   history_.emplace_front();
 }
 
-LineInputBase::~LineInputBase() {
-  EnsureNoRawMode();
-}
+LineInputBase::~LineInputBase() { EnsureNoRawMode(); }
 
 void LineInputBase::BeginReadLine() {
   FXL_DCHECK(!editing_);  // Two BeginReadLine calls with no enter input.
@@ -281,8 +279,7 @@
 
 void LineInputBase::Insert(char c) {
   if (pos_ == cur_line().size() &&
-      (max_cols_ == 0 ||
-       cur_line().size() + prompt_.size() < max_cols_ - 1)) {
+      (max_cols_ == 0 || cur_line().size() + prompt_.size() < max_cols_ - 1)) {
     // Append to end and no scrolling needed. Optimize output to avoid
     // redrawing the entire line.
     cur_line().push_back(c);
@@ -430,12 +427,12 @@
 }
 
 void LineInputStdout::EnsureNoRawMode() {
-  #if !defined(__Fuchsia__)
+#if !defined(__Fuchsia__)
   if (raw_mode_enabled_) {
     tcsetattr(STDOUT_FILENO, TCSAFLUSH, original_termios_.get());
     raw_mode_enabled_ = false;
   }
-  #endif
+#endif
 }
 
 LineInputBlockingStdio::LineInputBlockingStdio(const std::string& prompt)
diff --git a/bin/zxdb/console/line_input.h b/bin/zxdb/console/line_input.h
index 0d87c73..9a1a33b 100644
--- a/bin/zxdb/console/line_input.h
+++ b/bin/zxdb/console/line_input.h
@@ -131,7 +131,7 @@
   // you edit, and this shadow copy is replaced with the actual history
   // whenever you start editing a new line.
   std::deque<std::string> history_;  // front() is newest.
-  size_t history_index_ = 0;  // Offset from history_.front().
+  size_t history_index_ = 0;         // Offset from history_.front().
   const size_t max_history_ = 256;
 
   bool completion_mode_ = false;
@@ -176,7 +176,6 @@
   std::unique_ptr<termios> raw_termios_;
   std::unique_ptr<termios> original_termios_;
 #endif
-
 };
 
 // A blocking implementation that reads from stdin and writes to stdout.
diff --git a/bin/zxdb/console/line_input_unittest.cc b/bin/zxdb/console/line_input_unittest.cc
index 1dab55d..6eb6c55 100644
--- a/bin/zxdb/console/line_input_unittest.cc
+++ b/bin/zxdb/console/line_input_unittest.cc
@@ -27,9 +27,7 @@
  public:
   TestLineInput(const std::string& prompt) : LineInputBase(prompt) {}
 
-  void ClearOutput() {
-    output_.clear();
-  }
+  void ClearOutput() { output_.clear(); }
   std::string GetAndClearOutput() {
     std::string ret = output_;
     ClearOutput();
@@ -46,9 +44,7 @@
   }
 
  protected:
-  void Write(const std::string& data) {
-    output_.append(data);
-  }
+  void Write(const std::string& data) { output_.append(data); }
 
  private:
   std::string output_;
diff --git a/bin/zxdb/console/memory_format.cc b/bin/zxdb/console/memory_format.cc
index 6c39ac3..ec4c82b 100644
--- a/bin/zxdb/console/memory_format.cc
+++ b/bin/zxdb/console/memory_format.cc
@@ -19,16 +19,12 @@
 const char kNonAscii =
     ' ';  // When printing ASCII and the character is not in range.
 
-bool IsPrintableAscii(uint8_t c) {
-  return c >= ' ' && c < 0x7f;
-}
+bool IsPrintableAscii(uint8_t c) { return c >= ' ' && c < 0x7f; }
 
 }  // namespace
 
 // Optimized for simplicity over speed.
-std::string FormatMemory(const MemoryDump& dump,
-                         uint64_t begin,
-                         uint32_t size,
+std::string FormatMemory(const MemoryDump& dump, uint64_t begin, uint32_t size,
                          const MemoryFormatOptions& opts) {
   std::string out;
 
@@ -40,8 +36,8 @@
   // Max address character width.
   int addr_width = 0;
   if (opts.show_addrs) {
-    addr_width = static_cast<int>(fxl::StringPrintf(
-        "%" PRIX64, max_addr).size());
+    addr_width =
+        static_cast<int>(fxl::StringPrintf("%" PRIX64, max_addr).size());
   }
 
   uint64_t cur = begin;  // Current address being printed.
diff --git a/bin/zxdb/console/memory_format.h b/bin/zxdb/console/memory_format.h
index 7356807..c0b0703 100644
--- a/bin/zxdb/console/memory_format.h
+++ b/bin/zxdb/console/memory_format.h
@@ -23,9 +23,7 @@
   int separator_every = 0;
 };
 
-std::string FormatMemory(const MemoryDump& dump,
-                         uint64_t begin,
-                         uint32_t size,
+std::string FormatMemory(const MemoryDump& dump, uint64_t begin, uint32_t size,
                          const MemoryFormatOptions& opts);
 
 }  // namespace zxdb
diff --git a/bin/zxdb/console/memory_format_unittest.cc b/bin/zxdb/console/memory_format_unittest.cc
index dec7a61..e25b6c1 100644
--- a/bin/zxdb/console/memory_format_unittest.cc
+++ b/bin/zxdb/console/memory_format_unittest.cc
@@ -56,8 +56,10 @@
   opts.show_ascii = false;
   output = FormatMemory(dump, 0xF0, 0x20, opts);
   char expected4[] =
-      "0F0:  ?? ?? ?? ?? ?? ?? ?? ??""-?? ?? ?? ?? ?? ?? ?? ??\n"
-      "100:  ?? ?? ?? ?? ?? ?? ?? ??""-?? ?? ?? ?? ?? ?? ?? ??\n";
+      "0F0:  ?? ?? ?? ?? ?? ?? ?? ??"
+      "-?? ?? ?? ?? ?? ?? ?? ??\n"
+      "100:  ?? ?? ?? ?? ?? ?? ?? ??"
+      "-?? ?? ?? ?? ?? ?? ?? ??\n";
   EXPECT_EQ(expected4, output);
 
   // Non-aligned start offset, crosses valid/invalid boundary, weird separator
@@ -67,7 +69,8 @@
   opts.separator_every = 5;
   output = FormatMemory(dump, 0xFFA, 0x19, opts);
   char expected5[] =
-      "0FFA:  ?? ?? ?? ?? ??""-?? 00 01 02 03-04 05 06 07 08-09  |               "
+      "0FFA:  ?? ?? ?? ?? ??"
+      "-?? 00 01 02 03-04 05 06 07 08-09  |               "
       " \n"
       "100A:  0A 0B 0C 0D 0E-0F 10 11 12                       |               "
       " \n";
diff --git a/bin/zxdb/console/nouns.cc b/bin/zxdb/console/nouns.cc
index 0277b10..66abad5 100644
--- a/bin/zxdb/console/nouns.cc
+++ b/bin/zxdb/console/nouns.cc
@@ -4,8 +4,8 @@
 
 #include "garnet/bin/zxdb/console/nouns.h"
 
-#include <algorithm>
 #include <inttypes.h>
+#include <algorithm>
 #include <utility>
 
 #include "garnet/bin/zxdb/client/breakpoint.h"
@@ -111,11 +111,11 @@
   }
 
   OutputBuffer out;
-  FormatColumns({ColSpec(Align::kLeft),
-                 ColSpec(Align::kRight, 0, "#"),
-                 ColSpec(Align::kLeft, 0, "State"),
-                 ColSpec(Align::kRight, 0, "Koid"),
-                 ColSpec(Align::kLeft, 0, "Name")}, rows, &out);
+  FormatColumns(
+      {ColSpec(Align::kLeft), ColSpec(Align::kRight, 0, "#"),
+       ColSpec(Align::kLeft, 0, "State"), ColSpec(Align::kRight, 0, "Koid"),
+       ColSpec(Align::kLeft, 0, "Name")},
+      rows, &out);
   Console::get()->Output(std::move(out));
 }
 
@@ -198,11 +198,11 @@
   }
 
   OutputBuffer out;
-  FormatColumns({ColSpec(Align::kLeft),
-                 ColSpec(Align::kRight, 0, "#"),
-                 ColSpec(Align::kLeft, 0, "State"),
-                 ColSpec(Align::kRight, 0, "Koid"),
-                 ColSpec(Align::kLeft, 0, "Name")}, rows, &out);
+  FormatColumns(
+      {ColSpec(Align::kLeft), ColSpec(Align::kRight, 0, "#"),
+       ColSpec(Align::kLeft, 0, "State"), ColSpec(Align::kRight, 0, "Koid"),
+       ColSpec(Align::kLeft, 0, "Name")},
+      rows, &out);
   Console::get()->Output(std::move(out));
 }
 
@@ -259,16 +259,16 @@
     row.push_back(BreakpointScopeToString(context, settings));
     row.push_back(BreakpointStopToString(settings.stop_mode));
     row.push_back(BreakpointEnabledToString(settings.enabled));
-    row.push_back(fxl::StringPrintf("0x%" PRIx64, settings.location_address));
+    row.push_back(DescribeBreakpointLocation(settings));
   }
 
   OutputBuffer out;
-  FormatColumns({ColSpec(Align::kLeft),
-                 ColSpec(Align::kRight, 0, "#"),
-                 ColSpec(Align::kLeft, 0, "Scope"),
-                 ColSpec(Align::kLeft, 0, "Stop"),
-                 ColSpec(Align::kLeft, 0, "Enabled"),
-                 ColSpec(Align::kLeft, 0, "Location")}, rows, &out);
+  FormatColumns(
+      {ColSpec(Align::kLeft), ColSpec(Align::kRight, 0, "#"),
+       ColSpec(Align::kLeft, 0, "Scope"), ColSpec(Align::kLeft, 0, "Stop"),
+       ColSpec(Align::kLeft, 0, "Enabled"),
+       ColSpec(Align::kLeft, 0, "Location")},
+      rows, &out);
   Console::get()->Output(std::move(out));
 }
 
diff --git a/bin/zxdb/console/verbs_breakpoint.cc b/bin/zxdb/console/verbs_breakpoint.cc
index a57572f..e91a35f 100644
--- a/bin/zxdb/console/verbs_breakpoint.cc
+++ b/bin/zxdb/console/verbs_breakpoint.cc
@@ -24,8 +24,7 @@
 // Backend for setting attributes on a breakpoint from both creation and
 // editing. The given breakpoint is specified if this is an edit, or is null
 // if this is a creation.
-Err CreateOrEditBreakpoint(ConsoleContext* context,
-                           const Command& cmd,
+Err CreateOrEditBreakpoint(ConsoleContext* context, const Command& cmd,
                            Breakpoint* breakpoint) {
   // Get existing settings (or defaults for new one).
   BreakpointSettings settings;
@@ -71,10 +70,10 @@
     Err err = ParseBreakpointLocation(cmd.args()[0], &settings);
     if (err.has_error())
       return err;
-    settings.location_type = BreakpointSettings::LocationType::kAddress;
   } else {
-    return Err(ErrType::kInput, "Expecting only one arg for the location.\n"
-        "Formats: <function>, <file>:<line#>, <line#>, or *<address>");
+    return Err(ErrType::kInput,
+               "Expecting only one arg for the location.\n"
+               "Formats: <function>, <file>:<line#>, <line#>, or *<address>");
   }
 
   // Scope.
@@ -328,8 +327,8 @@
 
   // Check for one colon. Two colons is a C++ member function.
   size_t colon = input.find(':');
-  if (colon != std::string::npos &&
-      colon < input.size() - 1 && input[colon + 1] != ':') {
+  if (colon != std::string::npos && colon < input.size() - 1 &&
+      input[colon + 1] != ':') {
     // <file>:<line> format.
     std::string file = input.substr(0, colon);
 
@@ -364,7 +363,8 @@
   }
 
   // Number, assume line number in current file.
-  return Err("TODO(brettw): Need to get the current source file to interpret "
+  return Err(
+      "TODO(brettw): Need to get the current source file to interpret "
       "this line number inside of.");
 }
 
diff --git a/bin/zxdb/console/verbs_breakpoint_unittest.cc b/bin/zxdb/console/verbs_breakpoint_unittest.cc
index 7ebd1e4..a4e2042 100644
--- a/bin/zxdb/console/verbs_breakpoint_unittest.cc
+++ b/bin/zxdb/console/verbs_breakpoint_unittest.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "garnet/bin/zxdb/client/breakpoint_settings.h"
 #include "garnet/bin/zxdb/console/verbs_breakpoint.h"
+#include "garnet/bin/zxdb/client/breakpoint_settings.h"
 #include "gtest/gtest.h"
 
 namespace zxdb {
diff --git a/bin/zxdb/console/verbs_control.cc b/bin/zxdb/console/verbs_control.cc
index c68d7ea..34bc440 100644
--- a/bin/zxdb/console/verbs_control.cc
+++ b/bin/zxdb/console/verbs_control.cc
@@ -108,7 +108,7 @@
     } else {
       // Not a valid command.
       out.OutputErr(Err("\"" + on_what + "\" is not a valid command.\n"
-                        "Try just \"help\" to get a list."));
+                                         "Try just \"help\" to get a list."));
       Console::get()->Output(std::move(out));
       return Err();
     }
@@ -183,14 +183,14 @@
   }
 
   context->session()->Connect(host, port, [](const Err& err) {
-      if (err.has_error()) {
-        // Don't display error message if they canceled the connection.
-        if (err.type() != ErrType::kCanceled)
-          Console::get()->Output(err);
-      } else {
-        Console::get()->Output("Connected successfully.");
-      }
-    });
+    if (err.has_error()) {
+      // Don't display error message if they canceled the connection.
+      if (err.type() != ErrType::kCanceled)
+        Console::get()->Output(err);
+    } else {
+      Console::get()->Output("Connected successfully.");
+    }
+  });
   Console::get()->Output("Connecting (use \"disconnect\" to cancel)...\n");
 
   return Err();
@@ -211,11 +211,11 @@
     return Err(ErrType::kInput, "\"disconnect\" takes no arguments.");
 
   context->session()->Disconnect([](const Err& err) {
-      if (err.has_error())
-        Console::get()->Output(err);
-      else
-        Console::get()->Output("Disconnected successfully.");
-    });
+    if (err.has_error())
+      Console::get()->Output(err);
+    else
+      Console::get()->Output("Disconnected successfully.");
+  });
 
   return Err();
 }
@@ -229,9 +229,8 @@
       VerbRecord(&DoQuit, {"quit", "q"}, kQuitShortHelp, kQuitHelp);
   (*verbs)[Verb::kConnect] =
       VerbRecord(&DoConnect, {"connect"}, kConnectShortHelp, kConnectHelp);
-  (*verbs)[Verb::kDisconnect] =
-      VerbRecord(&DoDisconnect, {"disconnect"}, kDisconnectShortHelp,
-                 kDisconnectHelp);
+  (*verbs)[Verb::kDisconnect] = VerbRecord(
+      &DoDisconnect, {"disconnect"}, kDisconnectShortHelp, kDisconnectHelp);
 }
 
 }  // namespace zxdb
diff --git a/bin/zxdb/console/verbs_memory.cc b/bin/zxdb/console/verbs_memory.cc
index fb1b72b..5be51fc 100644
--- a/bin/zxdb/console/verbs_memory.cc
+++ b/bin/zxdb/console/verbs_memory.cc
@@ -106,9 +106,7 @@
 // disassemble -----------------------------------------------------------------
 
 // Completion callback after reading process memory.
-void CompleteDisassemble(const Err& err,
-                         MemoryDump dump,
-                         uint64_t num_instr,
+void CompleteDisassemble(const Err& err, MemoryDump dump, uint64_t num_instr,
                          fxl::WeakPtr<Process> weak_process,
                          Disassembler::Options options) {
   Console* console = Console::get();
diff --git a/bin/zxdb/console/verbs_process.cc b/bin/zxdb/console/verbs_process.cc
index 9faf230..f13c7ac 100644
--- a/bin/zxdb/console/verbs_process.cc
+++ b/bin/zxdb/console/verbs_process.cc
@@ -4,8 +4,8 @@
 
 #include "garnet/bin/zxdb/console/verbs.h"
 
-#include <algorithm>
 #include <inttypes.h>
+#include <algorithm>
 #include <vector>
 
 #include "garnet/bin/zxdb/client/err.h"
@@ -41,10 +41,8 @@
 
 // Callback for "run", "attach", "detach" and "stop". The verb affects the
 // message printed to the screen.
-void ProcessCommandCallback(const char* verb,
-                            fxl::WeakPtr<Target> target,
-                            bool display_message_on_success,
-                            const Err& err) {
+void ProcessCommandCallback(const char* verb, fxl::WeakPtr<Target> target,
+                            bool display_message_on_success, const Err& err) {
   if (!display_message_on_success && !err.has_error())
     return;
 
diff --git a/bin/zxdb/console/verbs_system.cc b/bin/zxdb/console/verbs_system.cc
index 3c5d3cf..2fffa91 100644
--- a/bin/zxdb/console/verbs_system.cc
+++ b/bin/zxdb/console/verbs_system.cc
@@ -24,9 +24,14 @@
   line << std::setw(indent * 2) << "";
 
   switch (rec.type) {
-    case debug_ipc::ProcessTreeRecord::Type::kJob: line << 'j'; break;
-    case debug_ipc::ProcessTreeRecord::Type::kProcess: line << 'p'; break;
-    default: line << '?';
+    case debug_ipc::ProcessTreeRecord::Type::kJob:
+      line << 'j';
+      break;
+    case debug_ipc::ProcessTreeRecord::Type::kProcess:
+      line << 'p';
+      break;
+    default:
+      line << '?';
   }
 
   line << ": " << rec.koid << " " << rec.name << "\n";
diff --git a/bin/zxdb/console/verbs_thread.cc b/bin/zxdb/console/verbs_thread.cc
index c491f04..dbd993d 100644
--- a/bin/zxdb/console/verbs_thread.cc
+++ b/bin/zxdb/console/verbs_thread.cc
@@ -86,7 +86,7 @@
       if no index is specified).
 )";
 Err DoContinue(ConsoleContext* context, const Command& cmd) {
-  Err err = cmd.ValidateNouns({ Noun::kProcess, Noun::kThread });
+  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
   if (err.has_error())
     return err;
 
@@ -155,7 +155,7 @@
       if no index is specified).
 )";
 Err DoPause(ConsoleContext* context, const Command& cmd) {
-  Err err = cmd.ValidateNouns({ Noun::kProcess, Noun::kThread });
+  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
   if (err.has_error())
     return err;
 
@@ -209,7 +209,7 @@
       Steps thread 2 in process 3.
 )";
 Err DoStepi(ConsoleContext* context, const Command& cmd) {
-  Err err = cmd.ValidateNouns({ Noun::kProcess, Noun::kThread });
+  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
   if (err.has_error())
     return err;
 
@@ -225,9 +225,8 @@
 }  // namespace
 
 void AppendThreadVerbs(std::map<Verb, VerbRecord>* verbs) {
-  (*verbs)[Verb::kContinue] =
-      VerbRecord(&DoContinue, {"continue", "c"}, kContinueShortHelp,
-                 kContinueHelp);
+  (*verbs)[Verb::kContinue] = VerbRecord(&DoContinue, {"continue", "c"},
+                                         kContinueShortHelp, kContinueHelp);
   (*verbs)[Verb::kPause] =
       VerbRecord(&DoPause, {"pause", "pa"}, kPauseShortHelp, kPauseHelp);
   (*verbs)[Verb::kStepi] =
diff --git a/docs/catapult.md b/docs/catapult.md
index e14fa7c..88e46ef 100644
--- a/docs/catapult.md
+++ b/docs/catapult.md
@@ -64,7 +64,7 @@
 
 ```sh
 # on Fuchsia device
-wget http://<ip address>:8080
+curl http://<ip address>:8080
 ```
 
 ## Upload data points
diff --git a/docs/gen/build_arguments.md b/docs/gen/build_arguments.md
index ee126c3..afd448e 100644
--- a/docs/gen/build_arguments.md
+++ b/docs/gen/build_arguments.md
@@ -21,7 +21,7 @@
 
 ### amber_repository_dir
  Directory containing files named by their merkleroot content IDs in
- ASCII hex.  The //build/image:amber_publish_blobs target populates
+ ASCII hex.  The [//build/image](https://fuchsia.googlesource.com/build/+/master/image):amber_publish_blobs target populates
  this with copies of build products, but never removes old files.
 
 **Default value for `target_cpu = "arm64"`:** "//out/arm64/amber-files"
@@ -74,14 +74,14 @@
 **Default value for `target_cpu = "x64"`:** true
 
 
-### build_libvulkan_arm_mali
- This is a list of targets that will be built as drivers. If more than one
+### build_libvulkan
+ This is a list of targets that will be built as vulkan ICDS. If more than one
  target is given then use_vulkan_loader_for_tests must be set to true, as
- otherwise tests won't know which libvulkan to use. Example gn arg:
- build_libvulkan_arm_mali =
- ["//third_party/arm-mali-bifrost:libvulkan_arm"]
+ otherwise tests won't know which libvulkan to use.
 
-**Default value:** []
+**Default value for `target_cpu = "arm64"`:** []
+
+**Default value for `target_cpu = "x64"`:** ["//third_party/mesa:magma_vulkan"]
 
 
 ### build_msd_arm_mali
@@ -91,9 +91,11 @@
 **Default value for `target_cpu = "x64"`:** false
 
 
-### build_msd_vsl_gc
+### build_vsl_gc
 
-**Default value:** false
+**Default value for `target_cpu = "arm64"`:** true
+
+**Default value for `target_cpu = "x64"`:** false
 
 
 ### clang_prefix
@@ -181,9 +183,9 @@
 
 **Default value:** [[]](https://fuchsia.googlesource.com/build/+/master/gn/packages.gni#8)
 
-**Current value for `target_cpu = "arm64"`:** [["garnet/packages/buildbot"]](/arm64/args.gn#2)
+**Current value for `target_cpu = "arm64"`:** ["garnet/packages/buildbot"]
 
-**Current value for `target_cpu = "x64"`:** [["garnet/packages/buildbot"]](/x64/args.gn#2)
+**Current value for `target_cpu = "x64"`:** ["garnet/packages/buildbot"]
 
 
 ### fvm_image_size
@@ -228,7 +230,7 @@
  of the build do not get copied here.  This directory is only for
  things that are generally useful for testing or debugging or
  whatnot outside of the GN build itself.  These are only installed
- by an explicit install_host_tools() rule (see //build/host.gni).
+ by an explicit install_host_tools() rule (see [//build/host.gni](https://fuchsia.googlesource.com/build/+/master/host.gni)).
 
 **Default value for `target_cpu = "arm64"`:** "//out/arm64/tools"
 
@@ -409,6 +411,12 @@
 **Default value:** ""
 
 
+### rust_lto
+ Sets the default LTO type for rustc bulids.
+
+**Default value:** "unset"
+
+
 ### rustc_prefix
  Sets a custom base directory for `rustc` and `cargo`.
  This can be used to test custom Rust toolchains.
@@ -416,7 +424,7 @@
 **Default value:** "//buildtools/linux-x64/rust/bin"
 
 
-### scene_manager_vulkan_swapchain
+### scenic_vulkan_swapchain
  0 - use normal swapchain
  1 - use vulkan swapchain, but wait for real display
  2 - use vulkan swapchain with fixed-size fake display
@@ -514,7 +522,7 @@
 ### select_variant_canonical
  *This should never be set as a build argument.*
  It exists only to be set in `toolchain_args`.
- See //build/toolchain/clang_toolchain.gni for details.
+ See [//build/toolchain/clang_toolchain.gni](https://fuchsia.googlesource.com/build/+/master/toolchain/clang_toolchain.gni) for details.
 
 **Default value:** []
 
@@ -547,7 +555,7 @@
  Synthesized packages can't express dependencies on other packages.
 
  Each element of this list is a scope that is very much like the body of
- a package() template invocation (see //build/package.gni).  That scope
+ a package() template invocation (see [//build/package.gni](https://fuchsia.googlesource.com/build/+/master/package.gni)).  That scope
  must set `name` to the string naming the package, as would be the name
  in the package() target written in a GN file.  This must be unique
  among all package names.
@@ -568,9 +576,9 @@
 
 **Default value:** ""
 
-**Current value for `target_cpu = "arm64"`:** ["arm64"](/arm64/args.gn#1)
+**Current value for `target_cpu = "arm64"`:** "arm64"
 
-**Current value for `target_cpu = "x64"`:** ["x64"](/x64/args.gn#1)
+**Current value for `target_cpu = "x64"`:** "x64"
 
 
 ### target_os
@@ -587,9 +595,7 @@
 ### thinlto_cache_dir
  ThinLTO cache directory path.
 
-**Default value for `target_cpu = "arm64"`:** "host_x64/thinlto-cache"
-
-**Default value for `target_cpu = "x64"`:** "x64-shared/thinlto-cache"
+**Default value:** "host_x64/thinlto-cache"
 
 
 ### thinlto_jobs
@@ -610,7 +616,7 @@
 ### toolchain_variant
  *This should never be set as a build argument.*
  It exists only to be set in `toolchain_args`.
- See //build/toolchain/clang_toolchain.gni for details.
+ See [//build/toolchain/clang_toolchain.gni](https://fuchsia.googlesource.com/build/+/master/toolchain/clang_toolchain.gni) for details.
  This variable is a scope giving details about the current toolchain:
      toolchain_variant.base
          [label] The "base" toolchain for this variant, *often the
diff --git a/docs/tracing_usage_guide.md b/docs/tracing_usage_guide.md
index 0954df2..ffaf2b0 100644
--- a/docs/tracing_usage_guide.md
+++ b/docs/tracing_usage_guide.md
@@ -4,15 +4,15 @@
 
 Fuchsia tracing library and utilities require access to the `trace_manager`'s
 services in the environment, which is typically set up by the
-[boot sequence](https://fuchsia.googlesource.com/docs/+/master/boot_sequence.md).
+[boot sequence](https://fuchsia.googlesource.com/docs/+/master/the-book/boot_sequence.md).
 
 ## Capturing Traces From a Development Host
 
-Traces are captured using the `traceutil` host utility.  To record a trace
+Traces are captured using the `fx traceutil` host utility.  To record a trace
 simply run the following on your development host:
 
 ```{shell}
-traceutil record
+fx traceutil record
 ```
 
 This will:
@@ -23,17 +23,17 @@
 This is a great place to start an investigation.  It is also a good when you
 are reporting a bug and are unsure what data is useful.
 
-Some additional command line arguments to `traceutil record` include:
- * `--duration <time>`
+Some additional command line arguments to `fx traceutil record` include:
+ * `-duration <time>`
 
    Sets the duration of the trace in seconds.
 
- * `--target <hostname or ip address>`
+ * `-target <hostname or ip address>`
 
    Specifies one which target to take a trace.  Useful if you have multiple
    targets on the same network or network discovery is not working.
 
-For a complete list of command line arguments run `traceutil --help`.
+For a complete list of command line arguments run `fx traceutil record --help`.
 
 ## Capturing Traces From a Fuchsia Target
 
@@ -56,7 +56,7 @@
 Trace-Viewer.  To convert one or more JSON files run:
 
 ```{shell}
-traceutil convert FILE ...
+fx traceutil convert FILE ...
 ```
 
 The HTML files written are standalone and can be opened in the
diff --git a/drivers/bluetooth/host/BUILD.gn b/drivers/bluetooth/host/BUILD.gn
index a48cf16..2dc962d 100644
--- a/drivers/bluetooth/host/BUILD.gn
+++ b/drivers/bluetooth/host/BUILD.gn
@@ -25,8 +25,6 @@
     "host_device.h",
 
     # FIDL servers
-    "fidl/adapter_server.cc",
-    "fidl/adapter_server.h",
     "fidl/gatt_client_server.cc",
     "fidl/gatt_client_server.h",
     "fidl/gatt_remote_service_server.cc",
@@ -56,6 +54,7 @@
     "//zircon/public/lib/ddk",
     "//zircon/public/lib/driver",
     "//zircon/public/lib/fbl",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/zx",
   ]
 }
diff --git a/drivers/bluetooth/host/fidl/adapter_server.cc b/drivers/bluetooth/host/fidl/adapter_server.cc
deleted file mode 100644
index 1d24b43..0000000
--- a/drivers/bluetooth/host/fidl/adapter_server.cc
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "adapter_server.h"
-
-#include "garnet/drivers/bluetooth/lib/gap/adapter.h"
-#include "garnet/drivers/bluetooth/lib/gap/bredr_connection_manager.h"
-#include "garnet/drivers/bluetooth/lib/gap/bredr_discovery_manager.h"
-#include "garnet/drivers/bluetooth/lib/gap/gap.h"
-#include "garnet/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h"
-#include "lib/fxl/logging.h"
-
-#include "helpers.h"
-
-using bluetooth::Bool;
-using bluetooth::ErrorCode;
-using bluetooth::Status;
-
-using bluetooth_control::AdapterState;
-
-namespace bthost {
-
-AdapterServer::AdapterServer(
-    fxl::WeakPtr<::btlib::gap::Adapter> adapter,
-    fidl::InterfaceRequest<bluetooth_host::Adapter> request)
-    : AdapterServerBase(adapter, this, std::move(request)),
-      requesting_discovery_(false),
-      weak_ptr_factory_(this) {}
-
-AdapterServer::~AdapterServer() {}
-
-void AdapterServer::GetInfo(GetInfoCallback callback) {
-  callback(fidl_helpers::NewAdapterInfo(*adapter()));
-}
-
-void AdapterServer::SetLocalName(::fidl::StringPtr local_name,
-                                 SetLocalNameCallback callback) {
-  adapter()->SetLocalName(local_name, [self = weak_ptr_factory_.GetWeakPtr(),
-                                       callback](auto status) {
-    callback(fidl_helpers::StatusToFidl(status, "Can't Set Local Name"));
-  });
-}
-
-void AdapterServer::StartDiscovery(StartDiscoveryCallback callback) {
-  FXL_VLOG(1) << "Adapter StartDiscovery()";
-  FXL_DCHECK(adapter());
-
-  if (le_discovery_session_ || requesting_discovery_) {
-    FXL_VLOG(1) << "Discovery already in progress";
-    callback(fidl_helpers::NewFidlError(ErrorCode::IN_PROGRESS,
-                                        "Discovery already in progress"));
-    return;
-  }
-
-  requesting_discovery_ = true;
-  auto bredr_manager = adapter()->bredr_discovery_manager();
-  // TODO(jamuraa): start these in parallel instead of sequence
-  bredr_manager->RequestDiscovery([self = weak_ptr_factory_.GetWeakPtr(),
-                                   bredr_manager, callback](
-                                      btlib::hci::Status status, auto session) {
-    if (!self) {
-      callback(
-          fidl_helpers::NewFidlError(ErrorCode::FAILED, "Adapter Shutdown"));
-      return;
-    }
-
-    if (!status || !session) {
-      FXL_VLOG(1) << "Failed to start BR/EDR discovery session";
-      callback(fidl_helpers::StatusToFidl(
-          status, "Failed to start BR/EDR discovery session"));
-      self->requesting_discovery_ = false;
-      return;
-    }
-
-    session->set_result_callback([self](const auto& device) {
-      if (self) {
-        self->OnDiscoveryResult(device);
-      }
-    });
-
-    self->bredr_discovery_session_ = std::move(session);
-
-    auto le_manager = self->adapter()->le_discovery_manager();
-    le_manager->StartDiscovery([self, callback](auto session) {
-      // End the new session if this AdapterServer got destroyed in the mean
-      // time (e.g. because the client disconnected).
-      if (!self) {
-        callback(
-            fidl_helpers::NewFidlError(ErrorCode::FAILED, "Adapter Shutdown"));
-        return;
-      }
-
-      if (!session) {
-        FXL_VLOG(1) << "Failed to start LE discovery session";
-        callback(fidl_helpers::NewFidlError(
-            ErrorCode::FAILED, "Failed to start LE discovery session"));
-        self->bredr_discovery_session_ = nullptr;
-        self->requesting_discovery_ = false;
-        return;
-      }
-
-      // Set up a general-discovery filter for connectable devices.
-      session->filter()->set_connectable(true);
-      session->filter()->SetGeneralDiscoveryFlags();
-      session->SetResultCallback([self](const auto& device) {
-        if (self) {
-          self->OnDiscoveryResult(device);
-        }
-      });
-
-      self->le_discovery_session_ = std::move(session);
-      self->requesting_discovery_ = false;
-
-      // Send the adapter state update.
-      AdapterState state;
-      state.discovering = bluetooth::Bool::New();
-      state.discovering->value = true;
-      self->binding()->events().OnAdapterStateChanged(std::move(state));
-
-      callback(Status());
-    });
-  });
-}
-
-void AdapterServer::StopDiscovery(StopDiscoveryCallback callback) {
-  FXL_VLOG(1) << "Adapter StopDiscovery()";
-  if (!le_discovery_session_) {
-    FXL_VLOG(1) << "No active discovery session";
-    callback(fidl_helpers::NewFidlError(ErrorCode::BAD_STATE,
-                                        "No discovery session in progress"));
-    return;
-  }
-
-  bredr_discovery_session_ = nullptr;
-  le_discovery_session_ = nullptr;
-
-  AdapterState state;
-  state.discovering = bluetooth::Bool::New();
-  state.discovering->value = false;
-  this->binding()->events().OnAdapterStateChanged(std::move(state));
-
-  callback(Status());
-}
-
-void AdapterServer::SetConnectable(bool connectable,
-                                   SetConnectableCallback callback) {
-  FXL_VLOG(1) << "Adapter SetConnectable(" << connectable << ")";
-
-  adapter()->bredr_connection_manager()->SetConnectable(
-      connectable, [callback](const auto& status) {
-        callback(fidl_helpers::StatusToFidl(status));
-      });
-}
-
-void AdapterServer::SetDiscoverable(bool discoverable,
-                                    SetDiscoverableCallback callback) {
-  FXL_VLOG(1) << "Adapter SetDiscoverable(" << discoverable << ")";
-  // TODO(NET-830): advertise LE here
-  if (!discoverable) {
-    bredr_discoverable_session_ = nullptr;
-
-    AdapterState state;
-    state.discoverable = bluetooth::Bool::New();
-    state.discoverable->value = false;
-    this->binding()->events().OnAdapterStateChanged(std::move(state));
-
-    callback(Status());
-  }
-  if (discoverable && requesting_discoverable_) {
-    FXL_VLOG(1) << "Discoverable already being set";
-    callback(fidl_helpers::NewFidlError(ErrorCode::IN_PROGRESS,
-                                        "Discovery already in progress"));
-    return;
-  }
-  requesting_discoverable_ = true;
-  auto bredr_manager = adapter()->bredr_discovery_manager();
-  bredr_manager->RequestDiscoverable(
-      [self = weak_ptr_factory_.GetWeakPtr(), callback](
-          btlib::hci::Status status, auto session) {
-        if (!self) {
-          callback(fidl_helpers::NewFidlError(ErrorCode::FAILED,
-                                              "Adapter Shutdown"));
-          return;
-        }
-        if (!status || !session) {
-          FXL_VLOG(1) << "Failed to set discoverable!";
-          callback(
-              fidl_helpers::StatusToFidl(status, "Failed to set discoverable"));
-          self->requesting_discoverable_ = false;
-        }
-        self->bredr_discoverable_session_ = std::move(session);
-        AdapterState state;
-        state.discoverable = bluetooth::Bool::New();
-        state.discoverable->value = true;
-        self->binding()->events().OnAdapterStateChanged(std::move(state));
-        callback(Status());
-      });
-}
-
-void AdapterServer::OnDiscoveryResult(
-    const ::btlib::gap::RemoteDevice& remote_device) {
-  auto fidl_device = fidl_helpers::NewRemoteDevice(remote_device);
-  if (!fidl_device) {
-    FXL_VLOG(1) << "Ignoring malformed discovery result";
-    return;
-  }
-
-  this->binding()->events().OnDeviceDiscovered(std::move(*fidl_device));
-}
-
-}  // namespace bthost
diff --git a/drivers/bluetooth/host/fidl/adapter_server.h b/drivers/bluetooth/host/fidl/adapter_server.h
deleted file mode 100644
index 4d390d0..0000000
--- a/drivers/bluetooth/host/fidl/adapter_server.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#pragma once
-
-#include "lib/fidl/cpp/binding.h"
-#include "lib/fidl/cpp/interface_request.h"
-#include "lib/fxl/macros.h"
-#include "lib/fxl/memory/weak_ptr.h"
-
-#include <bluetooth_control/cpp/fidl.h>
-#include <bluetooth_host/cpp/fidl.h>
-
-#include "garnet/drivers/bluetooth/host/fidl/server_base.h"
-
-namespace btlib {
-namespace gap {
-
-class BrEdrDiscoverySession;
-class BrEdrDiscoverableSession;
-class LowEnergyDiscoverySession;
-class RemoteDevice;
-
-}  // namespace gap
-}  // namespace btlib
-
-namespace bthost {
-
-// Implements the control.Adapter FIDL interface.
-class AdapterServer : public AdapterServerBase<::bluetooth_host::Adapter> {
- public:
-  AdapterServer(fxl::WeakPtr<::btlib::gap::Adapter> adapter,
-                fidl::InterfaceRequest<bluetooth_host::Adapter> request);
-  ~AdapterServer() override;
-
- private:
-  // ::bluetooth_control::Adapter overrides:
-  void GetInfo(GetInfoCallback callback) override;
-  void SetLocalName(::fidl::StringPtr local_name,
-                    SetLocalNameCallback callback) override;
-  void StartDiscovery(StartDiscoveryCallback callback) override;
-  void StopDiscovery(StopDiscoveryCallback callback) override;
-  void SetConnectable(bool connectable,
-                      SetConnectableCallback callback) override;
-  void SetDiscoverable(bool discoverable,
-                       SetDiscoverableCallback callback) override;
-
-  // Called by |le_discovery_session_| when devices are discovered.
-  void OnDiscoveryResult(const ::btlib::gap::RemoteDevice& remote_device);
-
-  // The currently active discovery sessions.
-  // These are non-null when a client requests to perform discovery.
-  bool requesting_discovery_;
-  std::unique_ptr<::btlib::gap::LowEnergyDiscoverySession>
-      le_discovery_session_;
-  std::unique_ptr<::btlib::gap::BrEdrDiscoverySession> bredr_discovery_session_;
-
-  // The currently active discoverable/advertising sessions.
-  // These are non-null when a client requests that the device is discoverable.
-  // TODO(NET-830): Enable connectable LE advertising
-  bool requesting_discoverable_;
-  std::unique_ptr<::btlib::gap::BrEdrDiscoverableSession>
-      bredr_discoverable_session_;
-
-  // Keep this as the last member to make sure that all weak pointers are
-  // invalidated before other members get destroyed.
-  fxl::WeakPtrFactory<AdapterServer> weak_ptr_factory_;
-
-  FXL_DISALLOW_COPY_AND_ASSIGN(AdapterServer);
-};
-
-}  // namespace bthost
diff --git a/drivers/bluetooth/host/fidl/gatt_client_server.cc b/drivers/bluetooth/host/fidl/gatt_client_server.cc
index 57f951d..c103c00 100644
--- a/drivers/bluetooth/host/fidl/gatt_client_server.cc
+++ b/drivers/bluetooth/host/fidl/gatt_client_server.cc
@@ -12,13 +12,13 @@
 #include "gatt_remote_service_server.h"
 #include "helpers.h"
 
-using bluetooth::ErrorCode;
-using bluetooth::Status;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Status;
 
-using bluetooth_gatt::Client;
-using bluetooth_gatt::RemoteService;
-using bluetooth_gatt::ServiceInfo;
-using bluetooth_gatt::ServiceInfoPtr;
+using fuchsia::bluetooth::gatt::Client;
+using fuchsia::bluetooth::gatt::RemoteService;
+using fuchsia::bluetooth::gatt::ServiceInfo;
+using fuchsia::bluetooth::gatt::ServiceInfoPtr;
 
 namespace bthost {
 
diff --git a/drivers/bluetooth/host/fidl/gatt_client_server.h b/drivers/bluetooth/host/fidl/gatt_client_server.h
index 7bb2f82..3dff628 100644
--- a/drivers/bluetooth/host/fidl/gatt_client_server.h
+++ b/drivers/bluetooth/host/fidl/gatt_client_server.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <bluetooth_gatt/cpp/fidl.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
 
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
@@ -16,11 +16,12 @@
 namespace bthost {
 
 // Implements the gatt::Client FIDL interface.
-class GattClientServer : public GattServerBase<bluetooth_gatt::Client> {
+class GattClientServer
+    : public GattServerBase<fuchsia::bluetooth::gatt::Client> {
  public:
-  GattClientServer(std::string peer_id,
-                   fbl::RefPtr<btlib::gatt::GATT> gatt,
-                   fidl::InterfaceRequest<bluetooth_gatt::Client> request);
+  GattClientServer(
+      std::string peer_id, fbl::RefPtr<btlib::gatt::GATT> gatt,
+      fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Client> request);
   ~GattClientServer() override = default;
 
  private:
@@ -29,7 +30,8 @@
                     ListServicesCallback callback) override;
   void ConnectToService(
       uint64_t id,
-      ::fidl::InterfaceRequest<bluetooth_gatt::RemoteService> service) override;
+      ::fidl::InterfaceRequest<fuchsia::bluetooth::gatt::RemoteService> service)
+      override;
 
   // The ID of the peer that this client is attached to.
   std::string peer_id_;
diff --git a/drivers/bluetooth/host/fidl/gatt_remote_service_server.cc b/drivers/bluetooth/host/fidl/gatt_remote_service_server.cc
index 7cd7159..73d6ca7 100644
--- a/drivers/bluetooth/host/fidl/gatt_remote_service_server.cc
+++ b/drivers/bluetooth/host/fidl/gatt_remote_service_server.cc
@@ -6,12 +6,11 @@
 
 #include "helpers.h"
 
-using bluetooth::ErrorCode;
-using bluetooth::Status;
-
-using bluetooth_gatt::Characteristic;
-using bluetooth_gatt::CharacteristicPtr;
-using bluetooth_gatt::Descriptor;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Status;
+using fuchsia::bluetooth::gatt::Characteristic;
+using fuchsia::bluetooth::gatt::CharacteristicPtr;
+using fuchsia::bluetooth::gatt::Descriptor;
 
 using btlib::common::ByteBuffer;
 using btlib::common::MutableBufferView;
@@ -51,7 +50,7 @@
 GattRemoteServiceServer::GattRemoteServiceServer(
     fbl::RefPtr<btlib::gatt::RemoteService> service,
     fbl::RefPtr<btlib::gatt::GATT> gatt,
-    fidl::InterfaceRequest<bluetooth_gatt::RemoteService> request)
+    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::RemoteService> request)
     : GattServerBase(gatt, this, std::move(request)),
       service_(std::move(service)),
       weak_ptr_factory_(this) {
diff --git a/drivers/bluetooth/host/fidl/gatt_remote_service_server.h b/drivers/bluetooth/host/fidl/gatt_remote_service_server.h
index aea337b..939dfd2 100644
--- a/drivers/bluetooth/host/fidl/gatt_remote_service_server.h
+++ b/drivers/bluetooth/host/fidl/gatt_remote_service_server.h
@@ -6,7 +6,7 @@
 
 #include <unordered_map>
 
-#include <bluetooth_gatt/cpp/fidl.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
 
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
@@ -19,16 +19,16 @@
 
 // Implements the gatt::RemoteService FIDL interface.
 class GattRemoteServiceServer
-    : public GattServerBase<bluetooth_gatt::RemoteService> {
+    : public GattServerBase<fuchsia::bluetooth::gatt::RemoteService> {
  public:
   GattRemoteServiceServer(
       fbl::RefPtr<btlib::gatt::RemoteService> service,
       fbl::RefPtr<btlib::gatt::GATT> gatt,
-      fidl::InterfaceRequest<bluetooth_gatt::RemoteService> request);
+      fidl::InterfaceRequest<fuchsia::bluetooth::gatt::RemoteService> request);
   ~GattRemoteServiceServer() override;
 
  private:
-  // bluetooth_gatt::RemoteService overrides:
+  // fuchsia::bluetooth::gatt::RemoteService overrides:
   void DiscoverCharacteristics(
       DiscoverCharacteristicsCallback callback) override;
   void ReadCharacteristic(uint64_t id,
diff --git a/drivers/bluetooth/host/fidl/gatt_server_server.cc b/drivers/bluetooth/host/fidl/gatt_server_server.cc
index 5f8be2b..237144a 100644
--- a/drivers/bluetooth/host/fidl/gatt_server_server.cc
+++ b/drivers/bluetooth/host/fidl/gatt_server_server.cc
@@ -12,17 +12,19 @@
 
 #include "helpers.h"
 
-using bluetooth::ErrorCode;
-using bluetooth::Status;
-using GattErrorCode = bluetooth_gatt::ErrorCode;
+#include "lib/fxl/functional/make_copyable.h"
 
-using bluetooth_gatt::Characteristic;
-using bluetooth_gatt::Descriptor;
-using bluetooth_gatt::LocalService;
-using bluetooth_gatt::LocalServiceDelegate;
-using bluetooth_gatt::LocalServiceDelegatePtr;
-using bluetooth_gatt::SecurityRequirementsPtr;
-using bluetooth_gatt::ServiceInfo;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Status;
+using GattErrorCode = fuchsia::bluetooth::gatt::ErrorCode;
+
+using fuchsia::bluetooth::gatt::Characteristic;
+using fuchsia::bluetooth::gatt::Descriptor;
+using fuchsia::bluetooth::gatt::LocalService;
+using fuchsia::bluetooth::gatt::LocalServiceDelegate;
+using fuchsia::bluetooth::gatt::LocalServiceDelegatePtr;
+using fuchsia::bluetooth::gatt::SecurityRequirementsPtr;
+using fuchsia::bluetooth::gatt::ServiceInfo;
 
 namespace bthost {
 namespace {
@@ -134,7 +136,7 @@
 // Implements the gatt::LocalService FIDL interface. Instances of this class are
 // only created by a GattServerServer.
 class GattServerServer::LocalServiceImpl
-    : public GattServerBase<::bluetooth_gatt::LocalService> {
+    : public GattServerBase<fuchsia::bluetooth::gatt::LocalService> {
  public:
   LocalServiceImpl(GattServerServer* owner,
                    uint64_t id,
@@ -161,7 +163,7 @@
   LocalServiceDelegate* delegate() { return delegate_.get(); }
 
  private:
-  // ::bluetooth_gatt::Service overrides:
+  // fuchsia::bluetooth::gatt::Service overrides:
   void RemoveService() override {
     CleanUp();
     owner_->RemoveService(id_);
@@ -195,7 +197,7 @@
 
 GattServerServer::GattServerServer(
     fbl::RefPtr<btlib::gatt::GATT> gatt,
-    fidl::InterfaceRequest<bluetooth_gatt::Server> request)
+    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request)
     : GattServerBase(gatt, this, std::move(request)), weak_ptr_factory_(this) {}
 
 GattServerServer::~GattServerServer() {
@@ -259,18 +261,18 @@
 
   // Set up event handlers.
   auto read_handler = [self](auto svc_id, auto id, auto offset,
-                             const auto& responder) {
+                             auto responder) mutable {
     if (self) {
-      self->OnReadRequest(svc_id, id, offset, responder);
+      self->OnReadRequest(svc_id, id, offset, std::move(responder));
     } else {
       responder(::btlib::att::ErrorCode::kUnlikelyError,
                 ::btlib::common::BufferView());
     }
   };
   auto write_handler = [self](auto svc_id, auto id, auto offset,
-                              const auto& value, const auto& responder) {
+                              const auto& value, auto responder) mutable {
     if (self) {
-      self->OnWriteRequest(svc_id, id, offset, value, responder);
+      self->OnWriteRequest(svc_id, id, offset, value, std::move(responder));
     } else {
       responder(::btlib::att::ErrorCode::kUnlikelyError);
     }
@@ -327,7 +329,7 @@
     ::btlib::gatt::IdType service_id,
     ::btlib::gatt::IdType id,
     uint16_t offset,
-    const ::btlib::gatt::ReadResponder& responder) {
+    ::btlib::gatt::ReadResponder responder) {
   auto iter = services_.find(service_id);
   if (iter == services_.end()) {
     responder(::btlib::att::ErrorCode::kUnlikelyError,
@@ -335,14 +337,14 @@
     return;
   }
 
-  auto cb = [responder](fidl::VectorPtr<uint8_t> value, auto error_code) {
+  auto cb = [responder = std::move(responder)](fidl::VectorPtr<uint8_t> value, auto error_code) {
     responder(GattErrorCodeFromFidl(error_code, true /* is_read */),
               ::btlib::common::BufferView(value->data(), value->size()));
   };
 
   auto* delegate = iter->second->delegate();
   FXL_DCHECK(delegate);
-  delegate->OnReadValue(id, offset, cb);
+  delegate->OnReadValue(id, offset, fxl::MakeCopyable(std::move(cb)));
 }
 
 void GattServerServer::OnWriteRequest(
@@ -350,7 +352,7 @@
     ::btlib::gatt::IdType id,
     uint16_t offset,
     const ::btlib::common::ByteBuffer& value,
-    const ::btlib::gatt::WriteResponder& responder) {
+    ::btlib::gatt::WriteResponder responder) {
   auto iter = services_.find(service_id);
   if (iter == services_.end()) {
     responder(::btlib::att::ErrorCode::kUnlikelyError);
@@ -366,11 +368,12 @@
     return;
   }
 
-  auto cb = [responder](auto error_code) {
+  auto cb = [responder = std::move(responder)](auto error_code) {
     responder(GattErrorCodeFromFidl(error_code, false /* is_read */));
   };
 
-  delegate->OnWriteValue(id, offset, std::move(fidl_value), cb);
+  delegate->OnWriteValue(id, offset, std::move(fidl_value),
+      fxl::MakeCopyable(std::move(cb)));
 }
 
 void GattServerServer::OnCharacteristicConfig(::btlib::gatt::IdType service_id,
diff --git a/drivers/bluetooth/host/fidl/gatt_server_server.h b/drivers/bluetooth/host/fidl/gatt_server_server.h
index 4b5d4a5..70eb9d8 100644
--- a/drivers/bluetooth/host/fidl/gatt_server_server.h
+++ b/drivers/bluetooth/host/fidl/gatt_server_server.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <bluetooth_gatt/cpp/fidl.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
 
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
@@ -17,12 +17,14 @@
 namespace bthost {
 
 // Implements the gatt::Server FIDL interface.
-class GattServerServer : public GattServerBase<bluetooth_gatt::Server> {
+class GattServerServer
+    : public GattServerBase<fuchsia::bluetooth::gatt::Server> {
  public:
   // |adapter_manager| is used to lazily request a handle to the corresponding
   // adapter. It MUST out-live this GattServerServer instance.
-  GattServerServer(fbl::RefPtr<btlib::gatt::GATT> gatt,
-                   fidl::InterfaceRequest<bluetooth_gatt::Server> request);
+  GattServerServer(
+      fbl::RefPtr<btlib::gatt::GATT> gatt,
+      fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request);
 
   ~GattServerServer() override;
 
@@ -34,25 +36,27 @@
  private:
   class LocalServiceImpl;
 
-  // ::bluetooth_gatt::Server overrides:
+  // ::fuchsia::bluetooth::gatt::Server overrides:
   void PublishService(
-      bluetooth_gatt::ServiceInfo service_info,
-      fidl::InterfaceHandle<bluetooth_gatt::LocalServiceDelegate> delegate,
-      fidl::InterfaceRequest<bluetooth_gatt::LocalService> service_iface,
+      fuchsia::bluetooth::gatt::ServiceInfo service_info,
+      fidl::InterfaceHandle<fuchsia::bluetooth::gatt::LocalServiceDelegate>
+          delegate,
+      fidl::InterfaceRequest<fuchsia::bluetooth::gatt::LocalService>
+          service_iface,
       PublishServiceCallback callback) override;
 
   // Called when a remote device issues a read request to one of our services.
   void OnReadRequest(::btlib::gatt::IdType service_id,
                      ::btlib::gatt::IdType id,
                      uint16_t offset,
-                     const ::btlib::gatt::ReadResponder& responder);
+                     ::btlib::gatt::ReadResponder responder);
 
   // Called when a remote device issues a write request to one of our services.
   void OnWriteRequest(::btlib::gatt::IdType service_id,
                       ::btlib::gatt::IdType id,
                       uint16_t offset,
                       const ::btlib::common::ByteBuffer& value,
-                      const ::btlib::gatt::WriteResponder& responder);
+                      ::btlib::gatt::WriteResponder responder);
 
   // Called when a remote device has configured notifications or indications on
   // a local characteristic.
diff --git a/drivers/bluetooth/host/fidl/helpers.cc b/drivers/bluetooth/host/fidl/helpers.cc
index 04be9cf..b8c4e52 100644
--- a/drivers/bluetooth/host/fidl/helpers.cc
+++ b/drivers/bluetooth/host/fidl/helpers.cc
@@ -12,69 +12,64 @@
 #include "garnet/drivers/bluetooth/lib/gap/advertising_data.h"
 #include "garnet/drivers/bluetooth/lib/gap/discovery_filter.h"
 
-using bluetooth::Bool;
-using bluetooth::Error;
-using bluetooth::ErrorCode;
-using bluetooth::Int8;
-using bluetooth::Status;
-using bluetooth_control::AdapterInfo;
-using bluetooth_control::AdapterState;
-using bluetooth_control::Appearance;
-using bluetooth_control::TechnologyType;
+using fuchsia::bluetooth::Bool;
+using fuchsia::bluetooth::Error;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Int8;
+using fuchsia::bluetooth::Status;
 
-namespace ble = bluetooth_low_energy;
+namespace ctrl = fuchsia::bluetooth::control;
+namespace ble = fuchsia::bluetooth::le;
 
 namespace bthost {
 namespace fidl_helpers {
 namespace {
 
-::bluetooth_control::TechnologyType TechnologyTypeToFidl(
-    ::btlib::gap::TechnologyType type) {
+ctrl::TechnologyType TechnologyTypeToFidl(::btlib::gap::TechnologyType type) {
   switch (type) {
     case ::btlib::gap::TechnologyType::kLowEnergy:
-      return ::bluetooth_control::TechnologyType::LOW_ENERGY;
+      return ctrl::TechnologyType::LOW_ENERGY;
     case ::btlib::gap::TechnologyType::kClassic:
-      return ::bluetooth_control::TechnologyType::CLASSIC;
+      return ctrl::TechnologyType::CLASSIC;
     case ::btlib::gap::TechnologyType::kDualMode:
-      return ::bluetooth_control::TechnologyType::DUAL_MODE;
+      return ctrl::TechnologyType::DUAL_MODE;
     default:
       FXL_NOTREACHED();
       break;
   }
 
   // This should never execute.
-  return ::bluetooth_control::TechnologyType::DUAL_MODE;
+  return ctrl::TechnologyType::DUAL_MODE;
 }
 
 }  // namespace
 
-::bluetooth::ErrorCode HostErrorToFidl(::btlib::common::HostError host_error) {
+ErrorCode HostErrorToFidl(::btlib::common::HostError host_error) {
   switch (host_error) {
     case ::btlib::common::HostError::kFailed:
-      return ::bluetooth::ErrorCode::FAILED;
+      return ErrorCode::FAILED;
     case ::btlib::common::HostError::kTimedOut:
-      return ::bluetooth::ErrorCode::TIMED_OUT;
+      return ErrorCode::TIMED_OUT;
     case ::btlib::common::HostError::kInvalidParameters:
-      return ::bluetooth::ErrorCode::INVALID_ARGUMENTS;
+      return ErrorCode::INVALID_ARGUMENTS;
     case ::btlib::common::HostError::kCanceled:
-      return ::bluetooth::ErrorCode::CANCELED;
+      return ErrorCode::CANCELED;
     case ::btlib::common::HostError::kInProgress:
-      return ::bluetooth::ErrorCode::IN_PROGRESS;
+      return ErrorCode::IN_PROGRESS;
     case ::btlib::common::HostError::kNotSupported:
-      return ::bluetooth::ErrorCode::NOT_SUPPORTED;
+      return ErrorCode::NOT_SUPPORTED;
     case ::btlib::common::HostError::kNotFound:
-      return ::bluetooth::ErrorCode::NOT_FOUND;
+      return ErrorCode::NOT_FOUND;
     case ::btlib::common::HostError::kProtocolError:
-      return ::bluetooth::ErrorCode::PROTOCOL_ERROR;
+      return ErrorCode::PROTOCOL_ERROR;
     default:
       break;
   }
 
-  return ::bluetooth::ErrorCode::FAILED;
+  return ErrorCode::FAILED;
 }
 
-Status NewFidlError(::bluetooth::ErrorCode error_code,
-                    std::string description) {
+Status NewFidlError(ErrorCode error_code, std::string description) {
   Status status;
   status.error = Error::New();
   status.error->error_code = error_code;
@@ -82,10 +77,9 @@
   return status;
 }
 
-::bluetooth_control::AdapterInfo NewAdapterInfo(
-    const ::btlib::gap::Adapter& adapter) {
-  ::bluetooth_control::AdapterInfo adapter_info;
-  adapter_info.state = ::bluetooth_control::AdapterState::New();
+ctrl::AdapterInfo NewAdapterInfo(const ::btlib::gap::Adapter& adapter) {
+  ctrl::AdapterInfo adapter_info;
+  adapter_info.state = ctrl::AdapterState::New();
 
   adapter_info.state->discoverable = Bool::New();
   adapter_info.state->discoverable->value = false;
@@ -98,9 +92,9 @@
   return adapter_info;
 }
 
-::bluetooth_control::RemoteDevicePtr NewRemoteDevice(
+ctrl::RemoteDevicePtr NewRemoteDevice(
     const ::btlib::gap::RemoteDevice& device) {
-  auto fidl_device = ::bluetooth_control::RemoteDevice::New();
+  auto fidl_device = ctrl::RemoteDevice::New();
   fidl_device->identifier = device.identifier();
   fidl_device->address = device.address().value().ToString();
   fidl_device->technology = TechnologyTypeToFidl(device.technology());
@@ -110,7 +104,7 @@
   fidl_device->bonded = false;
 
   // Set default value for device appearance.
-  fidl_device->appearance = ::bluetooth_control::Appearance::UNKNOWN;
+  fidl_device->appearance = ctrl::Appearance::UNKNOWN;
 
   if (device.rssi() != ::btlib::hci::kRSSIInvalid) {
     fidl_device->rssi = Int8::New();
@@ -139,8 +133,8 @@
   if (adv_data.local_name())
     fidl_device->name = *adv_data.local_name();
   if (adv_data.appearance()) {
-    fidl_device->appearance = static_cast<::bluetooth_control::Appearance>(
-        le16toh(*adv_data.appearance()));
+    fidl_device->appearance =
+        static_cast<ctrl::Appearance>(le16toh(*adv_data.appearance()));
   }
   if (adv_data.tx_power()) {
     auto fidl_tx_power = Int8::New();
diff --git a/drivers/bluetooth/host/fidl/helpers.h b/drivers/bluetooth/host/fidl/helpers.h
index e9493c8..bd0c434 100644
--- a/drivers/bluetooth/host/fidl/helpers.h
+++ b/drivers/bluetooth/host/fidl/helpers.h
@@ -4,10 +4,10 @@
 
 #pragma once
 
-#include <bluetooth/cpp/fidl.h>
-#include <bluetooth_control/cpp/fidl.h>
-#include <bluetooth_gatt/cpp/fidl.h>
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/control/cpp/fidl.h>
+#include <fuchsia/bluetooth/cpp/fidl.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 
 #include "lib/fidl/cpp/vector.h"
 #include "lib/fxl/type_converter.h"
@@ -32,21 +32,22 @@
 
 // Functions for generating a FIDL bluetooth::Status
 
-::bluetooth::ErrorCode HostErrorToFidl(::btlib::common::HostError host_error);
+fuchsia::bluetooth::ErrorCode HostErrorToFidl(
+    ::btlib::common::HostError host_error);
 
-::bluetooth::Status NewFidlError(::bluetooth::ErrorCode error_code,
-                                 std::string description);
+fuchsia::bluetooth::Status NewFidlError(
+    fuchsia::bluetooth::ErrorCode error_code, std::string description);
 
 template <typename ProtocolErrorCode>
-::bluetooth::Status StatusToFidl(
+fuchsia::bluetooth::Status StatusToFidl(
     const ::btlib::common::Status<ProtocolErrorCode>& status,
     std::string msg = "") {
-  ::bluetooth::Status fidl_status;
+  fuchsia::bluetooth::Status fidl_status;
 
   if (status.is_success())
     return fidl_status;
 
-  auto error = ::bluetooth::Error::New();
+  auto error = fuchsia::bluetooth::Error::New();
   error->error_code = HostErrorToFidl(status.error());
   error->description = msg.empty() ? status.ToString() : std::move(msg);
   if (status.is_protocol_error()) {
@@ -59,24 +60,24 @@
 
 // Functions to convert host library objects into FIDL types.
 
-::bluetooth_control::AdapterInfo NewAdapterInfo(
+fuchsia::bluetooth::control::AdapterInfo NewAdapterInfo(
     const ::btlib::gap::Adapter& adapter);
-::bluetooth_control::RemoteDevicePtr NewRemoteDevice(
+fuchsia::bluetooth::control::RemoteDevicePtr NewRemoteDevice(
     const ::btlib::gap::RemoteDevice& device);
 
-::bluetooth_low_energy::AdvertisingDataPtr NewAdvertisingData(
+fuchsia::bluetooth::le::AdvertisingDataPtr NewAdvertisingData(
     const ::btlib::common::ByteBuffer& advertising_data);
-::bluetooth_low_energy::RemoteDevicePtr NewLERemoteDevice(
+fuchsia::bluetooth::le::RemoteDevicePtr NewLERemoteDevice(
     const ::btlib::gap::RemoteDevice& device);
 
 // Validates the contents of a ScanFilter.
-bool IsScanFilterValid(const ::bluetooth_low_energy::ScanFilter& fidl_filter);
+bool IsScanFilterValid(const fuchsia::bluetooth::le::ScanFilter& fidl_filter);
 
 // Populates a library DiscoveryFilter based on a FIDL ScanFilter. Returns false
 // if |fidl_filter| contains any malformed data and leaves |out_filter|
 // unmodified.
 bool PopulateDiscoveryFilter(
-    const ::bluetooth_low_energy::ScanFilter& fidl_filter,
+    const fuchsia::bluetooth::le::ScanFilter& fidl_filter,
     ::btlib::gap::DiscoveryFilter* out_filter);
 
 }  // namespace fidl_helpers
diff --git a/drivers/bluetooth/host/fidl/host_server.cc b/drivers/bluetooth/host/fidl/host_server.cc
index 356955f..26c1aba 100644
--- a/drivers/bluetooth/host/fidl/host_server.cc
+++ b/drivers/bluetooth/host/fidl/host_server.cc
@@ -4,20 +4,32 @@
 
 #include "host_server.h"
 
-#include "garnet/drivers/bluetooth/host/gatt_host.h"
+#include "garnet/drivers/bluetooth/lib/gap/adapter.h"
 
-#include "adapter_server.h"
+#include "garnet/drivers/bluetooth/host/gatt_host.h"
+#include "garnet/drivers/bluetooth/lib/gap/bredr_connection_manager.h"
+#include "garnet/drivers/bluetooth/lib/gap/bredr_discovery_manager.h"
+#include "garnet/drivers/bluetooth/lib/gap/gap.h"
+#include "garnet/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h"
+#include "lib/fxl/logging.h"
+
 #include "helpers.h"
 #include "low_energy_central_server.h"
 #include "low_energy_peripheral_server.h"
 
 namespace bthost {
 
+using fuchsia::bluetooth::Bool;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Status;
+using fuchsia::bluetooth::control::AdapterState;
+
 HostServer::HostServer(zx::channel channel,
                        fxl::WeakPtr<::btlib::gap::Adapter> adapter,
                        fbl::RefPtr<GattHost> gatt_host)
     : AdapterServerBase(adapter, this, std::move(channel)),
-      gatt_host_(gatt_host) {
+      gatt_host_(gatt_host),
+      weak_ptr_factory_(this) {
   FXL_DCHECK(gatt_host_);
 }
 
@@ -25,23 +37,193 @@
   callback(fidl_helpers::NewAdapterInfo(*adapter()));
 }
 
-void HostServer::RequestAdapter(
-    fidl::InterfaceRequest<bluetooth_host::Adapter> request) {
-  BindServer<AdapterServer>(std::move(request));
+void HostServer::SetLocalName(::fidl::StringPtr local_name,
+                              SetLocalNameCallback callback) {
+  adapter()->SetLocalName(local_name, [self = weak_ptr_factory_.GetWeakPtr(),
+                                       callback](auto status) {
+    callback(fidl_helpers::StatusToFidl(status, "Can't Set Local Name"));
+  });
+}
+
+void HostServer::StartDiscovery(StartDiscoveryCallback callback) {
+  FXL_VLOG(1) << "Adapter StartDiscovery()";
+  FXL_DCHECK(adapter());
+
+  if (le_discovery_session_ || requesting_discovery_) {
+    FXL_VLOG(1) << "Discovery already in progress";
+    callback(fidl_helpers::NewFidlError(ErrorCode::IN_PROGRESS,
+                                        "Discovery already in progress"));
+    return;
+  }
+
+  requesting_discovery_ = true;
+  auto bredr_manager = adapter()->bredr_discovery_manager();
+  // TODO(jamuraa): start these in parallel instead of sequence
+  bredr_manager->RequestDiscovery([self = weak_ptr_factory_.GetWeakPtr(),
+                                   bredr_manager, callback](
+                                      btlib::hci::Status status, auto session) {
+    if (!self) {
+      callback(
+          fidl_helpers::NewFidlError(ErrorCode::FAILED, "Adapter Shutdown"));
+      return;
+    }
+
+    if (!status || !session) {
+      FXL_VLOG(1) << "Failed to start BR/EDR discovery session";
+      callback(fidl_helpers::StatusToFidl(
+          status, "Failed to start BR/EDR discovery session"));
+      self->requesting_discovery_ = false;
+      return;
+    }
+
+    session->set_result_callback([self](const auto& device) {
+      if (self) {
+        self->OnDiscoveryResult(device);
+      }
+    });
+
+    self->bredr_discovery_session_ = std::move(session);
+
+    auto le_manager = self->adapter()->le_discovery_manager();
+    le_manager->StartDiscovery([self, callback](auto session) {
+      // End the new session if this AdapterServer got destroyed in the mean
+      // time (e.g. because the client disconnected).
+      if (!self) {
+        callback(
+            fidl_helpers::NewFidlError(ErrorCode::FAILED, "Adapter Shutdown"));
+        return;
+      }
+
+      if (!session) {
+        FXL_VLOG(1) << "Failed to start LE discovery session";
+        callback(fidl_helpers::NewFidlError(
+            ErrorCode::FAILED, "Failed to start LE discovery session"));
+        self->bredr_discovery_session_ = nullptr;
+        self->requesting_discovery_ = false;
+        return;
+      }
+
+      // Set up a general-discovery filter for connectable devices.
+      session->filter()->set_connectable(true);
+      session->filter()->SetGeneralDiscoveryFlags();
+      session->SetResultCallback([self](const auto& device) {
+        if (self) {
+          self->OnDiscoveryResult(device);
+        }
+      });
+
+      self->le_discovery_session_ = std::move(session);
+      self->requesting_discovery_ = false;
+
+      // Send the adapter state update.
+      AdapterState state;
+      state.discovering = Bool::New();
+      state.discovering->value = true;
+      self->binding()->events().OnHostStateChanged(std::move(state));
+
+      callback(Status());
+    });
+  });
+}
+
+void HostServer::StopDiscovery(StopDiscoveryCallback callback) {
+  FXL_VLOG(1) << "Adapter StopDiscovery()";
+  if (!le_discovery_session_) {
+    FXL_VLOG(1) << "No active discovery session";
+    callback(fidl_helpers::NewFidlError(ErrorCode::BAD_STATE,
+                                        "No discovery session in progress"));
+    return;
+  }
+
+  bredr_discovery_session_ = nullptr;
+  le_discovery_session_ = nullptr;
+
+  AdapterState state;
+  state.discovering = Bool::New();
+  state.discovering->value = false;
+  this->binding()->events().OnHostStateChanged(std::move(state));
+
+  callback(Status());
+}
+
+void HostServer::SetConnectable(bool connectable,
+                                SetConnectableCallback callback) {
+  FXL_VLOG(1) << "Adapter SetConnectable(" << connectable << ")";
+
+  adapter()->bredr_connection_manager()->SetConnectable(
+      connectable, [callback](const auto& status) {
+        callback(fidl_helpers::StatusToFidl(status));
+      });
+}
+
+void HostServer::SetDiscoverable(bool discoverable,
+                                 SetDiscoverableCallback callback) {
+  FXL_VLOG(1) << "Adapter SetDiscoverable(" << discoverable << ")";
+  // TODO(NET-830): advertise LE here
+  if (!discoverable) {
+    bredr_discoverable_session_ = nullptr;
+
+    AdapterState state;
+    state.discoverable = Bool::New();
+    state.discoverable->value = false;
+    this->binding()->events().OnHostStateChanged(std::move(state));
+
+    callback(Status());
+  }
+  if (discoverable && requesting_discoverable_) {
+    FXL_VLOG(1) << "Discoverable already being set";
+    callback(fidl_helpers::NewFidlError(ErrorCode::IN_PROGRESS,
+                                        "Discovery already in progress"));
+    return;
+  }
+  requesting_discoverable_ = true;
+  auto bredr_manager = adapter()->bredr_discovery_manager();
+  bredr_manager->RequestDiscoverable(
+      [self = weak_ptr_factory_.GetWeakPtr(), callback](
+          btlib::hci::Status status, auto session) {
+        if (!self) {
+          callback(fidl_helpers::NewFidlError(ErrorCode::FAILED,
+                                              "Adapter Shutdown"));
+          return;
+        }
+        if (!status || !session) {
+          FXL_VLOG(1) << "Failed to set discoverable!";
+          callback(
+              fidl_helpers::StatusToFidl(status, "Failed to set discoverable"));
+          self->requesting_discoverable_ = false;
+        }
+        self->bredr_discoverable_session_ = std::move(session);
+        AdapterState state;
+        state.discoverable = Bool::New();
+        state.discoverable->value = true;
+        self->binding()->events().OnHostStateChanged(std::move(state));
+        callback(Status());
+      });
+}
+
+void HostServer::OnDiscoveryResult(
+    const ::btlib::gap::RemoteDevice& remote_device) {
+  auto fidl_device = fidl_helpers::NewRemoteDevice(remote_device);
+  if (!fidl_device) {
+    FXL_VLOG(1) << "Ignoring malformed discovery result";
+    return;
+  }
+
+  this->binding()->events().OnDeviceDiscovered(std::move(*fidl_device));
 }
 
 void HostServer::RequestLowEnergyCentral(
-    fidl::InterfaceRequest<bluetooth_low_energy::Central> request) {
+    fidl::InterfaceRequest<fuchsia::bluetooth::le::Central> request) {
   BindServer<LowEnergyCentralServer>(std::move(request), gatt_host_);
 }
 
 void HostServer::RequestLowEnergyPeripheral(
-    fidl::InterfaceRequest<bluetooth_low_energy::Peripheral> request) {
+    fidl::InterfaceRequest<fuchsia::bluetooth::le::Peripheral> request) {
   BindServer<LowEnergyPeripheralServer>(std::move(request));
 }
 
 void HostServer::RequestGattServer(
-    fidl::InterfaceRequest<bluetooth_gatt::Server> request) {
+    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request) {
   // GATT FIDL requests are handled by GattHost.
   gatt_host_->BindGattServer(std::move(request));
 }
diff --git a/drivers/bluetooth/host/fidl/host_server.h b/drivers/bluetooth/host/fidl/host_server.h
index eeaa9fa..8b402d7 100644
--- a/drivers/bluetooth/host/fidl/host_server.h
+++ b/drivers/bluetooth/host/fidl/host_server.h
@@ -7,15 +7,20 @@
 #include <memory>
 #include <unordered_map>
 
+#include <fuchsia/bluetooth/control/cpp/fidl.h>
+#include <fuchsia/bluetooth/host/cpp/fidl.h>
 #include <lib/zx/channel.h>
 
 #include "lib/fidl/cpp/binding.h"
+#include "lib/fidl/cpp/interface_request.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/weak_ptr.h"
 
 #include "garnet/drivers/bluetooth/host/fidl/server_base.h"
 #include "garnet/drivers/bluetooth/lib/gap/adapter.h"
-#include <bluetooth_host/cpp/fidl.h>
+#include "garnet/drivers/bluetooth/lib/gap/bredr_connection_manager.h"
+#include "garnet/drivers/bluetooth/lib/gap/bredr_discovery_manager.h"
+#include "garnet/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h"
 
 namespace bthost {
 
@@ -23,26 +28,37 @@
 
 // Implements the Host FIDL interface. Owns all FIDL connections that have been
 // opened through it.
-class HostServer : public AdapterServerBase<::bluetooth_host::Host> {
+class HostServer : public AdapterServerBase<fuchsia::bluetooth::host::Host> {
  public:
-  HostServer(zx::channel channel,
-             fxl::WeakPtr<btlib::gap::Adapter> adapter,
+  HostServer(zx::channel channel, fxl::WeakPtr<btlib::gap::Adapter> adapter,
              fbl::RefPtr<GattHost> gatt_host);
   ~HostServer() override = default;
 
  private:
-  // ::bluetooth_host::Host overrides:
+  // ::fuchsia::bluetooth::Host overrides:
   void GetInfo(GetInfoCallback callback) override;
-  void RequestAdapter(
-      ::fidl::InterfaceRequest<bluetooth_host::Adapter> adapter) override;
+  void SetLocalName(::fidl::StringPtr local_name,
+                    SetLocalNameCallback callback) override;
+
+  void StartDiscovery(StartDiscoveryCallback callback) override;
+  void StopDiscovery(StopDiscoveryCallback callback) override;
+  void SetConnectable(bool connectable,
+                      SetConnectableCallback callback) override;
+  void SetDiscoverable(bool discoverable,
+                       SetDiscoverableCallback callback) override;
+
+  // Called by |le_discovery_session_| when devices are discovered.
+  void OnDiscoveryResult(const ::btlib::gap::RemoteDevice& remote_device);
+
   void RequestLowEnergyCentral(
-      ::fidl::InterfaceRequest<bluetooth_low_energy::Central> central)
+      ::fidl::InterfaceRequest<fuchsia::bluetooth::le::Central> central)
       override;
   void RequestLowEnergyPeripheral(
-      ::fidl::InterfaceRequest<bluetooth_low_energy::Peripheral> peripheral)
+      ::fidl::InterfaceRequest<fuchsia::bluetooth::le::Peripheral> peripheral)
       override;
   void RequestGattServer(
-      ::fidl::InterfaceRequest<bluetooth_gatt::Server> server) override;
+      ::fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> server)
+      override;
   void Close() override;
 
   // Called when |server| receives a channel connection error.
@@ -62,12 +78,25 @@
   // We hold a reference to GattHost for dispatching GATT FIDL requests.
   fbl::RefPtr<GattHost> gatt_host_;
 
+  bool requesting_discovery_;
+  std::unique_ptr<::btlib::gap::LowEnergyDiscoverySession>
+      le_discovery_session_;
+  std::unique_ptr<::btlib::gap::BrEdrDiscoverySession> bredr_discovery_session_;
+
+  bool requesting_discoverable_;
+  std::unique_ptr<::btlib::gap::BrEdrDiscoverableSession>
+      bredr_discoverable_session_;
+
   // All active FIDL interface servers.
   // NOTE: Each key is a raw pointer that is owned by the corresponding value.
   // This allows us to create a set of managed objects that can be looked up via
   // raw pointer.
   std::unordered_map<Server*, std::unique_ptr<Server>> servers_;
 
+  // Keep this as the last member to make sure that all weak pointers are
+  // invalidated before other members get destroyed.
+  fxl::WeakPtrFactory<HostServer> weak_ptr_factory_;
+
   FXL_DISALLOW_COPY_AND_ASSIGN(HostServer);
 };
 
diff --git a/drivers/bluetooth/host/fidl/low_energy_central_server.cc b/drivers/bluetooth/host/fidl/low_energy_central_server.cc
index 080e28f..3bca5e7 100644
--- a/drivers/bluetooth/host/fidl/low_energy_central_server.cc
+++ b/drivers/bluetooth/host/fidl/low_energy_central_server.cc
@@ -9,14 +9,14 @@
 
 #include "helpers.h"
 
-using bluetooth::ErrorCode;
-using bluetooth::Int8;
-using bluetooth::Status;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Int8;
+using fuchsia::bluetooth::Status;
 
-using bluetooth_gatt::Client;
-using bluetooth_low_energy::CentralDelegate;
-using bluetooth_low_energy::CentralDelegatePtr;
-using bluetooth_low_energy::ScanFilterPtr;
+using fuchsia::bluetooth::gatt::Client;
+using fuchsia::bluetooth::le::CentralDelegate;
+using fuchsia::bluetooth::le::CentralDelegatePtr;
+using fuchsia::bluetooth::le::ScanFilterPtr;
 
 namespace bthost {
 
@@ -58,7 +58,7 @@
 
 void LowEnergyCentralServer::GetPeripheral(
     ::fidl::StringPtr identifier,
-     GetPeripheralCallback callback) {
+    GetPeripheralCallback callback) {
   // TODO:
   FXL_NOTIMPLEMENTED();
 }
@@ -141,7 +141,7 @@
 
 void LowEnergyCentralServer::ConnectPeripheral(
     ::fidl::StringPtr identifier,
-    ::fidl::InterfaceRequest<bluetooth_gatt::Client> client_request,
+    ::fidl::InterfaceRequest<Client> client_request,
     ConnectPeripheralCallback callback) {
   FXL_VLOG(1) << "Low Energy Central ConnectPeripheral()";
 
diff --git a/drivers/bluetooth/host/fidl/low_energy_central_server.h b/drivers/bluetooth/host/fidl/low_energy_central_server.h
index 8560948..034706a 100644
--- a/drivers/bluetooth/host/fidl/low_energy_central_server.h
+++ b/drivers/bluetooth/host/fidl/low_energy_central_server.h
@@ -7,7 +7,7 @@
 #include <memory>
 #include <unordered_map>
 
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
 
@@ -20,29 +20,29 @@
 
 // Implements the low_energy::Central FIDL interface.
 class LowEnergyCentralServer
-    : public AdapterServerBase<bluetooth_low_energy::Central> {
+    : public AdapterServerBase<fuchsia::bluetooth::le::Central> {
  public:
   LowEnergyCentralServer(
       fxl::WeakPtr<::btlib::gap::Adapter> adapter,
-      ::fidl::InterfaceRequest<::bluetooth_low_energy::Central> request,
+      ::fidl::InterfaceRequest<fuchsia::bluetooth::le::Central> request,
       fbl::RefPtr<GattHost> gatt_host);
   ~LowEnergyCentralServer() override;
 
  private:
-  // ::bluetooth_low_energy::Central overrides:
+  // fuchsia::bluetooth::le::Central overrides:
   void SetDelegate(
-      ::fidl::InterfaceHandle<::bluetooth_low_energy::CentralDelegate>
-          delegate) override;
+      ::fidl::InterfaceHandle<fuchsia::bluetooth::le::CentralDelegate> delegate)
+      override;
   void GetPeripherals(::fidl::VectorPtr<::fidl::StringPtr> service_uuids,
                       GetPeripheralsCallback callback) override;
   void GetPeripheral(::fidl::StringPtr identifier,
                      GetPeripheralCallback callback) override;
-  void StartScan(::bluetooth_low_energy::ScanFilterPtr filter,
+  void StartScan(fuchsia::bluetooth::le::ScanFilterPtr filter,
                  StartScanCallback callback) override;
   void StopScan() override;
   void ConnectPeripheral(
       ::fidl::StringPtr identifier,
-      ::fidl::InterfaceRequest<bluetooth_gatt::Client> client_request,
+      ::fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Client> client_request,
       ConnectPeripheralCallback callback) override;
   void DisconnectPeripheral(
       ::fidl::StringPtr identifier,
@@ -75,7 +75,7 @@
       connections_;
 
   // The delegate that is set via SetDelegate()
-  ::bluetooth_low_energy::CentralDelegatePtr delegate_;
+  fuchsia::bluetooth::le::CentralDelegatePtr delegate_;
 
   // Keep this as the last member to make sure that all weak pointers are
   // invalidated before other members get destroyed.
diff --git a/drivers/bluetooth/host/fidl/low_energy_peripheral_server.cc b/drivers/bluetooth/host/fidl/low_energy_peripheral_server.cc
index 1280bc3..bc3e882 100644
--- a/drivers/bluetooth/host/fidl/low_energy_peripheral_server.cc
+++ b/drivers/bluetooth/host/fidl/low_energy_peripheral_server.cc
@@ -12,15 +12,16 @@
 
 #include "helpers.h"
 
-using bluetooth::ErrorCode;
-using bluetooth::Status;
+using fuchsia::bluetooth::ErrorCode;
+using fuchsia::bluetooth::Status;
 
-using bluetooth_low_energy::AdvertisingData;
-using bluetooth_low_energy::AdvertisingDataPtr;
-using bluetooth_low_energy::Peripheral;
-using bluetooth_low_energy::PeripheralDelegate;
-using bluetooth_low_energy::PeripheralDelegatePtr;
-using bluetooth_low_energy::RemoteDevicePtr;
+using fuchsia::bluetooth::le::AdvertisingData;
+using fuchsia::bluetooth::le::AdvertisingDataPtr;
+using fuchsia::bluetooth::le::Peripheral;
+using fuchsia::bluetooth::le::PeripheralDelegate;
+using fuchsia::bluetooth::le::PeripheralDelegatePtr;
+using fuchsia::bluetooth::le::RemoteDevice;
+using fuchsia::bluetooth::le::RemoteDevicePtr;
 
 namespace bthost {
 
@@ -46,8 +47,7 @@
     : id_(id), delegate_(std::move(delegate)) {}
 
 void LowEnergyPeripheralServer::InstanceData::RetainConnection(
-    ConnectionRefPtr conn_ref,
-    bluetooth_low_energy::RemoteDevice peer) {
+    ConnectionRefPtr conn_ref, RemoteDevice peer) {
   FXL_DCHECK(connectable());
   FXL_DCHECK(!conn_ref_);
 
@@ -137,7 +137,7 @@
     callback(Status(), ad_id);
   };
 
-  advertising_manager->StartAdvertising(ad_data, scan_data, connect_cb,
+  advertising_manager->StartAdvertising(ad_data, scan_data, std::move(connect_cb),
                                         interval, anonymous,
                                         std::move(advertising_status_cb));
 }
@@ -205,7 +205,7 @@
   FXL_DCHECK(device);
 
   FXL_VLOG(1) << "Central connected";
-  ::bluetooth_low_energy::RemoteDevicePtr remote_device =
+  RemoteDevicePtr remote_device =
       fidl_helpers::NewLERemoteDevice(std::move(*device));
   FXL_DCHECK(remote_device);
   it->second.RetainConnection(std::move(conn), std::move(*remote_device));
diff --git a/drivers/bluetooth/host/fidl/low_energy_peripheral_server.h b/drivers/bluetooth/host/fidl/low_energy_peripheral_server.h
index 57dc26d..ba15f97 100644
--- a/drivers/bluetooth/host/fidl/low_energy_peripheral_server.h
+++ b/drivers/bluetooth/host/fidl/low_energy_peripheral_server.h
@@ -7,7 +7,7 @@
 #include <memory>
 #include <unordered_map>
 
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/weak_ptr.h"
@@ -20,15 +20,15 @@
 
 // Implements the low_energy::Central FIDL interface.
 class LowEnergyPeripheralServer
-    : public AdapterServerBase<bluetooth_low_energy::Peripheral> {
+    : public AdapterServerBase<fuchsia::bluetooth::le::Peripheral> {
  public:
   LowEnergyPeripheralServer(
       fxl::WeakPtr<::btlib::gap::Adapter> adapter,
-      fidl::InterfaceRequest<bluetooth_low_energy::Peripheral> request);
+      fidl::InterfaceRequest<fuchsia::bluetooth::le::Peripheral> request);
   ~LowEnergyPeripheralServer() override;
 
  private:
-  using DelegatePtr = bluetooth_low_energy::PeripheralDelegatePtr;
+  using DelegatePtr = fuchsia::bluetooth::le::PeripheralDelegatePtr;
   using ConnectionRefPtr = ::btlib::gap::LowEnergyConnectionRefPtr;
 
   class InstanceData final {
@@ -44,7 +44,7 @@
     // Takes ownership of |conn_ref| and notifies the delegate of the new
     // connection.
     void RetainConnection(ConnectionRefPtr conn_ref,
-                          bluetooth_low_energy::RemoteDevice central);
+                          fuchsia::bluetooth::le::RemoteDevice central);
 
     // Deletes the connetion reference and notifies the delegate of
     // disconnection.
@@ -58,14 +58,13 @@
     FXL_DISALLOW_COPY_AND_ASSIGN(InstanceData);
   };
 
-  // bluetooth_low_energy::Peripheral overrides:
+  // fuchsia::bluetooth::le::Peripheral overrides:
   void StartAdvertising(
-      bluetooth_low_energy::AdvertisingData advertising_data,
-      bluetooth_low_energy::AdvertisingDataPtr scan_result,
-      ::fidl::InterfaceHandle<bluetooth_low_energy::PeripheralDelegate>
+      fuchsia::bluetooth::le::AdvertisingData advertising_data,
+      fuchsia::bluetooth::le::AdvertisingDataPtr scan_result,
+      ::fidl::InterfaceHandle<fuchsia::bluetooth::le::PeripheralDelegate>
           delegate,
-      uint32_t interval,
-      bool anonymous,
+      uint32_t interval, bool anonymous,
       StartAdvertisingCallback callback) override;
 
   void StopAdvertising(::fidl::StringPtr advertisement_id,
diff --git a/drivers/bluetooth/host/fidl/server_base.h b/drivers/bluetooth/host/fidl/server_base.h
index 4dc1b42..9d2bc3d 100644
--- a/drivers/bluetooth/host/fidl/server_base.h
+++ b/drivers/bluetooth/host/fidl/server_base.h
@@ -4,9 +4,8 @@
 
 #pragma once
 
-#include <functional>
-
 #include <fbl/ref_ptr.h>
+#include <lib/fit/function.h>
 
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
@@ -33,7 +32,7 @@
  public:
   virtual ~Server() = default;
 
-  virtual void set_error_handler(std::function<void()> handler) = 0;
+  virtual void set_error_handler(fit::closure handler) = 0;
 };
 
 // ServerBase is a common base implementation for FIDL interface servers.
@@ -52,7 +51,7 @@
 
   ~ServerBase() override = default;
 
-  void set_error_handler(std::function<void()> handler) override {
+  void set_error_handler(fit::closure handler) override {
     binding_.set_error_handler(std::move(handler));
   }
 
diff --git a/drivers/bluetooth/host/gatt_host.cc b/drivers/bluetooth/host/gatt_host.cc
index 22a69f6..0020e6e 100644
--- a/drivers/bluetooth/host/gatt_host.cc
+++ b/drivers/bluetooth/host/gatt_host.cc
@@ -63,7 +63,7 @@
 }
 
 void GattHost::BindGattServer(
-    fidl::InterfaceRequest<bluetooth_gatt::Server> request) {
+    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request) {
   PostMessage([this, request = std::move(request)]() mutable {
     auto self = weak_ptr_factory_.GetWeakPtr();
     auto server = std::make_unique<GattServerServer>(gatt_, std::move(request));
@@ -79,7 +79,7 @@
 
 void GattHost::BindGattClient(
     Token token, std::string peer_id,
-    fidl::InterfaceRequest<bluetooth_gatt::Client> request) {
+    fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Client> request) {
   PostMessage([this, token, peer_id = std::move(peer_id),
                request = std::move(request)]() mutable {
     if (client_servers_.find(token) != client_servers_.end()) {
diff --git a/drivers/bluetooth/host/gatt_host.h b/drivers/bluetooth/host/gatt_host.h
index fb83394..eec929f 100644
--- a/drivers/bluetooth/host/gatt_host.h
+++ b/drivers/bluetooth/host/gatt_host.h
@@ -6,10 +6,10 @@
 
 #include <fbl/ref_counted.h>
 #include <fbl/ref_ptr.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
 
 #include "garnet/drivers/bluetooth/lib/common/task_domain.h"
 #include "garnet/drivers/bluetooth/lib/gatt/gatt.h"
-#include <bluetooth_gatt/cpp/fidl.h>
 
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/macros.h"
@@ -55,7 +55,8 @@
   void CloseServers();
 
   // Binds the given GATT server request to a FIDL server.
-  void BindGattServer(fidl::InterfaceRequest<bluetooth_gatt::Server> request);
+  void BindGattServer(
+      fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request);
 
   // Binds the given GATT client request to a FIDL server. The binding will be
   // associated with the given |token|. The same token can be
@@ -63,8 +64,9 @@
   //
   // The handle associated with |request| will be closed if |token| is already
   // bound to another handle.
-  void BindGattClient(Token token, std::string peer_id,
-                      fidl::InterfaceRequest<bluetooth_gatt::Client> request);
+  void BindGattClient(
+      Token token, std::string peer_id,
+      fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Client> request);
 
   // Unbinds a previously bound GATT client server associated with |token|.
   void UnbindGattClient(Token token);
diff --git a/drivers/bluetooth/host/host.cc b/drivers/bluetooth/host/host.cc
index d25783e..4672e3d 100644
--- a/drivers/bluetooth/host/host.cc
+++ b/drivers/bluetooth/host/host.cc
@@ -61,7 +61,7 @@
   };
 
   FXL_VLOG(1) << "bt-host: initializing GAP";
-  return gap_->Initialize(gap_init_callback, [] {
+  return gap_->Initialize(std::move(gap_init_callback), [] {
     FXL_VLOG(1) << "bt-host: HCI transport has closed";
   });
 }
diff --git a/drivers/bluetooth/host/host.h b/drivers/bluetooth/host/host.h
index 3cfd67c..483af79 100644
--- a/drivers/bluetooth/host/host.h
+++ b/drivers/bluetooth/host/host.h
@@ -4,10 +4,10 @@
 
 #pragma once
 
-#include <functional>
 #include <memory>
 
 #include <ddk/protocol/bt-hci.h>
+#include <lib/fit/function.h>
 #include <zircon/types.h>
 
 #include "garnet/drivers/bluetooth/host/gatt_host.h"
@@ -48,7 +48,7 @@
 class Host final : public fxl::RefCountedThreadSafe<Host> {
  public:
   // Initializes the system and reports the status in |success|.
-  using InitCallback = std::function<void(bool success)>;
+  using InitCallback = fit::function<void(bool success)>;
   bool Initialize(InitCallback callback);
 
   // Shuts down all systems.
diff --git a/drivers/bluetooth/lib/BUILD.gn b/drivers/bluetooth/lib/BUILD.gn
index b09da42..3ee1ab0 100644
--- a/drivers/bluetooth/lib/BUILD.gn
+++ b/drivers/bluetooth/lib/BUILD.gn
@@ -22,5 +22,6 @@
     "//garnet/drivers/bluetooth/lib/gatt:tests",
     "//garnet/drivers/bluetooth/lib/hci:tests",
     "//garnet/drivers/bluetooth/lib/l2cap:tests",
+    "//garnet/drivers/bluetooth/lib/sm:tests",
   ]
 }
diff --git a/drivers/bluetooth/lib/att/BUILD.gn b/drivers/bluetooth/lib/att/BUILD.gn
index c8befaf..1566b67 100644
--- a/drivers/bluetooth/lib/att/BUILD.gn
+++ b/drivers/bluetooth/lib/att/BUILD.gn
@@ -32,6 +32,7 @@
     ":definitions",
     "//garnet/drivers/bluetooth/lib/l2cap",
     "//garnet/public/lib/fxl",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/drivers/bluetooth/lib/att/attribute.cc b/drivers/bluetooth/lib/att/attribute.cc
index 389e7f2..053a4f1 100644
--- a/drivers/bluetooth/lib/att/attribute.cc
+++ b/drivers/bluetooth/lib/att/attribute.cc
@@ -49,28 +49,28 @@
 
 bool Attribute::ReadAsync(const std::string& peer_id,
                           uint16_t offset,
-                          const ReadResultCallback& result_callback) const {
+                          ReadResultCallback result_callback) const {
   if (!is_initialized() || !read_handler_)
     return false;
 
   if (!read_reqs_.allowed())
     return false;
 
-  read_handler_(peer_id, handle_, offset, result_callback);
+  read_handler_(peer_id, handle_, offset, std::move(result_callback));
   return true;
 }
 
 bool Attribute::WriteAsync(const std::string& peer_id,
                            uint16_t offset,
                            const common::ByteBuffer& value,
-                           const WriteResultCallback& result_callback) const {
+                           WriteResultCallback result_callback) const {
   if (!is_initialized() || !write_handler_)
     return false;
 
   if (!write_reqs_.allowed())
     return false;
 
-  write_handler_(peer_id, handle_, offset, std::move(value), result_callback);
+  write_handler_(peer_id, handle_, offset, std::move(value), std::move(result_callback));
   return true;
 }
 
diff --git a/drivers/bluetooth/lib/att/attribute.h b/drivers/bluetooth/lib/att/attribute.h
index 3141278..c5b8374 100644
--- a/drivers/bluetooth/lib/att/attribute.h
+++ b/drivers/bluetooth/lib/att/attribute.h
@@ -7,6 +7,8 @@
 #include <memory>
 #include <vector>
 
+#include <lib/fit/function.h>
+
 #include "garnet/drivers/bluetooth/lib/att/att.h"
 #include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
 #include "garnet/drivers/bluetooth/lib/common/uuid.h"
@@ -110,41 +112,41 @@
   // handler must call the provided the |result_callback| to signal the end of
   // the operation.
   using ReadResultCallback =
-      std::function<void(ErrorCode status, const common::ByteBuffer& value)>;
+      fit::function<void(ErrorCode status, const common::ByteBuffer& value)>;
   using ReadHandler =
-      std::function<void(const std::string& peer_id,
+      fit::function<void(const std::string& peer_id,
                          Handle handle,
                          uint16_t offset,
-                         const ReadResultCallback& result_callback)>;
-  void set_read_handler(const ReadHandler& read_handler) {
-    read_handler_ = read_handler;
+                         ReadResultCallback result_callback)>;
+  void set_read_handler(ReadHandler read_handler) {
+    read_handler_ = std::move(read_handler);
   }
 
   // An "ATT Write Command" will trigger WriteHandler with
   // a null |result_callback|
-  using WriteResultCallback = std::function<void(ErrorCode status)>;
+  using WriteResultCallback = fit::function<void(ErrorCode status)>;
   using WriteHandler =
-      std::function<void(const std::string& peer_id,
+      fit::function<void(const std::string& peer_id,
                          Handle handle,
                          uint16_t offset,
                          const common::ByteBuffer& value,
-                         const WriteResultCallback& result_callback)>;
-  void set_write_handler(const WriteHandler& write_handler) {
-    write_handler_ = write_handler;
+                         WriteResultCallback result_callback)>;
+  void set_write_handler(WriteHandler write_handler) {
+    write_handler_ = std::move(write_handler);
   }
 
   // Initiates an asynchronous read of the attribute value. Returns false if
   // this attribute is not dynamic.
   bool ReadAsync(const std::string& peer_id,
                  uint16_t offset,
-                 const ReadResultCallback& result_callback) const;
+                 ReadResultCallback result_callback) const;
 
   // Initiates an asynchronous write of the attribute value. Returns false if
   // this attribute is not dynamic.
   bool WriteAsync(const std::string& peer_id,
                   uint16_t offset,
                   const common::ByteBuffer& value,
-                  const WriteResultCallback& result_callback) const;
+                  WriteResultCallback result_callback) const;
 
  private:
   // Only an AttributeGrouping can construct this.
diff --git a/drivers/bluetooth/lib/att/bearer.cc b/drivers/bluetooth/lib/att/bearer.cc
index 59dab3c..ea0f85c 100644
--- a/drivers/bluetooth/lib/att/bearer.cc
+++ b/drivers/bluetooth/lib/att/bearer.cc
@@ -128,8 +128,8 @@
                                                ErrorCallback error_callback,
                                                common::ByteBufferPtr pdu)
     : opcode(opcode),
-      callback(callback),
-      error_callback(error_callback),
+      callback(std::move(callback)),
+      error_callback(std::move(error_callback)),
       pdu(std::move(pdu)) {
   FXL_DCHECK(this->callback);
   FXL_DCHECK(this->error_callback);
@@ -270,13 +270,13 @@
 }
 
 bool Bearer::StartTransaction(common::ByteBufferPtr pdu,
-                              const TransactionCallback& callback,
-                              const ErrorCallback& error_callback) {
+                              TransactionCallback callback,
+                              ErrorCallback error_callback) {
   FXL_DCHECK(pdu);
   FXL_DCHECK(callback);
   FXL_DCHECK(error_callback);
 
-  return SendInternal(std::move(pdu), callback, error_callback);
+  return SendInternal(std::move(pdu), std::move(callback), std::move(error_callback));
 }
 
 bool Bearer::SendWithoutResponse(common::ByteBufferPtr pdu) {
@@ -285,8 +285,8 @@
 }
 
 bool Bearer::SendInternal(common::ByteBufferPtr pdu,
-                          const TransactionCallback& callback,
-                          const ErrorCallback& error_callback) {
+                          TransactionCallback callback,
+                          ErrorCallback error_callback) {
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   if (!is_open()) {
     FXL_VLOG(2) << "att: Bearer closed";
@@ -332,14 +332,14 @@
   }
 
   tq->Enqueue(std::make_unique<PendingTransaction>(
-      reader.opcode(), callback, error_callback, std::move(pdu)));
+      reader.opcode(), std::move(callback), std::move(error_callback), std::move(pdu)));
   TryStartNextTransaction(tq);
 
   return true;
 }
 
 Bearer::HandlerId Bearer::RegisterHandler(OpCode opcode,
-                                          const Handler& handler) {
+                                          Handler handler) {
   FXL_DCHECK(handler);
 
   if (!is_open())
@@ -358,7 +358,7 @@
   auto res = handler_id_map_.emplace(id, opcode);
   FXL_CHECK(res.second) << "att: Handler ID got reused (id: " << id << ")";
 
-  handlers_[opcode] = handler;
+  handlers_[opcode] = std::move(handler);
 
   return id;
 }
diff --git a/drivers/bluetooth/lib/att/bearer.h b/drivers/bluetooth/lib/att/bearer.h
index 465ec28..5eed73b 100644
--- a/drivers/bluetooth/lib/att/bearer.h
+++ b/drivers/bluetooth/lib/att/bearer.h
@@ -9,6 +9,7 @@
 #include <unordered_map>
 
 #include <lib/async/cpp/task.h>
+#include <lib/fit/function.h>
 
 #include "garnet/drivers/bluetooth/lib/att/att.h"
 #include "garnet/drivers/bluetooth/lib/att/packet.h"
@@ -22,7 +23,6 @@
 #include "garnet/drivers/bluetooth/lib/l2cap/sdu.h"
 
 #include "lib/fxl/functional/cancelable_callback.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_counted.h"
@@ -80,9 +80,9 @@
 
   // Sets a callback to be invoked invoked when the underlying channel has
   // closed. |callback| should disconnect the underlying logical link.
-  void set_closed_callback(const fxl::Closure& callback) {
+  void set_closed_callback(fit::closure callback) {
     FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
-    closed_cb_ = callback;
+    closed_cb_ = std::move(callback);
   }
 
   // Closes the channel. This should be called when a protocol transaction
@@ -110,11 +110,11 @@
   //
   // Returns false if |pdu| is empty, exceeds the current MTU, or does not
   // correspond to a request or indication.
-  using TransactionCallback = std::function<void(const PacketReader& packet)>;
-  using ErrorCallback = std::function<void(Status, Handle attr_in_error)>;
+  using TransactionCallback = fit::function<void(const PacketReader& packet)>;
+  using ErrorCallback = fit::function<void(Status, Handle attr_in_error)>;
   bool StartTransaction(common::ByteBufferPtr pdu,
-                        const TransactionCallback& callback,
-                        const ErrorCallback& error_callback);
+                        TransactionCallback callback,
+                        ErrorCallback error_callback);
 
   // Sends |pdu| without initiating a transaction. Used for command and
   // notification PDUs which do not have flow control.
@@ -136,13 +136,13 @@
   using TransactionId = size_t;
   static constexpr TransactionId kInvalidTransactionId = 0u;
   using Handler =
-      std::function<void(TransactionId tid, const PacketReader& packet)>;
+      fit::function<void(TransactionId tid, const PacketReader& packet)>;
 
   // Handler: called when |pdu| does not need flow control. This will be
   // called for commands and notifications.
   using HandlerId = size_t;
   static constexpr HandlerId kInvalidHandlerId = 0u;
-  HandlerId RegisterHandler(OpCode opcode, const Handler& handler);
+  HandlerId RegisterHandler(OpCode opcode, Handler handler);
 
   // Unregisters a handler. |id| cannot be zero.
   void UnregisterHandler(HandlerId id);
@@ -231,8 +231,8 @@
   };
 
   bool SendInternal(common::ByteBufferPtr pdu,
-                    const TransactionCallback& callback,
-                    const ErrorCallback& error_callback);
+                    TransactionCallback callback,
+                    ErrorCallback error_callback);
 
   // Shuts down the link.
   void ShutDownInternal(bool due_to_timeout);
@@ -288,7 +288,7 @@
   fxl::CancelableClosure chan_closed_cb_;
 
   // Channel closed callback assigned to us via set_closed_callback().
-  fxl::Closure closed_cb_;
+  fit::closure closed_cb_;
 
   // The state of outgoing ATT requests and indications
   TransactionQueue request_queue_;
diff --git a/drivers/bluetooth/lib/att/status.h b/drivers/bluetooth/lib/att/status.h
index 34588a1..12f06f7 100644
--- a/drivers/bluetooth/lib/att/status.h
+++ b/drivers/bluetooth/lib/att/status.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <lib/fit/function.h>
+
 #include "garnet/drivers/bluetooth/lib/att/att.h"
 #include "garnet/drivers/bluetooth/lib/common/status.h"
 
@@ -22,7 +24,7 @@
 using Status = common::Status<ErrorCode>;
 
 // Copyable callback for reporting a Status.
-using StatusCallback = std::function<void(att::Status)>;
+using StatusCallback = fit::function<void(att::Status)>;
 
 }  // namespace att
 }  // namespace btlib
diff --git a/drivers/bluetooth/lib/common/run_task_sync.cc b/drivers/bluetooth/lib/common/run_task_sync.cc
index a136642..ccc97cb 100644
--- a/drivers/bluetooth/lib/common/run_task_sync.cc
+++ b/drivers/bluetooth/lib/common/run_task_sync.cc
@@ -15,7 +15,7 @@
 namespace btlib {
 namespace common {
 
-void RunTaskSync(const fxl::Closure& callback, async_t* dispatcher) {
+void RunTaskSync(fit::closure callback, async_t* dispatcher) {
   FXL_DCHECK(callback);
 
   // TODO(armansito) This check is risky. async_get_default() could return
@@ -30,7 +30,7 @@
   std::condition_variable cv;
   bool done = false;
 
-  async::PostTask(dispatcher, [callback, &mtx, &cv, &done] {
+  async::PostTask(dispatcher, [callback = std::move(callback), &mtx, &cv, &done] {
     callback();
 
     {
diff --git a/drivers/bluetooth/lib/common/run_task_sync.h b/drivers/bluetooth/lib/common/run_task_sync.h
index 8f7dce4..2c59e32 100644
--- a/drivers/bluetooth/lib/common/run_task_sync.h
+++ b/drivers/bluetooth/lib/common/run_task_sync.h
@@ -5,8 +5,7 @@
 #pragma once
 
 #include <lib/async/dispatcher.h>
-
-#include "lib/fxl/functional/closure.h"
+#include <lib/fit/function.h>
 
 namespace btlib {
 namespace common {
@@ -18,7 +17,7 @@
 //
 // NOTE: This should generally be avoided. This is primarily intended for
 // synchronous setup/shutdown sequences and unit tests.
-void RunTaskSync(const fxl::Closure& callback, async_t* dispatcher);
+void RunTaskSync(fit::closure callback, async_t* dispatcher);
 
 }  // namespace common
 }  // namespace btlib
diff --git a/drivers/bluetooth/lib/gap/adapter.cc b/drivers/bluetooth/lib/gap/adapter.cc
index 815b312..12bf48f 100644
--- a/drivers/bluetooth/lib/gap/adapter.cc
+++ b/drivers/bluetooth/lib/gap/adapter.cc
@@ -59,8 +59,8 @@
     ShutDown();
 }
 
-bool Adapter::Initialize(const InitializeCallback& callback,
-                         const fxl::Closure& transport_closed_cb) {
+bool Adapter::Initialize(InitializeCallback callback,
+                         fit::closure transport_closed_cb) {
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   FXL_DCHECK(callback);
   FXL_DCHECK(transport_closed_cb);
@@ -77,7 +77,7 @@
   FXL_DCHECK(init_seq_runner_->IsReady());
   FXL_DCHECK(!init_seq_runner_->HasQueuedCommands());
 
-  transport_closed_cb_ = transport_closed_cb;
+  transport_closed_cb_ = std::move(transport_closed_cb);
 
   // Start by resetting the controller to a clean state and then send
   // informational parameter commands that are not specific to LE or BR/EDR. The
@@ -128,7 +128,7 @@
         state_.controller_address_ = params->bd_addr;
       });
 
-  init_seq_runner_->RunCommands([callback, this](hci::Status status) {
+  init_seq_runner_->RunCommands([callback = std::move(callback), this](hci::Status status) mutable {
     if (!status) {
       FXL_LOG(ERROR)
           << "gap: Adapter: Failed to obtain initial controller information: "
@@ -138,7 +138,7 @@
       return;
     }
 
-    InitializeStep2(callback);
+    InitializeStep2(std::move(callback));
   });
 
   return true;
@@ -191,7 +191,7 @@
       });
 }
 
-void Adapter::InitializeStep2(const InitializeCallback& callback) {
+void Adapter::InitializeStep2(InitializeCallback callback) {
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   FXL_DCHECK(IsInitializing());
 
@@ -308,7 +308,7 @@
         });
   }
 
-  init_seq_runner_->RunCommands([callback, this](hci::Status status) {
+  init_seq_runner_->RunCommands([callback = std::move(callback), this](hci::Status status) mutable {
     if (!status) {
       FXL_LOG(ERROR) << "gap: Adapter: Failed to obtain initial controller "
                         "information (step 2): "
@@ -318,11 +318,11 @@
       return;
     }
 
-    InitializeStep3(callback);
+    InitializeStep3(std::move(callback));
   });
 }
 
-void Adapter::InitializeStep3(const InitializeCallback& callback) {
+void Adapter::InitializeStep3(InitializeCallback callback) {
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   FXL_DCHECK(IsInitializing());
 
@@ -409,7 +409,7 @@
         });
   }
 
-  init_seq_runner_->RunCommands([callback, this](hci::Status status) {
+  init_seq_runner_->RunCommands([callback = std::move(callback), this](hci::Status status) mutable {
     if (!status) {
       FXL_LOG(ERROR) << "gap: Adapter: Failed to obtain initial controller "
                         "information (step 3): "
@@ -419,11 +419,11 @@
       return;
     }
 
-    InitializeStep4(callback);
+    InitializeStep4(std::move(callback));
   });
 }
 
-void Adapter::InitializeStep4(const InitializeCallback& callback) {
+void Adapter::InitializeStep4(InitializeCallback callback) {
   FXL_DCHECK(IsInitializing());
 
   // Initialize the scan manager based on current feature support.
diff --git a/drivers/bluetooth/lib/gap/adapter.h b/drivers/bluetooth/lib/gap/adapter.h
index 588940c..c4533b5 100644
--- a/drivers/bluetooth/lib/gap/adapter.h
+++ b/drivers/bluetooth/lib/gap/adapter.h
@@ -8,12 +8,12 @@
 #include <string>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/drivers/bluetooth/lib/gap/adapter_state.h"
 #include "garnet/drivers/bluetooth/lib/gap/remote_device_cache.h"
 #include "garnet/drivers/bluetooth/lib/gatt/gatt.h"
 #include "garnet/drivers/bluetooth/lib/l2cap/l2cap.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/weak_ptr.h"
@@ -72,9 +72,9 @@
   // device disappeared or the transport channels were closed for an unknown
   // reason). The implementation is responsible for cleaning up this adapter by
   // calling ShutDown().
-  using InitializeCallback = std::function<void(bool success)>;
-  bool Initialize(const InitializeCallback& callback,
-                  const fxl::Closure& transport_closed_callback);
+  using InitializeCallback = fit::function<void(bool success)>;
+  bool Initialize(InitializeCallback callback,
+                  fit::closure transport_closed_callback);
 
   // Shuts down this Adapter. Invokes |callback| when shut down has completed.
   // TODO(armansito): This needs to do several things to potentially preserve
@@ -140,15 +140,15 @@
  private:
   // Second step of the initialization sequence. Called by Initialize() when the
   // first batch of HCI commands have been sent.
-  void InitializeStep2(const InitializeCallback& callback);
+  void InitializeStep2(InitializeCallback callback);
 
   // Third step of the initialization sequence. Called by InitializeStep2() when
   // the second batch of HCI commands have been sent.
-  void InitializeStep3(const InitializeCallback& callback);
+  void InitializeStep3(InitializeCallback callback);
 
   // Fourth step of the initialization sequence. Called by InitializeStep3()
   // when the third batch of HCI commands have been sent.
-  void InitializeStep4(const InitializeCallback& callback);
+  void InitializeStep4(InitializeCallback callback);
 
   // Builds and returns the HCI event mask based on our supported host side
   // features and controller capabilities. This is used to mask events that we
@@ -174,7 +174,7 @@
   fxl::RefPtr<hci::Transport> hci_;
 
   // Callback invoked to notify clients when the underlying transport is closed.
-  fxl::Closure transport_closed_cb_;
+  fit::closure transport_closed_cb_;
 
   // Parameters relevant to the initialization sequence.
   // TODO(armansito): The Initialize()/ShutDown() pattern has become common
diff --git a/drivers/bluetooth/lib/gap/adapter_unittest.cc b/drivers/bluetooth/lib/gap/adapter_unittest.cc
index ea4e501..d897a43 100644
--- a/drivers/bluetooth/lib/gap/adapter_unittest.cc
+++ b/drivers/bluetooth/lib/gap/adapter_unittest.cc
@@ -50,8 +50,8 @@
     TestingBase::TearDown();
   }
 
-  void InitializeAdapter(const Adapter::InitializeCallback& callback) {
-    adapter_->Initialize(callback, [this] {
+  void InitializeAdapter(Adapter::InitializeCallback callback) {
+    adapter_->Initialize(std::move(callback), [this] {
       transport_closed_called_ = true;
     });
   }
@@ -79,7 +79,7 @@
   };
 
   // The controller supports nothing.
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_FALSE(success);
@@ -101,7 +101,7 @@
       static_cast<uint64_t>(hci::LMPFeature::kLESupported);
   test_device()->set_settings(settings);
 
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_FALSE(success);
@@ -126,7 +126,7 @@
   settings.le_total_num_acl_data_packets = 1;
   test_device()->set_settings(settings);
 
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_TRUE(success);
@@ -150,7 +150,7 @@
   test_device()->SetDefaultResponseStatus(hci::kLEReadLocalSupportedFeatures,
                                           hci::StatusCode::kHardwareFailure);
 
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_FALSE(success);
@@ -171,7 +171,7 @@
   settings.ApplyLEOnlyDefaults();
   test_device()->set_settings(settings);
 
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_TRUE(success);
@@ -204,7 +204,7 @@
   test_device()->SetDefaultResponseStatus(hci::kWriteLocalName,
                                           hci::StatusCode::kHardwareFailure);
 
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_TRUE(success);
@@ -234,7 +234,7 @@
   settings.ApplyDualModeDefaults();
   test_device()->set_settings(settings);
 
-  InitializeAdapter(init_cb);
+  InitializeAdapter(std::move(init_cb));
   RunUntilIdle();
 
   EXPECT_TRUE(success);
diff --git a/drivers/bluetooth/lib/gap/advertising_data.cc b/drivers/bluetooth/lib/gap/advertising_data.cc
index 0654f97..cdcae2d 100644
--- a/drivers/bluetooth/lib/gap/advertising_data.cc
+++ b/drivers/bluetooth/lib/gap/advertising_data.cc
@@ -30,12 +30,14 @@
   }
 };
 
+namespace ble = fuchsia::bluetooth::le;
+
 namespace btlib {
 namespace gap {
 
 namespace {
 
-using UuidFunction = std::function<void(const common::UUID&)>;
+using UuidFunction = fit::function<void(const common::UUID&)>;
 
 bool ParseUuids(const common::BufferView& data,
                 size_t uuid_size,
@@ -254,30 +256,29 @@
   return true;
 }
 
-::bluetooth_low_energy::AdvertisingDataPtr AdvertisingData::AsLEAdvertisingData()
-    const {
-  auto fidl_data = ::bluetooth_low_energy::AdvertisingData::New();
+::ble::AdvertisingDataPtr AdvertisingData::AsLEAdvertisingData() const {
+  auto fidl_data = ::ble::AdvertisingData::New();
   FXL_DCHECK(fidl_data);
 
   if (tx_power_) {
-    fidl_data->tx_power_level = ::btfidl::Int8::New();
+    fidl_data->tx_power_level = ::fuchsia::bluetooth::Int8::New();
     fidl_data->tx_power_level->value = *tx_power_;
   }
 
   if (appearance_) {
-    fidl_data->appearance = ::btfidl::UInt16::New();
+    fidl_data->appearance = ::fuchsia::bluetooth::UInt16::New();
     fidl_data->appearance->value = *appearance_;
   }
 
   for (const auto& pair : manufacturer_data_) {
-    ::bluetooth_low_energy::ManufacturerSpecificDataEntry entry;
+    ::ble::ManufacturerSpecificDataEntry entry;
     entry.company_id = pair.first;
     entry.data = fxl::To<fidl::VectorPtr<unsigned char>>(pair.second);
     fidl_data->manufacturer_specific_data.push_back(std::move(entry));
   }
 
   for (const auto& pair : service_data_) {
-    ::bluetooth_low_energy::ServiceDataEntry entry;
+    ::ble::ServiceDataEntry entry;
     entry.uuid = pair.first.ToString();
     entry.data = fxl::To<fidl::VectorPtr<unsigned char>>(pair.second);
     fidl_data->service_data.push_back(std::move(entry));
@@ -298,9 +299,8 @@
   return fidl_data;
 }
 
-void AdvertisingData::FromFidl(
-    const ::bluetooth_low_energy::AdvertisingData& fidl_ad,
-    AdvertisingData* out_ad) {
+void AdvertisingData::FromFidl(const ::ble::AdvertisingData& fidl_ad,
+                               AdvertisingData* out_ad) {
   FXL_DCHECK(out_ad);
   common::UUID uuid;
   for (const auto& uuid_str : *fidl_ad.service_uuids) {
diff --git a/drivers/bluetooth/lib/gap/advertising_data.h b/drivers/bluetooth/lib/gap/advertising_data.h
index 243db78..6e402aa 100644
--- a/drivers/bluetooth/lib/gap/advertising_data.h
+++ b/drivers/bluetooth/lib/gap/advertising_data.h
@@ -8,18 +8,13 @@
 #include <unordered_map>
 #include <unordered_set>
 
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
+
 #include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
 #include "garnet/drivers/bluetooth/lib/common/optional.h"
 #include "garnet/drivers/bluetooth/lib/common/uuid.h"
 #include "garnet/drivers/bluetooth/lib/gap/gap.h"
 
-#include <bluetooth_low_energy/cpp/fidl.h>
-
-// The internal library components and the generated FIDL bindings are both
-// declared under the "bluetooth" namespace. We define an alias here to
-// disambiguate.
-namespace btfidl = ::bluetooth;
-
 namespace btlib {
 namespace gap {
 
@@ -55,7 +50,7 @@
 
   // Fill the AdvertisingData |out_ad| from the corresponding FIDL object |obj|
   // Does not clear |out_ad| first.
-  static void FromFidl(const ::bluetooth_low_energy::AdvertisingData& fidl_ad,
+  static void FromFidl(const fuchsia::bluetooth::le::AdvertisingData& fidl_ad,
                        AdvertisingData* out_ad);
 
   // Copies all of the data in this object to |out|, including making a copy of
@@ -134,7 +129,7 @@
   bool WriteBlock(common::MutableByteBuffer* buffer) const;
 
   // Makes a FIDL object that holds the same data
-  ::bluetooth_low_energy::AdvertisingDataPtr AsLEAdvertisingData() const;
+  fuchsia::bluetooth::le::AdvertisingDataPtr AsLEAdvertisingData() const;
 
   // Relation operators
   bool operator==(const AdvertisingData& other) const;
diff --git a/drivers/bluetooth/lib/gap/advertising_data_unittest.cc b/drivers/bluetooth/lib/gap/advertising_data_unittest.cc
index 3ca3142..7050ef0 100644
--- a/drivers/bluetooth/lib/gap/advertising_data_unittest.cc
+++ b/drivers/bluetooth/lib/gap/advertising_data_unittest.cc
@@ -107,7 +107,7 @@
 }
 
 TEST(GAP_AdvertisingDataTest, ParseFIDL) {
-  ::bluetooth_low_energy::AdvertisingData fidl_ad;
+  fuchsia::bluetooth::le::AdvertisingData fidl_ad;
 
   // Confirming UTF-8 codepoints are working as well.
   fidl_ad.name = "Test💖";
@@ -119,7 +119,7 @@
     array->at(i) = static_cast<uint8_t>(i * 3);
   }
 
-  bluetooth_low_energy::ServiceDataEntry service_data_entry;
+  fuchsia::bluetooth::le::ServiceDataEntry service_data_entry;
   service_data_entry.uuid = kId1AsString;
   service_data_entry.data = std::move(array);
   fidl_ad.service_data.push_back(std::move(service_data_entry));
diff --git a/drivers/bluetooth/lib/gap/bredr_connection_manager.cc b/drivers/bluetooth/lib/gap/bredr_connection_manager.cc
index eb3417f..9b9dbd4 100644
--- a/drivers/bluetooth/lib/gap/bredr_connection_manager.cc
+++ b/drivers/bluetooth/lib/gap/bredr_connection_manager.cc
@@ -18,7 +18,7 @@
   FXL_DCHECK(cb);
   auto read_enable = hci::CommandPacket::New(hci::kReadScanEnable);
   auto finish_enable_cb = [enabled, dispatcher, hci, finish_cb = std::move(cb)](
-                              auto, const hci::EventPacket& event) {
+                              auto, const hci::EventPacket& event) mutable {
     auto status = event.ToStatus();
     if (!status) {
       FXL_LOG(WARNING)
@@ -45,7 +45,7 @@
             auto, const hci::EventPacket& event) { cb(event.ToStatus()); });
   };
   hci->command_channel()->SendCommand(std::move(read_enable), dispatcher,
-                                      finish_enable_cb);
+                                      std::move(finish_enable_cb));
 }
 
 }  // namespace
@@ -123,7 +123,7 @@
 
   WritePageScanSettings(
       hci::kPageScanR1Interval, hci::kPageScanR1Window, use_interlaced_scan_,
-      [self, cb = std::move(status_cb)](const auto& status) {
+      [self, cb = std::move(status_cb)](const auto& status) mutable {
         if (!status) {
           FXL_LOG(WARNING) << "gap: BrEdrConnectionManager: Writing Page Scan "
                               "Settings Failed: "
@@ -162,7 +162,7 @@
 
   hci_cmd_runner_->QueueCommand(
       std::move(write_activity),
-      [self, cb, interval, window](const hci::EventPacket& event) {
+      [self, cb = cb.share(), interval, window](const hci::EventPacket& event) {
         if (!self) {
           cb(hci::Status(common::HostError::kFailed));
           return;
@@ -183,7 +183,7 @@
 
   hci_cmd_runner_->QueueCommand(
       std::move(write_type),
-      [self, cb, interlaced](const hci::EventPacket& event) {
+      [self, cb = cb.share(), interlaced](const hci::EventPacket& event) {
         if (!self) {
           cb(hci::Status(common::HostError::kFailed));
           return;
@@ -193,7 +193,7 @@
         FXL_VLOG(2) << "gap: BrEdrConnectionManager: page scan type updated";
       });
 
-  hci_cmd_runner_->RunCommands(cb);
+  hci_cmd_runner_->RunCommands(std::move(cb));
 }
 
 void BrEdrConnectionManager::OnConnectionRequest(
diff --git a/drivers/bluetooth/lib/gap/bredr_discovery_manager.cc b/drivers/bluetooth/lib/gap/bredr_discovery_manager.cc
index 48a7e42..062dea1 100644
--- a/drivers/bluetooth/lib/gap/bredr_discovery_manager.cc
+++ b/drivers/bluetooth/lib/gap/bredr_discovery_manager.cc
@@ -145,10 +145,11 @@
         FXL_DCHECK(event.event_code() == hci::kInquiryCompleteEventCode);
 
         if (!status) {
-          FXL_VLOG(1) << "gap: inquiry command failed";
+          FXL_VLOG(1) << "gap: inquiry complete failure: " << status.ToString();
           return;
         }
 
+        FXL_VLOG(1) << "gap: BrEdrDiscoveryManager: inquiry complete, restart";
         // We've stopped scanning because we timed out.
         self->MaybeStartInquiry();
       },
@@ -209,7 +210,7 @@
   FXL_LOG(INFO) << "gap: BrEdrDiscoveryManager: RequestDiscoverable";
 
   auto self = weak_ptr_factory_.GetWeakPtr();
-  auto status_cb = [self, cb = std::move(callback)](const auto& status) {
+  auto status_cb = [self, cb = callback.share()](const auto& status) {
     cb(status, (status ? self->AddDiscoverableSession() : nullptr));
   };
 
diff --git a/drivers/bluetooth/lib/gap/bredr_discovery_manager.h b/drivers/bluetooth/lib/gap/bredr_discovery_manager.h
index 6ee68fc..395de73 100644
--- a/drivers/bluetooth/lib/gap/bredr_discovery_manager.h
+++ b/drivers/bluetooth/lib/gap/bredr_discovery_manager.h
@@ -115,7 +115,7 @@
   // been successfully started, the callback will receive a session object that
   // it owns. If no sessions are owned, device discovery is stopped.
   using DiscoveryCallback =
-      std::function<void(const hci::Status& status,
+      fit::function<void(const hci::Status& status,
                          std::unique_ptr<BrEdrDiscoverySession> session)>;
   void RequestDiscovery(DiscoveryCallback callback);
 
@@ -125,7 +125,7 @@
   // Requests this device be discoverable. Devices are discoverable as long as
   // anyone holds a discoverable session.
   using DiscoverableCallback =
-      std::function<void(const hci::Status& status,
+      fit::function<void(const hci::Status& status,
                          std::unique_ptr<BrEdrDiscoverableSession> session)>;
   void RequestDiscoverable(DiscoverableCallback callback);
 
diff --git a/drivers/bluetooth/lib/gap/low_energy_advertising_manager.cc b/drivers/bluetooth/lib/gap/low_energy_advertising_manager.cc
index 8b5b16e..751a193 100644
--- a/drivers/bluetooth/lib/gap/low_energy_advertising_manager.cc
+++ b/drivers/bluetooth/lib/gap/low_energy_advertising_manager.cc
@@ -67,7 +67,7 @@
 void LowEnergyAdvertisingManager::StartAdvertising(
     const AdvertisingData& data,
     const AdvertisingData& scan_rsp,
-    const ConnectionCallback& connect_callback,
+    ConnectionCallback connect_callback,
     uint32_t interval_ms,
     bool anonymous,
     AdvertisingStatusCallback status_callback) {
@@ -86,7 +86,7 @@
 
   hci::LowEnergyAdvertiser::ConnectionCallback adv_conn_cb;
   if (connect_callback) {
-    adv_conn_cb = [self, id = ad_ptr->id(), connect_callback](auto link) {
+    adv_conn_cb = [self, id = ad_ptr->id(), connect_callback = std::move(connect_callback)](auto link) {
       FXL_VLOG(1)
           << "gap: LowEnergyAdvertisingManager: received new connection.";
       if (!self)
@@ -125,7 +125,7 @@
 
   // Call StartAdvertising, with the callback
   advertiser_->StartAdvertising(address, *data_block, *scan_rsp_block,
-                                adv_conn_cb, interval_ms, anonymous,
+                                std::move(adv_conn_cb), interval_ms, anonymous,
                                 std::move(status_cb));
 }
 
diff --git a/drivers/bluetooth/lib/gap/low_energy_advertising_manager.h b/drivers/bluetooth/lib/gap/low_energy_advertising_manager.h
index 8f8445b..4c5a4d1 100644
--- a/drivers/bluetooth/lib/gap/low_energy_advertising_manager.h
+++ b/drivers/bluetooth/lib/gap/low_energy_advertising_manager.h
@@ -50,13 +50,13 @@
   //
   // TODO(armansito): Return integer IDs instead.
   using ConnectionCallback =
-      std::function<void(std::string advertisement_id,
+      fit::function<void(std::string advertisement_id,
                          std::unique_ptr<hci::Connection> link)>;
   using AdvertisingStatusCallback =
       fit::function<void(std::string advertisement_id, hci::Status status)>;
   void StartAdvertising(const AdvertisingData& data,
                         const AdvertisingData& scan_rsp,
-                        const ConnectionCallback& connect_callback,
+                        ConnectionCallback connect_callback,
                         uint32_t interval_ms,
                         bool anonymous,
                         AdvertisingStatusCallback status_callback);
diff --git a/drivers/bluetooth/lib/gap/low_energy_advertising_manager_unittest.cc b/drivers/bluetooth/lib/gap/low_energy_advertising_manager_unittest.cc
index c637c70..45fc7b5 100644
--- a/drivers/bluetooth/lib/gap/low_energy_advertising_manager_unittest.cc
+++ b/drivers/bluetooth/lib/gap/low_energy_advertising_manager_unittest.cc
@@ -60,7 +60,7 @@
   void StartAdvertising(const common::DeviceAddress& address,
                         const common::ByteBuffer& data,
                         const common::ByteBuffer& scan_rsp,
-                        const ConnectionCallback& connect_callback,
+                        ConnectionCallback connect_callback,
                         uint32_t interval_ms,
                         bool anonymous,
                         AdvertisingStatusCallback callback) override {
@@ -80,7 +80,7 @@
     AdvertisementStatus new_status;
     AdvertisingData::FromBytes(data, &new_status.data);
     AdvertisingData::FromBytes(scan_rsp, &new_status.scan_rsp);
-    new_status.connect_cb = connect_callback;
+    new_status.connect_cb = std::move(connect_callback);
     new_status.interval_ms = interval_ms;
     new_status.anonymous = anonymous;
     ads_->emplace(address, std::move(new_status));
@@ -97,7 +97,7 @@
     // ones.
     // TODO(jamuraa): make this send it to the correct callback once we can
     // determine which one that is.
-    ConnectionCallback cb = ads_->begin()->second.connect_cb;
+    const auto& cb = ads_->begin()->second.connect_cb;
     if (cb) {
       cb(std::move(link));
     }
diff --git a/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc b/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc
index 7c7788e..3d8cbe8 100644
--- a/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc
+++ b/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc
@@ -363,13 +363,13 @@
 }
 
 void LowEnergyConnectionManager::SetConnectionParametersCallbackForTesting(
-    const ConnectionParametersCallback& callback) {
-  test_conn_params_cb_ = callback;
+    ConnectionParametersCallback callback) {
+  test_conn_params_cb_ = std::move(callback);
 }
 
 void LowEnergyConnectionManager::SetDisconnectCallbackForTesting(
-    const DisconnectCallback& callback) {
-  test_disconn_cb_ = callback;
+    DisconnectCallback callback) {
+  test_disconn_cb_ = std::move(callback);
 }
 
 void LowEnergyConnectionManager::ReleaseReference(
diff --git a/drivers/bluetooth/lib/gap/low_energy_connection_manager.h b/drivers/bluetooth/lib/gap/low_energy_connection_manager.h
index 454ee48..37b0f5b 100644
--- a/drivers/bluetooth/lib/gap/low_energy_connection_manager.h
+++ b/drivers/bluetooth/lib/gap/low_energy_connection_manager.h
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 
 #include "garnet/drivers/bluetooth/lib/gap/gap.h"
 #include "garnet/drivers/bluetooth/lib/gatt/gatt.h"
@@ -19,7 +20,6 @@
 #include "garnet/drivers/bluetooth/lib/hci/low_energy_connector.h"
 #include "garnet/drivers/bluetooth/lib/l2cap/l2cap.h"
 
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_ptr.h"
 #include "lib/fxl/memory/weak_ptr.h"
@@ -54,8 +54,8 @@
   bool active() const { return active_; }
 
   // Sets a callback to be called when the underlying connection is closed.
-  void set_closed_callback(const fxl::Closure& callback) {
-    closed_cb_ = callback;
+  void set_closed_callback(fit::closure callback) {
+    closed_cb_ = std::move(callback);
   }
 
   const std::string& device_identifier() const { return device_id_; }
@@ -77,7 +77,7 @@
   std::string device_id_;
   hci::ConnectionHandle handle_;
   fxl::WeakPtr<LowEnergyConnectionManager> manager_;
-  fxl::Closure closed_cb_;
+  fit::closure closed_cb_;
   fxl::ThreadChecker thread_checker_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(LowEnergyConnectionRef);
@@ -140,9 +140,9 @@
   // callbacks there.
 
   // Called when the connection parameters on a link have been updated.
-  using ConnectionParametersCallback = std::function<void(const RemoteDevice&)>;
+  using ConnectionParametersCallback = fit::function<void(const RemoteDevice&)>;
   void SetConnectionParametersCallbackForTesting(
-      const ConnectionParametersCallback& callback);
+       ConnectionParametersCallback callback);
 
   // Called when a link with the given handle gets disconnected. This event is
   // guaranteed to be called before invalidating connection references.
@@ -151,8 +151,8 @@
   // NOTE: This is intended ONLY for unit tests. Clients should watch for
   // disconnection events using LowEnergyConnectionRef::set_closed_callback()
   // instead. DO NOT use outside of tests.
-  using DisconnectCallback = std::function<void(hci::ConnectionHandle)>;
-  void SetDisconnectCallbackForTesting(const DisconnectCallback& callback);
+  using DisconnectCallback = fit::function<void(hci::ConnectionHandle)>;
+  void SetDisconnectCallbackForTesting(DisconnectCallback callback);
 
   // Sets the timeout interval to be used on future connect requests. The
   // default value is kLECreateConnecionTimeoutMs.
@@ -184,7 +184,7 @@
 
     // Notifies all elements in |callbacks| with |status| and the result of
     // |func|.
-    using RefFunc = std::function<LowEnergyConnectionRefPtr()>;
+    using RefFunc = fit::function<LowEnergyConnectionRefPtr()>;
     void NotifyCallbacks(hci::Status status, const RefFunc& func);
 
     const common::DeviceAddress& address() const { return address_; }
diff --git a/drivers/bluetooth/lib/gap/low_energy_discovery_manager.cc b/drivers/bluetooth/lib/gap/low_energy_discovery_manager.cc
index 05db154..049716b 100644
--- a/drivers/bluetooth/lib/gap/low_energy_discovery_manager.cc
+++ b/drivers/bluetooth/lib/gap/low_energy_discovery_manager.cc
@@ -27,8 +27,8 @@
 }
 
 void LowEnergyDiscoverySession::SetResultCallback(
-    const DeviceFoundCallback& callback) {
-  device_found_callback_ = callback;
+    DeviceFoundCallback callback) {
+  device_found_callback_ = std::move(callback);
   if (!manager_)
     return;
   for (const auto& cached_device_id : manager_->cached_scan_results()) {
diff --git a/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h b/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h
index 280efbb..e2234ba 100644
--- a/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h
+++ b/drivers/bluetooth/lib/gap/low_energy_discovery_manager.h
@@ -119,8 +119,8 @@
   // the cached results from the most recent scan period. If a filter was
   // assigned earlier, then the callback will only receive results that match
   // the filter.
-  using DeviceFoundCallback = std::function<void(const RemoteDevice& device)>;
-  void SetResultCallback(const DeviceFoundCallback& callback);
+  using DeviceFoundCallback = fit::function<void(const RemoteDevice& device)>;
+  void SetResultCallback(DeviceFoundCallback callback);
 
   // Sets a callback to get notified when the session becomes inactive due to an
   // internal error.
diff --git a/drivers/bluetooth/lib/gap/low_energy_discovery_manager_unittest.cc b/drivers/bluetooth/lib/gap/low_energy_discovery_manager_unittest.cc
index a34e161..841b16a 100644
--- a/drivers/bluetooth/lib/gap/low_energy_discovery_manager_unittest.cc
+++ b/drivers/bluetooth/lib/gap/low_energy_discovery_manager_unittest.cc
@@ -594,7 +594,7 @@
       };
   sessions.push_back(StartDiscoverySession());
   sessions[0]->filter()->SetGeneralDiscoveryFlags();
-  sessions[0]->SetResultCallback(result_cb);
+  sessions[0]->SetResultCallback(std::move(result_cb));
 
   // Session 1 is interested in performing limited discovery.
   std::unordered_set<common::DeviceAddress> devices_session1;
@@ -604,7 +604,7 @@
   sessions.push_back(StartDiscoverySession());
   sessions[1]->filter()->set_flags(
       static_cast<uint8_t>(AdvFlag::kLELimitedDiscoverableMode));
-  sessions[1]->SetResultCallback(result_cb);
+  sessions[1]->SetResultCallback(std::move(result_cb));
 
   // Session 2 is interested in devices with UUID 0x180d.
   std::unordered_set<common::DeviceAddress> devices_session2;
@@ -615,7 +615,7 @@
 
   uint16_t uuid = 0x180d;
   sessions[2]->filter()->set_service_uuids({common::UUID(uuid)});
-  sessions[2]->SetResultCallback(result_cb);
+  sessions[2]->SetResultCallback(std::move(result_cb));
 
   // Session 3 is interested in devices whose names contain "Device".
   std::unordered_set<common::DeviceAddress> devices_session3;
@@ -624,7 +624,7 @@
   };
   sessions.push_back(StartDiscoverySession());
   sessions[3]->filter()->set_name_substring("Device");
-  sessions[3]->SetResultCallback(result_cb);
+  sessions[3]->SetResultCallback(std::move(result_cb));
 
   // Session 4 is interested in non-connectable devices.
   std::unordered_set<common::DeviceAddress> devices_session4;
@@ -633,7 +633,7 @@
   };
   sessions.push_back(StartDiscoverySession());
   sessions[4]->filter()->set_connectable(false);
-  sessions[4]->SetResultCallback(result_cb);
+  sessions[4]->SetResultCallback(std::move(result_cb));
 
   RunUntilIdle();
 
@@ -691,7 +691,7 @@
       };
   sessions.push_back(StartDiscoverySession());
   sessions[0]->filter()->SetGeneralDiscoveryFlags();
-  sessions[0]->SetResultCallback(result_cb);
+  sessions[0]->SetResultCallback(std::move(result_cb));
 
   RunUntilIdle();
   ASSERT_EQ(3u, devices_session0.size());
@@ -704,7 +704,7 @@
   sessions.push_back(StartDiscoverySession());
   sessions[1]->filter()->set_flags(
       static_cast<uint8_t>(AdvFlag::kLELimitedDiscoverableMode));
-  sessions[1]->SetResultCallback(result_cb);
+  sessions[1]->SetResultCallback(std::move(result_cb));
 
   // Session 2 is interested in devices with UUID 0x180d.
   std::unordered_set<common::DeviceAddress> devices_session2;
@@ -715,7 +715,7 @@
 
   uint16_t uuid = 0x180d;
   sessions[2]->filter()->set_service_uuids({common::UUID(uuid)});
-  sessions[2]->SetResultCallback(result_cb);
+  sessions[2]->SetResultCallback(std::move(result_cb));
 
   // Session 3 is interested in devices whose names contain "Device".
   std::unordered_set<common::DeviceAddress> devices_session3;
@@ -724,7 +724,7 @@
   };
   sessions.push_back(StartDiscoverySession());
   sessions[3]->filter()->set_name_substring("Device");
-  sessions[3]->SetResultCallback(result_cb);
+  sessions[3]->SetResultCallback(std::move(result_cb));
 
   // Session 4 is interested in non-connectable devices.
   std::unordered_set<common::DeviceAddress> devices_session4;
@@ -733,7 +733,7 @@
   };
   sessions.push_back(StartDiscoverySession());
   sessions[4]->filter()->set_connectable(false);
-  sessions[4]->SetResultCallback(result_cb);
+  sessions[4]->SetResultCallback(std::move(result_cb));
 
   EXPECT_EQ(5u, sessions.size());
 
diff --git a/drivers/bluetooth/lib/gatt/client.cc b/drivers/bluetooth/lib/gatt/client.cc
index 7d96ac1..c77d7b1 100644
--- a/drivers/bluetooth/lib/gatt/client.cc
+++ b/drivers/bluetooth/lib/gatt/client.cc
@@ -35,7 +35,7 @@
     att::Handle range_start,
     att::Handle range_end,
     BufferView entries,
-    const Client::DescriptorCallback& desc_callback,
+    Client::DescriptorCallback desc_callback,
     att::Handle* out_last_handle) {
   FXL_DCHECK(out_last_handle);
 
@@ -150,7 +150,7 @@
     auto params = writer.mutable_payload<att::ExchangeMTURequestParams>();
     params->client_rx_mtu = htole16(att_->preferred_mtu());
 
-    auto rsp_cb = BindCallback([this, mtu_cb](const att::PacketReader& rsp) {
+    auto rsp_cb = BindCallback([this, mtu_cb = mtu_cb.share()](const att::PacketReader& rsp) {
       FXL_DCHECK(rsp.opcode() == att::kExchangeMTUResponse);
 
       if (rsp.payload_size() != sizeof(att::ExchangeMTUResponseParams)) {
@@ -174,7 +174,7 @@
     });
 
     auto error_cb = BindErrorCallback(
-        [this, mtu_cb](att::Status status, att::Handle handle) {
+        [this, mtu_cb = mtu_cb.share()](att::Status status, att::Handle handle) {
           // "If the Error Response is sent by the server with the Error Code
           // set to Request Not Supported, [...] the default MTU shall be used
           // (Vol 3, Part G, 4.3.1)"
@@ -191,7 +191,7 @@
           mtu_cb(status, 0);
         });
 
-    att_->StartTransaction(std::move(pdu), rsp_cb, error_cb);
+    att_->StartTransaction(std::move(pdu), std::move(rsp_cb), std::move(error_cb));
   }
 
   void DiscoverPrimaryServices(ServiceCallback svc_callback,
@@ -219,7 +219,7 @@
     params->type = htole16(types::kPrimaryService16);
 
     auto rsp_cb = BindCallback([this, svc_cb = std::move(svc_callback),
-                                res_cb = status_callback](
+                                res_cb = status_callback.share()](
                                    const att::PacketReader& rsp) mutable {
       FXL_DCHECK(rsp.opcode() == att::kReadByGroupTypeResponse);
 
@@ -298,7 +298,7 @@
     });
 
     auto error_cb =
-        BindErrorCallback([this, res_cb = status_callback](att::Status status,
+        BindErrorCallback([this, res_cb = status_callback.share()](att::Status status,
                                                            att::Handle handle) {
           // An Error Response code of "Attribute Not Found" indicates the end
           // of the procedure (v5.0, Vol 3, Part G, 4.4.1).
@@ -311,7 +311,7 @@
           res_cb(status);
         });
 
-    att_->StartTransaction(std::move(pdu), rsp_cb, error_cb);
+    att_->StartTransaction(std::move(pdu), std::move(rsp_cb), std::move(error_cb));
   }
 
   void DiscoverCharacteristics(att::Handle range_start,
@@ -341,7 +341,7 @@
 
     auto rsp_cb = BindCallback(
         [this, range_start, range_end, chrc_cb = std::move(chrc_callback),
-         res_cb = status_callback](const att::PacketReader& rsp) mutable {
+         res_cb = status_callback.share()](const att::PacketReader& rsp) mutable {
           FXL_DCHECK(rsp.opcode() == att::kReadByTypeResponse);
 
           if (rsp.payload_size() < sizeof(att::ReadByTypeResponseParams)) {
@@ -451,7 +451,7 @@
         });
 
     auto error_cb =
-        BindErrorCallback([this, res_cb = status_callback](att::Status status,
+        BindErrorCallback([this, res_cb = status_callback.share()](att::Status status,
                                                            att::Handle handle) {
           // An Error Response code of "Attribute Not Found" indicates the end
           // of the procedure (v5.0, Vol 3, Part G, 4.6.1).
@@ -464,7 +464,7 @@
           res_cb(status);
         });
 
-    att_->StartTransaction(std::move(pdu), rsp_cb, error_cb);
+    att_->StartTransaction(std::move(pdu), std::move(rsp_cb), std::move(error_cb));
   }
 
   void DiscoverDescriptors(att::Handle range_start,
@@ -488,7 +488,7 @@
 
     auto rsp_cb = BindCallback([this, range_start, range_end,
                                 desc_cb = std::move(desc_callback),
-                                res_cb = status_callback](
+                                res_cb = status_callback.share()](
                                    const att::PacketReader& rsp) mutable {
       FXL_DCHECK(rsp.opcode() == att::kFindInformationResponse);
 
@@ -508,11 +508,11 @@
       switch (rsp_params.format) {
         case att::UUIDType::k16Bit:
           result = ProcessDescriptorDiscoveryResponse<att::UUIDType::k16Bit>(
-              range_start, range_end, entries, desc_cb, &last_handle);
+              range_start, range_end, entries, desc_cb.share(), &last_handle);
           break;
         case att::UUIDType::k128Bit:
           result = ProcessDescriptorDiscoveryResponse<att::UUIDType::k128Bit>(
-              range_start, range_end, entries, desc_cb, &last_handle);
+              range_start, range_end, entries, desc_cb.share(), &last_handle);
           break;
         default:
           FXL_VLOG(1) << "gatt: invalid information data format";
@@ -538,7 +538,7 @@
     });
 
     auto error_cb =
-        BindErrorCallback([this, res_cb = status_callback](att::Status status,
+        BindErrorCallback([this, res_cb = status_callback.share()](att::Status status,
                                                            att::Handle handle) {
           // An Error Response code of "Attribute Not Found" indicates the end
           // of the procedure (v5.0, Vol 3, Part G, 4.7.1).
@@ -551,7 +551,7 @@
           res_cb(status);
         });
 
-    att_->StartTransaction(std::move(pdu), rsp_cb, error_cb);
+    att_->StartTransaction(std::move(pdu), std::move(rsp_cb), std::move(error_cb));
   }
 
   void ReadRequest(att::Handle handle, ReadCallback callback) override {
@@ -565,19 +565,19 @@
     auto params = writer.mutable_payload<att::ReadRequestParams>();
     params->handle = htole16(handle);
 
-    auto rsp_cb = BindCallback([this, callback](const att::PacketReader& rsp) {
+    auto rsp_cb = BindCallback([this, callback = callback.share()](const att::PacketReader& rsp) {
       FXL_DCHECK(rsp.opcode() == att::kReadResponse);
       callback(att::Status(), rsp.payload_data());
     });
 
     auto error_cb = BindErrorCallback(
-        [this, callback](att::Status status, att::Handle handle) {
+        [this, callback = callback.share()](att::Status status, att::Handle handle) {
           FXL_VLOG(1) << "gatt: Read request failed: " << status.ToString()
                       << ", handle: " << handle;
           callback(status, BufferView());
         });
 
-    if (!att_->StartTransaction(std::move(pdu), rsp_cb, error_cb)) {
+    if (!att_->StartTransaction(std::move(pdu), std::move(rsp_cb), std::move(error_cb))) {
       callback(att::Status(HostError::kPacketMalformed), BufferView());
     }
   }
@@ -606,7 +606,7 @@
         writer.mutable_payload_data().mutable_view(sizeof(att::Handle));
     value.Copy(&value_view);
 
-    auto rsp_cb = BindCallback([this, callback](const att::PacketReader& rsp) {
+    auto rsp_cb = BindCallback([this, callback = callback.share()](const att::PacketReader& rsp) {
       FXL_DCHECK(rsp.opcode() == att::kWriteResponse);
 
       if (rsp.payload_size()) {
@@ -619,13 +619,13 @@
     });
 
     auto error_cb = BindErrorCallback(
-        [this, callback](att::Status status, att::Handle handle) {
+        [this, callback = callback.share()](att::Status status, att::Handle handle) {
           FXL_VLOG(1) << "gatt: Write request failed: " << status.ToString()
                       << ", handle: " << handle;
           callback(status);
         });
 
-    if (!att_->StartTransaction(std::move(pdu), rsp_cb, error_cb)) {
+    if (!att_->StartTransaction(std::move(pdu), std::move(rsp_cb), std::move(error_cb))) {
       callback(att::Status(HostError::kPacketMalformed));
     }
   }
@@ -638,7 +638,7 @@
   // still alive.
   att::Bearer::TransactionCallback BindCallback(
       att::Bearer::TransactionCallback callback) {
-    return [self = weak_ptr_factory_.GetWeakPtr(), callback](const auto& rsp) {
+    return [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback)](const auto& rsp) {
       if (self) {
         callback(rsp);
       }
@@ -649,7 +649,7 @@
   // alive.
   att::Bearer::ErrorCallback BindErrorCallback(
       att::Bearer::ErrorCallback callback) {
-    return [self = weak_ptr_factory_.GetWeakPtr(), callback](
+    return [self = weak_ptr_factory_.GetWeakPtr(), callback = std::move(callback)](
                att::Status status, att::Handle handle) {
       if (self) {
         callback(status, handle);
diff --git a/drivers/bluetooth/lib/gatt/client.h b/drivers/bluetooth/lib/gatt/client.h
index 52e8370..9c4e076 100644
--- a/drivers/bluetooth/lib/gatt/client.h
+++ b/drivers/bluetooth/lib/gatt/client.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <functional>
+#include <lib/fit/function.h>
 
 #include "garnet/drivers/bluetooth/lib/att/att.h"
 #include "garnet/drivers/bluetooth/lib/att/bearer.h"
@@ -48,7 +48,7 @@
   // |status| will be set to an error if the MTU exchange fails. The |mtu|
   // parameter will be set to 0 and the underlying bearer's MTU will remain
   // unmodified.
-  using MTUCallback = std::function<void(att::Status status, uint16_t mtu)>;
+  using MTUCallback = fit::function<void(att::Status status, uint16_t mtu)>;
   virtual void ExchangeMTU(MTUCallback callback) = 0;
 
   // Performs the "Discover All Primary Services" procedure defined in
@@ -61,13 +61,13 @@
   // ATT transactions, it is possible for |status_callback| to be called with an
   // error even if some services have been discovered. It is up to the client
   // to clear any cached state in this case.
-  using ServiceCallback = std::function<void(const ServiceData&)>;
+  using ServiceCallback = fit::function<void(const ServiceData&)>;
   virtual void DiscoverPrimaryServices(ServiceCallback svc_callback,
                                        att::StatusCallback status_callback) = 0;
 
   // Performs the "Discover All Characteristics of a Service" procedure defined
   // in v5.0, Vol 3, Part G, 4.6.1.
-  using CharacteristicCallback = std::function<void(const CharacteristicData&)>;
+  using CharacteristicCallback = fit::function<void(const CharacteristicData&)>;
   virtual void DiscoverCharacteristics(att::Handle range_start,
                                        att::Handle range_end,
                                        CharacteristicCallback chrc_callback,
@@ -75,7 +75,7 @@
 
   // Performs the "Discover All Characteristic Descriptors" procedure defined in
   // Vol 3, Part G, 4.7.1.
-  using DescriptorCallback = std::function<void(const DescriptorData&)>;
+  using DescriptorCallback = fit::function<void(const DescriptorData&)>;
   virtual void DiscoverDescriptors(att::Handle range_start,
                                    att::Handle range_end,
                                    DescriptorCallback desc_callback,
@@ -88,7 +88,7 @@
   // Reports the status of the procedure and the resulting value in |callback|.
   // Returns an empty buffer if the status is an error.
   using ReadCallback =
-      std::function<void(att::Status, const common::ByteBuffer&)>;
+      fit::function<void(att::Status, const common::ByteBuffer&)>;
   virtual void ReadRequest(att::Handle handle, ReadCallback callback) = 0;
 
   // Sends an ATT Write Request with the requested attribute |handle| and
@@ -105,7 +105,7 @@
   // Assigns a callback that will be called when a notification or indication
   // PDU is received.
   using NotificationCallback =
-      std::function<void(bool indication,
+      fit::function<void(bool indication,
                          att::Handle handle,
                          const common::ByteBuffer& value)>;
   virtual void SetNotificationHandler(NotificationCallback handler) = 0;
diff --git a/drivers/bluetooth/lib/gatt/client_unittest.cc b/drivers/bluetooth/lib/gatt/client_unittest.cc
index 89ae2d8..73eb921 100644
--- a/drivers/bluetooth/lib/gatt/client_unittest.cc
+++ b/drivers/bluetooth/lib/gatt/client_unittest.cc
@@ -64,7 +64,7 @@
                                Client::DescriptorCallback desc_callback,
                                att::Handle range_start = 0x0001,
                                att::Handle range_end = 0xFFFF) {
-    async::PostTask(dispatcher(), [=] {
+    async::PostTask(dispatcher(), [=, desc_callback = std::move(desc_callback)]() mutable {
       client()->DiscoverDescriptors(
           range_start, range_end, std::move(desc_callback),
           [out_status](att::Status val) { *out_status = val; });
diff --git a/drivers/bluetooth/lib/gatt/fake_client.cc b/drivers/bluetooth/lib/gatt/fake_client.cc
index da0338c..35d1b3e 100644
--- a/drivers/bluetooth/lib/gatt/fake_client.cc
+++ b/drivers/bluetooth/lib/gatt/fake_client.cc
@@ -29,7 +29,8 @@
 
 void FakeClient::DiscoverPrimaryServices(ServiceCallback svc_callback,
                                          StatusCallback status_callback) {
-  async::PostTask(dispatcher_, [this, svc_callback, status_callback] {
+  async::PostTask(dispatcher_, [this, svc_callback = std::move(svc_callback),
+                                status_callback = std::move(status_callback)] {
     for (const auto& svc : services_) {
       svc_callback(svc);
     }
@@ -45,8 +46,9 @@
   last_chrc_discovery_end_handle_ = range_end;
   chrc_discovery_count_++;
 
-  async::PostTask(dispatcher_, [this, range_start, range_end, chrc_callback,
-                                status_callback] {
+  async::PostTask(dispatcher_, [this, range_start, range_end,
+                                chrc_callback = std::move(chrc_callback),
+                                status_callback = std::move(status_callback)] {
     for (const auto& chrc : chrcs_) {
       if (chrc.handle >= range_start && chrc.handle <= range_end) {
         chrc_callback(chrc);
@@ -71,7 +73,8 @@
   }
 
   async::PostTask(dispatcher_, [this, status, range_start, range_end,
-                                desc_callback, status_callback] {
+                                desc_callback = std::move(desc_callback),
+                                status_callback = std::move(status_callback)] {
     for (const auto& desc : descs_) {
       if (desc.handle >= range_start && desc.handle <= range_end) {
         desc_callback(desc);
diff --git a/drivers/bluetooth/lib/gatt/fake_client.h b/drivers/bluetooth/lib/gatt/fake_client.h
index b7d229f..1c24e98 100644
--- a/drivers/bluetooth/lib/gatt/fake_client.h
+++ b/drivers/bluetooth/lib/gatt/fake_client.h
@@ -68,13 +68,13 @@
   size_t desc_discovery_count() const { return desc_discovery_count_; }
 
   // Sets a callback which will run when ReadRequest gets called.
-  using ReadRequestCallback = std::function<void(att::Handle, ReadCallback)>;
+  using ReadRequestCallback = fit::function<void(att::Handle, ReadCallback)>;
   void set_read_request_callback(ReadRequestCallback callback) {
     read_request_callback_ = std::move(callback);
   }
 
   // Sets a callback which will run when WriteRequest gets called.
-  using WriteRequestCallback = std::function<
+  using WriteRequestCallback = fit::function<
       void(att::Handle, const common::ByteBuffer&, att::StatusCallback)>;
   void set_write_request_callback(WriteRequestCallback callback) {
     write_request_callback_ = std::move(callback);
diff --git a/drivers/bluetooth/lib/gatt/gatt.cc b/drivers/bluetooth/lib/gatt/gatt.cc
index adfd7b4..8ddd770 100644
--- a/drivers/bluetooth/lib/gatt/gatt.cc
+++ b/drivers/bluetooth/lib/gatt/gatt.cc
@@ -272,7 +272,7 @@
       }
 
       // NOTE: this makes a copy of |watcher_|.
-      async::PostTask(dispatcher_, [peer_id, watcher = watcher_,
+      async::PostTask(dispatcher_, [peer_id, watcher = watcher_.share(),
                                     svc = std::move(svc)]() mutable {
         watcher(peer_id, std::move(svc));
       });
diff --git a/drivers/bluetooth/lib/gatt/gatt.h b/drivers/bluetooth/lib/gatt/gatt.h
index e3b7a33..56a3a3f 100644
--- a/drivers/bluetooth/lib/gatt/gatt.h
+++ b/drivers/bluetooth/lib/gatt/gatt.h
@@ -134,7 +134,7 @@
   // Otherwise, it will run on an internal thread and the client is responsible
   // for synchronization.
   using RemoteServiceWatcher =
-      std::function<void(const std::string& peer_id,
+      fit::function<void(const std::string& peer_id,
                          fbl::RefPtr<RemoteService> service)>;
   virtual void RegisterRemoteServiceWatcher(RemoteServiceWatcher watcher,
                                             async_t* dispatcher = nullptr) = 0;
diff --git a/drivers/bluetooth/lib/gatt/local_service_manager.cc b/drivers/bluetooth/lib/gatt/local_service_manager.cc
index 9974b12..2e389eb 100644
--- a/drivers/bluetooth/lib/gatt/local_service_manager.cc
+++ b/drivers/bluetooth/lib/gatt/local_service_manager.cc
@@ -19,8 +19,8 @@
 att::Handle InsertCharacteristicAttributes(
     att::AttributeGrouping* grouping,
     const Characteristic& chrc,
-    const att::Attribute::ReadHandler& read_handler,
-    const att::Attribute::WriteHandler& write_handler) {
+    att::Attribute::ReadHandler read_handler,
+    att::Attribute::WriteHandler write_handler) {
   FXL_DCHECK(grouping);
   FXL_DCHECK(!grouping->complete());
   FXL_DCHECK(read_handler);
@@ -38,8 +38,8 @@
       chrc.type(), chrc.read_permissions(), chrc.write_permissions());
   FXL_DCHECK(value_attr);
 
-  value_attr->set_read_handler(read_handler);
-  value_attr->set_write_handler(write_handler);
+  value_attr->set_read_handler(std::move(read_handler));
+  value_attr->set_write_handler(std::move(write_handler));
 
   size_t uuid_size = chrc.type().CompactSize(false /* allow_32bit */);
   FXL_DCHECK(uuid_size == 2 || uuid_size == 16);
@@ -66,8 +66,8 @@
     const common::UUID& type,
     const att::AccessRequirements& read_reqs,
     const att::AccessRequirements& write_reqs,
-    const att::Attribute::ReadHandler& read_handler,
-    const att::Attribute::WriteHandler& write_handler) {
+    att::Attribute::ReadHandler read_handler,
+    att::Attribute::WriteHandler write_handler) {
   FXL_DCHECK(grouping);
   FXL_DCHECK(!grouping->complete());
   FXL_DCHECK(read_handler);
@@ -77,8 +77,8 @@
   auto* attr = grouping->AddAttribute(type, read_reqs, write_reqs);
   FXL_DCHECK(attr);
 
-  attr->set_read_handler(read_handler);
-  attr->set_write_handler(write_handler);
+  attr->set_read_handler(std::move(read_handler));
+  attr->set_write_handler(std::move(write_handler));
 }
 
 // Returns false if the given service hierarchy contains repeating identifiers.
@@ -325,7 +325,7 @@
 
     auto read_handler = [self, id, props](const auto& peer_id,
                                           att::Handle handle, uint16_t offset,
-                                          const auto& result_cb) {
+                                          auto result_cb) {
       if (!self) {
         result_cb(att::ErrorCode::kUnlikelyError, common::BufferView());
         return;
@@ -339,13 +339,13 @@
         return;
       }
 
-      self->read_handler_(self->id_, id, offset, result_cb);
+      self->read_handler_(self->id_, id, offset, std::move(result_cb));
     };
 
     auto write_handler = [self, id, props](const auto& peer_id,
                                            att::Handle handle, uint16_t offset,
                                            const auto& value,
-                                           const auto& result_cb) {
+                                           auto result_cb) {
       if (!self) {
         if (result_cb)
           result_cb(att::ErrorCode::kUnlikelyError);
@@ -363,11 +363,11 @@
       if (!result_cb && !(props & Property::kWriteWithoutResponse))
         return;
 
-      self->write_handler_(self->id_, id, offset, value, result_cb);
+      self->write_handler_(self->id_, id, offset, value, std::move(result_cb));
     };
 
     att::Handle chrc_handle = InsertCharacteristicAttributes(
-        grouping, *chrc, read_handler, write_handler);
+        grouping, *chrc, std::move(read_handler), std::move(write_handler));
 
     if (props & Property::kNotify || props & Property::kIndicate) {
       AddCCCDescriptor(grouping, *chrc, chrc_handle);
@@ -404,19 +404,19 @@
     auto self = weak_ptr_factory_.GetWeakPtr();
     auto read_handler = [self, id = desc->id()](
                             const auto& peer_id, att::Handle handle,
-                            uint16_t offset, const auto& result_cb) {
+                            uint16_t offset, auto result_cb) {
       if (!self) {
         result_cb(att::ErrorCode::kUnlikelyError, common::BufferView());
         return;
       }
 
-      self->read_handler_(self->id_, id, offset, result_cb);
+      self->read_handler_(self->id_, id, offset, std::move(result_cb));
     };
 
     auto write_handler = [self, id = desc->id()](
                              const auto& peer_id, att::Handle handle,
                              uint16_t offset, const auto& value,
-                             const auto& result_cb) {
+                             auto result_cb) {
       // Descriptors cannot be written using the "write without response"
       // procedure.
       if (!result_cb)
@@ -427,12 +427,12 @@
         return;
       }
 
-      self->write_handler_(self->id_, id, offset, value, result_cb);
+      self->write_handler_(self->id_, id, offset, value, std::move(result_cb));
     };
 
     InsertDescriptorAttribute(grouping, desc->type(), desc->read_permissions(),
-                              desc->write_permissions(), read_handler,
-                              write_handler);
+                              desc->write_permissions(), std::move(read_handler),
+                              std::move(write_handler));
   }
 
   void AddCCCDescriptor(att::AttributeGrouping* grouping,
@@ -450,32 +450,32 @@
 
     auto read_handler = [self, id, chrc_handle](
                             const auto& peer_id, att::Handle handle,
-                            uint16_t offset, const auto& result_cb) {
+                            uint16_t offset, auto result_cb) {
       if (!self) {
         result_cb(att::ErrorCode::kUnlikelyError, common::BufferView());
         return;
       }
 
-      self->OnReadCCC(id, peer_id, chrc_handle, offset, result_cb);
+      self->OnReadCCC(id, peer_id, chrc_handle, offset, std::move(result_cb));
     };
 
     auto write_handler = [self, id, chrc_handle, props = chrc.properties()](
                              const auto& peer_id, att::Handle handle,
                              uint16_t offset, const auto& value,
-                             const auto& result_cb) {
+                             auto result_cb) {
       if (!self) {
         result_cb(att::ErrorCode::kUnlikelyError);
         return;
       }
 
       self->OnWriteCCC(id, props, peer_id, chrc_handle, offset, value,
-                       result_cb);
+                       std::move(result_cb));
     };
 
     // The write permission is determined by the service.
     InsertDescriptorAttribute(grouping, types::kClientCharacteristicConfig,
                               read_reqs, chrc.update_permissions(),
-                              read_handler, write_handler);
+                              std::move(read_handler), std::move(write_handler));
   }
 
   IdType id_;
diff --git a/drivers/bluetooth/lib/gatt/local_service_manager.h b/drivers/bluetooth/lib/gatt/local_service_manager.h
index 68430cf..40d891e 100644
--- a/drivers/bluetooth/lib/gatt/local_service_manager.h
+++ b/drivers/bluetooth/lib/gatt/local_service_manager.h
@@ -24,10 +24,10 @@
 //   - |responder|: Should be called to respond to the read request with a
 //                  characteristic or descriptor value, or an ATT error code.
 using ReadResponder = att::Attribute::ReadResultCallback;
-using ReadHandler = std::function<void(IdType service_id,
+using ReadHandler = fit::function<void(IdType service_id,
                                        IdType id,
                                        uint16_t offset,
-                                       const ReadResponder& responder)>;
+                                       ReadResponder responder)>;
 
 // Called to write the value of a dynamic characteristic or characteristic
 // descriptor.
@@ -40,15 +40,15 @@
 //                  if the client has initiated a "Write Without Response"
 //                  procedure, in which case a response is not required.
 using WriteResponder = att::Attribute::WriteResultCallback;
-using WriteHandler = std::function<void(IdType service_id,
+using WriteHandler = fit::function<void(IdType service_id,
                                         IdType id,
                                         uint16_t offset,
                                         const common::ByteBuffer& value,
-                                        const WriteResponder& responder)>;
+                                        WriteResponder responder)>;
 
 // Called when the peer device with the given |peer_id| has enabled or disabled
 // notifications/indications on the characteristic with id |chrc_id|.
-using ClientConfigCallback = std::function<void(IdType service_id,
+using ClientConfigCallback = fit::function<void(IdType service_id,
                                                 IdType chrc_id,
                                                 const std::string& peer_id,
                                                 bool notify,
@@ -56,7 +56,7 @@
 
 // Called with the ID and range of attributes handles spanned (inclusive) by a
 // service that was added or removed.
-using ServiceChangedCallback = std::function<void(IdType service_id,
+using ServiceChangedCallback = fit::function<void(IdType service_id,
                                                   att::Handle start,
                                                   att::Handle end)>;
 
diff --git a/drivers/bluetooth/lib/gatt/local_service_manager_unittest.cc b/drivers/bluetooth/lib/gatt/local_service_manager_unittest.cc
index e0e82c3..0a9098b 100644
--- a/drivers/bluetooth/lib/gatt/local_service_manager_unittest.cc
+++ b/drivers/bluetooth/lib/gatt/local_service_manager_unittest.cc
@@ -49,8 +49,8 @@
                        ReadHandler read_handler = NopReadHandler,
                        WriteHandler write_handler = NopWriteHandler,
                        ClientConfigCallback ccc_callback = NopCCCallback) {
-  return mgr->RegisterService(std::move(service), read_handler, write_handler,
-                              ccc_callback);
+  return mgr->RegisterService(std::move(service), std::move(read_handler), std::move(write_handler),
+                              std::move(ccc_callback));
 }
 
 TEST(GATT_LocalServiceManagerTest, EmptyService) {
@@ -455,9 +455,9 @@
                                        kReadReqs, kWriteReqs, kUpdateReqs));
 
   bool called = false;
-  auto read_cb = [&called](auto, auto, auto, auto&) { called = true; };
+  auto read_cb = [&called](auto, auto, auto, auto) { called = true; };
 
-  EXPECT_NE(0u, RegisterService(&mgr, std::move(service), read_cb));
+  EXPECT_NE(0u, RegisterService(&mgr, std::move(service), std::move(read_cb)));
 
   auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
   ASSERT_TRUE(attr);
@@ -468,7 +468,7 @@
     result_called = true;
   };
 
-  EXPECT_FALSE(attr->ReadAsync(kTestDeviceId, 0, result_cb));
+  EXPECT_FALSE(attr->ReadAsync(kTestDeviceId, 0, std::move(result_cb)));
   EXPECT_FALSE(called);
   EXPECT_FALSE(result_called);
 }
@@ -487,9 +487,9 @@
       kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
 
   bool called = false;
-  auto read_cb = [&called](auto, auto, auto, auto&) { called = true; };
+  auto read_cb = [&called](auto, auto, auto, auto) { called = true; };
 
-  EXPECT_NE(0u, RegisterService(&mgr, std::move(service), read_cb));
+  EXPECT_NE(0u, RegisterService(&mgr, std::move(service), std::move(read_cb)));
 
   auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
   ASSERT_TRUE(attr);
@@ -498,7 +498,7 @@
   att::ErrorCode ecode = att::ErrorCode::kNoError;
   auto result_cb = [&ecode](auto code, const auto&) { ecode = code; };
 
-  EXPECT_TRUE(attr->ReadAsync(kTestDeviceId, 0, result_cb));
+  EXPECT_TRUE(attr->ReadAsync(kTestDeviceId, 0, std::move(result_cb)));
 
   // The error should be handled internally and not reach |read_cb|.
   EXPECT_FALSE(called);
@@ -524,7 +524,7 @@
   bool called = false;
   IdType svc_id;
   auto read_cb = [&](auto cb_svc_id, auto id, auto offset,
-                     const auto& responder) {
+                     auto responder) {
     called = true;
     EXPECT_EQ(svc_id, cb_svc_id);
     EXPECT_EQ(kChrcId, id);
@@ -532,7 +532,7 @@
     responder(att::ErrorCode::kNoError, kTestValue);
   };
 
-  svc_id = RegisterService(&mgr, std::move(service), read_cb);
+  svc_id = RegisterService(&mgr, std::move(service), std::move(read_cb));
   ASSERT_NE(0u, svc_id);
 
   auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
@@ -545,7 +545,7 @@
     EXPECT_TRUE(common::ContainersEqual(kTestValue, value));
   };
 
-  EXPECT_TRUE(attr->ReadAsync(kTestDeviceId, kOffset, result_cb));
+  EXPECT_TRUE(attr->ReadAsync(kTestDeviceId, kOffset, std::move(result_cb)));
 
   EXPECT_TRUE(called);
   EXPECT_EQ(att::ErrorCode::kNoError, ecode);
@@ -564,10 +564,10 @@
                                        0, kReadReqs, kWriteReqs, kUpdateReqs));
 
   bool called = false;
-  auto write_cb = [&called](auto, auto, auto, auto&, auto&) { called = true; };
+  auto write_cb = [&called](auto, auto, auto, auto&, auto) { called = true; };
 
   EXPECT_NE(
-      0u, RegisterService(&mgr, std::move(service), NopReadHandler, write_cb));
+      0u, RegisterService(&mgr, std::move(service), NopReadHandler, std::move(write_cb)));
 
   auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
   ASSERT_TRUE(attr);
@@ -576,7 +576,7 @@
   bool result_called = false;
   auto result_cb = [&result_called](auto) { result_called = true; };
 
-  EXPECT_FALSE(attr->WriteAsync(kTestDeviceId, 0, kTestValue, result_cb));
+  EXPECT_FALSE(attr->WriteAsync(kTestDeviceId, 0, kTestValue, std::move(result_cb)));
   EXPECT_FALSE(called);
   EXPECT_FALSE(result_called);
 }
@@ -595,10 +595,10 @@
       kChrcId, kChrcType16, 0, 0, kReadReqs, kWriteReqs, kUpdateReqs));
 
   bool called = false;
-  auto write_cb = [&called](auto, auto, auto, auto&, auto&) { called = true; };
+  auto write_cb = [&called](auto, auto, auto, auto&, auto) { called = true; };
 
   EXPECT_NE(
-      0u, RegisterService(&mgr, std::move(service), NopReadHandler, write_cb));
+      0u, RegisterService(&mgr, std::move(service), NopReadHandler, std::move(write_cb)));
 
   auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
   ASSERT_TRUE(attr);
@@ -607,7 +607,7 @@
   att::ErrorCode ecode = att::ErrorCode::kNoError;
   auto result_cb = [&ecode](auto code) { ecode = code; };
 
-  EXPECT_TRUE(attr->WriteAsync(kTestDeviceId, 0, kTestValue, result_cb));
+  EXPECT_TRUE(attr->WriteAsync(kTestDeviceId, 0, kTestValue, std::move(result_cb)));
 
   // The error should be handled internally and not reach |write_cb|.
   EXPECT_FALSE(called);
@@ -633,7 +633,7 @@
   bool called = false;
   IdType svc_id;
   auto write_cb = [&](auto cb_svc_id, auto id, auto offset, const auto& value,
-                      const auto& responder) {
+                      auto responder) {
     called = true;
     EXPECT_EQ(svc_id, cb_svc_id);
     EXPECT_EQ(kChrcId, id);
@@ -642,7 +642,7 @@
     responder(att::ErrorCode::kNoError);
   };
 
-  svc_id = RegisterService(&mgr, std::move(service), NopReadHandler, write_cb);
+  svc_id = RegisterService(&mgr, std::move(service), NopReadHandler, std::move(write_cb));
   ASSERT_NE(0u, svc_id);
 
   auto* attr = mgr.database()->FindAttribute(kFirstChrcValueHandle);
@@ -652,7 +652,7 @@
   att::ErrorCode ecode = att::ErrorCode::kUnlikelyError;
   auto result_cb = [&ecode](auto code) { ecode = code; };
 
-  EXPECT_TRUE(attr->WriteAsync(kTestDeviceId, kOffset, kTestValue, result_cb));
+  EXPECT_TRUE(attr->WriteAsync(kTestDeviceId, kOffset, kTestValue, std::move(result_cb)));
 
   EXPECT_TRUE(called);
   EXPECT_EQ(att::ErrorCode::kNoError, ecode);
@@ -674,9 +674,9 @@
   service->AddCharacteristic(std::move(chrc));
 
   bool called = false;
-  auto read_cb = [&called](auto, auto, auto, auto&) { called = true; };
+  auto read_cb = [&called](auto, auto, auto, auto) { called = true; };
 
-  EXPECT_NE(0u, RegisterService(&mgr, std::move(service), read_cb));
+  EXPECT_NE(0u, RegisterService(&mgr, std::move(service), std::move(read_cb)));
 
   auto* attr = mgr.database()->FindAttribute(kFirstDescrHandle);
   ASSERT_TRUE(attr);
@@ -687,7 +687,7 @@
     result_called = true;
   };
 
-  EXPECT_FALSE(attr->ReadAsync(kTestDeviceId, 0, result_cb));
+  EXPECT_FALSE(attr->ReadAsync(kTestDeviceId, 0, std::move(result_cb)));
   EXPECT_FALSE(called);
   EXPECT_FALSE(result_called);
 }
@@ -723,7 +723,7 @@
     responder(att::ErrorCode::kNoError, kTestValue);
   };
 
-  svc_id = RegisterService(&mgr, std::move(service), read_cb);
+  svc_id = RegisterService(&mgr, std::move(service), std::move(read_cb));
   ASSERT_NE(0u, svc_id);
 
   auto* attr = mgr.database()->FindAttribute(kFirstDescrHandle);
@@ -736,7 +736,7 @@
     EXPECT_TRUE(common::ContainersEqual(kTestValue, value));
   };
 
-  EXPECT_TRUE(attr->ReadAsync(kTestDeviceId, kOffset, result_cb));
+  EXPECT_TRUE(attr->ReadAsync(kTestDeviceId, kOffset, std::move(result_cb)));
 
   EXPECT_TRUE(called);
   EXPECT_EQ(att::ErrorCode::kNoError, ecode);
@@ -759,7 +759,7 @@
   service->AddCharacteristic(std::move(chrc));
 
   bool called = false;
-  auto write_cb = [&called](auto, auto, auto, auto&, auto&) { called = true; };
+  auto write_cb = [&called](auto, auto, auto, auto&, auto) { called = true; };
 
   EXPECT_NE(
       0u, RegisterService(&mgr, std::move(service), NopReadHandler, write_cb));
diff --git a/drivers/bluetooth/lib/gatt/remote_characteristic.cc b/drivers/bluetooth/lib/gatt/remote_characteristic.cc
index 57436cf..fdb7d8b 100644
--- a/drivers/bluetooth/lib/gatt/remote_characteristic.cc
+++ b/drivers/bluetooth/lib/gatt/remote_characteristic.cc
@@ -25,7 +25,7 @@
 }
 
 void NotifyValue(const common::ByteBuffer& value,
-                 const RemoteCharacteristic::ValueCallback& callback,
+                 RemoteCharacteristic::ValueCallback callback,
                  async_t* dispatcher) {
   if (!dispatcher) {
     callback(value);
@@ -36,7 +36,7 @@
   if (buffer) {
     value.Copy(buffer.get());
     async::PostTask(dispatcher,
-                    [callback, val = std::move(buffer)] { callback(*val); });
+                    [callback = std::move(callback), val = std::move(buffer)] { callback(*val); });
   } else {
     FXL_VLOG(1) << "gatt: out of memory!";
   }
@@ -295,9 +295,9 @@
   FXL_DCHECK(client_);
   FXL_DCHECK(!shut_down_);
 
-  for (const auto& iter : notify_handlers_) {
-    const auto& handler = iter.second;
-    NotifyValue(value, handler.callback, handler.dispatcher);
+  for (auto& iter : notify_handlers_) {
+    auto& handler = iter.second;
+    NotifyValue(value, handler.callback.share(), handler.dispatcher);
   }
 }
 
diff --git a/drivers/bluetooth/lib/gatt/remote_characteristic.h b/drivers/bluetooth/lib/gatt/remote_characteristic.h
index 3c4cda5..ff739ad 100644
--- a/drivers/bluetooth/lib/gatt/remote_characteristic.h
+++ b/drivers/bluetooth/lib/gatt/remote_characteristic.h
@@ -53,9 +53,9 @@
 // MUST call ShutDown() on the GATT thread to ensure safe clean up.
 class RemoteCharacteristic final {
  public:
-  using ValueCallback = std::function<void(const common::ByteBuffer&)>;
+  using ValueCallback = fit::function<void(const common::ByteBuffer&)>;
   using NotifyStatusCallback =
-      std::function<void(att::Status, IdType handler_id)>;
+      fit::function<void(att::Status, IdType handler_id)>;
 
   // Represents a "Characteristic Descriptor" (Vol 3, Part G, 3.3.3).
   class Descriptor final {
diff --git a/drivers/bluetooth/lib/gatt/remote_service.cc b/drivers/bluetooth/lib/gatt/remote_service.cc
index d2c51af..e49505d 100644
--- a/drivers/bluetooth/lib/gatt/remote_service.cc
+++ b/drivers/bluetooth/lib/gatt/remote_service.cc
@@ -92,7 +92,7 @@
   }
 }
 
-bool RemoteService::AddRemovedHandler(fxl::Closure handler,
+bool RemoteService::AddRemovedHandler(fit::closure handler,
                                       async_t* dispatcher) {
   std::lock_guard<std::mutex> lock(mtx_);
 
diff --git a/drivers/bluetooth/lib/gatt/remote_service.h b/drivers/bluetooth/lib/gatt/remote_service.h
index 6a23a48..27c402b 100644
--- a/drivers/bluetooth/lib/gatt/remote_service.h
+++ b/drivers/bluetooth/lib/gatt/remote_service.h
@@ -21,7 +21,7 @@
 
 // Callback type invoked to notify when GATT services get discovered.
 class RemoteService;
-using RemoteServiceWatcher = std::function<void(fbl::RefPtr<RemoteService>)>;
+using RemoteServiceWatcher = fit::function<void(fbl::RefPtr<RemoteService>)>;
 
 using ServiceList = std::vector<fbl::RefPtr<RemoteService>>;
 using ServiceListCallback = fit::function<void(att::Status, ServiceList)>;
@@ -60,7 +60,7 @@
   // Adds a handler which will be called when this service gets removed.
   // Returns false if the service was already shut down. |callback| will be
   // posted on |dispatcher|.
-  bool AddRemovedHandler(fxl::Closure handler, async_t* dispatcher = nullptr);
+  bool AddRemovedHandler(fit::closure handler, async_t* dispatcher = nullptr);
 
   // Returns true if all contents of this service have been discovered. This can
   // only be called on the GATT thread and is primarily intended for unit tests.
@@ -81,7 +81,7 @@
   //
   // NOTE: Providing a |dispatcher| results in a copy of the resulting value.
   using ReadValueCallback =
-      std::function<void(att::Status, const common::ByteBuffer&)>;
+      fit::function<void(att::Status, const common::ByteBuffer&)>;
   void ReadCharacteristic(IdType id,
                           ReadValueCallback callback,
                           async_t* dispatcher = nullptr);
@@ -140,7 +140,7 @@
     async_t* dispatcher;
   };
 
-  using PendingClosure = PendingCallback<fxl::Closure>;
+  using PendingClosure = PendingCallback<fit::closure>;
   using PendingCharacteristicCallback = PendingCallback<CharacteristicCallback>;
 
   // A RemoteService can only be constructed by a RemoteServiceManager.
diff --git a/drivers/bluetooth/lib/hci/acl_data_channel.cc b/drivers/bluetooth/lib/hci/acl_data_channel.cc
index 418855f..ec6da00 100644
--- a/drivers/bluetooth/lib/hci/acl_data_channel.cc
+++ b/drivers/bluetooth/lib/hci/acl_data_channel.cc
@@ -439,7 +439,7 @@
     FXL_DCHECK(rx_dispatcher_);
 
     async::PostTask(rx_dispatcher_,
-                    [cb = rx_callback_, packet = std::move(packet)]() mutable {
+                    [cb = rx_callback_.share(), packet = std::move(packet)]() mutable {
                       cb(std::move(packet));
                     });
   }
diff --git a/drivers/bluetooth/lib/hci/acl_data_channel.h b/drivers/bluetooth/lib/hci/acl_data_channel.h
index 2558d5c..7711d01 100644
--- a/drivers/bluetooth/lib/hci/acl_data_channel.h
+++ b/drivers/bluetooth/lib/hci/acl_data_channel.h
@@ -5,7 +5,6 @@
 #ifndef GARNET_DRIVERS_BLUETOOTH_LIB_HCI_ACL_DATA_CHANNEL_H_
 #define GARNET_DRIVERS_BLUETOOTH_LIB_HCI_ACL_DATA_CHANNEL_H_
 
-#include <functional>
 #include <list>
 #include <mutex>
 #include <queue>
@@ -99,7 +98,7 @@
   // The ownership of the |data_packet| is passed to the callback implementation
   // as a rvalue reference..
   using DataReceivedCallback =
-      std::function<void(ACLDataPacketPtr data_packet)>;
+      fit::function<void(ACLDataPacketPtr data_packet)>;
 
   // Assigns a handler callback for received ACL data packets. |rx_callback|
   // will be posted on |dispatcher|.
diff --git a/drivers/bluetooth/lib/hci/acl_data_channel_unittest.cc b/drivers/bluetooth/lib/hci/acl_data_channel_unittest.cc
index 60024ea..16990d0 100644
--- a/drivers/bluetooth/lib/hci/acl_data_channel_unittest.cc
+++ b/drivers/bluetooth/lib/hci/acl_data_channel_unittest.cc
@@ -603,7 +603,7 @@
     else
       FXL_NOTREACHED();
   };
-  set_data_received_callback(data_rx_cb);
+  set_data_received_callback(std::move(data_rx_cb));
 
   // Malformed packet: smaller than the ACL header.
   auto invalid0 = common::CreateStaticByteBuffer(0x01, 0x00, 0x00);
diff --git a/drivers/bluetooth/lib/hci/command_channel.cc b/drivers/bluetooth/lib/hci/command_channel.cc
index 7c3ec8e..a0406ec 100644
--- a/drivers/bluetooth/lib/hci/command_channel.cc
+++ b/drivers/bluetooth/lib/hci/command_channel.cc
@@ -9,6 +9,7 @@
 #include <lib/async/default.h>
 #include <zircon/status.h>
 
+#include "garnet/drivers/bluetooth/lib/common/run_or_post.h"
 #include "garnet/drivers/bluetooth/lib/common/run_task_sync.h"
 #include "lib/fxl/functional/auto_call.h"
 #include "lib/fxl/logging.h"
@@ -96,10 +97,9 @@
   callback_ = nullptr;
 }
 
-CommandChannel::EventCallback CommandChannel::TransactionData::MakeCallback()
-    const {
+CommandChannel::EventCallback CommandChannel::TransactionData::MakeCallback() {
   return
-      [id = id_, cb = callback_](const EventPacket& event) { cb(id, event); };
+      [id = id_, cb = callback_.share()](const EventPacket& event) { cb(id, event); };
 }
 
 CommandChannel::CommandChannel(Transport* transport,
@@ -182,7 +182,7 @@
     event_code_handlers_.clear();
     subevent_code_handlers_.clear();
     pending_transactions_.clear();
-    expiring_event_handler_ids_.clear();
+    async_cmd_handlers_.clear();
   }
 }
 
@@ -193,7 +193,7 @@
     const EventCode complete_event_code) {
   if (!is_initialized_) {
     FXL_VLOG(1)
-        << "hci: CommandChannel: Cannot send commands while uninitialized";
+        << "hci: CommandChannel: can't send commands while uninitialized";
     return 0u;
   }
 
@@ -209,9 +209,9 @@
     // Cannot send an asynchronous command if there's an external event handler
     // registered for the completion event.
     if (it != event_code_handlers_.end() &&
-        expiring_event_handler_ids_.count(it->second) == 0) {
+        async_cmd_handlers_.count(complete_event_code) == 0) {
       FXL_VLOG(1)
-          << "hci: CommandChannel: Event handler already handling this event.";
+          << "hci: CommandChannel: event handler already handling this event";
       return 0u;
     }
   }
@@ -252,15 +252,17 @@
   }
 
   std::lock_guard<std::mutex> lock(event_handler_mutex_);
-  if (event_code_handlers_.find(event_code) != event_code_handlers_.end()) {
-    FXL_LOG(ERROR) << "hci: event handler already registered for event code: "
+  auto it = async_cmd_handlers_.find(event_code);
+  if (it != async_cmd_handlers_.end()) {
+    FXL_LOG(ERROR) << "hci: async event handler " << it->second
+                   << " already registered for event code: "
                    << fxl::StringPrintf("0x%02x", event_code);
     return 0u;
   }
 
   auto id = NewEventHandler(event_code, false /* is_le_meta */,
                             std::move(event_callback), dispatcher);
-  event_code_handlers_[event_code] = id;
+  event_code_handlers_.emplace(event_code, id);
   return id;
 }
 
@@ -270,17 +272,9 @@
     async_t* dispatcher) {
   std::lock_guard<std::mutex> lock(event_handler_mutex_);
 
-  if (subevent_code_handlers_.find(subevent_code) !=
-      subevent_code_handlers_.end()) {
-    FXL_LOG(ERROR)
-        << "hci: event handler already registered for LE Meta subevent code: "
-        << fxl::StringPrintf("0x%02x", subevent_code);
-    return 0u;
-  }
-
   auto id = NewEventHandler(subevent_code, true /* is_le_meta */,
                             std::move(event_callback), dispatcher);
-  subevent_code_handlers_[subevent_code] = id;
+  subevent_code_handlers_.emplace(subevent_code, id);
   return id;
 }
 
@@ -288,22 +282,32 @@
   std::lock_guard<std::mutex> lock(event_handler_mutex_);
 
   // Internal handler ids can't be removed.
-  if (expiring_event_handler_ids_.count(id))
+  auto it = std::find_if(async_cmd_handlers_.begin(), async_cmd_handlers_.end(),
+                         [id](auto&& p) { return p.second == id; });
+  if (it != async_cmd_handlers_.end()) {
     return;
+  }
 
   RemoveEventHandlerInternal(id);
 }
 
 void CommandChannel::RemoveEventHandlerInternal(EventHandlerId id) {
   auto iter = event_handler_id_map_.find(id);
-  if (iter == event_handler_id_map_.end())
+  if (iter == event_handler_id_map_.end()) {
     return;
+  }
 
   if (iter->second.event_code != 0) {
-    if (iter->second.is_le_meta_subevent) {
-      subevent_code_handlers_.erase(iter->second.event_code);
-    } else {
-      event_code_handlers_.erase(iter->second.event_code);
+    auto* event_handlers = iter->second.is_le_meta_subevent
+                               ? &subevent_code_handlers_
+                               : &event_code_handlers_;
+
+    auto range = event_handlers->equal_range(iter->second.event_code);
+    for (auto it = range.first; it != range.second; ++it) {
+      if (it->second == id) {
+        event_handlers->erase(it);
+        break;
+      }
     }
   }
   event_handler_id_map_.erase(iter);
@@ -386,6 +390,8 @@
   // We already have a handler for this transaction, or another transaction
   // is already waiting and it will be queued.
   if (event_code_handlers_.count(data->complete_event_code())) {
+    FXL_VLOG(3) << "hci: CommandChannel: async command " << data->id()
+                << ": a handler already exists.";
     return;
   }
 
@@ -394,8 +400,10 @@
                             data->MakeCallback(), data->dispatcher());
   FXL_DCHECK(id != 0u);
   data->set_handler_id(id);
-  expiring_event_handler_ids_.insert(id);
-  event_code_handlers_[data->complete_event_code()] = id;
+  async_cmd_handlers_[data->complete_event_code()] = id;
+  event_code_handlers_.emplace(data->complete_event_code(), id);
+  FXL_VLOG(3) << "hci: CommandChannel: async command " << data->id()
+              << " assigned handler " << id;
 }
 
 CommandChannel::EventHandlerId CommandChannel::NewEventHandler(
@@ -415,8 +423,10 @@
   data.dispatcher = dispatcher;
   data.is_le_meta_subevent = is_le_meta;
 
+  FXL_VLOG(3) << "hci: CommandChannel: adding event handler " << id
+              << " for event code " << fxl::StringPrintf("0x%02x", event_code);
   FXL_DCHECK(event_handler_id_map_.find(id) == event_handler_id_map_.end());
-  event_handler_id_map_[id] = data;
+  event_handler_id_map_[id] = std::move(data);
 
   return id;
 }
@@ -478,58 +488,77 @@
   // If an asyncronous command failed, then remove it's event handler.
   if (async_failed) {
     RemoveEventHandlerInternal(pending->handler_id());
-    expiring_event_handler_ids_.erase(pending->handler_id());
+    async_cmd_handlers_.erase(pending->complete_event_code());
   }
 }
 
 void CommandChannel::NotifyEventHandler(std::unique_ptr<EventPacket> event) {
   EventCode event_code;
-  const std::unordered_map<EventCode, EventHandlerId>* event_handlers;
-
-  if (event->event_code() == kLEMetaEventCode) {
-    event_code = event->view().payload<LEMetaEventParams>().subevent_code;
-    event_handlers = &subevent_code_handlers_;
-  } else {
-    event_code = event->event_code();
-    event_handlers = &event_code_handlers_;
-  }
-
-  auto iter = event_handlers->find(event_code);
-  if (iter == event_handlers->end()) {
-    FXL_VLOG(1) << "hci: CommandChannel: Event " << event_code
-                << " received with no handler";
-    return;
-  }
-
-  EventCallback callback;
-  async_t* dispatcher;
+  const std::unordered_multimap<EventCode, EventHandlerId>* event_handlers;
+  std::vector<std::pair<EventCallback, async_t*>> pending_callbacks;
 
   {
     std::lock_guard<std::mutex> lock(event_handler_mutex_);
-    auto handler_iter = event_handler_id_map_.find(iter->second);
-    FXL_DCHECK(handler_iter != event_handler_id_map_.end());
 
-    auto& handler = handler_iter->second;
-    FXL_DCHECK(handler.event_code == event_code);
+    if (event->event_code() == kLEMetaEventCode) {
+      event_code = event->view().payload<LEMetaEventParams>().subevent_code;
+      event_handlers = &subevent_code_handlers_;
+    } else {
+      event_code = event->event_code();
+      event_handlers = &event_code_handlers_;
+    }
 
-    callback = handler.event_callback;
-    dispatcher = handler.dispatcher;
+    auto range = event_handlers->equal_range(event_code);
+    if (range.first == event_handlers->end()) {
+      FXL_VLOG(1) << "hci: CommandChannel: Event "
+                  << fxl::StringPrintf("0x%02x", event_code)
+                  << " received with no handler";
+      return;
+    }
 
-    auto expired_it = expiring_event_handler_ids_.find(iter->second);
-    if (expired_it != expiring_event_handler_ids_.end()) {
-      RemoveEventHandlerInternal(iter->second);
-      expiring_event_handler_ids_.erase(expired_it);
+    auto iter = range.first;
+    while (iter != range.second) {
+      EventCallback callback;
+      async_t* dispatcher;
+      EventHandlerId event_id = iter->second;
+      FXL_VLOG(5) << "hci: CommandChannel: notifying handler (id " << event_id
+                  << ") for event code "
+                  << fxl::StringPrintf("0x%02x", event_code);
+      auto handler_iter = event_handler_id_map_.find(event_id);
+      FXL_DCHECK(handler_iter != event_handler_id_map_.end());
+
+      auto& handler = handler_iter->second;
+      FXL_DCHECK(handler.event_code == event_code);
+
+      callback = handler.event_callback.share();
+      dispatcher = handler.dispatcher;
+
+      ++iter;  // Advance so we don't point to an invalid iterator.
+      auto expired_it = async_cmd_handlers_.find(event_code);
+      if (expired_it != async_cmd_handlers_.end()) {
+        RemoveEventHandlerInternal(event_id);
+        async_cmd_handlers_.erase(expired_it);
+      }
+      pending_callbacks.emplace_back(std::move(callback), dispatcher);
     }
   }
+  // Process queue so callbacks can't add a handler if another queued command
+  // finishes on the same event.
+  TrySendQueuedCommands();
 
-  if (thread_checker_.IsCreationThreadCurrent()) {
-    callback(*event);
-    return;
+  auto it = pending_callbacks.begin();
+  for (; it != pending_callbacks.end() - 1; ++it) {
+    auto event_copy = EventPacket::New(event->view().payload_size());
+    common::MutableBufferView buf = event_copy->mutable_view()->mutable_data();
+    event->view().data().Copy(&buf);
+    common::RunOrPost(
+        [ev = std::move(event_copy), cb = std::move(it->first)]() { cb(*ev); },
+        it->second);
   }
-
-  // Post the event on the requested dispatcher.
-  async::PostTask(dispatcher,
-      [event = std::move(event), callback]() mutable { callback(*event); });
+  // Don't copy for the last callback.
+  common::RunOrPost(
+      [ev = std::move(event), cb = std::move(it->first)]() { cb(*ev); },
+      it->second);
 }
 
 void CommandChannel::OnChannelReady(
@@ -598,10 +627,10 @@
     if (packet->event_code() == kCommandStatusEventCode ||
         packet->event_code() == kCommandCompleteEventCode) {
       UpdateTransaction(std::move(packet));
+      TrySendQueuedCommands();
     } else {
       NotifyEventHandler(std::move(packet));
     }
-    TrySendQueuedCommands();
   }
 
   status = wait->Begin(async);
diff --git a/drivers/bluetooth/lib/hci/command_channel.h b/drivers/bluetooth/lib/hci/command_channel.h
index fa4ac15..2477456 100644
--- a/drivers/bluetooth/lib/hci/command_channel.h
+++ b/drivers/bluetooth/lib/hci/command_channel.h
@@ -6,7 +6,6 @@
 #define GARNET_DRIVERS_BLUETOOTH_LIB_HCI_COMMAND_CHANNEL_H_
 
 #include <atomic>
-#include <functional>
 #include <list>
 #include <memory>
 #include <mutex>
@@ -104,7 +103,7 @@
   // See Bluetooth Core Spec v5.0, Volume 2, Part E, Section 4.4 "Command Flow
   // Control" for more information about the HCI command flow control.
   using CommandCallback =
-      std::function<void(TransactionId id, const EventPacket& event)>;
+      fit::function<void(TransactionId id, const EventPacket& event)>;
   TransactionId SendCommand(
       std::unique_ptr<CommandPacket> command_packet,
       async_t* dispatcher,
@@ -117,7 +116,7 @@
 
   // Callback invoked to report generic HCI events excluding CommandComplete and
   // CommandStatus events.
-  using EventCallback = std::function<void(const EventPacket& event_packet)>;
+  using EventCallback = fit::function<void(const EventPacket& event_packet)>;
 
   // Registers an event handler for HCI events that match |event_code|. Incoming
   // HCI event packets that are not associated with a pending command sequence
@@ -134,15 +133,16 @@
   // Returns an ID if the handler was successfully registered. Returns
   // zero in case of an error.
   //
-  // Only one handler can be registered for a given |event_code| at a time. If a
-  // handler was previously registered for the given |event_code|, this method
-  // returns zero.
+  // Multiple handlers can be registered for a given |event_code| at a time.
+  // All handlers that are registered will be called with a reference to the
+  // event.
   //
   // If an asynchronous command is queued which completes on |event_code|, this
-  // method returns zero. It is good practice to avoid using asynchrous commands
-  // and event handlers for the same event code.  In most cases, registering a
-  // long-lived event handler and ending transactions on CommandStatus is
-  // recommended.
+  // method returns zero. It is good practice to avoid using asynchronous
+  // commands and event handlers for the same event code.  SendCommand allows
+  // for queueing multiple asynchronous commands with the same callback.
+  // Alternately a long-lived event handler can be registered with Commands
+  // completing on CommandStatus.
   //
   // If |dispatcher| corresponds to the I/O thread's dispatcher, then the
   // callback will be executed as soon as the event is received from the command
@@ -193,7 +193,7 @@
     void Complete(std::unique_ptr<EventPacket> event);
 
     // Makes an EventCallback that calls the callback correctly.
-    EventCallback MakeCallback() const;
+    EventCallback MakeCallback();
 
     async_t* dispatcher() const { return dispatcher_; }
     EventCode complete_event_code() const { return complete_event_code_; }
@@ -293,14 +293,6 @@
   // EventHandlerId counter.
   std::atomic_size_t next_event_handler_id_ __TA_GUARDED(event_handler_mutex_);
 
-  // Event handlers that are automatically removed after being called.
-  //
-  // These are currently only used internally for asynchronous commands to
-  // end transacions and deliver these events to callbacks.
-  // These can not be detected or removed using RemoveEventHandler.
-  std::unordered_set<EventHandlerId> expiring_event_handler_ids_
-      __TA_GUARDED(event_handler_mutex_);
-
   // Used to assert that certain public functions are only called on the
   // creation thread.
   fxl::ThreadChecker thread_checker_;
@@ -348,14 +340,24 @@
   std::unordered_map<EventHandlerId, EventHandlerData> event_handler_id_map_
       __TA_GUARDED(event_handler_mutex_);
 
-  // Mapping from event code to the event handler that was registered to handle
-  // that event code.
-  std::unordered_map<EventCode, EventHandlerId> event_code_handlers_
+  // Mapping from event code to the event handlers that were registered to
+  // handle that event code.
+  std::unordered_multimap<EventCode, EventHandlerId> event_code_handlers_
       __TA_GUARDED(event_handler_mutex_);
 
-  // Mapping from LE Meta Event Subevent code to the event handler that was
+  // Mapping from LE Meta Event Subevent code to the event handlers that were
   // registered to handle that event code.
-  std::unordered_map<EventCode, EventHandlerId> subevent_code_handlers_
+  std::unordered_multimap<EventCode, EventHandlerId> subevent_code_handlers_
+      __TA_GUARDED(event_handler_mutex_);
+
+  // Mapping from event code to the event handler for async command completion.
+  // These are automatically removed after being called once.
+  // Any event codes in this map are also in event_code_handlers_ and
+  // the event handler id here must be the only one for this event code.
+  //
+  // The event ids in this map can not be detected or removed using
+  // RemoveEventHandler (but can by RemoveEventHandlerInternal).
+  std::unordered_map<EventCode, EventHandlerId> async_cmd_handlers_
       __TA_GUARDED(event_handler_mutex_);
 
   FXL_DISALLOW_COPY_AND_ASSIGN(CommandChannel);
diff --git a/drivers/bluetooth/lib/hci/command_channel_unittest.cc b/drivers/bluetooth/lib/hci/command_channel_unittest.cc
index 9d8df63..dbdc9a8 100644
--- a/drivers/bluetooth/lib/hci/command_channel_unittest.cc
+++ b/drivers/bluetooth/lib/hci/command_channel_unittest.cc
@@ -37,13 +37,13 @@
 class TestCallbackObject
     : public fxl::RefCountedThreadSafe<TestCallbackObject> {
  public:
-  explicit TestCallbackObject(const fxl::Closure& deletion_callback)
-      : deletion_cb_(deletion_callback) {}
+  explicit TestCallbackObject(fit::closure deletion_callback)
+      : deletion_cb_(std::move(deletion_callback)) {}
 
   virtual ~TestCallbackObject() { deletion_cb_(); }
 
  private:
-  fxl::Closure deletion_cb_;
+  fit::closure deletion_cb_;
 };
 
 class CommandChannelTest : public TestingBase {
@@ -486,7 +486,7 @@
 
   EXPECT_EQ(3u, cb_count);
 
-  // Should not be able to regisrer an event handler now, we're still waiting on
+  // Should not be able to register an event handler now, we're still waiting on
   // the asynchronous command.
   auto event_id0 = cmd_channel()->AddEventHandler(
       kTestEventCode0, [](const auto&) {}, dispatcher());
@@ -577,6 +577,7 @@
   ASSERT_NE(0u, id);
   ASSERT_EQ(0u, transaction_count);
 
+  // This returns invalid because an async command is registered.
   auto invalid_id = cmd_channel()->AddEventHandler(
       kTestEventCode0, [](const auto&) {}, dispatcher());
 
@@ -614,25 +615,32 @@
   };
 
   int event_count1 = 0;
-  auto event_cb1 = [&event_count1, kTestEventCode1,
+  auto event_cb1 = [&event_count1, kTestEventCode0,
                     this](const EventPacket& event) {
     event_count1++;
-    EXPECT_EQ(kTestEventCode1, event.event_code());
+    EXPECT_EQ(kTestEventCode0, event.event_code());
   };
 
+  int event_count2 = 0;
+  auto event_cb2 = [&event_count2, kTestEventCode1,
+                    this](const EventPacket& event) {
+    event_count2++;
+    EXPECT_EQ(kTestEventCode1, event.event_code());
+  };
   auto id0 = cmd_channel()->AddEventHandler(kTestEventCode0, event_cb0,
                                             dispatcher());
   EXPECT_NE(0u, id0);
 
-  // Cannot register a handler for the same event code more than once.
-  auto id1 = cmd_channel()->AddEventHandler(kTestEventCode0, event_cb1,
-                                            dispatcher());
-  EXPECT_EQ(0u, id1);
+  // Can register a handler for the same event code more than once.
+  auto id1 =
+      cmd_channel()->AddEventHandler(kTestEventCode0, event_cb1, dispatcher());
+  EXPECT_NE(0u, id1);
+  EXPECT_NE(id0, id1);
 
   // Add a handler for a different event code.
-  id1 = cmd_channel()->AddEventHandler(kTestEventCode1, event_cb1,
-                                       dispatcher());
-  EXPECT_NE(0u, id1);
+  auto id2 =
+      cmd_channel()->AddEventHandler(kTestEventCode1, event_cb2, dispatcher());
+  EXPECT_NE(0u, id2);
 
   auto reset = CommandPacket::New(kReset);
   auto transaction_id = cmd_channel()->SendCommand(
@@ -656,10 +664,12 @@
   RunUntilIdle();
 
   EXPECT_EQ(3, event_count0);
-  EXPECT_EQ(2, event_count1);
+  EXPECT_EQ(3, event_count1);
+  EXPECT_EQ(2, event_count2);
 
   event_count0 = 0;
   event_count1 = 0;
+  event_count2 = 0;
 
   // Remove the first event handler.
   cmd_channel()->RemoveEventHandler(id0);
@@ -676,7 +686,27 @@
   RunUntilIdle();
 
   EXPECT_EQ(0, event_count0);
-  EXPECT_EQ(2, event_count1);
+  EXPECT_EQ(7, event_count1);
+  EXPECT_EQ(2, event_count2);
+
+  event_count0 = 0;
+  event_count1 = 0;
+  event_count2 = 0;
+
+  // Remove the second event handler.
+  cmd_channel()->RemoveEventHandler(id1);
+  test_device()->SendCommandChannelPacket(event0);
+  test_device()->SendCommandChannelPacket(event0);
+  test_device()->SendCommandChannelPacket(event1);
+  test_device()->SendCommandChannelPacket(event0);
+  test_device()->SendCommandChannelPacket(event1);
+  test_device()->SendCommandChannelPacket(event1);
+
+  RunUntilIdle();
+
+  EXPECT_EQ(0, event_count0);
+  EXPECT_EQ(0, event_count1);
+  EXPECT_EQ(3, event_count2);
 }
 
 // Tests:
@@ -766,32 +796,33 @@
       kTestSubeventCode0, event_cb0, dispatcher());
   EXPECT_NE(0u, id0);
 
-  // Cannot register a handler for the same event code more than once.
+  // Can register a handler for the same event code more than once.
   auto id1 = cmd_channel()->AddLEMetaEventHandler(
       kTestSubeventCode0, event_cb0, dispatcher());
-  EXPECT_EQ(0u, id1);
-
-  // Add a handle for a different event code.
-  id1 = cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode1, event_cb1,
-                                             dispatcher());
   EXPECT_NE(0u, id1);
+  EXPECT_NE(id0, id1);
+
+  // Add a handler for a different event code.
+  auto id2 = cmd_channel()->AddLEMetaEventHandler(kTestSubeventCode1, event_cb1,
+                                                  dispatcher());
+  EXPECT_NE(0u, id2);
 
   test_device()->StartCmdChannel(test_cmd_chan());
   test_device()->StartAclChannel(test_acl_chan());
 
   test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
   RunUntilIdle();
-  EXPECT_EQ(1, event_count0);
+  EXPECT_EQ(2, event_count0);
   EXPECT_EQ(0, event_count1);
 
   test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
   RunUntilIdle();
-  EXPECT_EQ(2, event_count0);
+  EXPECT_EQ(4, event_count0);
   EXPECT_EQ(0, event_count1);
 
   test_device()->SendCommandChannelPacket(le_meta_event_bytes1);
   RunUntilIdle();
-  EXPECT_EQ(2, event_count0);
+  EXPECT_EQ(4, event_count0);
   EXPECT_EQ(1, event_count1);
 
   // Remove the first event handler.
@@ -799,7 +830,7 @@
   test_device()->SendCommandChannelPacket(le_meta_event_bytes0);
   test_device()->SendCommandChannelPacket(le_meta_event_bytes1);
   RunUntilIdle();
-  EXPECT_EQ(2, event_count0);
+  EXPECT_EQ(5, event_count0);
   EXPECT_EQ(2, event_count1);
 }
 
@@ -956,7 +987,7 @@
       if (cb_count < 2) {
         // Add the second command when the first one completes.
         auto packet = CommandPacket::New(kReset);
-        id2 = cmd_channel->SendCommand(std::move(packet), dispatcher, cb,
+        id2 = cmd_channel->SendCommand(std::move(packet), dispatcher, cb.share(),
                                        kTestEventCode0);
       }
     }
@@ -965,7 +996,7 @@
 
   auto packet = CommandPacket::New(kReset);
   id1 = cmd_channel()->SendCommand(
-      std::move(packet), dispatcher(), cb, kTestEventCode0);
+      std::move(packet), dispatcher(), cb.share(), kTestEventCode0);
 
   RunUntilIdle();
 
diff --git a/drivers/bluetooth/lib/hci/connection.h b/drivers/bluetooth/lib/hci/connection.h
index d4e9ca8..159d395 100644
--- a/drivers/bluetooth/lib/hci/connection.h
+++ b/drivers/bluetooth/lib/hci/connection.h
@@ -4,10 +4,11 @@
 
 #pragma once
 
+#include <lib/fit/function.h>
+
 #include "garnet/drivers/bluetooth/lib/common/device_address.h"
 #include "garnet/drivers/bluetooth/lib/hci/connection_parameters.h"
 #include "garnet/drivers/bluetooth/lib/hci/hci.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_ptr.h"
diff --git a/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.cc b/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.cc
index 1d976ac..37b4d0b 100644
--- a/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.cc
+++ b/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.cc
@@ -134,7 +134,7 @@
     const common::DeviceAddress& address,
     const common::ByteBuffer& data,
     const common::ByteBuffer& scan_rsp,
-    const ConnectionCallback& connect_callback,
+    ConnectionCallback connect_callback,
     uint32_t interval_ms,
     bool anonymous,
     AdvertisingStatusCallback callback) {
@@ -227,7 +227,7 @@
 
   hci_cmd_runner_->RunCommands([this, address, interval_slices,
                                 callback = std::move(callback),
-                                connect_callback](Status status) mutable {
+                                connect_callback = std::move(connect_callback)](Status status) mutable {
     FXL_DCHECK(starting_);
     starting_ = false;
 
@@ -237,7 +237,7 @@
     uint16_t interval;
     if (status) {
       advertised_ = address;
-      connect_callback_ = connect_callback;
+      connect_callback_ = std::move(connect_callback);
       interval = TimeslicesToMilliseconds(interval_slices);
     } else {
       // Clear out the advertising data if it partially succeeded.
diff --git a/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.h b/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.h
index 56d0035..26dfdb1 100644
--- a/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.h
+++ b/drivers/bluetooth/lib/hci/legacy_low_energy_advertiser.h
@@ -30,7 +30,7 @@
   void StartAdvertising(const common::DeviceAddress& address,
                         const common::ByteBuffer& data,
                         const common::ByteBuffer& scan_rsp,
-                        const ConnectionCallback& connect_callback,
+                        ConnectionCallback connect_callback,
                         uint32_t interval_ms,
                         bool anonymous,
                         AdvertisingStatusCallback callback) override;
diff --git a/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.cc b/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.cc
index eb6cf67..70bcaad 100644
--- a/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.cc
+++ b/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.cc
@@ -64,7 +64,7 @@
                                        bool filter_duplicates,
                                        LEScanFilterPolicy filter_policy,
                                        int64_t period_ms,
-                                       const ScanStatusCallback& callback) {
+                                       ScanStatusCallback callback) {
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   FXL_DCHECK(callback);
   FXL_DCHECK(period_ms == kPeriodInfinite || period_ms > 0);
@@ -88,7 +88,7 @@
 
   set_state(State::kInitiating);
   active_scanning_ = active;
-  scan_cb_ = callback;
+  scan_cb_ = std::move(callback);
 
   // HCI_LE_Set_Scan_Parameters
   auto command = CommandPacket::New(kLESetScanParameters,
@@ -121,9 +121,7 @@
     FXL_DCHECK(state() == State::kInitiating);
 
     if (!status) {
-      auto cb = scan_cb_;
-
-      scan_cb_ = nullptr;
+      auto cb = std::move(scan_cb_);
       set_state(State::kIdle);
 
       FXL_LOG(ERROR) << "gap: LegacyLowEnergyScanner: failed to start scan: "
@@ -220,9 +218,7 @@
       // ScanStatus::kFailed instead.
     }
 
-    auto cb = scan_cb_;
-
-    scan_cb_ = nullptr;
+    auto cb = std::move(scan_cb_);
     set_state(State::kIdle);
 
     cb(!status ? ScanStatus::kFailed
diff --git a/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.h b/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.h
index fe0477b..6a88be8 100644
--- a/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.h
+++ b/drivers/bluetooth/lib/hci/legacy_low_energy_scanner.h
@@ -41,7 +41,7 @@
                  bool filter_duplicates,
                  LEScanFilterPolicy filter_policy,
                  int64_t period_ms,
-                 const ScanStatusCallback& callback) override;
+                 ScanStatusCallback callback) override;
   bool StopScan() override;
 
   // Used by tests to directly end a scan period without relying on a timeout.
diff --git a/drivers/bluetooth/lib/hci/legacy_low_energy_scanner_unittest.cc b/drivers/bluetooth/lib/hci/legacy_low_energy_scanner_unittest.cc
index 4c3abe6..300f096 100644
--- a/drivers/bluetooth/lib/hci/legacy_low_energy_scanner_unittest.cc
+++ b/drivers/bluetooth/lib/hci/legacy_low_energy_scanner_unittest.cc
@@ -66,10 +66,10 @@
     TestingBase::TearDown();
   }
 
-  using DeviceFoundCallback = std::function<void(const LowEnergyScanResult&,
+  using DeviceFoundCallback = fit::function<void(const LowEnergyScanResult&,
                                                  const common::ByteBuffer&)>;
-  void set_device_found_callback(const DeviceFoundCallback& cb) {
-    device_found_cb_ = cb;
+  void set_device_found_callback(DeviceFoundCallback cb) {
+    device_found_cb_ = std::move(cb);
   }
 
   // LowEnergyScanner::Observer overrides:
diff --git a/drivers/bluetooth/lib/hci/low_energy_advertiser.h b/drivers/bluetooth/lib/hci/low_energy_advertiser.h
index 425f8ab..cd04916 100644
--- a/drivers/bluetooth/lib/hci/low_energy_advertiser.h
+++ b/drivers/bluetooth/lib/hci/low_energy_advertiser.h
@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include <functional>
 #include <memory>
 
 #include <lib/fit/function.h>
@@ -50,11 +49,11 @@
   // be called before any calls to |connect_callback|.
   using AdvertisingStatusCallback =
       fit::function<void(uint32_t interval_ms, Status status)>;
-  using ConnectionCallback = std::function<void(ConnectionPtr link)>;
+  using ConnectionCallback = fit::function<void(ConnectionPtr link)>;
   virtual void StartAdvertising(const common::DeviceAddress& address,
                                 const common::ByteBuffer& data,
                                 const common::ByteBuffer& scan_rsp,
-                                const ConnectionCallback& connect_callback,
+                                ConnectionCallback connect_callback,
                                 uint32_t interval_ms,
                                 bool anonymous,
                                 AdvertisingStatusCallback callback) = 0;
diff --git a/drivers/bluetooth/lib/hci/low_energy_connector.cc b/drivers/bluetooth/lib/hci/low_energy_connector.cc
index 7d3d578..66f30d7 100644
--- a/drivers/bluetooth/lib/hci/low_energy_connector.cc
+++ b/drivers/bluetooth/lib/hci/low_energy_connector.cc
@@ -20,11 +20,11 @@
 
 LowEnergyConnector::PendingRequest::PendingRequest(
     const common::DeviceAddress& peer_address,
-    const StatusCallback& status_callback)
+    StatusCallback status_callback)
     : canceled(false),
       timed_out(false),
       peer_address(peer_address),
-      status_callback(status_callback) {}
+      status_callback(std::move(status_callback)) {}
 
 LowEnergyConnector::LowEnergyConnector(fxl::RefPtr<Transport> hci,
                                        async_t* dispatcher,
@@ -60,7 +60,7 @@
     uint16_t scan_interval,
     uint16_t scan_window,
     const LEPreferredConnectionParameters& initial_parameters,
-    const StatusCallback& status_callback,
+    StatusCallback status_callback,
     int64_t timeout_ms) {
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   FXL_DCHECK(status_callback);
@@ -71,7 +71,7 @@
     return false;
 
   FXL_DCHECK(!request_timeout_task_.is_pending());
-  pending_request_ = PendingRequest(peer_address, status_callback);
+  pending_request_ = PendingRequest(peer_address, std::move(status_callback));
 
   auto request = CommandPacket::New(kLECreateConnection,
                                     sizeof(LECreateConnectionCommandParams));
diff --git a/drivers/bluetooth/lib/hci/low_energy_connector.h b/drivers/bluetooth/lib/hci/low_energy_connector.h
index 7d7849d..91e323c 100644
--- a/drivers/bluetooth/lib/hci/low_energy_connector.h
+++ b/drivers/bluetooth/lib/hci/low_energy_connector.h
@@ -49,7 +49,7 @@
   //   - |delegate|: The delegate that will be notified when a new logical link
   //     is established due to an incoming request (remote initiated).
   using IncomingConnectionDelegate =
-      std::function<void(ConnectionPtr connection)>;
+      fit::function<void(ConnectionPtr connection)>;
   LowEnergyConnector(fxl::RefPtr<Transport> hci,
                      async_t* dispatcher,
                      IncomingConnectionDelegate delegate);
@@ -74,7 +74,7 @@
   // |timeout_ms| specifies a time period after which the request will time out.
   // When a request to create connection times out, |status_callback| will be
   // called with a null |link| and a |status| with error Host::Error::kTimedOut.
-  using StatusCallback = std::function<void(Status status, ConnectionPtr link)>;
+  using StatusCallback = fit::function<void(Status status, ConnectionPtr link)>;
   bool CreateConnection(
       LEOwnAddressType own_address_type,
       bool use_whitelist,
@@ -82,7 +82,7 @@
       uint16_t scan_interval,
       uint16_t scan_window,
       const LEPreferredConnectionParameters& initial_parameters,
-      const StatusCallback& status_callback,
+      StatusCallback status_callback,
       int64_t timeout_ms);
 
   // Cancels the currently pending connection attempt.
@@ -99,7 +99,7 @@
   struct PendingRequest {
     PendingRequest() = default;
     PendingRequest(const common::DeviceAddress& peer_address,
-                   const StatusCallback& status_callback);
+                   StatusCallback status_callback);
 
     bool canceled;
     bool timed_out;
diff --git a/drivers/bluetooth/lib/hci/low_energy_scanner.h b/drivers/bluetooth/lib/hci/low_energy_scanner.h
index 969c606..bd4449f 100644
--- a/drivers/bluetooth/lib/hci/low_energy_scanner.h
+++ b/drivers/bluetooth/lib/hci/low_energy_scanner.h
@@ -139,14 +139,14 @@
     // Called when the scan was terminated due to a call to StopScan().
     kStopped,
   };
-  using ScanStatusCallback = std::function<void(ScanStatus)>;
+  using ScanStatusCallback = fit::function<void(ScanStatus)>;
   virtual bool StartScan(bool active,
                          uint16_t scan_interval,
                          uint16_t scan_window,
                          bool filter_duplicates,
                          LEScanFilterPolicy filter_policy,
                          int64_t period_ms,
-                         const ScanStatusCallback& callback) = 0;
+                         ScanStatusCallback callback) = 0;
 
   // Stops a previously started device scan. Returns false if a scan is not in
   // progress. Otherwise, cancels any in progress scan procedure and returns
diff --git a/drivers/bluetooth/lib/hci/sequential_command_runner.cc b/drivers/bluetooth/lib/hci/sequential_command_runner.cc
index 054c17f..dcf5ab8 100644
--- a/drivers/bluetooth/lib/hci/sequential_command_runner.cc
+++ b/drivers/bluetooth/lib/hci/sequential_command_runner.cc
@@ -8,6 +8,8 @@
 #include "hci.h"
 #include "transport.h"
 
+#include "lib/fxl/functional/make_copyable.h"
+
 namespace btlib {
 namespace hci {
 
@@ -28,12 +30,12 @@
 
 void SequentialCommandRunner::QueueCommand(
     std::unique_ptr<CommandPacket> command_packet,
-    const CommandCompleteCallback& callback) {
+    CommandCompleteCallback callback) {
   FXL_DCHECK(!status_callback_);
   FXL_DCHECK(thread_checker_.IsCreationThreadCurrent());
   FXL_DCHECK(sizeof(CommandHeader) <= command_packet->view().size());
 
-  command_queue_.push(std::make_pair(std::move(command_packet), callback));
+  command_queue_.push(std::make_pair(std::move(command_packet), std::move(callback)));
 }
 
 void SequentialCommandRunner::RunCommands(StatusCallback status_callback) {
@@ -76,9 +78,9 @@
   auto next = std::move(command_queue_.front());
   command_queue_.pop();
 
-  command_callback_.Reset(
-      [this, cmd_cb = next.second](CommandChannel::TransactionId,
-                                   const EventPacket& event_packet) {
+  command_callback_.Reset(fxl::MakeCopyable(
+      [this, cmd_cb = std::move(next.second)](CommandChannel::TransactionId,
+                                   const EventPacket& event_packet) mutable {
         auto status = event_packet.ToStatus();
         if (!status) {
           NotifyStatusAndReset(status);
@@ -103,7 +105,7 @@
           // To prevent that we push the current sequence number and |cmd_cb|
           // itself onto the stack.
           uint64_t prev_seq_no = sequence_number_;
-          auto cb = cmd_cb;
+          auto cb = std::move(cmd_cb);
           cb(event_packet);
 
           // The sequence could have been cancelled by |cmd_cb| (and a new
@@ -114,7 +116,7 @@
         }
 
         RunNextQueuedCommand();
-      });
+      }));
 
   if (!transport_->command_channel()->SendCommand(
           std::move(next.first), dispatcher_, command_callback_.callback())) {
diff --git a/drivers/bluetooth/lib/hci/sequential_command_runner.h b/drivers/bluetooth/lib/hci/sequential_command_runner.h
index a055d9e..f912989 100644
--- a/drivers/bluetooth/lib/hci/sequential_command_runner.h
+++ b/drivers/bluetooth/lib/hci/sequential_command_runner.h
@@ -43,10 +43,10 @@
   // completion event to the command sequence. Cannot be called once
   // RunCommands() has been called.
   using CommandCompleteCallback =
-      std::function<void(const EventPacket& command_complete)>;
+      fit::function<void(const EventPacket& command_complete)>;
   void QueueCommand(
       std::unique_ptr<CommandPacket> command_packet,
-      const CommandCompleteCallback& callback = CommandCompleteCallback());
+      CommandCompleteCallback callback = CommandCompleteCallback());
 
   // Runs all the queued commands. Once this is called no new commands can be
   // queued. This method will return before queued commands have been run.
diff --git a/drivers/bluetooth/lib/hci/status.h b/drivers/bluetooth/lib/hci/status.h
index 5906eba..10e9113 100644
--- a/drivers/bluetooth/lib/hci/status.h
+++ b/drivers/bluetooth/lib/hci/status.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <lib/fit/function.h>
+
 #include "garnet/drivers/bluetooth/lib/common/status.h"
 #include "garnet/drivers/bluetooth/lib/hci/hci_constants.h"
 
@@ -43,7 +45,7 @@
   explicit Status(hci::StatusCode proto_code);
 };
 
-using StatusCallback = std::function<void(const Status& status)>;
+using StatusCallback = fit::function<void(const Status& status)>;
 
 }  // namespace hci
 }  // namespace btlib
diff --git a/drivers/bluetooth/lib/hci/transport.cc b/drivers/bluetooth/lib/hci/transport.cc
index 478ad57..e9a04ac 100644
--- a/drivers/bluetooth/lib/hci/transport.cc
+++ b/drivers/bluetooth/lib/hci/transport.cc
@@ -91,14 +91,14 @@
 }
 
 void Transport::SetTransportClosedCallback(
-    const fxl::Closure& callback,
+    fit::closure callback,
     async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
   FXL_DCHECK(!closed_cb_);
   FXL_DCHECK(!closed_cb_dispatcher_);
 
-  closed_cb_ = callback;
+  closed_cb_ = std::move(callback);
   closed_cb_dispatcher_ = dispatcher;
 }
 
@@ -187,7 +187,7 @@
 
   FXL_LOG(INFO) << "hci: Transport: HCI channel(s) were closed";
   if (closed_cb_)
-    async::PostTask(closed_cb_dispatcher_, closed_cb_);
+    async::PostTask(closed_cb_dispatcher_, closed_cb_.share());
 }
 
 }  // namespace hci
diff --git a/drivers/bluetooth/lib/hci/transport.h b/drivers/bluetooth/lib/hci/transport.h
index 6b41ff1..a924429 100644
--- a/drivers/bluetooth/lib/hci/transport.h
+++ b/drivers/bluetooth/lib/hci/transport.h
@@ -95,7 +95,7 @@
   // packet processing is no longer guaranteed to work. It is the responsibility
   // of the callback implementation to clean up this Transport instance by
   // calling ShutDown() and/or deleting it.
-  void SetTransportClosedCallback(const fxl::Closure& callback,
+  void SetTransportClosedCallback(fit::closure callback,
                                   async_t* dispatcher);
 
  private:
@@ -146,7 +146,7 @@
 
   // Callback invoked when the transport is closed (due to a channel error) and
   // its dispatcher.
-  fxl::Closure closed_cb_;
+  fit::closure closed_cb_;
   async_t* closed_cb_dispatcher_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(Transport);
diff --git a/drivers/bluetooth/lib/l2cap/channel.cc b/drivers/bluetooth/lib/l2cap/channel.cc
index b0d7248..e889a0c 100644
--- a/drivers/bluetooth/lib/l2cap/channel.cc
+++ b/drivers/bluetooth/lib/l2cap/channel.cc
@@ -74,7 +74,7 @@
     if (!pending_rx_sdus_.empty()) {
       run_task = true;
       dispatcher = dispatcher_;
-      task = [func = rx_cb_, pending = std::move(pending_rx_sdus_)]() mutable {
+      task = [func = rx_cb_.share(), pending = std::move(pending_rx_sdus_)]() mutable {
         while (!pending.empty()) {
           func(std::move(pending.front()));
           pending.pop();
@@ -199,7 +199,7 @@
     }
 
     dispatcher = dispatcher_;
-    task = [func = rx_cb_, pdu = std::move(pdu)] { func(pdu); };
+    task = [func = rx_cb_.share(), pdu = std::move(pdu)] { func(pdu); };
 
     FXL_DCHECK(rx_cb_);
   }
diff --git a/drivers/bluetooth/lib/l2cap/channel.h b/drivers/bluetooth/lib/l2cap/channel.h
index 7beb7a6..3211395 100644
--- a/drivers/bluetooth/lib/l2cap/channel.h
+++ b/drivers/bluetooth/lib/l2cap/channel.h
@@ -18,7 +18,6 @@
 
 #include "garnet/drivers/bluetooth/lib/hci/connection.h"
 #include "garnet/drivers/bluetooth/lib/l2cap/sdu.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/synchronization/thread_checker.h"
 
@@ -65,7 +64,7 @@
   // Callback invoked when a new SDU is received on this channel. Any previously
   // buffered SDUs will be sent to |rx_cb| right away, provided that |rx_cb| is
   // not empty and the underlying logical link is active.
-  using RxCallback = std::function<void(const SDU& sdu)>;
+  using RxCallback = fit::function<void(const SDU& sdu)>;
 
   // Activates this channel assigning |dispatcher| to execute |rx_callback| and
   // |closed_callback|.
diff --git a/drivers/bluetooth/lib/l2cap/channel_manager.cc b/drivers/bluetooth/lib/l2cap/channel_manager.cc
index 2201f67..ad9a5e9 100644
--- a/drivers/bluetooth/lib/l2cap/channel_manager.cc
+++ b/drivers/bluetooth/lib/l2cap/channel_manager.cc
@@ -58,7 +58,7 @@
 
   auto* ll = RegisterInternal(handle, hci::Connection::LinkType::kLE, role);
   ll->set_error_callback(std::move(link_error_cb), dispatcher);
-  ll->le_signaling_channel()->set_conn_param_update_callback(conn_param_cb,
+  ll->le_signaling_channel()->set_conn_param_update_callback(std::move(conn_param_cb),
                                                              dispatcher);
 }
 
diff --git a/drivers/bluetooth/lib/l2cap/fake_channel.cc b/drivers/bluetooth/lib/l2cap/fake_channel.cc
index 975d3ea..d1c3741 100644
--- a/drivers/bluetooth/lib/l2cap/fake_channel.cc
+++ b/drivers/bluetooth/lib/l2cap/fake_channel.cc
@@ -30,14 +30,14 @@
 
   auto pdu = fragmenter_.BuildBasicFrame(id(), data);
   async::PostTask(dispatcher_,
-                  [cb = rx_cb_, pdu = std::move(pdu)] { cb(pdu); });
+                  [cb = rx_cb_.share(), pdu = std::move(pdu)] { cb(pdu); });
 }
 
-void FakeChannel::SetSendCallback(const SendCallback& callback,
+void FakeChannel::SetSendCallback(SendCallback callback,
                                   async_t* dispatcher) {
   FXL_DCHECK(static_cast<bool>(callback) == static_cast<bool>(dispatcher));
 
-  send_cb_ = callback;
+  send_cb_ = std::move(callback);
   send_dispatcher_ = dispatcher;
 }
 
@@ -67,7 +67,7 @@
 
   dispatcher_ = dispatcher;
   closed_cb_ = std::move(closed_callback);
-  rx_cb_ = rx_callback;
+  rx_cb_ = std::move(rx_callback);
 
   return true;
 }
@@ -82,7 +82,7 @@
   link_error_ = true;
 
   if (link_err_cb_) {
-    async::PostTask(link_err_dispatcher_, link_err_cb_);
+    async::PostTask(link_err_dispatcher_, link_err_cb_.share());
   }
 }
 
@@ -101,7 +101,7 @@
   FXL_DCHECK(send_dispatcher_);
   async::PostTask(
       send_dispatcher_,
-      [cb = send_cb_, sdu = std::move(sdu)]() mutable { cb(std::move(sdu)); });
+      [cb = send_cb_.share(), sdu = std::move(sdu)]() mutable { cb(std::move(sdu)); });
 
   return true;
 }
diff --git a/drivers/bluetooth/lib/l2cap/fake_channel.h b/drivers/bluetooth/lib/l2cap/fake_channel.h
index 2cc6629..369c0af 100644
--- a/drivers/bluetooth/lib/l2cap/fake_channel.h
+++ b/drivers/bluetooth/lib/l2cap/fake_channel.h
@@ -35,8 +35,8 @@
 
   // Sets a delegate to notify when a frame was sent over the channel.
   using SendCallback =
-      std::function<void(std::unique_ptr<const common::ByteBuffer>)>;
-  void SetSendCallback(const SendCallback& callback, async_t* dispatcher);
+      fit::function<void(std::unique_ptr<const common::ByteBuffer>)>;
+  void SetSendCallback(SendCallback callback, async_t* dispatcher);
 
   // Sets a callback to emulate the result of "SignalLinkError()". In
   // production, this callback is invoked by the link. This will be internally
diff --git a/drivers/bluetooth/lib/l2cap/fake_layer.cc b/drivers/bluetooth/lib/l2cap/fake_layer.cc
index aac79cb..1756719 100644
--- a/drivers/bluetooth/lib/l2cap/fake_layer.cc
+++ b/drivers/bluetooth/lib/l2cap/fake_layer.cc
@@ -31,7 +31,7 @@
 
   LinkData& link_data = iter->second;
   async::PostTask(link_data.dispatcher,
-                  [params, cb = link_data.le_conn_param_cb] { cb(params); });
+                  [params, cb = link_data.le_conn_param_cb.share()] { cb(params); });
 }
 
 void FakeLayer::RegisterACL(hci::ConnectionHandle handle,
@@ -92,9 +92,9 @@
     return;
   }
 
-  const auto& link = iter->second;
+  auto& link = iter->second;
   auto chan = fbl::AdoptRef(new FakeChannel(id, handle, iter->second.type));
-  chan->SetLinkErrorCallback(link.link_error_cb, link.dispatcher);
+  chan->SetLinkErrorCallback(link.link_error_cb.share(), link.dispatcher);
 
   async::PostTask(dispatcher, [chan, cb = std::move(callback)] { cb(chan); });
 
diff --git a/drivers/bluetooth/lib/l2cap/l2cap.cc b/drivers/bluetooth/lib/l2cap/l2cap.cc
index 734654e..f84d136 100644
--- a/drivers/bluetooth/lib/l2cap/l2cap.cc
+++ b/drivers/bluetooth/lib/l2cap/l2cap.cc
@@ -48,7 +48,7 @@
                    LinkErrorCallback link_error_callback,
                    async_t* dispatcher) override {
     PostMessage([this, handle, role, lec = std::move(link_error_callback),
-                 dispatcher] {
+                 dispatcher]() mutable {
       if (chanmgr_) {
         chanmgr_->RegisterACL(handle, role, std::move(lec), dispatcher);
       }
@@ -61,7 +61,7 @@
                   LinkErrorCallback link_error_callback,
                   async_t* dispatcher) override {
     PostMessage([this, handle, role, cpc = std::move(conn_param_callback),
-                 lec = std::move(link_error_callback), dispatcher] {
+                 lec = std::move(link_error_callback), dispatcher]() mutable {
       if (chanmgr_) {
         chanmgr_->RegisterLE(handle, role, std::move(cpc), std::move(lec),
                              dispatcher);
diff --git a/drivers/bluetooth/lib/l2cap/l2cap.h b/drivers/bluetooth/lib/l2cap/l2cap.h
index 6946047..50bb335 100644
--- a/drivers/bluetooth/lib/l2cap/l2cap.h
+++ b/drivers/bluetooth/lib/l2cap/l2cap.h
@@ -36,7 +36,7 @@
   using ChannelCallback = fit::function<void(fbl::RefPtr<Channel>)>;
   using LEConnectionParameterUpdateCallback =
       internal::LESignalingChannel::ConnectionParameterUpdateCallback;
-  using LinkErrorCallback = std::function<void()>;  // copyable
+  using LinkErrorCallback = fit::closure;
 
   // Constructs an uninitialized L2CAP object that can be used in production.
   // This spawns a thread on which L2CAP tasks will be scheduled (using
diff --git a/drivers/bluetooth/lib/l2cap/le_signaling_channel.cc b/drivers/bluetooth/lib/l2cap/le_signaling_channel.cc
index c1bbc08..fd8cdae 100644
--- a/drivers/bluetooth/lib/l2cap/le_signaling_channel.cc
+++ b/drivers/bluetooth/lib/l2cap/le_signaling_channel.cc
@@ -87,7 +87,10 @@
              common::BufferView(&rsp, sizeof(rsp)));
 
   if (!reject && dispatcher_) {
-    async::PostTask(dispatcher_, std::bind(conn_param_update_cb_, params));
+    async::PostTask(dispatcher_, [cb = conn_param_update_cb_.share(),
+                                  params = std::move(params)]() mutable {
+      cb(std::move(params));
+    });
   }
 }
 
diff --git a/drivers/bluetooth/lib/l2cap/le_signaling_channel.h b/drivers/bluetooth/lib/l2cap/le_signaling_channel.h
index 978ccbe..fcd67fb 100644
--- a/drivers/bluetooth/lib/l2cap/le_signaling_channel.h
+++ b/drivers/bluetooth/lib/l2cap/le_signaling_channel.h
@@ -17,7 +17,7 @@
 class LESignalingChannel : public SignalingChannel {
  public:
   using ConnectionParameterUpdateCallback =
-      std::function<void(const hci::LEPreferredConnectionParameters& params)>;
+      fit::function<void(const hci::LEPreferredConnectionParameters& params)>;
 
   LESignalingChannel(fbl::RefPtr<Channel> chan, hci::Connection::Role role);
   ~LESignalingChannel() override = default;
diff --git a/drivers/bluetooth/lib/l2cap/logical_link.h b/drivers/bluetooth/lib/l2cap/logical_link.h
index dfa041d..fbd997e 100644
--- a/drivers/bluetooth/lib/l2cap/logical_link.h
+++ b/drivers/bluetooth/lib/l2cap/logical_link.h
@@ -10,6 +10,7 @@
 #include <unordered_map>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 #include <zircon/compiler.h>
 
 #include "garnet/drivers/bluetooth/lib/hci/acl_data_packet.h"
@@ -20,7 +21,6 @@
 #include "garnet/drivers/bluetooth/lib/l2cap/fragmenter.h"
 #include "garnet/drivers/bluetooth/lib/l2cap/l2cap_defs.h"
 #include "garnet/drivers/bluetooth/lib/l2cap/recombiner.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/synchronization/thread_checker.h"
 
diff --git a/drivers/bluetooth/lib/l2cap/pdu.h b/drivers/bluetooth/lib/l2cap/pdu.h
index ec23c04..36446ed 100644
--- a/drivers/bluetooth/lib/l2cap/pdu.h
+++ b/drivers/bluetooth/lib/l2cap/pdu.h
@@ -50,7 +50,7 @@
     //
     // TODO(armansito): Allow jumping to an offset. With that we can remove
     // PDU::Copy() and PDU::ViewFirstFragment().
-    using ReadFunc = std::function<void(const common::ByteBuffer& data)>;
+    using ReadFunc = fit::function<void(const common::ByteBuffer& data)>;
     bool ReadNext(size_t size, const ReadFunc& func);
 
    private:
diff --git a/drivers/bluetooth/lib/l2cap/signaling_channel_unittest.cc b/drivers/bluetooth/lib/l2cap/signaling_channel_unittest.cc
index 6abdb81..53f6b69 100644
--- a/drivers/bluetooth/lib/l2cap/signaling_channel_unittest.cc
+++ b/drivers/bluetooth/lib/l2cap/signaling_channel_unittest.cc
@@ -26,8 +26,8 @@
   }
   ~TestSignalingChannel() override = default;
 
-  using PacketCallback = std::function<void(const SignalingPacket& packet)>;
-  void set_packet_callback(const PacketCallback& cb) { packet_cb_ = cb; }
+  using PacketCallback = fit::function<void(const SignalingPacket& packet)>;
+  void set_packet_callback(PacketCallback cb) { packet_cb_ = std::move(cb); }
 
  private:
   // SignalingChannel override
diff --git a/drivers/bluetooth/lib/sm/BUILD.gn b/drivers/bluetooth/lib/sm/BUILD.gn
new file mode 100644
index 0000000..c7244e2
--- /dev/null
+++ b/drivers/bluetooth/lib/sm/BUILD.gn
@@ -0,0 +1,35 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("definitions") {
+  sources = [
+    "packet.cc",
+    "packet.h",
+    "smp.h",
+  ]
+
+  public_deps = [
+    "//garnet/drivers/bluetooth/lib/common",
+  ]
+}
+
+static_library("sm") {
+  # TODO(armansito): sources
+
+  public_deps = [
+    ":definitions",
+  ]
+}
+
+source_set("tests") {
+  testonly = true
+
+  # TODO(armansito): sources
+
+  deps = [
+    ":sm",
+    "//garnet/drivers/bluetooth/lib/l2cap:testing",
+    "//third_party/googletest:gtest",
+  ]
+}
diff --git a/drivers/bluetooth/lib/sm/packet.cc b/drivers/bluetooth/lib/sm/packet.cc
new file mode 100644
index 0000000..c82e1b7
--- /dev/null
+++ b/drivers/bluetooth/lib/sm/packet.cc
@@ -0,0 +1,20 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "packet.h"
+
+namespace btlib {
+namespace sm {
+
+PacketReader::PacketReader(const common::ByteBuffer* buffer)
+    : common::PacketView<Header>(buffer, buffer->size() - sizeof(Header)) {}
+
+PacketWriter::PacketWriter(Code code, common::MutableByteBuffer* buffer)
+    : common::MutablePacketView<Header>(buffer,
+                                        buffer->size() - sizeof(Header)) {
+  mutable_header()->code = code;
+}
+
+}  // namespace sm
+}  // namespace btlib
diff --git a/drivers/bluetooth/lib/sm/packet.h b/drivers/bluetooth/lib/sm/packet.h
new file mode 100644
index 0000000..8b7aec5
--- /dev/null
+++ b/drivers/bluetooth/lib/sm/packet.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
+#include "garnet/drivers/bluetooth/lib/common/packet_view.h"
+#include "garnet/drivers/bluetooth/lib/sm/smp.h"
+
+namespace btlib {
+namespace sm {
+
+// Utilities for processing SMP packets.
+
+class PacketReader : public common::PacketView<Header> {
+ public:
+  explicit PacketReader(const common::ByteBuffer* buffer);
+  inline Code code() const { return header().code; }
+};
+
+class PacketWriter : public common::MutablePacketView<Header> {
+ public:
+  // Constructor writes |code| into |buffer|.
+  PacketWriter(Code code, common::MutableByteBuffer* buffer);
+};
+
+}  // namespace sm
+}  // namespace btlib
diff --git a/drivers/bluetooth/lib/sm/smp.h b/drivers/bluetooth/lib/sm/smp.h
new file mode 100644
index 0000000..411931a
--- /dev/null
+++ b/drivers/bluetooth/lib/sm/smp.h
@@ -0,0 +1,262 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <cstdint>
+
+#include <zircon/compiler.h>
+
+#include "garnet/drivers/bluetooth/lib/common/device_address.h"
+#include "garnet/drivers/bluetooth/lib/common/uint128.h"
+
+// This file defines constants that are used by the Security Manager Protocol
+// (SMP) that operates over the L2CAP SMP channel.
+
+namespace btlib {
+namespace sm {
+
+// The field that identifies the type of a command.
+using Code = uint8_t;
+
+struct Header {
+  Code code;
+} __PACKED;
+
+enum class IOCapability : uint8_t {
+  kDisplayOnly = 0x00,
+  kDisplayYesNo = 0x01,
+  kKeyboardOnly = 0x02,
+  kNoInputNoOutput = 0x03,
+  kKeyboardDisplay = 0x04,
+};
+
+enum class OOBDataFlag : uint8_t {
+  kNotPresent = 0x00,
+  kPresent = 0x01,
+};
+
+// Possible values that can be assigned to the "AuthReq" bit field (Vol 3, Part
+// H, Figure 3.3).
+enum AuthReq : uint8_t {
+  // Indicates that bonding is requested.
+  kBondingFlag = (1 << 0),
+
+  // Indicates whether Man-in-the-middle protection is required.
+  kMITM = (1 << 2),
+
+  // Indicates whether Secure Connections is supported.
+  kSC = (1 << 3),
+
+  // Indicates whether Keypress notifications should be generated for the
+  // Passkey Entry protocol.
+  kKeypress = (1 << 4),
+
+  // Indicates whether cross-transport key generation is supported for Secure
+  // Connections.
+  kCT2 = (1 << 5),
+};
+using AuthReqField = uint8_t;
+
+// Possible values for the Key Distribution/Generation fields (Vol 3, Part H,
+// Figure 3.11)
+enum KeyDistGen : uint8_t {
+  // LE: Indicates that the LTK will be distributed using the "Encryption
+  // Information" command in LE legacy pairing. Ignored in LE Secure
+  // Connections.
+  //
+  // BR/EDR: Indicates that the LTK will be derived from the BR/EDR Link Key.
+  kEncKey = (1 << 0),
+
+  // Indicates that the IRK will be distributed using the "Identity Information"
+  // command and the Identity Address using the "Identity Address Information"
+  // command.
+  kIdKey = (1 << 1),
+
+  // Indicates that the CSRK will be distributed using the "Signing Information"
+  // command.
+  kSignKey = (1 << 2),
+
+  // LE: Indicates that the BR/EDR Link Key will be derived from the LTK.
+  // Ignored if LE Secure Connections isn't supported.
+  //
+  // BR/EDR: Reserved for future use.
+  kLinkKey = (1 << 3),
+};
+using KeyDistGenField = uint8_t;
+
+// Possible failure reason codes used in the "Pairing Failed" command.
+// (Vol 3, Part H, 3.5.5).
+enum class PairingFailReason : uint8_t {
+  // User input of passkey failed, e.g. due to cancelation.
+  kPasskeyEntryFailed = 0x01,
+
+  // OOB data is not available.
+  kOOBNotAvailable = 0x02,
+
+  // Authentication requirements cannot be met due to IO capabilities.
+  kAuthenticationRequirements = 0x03,
+
+  // The confirm value does not match what was calculated.
+  kConfirmValueFailed = 0x04,
+
+  // Pairing is not supported.
+  kPairingNotSupported = 0x05,
+
+  // The resultant encryption key size is insufficient given local security
+  // requirements.
+  kEncryptionKeySize = 0x06,
+
+  // An SMP command is not supported.
+  kCommandNotSupported = 0x07,
+
+  // Pairing failed due to an unspecified reason.
+  kUnspecifiedReason = 0x08,
+
+  // Pairing/authentication procedure is disallowed because too little time has
+  // elapsed since the last pairing/security request.
+  kRepeatedAttempts = 0x09,
+
+  // SMP command parameters were invalid.
+  kInvalidParameters = 0x0A,
+
+  // Indicates to the remote device that the DHKey Check value received doesn't
+  // match the one calculated locally.
+  kDHKeyCheckFailed = 0x0B,
+
+  // Indicates that the confirm values in the numeric comparison protocol do not
+  // match.
+  kNumericComparisonFailed = 0x0C,
+
+  // Indicates that pairing over the LE transport failed due to a concurrent
+  // pairing request over the BR/EDR transport.
+  kBREDRPairingInProgress = 0x0D,
+
+  // Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot
+  // be used to derive keys for the LE transport.
+  kCrossTransportKeyDerivationNotAllowed = 0x0E,
+};
+
+// Possible keypress notification types used in the "Keypress Notification"
+// command (Vol 3, Part H, 3.5.8).
+enum class KeypressNotificationType : uint8_t {
+  kStarted = 0,
+  kDigitEntered = 1,
+  kDigitErased = 2,
+  kCleared = 3,
+  kCompleted = 4,
+};
+
+// Possible address types used in the "Identity Address Information" command
+// (Vol 3, Part H, 3.6.5).
+enum class AddressType : uint8_t {
+  kPublic = 0x00,
+  kStaticRandom = 0x01,
+};
+
+// ========== SMP PDUs ========
+constexpr Code kInvalidCode = 0x00;
+
+// ======================================
+// Pairing Request (Vol 3, Part H, 3.5.1)
+constexpr Code kPairingRequest = 0x01;
+struct PairingRequestParams {
+  // The local I/O capability.
+  IOCapability io_capability;
+
+  // Whether or not OOB authentication data is available.
+  OOBDataFlag oob_data_flag;
+
+  // The requested security properties (Vol 3, Part H, 2.3.1).
+  AuthReqField auth_req;
+
+  // Maxomum encryption key size supported. Valid values are 7-16.
+  uint8_t max_encryption_key_size;
+
+  // The keys that the initiator requests to distribute/generate.
+  KeyDistGenField initiator_key_dist_gen;
+
+  // The keys that the responder requests to distribute/generate.
+  KeyDistGenField responder_key_dist_gen;
+} __PACKED;
+
+// =======================================
+// Pairing Response (Vol 3, Part H, 3.5.2)
+constexpr Code kPairingResponse = 0x02;
+using PairingResponseParams = PairingRequestParams;
+
+// ======================================
+// Pairing Confirm (Vol 3, Part H, 3.5.3)
+constexpr Code kPairingConfirm = 0x03;
+using PairingConfirmValue = common::UInt128;
+
+// =====================================
+// Pairing Random (Vol 3, Part H, 3.5.4)
+constexpr Code kPairingRandom = 0x04;
+using PairingRandomValue = common::UInt128;
+
+// =====================================
+// Pairing Failed (Vol 3, Part H, 3.5.5)
+constexpr Code kPairingFailed = 0x05;
+
+// See enum PairingFailReason above for parameters.
+
+// =============================================
+// Encryption Information (LE Legacy Pairing only; Vol 3, Part H, 3.6.2)
+constexpr Code kEncryptionInformation = 0x06;
+using LTK = common::UInt128;
+
+// ====================================================================
+// Master Identification (LE Legacy Pairing only; Vol 3, Part H, 3.6.3)
+constexpr Code kMasterIdentification = 0x07;
+struct MasterIdentificationParams {
+  uint16_t ediv;
+  uint64_t rand;
+} __PACKED;
+
+// ===========================================
+// Identity Information (Vol 3, Part H, 3.6.4)
+constexpr Code kIdentityInfo = 0x08;
+using IRK = common::UInt128;
+
+// ===================================================
+// Identity Address Information (Vol 3, Part H, 3.6.5)
+constexpr Code kIdentityAddressInfo = 0x09;
+struct IdentityAddressInfoParams {
+  AddressType type;
+  common::DeviceAddressBytes bd_addr;
+} __PACKED;
+
+// ==========================================
+// Signing Information (Vol 3, Part H, 3.6.6)
+constexpr Code kSigningInfo = 0x0A;
+using CSRK = common::UInt128;
+
+// =======================================
+// Security Request (Vol 3, Part H, 3.6.7)
+constexpr Code kSecurityRequest = 0x0B;
+
+// See enum AuthReq for parameters.
+
+// ==================================================================
+// Pairing Public Key (Secure Connections only; Vol 3, Part H, 3.5.6)
+constexpr Code kPairingPublicKey = 0x0C;
+struct PairingPublicKeyParams {
+  uint8_t x[32];
+  uint8_t y[32];
+} __PACKED;
+
+// ======================================================================
+// Pairing DHKey Check (LE Secure Connections only; Vol 3, Part H, 3.5.7)
+constexpr Code kPairingDHKeyCheck = 0x0D;
+using PairingDHKeyCheckValueE = common::UInt128;
+
+// ============================================
+// Keypress Notification (Vol 3, Part H, 3.5.8)
+constexpr Code kKeypressNotification = 0x0E;
+
+// See enum KeypressNotificationType above for parameters.
+
+}  // namespace sm
+}  // namespace btlib
diff --git a/drivers/bluetooth/lib/testing/fake_controller.cc b/drivers/bluetooth/lib/testing/fake_controller.cc
index b80467d..32b3006 100644
--- a/drivers/bluetooth/lib/testing/fake_controller.cc
+++ b/drivers/bluetooth/lib/testing/fake_controller.cc
@@ -189,42 +189,42 @@
 }
 
 void FakeController::SetScanStateCallback(
-    const ScanStateCallback& callback,
+    ScanStateCallback callback,
     async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
 
-  scan_state_cb_ = callback;
+  scan_state_cb_ = std::move(callback);
   scan_state_cb_dispatcher_ = dispatcher;
 }
 
 void FakeController::SetAdvertisingStateCallback(
-    const fxl::Closure& callback,
+    fit::closure callback,
     async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
 
-  advertising_state_cb_ = callback;
+  advertising_state_cb_ = std::move(callback);
   advertising_state_cb_dispatcher_ = dispatcher;
 }
 
 void FakeController::SetConnectionStateCallback(
-    const ConnectionStateCallback& callback,
+    ConnectionStateCallback callback,
     async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
 
-  conn_state_cb_ = callback;
+  conn_state_cb_ = std::move(callback);
   conn_state_cb_dispatcher_ = dispatcher;
 }
 
 void FakeController::SetLEConnectionParametersCallback(
-    const LEConnectionParametersCallback& callback,
+    LEConnectionParametersCallback callback,
     async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
 
-  le_conn_params_cb_ = callback;
+  le_conn_params_cb_ = std::move(callback);
   le_conn_params_cb_dispatcher_ = dispatcher;
 }
 
@@ -536,7 +536,7 @@
   }
 
   FXL_DCHECK(advertising_state_cb_dispatcher_);
-  async::PostTask(advertising_state_cb_dispatcher_, advertising_state_cb_);
+  async::PostTask(advertising_state_cb_dispatcher_, advertising_state_cb_.share());
 }
 
 void FakeController::NotifyConnectionState(const common::DeviceAddress& addr,
@@ -547,7 +547,7 @@
 
   FXL_DCHECK(conn_state_cb_dispatcher_);
   async::PostTask(conn_state_cb_dispatcher_, [
-    addr, connected, canceled, cb = conn_state_cb_
+    addr, connected, canceled, cb = conn_state_cb_.share()
   ] { cb(addr, connected, canceled); });
 }
 
@@ -559,7 +559,7 @@
 
   FXL_DCHECK(le_conn_params_cb_dispatcher_);
   async::PostTask(le_conn_params_cb_dispatcher_,
-      [addr, params, cb = le_conn_params_cb_] { cb(addr, params); });
+      [addr, params, cb = le_conn_params_cb_.share()] { cb(addr, params); });
 }
 
 void FakeController::OnLECreateConnectionCommandReceived(
@@ -1112,7 +1112,7 @@
       if (scan_state_cb_) {
         FXL_DCHECK(scan_state_cb_dispatcher_);
         async::PostTask(scan_state_cb_dispatcher_, [
-          cb = scan_state_cb_, enabled = le_scan_state_.enabled
+          cb = scan_state_cb_.share(), enabled = le_scan_state_.enabled
         ] { cb(enabled); });
       }
 
diff --git a/drivers/bluetooth/lib/testing/fake_controller.h b/drivers/bluetooth/lib/testing/fake_controller.h
index aeee984..1e95cd0 100644
--- a/drivers/bluetooth/lib/testing/fake_controller.h
+++ b/drivers/bluetooth/lib/testing/fake_controller.h
@@ -11,6 +11,7 @@
 #include <fbl/ref_counted.h>
 #include <fbl/ref_ptr.h>
 #include <lib/async/default.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
 #include "garnet/drivers/bluetooth/lib/common/device_address.h"
@@ -20,7 +21,6 @@
 #include "garnet/drivers/bluetooth/lib/l2cap/l2cap_defs.h"
 #include "garnet/drivers/bluetooth/lib/testing/fake_controller_base.h"
 #include "lib/fxl/functional/cancelable_callback.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/macros.h"
 
@@ -140,27 +140,27 @@
   void AddDevice(std::unique_ptr<FakeDevice> device);
 
   // Sets a callback to be invoked when the scan state changes.
-  using ScanStateCallback = std::function<void(bool enabled)>;
-  void SetScanStateCallback(const ScanStateCallback& callback,
+  using ScanStateCallback = fit::function<void(bool enabled)>;
+  void SetScanStateCallback(ScanStateCallback callback,
                             async_t* dispatcher);
 
   // Sets a callback to be invoked when the LE Advertising state changes.
-  void SetAdvertisingStateCallback(const fxl::Closure& callback,
+  void SetAdvertisingStateCallback(fit::closure callback,
                                    async_t* dispatcher);
 
   // Sets a callback to be invoked on connection events.
-  using ConnectionStateCallback = std::function<
+  using ConnectionStateCallback = fit::function<
       void(const common::DeviceAddress&, bool connected, bool canceled)>;
-  void SetConnectionStateCallback(const ConnectionStateCallback& callback,
+  void SetConnectionStateCallback(ConnectionStateCallback callback,
                                   async_t* dispatcher);
 
   // Sets a callback to be invoked when LE connection parameters are updated for
   // a fake device.
   using LEConnectionParametersCallback =
-      std::function<void(const common::DeviceAddress&,
+      fit::function<void(const common::DeviceAddress&,
                          const hci::LEConnectionParameters&)>;
   void SetLEConnectionParametersCallback(
-      const LEConnectionParametersCallback& callback,
+      LEConnectionParametersCallback callback,
       async_t* dispatcher);
 
   // Sends a HCI event with the given parameters.
@@ -311,7 +311,7 @@
   ScanStateCallback scan_state_cb_;
   async_t* scan_state_cb_dispatcher_;
 
-  fxl::Closure advertising_state_cb_;
+  fit::closure advertising_state_cb_;
   async_t* advertising_state_cb_dispatcher_;
 
   ConnectionStateCallback conn_state_cb_;
diff --git a/drivers/bluetooth/lib/testing/fake_controller_test.h b/drivers/bluetooth/lib/testing/fake_controller_test.h
index c4ac694..1a9d3c6 100644
--- a/drivers/bluetooth/lib/testing/fake_controller_test.h
+++ b/drivers/bluetooth/lib/testing/fake_controller_test.h
@@ -87,8 +87,8 @@
   // InitializeACLDataChannel() must be called once and its data rx handler must
   // not be overridden by tests for |callback| to work.
   void set_data_received_callback(
-      const hci::ACLDataChannel::DataReceivedCallback& callback) {
-    data_received_callback_ = callback;
+       hci::ACLDataChannel::DataReceivedCallback callback) {
+    data_received_callback_ = std::move(callback);
   }
 
   fxl::RefPtr<hci::Transport> transport() const { return transport_; }
diff --git a/drivers/bluetooth/lib/testing/test_controller.cc b/drivers/bluetooth/lib/testing/test_controller.cc
index 4ec3553..6cec17e 100644
--- a/drivers/bluetooth/lib/testing/test_controller.cc
+++ b/drivers/bluetooth/lib/testing/test_controller.cc
@@ -45,26 +45,26 @@
   cmd_transactions_.push(std::move(transaction));
 }
 
-void TestController::SetDataCallback(const DataCallback& callback,
+void TestController::SetDataCallback(DataCallback callback,
                                      async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
   FXL_DCHECK(!data_callback_);
   FXL_DCHECK(!data_dispatcher_);
 
-  data_callback_ = callback;
+  data_callback_ = std::move(callback);
   data_dispatcher_ = dispatcher;
 }
 
 void TestController::SetTransactionCallback(
-    const fxl::Closure& callback,
+    fit::closure callback,
     async_t* dispatcher) {
   FXL_DCHECK(callback);
   FXL_DCHECK(dispatcher);
   FXL_DCHECK(!transaction_callback_);
   FXL_DCHECK(!transaction_dispatcher_);
 
-  transaction_callback_ = callback;
+  transaction_callback_ = std::move(callback);
   transaction_dispatcher_ = dispatcher;
 }
 
@@ -86,7 +86,7 @@
 
   cmd_transactions_.pop();
   if (transaction_callback_)
-    async::PostTask(transaction_dispatcher_, transaction_callback_);
+    async::PostTask(transaction_dispatcher_, transaction_callback_.share());
 }
 
 void TestController::OnACLDataPacketReceived(
@@ -97,7 +97,7 @@
   common::DynamicByteBuffer packet_copy(acl_data_packet);
   async::PostTask(data_dispatcher_,
                   [packet_copy = std::move(packet_copy),
-                   cb = data_callback_]() mutable { cb(packet_copy); });
+                   cb = data_callback_.share()]() mutable { cb(packet_copy); });
 }
 
 }  // namespace testing
diff --git a/drivers/bluetooth/lib/testing/test_controller.h b/drivers/bluetooth/lib/testing/test_controller.h
index 20ce726..dc15adf 100644
--- a/drivers/bluetooth/lib/testing/test_controller.h
+++ b/drivers/bluetooth/lib/testing/test_controller.h
@@ -8,10 +8,11 @@
 #include <vector>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
+
 #include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
 #include "garnet/drivers/bluetooth/lib/hci/hci.h"
 #include "garnet/drivers/bluetooth/lib/testing/fake_controller_base.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
 namespace btlib {
@@ -57,11 +58,11 @@
   void QueueCommandTransaction(CommandTransaction transaction);
 
   // Callback to invoke when a packet is received over the data channel.
-  using DataCallback = std::function<void(const common::ByteBuffer& packet)>;
-  void SetDataCallback(const DataCallback& callback, async_t* dispatcher);
+  using DataCallback = fit::function<void(const common::ByteBuffer& packet)>;
+  void SetDataCallback(DataCallback callback, async_t* dispatcher);
 
   // Callback invoked when a transaction completes.
-  void SetTransactionCallback(const fxl::Closure& callback,
+  void SetTransactionCallback(fit::closure callback,
                               async_t* dispatcher);
 
  private:
@@ -74,7 +75,7 @@
   std::queue<CommandTransaction> cmd_transactions_;
   DataCallback data_callback_;
   async_t* data_dispatcher_;
-  fxl::Closure transaction_callback_;
+  fit::closure transaction_callback_;
   async_t* transaction_dispatcher_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(TestController);
diff --git a/drivers/gpu/msd-arm-mali/tests/integration/BUILD.gn b/drivers/gpu/msd-arm-mali/tests/integration/BUILD.gn
index ed34563..53b1d09 100644
--- a/drivers/gpu/msd-arm-mali/tests/integration/BUILD.gn
+++ b/drivers/gpu/msd-arm-mali/tests/integration/BUILD.gn
@@ -22,7 +22,7 @@
   ]
 
   public_deps = [
-    "//garnet/lib/magma:libmagma",
+    "//garnet/lib/magma/src/libmagma",
     "//garnet/lib/magma/include:magma_abi",
     "//garnet/lib/magma/src/magma_util",
     "//garnet/lib/magma/tests/helper:platform_device_helper",
diff --git a/drivers/gpu/msd-intel-gen/tests/integration/BUILD.gn b/drivers/gpu/msd-intel-gen/tests/integration/BUILD.gn
index ac74ff6..00063a2 100644
--- a/drivers/gpu/msd-intel-gen/tests/integration/BUILD.gn
+++ b/drivers/gpu/msd-intel-gen/tests/integration/BUILD.gn
@@ -22,7 +22,7 @@
   ]
 
   public_deps = [
-    "$magma_build_root:libmagma",
+    "$magma_build_root/src/libmagma",
     "$magma_build_root/include:magma_abi",
     "$magma_build_root/src/magma_util",
     "//third_party/googletest:gtest",
diff --git a/drivers/video/amlogic-decoder/BUILD.gn b/drivers/video/amlogic-decoder/BUILD.gn
index 1cbbd96..e359fb0 100644
--- a/drivers/video/amlogic-decoder/BUILD.gn
+++ b/drivers/video/amlogic-decoder/BUILD.gn
@@ -5,12 +5,34 @@
 import("//build/config/fuchsia/rules.gni")
 import("//build/package.gni")
 
+declare_args() {
+  amlogic_decoder_tests = false
+}
+
 driver_module("amlogic_decoder") {
   output_name = "amlogic_video_decoder"
 
   deps = [
     ":sources",
   ]
+  if (amlogic_decoder_tests) {
+    testonly = true
+    deps += [ ":tests" ]
+  }
+}
+
+config("sources_include_config") {
+  include_dirs = [ "." ]
+}
+
+source_set("test_support") {
+  deps = [
+    "//zircon/public/lib/ddk",
+    "//zircon/public/lib/driver",
+  ]
+  sources = [
+    "tests/test_support.h",
+  ]
 }
 
 source_set("sources") {
@@ -30,6 +52,27 @@
     "//zircon/public/lib/hwreg",
     "//zircon/public/lib/zx",
   ]
+  deps = [
+    ":test_support",
+  ]
+  if (amlogic_decoder_tests) {
+    testonly = true
+    defines = [ "ENABLE_DECODER_TESTS" ]
+  }
+  public_configs = [ ":sources_include_config" ]
+}
+
+source_set("tests") {
+  testonly = true
+  deps = [
+    ":test_support",
+    ":sources",
+    "//third_party/googletest:gtest",
+  ]
+  sources = [
+    "tests/test_support.cc",
+    "tests/unit_tests/test_binding.cc",
+  ]
 }
 
 copy("video-ucode") {
@@ -43,6 +86,11 @@
 
 package("amlogic_video_decoder") {
   deprecated_system_image = true
+
+  if (amlogic_decoder_tests) {
+    testonly = true
+  }
+
   deps = [
     ":amlogic_decoder",
     ":video-ucode($shlib_toolchain)",
diff --git a/drivers/video/amlogic-decoder/amlogic-video.cc b/drivers/video/amlogic-decoder/amlogic-video.cc
index b8c1b42..c9d0485 100644
--- a/drivers/video/amlogic-decoder/amlogic-video.cc
+++ b/drivers/video/amlogic-decoder/amlogic-video.cc
@@ -25,6 +25,10 @@
 #include "macros.h"
 #include "registers.h"
 
+#if ENABLE_DECODER_TESTS
+#include "tests/test_support.h"
+#endif
+
 extern "C" {
 zx_status_t amlogic_video_bind(void* ctx, zx_device_t* parent);
 }
@@ -170,7 +174,7 @@
   DosSwReset0::Get().FromValue(1 << 4).WriteTo(dosbus_.get());
   DosSwReset0::Get().FromValue(0).WriteTo(dosbus_.get());
 
-  Reset0Register::Get().ReadFrom(cbus_.get());
+  Reset0Register::Get().ReadFrom(reset_.get());
   PowerCtlVld::Get().FromValue(1 << 4).WriteTo(dosbus_.get());
   uint32_t buffer_address =
       static_cast<uint32_t>(io_buffer_phys(&stream_buffer_));
@@ -203,15 +207,34 @@
   return ZX_OK;
 }
 
-zx_status_t AmlogicVideo::Init(zx_device_t* parent) {
+zx_status_t AmlogicVideo::InitRegisters(zx_device_t* parent) {
   parent_ = parent;
 
   zx_status_t status =
       device_get_protocol(parent_, ZX_PROTOCOL_PLATFORM_DEV, &pdev_);
+
   if (status != ZX_OK) {
     DECODE_ERROR("Failed to get parent protocol");
     return ZX_ERR_NO_MEMORY;
   }
+  pdev_device_info_t info;
+  status = pdev_get_device_info(&pdev_, &info);
+  if (status != ZX_OK) {
+    DECODE_ERROR("pdev_get_device_info failed");
+    return status;
+  }
+  switch (info.pid) {
+    case PDEV_PID_AMLOGIC_S912:
+      device_type_ = DeviceType::kGXM;
+      break;
+    case PDEV_PID_AMLOGIC_S905D2:
+      device_type_ = DeviceType::kG12A;
+      break;
+    default:
+      DECODE_ERROR("Unknown soc pid: %d\n", info.pid);
+      return ZX_ERR_INVALID_ARGS;
+  }
+
   status = pdev_map_mmio_buffer(&pdev_, kCbus, ZX_CACHE_POLICY_UNCACHED_DEVICE,
                                 &mmio_cbus_);
   if (status != ZX_OK) {
@@ -265,6 +288,14 @@
   aobus_ = std::make_unique<AoRegisterIo>(io_buffer_virt(&mmio_aobus_));
   dmc_ = std::make_unique<DmcRegisterIo>(io_buffer_virt(&mmio_dmc_));
 
+  int64_t reset_register_offset = 0;
+  if (device_type_ == DeviceType::kG12A) {
+    // Some portions of the cbus moved in newer versions (TXL and later).
+    reset_register_offset = (0x0401 - 0x1101);
+  }
+  auto cbus_base = static_cast<volatile uint32_t*>(io_buffer_virt(&mmio_cbus_));
+  reset_ = std::make_unique<ResetRegisterIo>(cbus_base + reset_register_offset);
+
   firmware_ = std::make_unique<FirmwareBlob>();
   status = firmware_->LoadFirmware(parent_);
   if (status != ZX_OK) {
@@ -272,10 +303,28 @@
     return status;
   }
 
+  return ZX_OK;
+}
+
+zx_status_t AmlogicVideo::Bind() {
+  device_add_args_t vc_video_args = {};
+  vc_video_args.version = DEVICE_ADD_ARGS_VERSION;
+  vc_video_args.name = "amlogic_video";
+  vc_video_args.ctx = this;
+  vc_video_args.ops = &amlogic_video_device_ops;
+
+  zx_status_t status = device_add(parent_, &vc_video_args, &device_);
+  if (status != ZX_OK) {
+    DECODE_ERROR("Failed to bind device");
+    return ZX_ERR_NO_MEMORY;
+  }
+  return ZX_OK;
+}
+
+zx_status_t AmlogicVideo::InitDecoder() {
   EnableVideoPower();
-  status = InitializeStreamBuffer();
-  if (status != ZX_OK)
-    return status;
+  zx_status_t status = InitializeStreamBuffer();
+  if (status != ZX_OK) return status;
 
   {
     uint8_t* firmware_data;
@@ -290,31 +339,37 @@
     if (status != ZX_OK)
       return status;
   }
-  device_add_args_t vc_video_args = {};
-  vc_video_args.version = DEVICE_ADD_ARGS_VERSION;
-  vc_video_args.name = "amlogic_video";
-  vc_video_args.ctx = this;
-  vc_video_args.ops = &amlogic_video_device_ops;
-
-  status = device_add(parent_, &vc_video_args, &device_);
-  if (status != ZX_OK) {
-    DECODE_ERROR("Failed to bind device");
-    return ZX_ERR_NO_MEMORY;
-  }
   return ZX_OK;
 }
 
 zx_status_t amlogic_video_bind(void* ctx, zx_device_t* parent) {
+#if ENABLE_DECODER_TESTS
+  TestSupport::set_parent_device(parent);
+  TestSupport::RunAllTests();
+#endif
+
   auto video = std::make_unique<AmlogicVideo>();
   if (!video) {
     DECODE_ERROR("Failed to create AmlogicVideo");
     return ZX_ERR_NO_MEMORY;
   }
 
-  zx_status_t status = video->Init(parent);
+  zx_status_t status = video->InitRegisters(parent);
   if (status != ZX_OK) {
-    DECODE_ERROR("Failed to initialize AmlogicVideo");
-    return ZX_ERR_NO_MEMORY;
+    DECODE_ERROR("Failed to initialize registers");
+    return status;
+  }
+
+  status = video->InitDecoder();
+  if (status != ZX_OK) {
+    DECODE_ERROR("Failed to initialize decoder");
+    return status;
+  }
+
+  status = video->Bind();
+  if (status != ZX_OK) {
+    DECODE_ERROR("Failed to bind device");
+    return status;
   }
 
   video.release();
diff --git a/drivers/video/amlogic-decoder/amlogic-video.h b/drivers/video/amlogic-decoder/amlogic-video.h
index 23d4056..e3826bc 100644
--- a/drivers/video/amlogic-decoder/amlogic-video.h
+++ b/drivers/video/amlogic-decoder/amlogic-video.h
@@ -22,9 +22,17 @@
 
 class AmlogicVideo {
  public:
+  enum class DeviceType {
+    kUnknown,
+    kGXM,   // S912
+    kG12A,  // S905D2
+  };
+
   ~AmlogicVideo();
 
-  zx_status_t Init(zx_device_t* parent);
+  zx_status_t InitRegisters(zx_device_t* parent);
+  zx_status_t InitDecoder();
+  zx_status_t Bind();
 
   zx_status_t LoadDecoderFirmware(uint8_t* data, uint32_t size);
 
@@ -36,6 +44,7 @@
   zx_device_t* parent_ = nullptr;
   zx_device_t* device_ = nullptr;
   platform_device_protocol_t pdev_;
+  DeviceType device_type_ = DeviceType::kUnknown;
   io_buffer_t mmio_cbus_ = {};
   io_buffer_t mmio_dosbus_ = {};
   io_buffer_t mmio_hiubus_ = {};
@@ -46,6 +55,7 @@
   std::unique_ptr<HiuRegisterIo> hiubus_;
   std::unique_ptr<AoRegisterIo> aobus_;
   std::unique_ptr<DmcRegisterIo> dmc_;
+  std::unique_ptr<ResetRegisterIo> reset_;
 
   std::unique_ptr<FirmwareBlob> firmware_;
 
diff --git a/drivers/video/amlogic-decoder/binding.c b/drivers/video/amlogic-decoder/binding.c
index fa3e964..b1e17e3 100644
--- a/drivers/video/amlogic-decoder/binding.c
+++ b/drivers/video/amlogic-decoder/binding.c
@@ -20,6 +20,5 @@
 ZIRCON_DRIVER_BEGIN(amlogic_video, amlogic_video_driver_ops, "zircon", "0.1", 4)
 BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PLATFORM_DEV),
     BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_AMLOGIC),
-    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_AMLOGIC_S912),
     BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_AMLOGIC_VIDEO),
     ZIRCON_DRIVER_END(amlogic_video)
diff --git a/drivers/video/amlogic-decoder/registers.h b/drivers/video/amlogic-decoder/registers.h
index 434c257..bb0a018 100644
--- a/drivers/video/amlogic-decoder/registers.h
+++ b/drivers/video/amlogic-decoder/registers.h
@@ -76,6 +76,11 @@
   DmcRegisterIo(volatile void* mmio) : hwreg::RegisterIo(mmio) {}
 };
 
+class ResetRegisterIo : public hwreg::RegisterIo {
+ public:
+  ResetRegisterIo(volatile void* mmio) : hwreg::RegisterIo(mmio) {}
+};
+
 #define DEFINE_REGISTER(name, type, address)                           \
   class name : public TypedRegisterBase<type, name, uint32_t> {        \
    public:                                                             \
@@ -151,7 +156,7 @@
   DEF_BIT(13, vdec);
 };
 
-DEFINE_REGISTER(Reset0Register, CbusRegisterIo, 0x1101);
+DEFINE_REGISTER(Reset0Register, ResetRegisterIo, 0x1101);
 
 // clang-format on
 
diff --git a/drivers/video/amlogic-decoder/tests/test_support.cc b/drivers/video/amlogic-decoder/tests/test_support.cc
new file mode 100644
index 0000000..4cc7e50
--- /dev/null
+++ b/drivers/video/amlogic-decoder/tests/test_support.cc
@@ -0,0 +1,22 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gtest/gtest.h"
+
+#include "test_support.h"
+
+static zx_device_t* g_parent_device;
+
+zx_device_t* TestSupport::parent_device() { return g_parent_device; }
+
+void TestSupport::set_parent_device(zx_device_t* handle) {
+  g_parent_device = handle;
+}
+
+void TestSupport::RunAllTests() {
+  const int kArgc = 1;
+  const char* argv[kArgc] = {"test_support"};
+  testing::InitGoogleTest(const_cast<int*>(&kArgc), const_cast<char**>(argv));
+  (void)RUN_ALL_TESTS();
+}
diff --git a/drivers/video/amlogic-decoder/tests/test_support.h b/drivers/video/amlogic-decoder/tests/test_support.h
new file mode 100644
index 0000000..1bd36d3
--- /dev/null
+++ b/drivers/video/amlogic-decoder/tests/test_support.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TEST_SUPPORT_H_
+#define TEST_SUPPORT_H_
+
+#include <ddk/device.h>
+
+#include <zircon/errors.h>
+#include <zircon/syscalls.h>
+
+class TestSupport {
+ public:
+  static zx_device_t* parent_device();
+
+  static void set_parent_device(zx_device_t* handle);
+
+  static void RunAllTests();
+};
+
+#endif  // TEST_SUPPORT_H_
diff --git a/drivers/video/amlogic-decoder/tests/unit_tests/test_binding.cc b/drivers/video/amlogic-decoder/tests/unit_tests/test_binding.cc
new file mode 100644
index 0000000..7afc116
--- /dev/null
+++ b/drivers/video/amlogic-decoder/tests/unit_tests/test_binding.cc
@@ -0,0 +1,17 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "amlogic-video.h"
+#include "gtest/gtest.h"
+#include "tests/test_support.h"
+
+TEST(Binding, Destruction) {
+  auto video = std::make_unique<AmlogicVideo>();
+  ASSERT_TRUE(video);
+
+  zx_status_t status = video->InitRegisters(TestSupport::parent_device());
+  EXPECT_EQ(ZX_OK, status);
+
+  video.reset();
+}
diff --git a/drivers/wlan/lib/BUILD.gn b/drivers/wlan/lib/BUILD.gn
index fafab3e..a49b5c4 100644
--- a/drivers/wlan/lib/BUILD.gn
+++ b/drivers/wlan/lib/BUILD.gn
@@ -17,6 +17,7 @@
 
   public_deps = [
     "//garnet/public/lib/fidl/cpp",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/drivers/wlan/lib/include/wlan/async/dispatcher.h b/drivers/wlan/lib/include/wlan/async/dispatcher.h
index 0ee8846..d24f3a8 100644
--- a/drivers/wlan/lib/include/wlan/async/dispatcher.h
+++ b/drivers/wlan/lib/include/wlan/async/dispatcher.h
@@ -4,12 +4,13 @@
 
 #pragma once
 
-#include <functional>
+#include <mutex>
+
 #include <lib/async/cpp/task.h>
 #include <lib/async/dispatcher.h>
 #include <lib/async/task.h>
 #include <lib/fidl/cpp/thread_safe_binding_set.h>
-#include <mutex>
+#include <lib/fit/function.h>
 #include <zx/channel.h>
 #include <zx/time.h>
 
@@ -39,7 +40,7 @@
     //
     // If |InitiateShutdown| has been already called previously,
     // then it returns immediately, and |ready_callback| is ignored.
-    void InitiateShutdown(std::function<void()> ready_callback) {
+    void InitiateShutdown(fit::closure ready_callback) {
         {
             std::lock_guard<std::mutex> guard(lock_);
             if (shutdown_initiated_) {
diff --git a/drivers/wlan/mediatek/ralink/BUILD.gn b/drivers/wlan/mediatek/ralink/BUILD.gn
index c248805..5f7b9df 100644
--- a/drivers/wlan/mediatek/ralink/BUILD.gn
+++ b/drivers/wlan/mediatek/ralink/BUILD.gn
@@ -29,6 +29,7 @@
     "//zircon/public/lib/async-loop-cpp",
     "//zircon/public/lib/driver",
     "//zircon/public/lib/fbl",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/sync",
     "//zircon/public/lib/zx",
   ]
diff --git a/drivers/wlan/mediatek/ralink/device.cpp b/drivers/wlan/mediatek/ralink/device.cpp
index 9070c7e..48d2fa1 100644
--- a/drivers/wlan/mediatek/ralink/device.cpp
+++ b/drivers/wlan/mediatek/ralink/device.cpp
@@ -79,6 +79,8 @@
 
 namespace ralink {
 
+namespace wlan_device = ::fuchsia::wlan::device;
+
 #define DEV(c) static_cast<Device*>(c)
 static zx_protocol_device_t wlanphy_device_ops = {
     .version = DEVICE_OPS_VERSION,
diff --git a/drivers/wlan/mediatek/ralink/device.h b/drivers/wlan/mediatek/ralink/device.h
index dfb68de..2238c60 100644
--- a/drivers/wlan/mediatek/ralink/device.h
+++ b/drivers/wlan/mediatek/ralink/device.h
@@ -8,17 +8,17 @@
 #include <ddk/usb-request.h>
 #include <driver/usb.h>
 #include <fbl/unique_ptr.h>
+#include <lib/fit/function.h>
 #include <lib/zx/time.h>
 #include <wlan/async/dispatcher.h>
 #include <wlan/protocol/mac.h>
 #include <zircon/compiler.h>
 
-#include <wlan_device/cpp/fidl.h>
+#include <fuchsia/wlan/device/cpp/fidl.h>
 
 #include <array>
 #include <cstddef>
 #include <cstdint>
-#include <functional>
 #include <map>
 #include <mutex>
 #include <thread>
@@ -54,7 +54,7 @@
     void* cookie_;
 };
 
-class Device : public wlan_device::Phy {
+class Device : public ::fuchsia::wlan::device::Phy {
    public:
     Device(zx_device_t* device, usb_protocol_t usb, uint8_t bulk_in,
            std::vector<uint8_t>&& bulk_out);
@@ -82,9 +82,9 @@
     zx_status_t WlanmacSetKey(uint32_t options, wlan_key_config_t* key_config);
 
     virtual void Query(QueryCallback callback) override;
-    virtual void CreateIface(wlan_device::CreateIfaceRequest req,
+    virtual void CreateIface(::fuchsia::wlan::device::CreateIfaceRequest req,
                              CreateIfaceCallback callback) override;
-    virtual void DestroyIface(wlan_device::DestroyIfaceRequest req,
+    virtual void DestroyIface(::fuchsia::wlan::device::DestroyIfaceRequest req,
                               DestroyIfaceCallback callback) override;
 
    private:
@@ -251,7 +251,7 @@
     std::mutex lock_;
     bool dead_ __TA_GUARDED(lock_) = false;
     fbl::unique_ptr<WlanmacIfcProxy> wlanmac_proxy_ __TA_GUARDED(lock_);
-    wlan::async::Dispatcher<wlan_device::Phy> dispatcher_;
+    wlan::async::Dispatcher<::fuchsia::wlan::device::Phy> dispatcher_;
 
     constexpr static size_t kEepromSize = 0x0100;
     std::array<uint16_t, kEepromSize> eeprom_ = {};
diff --git a/drivers/wlan/testing/phy-device.cpp b/drivers/wlan/testing/phy-device.cpp
index 1e48185..9eeff59 100644
--- a/drivers/wlan/testing/phy-device.cpp
+++ b/drivers/wlan/testing/phy-device.cpp
@@ -17,6 +17,8 @@
 namespace wlan {
 namespace testing {
 
+namespace wlan_device = ::fuchsia::wlan::device;
+
 #define DEV(c) static_cast<PhyDevice*>(c)
 static zx_protocol_device_t wlanphy_test_device_ops = {
     .version = DEVICE_OPS_VERSION,
diff --git a/drivers/wlan/testing/phy-device.h b/drivers/wlan/testing/phy-device.h
index a94f06d..83d7134 100644
--- a/drivers/wlan/testing/phy-device.h
+++ b/drivers/wlan/testing/phy-device.h
@@ -9,7 +9,7 @@
 #include <wlan/async/dispatcher.h>
 #include <zircon/types.h>
 
-#include <wlan_device/cpp/fidl.h>
+#include <fuchsia/wlan/device/cpp/fidl.h>
 
 #include <memory>
 #include <mutex>
@@ -20,7 +20,7 @@
 
 class IfaceDevice;
 
-class PhyDevice : public wlan_device::Phy {
+class PhyDevice : public ::fuchsia::wlan::device::Phy {
    public:
     PhyDevice(zx_device_t* device);
     virtual ~PhyDevice() = default;
@@ -33,9 +33,9 @@
                          size_t out_len, size_t* out_actual);
 
     virtual void Query(QueryCallback callback) override;
-    virtual void CreateIface(wlan_device::CreateIfaceRequest req,
+    virtual void CreateIface(::fuchsia::wlan::device::CreateIfaceRequest req,
                              CreateIfaceCallback callback) override;
-    virtual void DestroyIface(wlan_device::DestroyIfaceRequest req,
+    virtual void DestroyIface(::fuchsia::wlan::device::DestroyIfaceRequest req,
                               DestroyIfaceCallback callback) override;
 
    private:
@@ -45,7 +45,7 @@
     zx_device_t* parent_;
 
     std::mutex lock_;
-    std::unique_ptr<wlan::async::Dispatcher<wlan_device::Phy>> dispatcher_;
+    std::unique_ptr<wlan::async::Dispatcher<::fuchsia::wlan::device::Phy>> dispatcher_;
     std::unordered_map<uint16_t, IfaceDevice*> ifaces_;
     // Next available Iface id. Must be checked against the map to prevent overwriting an existing
     // IfaceDevice pointer in the map.
diff --git a/drivers/wlan/testing/util/src/main.rs b/drivers/wlan/testing/util/src/main.rs
index 0ff23ef..5821d84 100644
--- a/drivers/wlan/testing/util/src/main.rs
+++ b/drivers/wlan/testing/util/src/main.rs
@@ -9,7 +9,7 @@
 #[macro_use]
 extern crate fdio;
 extern crate fidl;
-extern crate fidl_wlan_device as wlan;
+extern crate fidl_fuchsia_wlan_device as wlan;
 extern crate fuchsia_async as async;
 extern crate fuchsia_wlan_dev as wlan_dev;
 extern crate futures;
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/BUILD.gn b/drivers/wlan/third_party/broadcom/brcmfmac/BUILD.gn
index 2a10474..90fc1a4 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/BUILD.gn
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/BUILD.gn
@@ -94,6 +94,7 @@
     "//zircon/public/lib/driver",
     "//zircon/public/lib/sync",
     "//zircon/public/lib/zx",
+    "//zircon/public/lib/async-loop",
   ]
 
   configs += [ "//build/config/fuchsia:enable_zircon_asserts" ]
@@ -127,6 +128,9 @@
     "//zircon/public/lib/fbl",
     "//zircon/public/lib/sync",
     "//zircon/public/lib/zx",
+    "//zircon/public/lib/fbl",
+    "//third_party/googletest:gtest_main",
+    "//zircon/public/lib/async-loop",
   ]
 }
 
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/btcoex.c b/drivers/wlan/third_party/broadcom/brcmfmac/btcoex.c
index a890cce..5b00d8d 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/btcoex.c
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/btcoex.c
@@ -89,7 +89,7 @@
  */
 struct brcmf_btcoex_info {
     struct brcmf_cfg80211_vif* vif;
-    struct timer_list timer;
+    brcmf_timer_info_t timer;
     uint16_t timeout;
     bool timer_on;
     bool dhcp_done;
@@ -266,9 +266,9 @@
 /**
  * brcmf_btcoex_timerfunc() - BT coex timer callback
  */
-static void brcmf_btcoex_timerfunc(struct timer_list* t) {
+static void brcmf_btcoex_timerfunc(void* data) {
     pthread_mutex_lock(&irq_callback_lock);
-    struct brcmf_btcoex_info* bt_local = from_timer(bt_local, t, timer);
+    struct brcmf_btcoex_info* bt_local = data;
     brcmf_dbg(TRACE, "enter\n");
 
     bt_local->timer_on = false;
@@ -285,7 +285,7 @@
     btci = container_of(work, struct brcmf_btcoex_info, work);
     if (btci->timer_on) {
         btci->timer_on = false;
-        del_timer_sync(&btci->timer);
+        brcmf_timer_stop(&btci->timer);
     }
 
     switch (btci->bt_state) {
@@ -296,11 +296,11 @@
         brcmf_dbg(INFO, "DHCP started\n");
         btci->bt_state = BRCMF_BT_DHCP_OPPR_WIN;
         if (btci->timeout < BRCMF_BTCOEX_OPPR_WIN_TIME_MSEC) {
-            mod_timer(&btci->timer, btci->timer.expires);
+            // TODO(cphoenix): Was btci->timer.expires which wasn't set anywhere
+            brcmf_timer_set(&btci->timer, btci->timeout);
         } else {
             btci->timeout -= BRCMF_BTCOEX_OPPR_WIN_TIME_MSEC;
-            mod_timer(&btci->timer,
-                      zx_clock_get(ZX_CLOCK_MONOTONIC) + ZX_MSEC(BRCMF_BTCOEX_OPPR_WIN_TIME_MSEC));
+            brcmf_timer_set(&btci->timer, ZX_MSEC(BRCMF_BTCOEX_OPPR_WIN_TIME_MSEC));
         }
         btci->timer_on = true;
         break;
@@ -316,7 +316,7 @@
         brcmf_btcoex_boost_wifi(btci, true);
 
         btci->bt_state = BRCMF_BT_DHCP_FLAG_FORCE_TIMEOUT;
-        mod_timer(&btci->timer, zx_clock_get(ZX_CLOCK_MONOTONIC) + ZX_MSEC(btci->timeout));
+        brcmf_timer_set(&btci->timer, ZX_MSEC(btci->timeout));
         btci->timer_on = true;
         break;
 
@@ -365,7 +365,7 @@
     /* Set up timer for BT  */
     btci->timer_on = false;
     btci->timeout = BRCMF_BTCOEX_OPPR_WIN_TIME_MSEC;
-    timer_setup(&btci->timer, brcmf_btcoex_timerfunc, 0);
+    brcmf_timer_init(&btci->timer, brcmf_btcoex_timerfunc);
     btci->cfg = cfg;
     btci->saved_regs_part1 = false;
     btci->saved_regs_part2 = false;
@@ -389,7 +389,7 @@
 
     if (cfg->btcoex->timer_on) {
         cfg->btcoex->timer_on = false;
-        del_timer_sync(&cfg->btcoex->timer);
+        brcmf_timer_stop(&cfg->btcoex->timer);
     }
 
     workqueue_cancel_work(&cfg->btcoex->work);
@@ -421,7 +421,7 @@
     if (btci->timer_on) {
         brcmf_dbg(INFO, "disable BT DHCP Timer\n");
         btci->timer_on = false;
-        del_timer_sync(&btci->timer);
+        brcmf_timer_stop(&btci->timer);
 
         /* schedule worker if transition to IDLE is needed */
         if (btci->bt_state != BRCMF_BT_DHCP_IDLE) {
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.c b/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.c
index 258e9dc..22698fb 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.c
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.c
@@ -711,9 +711,8 @@
     scan_request = cfg->scan_request;
     cfg->scan_request = NULL;
 
-    if (timer_pending(&cfg->escan_timeout)) {
-        del_timer_sync(&cfg->escan_timeout);
-    }
+    // Canceling if it's inactive is OK. Checking if it's active just invites race conditions.
+    brcmf_timer_stop(&cfg->escan_timeout);
 
     if (fw_abort) {
         /* Do a scan abort to stop the driver's scan engine */
@@ -1119,8 +1118,7 @@
     }
 
     /* Arm scan timeout timer */
-    mod_timer(&cfg->escan_timeout,
-              zx_clock_get(ZX_CLOCK_MONOTONIC) + ZX_MSEC(BRCMF_ESCAN_TIMER_INTERVAL_MS));
+    brcmf_timer_set(&cfg->escan_timeout, ZX_MSEC(BRCMF_ESCAN_TIMER_INTERVAL_MS));
 
     return ZX_OK;
 
@@ -2942,9 +2940,9 @@
     brcmf_notify_escan_complete(cfg, cfg->escan_info.ifp, true, true);
 }
 
-static void brcmf_escan_timeout(struct timer_list* t) {
+static void brcmf_escan_timeout(void* data) {
     pthread_mutex_lock(&irq_callback_lock);
-    struct brcmf_cfg80211_info* cfg = from_timer(cfg, t, escan_timeout);
+    struct brcmf_cfg80211_info* cfg = data;
 
     if (cfg->int_escan_map || cfg->scan_request) {
         brcmf_err("timer expired\n");
@@ -3097,7 +3095,7 @@
     brcmf_fweh_register(cfg->pub, BRCMF_E_ESCAN_RESULT, brcmf_cfg80211_escan_handler);
     cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
     /* Init scan_timeout timer */
-    timer_setup(&cfg->escan_timeout, brcmf_escan_timeout, 0);
+    brcmf_timer_init(&cfg->escan_timeout, brcmf_escan_timeout);
     workqueue_init_work(&cfg->escan_timeout_work, brcmf_cfg80211_escan_timeout_worker);
 }
 
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.h b/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.h
index ae9b99d..8cd2c7c 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.h
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/cfg80211.h
@@ -327,7 +327,7 @@
     uint8_t* extra_buf;
     struct dentry* debugfsdir;
     struct escan_info escan_info;
-    struct timer_list escan_timeout;
+    brcmf_timer_info_t escan_timeout;
     struct work_struct escan_timeout_work;
     struct list_head vif_list;
     struct brcmf_cfg80211_vif_event vif_event;
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/common.c b/drivers/wlan/third_party/broadcom/brcmfmac/common.c
index af85dc2..955e894 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/common.c
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/common.c
@@ -500,12 +500,27 @@
     }
 };
 
+static async_loop_t* async_loop;
+
 zx_status_t brcmfmac_module_init(zx_device_t* device) {
     zx_status_t err;
 
     /* Initialize debug system first */
     brcmf_debugfs_init();
 
+    async_loop_config_t async_config;
+    memset(&async_config, 0, sizeof(async_config));
+    err = async_loop_create(&async_config, &async_loop);
+    if (err != ZX_OK) {
+        return err;
+    }
+    err = async_loop_start_thread(async_loop, "async_thread", NULL);
+    if (err != ZX_OK) {
+        async_loop_destroy(async_loop);
+        return err;
+    }
+    default_async = async_loop_get_dispatcher(async_loop);
+
     /* Get the platform data (if available) for our devices */
     err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe);
     if (err == ZX_ERR_IO_NOT_PRESENT) {
@@ -532,6 +547,9 @@
     if (brcmfmac_pdata) {
         platform_driver_unregister(&brcmf_pd);
     }
+    if (default_async != NULL) {
+        async_loop_destroy(async_loop);
+    }
     brcmf_debugfs_exit();
 }
 
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/device.c b/drivers/wlan/third_party/broadcom/brcmfmac/device.c
index 4e14c8e..58138bb 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/device.c
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/device.c
@@ -22,6 +22,8 @@
 
 pthread_mutex_t irq_callback_lock;
 
+async_t* default_async;
+
 struct brcmf_bus* dev_get_drvdata(struct brcmf_device* dev) {
     return dev->drvdata;
 }
@@ -34,3 +36,47 @@
 void dev_set_drvdata(struct brcmf_device* dev, struct brcmf_bus* drvdata) {
     dev->drvdata = drvdata;
 }
+
+static void brcmf_timer_handler(async_t* async, async_task_t* task, zx_status_t status) {
+    if (status != ZX_OK) {
+        return;
+    }
+    brcmf_timer_info_t* timer = containerof(task, brcmf_timer_info_t, task);
+    timer->callback_function(timer->data);
+    mtx_lock(&timer->lock);
+    timer->scheduled = false;
+    completion_signal(&timer->finished);
+    mtx_unlock(&timer->lock);
+}
+
+void brcmf_timer_init(brcmf_timer_info_t* timer, brcmf_timer_callback_t* callback) {
+    memset(&timer->task.state, 0, sizeof(timer->task.state));
+    timer->task.handler = brcmf_timer_handler;
+    timer->callback_function = callback;
+    timer->finished = COMPLETION_INIT;
+    timer->scheduled = false;
+    mtx_init(&timer->lock, mtx_plain);
+}
+
+void brcmf_timer_set(brcmf_timer_info_t* timer, zx_duration_t delay) {
+    mtx_lock(&timer->lock);
+    async_cancel_task(default_async, &timer->task); // Make sure it's not scheduled
+    timer->task.deadline = delay + async_now(default_async);
+    timer->scheduled = true;
+    completion_reset(&timer->finished);
+    async_post_task(default_async, &timer->task);
+    mtx_unlock(&timer->lock);
+}
+
+void brcmf_timer_stop(brcmf_timer_info_t* timer) {
+    mtx_lock(&timer->lock);
+    if (!timer->scheduled) {
+        mtx_unlock(&timer->lock);
+        return;
+    }
+    zx_status_t result = async_cancel_task(default_async, &timer->task);
+    mtx_unlock(&timer->lock);
+    if (result != ZX_OK) {
+        completion_wait(&timer->finished, ZX_TIME_INFINITE);
+    }
+}
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/device.h b/drivers/wlan/third_party/broadcom/brcmfmac/device.h
index 57c903b..5413189 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/device.h
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/device.h
@@ -19,8 +19,15 @@
 
 #include <ddk/driver.h>
 #include <ddk/protocol/pci.h>
+#include <lib/async-loop/loop.h> // to start the worker thread
+#include <lib/async/default.h>  // for async_get_default()
+#include <lib/async/task.h>     // for async_post_task()
+#include <lib/async/time.h>     // for async_now()
 #include <pthread.h>
+#include <string.h>
+#include <sync/completion.h>
 #include <threads.h>
+#include <zircon/listnode.h>
 #include <zircon/types.h>
 
 #define BACKPLANE_ID_HIGH_REVCODE_HIGH 0x7000
@@ -49,6 +56,26 @@
 #define BC_CORE_POWER_CONTROL_RELOAD 0x2
 #define BC_CORE_POWER_CONTROL_SHIFT 13
 
+extern async_t* default_async;
+
+// This is the function that timer users write to receive callbacks.
+typedef void (brcmf_timer_callback_t)(void* data);
+
+typedef struct brcmf_timer_info {
+    async_task_t task;
+    void* data;
+    brcmf_timer_callback_t* callback_function;
+    bool scheduled;
+    completion_t finished;
+    mtx_t lock;
+} brcmf_timer_info_t;
+
+void brcmf_timer_init(brcmf_timer_info_t* timer, brcmf_timer_callback_t* callback);
+
+void brcmf_timer_set(brcmf_timer_info_t* timer, zx_duration_t delay);
+
+void brcmf_timer_stop(brcmf_timer_info_t* timer);
+
 struct brcmf_device {
     void* of_node;
     void* parent;
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/linuxisms.h b/drivers/wlan/third_party/broadcom/brcmfmac/linuxisms.h
index e85ea15..bab24bd 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/linuxisms.h
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/linuxisms.h
@@ -302,10 +302,6 @@
 LINUX_FUNCVI(sdio_f0_readb)
 LINUX_FUNCII(allow_signal)
 LINUX_FUNCX(kthread_should_stop)
-LINUX_FUNCVI(mod_timer)
-LINUX_FUNCVI(add_timer)
-LINUX_FUNCVI(timer_setup)
-LINUX_FUNCVI(timer_pending)
 LINUX_FUNCII(__ffs)
 LINUX_FUNCVS(kthread_run)
 static inline const char* dev_name(void* dev) {
@@ -313,10 +309,8 @@
 }
 LINUX_FUNCVI(init_waitqueue_head)
 LINUX_FUNCVI(device_release_driver)
-LINUX_FUNCVI(del_timer_sync)
 LINUX_FUNCVV(strnchr)
 LINUX_FUNCVI(request_firmware)
-#define from_timer(a, b, c) ((void*)0)
 #define module_param_string(a, b, c, d)
 #define module_exit(a) \
     void* __modexit() { return a; }
@@ -1025,10 +1019,6 @@
     void* private;
 };
 
-struct timer_list {
-    zx_time_t expires;
-};
-
 struct asdf {
     int foo;
 };
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/p2p.h b/drivers/wlan/third_party/broadcom/brcmfmac/p2p.h
index 5dceaad..cbbad8d 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/p2p.h
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/p2p.h
@@ -138,7 +138,7 @@
     uint8_t dev_addr[ETH_ALEN];
     uint8_t int_addr[ETH_ALEN];
     struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
-    struct timer_list listen_timer;
+    brcmf_timer_info_t listen_timer;
     uint8_t listen_channel;
     struct ieee80211_channel remain_on_channel;
     uint32_t remain_on_channel_cookie;
diff --git a/drivers/wlan/third_party/broadcom/brcmfmac/sdio.c b/drivers/wlan/third_party/broadcom/brcmfmac/sdio.c
index d738f45..f3d02f9 100644
--- a/drivers/wlan/third_party/broadcom/brcmfmac/sdio.c
+++ b/drivers/wlan/third_party/broadcom/brcmfmac/sdio.c
@@ -514,7 +514,7 @@
     wait_queue_head_t ctrl_wait;
     wait_queue_head_t dcmd_resp_wait;
 
-    struct timer_list timer;
+    brcmf_timer_info_t timer;
     completion_t watchdog_wait;
     struct task_struct* watchdog_tsk;
     bool wd_active;
@@ -3851,15 +3851,15 @@
     return ZX_OK;
 }
 
-static void brcmf_sdio_watchdog(struct timer_list* t) {
+static void brcmf_sdio_watchdog(void* data) {
     pthread_mutex_lock(&irq_callback_lock);
-    struct brcmf_sdio* bus = from_timer(bus, t, timer);
+    struct brcmf_sdio* bus = data;
 
     if (bus->watchdog_tsk) {
         completion_signal(&bus->watchdog_wait);
         /* Reschedule the watchdog */
         if (bus->wd_active) {
-            mod_timer(&bus->timer, zx_clock_get(ZX_CLOCK_MONOTONIC) + ZX_MSEC(BRCMF_WD_POLL_MSEC));
+            brcmf_timer_set(&bus->timer, ZX_MSEC(BRCMF_WD_POLL_MSEC));
         }
     }
     pthread_mutex_unlock(&irq_callback_lock);
@@ -4048,7 +4048,7 @@
     init_waitqueue_head(&bus->dcmd_resp_wait);
 
     /* Set up the watchdog timer */
-    timer_setup(&bus->timer, brcmf_sdio_watchdog, 0);
+    brcmf_timer_init(&bus->timer, brcmf_sdio_watchdog);
     /* Initialize watchdog thread */
     bus->watchdog_wait = COMPLETION_INIT;
     ret = kthread_run(brcmf_sdio_watchdog_thread, bus, "brcmf_wdog/%s",
@@ -4183,7 +4183,7 @@
 void brcmf_sdio_wd_timer(struct brcmf_sdio* bus, bool active) {
     /* Totally stop the timer */
     if (!active && bus->wd_active) {
-        del_timer_sync(&bus->timer);
+        brcmf_timer_stop(&bus->timer);
         bus->wd_active = false;
         return;
     }
@@ -4198,12 +4198,11 @@
             /* Create timer again when watchdog period is
                dynamically changed or in the first instance
              */
-            bus->timer.expires = zx_clock_get(ZX_CLOCK_MONOTONIC) + ZX_MSEC(BRCMF_WD_POLL_MSEC);
-            add_timer(&bus->timer);
+            brcmf_timer_set(&bus->timer, ZX_MSEC(BRCMF_WD_POLL_MSEC));
             bus->wd_active = true;
         } else {
             /* Re arm the timer, at last watchdog period */
-            mod_timer(&bus->timer, zx_clock_get(ZX_CLOCK_MONOTONIC) + ZX_MSEC(BRCMF_WD_POLL_MSEC));
+            brcmf_timer_set(&bus->timer, ZX_MSEC(BRCMF_WD_POLL_MSEC));
         }
     }
 }
diff --git a/drivers/wlan/wlantap/wlantap-ctl.cpp b/drivers/wlan/wlantap/wlantap-ctl.cpp
index f0dc465..250e95d 100644
--- a/drivers/wlan/wlantap/wlantap-ctl.cpp
+++ b/drivers/wlan/wlantap/wlantap-ctl.cpp
@@ -4,7 +4,7 @@
 
 #include <ddk/debug.h>
 #include <ddk/device.h>
-#include <wlan_device/cpp/fidl.h>
+#include <fuchsia/wlan/device/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/dispatcher.h>
 #include <wlan/protocol/ioctl.h>
@@ -18,6 +18,8 @@
 
 namespace {
 
+namespace wlantap = ::fuchsia::wlan::tap;
+
 class WlantapDriver {
 public:
     zx_status_t GetOrStartLoop(async_t** out) {
@@ -81,7 +83,7 @@
         // Immediately wrap the handle to make sure we don't leak it
         zx::channel user_channel(in.channel);
 
-        auto phy_config = ::wlantap::WlantapPhyConfig::New();
+        auto phy_config = wlantap::WlantapPhyConfig::New();
         const uint8_t* in_end = static_cast<const uint8_t*>(in_buf) + in_len;
         zx_status_t status = DecodeFidl(&in.config[0], in_end - &in.config[0], phy_config.get());
         if (status != ZX_OK) {
@@ -94,8 +96,7 @@
             zxlogf(ERROR, "could not start wlantap event loop: %d", status);
             return status;
         }
-        status = wlan::wlantap::CreatePhy(device_, std::move(user_channel), std::move(phy_config),
-                                          loop);
+        status = wlan::CreatePhy(device_, std::move(user_channel), std::move(phy_config), loop);
         if (status != ZX_OK) {
             zxlogf(ERROR, "could not create wlantap phy: %d\n", status);
             return status;
diff --git a/drivers/wlan/wlantap/wlantap-mac.cpp b/drivers/wlan/wlantap/wlantap-mac.cpp
index 84180f7..08816cc 100644
--- a/drivers/wlan/wlantap/wlantap-mac.cpp
+++ b/drivers/wlan/wlantap/wlantap-mac.cpp
@@ -5,13 +5,16 @@
 #include "wlantap-mac.h"
 #include <ddk/debug.h>
 #include <ddk/driver.h>
-#include <wlan_device/cpp/fidl.h>
+#include <fuchsia/wlan/device/cpp/fidl.h>
 #include <lib/fxl/arraysize.h>
 #include <wlan/common/channel.h>
 #include <wlan/wlanmac-ifc-proxy.h>
 
 namespace wlan {
-namespace wlantap {
+
+namespace wlantap = ::fuchsia::wlan::tap;
+namespace wlan_device = ::fuchsia::wlan::device;
+
 namespace {
 
 uint16_t ConvertSupportedPhys(const ::fidl::VectorPtr<wlan_device::SupportedPhy>& phys) {
@@ -102,7 +105,7 @@
 
 struct WlantapMacImpl : WlantapMac {
     WlantapMacImpl(zx_device_t* phy_device, uint16_t id, wlan_device::MacRole role,
-                   const ::wlantap::WlantapPhyConfig* phy_config, Listener* listener)
+                   const wlantap::WlantapPhyConfig* phy_config, Listener* listener)
         : id_(id), role_(role), phy_config_(phy_config), listener_(listener)
     { }
 
@@ -215,7 +218,7 @@
     // WlantapMac impl
 
     virtual void Rx(const std::vector<uint8_t>& data,
-                    const ::wlantap::WlanRxInfo& rx_info) override {
+                    const wlantap::WlanRxInfo& rx_info) override {
         std::lock_guard<std::mutex> guard(lock_);
         if (ifc_) {
             wlan_rx_info_t converted_info = {
@@ -257,7 +260,7 @@
     wlan_device::MacRole role_;
     std::mutex lock_;
     WlanmacIfcProxy ifc_ __TA_GUARDED(lock_);
-    const ::wlantap::WlantapPhyConfig* phy_config_;
+    const wlantap::WlantapPhyConfig* phy_config_;
     Listener* listener_;
 };
 
@@ -266,7 +269,7 @@
 
 zx_status_t CreateWlantapMac(zx_device_t* parent_phy,
                              const wlan_device::CreateIfaceRequest& request,
-                             const ::wlantap::WlantapPhyConfig* phy_config,
+                             const wlantap::WlantapPhyConfig* phy_config,
                              uint16_t id, WlantapMac::Listener* listener, WlantapMac** ret) {
     char name[ZX_MAX_NAME_LEN + 1];
     snprintf(name, sizeof(name), "%s-mac%u", device_get_name(parent_phy), id);
@@ -305,5 +308,4 @@
     return ZX_OK;
 }
 
-} // namespace wlantap
 } // namespace wlan
diff --git a/drivers/wlan/wlantap/wlantap-mac.h b/drivers/wlan/wlantap/wlantap-mac.h
index eecef66..07b6dad 100644
--- a/drivers/wlan/wlantap/wlantap-mac.h
+++ b/drivers/wlan/wlantap/wlantap-mac.h
@@ -5,11 +5,10 @@
 #pragma once
 
 #include <ddk/device.h>
-#include <wlantap/cpp/fidl.h>
+#include <fuchsia/wlan/tap/cpp/fidl.h>
 #include <wlan/protocol/mac.h>
 
 namespace wlan {
-namespace wlantap {
 
 class WlantapMac {
   public:
@@ -24,7 +23,7 @@
     };
 
     virtual void Rx(const std::vector<uint8_t>& data,
-                    const ::wlantap::WlanRxInfo& rx_info) = 0;
+                    const ::fuchsia::wlan::tap::WlanRxInfo& rx_info) = 0;
     virtual void Status(uint32_t status) = 0;
 
     virtual void RemoveDevice() = 0;
@@ -33,11 +32,10 @@
 };
 
 zx_status_t CreateWlantapMac(zx_device_t* parent_phy,
-                             const wlan_device::CreateIfaceRequest& request,
-                             const ::wlantap::WlantapPhyConfig* phy_config,
+                             const ::fuchsia::wlan::device::CreateIfaceRequest& request,
+                             const ::fuchsia::wlan::tap::WlantapPhyConfig* phy_config,
                              uint16_t id,
                              WlantapMac::Listener* listener,
                              WlantapMac** ret);
 
-} // namespace wlantap
 } // namespace wlan
diff --git a/drivers/wlan/wlantap/wlantap-phy.cpp b/drivers/wlan/wlantap/wlantap-phy.cpp
index 1cb1286..37d8b28 100644
--- a/drivers/wlan/wlantap/wlantap-phy.cpp
+++ b/drivers/wlan/wlantap/wlantap-phy.cpp
@@ -7,15 +7,18 @@
 
 #include <array>
 #include <ddk/debug.h>
-#include <wlan_device/cpp/fidl.h>
-#include <wlan_device/c/fidl.h>
-#include <wlantap/c/fidl.h>
+#include <fuchsia/wlan/device/cpp/fidl.h>
+#include <fuchsia/wlan/device/c/fidl.h>
+#include <fuchsia/wlan/tap/c/fidl.h>
 #include <wlan/async/dispatcher.h>
 #include <wlan/protocol/ioctl.h>
 #include <wlan/protocol/phy.h>
 
 namespace wlan {
-namespace wlantap {
+
+namespace wlantap = ::fuchsia::wlan::tap;
+namespace wlan_device = ::fuchsia::wlan::device;
+
 namespace {
 
 template<typename T>
@@ -78,7 +81,7 @@
     }
 
     void SendSetChannelEvent(uint16_t wlanmac_id, wlan_channel_t* channel) {
-        ::wlantap::SetChannelArgs args = {
+        wlantap::SetChannelArgs args = {
             .wlanmac_id = wlanmac_id,
             .chan = {
                     .primary = channel->primary,
@@ -90,7 +93,7 @@
     }
 
     void SendConfigureBssEvent(uint16_t wlanmac_id, wlan_bss_config_t* config) {
-        ::wlantap::ConfigureBssArgs args = {
+        wlantap::ConfigureBssArgs args = {
             .wlanmac_id = wlanmac_id,
             .config = {
                     .bss_type = config->bss_type,
@@ -117,18 +120,18 @@
     }
 
     void SendWlanmacStartEvent(uint16_t wlanmac_id) {
-        ::wlantap::WlanmacStartArgs args = { .wlanmac_id = wlanmac_id };
+        wlantap::WlanmacStartArgs args = { .wlanmac_id = wlanmac_id };
         Send(EventOrdinal::WlanmacStart, &args);
     }
 
 private:
     enum class EventOrdinal : uint32_t {
-        Tx = wlantap_WlantapPhyTxOrdinal,
-        SetChannel = wlantap_WlantapPhySetChannelOrdinal,
-        ConfigureBss = wlantap_WlantapPhyConfigureBssOrdinal,
+        Tx = fuchsia_wlan_tap_WlantapPhyTxOrdinal,
+        SetChannel = fuchsia_wlan_tap_WlantapPhySetChannelOrdinal,
+        ConfigureBss = fuchsia_wlan_tap_WlantapPhyConfigureBssOrdinal,
         // TODO: ConfigureBeacon
-        SetKey = wlantap_WlantapPhySetKeyOrdinal,
-        WlanmacStart = wlantap_WlantapPhyWlanmacStartOrdinal
+        SetKey = fuchsia_wlan_tap_WlantapPhySetKeyOrdinal,
+        WlanmacStart = fuchsia_wlan_tap_WlantapPhyWlanmacStartOrdinal
     };
 
     template<typename T>
@@ -140,7 +143,7 @@
         }
     }
 
-    static void ConvertTxInfo(const wlan_tx_info_t& in, ::wlantap::WlanTxInfo* out) {
+    static void ConvertTxInfo(const wlan_tx_info_t& in, wlantap::WlanTxInfo* out) {
         out->tx_flags = in.tx_flags;
         out->valid_fields = in.valid_fields;
         out->phy = in.phy;
@@ -152,8 +155,8 @@
     fidl::Encoder encoder_;
     const zx::channel& channel_;
     // Messages that require memory allocation
-    ::wlantap::TxArgs tx_args_;
-    ::wlantap::SetKeyArgs set_key_args_;
+    wlantap::TxArgs tx_args_;
+    wlantap::SetKeyArgs set_key_args_;
 };
 
 template<typename T, size_t MAX_COUNT>
@@ -202,9 +205,9 @@
 
 constexpr size_t kMaxMacDevices = 4;
 
-struct WlantapPhy : wlan_device::Phy, ::wlantap::WlantapPhy, WlantapMac::Listener {
+struct WlantapPhy : wlan_device::Phy, wlantap::WlantapPhy, WlantapMac::Listener {
     WlantapPhy(zx_device_t* device, zx::channel user_channel,
-               std::unique_ptr<::wlantap::WlantapPhyConfig> phy_config,
+               std::unique_ptr<wlantap::WlantapPhyConfig> phy_config,
                async_t* loop)
       : phy_config_(std::move(phy_config)),
         phy_dispatcher_(loop),
@@ -314,7 +317,7 @@
     // wlantap::WlantapPhy impl
 
     virtual void Rx(uint16_t wlanmac_id, ::fidl::VectorPtr<uint8_t> data,
-                    ::wlantap::WlanRxInfo info) override {
+                    wlantap::WlanRxInfo info) override {
         std::lock_guard<std::mutex> guard(wlanmac_lock_);
         if (WlantapMac* wlanmac = wlanmac_devices_.Get(wlanmac_id)) {
             wlanmac->Rx(data, info);
@@ -363,9 +366,9 @@
     }
 
     zx_device_t* device_;
-    const std::unique_ptr<const ::wlantap::WlantapPhyConfig> phy_config_;
+    const std::unique_ptr<const wlantap::WlantapPhyConfig> phy_config_;
     wlan::async::Dispatcher<wlan_device::Phy> phy_dispatcher_;
-    fidl::Binding<::wlantap::WlantapPhy> user_channel_binding_;
+    fidl::Binding<wlantap::WlantapPhy> user_channel_binding_;
     std::mutex wlanmac_lock_;
     DevicePool<WlantapMac, kMaxMacDevices> wlanmac_devices_ __TA_GUARDED(wlanmac_lock_);
     std::mutex event_sender_lock_;
@@ -375,7 +378,7 @@
 } // namespace
 
 zx_status_t CreatePhy(zx_device_t* wlantapctl, zx::channel user_channel,
-                      std::unique_ptr<::wlantap::WlantapPhyConfig> config, async_t* loop) {
+                      std::unique_ptr<wlantap::WlantapPhyConfig> config, async_t* loop) {
     auto phy = std::make_unique<WlantapPhy>(wlantapctl, std::move(user_channel), std::move(config),
                                             loop);
     static zx_protocol_device_t device_ops = {
@@ -403,5 +406,4 @@
     return ZX_OK;
 }
 
-} // namespace wlantap
 } // namespace wlan
diff --git a/drivers/wlan/wlantap/wlantap-phy.h b/drivers/wlan/wlantap/wlantap-phy.h
index 7f3ca36..b572672 100644
--- a/drivers/wlan/wlantap/wlantap-phy.h
+++ b/drivers/wlan/wlantap/wlantap-phy.h
@@ -5,16 +5,15 @@
 #pragma once
 
 #include <ddk/device.h>
-#include <wlantap/cpp/fidl.h>
+#include <fuchsia/wlan/tap/cpp/fidl.h>
 #include <zx/channel.h>
 #include <lib/async/dispatcher.h>
 #include <wlan/protocol/wlantap.h>
 
 namespace wlan {
-namespace wlantap {
 
 zx_status_t CreatePhy(zx_device_t* wlantapctl, zx::channel user_channel,
-                      std::unique_ptr<::wlantap::WlantapPhyConfig> ioctl_in, async_t* loop);
+                      std::unique_ptr<::fuchsia::wlan::tap::WlantapPhyConfig> ioctl_in,
+                      async_t* loop);
 
-} // namespace wlantap
 } // namespace wlan
diff --git a/examples/bluetooth/ble_battery_service/src/main.rs b/examples/bluetooth/ble_battery_service/src/main.rs
index 0f3643d..e0a5357 100644
--- a/examples/bluetooth/ble_battery_service/src/main.rs
+++ b/examples/bluetooth/ble_battery_service/src/main.rs
@@ -13,7 +13,7 @@
 extern crate fidl_bluetooth as bt;
 extern crate fidl_bluetooth_gatt as gatt;
 extern crate fidl_bluetooth_low_energy as le;
-extern crate fidl_power_manager;
+extern crate fidl_fuchsia_power;
 extern crate parking_lot;
 
 mod cancelable_future;
@@ -23,7 +23,7 @@
 use failure::{Error, Fail};
 use futures::prelude::*;
 use futures::future::{FutureResult, ok as fok};
-use fidl_power_manager::{
+use fidl_fuchsia_power::{
     PowerManager,
     PowerManagerMarker,
     PowerManagerWatcher,
diff --git a/examples/bluetooth/bt-le-heart-rate-peripheral/app.cc b/examples/bluetooth/bt-le-heart-rate-peripheral/app.cc
index 65be216..f4a2197 100644
--- a/examples/bluetooth/bt-le-heart-rate-peripheral/app.cc
+++ b/examples/bluetooth/bt-le-heart-rate-peripheral/app.cc
@@ -9,28 +9,29 @@
 
 #include <lib/fxl/logging.h>
 
+namespace ble = fuchsia::bluetooth::le;
+
 namespace bt_le_heart_rate {
 
 App::App(std::unique_ptr<HeartModel> heart_model)
     : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
       service_(std::move(heart_model)) {
   gatt_server_ =
-      context_->ConnectToEnvironmentService<bluetooth_gatt::Server>();
+      context_->ConnectToEnvironmentService<fuchsia::bluetooth::gatt::Server>();
   FXL_DCHECK(gatt_server_);
 
   service_.PublishService(&gatt_server_);
 
-  peripheral_ =
-      context_->ConnectToEnvironmentService<bluetooth_low_energy::Peripheral>();
+  peripheral_ = context_->ConnectToEnvironmentService<ble::Peripheral>();
   FXL_DCHECK(peripheral_);
 }
 
 void App::StartAdvertising() {
-  bluetooth_low_energy::AdvertisingData ad;
+  ble::AdvertisingData ad;
   ad.name = kDeviceName;
   ad.service_uuids = fidl::VectorPtr<fidl::StringPtr>({Service::kServiceUuid});
 
-  const auto start_adv_result_cb = [](bluetooth::Status status,
+  const auto start_adv_result_cb = [](fuchsia::bluetooth::Status status,
                                       fidl::StringPtr advertisement_id) {
     std::cout << "StartAdvertising status: " << bool(status.error)
               << ", advertisement_id: " << advertisement_id << std::endl;
@@ -44,7 +45,7 @@
 constexpr char App::kDeviceName[];
 
 void App::OnCentralConnected(fidl::StringPtr advertisement_id,
-                             bluetooth_low_energy::RemoteDevice central) {
+                             ble::RemoteDevice central) {
   std::cout << "Central (" << central.identifier << ") connected" << std::endl;
 
   // Save the binding for this connection.
diff --git a/examples/bluetooth/bt-le-heart-rate-peripheral/app.h b/examples/bluetooth/bt-le-heart-rate-peripheral/app.h
index 372b3a5..6b95eac 100644
--- a/examples/bluetooth/bt-le-heart-rate-peripheral/app.h
+++ b/examples/bluetooth/bt-le-heart-rate-peripheral/app.h
@@ -8,8 +8,8 @@
 #include <memory>
 #include <unordered_map>
 
-#include <bluetooth_gatt/cpp/fidl.h>
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 #include <lib/app/cpp/startup_context.h>
 #include <lib/fidl/cpp/binding.h>
 #include <lib/fidl/cpp/string.h>
@@ -18,7 +18,7 @@
 
 namespace bt_le_heart_rate {
 
-class App final : public bluetooth_low_energy::PeripheralDelegate {
+class App final : public fuchsia::bluetooth::le::PeripheralDelegate {
  public:
   explicit App(std::unique_ptr<HeartModel> heart_model);
   ~App() = default;
@@ -28,12 +28,13 @@
   Service* service() { return &service_; }
 
  private:
-  using Binding = fidl::Binding<bluetooth_low_energy::PeripheralDelegate>;
+  using Binding = fidl::Binding<fuchsia::bluetooth::le::PeripheralDelegate>;
 
   static constexpr char kDeviceName[] = "FX BLE Heart Rate";
 
-  void OnCentralConnected(fidl::StringPtr advertisement_id,
-                          bluetooth_low_energy::RemoteDevice central) override;
+  void OnCentralConnected(
+      fidl::StringPtr advertisement_id,
+      fuchsia::bluetooth::le::RemoteDevice central) override;
   void OnCentralDisconnected(fidl::StringPtr device_id) override;
 
   // Application
@@ -41,12 +42,12 @@
 
   // GATT
   Service service_;
-  bluetooth_gatt::ServerPtr gatt_server_;
+  fuchsia::bluetooth::gatt::ServerPtr gatt_server_;
 
   // BLE advertisement
   std::unique_ptr<Binding> binding_;  // For current advertisement
   std::unordered_map<std::string, std::unique_ptr<Binding>> connected_bindings_;
-  bluetooth_low_energy::PeripheralPtr peripheral_;
+  fuchsia::bluetooth::le::PeripheralPtr peripheral_;
 };
 
 }  // namespace bt_le_heart_rate
diff --git a/examples/bluetooth/bt-le-heart-rate-peripheral/service.cc b/examples/bluetooth/bt-le-heart-rate-peripheral/service.cc
index 11d0a70..2b612f6 100644
--- a/examples/bluetooth/bt-le-heart-rate-peripheral/service.cc
+++ b/examples/bluetooth/bt-le-heart-rate-peripheral/service.cc
@@ -13,6 +13,10 @@
 #include <lib/async/default.h>
 #include <lib/fxl/logging.h>
 
+using fuchsia::bluetooth::Status;
+
+namespace gatt = fuchsia::bluetooth::gatt;
+
 namespace bt_le_heart_rate {
 namespace {
 
@@ -106,46 +110,44 @@
   FXL_DCHECK(heart_model_);
 }
 
-void Service::PublishService(bluetooth_gatt::ServerPtr* gatt_server) {
-  using namespace bluetooth_gatt;
-
+void Service::PublishService(gatt::ServerPtr* gatt_server) {
   // Heart Rate Measurement
   // Allow update with default security of "none required."
-  Characteristic hrm;
+  gatt::Characteristic hrm;
   hrm.id = kHeartRateMeasurementId;
   hrm.type = kHeartRateMeasurementUuid;
-  hrm.properties = kPropertyNotify;
-  hrm.permissions = AttributePermissions::New();
-  hrm.permissions->update = SecurityRequirements::New();
+  hrm.properties = gatt::kPropertyNotify;
+  hrm.permissions = gatt::AttributePermissions::New();
+  hrm.permissions->update = gatt::SecurityRequirements::New();
 
   // Body Sensor Location
-  Characteristic bsl;
+  gatt::Characteristic bsl;
   bsl.id = kBodySensorLocationId;
   bsl.type = kBodySensorLocationUuid;
-  bsl.properties = kPropertyRead;
-  bsl.permissions = AttributePermissions::New();
-  bsl.permissions->read = SecurityRequirements::New();
+  bsl.properties = gatt::kPropertyRead;
+  bsl.permissions = gatt::AttributePermissions::New();
+  bsl.permissions->read = gatt::SecurityRequirements::New();
 
   // Heart Rate Control Point
-  Characteristic hrcp;
+  gatt::Characteristic hrcp;
   hrcp.id = kHeartRateControlPointId;
   hrcp.type = kHeartRateControlPointUuid;
-  hrcp.properties = kPropertyWrite;
-  hrcp.permissions = AttributePermissions::New();
-  hrcp.permissions->write = SecurityRequirements::New();
+  hrcp.properties = gatt::kPropertyWrite;
+  hrcp.permissions = gatt::AttributePermissions::New();
+  hrcp.permissions->write = gatt::SecurityRequirements::New();
 
-  fidl::VectorPtr<Characteristic> characteristics;
+  fidl::VectorPtr<gatt::Characteristic> characteristics;
   characteristics.push_back(std::move(hrm));
   characteristics.push_back(std::move(bsl));
   characteristics.push_back(std::move(hrcp));
 
-  ServiceInfo si;
+  gatt::ServiceInfo si;
   si.primary = true;
   si.type = kServiceUuid;
   si.characteristics = std::move(characteristics);
 
   std::cout << "Publishing service..." << std::endl;
-  auto publish_svc_result_cb = [](bluetooth::Status status) {
+  auto publish_svc_result_cb = [](Status status) {
     std::cout << "PublishService status: " << bool(status.error) << std::endl;
   };
   (*gatt_server)
@@ -223,14 +225,14 @@
             << std::endl;
 
   if (id != kBodySensorLocationId) {
-    callback(nullptr, bluetooth_gatt::ErrorCode::NOT_PERMITTED);
+    callback(nullptr, gatt::ErrorCode::NOT_PERMITTED);
     return;
   }
 
   // Body Sensor Location payload
   fidl::VectorPtr<uint8_t> value;
   value.push_back(static_cast<uint8_t>(BodySensorLocation::kOther));
-  callback(std::move(value), bluetooth_gatt::ErrorCode::NO_ERROR);
+  callback(std::move(value), gatt::ErrorCode::NO_ERROR);
 }
 
 void Service::OnWriteValue(uint64_t id, uint16_t offset,
@@ -245,19 +247,19 @@
     std::cout << "Ignoring writes to characteristic other than Heart Rate "
                  "Control Point"
               << std::endl;
-    callback(bluetooth_gatt::ErrorCode::NOT_PERMITTED);
+    callback(gatt::ErrorCode::NOT_PERMITTED);
     return;
   }
 
   if (offset != 0) {
     std::cout << "Write to control point at invalid offset" << std::endl;
-    callback(bluetooth_gatt::ErrorCode::INVALID_OFFSET);
+    callback(gatt::ErrorCode::INVALID_OFFSET);
     return;
   }
 
   if (value->size() != 1) {
     std::cout << "Write to control point of invalid length" << std::endl;
-    callback(bluetooth_gatt::ErrorCode::INVALID_VALUE_LENGTH);
+    callback(gatt::ErrorCode::INVALID_VALUE_LENGTH);
     return;
   }
 
@@ -271,7 +273,7 @@
 
   std::cout << "Resetting Energy Expended" << std::endl;
   heart_model_->ResetEnergyExpended();
-  callback(bluetooth_gatt::ErrorCode::NO_ERROR);
+  callback(gatt::ErrorCode::NO_ERROR);
 }
 
 void Service::OnWriteWithoutResponse(uint64_t id, uint16_t offset,
diff --git a/examples/bluetooth/bt-le-heart-rate-peripheral/service.h b/examples/bluetooth/bt-le-heart-rate-peripheral/service.h
index 569749f..405fad8 100644
--- a/examples/bluetooth/bt-le-heart-rate-peripheral/service.h
+++ b/examples/bluetooth/bt-le-heart-rate-peripheral/service.h
@@ -7,7 +7,7 @@
 
 #include <unordered_set>
 
-#include <bluetooth_gatt/cpp/fidl.h>
+#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 #include <lib/fidl/cpp/string.h>
 #include <lib/fidl/cpp/vector.h>
@@ -17,7 +17,7 @@
 
 class HeartModel;
 
-class Service final : bluetooth_gatt::LocalServiceDelegate {
+class Service final : fuchsia::bluetooth::gatt::LocalServiceDelegate {
  public:
   // See assigned numbers for GATT services and characteristics.
   // https://www.bluetooth.com/specifications/gatt/services
@@ -35,8 +35,9 @@
 
   // See Assigned Numbers for Heart Rate Service
   // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml
-  static constexpr bluetooth_gatt::ErrorCode CONTROL_POINT_NOT_SUPPORTED =
-      static_cast<bluetooth_gatt::ErrorCode>(0x80);
+  static constexpr fuchsia::bluetooth::gatt::ErrorCode
+      CONTROL_POINT_NOT_SUPPORTED =
+          static_cast<fuchsia::bluetooth::gatt::ErrorCode>(0x80);
 
   // Heart Rate Service v1.0, 3.3.1 [Control Point] Characteristic Behavior.
   static constexpr uint8_t kResetEnergyExpendedValue = 0x01;
@@ -44,7 +45,7 @@
   explicit Service(std::unique_ptr<HeartModel> heart_model);
   ~Service() = default;
 
-  void PublishService(bluetooth_gatt::ServerPtr* gatt_server);
+  void PublishService(fuchsia::bluetooth::gatt::ServerPtr* gatt_server);
 
   void set_measurement_interval(int msec) { measurement_interval_ = msec; }
 
@@ -66,8 +67,8 @@
                               fidl::VectorPtr<uint8_t> value) override;
 
   std::unique_ptr<HeartModel> heart_model_;
-  fidl::Binding<bluetooth_gatt::LocalServiceDelegate> binding_;
-  bluetooth_gatt::LocalServicePtr service_;
+  fidl::Binding<fuchsia::bluetooth::gatt::LocalServiceDelegate> binding_;
+  fuchsia::bluetooth::gatt::LocalServicePtr service_;
 
   // Peers that have enabled measurement notifications.
   std::unordered_set<std::string> measurement_peers_;
diff --git a/examples/bluetooth/bt_beacon_reader/app.cc b/examples/bluetooth/bt_beacon_reader/app.cc
index 4c7402a..93b67a5 100644
--- a/examples/bluetooth/bt_beacon_reader/app.cc
+++ b/examples/bluetooth/bt_beacon_reader/app.cc
@@ -11,22 +11,13 @@
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
 
-#include <bluetooth_control/cpp/fidl.h>
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/control/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 #include "lib/fxl/functional/auto_call.h"
 #include "lib/fxl/logging.h"
 #include "lib/fxl/strings/split_string.h"
 
-char* date_string() {
-  static char date_buf[80];
-  time_t t = time(NULL);
-  struct tm tm = *localtime(&t);
-
-  snprintf(date_buf, sizeof(date_buf), "%4d-%02d-%02d %02d:%02d:%02d",
-           tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min,
-           tm.tm_sec);
-  return date_buf;
-}
+namespace ble = fuchsia::bluetooth::le;
 
 namespace bt_beacon_reader {
 
@@ -37,8 +28,7 @@
       just_tilts_(just_tilts) {
   FXL_DCHECK(context_);
 
-  central_ =
-      context_->ConnectToEnvironmentService<bluetooth_low_energy::Central>();
+  central_ = context_->ConnectToEnvironmentService<ble::Central>();
   FXL_DCHECK(central_);
 
   central_.set_error_handler([this] {
@@ -47,17 +37,17 @@
   });
 
   // Register with the Control as its delegate.
-  bluetooth_low_energy::CentralDelegatePtr delegate;
+  ble::CentralDelegatePtr delegate;
   central_delegate_.Bind(delegate.NewRequest());
   central_->SetDelegate(std::move(delegate));
 }
 
 void App::StartScanning() {
-  bluetooth_low_energy::ScanFilterPtr filter =
-      bluetooth_low_energy::ScanFilter::New();
-  filter->connectable = bluetooth::Bool::New();
+  ble::ScanFilterPtr filter = ble::ScanFilter::New();
+  filter->connectable = fuchsia::bluetooth::Bool::New();
   filter->connectable->value = false;
-  central_->StartScan(std::move(filter), [](bluetooth::Status status) {});
+  central_->StartScan(std::move(filter),
+                      [](fuchsia::bluetooth::Status status) {});
 }
 
 // Called when the scan state changes, e.g. when a scan session terminates due
@@ -66,7 +56,7 @@
   printf("Device %s scanning.\n", scanning ? "started" : "stopped");
 }
 
-void PrintRDHeader(const bluetooth_low_energy::RemoteDevice& device) {
+void PrintRDHeader(const ble::RemoteDevice& device) {
   printf("id: %s ", device.identifier->c_str());
   if (device.advertising_data && device.advertising_data->appearance) {
     uint16_t appearance = device.advertising_data->appearance->value;
@@ -79,7 +69,7 @@
   printf("\n");
 }
 
-void PrintGeneralBeaconData(const bluetooth_low_energy::RemoteDevice& device) {
+void PrintGeneralBeaconData(const ble::RemoteDevice& device) {
   if (!device.advertising_data) {
     return;
   }
@@ -99,7 +89,7 @@
   }
 }
 
-void App::OnDeviceDiscovered(bluetooth_low_energy::RemoteDevice device) {
+void App::OnDeviceDiscovered(ble::RemoteDevice device) {
   if (just_tilts_) {
     std::unique_ptr<TiltDetection> tilt = TiltDetection::Create(device);
     if (tilt) {
diff --git a/examples/bluetooth/bt_beacon_reader/app.h b/examples/bluetooth/bt_beacon_reader/app.h
index 595e7f1..9dad414 100644
--- a/examples/bluetooth/bt_beacon_reader/app.h
+++ b/examples/bluetooth/bt_beacon_reader/app.h
@@ -5,7 +5,7 @@
 #ifndef GARNET_EXAMPLES_BLUETOOTH_BT_BEACON_READER_APP_H_
 #define GARNET_EXAMPLES_BLUETOOTH_BT_BEACON_READER_APP_H_
 
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 
 #include "lib/app/cpp/startup_context.h"
@@ -13,24 +13,24 @@
 
 namespace bt_beacon_reader {
 
-class App final : public bluetooth_low_energy::CentralDelegate {
+class App final : public fuchsia::bluetooth::le::CentralDelegate {
  public:
   App(async::Loop* loop, bool just_tilts);
 
   void StartScanning();
 
  private:
-  // bluetooth_low_energy::CentralDelegate overrides:
+  // fuchsia::bluetooth::le::CentralDelegate overrides:
   void OnScanStateChanged(bool scanning);
-  void OnDeviceDiscovered(bluetooth_low_energy::RemoteDevice device);
+  void OnDeviceDiscovered(fuchsia::bluetooth::le::RemoteDevice device);
   void OnPeripheralDisconnected(::fidl::StringPtr identifier);
 
   async::Loop* const loop_;
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
-  bluetooth_low_energy::CentralPtr central_;
+  fuchsia::bluetooth::le::CentralPtr central_;
 
   // Local CentralDelegate binding.
-  fidl::Binding<bluetooth_low_energy::CentralDelegate> central_delegate_;
+  fidl::Binding<fuchsia::bluetooth::le::CentralDelegate> central_delegate_;
 
   bool just_tilts_;
 
diff --git a/examples/bluetooth/bt_beacon_reader/beacons.cc b/examples/bluetooth/bt_beacon_reader/beacons.cc
index a89a209..5177bc3 100644
--- a/examples/bluetooth/bt_beacon_reader/beacons.cc
+++ b/examples/bluetooth/bt_beacon_reader/beacons.cc
@@ -6,10 +6,12 @@
 
 #include "beacons.h"
 
+namespace ble = fuchsia::bluetooth::le;
+
 namespace bt_beacon_reader {
 
 std::unique_ptr<IBeaconDetection> IBeaconDetection::Create(
-    const bluetooth_low_energy::RemoteDevice& device) {
+    const ble::RemoteDevice& device) {
   if (!device.advertising_data ||
       device.advertising_data->manufacturer_specific_data->size() != 1) {
     return nullptr;
@@ -44,7 +46,7 @@
 }
 
 std::unique_ptr<TiltDetection> TiltDetection::Create(
-    const bluetooth_low_energy::RemoteDevice& device) {
+    const ble::RemoteDevice& device) {
   std::unique_ptr<IBeaconDetection> beacon = IBeaconDetection::Create(device);
   if (!beacon) {
     return nullptr;
diff --git a/examples/bluetooth/bt_beacon_reader/beacons.h b/examples/bluetooth/bt_beacon_reader/beacons.h
index 7662e47..4a05129 100644
--- a/examples/bluetooth/bt_beacon_reader/beacons.h
+++ b/examples/bluetooth/bt_beacon_reader/beacons.h
@@ -4,7 +4,7 @@
 
 #include <memory>
 
-#include <bluetooth_low_energy/cpp/fidl.h>
+#include <fuchsia/bluetooth/le/cpp/fidl.h>
 
 namespace bt_beacon_reader {
 
@@ -15,7 +15,7 @@
   // If it is a beacon, fills out this class and returns it.
   // Otherwise, returns a nullptr.
   static std::unique_ptr<IBeaconDetection> Create(
-      const bluetooth_low_energy::RemoteDevice& device);
+      const fuchsia::bluetooth::le::RemoteDevice& device);
 
   uint8_t power_lvl_ = 0;
   std::string uuid_;
@@ -31,7 +31,7 @@
 class TiltDetection {
  public:
   static std::unique_ptr<TiltDetection> Create(
-      const bluetooth_low_energy::RemoteDevice& device);
+      const fuchsia::bluetooth::le::RemoteDevice& device);
 
   void Print();
 
diff --git a/examples/escher/common/BUILD.gn b/examples/escher/common/BUILD.gn
index 97658f8..ac2ffde 100644
--- a/examples/escher/common/BUILD.gn
+++ b/examples/escher/common/BUILD.gn
@@ -30,7 +30,6 @@
 
   if (is_fuchsia) {
     deps += [
-      "//garnet/examples/escher/common/services",
       "//garnet/public/lib/app/cpp",
       "//garnet/public/lib/fsl",
       "//zircon/public/lib/async-loop-cpp"
diff --git a/examples/escher/common/demo.cc b/examples/escher/common/demo.cc
index 0a27911..826324a 100644
--- a/examples/escher/common/demo.cc
+++ b/examples/escher/common/demo.cc
@@ -22,12 +22,34 @@
       return false;
     } else if (key == "RETURN") {
       return false;
-    } else {
-      // Illegal value.
-      FXL_LOG(ERROR) << "Cannot handle key value: " << key;
-      FXL_CHECK(false);
-      return false;
+    }
+    // Illegal value.
+    FXL_LOG(ERROR) << "Cannot handle key value: " << key;
+    FXL_CHECK(false);
+    return false;
+  } else {
+    char key_char = key[0];
+    switch (key_char) {
+      case 'T':
+        ToggleTracing();
+        return true;
+      default:
+        return false;
     }
   }
-  return false;
+}
+
+void Demo::ToggleTracing() {
+#ifdef __fuchsia__
+  // On Fuchsia, use system-wide tracing in the usual way.
+  FXL_LOG(INFO) << "ToggleTracing() only supported for Escher-Linux.";
+#else
+  if (tracer_) {
+    tracer_.reset();
+    FXL_LOG(INFO) << "Tracing disabled.";
+  } else {
+    tracer_ = std::make_unique<escher::Tracer>();
+    FXL_LOG(INFO) << "Tracing enabled.";
+  }
+#endif
 }
diff --git a/examples/escher/common/demo.h b/examples/escher/common/demo.h
index 9fdd0fe..9ddb402 100644
--- a/examples/escher/common/demo.h
+++ b/examples/escher/common/demo.h
@@ -7,6 +7,7 @@
 
 #include "garnet/examples/escher/common/demo_harness.h"
 #include "lib/escher/escher.h"
+#include "lib/escher/util/tracer.h"
 #include "lib/escher/vk/vulkan_context.h"
 
 // Base class for Escher demos.
@@ -22,21 +23,18 @@
 
   // Begin a touch.  Only one touch can have the specified |touch_id| at any
   // given time (it is guaranteed to not be reused until EndTouch() is called).
-  virtual void BeginTouch(uint64_t touch_id,
-                          double x_position,
+  virtual void BeginTouch(uint64_t touch_id, double x_position,
                           double y_position) {}
   // Continue a touch.  Multiple positions may be aggregated since the last time
   // that BeginTouch()/ContinueTouch() were called; the number of positions is
   // provided by |position_count| which is guaranteed to be >= 1.  If multiple
   // positions are aggregated, they are provided in order of occurrence.
-  virtual void ContinueTouch(uint64_t touch_id,
-                             const double* x_positions,
-                             const double* y_positions,
-                             size_t position_count) {}
+  virtual void ContinueTouch(uint64_t touch_id, const double* x_positions,
+                             const double* y_positions, size_t position_count) {
+  }
   // End a touch.  Afterward, |touch_id| may appear in a subsequent call of
   // BeginTouch().
-  virtual void EndTouch(uint64_t touch_id,
-                        double x_position,
+  virtual void EndTouch(uint64_t touch_id, double x_position,
                         double y_position) {}
 
   virtual void DrawFrame() = 0;
@@ -47,10 +45,14 @@
     return vulkan_context_;
   }
 
+ protected:
+  void ToggleTracing();
+
  private:
   DemoHarness* const harness_;
   escher::VulkanContext vulkan_context_;
   escher::Escher escher_;
+  std::unique_ptr<escher::Tracer> tracer_;
 };
 
 #endif  // GARNET_EXAMPLES_ESCHER_COMMON_DEMO_H_
diff --git a/examples/escher/common/demo_harness_fuchsia.cc b/examples/escher/common/demo_harness_fuchsia.cc
index 2e7505f..5484fb3 100644
--- a/examples/escher/common/demo_harness_fuchsia.cc
+++ b/examples/escher/common/demo_harness_fuchsia.cc
@@ -9,6 +9,7 @@
 #include <zx/time.h>
 
 #include "garnet/examples/escher/common/demo.h"
+#include "lib/escher/util/trace_macros.h"
 
 // When running on Fuchsia, New() instantiates a DemoHarnessFuchsia.
 std::unique_ptr<DemoHarness> DemoHarness::New(
@@ -24,8 +25,7 @@
     : DemoHarness(window_params),
       loop_(loop),
       owned_loop_(loop_ ? nullptr : new async::Loop()),
-      startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()),
-      escher_demo_binding_(this) {
+      startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
   if (!loop_) {
     loop_ = owned_loop_.get();
   }
@@ -67,27 +67,11 @@
     loop_->Quit();
     device().waitIdle();
   } else {
-    demo_->DrawFrame();
+    {
+      TRACE_DURATION("gfx", "escher::DemoHarness::DrawFrame");
+      demo_->DrawFrame();
+    }
     async::PostDelayedTask(loop_->async(),
                            [this] { this->RenderFrameOrQuit(); }, zx::msec(1));
   }
 }
-
-void DemoHarnessFuchsia::HandleKeyPress(uint8_t key) {
-  demo_->HandleKeyPress(std::string(1, static_cast<char>(key)));
-}
-
-void DemoHarnessFuchsia::HandleTouchBegin(uint64_t touch_id, double xpos,
-                                          double ypos) {
-  demo_->BeginTouch(touch_id, xpos, ypos);
-}
-
-void DemoHarnessFuchsia::HandleTouchContinue(uint64_t touch_id, double xpos,
-                                             double ypos) {
-  demo_->ContinueTouch(touch_id, &xpos, &ypos, 1);
-}
-
-void DemoHarnessFuchsia::HandleTouchEnd(uint64_t touch_id, double xpos,
-                                        double ypos) {
-  demo_->EndTouch(touch_id, xpos, ypos);
-}
diff --git a/examples/escher/common/demo_harness_fuchsia.h b/examples/escher/common/demo_harness_fuchsia.h
index ad1b3a6..36a57a8 100644
--- a/examples/escher/common/demo_harness_fuchsia.h
+++ b/examples/escher/common/demo_harness_fuchsia.h
@@ -7,27 +7,19 @@
 
 #include <memory>
 
-#include <escher_demo/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 
 #include "garnet/examples/escher/common/demo_harness.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
 
-class DemoHarnessFuchsia : public DemoHarness, public escher_demo::EscherDemo {
+class DemoHarnessFuchsia : public DemoHarness {
  public:
   DemoHarnessFuchsia(async::Loop* loop, WindowParams window_params);
 
   // |DemoHarness|
   void Run(Demo* demo) override;
 
-  // |EscherDemo|
-  void HandleKeyPress(uint8_t key) override;
-  void HandleTouchBegin(uint64_t touch_id, double xpos, double ypos) override;
-  void HandleTouchContinue(uint64_t touch_id, double xpos,
-                           double ypos) override;
-  void HandleTouchEnd(uint64_t touch_id, double xpos, double ypos) override;
-
   fuchsia::sys::StartupContext* startup_context() {
     return startup_context_.get();
   }
@@ -53,7 +45,6 @@
   std::unique_ptr<async::Loop> owned_loop_;
 
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
-  fidl::Binding<escher_demo::EscherDemo> escher_demo_binding_;
   std::unique_ptr<fuchsia::sys::ServiceProviderImpl> outgoing_services_;
 };
 
diff --git a/examples/escher/common/demo_harness_linux.cc b/examples/escher/common/demo_harness_linux.cc
index 7d3fda4..5f10ba5 100644
--- a/examples/escher/common/demo_harness_linux.cc
+++ b/examples/escher/common/demo_harness_linux.cc
@@ -7,6 +7,7 @@
 #include <GLFW/glfw3.h>
 
 #include "garnet/examples/escher/common/demo.h"
+#include "lib/escher/util/trace_macros.h"
 #include "lib/fxl/logging.h"
 
 static DemoHarness* g_harness = nullptr;
@@ -22,11 +23,8 @@
                    << std::endl;
 }
 
-static void DemoGlfwKeyCallback(GLFWwindow* window,
-                                int key,
-                                int scancode,
-                                int action,
-                                int mods) {
+static void DemoGlfwKeyCallback(GLFWwindow* window, int key, int scancode,
+                                int action, int mods) {
   auto demo = g_harness->GetRunningDemo();
   if (!demo)
     return;
@@ -90,8 +88,7 @@
   }
 }
 
-static void DemoGlfwCursorPosCallback(GLFWwindow* window,
-                                      double x_pos,
+static void DemoGlfwCursorPosCallback(GLFWwindow* window, double x_pos,
                                       double y_pos) {
   g_x_pos = x_pos;
   g_y_pos = y_pos;
@@ -106,10 +103,8 @@
   }
 }
 
-static void DemoGlfwMouseButtonCallback(GLFWwindow* window,
-                                        int button,
-                                        int action,
-                                        int mods) {
+static void DemoGlfwMouseButtonCallback(GLFWwindow* window, int button,
+                                        int action, int mods) {
   if (button != GLFW_MOUSE_BUTTON_1) {
     // We only handle the primary mouse button.
     return;
@@ -194,7 +189,10 @@
   demo_ = demo;
 
   while (!this->ShouldQuit()) {
-    demo->DrawFrame();
+    {
+      TRACE_DURATION("gfx", "escher::DemoHarness::DrawFrame");
+      demo->DrawFrame();
+    }
     glfwPollEvents();
   }
   device().waitIdle();
diff --git a/examples/escher/common/services/BUILD.gn b/examples/escher/common/services/BUILD.gn
deleted file mode 100644
index 04325d4..0000000
--- a/examples/escher/common/services/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2015 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/fidl/fidl.gni")
-
-fidl("services") {
-  name = "escher_demo"
-
-  sources = [
-    "escher_demo.fidl",
-  ]
-
-  public_deps = [
-    "//garnet/public/lib/app/fidl",
-  ]
-}
diff --git a/examples/escher/common/services/escher_demo.fidl b/examples/escher/common/services/escher_demo.fidl
deleted file mode 100644
index f21e2d8..0000000
--- a/examples/escher/common/services/escher_demo.fidl
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2015 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library escher_demo;
-
-[Discoverable]
-interface EscherDemo {
-  // GetCurrentFrameNumber() -> (uint64 frame_number);
-  1: HandleKeyPress(uint8 key);
-  2: HandleTouchBegin(uint64 touch_id, float64 xpos, float64 ypos);
-  3: HandleTouchContinue(uint64 touch_id, float64 xpos, float64 ypos);
-  4: HandleTouchEnd(uint64 touch_id, float64 xpos, float64 ypos);
-};
diff --git a/examples/escher/waterfall/waterfall_demo.cc b/examples/escher/waterfall/waterfall_demo.cc
index 26496fa..d21b2b3 100644
--- a/examples/escher/waterfall/waterfall_demo.cc
+++ b/examples/escher/waterfall/waterfall_demo.cc
@@ -32,14 +32,10 @@
 WaterfallDemo::WaterfallDemo(DemoHarness* harness, int argc, char** argv)
     : Demo(harness),
       renderer_(escher::PaperRenderer::New(escher())),
-      shadow_renderer_(
-          escher::ShadowMapRenderer::New(escher(),
-                                         renderer_->model_data(),
-                                         renderer_->model_renderer())),
-      moment_shadow_renderer_(
-          escher::MomentShadowMapRenderer::New(escher(),
-                                               renderer_->model_data(),
-                                               renderer_->model_renderer())),
+      shadow_renderer_(escher::ShadowMapRenderer::New(
+          escher(), renderer_->model_data(), renderer_->model_renderer())),
+      moment_shadow_renderer_(escher::MomentShadowMapRenderer::New(
+          escher(), renderer_->model_data(), renderer_->model_renderer())),
       swapchain_helper_(harness->GetVulkanSwapchain(),
                         escher()->vulkan_context().device,
                         escher()->vulkan_context().queue) {
@@ -156,6 +152,9 @@
       case 'D':
         show_debug_info_ = !show_debug_info_;
         return true;
+      case 'M':
+        stop_time_ = !stop_time_;
+        return true;
       case 'P':
         profile_one_frame_ = true;
         return true;
@@ -164,9 +163,6 @@
         FXL_LOG(INFO) << "Sort object by pipeline: "
                       << (sort_by_pipeline_ ? "true" : "false");
         return true;
-      case 'T':
-        stop_time_ = !stop_time_;
-        return true;
       case '1':
         current_scene_ = 0;
         return true;
diff --git a/examples/fidl/echo2_client_cpp/echo2_client.cc b/examples/fidl/echo2_client_cpp/echo2_client.cc
index bb9aff5..1f84429 100644
--- a/examples/fidl/echo2_client_cpp/echo2_client.cc
+++ b/examples/fidl/echo2_client_cpp/echo2_client.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <echo2/cpp/fidl.h>
+#define FIDL_ENABLE_LEGACY_WAIT_FOR_RESPONSE
+
+#include <fidl/examples/echo/cpp/fidl.h>
 #include <launchpad/launchpad.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/default.h>
@@ -19,7 +21,7 @@
   EchoClientApp()
       : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {}
 
-  echo2::EchoPtr& echo() { return echo_; }
+  fidl::examples::echo::EchoPtr& echo() { return echo_; }
 
   void Start(std::string server_url) {
     fuchsia::sys::LaunchInfo launch_info;
@@ -29,7 +31,7 @@
                                           controller_.NewRequest());
 
     echo_provider_.ConnectToService(echo_.NewRequest().TakeChannel(),
-                                    Echo::Name_);
+                                    fidl::examples::echo::Echo::Name_);
   }
 
  private:
@@ -39,7 +41,7 @@
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
   fuchsia::sys::Services echo_provider_;
   fuchsia::sys::ComponentControllerPtr controller_;
-  echo2::EchoPtr echo_;
+  fidl::examples::echo::EchoPtr echo_;
 };
 
 }  // namespace echo2
diff --git a/examples/fidl/echo2_client_go/echo2_client.go b/examples/fidl/echo2_client_go/echo2_client.go
index 18e23d3..9cdb87f 100644
--- a/examples/fidl/echo2_client_go/echo2_client.go
+++ b/examples/fidl/echo2_client_go/echo2_client.go
@@ -11,7 +11,7 @@
 	"app/context"
 	"svc/services"
 
-	"fidl/echo2"
+	echo2 "fidl/fidl/examples/echo"
 	"fidl/fuchsia/sys"
 )
 
diff --git a/examples/fidl/echo2_client_rust/src/main.rs b/examples/fidl/echo2_client_rust/src/main.rs
index 641967d..bb37e00 100644
--- a/examples/fidl/echo2_client_rust/src/main.rs
+++ b/examples/fidl/echo2_client_rust/src/main.rs
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 extern crate fidl;
-extern crate fidl_echo2;
+extern crate fidl_fidl_examples_echo;
 extern crate failure;
 extern crate fuchsia_app as component;
 extern crate fuchsia_async as async;
@@ -15,7 +15,7 @@
 use component::client::Launcher;
 use failure::{Error, ResultExt};
 use futures::prelude::*;
-use fidl_echo2::EchoMarker;
+use fidl_fidl_examples_echo::EchoMarker;
 use structopt::StructOpt;
 
 fn main() -> Result<(), Error> {
diff --git a/examples/fidl/echo2_server_c/echo_server.c b/examples/fidl/echo2_server_c/echo_server.c
index 2d3e42c..3c82a2d 100644
--- a/examples/fidl/echo2_server_c/echo_server.c
+++ b/examples/fidl/echo2_server_c/echo_server.c
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <lib/async-loop/loop.h>
 #include <lib/svc/dir.h>
 #include <stdio.h>
diff --git a/examples/fidl/echo2_server_cpp/BUILD.gn b/examples/fidl/echo2_server_cpp/BUILD.gn
index 85d3f9c..42a9cc7 100644
--- a/examples/fidl/echo2_server_cpp/BUILD.gn
+++ b/examples/fidl/echo2_server_cpp/BUILD.gn
@@ -4,6 +4,19 @@
 
 import("//build/package.gni")
 
+source_set("lib") {
+  sources = [
+    "echo2_server_app.cc",
+    "echo2_server_app.h",
+  ]
+
+  public_deps = [
+    "//garnet/examples/fidl/services:echo2",
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/fidl/cpp",
+  ]
+}
+
 executable("bin") {
   output_name = "echo2_server_cpp"
 
@@ -12,9 +25,7 @@
   ]
 
   deps = [
-    "//garnet/examples/fidl/services:echo2",
-    "//garnet/public/lib/app/cpp",
-    "//garnet/public/lib/fidl/cpp",
+    ":lib",
     "//zircon/public/lib/async-default",
     "//zircon/public/lib/async-loop-cpp",
   ]
@@ -27,3 +38,33 @@
 
   binary = "echo2_server_cpp"
 }
+
+executable("echo2_server_cpp_unittests") {
+  testonly = true
+
+  sources = [
+    "echo2_server_app_unittest.cc",
+  ]
+
+  deps = [
+    ":lib",
+    "//garnet/public/lib/app/cpp/testing",
+    "//garnet/public/lib/fxl/test:gtest_main",
+    "//garnet/public/lib/gtest",
+  ]
+}
+
+package("echo2_server_cpp_tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  deps = [
+    ":echo2_server_cpp_unittests",
+  ]
+
+  tests = [
+    {
+      name = "echo2_server_cpp_unittests"
+    },
+  ]
+}
diff --git a/examples/fidl/echo2_server_cpp/echo2_server.cc b/examples/fidl/echo2_server_cpp/echo2_server.cc
index 6152726..d6486a4 100644
--- a/examples/fidl/echo2_server_cpp/echo2_server.cc
+++ b/examples/fidl/echo2_server_cpp/echo2_server.cc
@@ -2,44 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <echo2/cpp/fidl.h>
+#include "echo2_server_app.h"
+
 #include <lib/async-loop/cpp/loop.h>
-#include <lib/zx/channel.h>
-
-#include "lib/app/cpp/startup_context.h"
-
-namespace echo2 {
-
-class EchoServerApp : public Echo {
- public:
-  EchoServerApp()
-      : context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
-    context_->outgoing().AddPublicService<Echo>(
-        [this](fidl::InterfaceRequest<Echo> request) {
-          bindings_.AddBinding(this, std::move(request));
-        });
-  }
-
-  ~EchoServerApp() {}
-
-  void EchoString(fidl::StringPtr value, EchoStringCallback callback) override {
-    printf("EchoString: %s\n", value->data());
-    callback(std::move(value));
-  }
-
- private:
-  EchoServerApp(const EchoServerApp&) = delete;
-  EchoServerApp& operator=(const EchoServerApp&) = delete;
-
-  std::unique_ptr<fuchsia::sys::StartupContext> context_;
-  fidl::BindingSet<Echo> bindings_;
-};
-
-}  // namespace echo2
 
 int main(int argc, const char** argv) {
   async::Loop loop(&kAsyncLoopConfigMakeDefault);
-
   echo2::EchoServerApp app;
   loop.Run();
   return 0;
diff --git a/examples/fidl/echo2_server_cpp/echo2_server_app.cc b/examples/fidl/echo2_server_cpp/echo2_server_app.cc
new file mode 100644
index 0000000..c6170e3
--- /dev/null
+++ b/examples/fidl/echo2_server_cpp/echo2_server_app.cc
@@ -0,0 +1,29 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "echo2_server_app.h"
+
+#include "lib/app/cpp/startup_context.h"
+
+namespace echo2 {
+
+EchoServerApp::EchoServerApp()
+    : EchoServerApp(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {}
+
+EchoServerApp::EchoServerApp(
+    std::unique_ptr<fuchsia::sys::StartupContext> context)
+    : context_(std::move(context)) {
+  context_->outgoing().AddPublicService<Echo>(
+      [this](fidl::InterfaceRequest<Echo> request) {
+        bindings_.AddBinding(this, std::move(request));
+      });
+}
+
+void EchoServerApp::EchoString(fidl::StringPtr value,
+                               EchoStringCallback callback) {
+  printf("EchoString: %s\n", value->data());
+  callback(std::move(value));
+}
+
+}  // namespace echo2
diff --git a/examples/fidl/echo2_server_cpp/echo2_server_app.h b/examples/fidl/echo2_server_cpp/echo2_server_app.h
new file mode 100644
index 0000000..349d713
--- /dev/null
+++ b/examples/fidl/echo2_server_cpp/echo2_server_app.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_EXAMPLES_FIDL_ECHO2_SERVER_CPP_ECHO2_SERVER_APP_H_
+#define GARNET_EXAMPLES_FIDL_ECHO2_SERVER_CPP_ECHO2_SERVER_APP_H_
+
+#include <fidl/examples/echo/cpp/fidl.h>
+
+#include "lib/app/cpp/startup_context.h"
+
+namespace echo2 {
+
+class EchoServerApp : public fidl::examples::echo::Echo {
+ public:
+  EchoServerApp();
+  virtual void EchoString(fidl::StringPtr value, EchoStringCallback callback);
+
+ protected:
+  EchoServerApp(std::unique_ptr<fuchsia::sys::StartupContext> context);
+
+ private:
+  EchoServerApp(const EchoServerApp&) = delete;
+  EchoServerApp& operator=(const EchoServerApp&) = delete;
+  std::unique_ptr<fuchsia::sys::StartupContext> context_;
+  fidl::BindingSet<Echo> bindings_;
+};
+
+}  // namespace echo2
+
+#endif  // GARNET_EXAMPLES_FIDL_ECHO2_SERVER_CPP_ECHO2_SERVER_APP_H_
diff --git a/examples/fidl/echo2_server_cpp/echo2_server_app_unittest.cc b/examples/fidl/echo2_server_cpp/echo2_server_app_unittest.cc
new file mode 100644
index 0000000..c641cde
--- /dev/null
+++ b/examples/fidl/echo2_server_cpp/echo2_server_app_unittest.cc
@@ -0,0 +1,64 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "echo2_server_app.h"
+#include "lib/app/cpp/testing/startup_context_for_test.h"
+#include "lib/gtest/test_with_loop.h"
+
+namespace echo2 {
+namespace testing {
+
+class EchoServerAppForTest : public EchoServerApp {
+ public:
+  EchoServerAppForTest(std::unique_ptr<fuchsia::sys::StartupContext> context)
+      : EchoServerApp(std::move(context)) {}
+};
+
+class EchoServerAppTest : public ::gtest::TestWithLoop {
+ public:
+  void SetUp() override {
+    TestWithLoop::SetUp();
+    auto context = fuchsia::sys::testing::StartupContextForTest::Create();
+    services_ = &context->services();
+    echoServerApp_.reset(new EchoServerAppForTest(std::move(context)));
+  }
+
+  void TearDown() override {
+    echoServerApp_.reset();
+    TestWithLoop::TearDown();
+  }
+
+ protected:
+  fidl::examples::echo::EchoPtr echo() {
+    fidl::examples::echo::EchoPtr echo;
+    services_->ConnectToService(echo.NewRequest());
+    return echo;
+  }
+
+ private:
+  std::unique_ptr<EchoServerAppForTest> echoServerApp_;
+  const fuchsia::sys::Services* services_;
+};
+
+// Answer "Hello World" with "Hello World"
+TEST_F(EchoServerAppTest, EchoString_HelloWorld) {
+  fidl::examples::echo::EchoPtr echo_ = echo();
+  ::fidl::StringPtr message = "bogus";
+  echo_->EchoString("Hello World!",
+                    [&](::fidl::StringPtr retval) { message = retval; });
+  RunLoopUntilIdle();
+  EXPECT_EQ("Hello World!", message);
+}
+
+// Answer "" with ""
+TEST_F(EchoServerAppTest, EchoString_Empty) {
+  fidl::examples::echo::EchoPtr echo_ = echo();
+  ::fidl::StringPtr message = "bogus";
+  echo_->EchoString("", [&](::fidl::StringPtr retval) { message = retval; });
+  RunLoopUntilIdle();
+  EXPECT_EQ("", message);
+}
+
+}  // namespace testing
+}  // namespace echo2
diff --git a/examples/fidl/echo2_server_go/echo2_server.go b/examples/fidl/echo2_server_go/echo2_server.go
index 1f60181..aed7030 100644
--- a/examples/fidl/echo2_server_go/echo2_server.go
+++ b/examples/fidl/echo2_server_go/echo2_server.go
@@ -12,7 +12,7 @@
 
 	"syscall/zx"
 
-	"fidl/echo2"
+	echo2 "fidl/fidl/examples/echo"
 )
 
 type echoImpl struct{}
diff --git a/examples/fidl/echo2_server_rust/src/main.rs b/examples/fidl/echo2_server_rust/src/main.rs
index d0d9523..d4a16d9 100644
--- a/examples/fidl/echo2_server_rust/src/main.rs
+++ b/examples/fidl/echo2_server_rust/src/main.rs
@@ -8,29 +8,26 @@
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
 extern crate futures;
-extern crate fidl_echo2;
+extern crate fidl_fidl_examples_echo;
 
 use component::server::ServicesServer;
 use failure::{Error, ResultExt};
 use futures::future;
 use futures::prelude::*;
-use fidl::endpoints2::ServiceMarker;
-use fidl_echo2::{Echo, EchoMarker, EchoImpl};
+use fidl::endpoints2::{ServiceMarker, RequestStream};
+use fidl_fidl_examples_echo::{EchoMarker, EchoRequest, EchoRequestStream};
 
 fn spawn_echo_server(chan: async::Channel) {
-    async::spawn(EchoImpl {
-        state: (),
-        on_open: |_,_| future::ok(()),
-        echo_string: |_, s, res| {
-            println!("Received echo request for string {:?}", s);
-            res.send(s.as_ref().map(|s| &**s))
+    async::spawn(EchoRequestStream::from_channel(chan)
+        .for_each(|EchoRequest::EchoString { value, responder }| {
+            println!("Received echo request for string {:?}", value);
+            responder.send(value.as_ref().map(|s| &**s))
                .into_future()
                .map(|_| println!("echo response sent successfully"))
                .recover(|e| eprintln!("error sending response: {:?}", e))
-       }
-    }
-    .serve(chan)
-    .recover(|e| eprintln!("error running echo server: {:?}", e)))
+        })
+        .map(|_| ())
+        .recover(|e| eprintln!("error running echo server: {:?}", e)))
 }
 
 fn main() -> Result<(), Error> {
diff --git a/examples/fidl/services/BUILD.gn b/examples/fidl/services/BUILD.gn
index 041ed1a..b630235 100644
--- a/examples/fidl/services/BUILD.gn
+++ b/examples/fidl/services/BUILD.gn
@@ -5,6 +5,9 @@
 import("//build/fidl/fidl.gni")
 
 fidl("echo2") {
+  name = "fidl.examples.echo"
+  cpp_legacy_callbacks = true
+
   sources = [
     "echo2.fidl",
   ]
diff --git a/examples/fidl/services/echo2.fidl b/examples/fidl/services/echo2.fidl
index 55a2777..34396b2 100644
--- a/examples/fidl/services/echo2.fidl
+++ b/examples/fidl/services/echo2.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library echo2;
+library fidl.examples.echo;
 
 [Discoverable]
 interface Echo {
diff --git a/examples/network/wget/BUILD.gn b/examples/http/httpget_cpp/BUILD.gn
similarity index 69%
rename from examples/network/wget/BUILD.gn
rename to examples/http/httpget_cpp/BUILD.gn
index c2748c0..7bc33f5 100644
--- a/examples/network/wget/BUILD.gn
+++ b/examples/http/httpget_cpp/BUILD.gn
@@ -5,10 +5,10 @@
 import("//build/package.gni")
 
 executable("bin") {
-  output_name = "wget"
+  output_name = "httpget_cpp"
 
   sources = [
-    "wget.cc",
+    "httpget.cc",
   ]
 
   deps = [
@@ -16,18 +16,14 @@
     "//garnet/public/lib/fidl/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
-    "//garnet/public/lib/network/fidl",
+    "//garnet/public/lib/net/oldhttp/fidl",
   ]
 }
 
-package("wget") {
-  deprecated_system_image = true
-
+package("httpget_cpp") {
   deps = [
     ":bin",
   ]
 
-  binaries = [ {
-        name = "wget"
-      } ]
+  binary = "httpget_cpp"
 }
diff --git a/examples/network/wget/wget.cc b/examples/http/httpget_cpp/httpget.cc
similarity index 83%
rename from examples/network/wget/wget.cc
rename to examples/http/httpget_cpp/httpget.cc
index 3ab53f5..f7851a3 100644
--- a/examples/network/wget/wget.cc
+++ b/examples/http/httpget_cpp/httpget.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include <lib/async-loop/cpp/loop.h>
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
@@ -14,9 +14,11 @@
 
 namespace examples {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 class ResponsePrinter {
  public:
-  void Run(async::Loop* loop, network::URLResponse response) const {
+  void Run(async::Loop* loop, http::URLResponse response) const {
     if (response.error) {
       printf("Got error: %d (%s)\n", response.error->code,
              response.error->description.get().c_str());
@@ -29,7 +31,7 @@
     loop->Quit();  // All done!
   }
 
-  void PrintResponse(const network::URLResponse& response) const {
+  void PrintResponse(const http::URLResponse& response) const {
     printf(">>> Headers <<< \n");
     printf("  %s\n", response.status_line.get().c_str());
     if (response.headers) {
@@ -74,9 +76,9 @@
   WGetApp(async::Loop* loop)
       : loop_(loop),
         context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
-    network_service_ =
-        context_->ConnectToEnvironmentService<network::NetworkService>();
-    FXL_DCHECK(network_service_);
+    http_service_ =
+        context_->ConnectToEnvironmentService<http::HttpService>();
+    FXL_DCHECK(http_service_);
   }
 
   bool Start(const std::vector<std::string>& args) {
@@ -90,15 +92,15 @@
     }
     printf("Loading: %s\n", url.c_str());
 
-    network_service_->CreateURLLoader(url_loader_.NewRequest());
+    http_service_->CreateURLLoader(url_loader_.NewRequest());
 
-    network::URLRequest request;
+    http::URLRequest request;
     request.url = url;
     request.method = "GET";
     request.auto_follow_redirects = true;
 
     url_loader_->Start(std::move(request),
-                       [this](network::URLResponse response) {
+                       [this](http::URLResponse response) {
                          ResponsePrinter printer;
                          printer.Run(loop_, std::move(response));
                        });
@@ -109,8 +111,8 @@
   async::Loop* const loop_;
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
 
-  network::NetworkServicePtr network_service_;
-  network::URLLoaderPtr url_loader_;
+  http::HttpServicePtr http_service_;
+  http::URLLoaderPtr url_loader_;
 };
 
 }  // namespace examples
diff --git a/examples/network/wget-rs/BUILD.gn b/examples/http/httpget_rust/BUILD.gn
similarity index 74%
rename from examples/network/wget-rs/BUILD.gn
rename to examples/http/httpget_rust/BUILD.gn
index 117d857..895c58d 100644
--- a/examples/network/wget-rs/BUILD.gn
+++ b/examples/http/httpget_rust/BUILD.gn
@@ -6,12 +6,12 @@
 import("//build/package.gni")
 
 rustc_binary("bin") {
-  name = "wget_rs"
+  name = "httpget_rust"
 
   deps = [
     "//garnet/public/lib/fidl/rust/fidl",
     "//garnet/public/lib/mem/fidl:fidl-rustc",
-    "//garnet/public/lib/network/fidl:fidl-rustc",
+    "//garnet/public/lib/net/oldhttp/fidl:fidl-rustc",
     "//garnet/public/rust/crates/fuchsia-app",
     "//garnet/public/rust/crates/fuchsia-async",
     "//garnet/public/rust/crates/fuchsia-zircon",
@@ -20,15 +20,10 @@
   ]
 }
 
-package("wget-rs") {
-  deprecated_system_image = true
-
+package("httpget_rust") {
   deps = [
     ":bin",
   ]
 
-  binaries = [ {
-        name = "rust_crates/wget_rs"
-        dest = "wget-rs"
-      } ]
+  binary = "rust_crates/httpget_rust"
 }
diff --git a/examples/network/wget-rs/src/main.rs b/examples/http/httpget_rust/src/main.rs
similarity index 78%
rename from examples/network/wget-rs/src/main.rs
rename to examples/http/httpget_rust/src/main.rs
index 809cf9c..839564e 100644
--- a/examples/network/wget-rs/src/main.rs
+++ b/examples/http/httpget_rust/src/main.rs
@@ -10,13 +10,13 @@
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
 extern crate futures;
-extern crate fidl_network as netsvc;
+extern crate fidl_fuchsia_net_oldhttp as http;
 
 use failure::{Error, ResultExt};
 use futures::prelude::*;
 use futures::io::AllowStdIo;
 
-fn print_headers(resp: &netsvc::UrlResponse) {
+fn print_headers(resp: &http::UrlResponse) {
     println!(">>> Headers <<<");
     if let Some(status) = &resp.status_line {
         println!("  {}", status);
@@ -34,7 +34,7 @@
     }
 }
 
-/// Connects to the network service, sends a url request, and prints the response.
+/// Connects to the http service, sends a url request, and prints the response.
 fn main_res() -> Result<(), Error> {
     let url = match std::env::args().nth(1) {
         Some(url) => {
@@ -53,29 +53,29 @@
     // Set up async executor
     let mut exec = async::Executor::new()?;
 
-    // Connect to the network service
-    let net = component::client::connect_to_service::<netsvc::NetworkServiceMarker>()?;
+    // Connect to the http service
+    let net = component::client::connect_to_service::<http::HttpServiceMarker>()?;
 
     // Create a UrlLoader instance
     let (s, p) = zx::Channel::create().context("failed to create zx channel")?;
     let proxy = async::Channel::from_channel(p).context("failed to make async channel")?;
 
-    let loader_server = fidl::endpoints2::ServerEnd::<netsvc::UrlLoaderMarker>::new(s);
+    let loader_server = fidl::endpoints2::ServerEnd::<http::UrlLoaderMarker>::new(s);
     net.create_url_loader(loader_server)?;
 
     // Send the UrlRequest to fetch the webpage
-    let mut req = netsvc::UrlRequest {
+    let mut req = http::UrlRequest {
         url: url,
         method: String::from("GET"),
         headers: None,
         body: None,
         response_body_buffer_size: 0,
         auto_follow_redirects: true,
-        cache_mode: netsvc::CacheMode::Default,
-        response_body_mode: netsvc::ResponseBodyMode::Stream,
+        cache_mode: http::CacheMode::Default,
+        response_body_mode: http::ResponseBodyMode::Stream,
     };
 
-	let loader_proxy = netsvc::UrlLoaderProxy::new(proxy);
+	let loader_proxy = http::UrlLoaderProxy::new(proxy);
     let fut = loader_proxy.start(&mut req).err_into().and_then(|resp| {
         if let Some(e) = resp.error {
             let code = e.code;
@@ -87,13 +87,13 @@
         print_headers(&resp);
 
         match resp.body.map(|x| *x) {
-            Some(netsvc::UrlBody::Stream(s)) => {
+            Some(http::UrlBody::Stream(s)) => {
                 Some(async::Socket::from_socket(s)
                         .into_future()
                         .err_into())
             }
-            Some(netsvc::UrlBody::Buffer(_)) |
-            Some(netsvc::UrlBody::SizedBuffer(_)) |
+            Some(http::UrlBody::Buffer(_)) |
+            Some(http::UrlBody::SizedBuffer(_)) |
             None =>  None,
         }
     }).and_then(|socket_opt| {
diff --git a/examples/network/postfile/BUILD.gn b/examples/http/postfile/BUILD.gn
similarity index 92%
rename from examples/network/postfile/BUILD.gn
rename to examples/http/postfile/BUILD.gn
index 6e875b8..daef904 100644
--- a/examples/network/postfile/BUILD.gn
+++ b/examples/http/postfile/BUILD.gn
@@ -16,7 +16,7 @@
     "//garnet/public/lib/fidl/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
-    "//garnet/public/lib/network/fidl",
+    "//garnet/public/lib/net/oldhttp/fidl",
   ]
 }
 
diff --git a/examples/network/postfile/postfile.cc b/examples/http/postfile/postfile.cc
similarity index 87%
rename from examples/network/postfile/postfile.cc
rename to examples/http/postfile/postfile.cc
index e5c616f..0e5cbaa 100644
--- a/examples/network/postfile/postfile.cc
+++ b/examples/http/postfile/postfile.cc
@@ -8,7 +8,7 @@
 
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/default.h>
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
@@ -20,9 +20,11 @@
 
 namespace examples {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 class ResponsePrinter {
  public:
-  void Run(async::Loop* loop, network::URLResponse response) const {
+  void Run(async::Loop* loop, http::URLResponse response) const {
     if (response.error) {
       printf("Got error: %d (%s)\n", response.error->code,
              response.error->description->c_str());
@@ -34,7 +36,7 @@
     loop->Quit();  // All done!
   }
 
-  void PrintResponse(const network::URLResponse& response) const {
+  void PrintResponse(const http::URLResponse& response) const {
     printf(">>> Headers <<< \n");
     printf("  %s\n", response.status_line.get().c_str());
     if (response.headers) {
@@ -75,8 +77,8 @@
   PostFileApp(async::Loop* loop)
       : loop_(loop),
         context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
-    network_service_ =
-        context_->ConnectToEnvironmentService<network::NetworkService>();
+    http_service_ =
+        context_->ConnectToEnvironmentService<http::HttpService>();
   }
 
   bool Start(const std::vector<std::string>& args) {
@@ -96,12 +98,12 @@
       return false;
     }
 
-    network::URLRequest request;
+    http::URLRequest request;
     request.url = url;
     request.method = "POST";
     request.auto_follow_redirects = true;
 
-    network::HttpHeader header;
+    http::HttpHeader header;
     header.name = "Content-Type";
     header.value = "multipart/form-data; boundary=" + boundary;
     request.headers.push_back(std::move(header));
@@ -114,7 +116,7 @@
       return false;
     }
 
-    request.body = network::URLBody::New();
+    request.body = http::URLBody::New();
     request.body->set_stream(std::move(consumer));
 
     async_t* async = async_get_default();
@@ -126,10 +128,10 @@
                                   }
                                 });
 
-    network_service_->CreateURLLoader(url_loader_.NewRequest());
+    http_service_->CreateURLLoader(url_loader_.NewRequest());
 
     url_loader_->Start(std::move(request),
-                       [this](network::URLResponse response) {
+                       [this](http::URLResponse response) {
                          ResponsePrinter printer;
                          printer.Run(loop_, std::move(response));
                        });
@@ -139,8 +141,8 @@
  private:
   async::Loop* const loop_;
   std::unique_ptr<fuchsia::sys::StartupContext> context_;
-  network::NetworkServicePtr network_service_;
-  network::URLLoaderPtr url_loader_;
+  http::HttpServicePtr http_service_;
+  http::URLLoaderPtr url_loader_;
 };
 
 }  // namespace examples
diff --git a/examples/media/audio_player/BUILD.gn b/examples/media/audio_player/BUILD.gn
index 396d2e3..f7cf128 100644
--- a/examples/media/audio_player/BUILD.gn
+++ b/examples/media/audio_player/BUILD.gn
@@ -18,5 +18,6 @@
     "//garnet/public/lib/media/fidl:media_player",
     "//garnet/public/lib/media/timeline",
     "//garnet/public/lib/url",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/examples/media/audio_player/audio_player.cc b/examples/media/audio_player/audio_player.cc
index f482d86..08617ba 100644
--- a/examples/media/audio_player/audio_player.cc
+++ b/examples/media/audio_player/audio_player.cc
@@ -7,9 +7,10 @@
 #include <iomanip>
 
 #include <fcntl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/loop.h>
 #include <lib/async/default.h>
-#include <media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/examples/media/audio_player/audio_player_params.h"
 #include "lib/app/cpp/connect.h"
@@ -19,31 +20,30 @@
 #include "lib/media/timeline/timeline.h"
 #include "lib/url/gurl.h"
 
-using media_player::MediaPlayer;
-using media_player::MediaPlayerStatus;
-using media_player::MediaPlayerStatusPtr;
-using media_player::NetMediaService;
-
 namespace examples {
 
 AudioPlayer::AudioPlayer(const AudioPlayerParams& params,
-                         fxl::Closure quit_callback)
-    : quit_callback_(quit_callback), quit_when_done_(!params.stay()) {
+                         fit::closure quit_callback)
+    : quit_callback_(std::move(quit_callback)),
+      quit_when_done_(!params.stay()) {
   FXL_DCHECK(params.is_valid());
   FXL_DCHECK(quit_callback_);
 
   auto startup_context = fuchsia::sys::StartupContext::CreateFromStartupInfo();
 
-  media_player_ = startup_context->ConnectToEnvironmentService<MediaPlayer>();
-  media_player_.events().StatusChanged = [this](MediaPlayerStatus status) {
+  media_player_ =
+      startup_context
+          ->ConnectToEnvironmentService<fuchsia::mediaplayer::MediaPlayer>();
+  media_player_.events().StatusChanged = [this](fuchsia::mediaplayer::MediaPlayerStatus status) {
     HandleStatusChanged(status);
   };
 
   if (!params.service_name().empty()) {
-    auto net_media_service =
-        startup_context->ConnectToEnvironmentService<NetMediaService>();
+    auto net_media_service = startup_context->ConnectToEnvironmentService<
+        fuchsia::mediaplayer::NetMediaService>();
 
-    fidl::InterfaceHandle<MediaPlayer> media_player_handle;
+    fidl::InterfaceHandle<fuchsia::mediaplayer::MediaPlayer>
+        media_player_handle;
     media_player_->AddBinding(media_player_handle.NewRequest());
 
     net_media_service->PublishMediaPlayer(params.service_name(),
@@ -67,7 +67,7 @@
 AudioPlayer::~AudioPlayer() {}
 
 void AudioPlayer::HandleStatusChanged(
-    const media_player::MediaPlayerStatus& status) {
+    const fuchsia::mediaplayer::MediaPlayerStatus& status) {
   // Process status received from the player.
   if (status.end_of_stream && quit_when_done_) {
     quit_callback_();
diff --git a/examples/media/audio_player/audio_player.h b/examples/media/audio_player/audio_player.h
index 44a05e6..6649190 100644
--- a/examples/media/audio_player/audio_player.h
+++ b/examples/media/audio_player/audio_player.h
@@ -5,12 +5,12 @@
 #ifndef GARNET_EXAMPLES_MEDIA_AUDIO_PLAYER_AUDIO_PLAYER_H_
 #define GARNET_EXAMPLES_MEDIA_AUDIO_PLAYER_AUDIO_PLAYER_H_
 
-#include <media/cpp/fidl.h>
-#include <media_player/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
+#include <fuchsia/mediaplayer/cpp/fidl.h>
 
 #include "garnet/examples/media/audio_player/audio_player_params.h"
 #include "lib/app/cpp/startup_context.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/media/timeline/timeline_function.h"
 
@@ -18,16 +18,16 @@
 
 class AudioPlayer {
  public:
-  AudioPlayer(const AudioPlayerParams& params, fxl::Closure quit_callback);
+  AudioPlayer(const AudioPlayerParams& params, fit::closure quit_callback);
 
   ~AudioPlayer();
 
  private:
   // Handles a status update from the player.
-  void HandleStatusChanged(const media_player::MediaPlayerStatus& status);
+  void HandleStatusChanged(const fuchsia::mediaplayer::MediaPlayerStatus& status);
 
-  fxl::Closure quit_callback_;
-  media_player::MediaPlayerPtr media_player_;
+  fit::closure quit_callback_;
+  fuchsia::mediaplayer::MediaPlayerPtr media_player_;
   bool metadata_shown_ = false;
   bool problem_shown_ = false;
   bool quit_when_done_;
diff --git a/examples/media/audio_player/audio_player_params.h b/examples/media/audio_player/audio_player_params.h
index 391a6b4..982cbed 100644
--- a/examples/media/audio_player/audio_player_params.h
+++ b/examples/media/audio_player/audio_player_params.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_EXAMPLES_MEDIA_AUDIO_PLAYER_AUDIO_PLAYER_PARAMS_H_
+#define GARNET_EXAMPLES_MEDIA_AUDIO_PLAYER_AUDIO_PLAYER_PARAMS_H_
 
 #include <string>
 
@@ -36,3 +37,5 @@
 };
 
 }  // namespace examples
+
+#endif  // GARNET_EXAMPLES_MEDIA_AUDIO_PLAYER_AUDIO_PLAYER_PARAMS_H_
diff --git a/examples/media/audio_player_rust/src/main.rs b/examples/media/audio_player_rust/src/main.rs
index 533c93e..03eee36 100644
--- a/examples/media/audio_player_rust/src/main.rs
+++ b/examples/media/audio_player_rust/src/main.rs
@@ -5,7 +5,7 @@
 extern crate failure;
 extern crate fdio;
 extern crate fidl;
-extern crate fidl_media_player;
+extern crate fidl_fuchsia_mediaplayer;
 extern crate fuchsia_app as app;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
@@ -18,7 +18,7 @@
 use app::client::connect_to_service;
 use failure::{Error, ResultExt};
 use fdio::fdio_sys::*;
-use fidl_media_player::*;
+use fidl_fuchsia_mediaplayer::*;
 use futures::prelude::*;
 use mxruntime_sys::*;
 use std::fs::File;
diff --git a/examples/media/fx/BUILD.gn b/examples/media/fx/BUILD.gn
index e7e94c9..b8a75e9 100644
--- a/examples/media/fx/BUILD.gn
+++ b/examples/media/fx/BUILD.gn
@@ -14,5 +14,7 @@
     "//garnet/public/lib/media/fidl",
     "//garnet/public/lib/media/timeline",
     "//zircon/public/lib/audio-utils",
+    "//zircon/public/lib/fit",
+    "//zircon/public/lib/vmo-utils",
   ]
 }
diff --git a/examples/media/fx/fx.cpp b/examples/media/fx/fx.cpp
index ea99966..304db1c 100644
--- a/examples/media/fx/fx.cpp
+++ b/examples/media/fx/fx.cpp
@@ -2,22 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <inttypes.h>
-#include <stdio.h>
-
 #include <audio-utils/audio-input.h>
 #include <fbl/algorithm.h>
 #include <fbl/auto_call.h>
 #include <fbl/limits.h>
 #include <fbl/unique_ptr.h>
-#include <fbl/vmo_mapper.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <inttypes.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
+#include <lib/fit/function.h>
+#include <lib/vmo-utils/vmo_mapper.h>
 #include <lib/zx/time.h>
 #include <lib/zx/vmar.h>
 #include <lib/zx/vmo.h>
-#include <media/cpp/fidl.h>
+#include <stdio.h>
 #include <zircon/compiler.h>
 #include <zircon/errors.h>
 #include <zircon/types.h>
@@ -25,7 +25,6 @@
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fsl/tasks/fd_waiter.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/media/timeline/timeline_function.h"
 
 #include "garnet/lib/media/wav_writer/wav_writer.h"
@@ -78,12 +77,12 @@
 
 class FxProcessor {
  public:
-  FxProcessor(fbl::unique_ptr<AudioInput> input, fxl::Closure quit_callback)
-      : input_(fbl::move(input)), quit_callback_(quit_callback) {
+  FxProcessor(fbl::unique_ptr<AudioInput> input, fit::closure quit_callback)
+      : input_(fbl::move(input)), quit_callback_(std::move(quit_callback)) {
     FXL_DCHECK(quit_callback_);
   }
 
-  void Startup(media::AudioServerPtr audio_server);
+  void Startup(fuchsia::media::AudioServerPtr audio_server);
 
  private:
   using EffectFn = void (FxProcessor::*)(int16_t* src, int16_t* dst,
@@ -105,8 +104,8 @@
   void HandleKeystroke(zx_status_t status, uint32_t events);
   void Shutdown(const char* reason = "unknown");
   void ProcessInput();
-  void ProduceOutputPackets(::media::AudioPacket* out_pkt1,
-                            ::media::AudioPacket* out_pkt2);
+  void ProduceOutputPackets(fuchsia::media::AudioPacket* out_pkt1,
+                            fuchsia::media::AudioPacket* out_pkt2);
   void ApplyEffect(int16_t* src, uint32_t src_offset, uint32_t src_rb_size,
                    int16_t* dst, uint32_t dst_offset, uint32_t dst_rb_size,
                    uint32_t frames, EffectFn effect);
@@ -128,7 +127,7 @@
                   float mix_delta = 0.0f);
   void UpdatePreampGain(float delta);
 
-  fbl::VmoMapper output_buf_;
+  vmo_utils::VmoMapper output_buf_;
   size_t output_buf_sz_ = 0;
   uint32_t output_buf_frames_ = 0;
   uint64_t output_buf_wp_ = 0;
@@ -150,9 +149,9 @@
   uint16_t preamp_gain_fixed_;
 
   fbl::unique_ptr<AudioInput> input_;
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   uint32_t input_buffer_frames_ = 0;
-  media::AudioRenderer2Ptr audio_renderer_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer_;
   media::TimelineFunction clock_mono_to_input_wr_ptr_;
   fsl::FDWaiter keystroke_waiter_;
   media::audio::WavWriter<kWavWriterEnabled> wav_writer_;
@@ -161,7 +160,7 @@
   bool lead_time_frames_known_ = false;
 };
 
-void FxProcessor::Startup(media::AudioServerPtr audio_server) {
+void FxProcessor::Startup(fuchsia::media::AudioServerPtr audio_server) {
   auto cleanup = fbl::MakeAutoCall([this] { Shutdown("Startup failure"); });
 
   zx_thread_set_priority(24 /* HIGH_PRIORITY in LK */);
@@ -175,7 +174,7 @@
   input_buffer_frames_ = input_->ring_buffer_bytes() / input_->frame_sz();
 
   if (!wav_writer_.Initialize(
-          "/tmp/fx.wav", media::AudioSampleFormat::SIGNED_16,
+          "/tmp/fx.wav", fuchsia::media::AudioSampleFormat::SIGNED_16,
           input_->channel_cnt(), input_->frame_rate(), 16)) {
     printf("Unable to initialize WAV file for recording.\n");
     return;
@@ -184,12 +183,13 @@
   // Create a renderer.  Setup connection error handlers.
   audio_server->CreateRendererV2(audio_renderer_.NewRequest());
 
-  audio_renderer_.set_error_handler(
-      [this]() { Shutdown("AudioRenderer connection closed"); });
+  audio_renderer_.set_error_handler([this]() {
+    Shutdown("fuchsia::media::AudioRenderer connection closed");
+  });
 
   // Set the format.
-  media::AudioPcmFormat format;
-  format.sample_format = media::AudioSampleFormat::SIGNED_16;
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = fuchsia::media::AudioSampleFormat::SIGNED_16;
   format.channels = input_->channel_cnt();
   format.frames_per_second = input_->frame_rate();
   audio_renderer_->SetPcmFormat(std::move(format));
@@ -443,7 +443,7 @@
 }
 
 void FxProcessor::ProcessInput() {
-  media::AudioPacket pkt1, pkt2;
+  fuchsia::media::AudioPacket pkt1, pkt2;
 
   pkt1.payload_size = 0;
   pkt2.payload_size = 0;
@@ -482,8 +482,8 @@
                          zx::nsec(PROCESS_CHUNK_TIME));
 }
 
-void FxProcessor::ProduceOutputPackets(::media::AudioPacket* out_pkt1,
-                                       ::media::AudioPacket* out_pkt2) {
+void FxProcessor::ProduceOutputPackets(fuchsia::media::AudioPacket* out_pkt1,
+                                       fuchsia::media::AudioPacket* out_pkt2) {
   // Figure out how much input data we have to process.
   zx_time_t now = zx_clock_get(ZX_CLOCK_MONOTONIC);
   int64_t input_wp = clock_mono_to_input_wr_ptr_.Apply(now);
@@ -525,7 +525,7 @@
     out_pkt2->payload_offset = 0;
     out_pkt2->payload_size = (todo - pkt1_frames) * input_->frame_sz();
   } else {
-    out_pkt2->timestamp = ::media::kNoTimestamp;
+    out_pkt2->timestamp = fuchsia::media::kNoTimestamp;
     out_pkt2->payload_offset = 0;
     out_pkt2->payload_size = 0;
   }
@@ -733,8 +733,9 @@
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context =
       fuchsia::sys::StartupContext::CreateFromStartupInfo();
 
-  media::AudioServerPtr audio_server =
-      startup_context->ConnectToEnvironmentService<media::AudioServer>();
+  fuchsia::media::AudioServerPtr audio_server =
+      startup_context
+          ->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   FxProcessor fx(fbl::move(input), [&loop]() {
     async::PostTask(loop.async(), [&loop]() { loop.Quit(); });
diff --git a/examples/media/master_gain/main.cc b/examples/media/master_gain/main.cc
index 21481d6..ef54948 100644
--- a/examples/media/master_gain/main.cc
+++ b/examples/media/master_gain/main.cc
@@ -5,9 +5,9 @@
 #include <iomanip>
 #include <iostream>
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
-#include <media/cpp/fidl.h>
 
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
@@ -44,7 +44,8 @@
   auto startup_context = fuchsia::sys::StartupContext::CreateFromStartupInfo();
 
   auto audio_server =
-      startup_context->ConnectToEnvironmentService<media::AudioServer>();
+      startup_context
+          ->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   if (set_gain) {
     audio_server->SetMasterGain(gain_target);
diff --git a/examples/media/simple_sine/BUILD.gn b/examples/media/simple_sine/BUILD.gn
index d9e5eb0..e728e18 100644
--- a/examples/media/simple_sine/BUILD.gn
+++ b/examples/media/simple_sine/BUILD.gn
@@ -14,5 +14,6 @@
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/media/fidl",
+    "//zircon/public/lib/vmo-utils",
   ]
 }
diff --git a/examples/media/simple_sine/README.md b/examples/media/simple_sine/README.md
index 03ba4a7..fb4d790 100644
--- a/examples/media/simple_sine/README.md
+++ b/examples/media/simple_sine/README.md
@@ -1,7 +1,7 @@
 # Simple Sine Example App
 
 This directory contains an example application that shows, in simplest possible
-implementation, how to play audio via the lowest-layer FIDL interfaces. 
+implementation, how to play audio via the lowest-layer FIDL interfaces.
 
 ### USAGE
 
diff --git a/examples/media/simple_sine/main.cc b/examples/media/simple_sine/main.cc
index 3d3abb0..cd09408 100644
--- a/examples/media/simple_sine/main.cc
+++ b/examples/media/simple_sine/main.cc
@@ -4,6 +4,7 @@
 
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
+
 #include "garnet/examples/media/simple_sine/simple_sine.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fxl/command_line.h"
diff --git a/examples/media/simple_sine/simple_sine.cc b/examples/media/simple_sine/simple_sine.cc
index 4b83e31..8aeb11f 100644
--- a/examples/media/simple_sine/simple_sine.cc
+++ b/examples/media/simple_sine/simple_sine.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "garnet/examples/media/simple_sine/simple_sine.h"
+
 #include "lib/fxl/logging.h"
 
 namespace {
@@ -31,7 +32,8 @@
 
 namespace examples {
 
-MediaApp::MediaApp(fxl::Closure quit_callback) : quit_callback_(quit_callback) {
+MediaApp::MediaApp(fit::closure quit_callback)
+    : quit_callback_(std::move(quit_callback)) {
   FXL_DCHECK(quit_callback_);
 }
 
@@ -54,21 +56,23 @@
     SendPacket(CreateAudioPacket(payload_num));
   }
 
-  audio_renderer_->PlayNoReply(media::kNoTimestamp, media::kNoTimestamp);
+  audio_renderer_->PlayNoReply(fuchsia::media::kNoTimestamp,
+                               fuchsia::media::kNoTimestamp);
 }
 
 // Use StartupContext to acquire AudioServerPtr and AudioRenderer2Ptr in
 // turn. Set error handler, in case of channel closure.
 void MediaApp::AcquireRenderer(fuchsia::sys::StartupContext* app_context) {
   // AudioServer is needed only long enough to create the renderer(s).
-  media::AudioServerPtr audio_server =
-      app_context->ConnectToEnvironmentService<media::AudioServer>();
+  fuchsia::media::AudioServerPtr audio_server =
+      app_context->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   // Only one of [AudioRenderer or MediaRenderer] must be kept open for playback
   audio_server->CreateRendererV2(audio_renderer_.NewRequest());
 
   audio_renderer_.set_error_handler([this]() {
-    FXL_LOG(ERROR) << "AudioRenderer connection lost. Quitting.";
+    FXL_LOG(ERROR)
+        << "fuchsia::media::AudioRenderer connection lost. Quitting.";
     Shutdown();
   });
 }
@@ -77,10 +81,11 @@
 void MediaApp::SetMediaType() {
   FXL_DCHECK(audio_renderer_);
 
-  media::AudioPcmFormat format;
+  fuchsia::media::AudioPcmFormat format;
 
-  format.sample_format = (use_float_ ? media::AudioSampleFormat::FLOAT
-                                     : media::AudioSampleFormat::SIGNED_16);
+  format.sample_format =
+      (use_float_ ? fuchsia::media::AudioSampleFormat::FLOAT
+                  : fuchsia::media::AudioSampleFormat::SIGNED_16);
   format.channels = kNumChannels;
   format.frames_per_second = kRendererFrameRate;
 
@@ -129,8 +134,8 @@
 
 // We divided our cross-proc buffer into different zones, called payloads.
 // Create a packet corresponding to this particular payload.
-media::AudioPacket MediaApp::CreateAudioPacket(size_t payload_num) {
-  media::AudioPacket packet;
+fuchsia::media::AudioPacket MediaApp::CreateAudioPacket(size_t payload_num) {
+  fuchsia::media::AudioPacket packet;
   packet.payload_offset = (payload_num * payload_size_) % total_mapping_size_;
   packet.payload_size = payload_size_;
   return packet;
@@ -139,7 +144,7 @@
 // Submit a packet, incrementing our count of packets sent. When it returns:
 // a. if there are more packets to send, create and send the next packet;
 // b. if all expected packets have completed, begin closing down the system.
-void MediaApp::SendPacket(media::AudioPacket packet) {
+void MediaApp::SendPacket(fuchsia::media::AudioPacket packet) {
   ++num_packets_sent_;
   audio_renderer_->SendPacket(std::move(packet),
                               [this]() { OnSendPacketComplete(); });
diff --git a/examples/media/simple_sine/simple_sine.h b/examples/media/simple_sine/simple_sine.h
index 2a51cc2..517c1f9 100644
--- a/examples/media/simple_sine/simple_sine.h
+++ b/examples/media/simple_sine/simple_sine.h
@@ -5,16 +5,17 @@
 #ifndef GARNET_EXAMPLES_MEDIA_SIMPLE_SINE_SIMPLE_SINE_H_
 #define GARNET_EXAMPLES_MEDIA_SIMPLE_SINE_SIMPLE_SINE_H_
 
-#include <fbl/vmo_mapper.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
+#include <lib/vmo-utils/vmo_mapper.h>
+
 #include "lib/app/cpp/startup_context.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace examples {
 
 class MediaApp {
  public:
-  MediaApp(fxl::Closure quit_callback);
+  MediaApp(fit::closure quit_callback);
 
   void set_float(bool enable_float) { use_float_ = enable_float; }
 
@@ -27,17 +28,17 @@
   zx_status_t CreateMemoryMapping();
   void WriteAudioIntoBuffer();
 
-  media::AudioPacket CreateAudioPacket(size_t packet_num);
-  void SendPacket(media::AudioPacket packet);
+  fuchsia::media::AudioPacket CreateAudioPacket(size_t packet_num);
+  void SendPacket(fuchsia::media::AudioPacket packet);
   void OnSendPacketComplete();
 
   void Shutdown();
 
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
 
-  media::AudioRenderer2Ptr audio_renderer_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer_;
 
-  fbl::VmoMapper payload_buffer_;
+  vmo_utils::VmoMapper payload_buffer_;
   size_t sample_size_;
   size_t payload_size_;
   size_t total_mapping_size_;
diff --git a/examples/media/simple_sine_sync/BUILD.gn b/examples/media/simple_sine_sync/BUILD.gn
index 7f06dae..c2c8e9a 100644
--- a/examples/media/simple_sine_sync/BUILD.gn
+++ b/examples/media/simple_sine_sync/BUILD.gn
@@ -14,5 +14,6 @@
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/media/fidl",
     "//garnet/public/lib/media/transport",
+    "//zircon/public/lib/vmo-utils",
   ]
 }
diff --git a/examples/media/simple_sine_sync/main.cc b/examples/media/simple_sine_sync/main.cc
index 1e5ae5d..b8d3202 100644
--- a/examples/media/simple_sine_sync/main.cc
+++ b/examples/media/simple_sine_sync/main.cc
@@ -4,11 +4,10 @@
 
 #include <iostream>
 
+#include "garnet/examples/media/simple_sine_sync/simple_sine_sync.h"
 #include "lib/fxl/command_line.h"
 #include "lib/fxl/strings/string_number_conversions.h"
 
-#include "garnet/examples/media/simple_sine_sync/simple_sine_sync.h"
-
 namespace {
 
 constexpr char kLowWaterMarkSwitch[] = "wake";
diff --git a/examples/media/simple_sine_sync/simple_sine_sync.cc b/examples/media/simple_sine_sync/simple_sine_sync.cc
index 172d800..9a91b6c 100644
--- a/examples/media/simple_sine_sync/simple_sine_sync.cc
+++ b/examples/media/simple_sine_sync/simple_sine_sync.cc
@@ -3,9 +3,11 @@
 // found in the LICENSE file.
 
 #include "garnet/examples/media/simple_sine_sync/simple_sine_sync.h"
-#include <media/cpp/fidl.h>
+
+#include <fuchsia/media/cpp/fidl.h>
 #include <math.h>
 #include <zircon/syscalls.h>
+
 #include "lib/app/cpp/environment_services.h"
 #include "lib/fidl/cpp/synchronous_interface_ptr.h"
 #include "lib/fxl/logging.h"
@@ -96,8 +98,9 @@
 
   int64_t ref_start_time;
   int64_t media_start_time;
-  audio_renderer_->Play(media::kNoTimestamp, media::kNoTimestamp,
-                        &ref_start_time, &media_start_time);
+  audio_renderer_->Play(fuchsia::media::kNoTimestamp,
+                        fuchsia::media::kNoTimestamp, &ref_start_time,
+                        &media_start_time);
   start_time_known_ = true;
 
   // TODO(johngro): This program is making the assumption that the platform's
@@ -125,9 +128,9 @@
   return 0;
 }
 
-// Connect to the AudioServer and get an AudioRenderer.
+// Connect to the udioServer and get an AudioRenderer.
 bool MediaApp::AcquireRenderer() {
-  media::AudioServerSyncPtr audio_server;
+  fuchsia::media::AudioServerSyncPtr audio_server;
   fuchsia::sys::ConnectToEnvironmentService(audio_server.NewRequest());
   return audio_server->CreateRendererV2(audio_renderer_.NewRequest());
 }
@@ -136,9 +139,10 @@
 void MediaApp::SetMediaType() {
   FXL_DCHECK(audio_renderer_);
 
-  media::AudioPcmFormat format;
-  format.sample_format = use_float_ ? media::AudioSampleFormat::FLOAT
-                                    : media::AudioSampleFormat::SIGNED_16;
+  fuchsia::media::AudioPcmFormat format;
+  format.sample_format = use_float_
+                             ? fuchsia::media::AudioSampleFormat::FLOAT
+                             : fuchsia::media::AudioSampleFormat::SIGNED_16;
   format.channels = kNumChannels;
   format.frames_per_second = kRendererFrameRate;
 
@@ -184,15 +188,15 @@
 }
 
 // Create a packet for this payload.
-media::AudioPacket MediaApp::CreateAudioPacket(size_t payload_num) {
-  media::AudioPacket packet;
+fuchsia::media::AudioPacket MediaApp::CreateAudioPacket(size_t payload_num) {
+  fuchsia::media::AudioPacket packet;
   packet.payload_offset = (payload_num % kNumPayloads) * payload_size_;
   packet.payload_size = payload_size_;
   return packet;
 }
 
 // Submit a packet, incrementing our count of packets sent.
-bool MediaApp::SendAudioPacket(media::AudioPacket packet) {
+bool MediaApp::SendAudioPacket(fuchsia::media::AudioPacket packet) {
   if (verbose_) {
     const float delay =
         (start_time_known_
diff --git a/examples/media/simple_sine_sync/simple_sine_sync.h b/examples/media/simple_sine_sync/simple_sine_sync.h
index 29e211c..560752f 100644
--- a/examples/media/simple_sine_sync/simple_sine_sync.h
+++ b/examples/media/simple_sine_sync/simple_sine_sync.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_EXAMPLES_MEDIA_SIMPLE_SINE_SYNC_SIMPLE_SINE_SYNC_H_
+#define GARNET_EXAMPLES_MEDIA_SIMPLE_SINE_SYNC_SIMPLE_SINE_SYNC_H_
 
-#include <fbl/vmo_mapper.h>
-
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/vmo-utils/vmo_mapper.h>
 
 namespace examples {
 
@@ -36,14 +36,14 @@
 
   bool RefillBuffer();
 
-  media::AudioPacket CreateAudioPacket(size_t payload_num);
-  bool SendAudioPacket(media::AudioPacket packet);
+  fuchsia::media::AudioPacket CreateAudioPacket(size_t payload_num);
+  bool SendAudioPacket(fuchsia::media::AudioPacket packet);
 
   void WaitForPackets(size_t num_packets);
 
-  media::AudioRenderer2SyncPtr audio_renderer_;
+  fuchsia::media::AudioRenderer2SyncPtr audio_renderer_;
 
-  fbl::VmoMapper payload_buffer_;
+  vmo_utils::VmoMapper payload_buffer_;
   size_t sample_size_;
   size_t payload_size_;
   size_t total_mapping_size_;
@@ -58,3 +58,5 @@
 };
 
 }  // namespace examples
+
+#endif  // GARNET_EXAMPLES_MEDIA_SIMPLE_SINE_SYNC_SIMPLE_SINE_SYNC_H_
diff --git a/examples/media/tones/BUILD.gn b/examples/media/tones/BUILD.gn
index 7aa2842..81a517a 100644
--- a/examples/media/tones/BUILD.gn
+++ b/examples/media/tones/BUILD.gn
@@ -19,5 +19,7 @@
     "//garnet/public/lib/media/fidl",
     "//garnet/public/lib/media/timeline",
     "//zircon/public/lib/fbl",
+    "//zircon/public/lib/fit",
+    "//zircon/public/lib/vmo-utils",
   ]
 }
diff --git a/examples/media/tones/midi.h b/examples/media/tones/midi.h
index 74ab79a..612a4b7 100644
--- a/examples/media/tones/midi.h
+++ b/examples/media/tones/midi.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_EXAMPLES_MEDIA_TONES_MIDI_H_
+#define GARNET_EXAMPLES_MEDIA_TONES_MIDI_H_
 
 // clang-format off
 
@@ -42,3 +43,5 @@
 #define MIDI_REF_INDEX              69
 
 // clang-format on
+
+#endif  // GARNET_EXAMPLES_MEDIA_TONES_MIDI_H_
diff --git a/examples/media/tones/midi_keyboard.cc b/examples/media/tones/midi_keyboard.cc
index f620c6a..547e330 100644
--- a/examples/media/tones/midi_keyboard.cc
+++ b/examples/media/tones/midi_keyboard.cc
@@ -4,6 +4,8 @@
 
 #include "garnet/examples/media/tones/midi_keyboard.h"
 
+#include <iostream>
+
 #include <dirent.h>
 #include <fbl/auto_call.h>
 #include <fcntl.h>
@@ -11,7 +13,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <zircon/device/midi.h>
-#include <iostream>
 
 #include "garnet/examples/media/tones/midi.h"
 #include "garnet/examples/media/tones/tones.h"
@@ -80,7 +81,7 @@
   waiting_ = false;
 
   while (true) {
-    uint8_t event[3] = { 0 };
+    uint8_t event[3] = {0};
     int evt_size = ::read(dev_.get(), event, sizeof(event));
 
     if (evt_size < 0) {
@@ -116,8 +117,8 @@
     if ((cmd == MIDI_NOTE_ON) || (cmd == MIDI_NOTE_OFF)) {
       // By default, MIDI event sources map the value 60 to middle C.
       static constexpr int kOffsetMiddleC = 60;
-      int note = static_cast<int>(event[1] & MIDI_NOTE_NUMBER_MASK)
-               - kOffsetMiddleC;
+      int note =
+          static_cast<int>(event[1] & MIDI_NOTE_NUMBER_MASK) - kOffsetMiddleC;
       int velocity = static_cast<int>(event[2] & MIDI_NOTE_VELOCITY_MASK);
       bool note_on = (cmd == MIDI_NOTE_ON) && (velocity != 0);
 
diff --git a/examples/media/tones/midi_keyboard.h b/examples/media/tones/midi_keyboard.h
index 82d5a2f..3b40dc3 100644
--- a/examples/media/tones/midi_keyboard.h
+++ b/examples/media/tones/midi_keyboard.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_EXAMPLES_MEDIA_TONES_MIDI_KEYBOARD_H_
+#define GARNET_EXAMPLES_MEDIA_TONES_MIDI_KEYBOARD_H_
 
 #include <memory>
 
@@ -35,3 +36,5 @@
 };
 
 }  // namespace examples
+
+#endif  // GARNET_EXAMPLES_MEDIA_TONES_MIDI_KEYBOARD_H_
diff --git a/examples/media/tones/tone_generator.cc b/examples/media/tones/tone_generator.cc
index 639a5bd..34bd49c 100644
--- a/examples/media/tones/tone_generator.cc
+++ b/examples/media/tones/tone_generator.cc
@@ -11,10 +11,8 @@
 
 namespace examples {
 
-ToneGenerator::ToneGenerator(uint32_t frames_per_second,
-                             float frequency,
-                             float volume,
-                             float decay)
+ToneGenerator::ToneGenerator(uint32_t frames_per_second, float frequency,
+                             float volume, float decay)
     : frames_per_second_(frames_per_second),
       frequency_(frequency),
       volume_(volume),
@@ -22,8 +20,7 @@
       real_sample_(0.0f),
       imaginary_sample_(1.0f) {}
 
-void ToneGenerator::MixSamples(float* dest,
-                               uint32_t frame_count,
+void ToneGenerator::MixSamples(float* dest, uint32_t frame_count,
                                uint32_t channel_count) {
   // We're using the 'slope iteration method' here to avoid calling |sin| for
   // every sample or having to build a lookup table. While this method is
diff --git a/examples/media/tones/tone_generator.h b/examples/media/tones/tone_generator.h
index ca9ec52..2c3a1e2 100644
--- a/examples/media/tones/tone_generator.h
+++ b/examples/media/tones/tone_generator.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_MEDIA_FRAMEWORK_TONE_GENERATOR_H_
-#define SERVICES_MEDIA_FRAMEWORK_TONE_GENERATOR_H_
+#ifndef GARNET_EXAMPLES_MEDIA_TONES_TONE_GENERATOR_H_
+#define GARNET_EXAMPLES_MEDIA_TONES_TONE_GENERATOR_H_
 
 namespace examples {
 
@@ -15,9 +15,7 @@
   // |decay| specifies the factor by which volume should be reduced in one
   // second. A |decay| value of 0.0 produces a constant tone. A |decay| value
   // of 0.9 reducees the volume 90% (to 10%) in one second.
-  ToneGenerator(uint32_t frames_per_second,
-                float frequency,
-                float volume,
+  ToneGenerator(uint32_t frames_per_second, float frequency, float volume,
                 float decay);
 
   // Mixes |frame_count| samples into |dest|, summing the first sample into
@@ -39,4 +37,4 @@
 
 }  // namespace examples
 
-#endif  // SERVICES_MEDIA_FRAMEWORK_TONE_GENERATOR_H_
+#endif  // GARNET_EXAMPLES_MEDIA_TONES_TONE_GENERATOR_H_
diff --git a/examples/media/tones/tones.cc b/examples/media/tones/tones.cc
index 21b7135..49724d1 100644
--- a/examples/media/tones/tones.cc
+++ b/examples/media/tones/tones.cc
@@ -9,10 +9,10 @@
 #include <limits>
 
 #include <fbl/auto_call.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/async-loop/loop.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
-#include <media/cpp/fidl.h>
 
 #include "garnet/examples/media/tones/midi_keyboard.h"
 #include "lib/fxl/logging.h"
@@ -77,12 +77,12 @@
   }
 }
 
-static constexpr media::AudioSampleFormat kSampleFormat =
-    media::AudioSampleFormat::SIGNED_16;
+static constexpr fuchsia::media::AudioSampleFormat kSampleFormat =
+    fuchsia::media::AudioSampleFormat::SIGNED_16;
 static constexpr uint32_t kBytesPerFrame = kChannelCount * sizeof(uint16_t);
 #else
-static constexpr media::AudioSampleFormat kSampleFormat =
-    media::AudioSampleFormat::FLOAT;
+static constexpr fuchsia::media::AudioSampleFormat kSampleFormat =
+    fuchsia::media::AudioSampleFormat::FLOAT;
 static constexpr uint32_t kBytesPerFrame = kChannelCount * sizeof(float);
 #endif
 
@@ -97,13 +97,14 @@
 
 }  // namespace
 
-Tones::Tones(bool interactive, fxl::Closure quit_callback)
-    : interactive_(interactive), quit_callback_(quit_callback) {
+Tones::Tones(bool interactive, fit::closure quit_callback)
+    : interactive_(interactive), quit_callback_(std::move(quit_callback)) {
   // Connect to the audio service and get a renderer.
   auto startup_context = fuchsia::sys::StartupContext::CreateFromStartupInfo();
 
-  media::AudioServerPtr audio_server =
-      startup_context->ConnectToEnvironmentService<media::AudioServer>();
+  fuchsia::media::AudioServerPtr audio_server =
+      startup_context
+          ->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   audio_server->CreateRendererV2(audio_renderer_.NewRequest());
 
@@ -113,7 +114,7 @@
   });
 
   // Configure the format of the renderer.
-  media::AudioPcmFormat format;
+  fuchsia::media::AudioPcmFormat format;
   format.sample_format = kSampleFormat;
   format.channels = kChannelCount;
   format.frames_per_second = kFramesPerSecond;
@@ -257,7 +258,8 @@
     }
 
     SendPackets();
-    audio_renderer_->PlayNoReply(media::kNoTimestamp, media::kNoTimestamp);
+    audio_renderer_->PlayNoReply(fuchsia::media::kNoTimestamp,
+                                 fuchsia::media::kNoTimestamp);
     started_ = true;
   } else {
     SendPackets();
@@ -269,7 +271,7 @@
 void Tones::SendPackets() {
   while (!done() && (active_packets_in_flight_ < target_packets_in_flight_)) {
     // Allocate packet and locate its position in the buffer.
-    media::AudioPacket packet;
+    fuchsia::media::AudioPacket packet;
     packet.payload_offset = (pts_ * kBytesPerFrame) % payload_buffer_.size();
     packet.payload_size = kBytesPerBuffer;
 
diff --git a/examples/media/tones/tones.h b/examples/media/tones/tones.h
index 03a7b72..4b9dbb6 100644
--- a/examples/media/tones/tones.h
+++ b/examples/media/tones/tones.h
@@ -8,8 +8,9 @@
 #include <list>
 #include <map>
 
-#include <fbl/vmo_mapper.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
+#include <lib/vmo-utils/vmo_mapper.h>
 
 #include "garnet/examples/media/tones/tone_generator.h"
 #include "lib/app/cpp/startup_context.h"
@@ -23,7 +24,7 @@
 
 class Tones {
  public:
-  Tones(bool interactive, fxl::Closure quit_callback);
+  Tones(bool interactive, fit::closure quit_callback);
 
   ~Tones();
 
@@ -67,13 +68,13 @@
   }
 
   bool interactive_;
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   fsl::FDWaiter fd_waiter_;
-  media::AudioRenderer2Ptr audio_renderer_;
+  fuchsia::media::AudioRenderer2Ptr audio_renderer_;
   std::map<int64_t, float> frequencies_by_pts_;
   std::list<ToneGenerator> tone_generators_;
   int64_t pts_ = 0;
-  fbl::VmoMapper payload_buffer_;
+  vmo_utils::VmoMapper payload_buffer_;
   uint32_t active_packets_in_flight_ = 0;
   uint32_t target_packets_in_flight_ = 0;
   bool started_ = false;
diff --git a/examples/media/tts/BUILD.gn b/examples/media/tts/BUILD.gn
index 8ac5188..7127220 100644
--- a/examples/media/tts/BUILD.gn
+++ b/examples/media/tts/BUILD.gn
@@ -11,5 +11,6 @@
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/tts/fidl",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/examples/media/tts/main.cc b/examples/media/tts/main.cc
index a4d003d..0fc73e0 100644
--- a/examples/media/tts/main.cc
+++ b/examples/media/tts/main.cc
@@ -2,33 +2,33 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <fuchsia/tts/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
-#include <tts/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "lib/app/cpp/connect.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/synchronous_interface_ptr.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 
 namespace {
 
 class TtsClient {
  public:
-  TtsClient(fxl::Closure quit_callback);
+  TtsClient(fit::closure quit_callback);
   void Say(std::string words);
 
  private:
-  fxl::Closure quit_callback_;
-  tts::TtsServicePtr tts_service_;
+  fit::closure quit_callback_;
+  fuchsia::tts::TtsServicePtr tts_service_;
 };
 
-TtsClient::TtsClient(fxl::Closure quit_callback)
-    : quit_callback_(quit_callback) {
+TtsClient::TtsClient(fit::closure quit_callback)
+    : quit_callback_(std::move(quit_callback)) {
   FXL_DCHECK(quit_callback_);
   auto app_ctx = fuchsia::sys::StartupContext::CreateFromStartupInfo();
-  tts_service_ = app_ctx->ConnectToEnvironmentService<tts::TtsService>();
+  tts_service_ = app_ctx->ConnectToEnvironmentService<fuchsia::tts::TtsService>();
   tts_service_.set_error_handler([this]() {
     printf("Connection error when trying to talk to the TtsService\n");
     quit_callback_();
diff --git a/examples/media/wav_record/BUILD.gn b/examples/media/wav_record/BUILD.gn
index fb12da1..268c833 100644
--- a/examples/media/wav_record/BUILD.gn
+++ b/examples/media/wav_record/BUILD.gn
@@ -3,18 +3,18 @@
 #found in the LICENSE file.
 
 executable("wav_record") {
-  sources =
-      [
-        "main.cc",
-        "wav_recorder.cc",
-        "wav_recorder.h",
-      ]
+  sources = [
+    "main.cc",
+    "wav_recorder.cc",
+    "wav_recorder.h",
+  ]
 
-      deps = [
-        "//garnet/lib/media/wav_writer",
-        "//garnet/public/lib/app/cpp",
-        "//garnet/public/lib/fsl",
-        "//garnet/public/lib/media/audio",
-        "//garnet/public/lib/media/fidl",
-      ]
+  deps = [
+    "//garnet/lib/media/wav_writer",
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/fsl",
+    "//garnet/public/lib/media/audio",
+    "//garnet/public/lib/media/fidl",
+    "//zircon/public/lib/fit",
+  ]
 }
diff --git a/examples/media/wav_record/wav_recorder.cc b/examples/media/wav_record/wav_recorder.cc
index cb6cc49..6edbc58 100644
--- a/examples/media/wav_record/wav_recorder.cc
+++ b/examples/media/wav_record/wav_recorder.cc
@@ -62,8 +62,8 @@
   filename_ = pos_args[0].c_str();
 
   // Connect to the mixer and obtain a capturer
-  media::AudioServerPtr audio_server =
-      app_context->ConnectToEnvironmentService<media::AudioServer>();
+  fuchsia::media::AudioServerPtr audio_server =
+      app_context->ConnectToEnvironmentService<fuchsia::media::AudioServer>();
 
   audio_server->CreateCapturer(capturer_.NewRequest(), loopback_);
   capturer_.set_error_handler([this]() {
@@ -72,7 +72,7 @@
   });
 
   // Fetch the initial media type and figure out what we need to do from there.
-  capturer_->GetMediaType([this](media::MediaType type) {
+  capturer_->GetMediaType([this](fuchsia::media::MediaType type) {
     OnDefaultFormatFetched(std::move(type));
   });
 
@@ -90,8 +90,8 @@
   printf("  --%s : capture using 'async-mode'\n", kAsyncModeOption.c_str());
   printf("  --%s : use floating-point format\n", kFloatFormatOption.c_str());
   printf("  --%s=<rate> : desired capture frame rate, on the range [%u, %u].\n",
-         kFrameRateOption.c_str(), media::kMinLpcmFramesPerSecond,
-         media::kMaxLpcmFramesPerSecond);
+         kFrameRateOption.c_str(), fuchsia::media::kMinLpcmFramesPerSecond,
+         fuchsia::media::kMaxLpcmFramesPerSecond);
   printf(
       "  --%s=<count> : desired number of channels to capture, on the range "
       "[%u, %u].\n",
@@ -155,7 +155,7 @@
   capturer_->CaptureAt(
       capture_frame_offset_,
       capture_frames_per_chunk_,
-      [this](media::MediaPacket packet) {
+      [this](fuchsia::media::MediaPacket packet) {
         OnPacketCaptured(std::move(packet));
       });
   // clang-format on
@@ -166,7 +166,7 @@
   }
 }
 
-void WavRecorder::OnDefaultFormatFetched(media::MediaType type) {
+void WavRecorder::OnDefaultFormatFetched(fuchsia::media::MediaType type) {
   auto cleanup = fbl::MakeAutoCall([this]() { Shutdown(); });
   zx_status_t res;
 
@@ -178,8 +178,8 @@
   const auto& fmt = type.details.audio();
 
   sample_format_ = cmd_line_.HasOption(kFloatFormatOption)
-                       ? media::AudioSampleFormat::FLOAT
-                       : media::AudioSampleFormat::SIGNED_16;
+                       ? fuchsia::media::AudioSampleFormat::FLOAT
+                       : fuchsia::media::AudioSampleFormat::SIGNED_16;
   channel_count_ = fmt.channels;
   frames_per_second_ = fmt.frames_per_second;
 
@@ -197,10 +197,11 @@
       return;
     }
 
-    if ((rate < media::kMinLpcmFramesPerSecond) ||
-        (rate > media::kMaxLpcmFramesPerSecond)) {
+    if ((rate < fuchsia::media::kMinLpcmFramesPerSecond) ||
+        (rate > fuchsia::media::kMaxLpcmFramesPerSecond)) {
       printf("Frame rate (%u) must be on the range [%u, %u]\n", rate,
-             media::kMinLpcmFramesPerSecond, media::kMaxLpcmFramesPerSecond);
+             fuchsia::media::kMinLpcmFramesPerSecond,
+             fuchsia::media::kMaxLpcmFramesPerSecond);
       return;
     }
 
@@ -230,8 +231,9 @@
   }
 
   uint32_t bytes_per_sample =
-      (sample_format_ == media::AudioSampleFormat::FLOAT) ? sizeof(float)
-                                                          : sizeof(int16_t);
+      (sample_format_ == fuchsia::media::AudioSampleFormat::FLOAT)
+          ? sizeof(float)
+          : sizeof(int16_t);
   bytes_per_frame_ = channel_count_ * bytes_per_sample;
   uint32_t bits_per_sample = bytes_per_sample * 8;
 
@@ -276,22 +278,24 @@
     FXL_DCHECK(payload_buf_frames_);
     FXL_DCHECK(capture_frames_per_chunk_);
     FXL_DCHECK((payload_buf_frames_ % capture_frames_per_chunk_) == 0);
-    capturer_.events().OnPacketCaptured = [this](media::MediaPacket pkt) {
-      OnPacketCaptured(std::move(pkt));
-    };
+    capturer_.events().OnPacketCaptured =
+        [this](fuchsia::media::MediaPacket pkt) {
+          OnPacketCaptured(std::move(pkt));
+        };
     capturer_->StartAsyncCapture(capture_frames_per_chunk_);
   }
 
   printf("Recording %s, %u Hz, %u channel linear PCM from %s into '%s'\n",
-         sample_format_ == media::AudioSampleFormat::FLOAT ? "32-bit float"
-                                                           : "16-bit signed",
+         sample_format_ == fuchsia::media::AudioSampleFormat::FLOAT
+             ? "32-bit float"
+             : "16-bit signed",
          frames_per_second_, channel_count_,
          loopback_ ? "loopback" : "default input", filename_);
 
   cleanup.cancel();
 }
 
-void WavRecorder::OnPacketCaptured(media::MediaPacket pkt) {
+void WavRecorder::OnPacketCaptured(fuchsia::media::MediaPacket pkt) {
   if (verbose_) {
     printf("PACKET [%6lu, %6lu] flags 0x%02x : ts %ld\n", pkt.payload_offset,
            pkt.payload_size, pkt.flags, pkt.pts);
@@ -317,7 +321,7 @@
 
   if (!clean_shutdown_ && (capturer_.events().OnPacketCaptured == nullptr)) {
     SendCaptureJob();
-  } else if (pkt.flags & media::kFlagEos) {
+  } else if (pkt.flags & fuchsia::media::kFlagEos) {
     Shutdown();
   }
 }
diff --git a/examples/media/wav_record/wav_recorder.h b/examples/media/wav_record/wav_recorder.h
index 282eb0c..976abe2 100644
--- a/examples/media/wav_record/wav_recorder.h
+++ b/examples/media/wav_record/wav_recorder.h
@@ -5,21 +5,22 @@
 #ifndef GARNET_EXAMPLES_MEDIA_WAV_RECORD_WAV_RECORDER_H_
 #define GARNET_EXAMPLES_MEDIA_WAV_RECORD_WAV_RECORDER_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "garnet/lib/media/wav_writer/wav_writer.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fsl/tasks/fd_waiter.h"
 #include "lib/fxl/command_line.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/logging.h"
 
 namespace examples {
 
 class WavRecorder {
  public:
-  WavRecorder(fxl::CommandLine cmd_line, fxl::Closure quit_callback)
-      : cmd_line_(std::move(cmd_line)), quit_callback_(quit_callback) {
+  WavRecorder(fxl::CommandLine cmd_line, fit::closure quit_callback)
+      : cmd_line_(std::move(cmd_line)),
+        quit_callback_(std::move(quit_callback)) {
     FXL_DCHECK(quit_callback_);
   }
 
@@ -31,16 +32,16 @@
   void Shutdown();
   bool SetupPayloadBuffer();
   void SendCaptureJob();
-  void OnDefaultFormatFetched(media::MediaType type);
-  void OnPacketCaptured(media::MediaPacket pkt);
+  void OnDefaultFormatFetched(fuchsia::media::MediaType type);
+  void OnPacketCaptured(fuchsia::media::MediaPacket pkt);
   void OnQuit();
 
-  media::AudioCapturerPtr capturer_;
+  fuchsia::media::AudioCapturerPtr capturer_;
   fsl::FDWaiter keystroke_waiter_;
   media::audio::WavWriter<> wav_writer_;
 
   fxl::CommandLine cmd_line_;
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   const char* filename_ = "";
   bool verbose_ = false;
   bool loopback_ = false;
@@ -50,7 +51,7 @@
   size_t payload_buf_size_ = 0;
   size_t payload_buf_frames_ = 0;
 
-  media::AudioSampleFormat sample_format_;
+  fuchsia::media::AudioSampleFormat sample_format_;
   uint32_t channel_count_ = 0;
   uint32_t frames_per_second_ = 0;
   uint32_t bytes_per_frame_ = 0;
diff --git a/examples/netconnector/BUILD.gn b/examples/netconnector/BUILD.gn
index e5a1b12..0c15400 100644
--- a/examples/netconnector/BUILD.gn
+++ b/examples/netconnector/BUILD.gn
@@ -13,7 +13,9 @@
     "netconnector_example",
   ]
 
-  binaries = [ {
-        name = "netconnector_example"
-      } ]
+  binaries = [
+    {
+      name = "netconnector_example"
+    },
+  ]
 }
diff --git a/examples/netconnector/netconnector_example/BUILD.gn b/examples/netconnector/netconnector_example/BUILD.gn
index 11cca26..8d98d1c 100644
--- a/examples/netconnector/netconnector_example/BUILD.gn
+++ b/examples/netconnector/netconnector_example/BUILD.gn
@@ -21,5 +21,6 @@
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/netconnector/cpp",
     "//garnet/public/lib/netconnector/fidl",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/examples/netconnector/netconnector_example/main.cc b/examples/netconnector/netconnector_example/main.cc
index 0e70634..fbfa385 100644
--- a/examples/netconnector/netconnector_example/main.cc
+++ b/examples/netconnector/netconnector_example/main.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <netconnector/cpp/fidl.h>
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
+#include <netconnector/cpp/fidl.h>
 
 #include "garnet/examples/netconnector/netconnector_example/netconnector_example_impl.h"
 #include "garnet/examples/netconnector/netconnector_example/netconnector_example_params.h"
diff --git a/examples/netconnector/netconnector_example/netconnector_example_impl.cc b/examples/netconnector/netconnector_example/netconnector_example_impl.cc
index 81c3491..119d03c 100644
--- a/examples/netconnector/netconnector_example/netconnector_example_impl.cc
+++ b/examples/netconnector/netconnector_example/netconnector_example_impl.cc
@@ -6,8 +6,8 @@
 
 #include <lib/async/default.h>
 #include <lib/zx/channel.h>
-
 #include <netconnector/cpp/fidl.h>
+
 #include "garnet/examples/netconnector/netconnector_example/netconnector_example_params.h"
 #include "lib/fxl/logging.h"
 
@@ -21,8 +21,8 @@
 }  // namespace
 
 NetConnectorExampleImpl::NetConnectorExampleImpl(
-    NetConnectorExampleParams* params, fxl::Closure quit_callback)
-    : quit_callback_(quit_callback),
+    NetConnectorExampleParams* params, fit::closure quit_callback)
+    : quit_callback_(std::move(quit_callback)),
       startup_context_(fuchsia::sys::StartupContext::CreateFromStartupInfo()) {
   // The MessageRelay makes using the channel easier. Hook up its callbacks.
   message_relay_.SetMessageReceivedCallback(
diff --git a/examples/netconnector/netconnector_example/netconnector_example_impl.h b/examples/netconnector/netconnector_example/netconnector_example_impl.h
index 4057f3e..b7b1a53 100644
--- a/examples/netconnector/netconnector_example/netconnector_example_impl.h
+++ b/examples/netconnector/netconnector_example/netconnector_example_impl.h
@@ -5,12 +5,12 @@
 #ifndef GARNET_EXAMPLES_NETCONNECTOR_NETCONNECTOR_EXAMPLE_NETCONNECTOR_EXAMPLE_IMPL_H_
 #define GARNET_EXAMPLES_NETCONNECTOR_NETCONNECTOR_EXAMPLE_NETCONNECTOR_EXAMPLE_IMPL_H_
 
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
 #include "garnet/examples/netconnector/netconnector_example/netconnector_example_params.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/netconnector/cpp/message_relay.h"
 
@@ -19,7 +19,7 @@
 class NetConnectorExampleImpl {
  public:
   NetConnectorExampleImpl(NetConnectorExampleParams* params,
-                          fxl::Closure quit_callback);
+                          fit::closure quit_callback);
 
   ~NetConnectorExampleImpl();
 
@@ -28,7 +28,7 @@
 
   void HandleReceivedMessage(std::vector<uint8_t> message);
 
-  fxl::Closure quit_callback_;
+  fit::closure quit_callback_;
   std::unique_ptr<fuchsia::sys::StartupContext> startup_context_;
   netconnector::MessageRelay message_relay_;
   std::vector<std::string>::const_iterator conversation_iter_;
diff --git a/examples/netconnector/netconnector_example/netconnector_example_params.h b/examples/netconnector/netconnector_example/netconnector_example_params.h
index ca3daea..7ffc8f5 100644
--- a/examples/netconnector/netconnector_example/netconnector_example_params.h
+++ b/examples/netconnector/netconnector_example/netconnector_example_params.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_EXAMPLES_NETCONNECTOR_NETCONNECTOR_EXAMPLE_NETCONNECTOR_EXAMPLE_PARAMS_H_
+#define GARNET_EXAMPLES_NETCONNECTOR_NETCONNECTOR_EXAMPLE_NETCONNECTOR_EXAMPLE_PARAMS_H_
 
 #include <string>
 
@@ -34,3 +35,5 @@
 };
 
 }  // namespace examples
+
+#endif  // GARNET_EXAMPLES_NETCONNECTOR_NETCONNECTOR_EXAMPLE_NETCONNECTOR_EXAMPLE_PARAMS_H_
diff --git a/examples/ui/BUILD.gn b/examples/ui/BUILD.gn
index 2cdf98a..4d35c31 100644
--- a/examples/ui/BUILD.gn
+++ b/examples/ui/BUILD.gn
@@ -13,6 +13,7 @@
     "shadertoy/client",
     "shadertoy/service",
     "shapes",
+    "shapes_a11y",
     "sketchy",
     "spinning_square",
     "tile",
@@ -104,6 +105,14 @@
   binary = "shapes_view"
 }
 
+package("shapes_a11y_view") {
+  deps = [
+    "shapes_a11y",
+  ]
+
+  binary = "shapes_a11y_view"
+}
+
 package("sketchy_client") {
   deprecated_system_image = true
 
diff --git a/examples/ui/shadertoy/client/view.cc b/examples/ui/shadertoy/client/view.cc
index 689e8ad..520109c 100644
--- a/examples/ui/shadertoy/client/view.cc
+++ b/examples/ui/shadertoy/client/view.cc
@@ -72,7 +72,7 @@
   // Pass the other end of the ImagePipe to the Session, and wrap the
   // resulting resource in a Material.
   uint32_t image_pipe_id = session()->AllocResourceId();
-  session()->Enqueue(scenic_lib::NewCreateImagePipeCommand(
+  session()->Enqueue(scenic_lib::NewCreateImagePipeCmd(
       image_pipe_id, std::move(image_pipe_request)));
   scenic_lib::Material material(session());
   material.SetTexture(image_pipe_id);
diff --git a/examples/ui/shadertoy/service/BUILD.gn b/examples/ui/shadertoy/service/BUILD.gn
index 8e1dd4a..23fcede 100644
--- a/examples/ui/shadertoy/service/BUILD.gn
+++ b/examples/ui/shadertoy/service/BUILD.gn
@@ -37,6 +37,7 @@
     "//garnet/public/lib/ui/gfx/fidl",
     "//garnet/public/lib/ui/scenic:fidl_helpers",
     "//garnet/public/lib/vulkan",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/trace-provider",
   ]
 
diff --git a/examples/ui/shadertoy/service/compiler.h b/examples/ui/shadertoy/service/compiler.h
index 686bcf6..d572a97 100644
--- a/examples/ui/shadertoy/service/compiler.h
+++ b/examples/ui/shadertoy/service/compiler.h
@@ -11,6 +11,7 @@
 #include <thread>
 
 #include <lib/async-loop/cpp/loop.h>
+#include <lib/fit/function.h>
 #include <vulkan/vulkan.hpp>
 
 #include "garnet/examples/ui/shadertoy/service/pipeline.h"
@@ -40,7 +41,7 @@
   };
 
   // Callback that is used to asynchronously notify clients of the result.
-  using ResultCallback = std::function<void(Result)>;
+  using ResultCallback = fit::function<void(Result)>;
 
   // Compile GLSL source code on a background thread, and post a task to invoke
   // ResultCallback on the main thread.
diff --git a/examples/ui/shadertoy/service/imagepipe_shadertoy.cc b/examples/ui/shadertoy/service/imagepipe_shadertoy.cc
index a94c979..94f3839 100644
--- a/examples/ui/shadertoy/service/imagepipe_shadertoy.cc
+++ b/examples/ui/shadertoy/service/imagepipe_shadertoy.cc
@@ -5,17 +5,12 @@
 #include "garnet/examples/ui/shadertoy/service/imagepipe_shadertoy.h"
 
 #include "garnet/examples/ui/shadertoy/service/renderer.h"
+#include "lib/escher/flib/fence.h"
 #include "lib/escher/util/fuchsia_utils.h"
 #include "lib/escher/vk/framebuffer.h"
 #include "lib/escher/vk/image.h"
 #include "lib/escher/vk/simple_image_factory.h"
 
-namespace {
-// TODO: Copied this constant from mozart/src/scene_manager/sync/fence.h.
-// Put it in a shared header file somewhere.
-constexpr zx_status_t kFenceSignalled = ZX_EVENT_SIGNALED;
-}  // namespace
-
 namespace shadertoy {
 
 ShadertoyStateForImagePipe::ShadertoyStateForImagePipe(
@@ -72,7 +67,7 @@
 
     // The release fences should be immediately ready to render, since they are
     // passed to DrawFrame() as the 'framebuffer_ready' semaphore.
-    release_semaphore_pair.second.signal(0u, kFenceSignalled);
+    release_semaphore_pair.second.signal(0u, escher::kFenceSignalled);
 
     auto image = factory.NewImage(escher_image_info);
     zx::vmo vmo = escher::ExportMemoryAsVmo(escher(), image->memory());
@@ -98,9 +93,9 @@
     image_info.stride = 0;  // inapplicable to GPU_OPTIMAL tiling.
     image_info.tiling = fuchsia::images::Tiling::GPU_OPTIMAL;
 
-    image_pipe_->AddImage(fb.image_pipe_id, std::move(image_info),
-                          std::move(vmo), fuchsia::images::MemoryType::VK_DEVICE_MEMORY,
-                          image->memory_offset());
+    image_pipe_->AddImage(
+        fb.image_pipe_id, std::move(image_info), std::move(vmo),
+        fuchsia::images::MemoryType::VK_DEVICE_MEMORY, image->memory_offset());
   }
 }
 
@@ -142,13 +137,13 @@
                         fb.release_semaphore, fb.acquire_semaphore);
 
   // Present the image and request another frame.
-  auto present_image_callback =
-      [weak = weak_ptr_factory()->GetWeakPtr()](fuchsia::images::PresentationInfo info) {
-        // Need this cast in order to call protected member of superclass.
-        if (auto self = static_cast<ShadertoyStateForImagePipe*>(weak.get())) {
-          self->OnFramePresented(std::move(info));
-        }
-      };
+  auto present_image_callback = [weak = weak_ptr_factory()->GetWeakPtr()](
+                                    fuchsia::images::PresentationInfo info) {
+    // Need this cast in order to call protected member of superclass.
+    if (auto self = static_cast<ShadertoyStateForImagePipe*>(weak.get())) {
+      self->OnFramePresented(std::move(info));
+    }
+  };
 
   fidl::VectorPtr<zx::event> acquire_fences;
   acquire_fences.push_back(std::move(acquire_fence));
diff --git a/examples/ui/shadertoy/service/services/BUILD.gn b/examples/ui/shadertoy/service/services/BUILD.gn
index 3d6ff0d..e908a6f 100644
--- a/examples/ui/shadertoy/service/services/BUILD.gn
+++ b/examples/ui/shadertoy/service/services/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("services") {
   name = "fuchsia.examples.shadertoy"
+  cpp_legacy_callbacks = true
 
   sources = [
     "shadertoy.fidl",
diff --git a/examples/ui/shapes_a11y/BUILD.gn b/examples/ui/shapes_a11y/BUILD.gn
new file mode 100644
index 0000000..64f1e5c
--- /dev/null
+++ b/examples/ui/shapes_a11y/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+executable("shapes_a11y") {
+  output_name = "shapes_a11y_view"
+
+  sources = [
+    "a11y_client_app.h",
+    "main.cc",
+    "shapes_a11y_view.cc",
+    "shapes_a11y_view.h",
+  ]
+
+  deps = [
+    "//garnet/public/lib/app/cpp",
+    "//garnet/public/lib/fidl/cpp",
+    "//garnet/public/lib/fsl",
+    "//garnet/public/lib/fxl",
+    "//garnet/public/lib/ui/a11y/fidl",
+    "//garnet/public/lib/ui/gfx/fidl",
+    "//garnet/public/lib/ui/scenic:client",
+    "//garnet/public/lib/ui/view_framework:view_provider",
+    "//garnet/public/lib/ui/views/fidl:v1",
+    "//zircon/public/lib/trace-provider",
+  ]
+}
diff --git a/examples/ui/shapes_a11y/README.md b/examples/ui/shapes_a11y/README.md
new file mode 100644
index 0000000..40db6f1
--- /dev/null
+++ b/examples/ui/shapes_a11y/README.md
@@ -0,0 +1,3 @@
+# A11y Shapes Test
+
+This directory contains a simple application that is able to fire a11y events on touch.
diff --git a/examples/ui/shapes_a11y/a11y_client_app.h b/examples/ui/shapes_a11y/a11y_client_app.h
new file mode 100644
index 0000000..c7b1f79
--- /dev/null
+++ b/examples/ui/shapes_a11y/a11y_client_app.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_A11Y_SERVICE_H
+#define FUCHSIA_A11Y_SERVICE_H
+
+#include <fuchsia/ui/a11y/cpp/fidl.h>
+
+#include "lib/fidl/cpp/binding_set.h"
+#include "lib/fxl/logging.h"
+
+namespace examples {
+
+class A11yClientApp: public fuchsia::ui::a11y::A11yClient {
+ public:
+  A11yClientApp() {}
+
+  ~A11yClientApp() {}
+
+  void AddBinding(
+      fidl::InterfaceRequest<fuchsia::ui::a11y::A11yClient> request) {
+    bindings_.AddBinding(this, std::move(request));
+  }
+
+  void NotifyViewSelected() override {
+    FXL_LOG(INFO) << "Flag has been captured.";
+  }
+
+ private:
+
+  fidl::BindingSet<fuchsia::ui::a11y::A11yClient> bindings_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(A11yClientApp);
+};
+
+}
+
+#endif //FUCHSIA_A11Y_SERVICE_H
diff --git a/examples/ui/shapes_a11y/main.cc b/examples/ui/shapes_a11y/main.cc
new file mode 100644
index 0000000..c04dc62
--- /dev/null
+++ b/examples/ui/shapes_a11y/main.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <trace-provider/provider.h>
+
+#include "garnet/examples/ui/shapes_a11y/shapes_a11y_view.h"
+#include "lib/fsl/tasks/message_loop.h"
+#include "lib/ui/view_framework/view_provider_app.h"
+
+int main(int argc, const char** argv) {
+  fsl::MessageLoop loop;
+  trace::TraceProvider trace_provider(loop.async());
+  // Launching server app
+
+  // Initializing view
+  mozart::ViewProviderApp app([](mozart::ViewContext view_context) {
+
+    return std::make_unique<examples::ShapesA11yView>(
+        std::move(view_context.view_manager),
+        std::move(view_context.view_owner_request)
+      );
+  });
+  loop.Run();
+  return 0;
+}
diff --git a/examples/ui/shapes_a11y/shapes_a11y_view.cc b/examples/ui/shapes_a11y/shapes_a11y_view.cc
new file mode 100644
index 0000000..3fe0094
--- /dev/null
+++ b/examples/ui/shapes_a11y/shapes_a11y_view.cc
@@ -0,0 +1,59 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/examples/ui/shapes_a11y/shapes_a11y_view.h"
+
+namespace examples {
+
+namespace {
+constexpr float kBackgroundElevation = 0.f;
+}  // namespace
+
+ShapesA11yView::ShapesA11yView(
+    ::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
+    fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner> view_owner_request)
+    : BaseView(std::move(view_manager), std::move(view_owner_request),
+               "Shapes_A11y"),
+      background_node_(session()) {
+  scenic_lib::Material background_material(session());
+  background_material.SetColor(0xf2, 0xd8, 0x5b, 0xff);
+  background_node_.SetMaterial(background_material);
+  parent_node().AddChild(background_node_);
+
+  StartA11yClient();
+
+}
+
+ShapesA11yView::~ShapesA11yView() {}
+
+void ShapesA11yView::StartA11yClient() {
+  fuchsia::sys::ServiceProviderPtr provider_ptr;
+  a11y_provider_.AddBinding(provider_ptr.NewRequest());
+  a11y_provider_.AddServiceForName(
+      [this](zx::channel c) {
+        fidl::InterfaceRequest<fuchsia::ui::a11y::A11yClient> request(
+            std::move(c));
+        this->a11y_client_app_.AddBinding(std::move(request));
+      },
+      fuchsia::ui::a11y::A11yClient::Name_);
+  auto names = fidl::VectorPtr<fidl::StringPtr>::New(0);
+  names.push_back(fuchsia::ui::a11y::A11yClient::Name_);
+  view()->OfferServiceProvider(provider_ptr.Unbind(), std::move(names));
+}
+
+void ShapesA11yView::OnSceneInvalidated(
+    fuchsia::images::PresentationInfo presentation_info) {
+  if (!has_logical_size())
+    return;
+
+  const float center_x = logical_size().width * .5f;
+  const float center_y = logical_size().height * .5f;
+
+  scenic_lib::Rectangle background_shape(session(), logical_size().width,
+                                         logical_size().height);
+  background_node_.SetShape(background_shape);
+  background_node_.SetTranslation(center_x, center_y, kBackgroundElevation);
+}
+
+}  // namespace examples
diff --git a/examples/ui/shapes_a11y/shapes_a11y_view.h b/examples/ui/shapes_a11y/shapes_a11y_view.h
new file mode 100644
index 0000000..275d87b
--- /dev/null
+++ b/examples/ui/shapes_a11y/shapes_a11y_view.h
@@ -0,0 +1,49 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GARNET_EXAMPLES_UI_SHAPES_SHAPES_A11Y_VIEW_H_
+#define GARNET_EXAMPLES_UI_SHAPES_SHAPES_A11Y_VIEW_H_
+
+#include <fuchsia/sys/cpp/fidl.h>
+#include <fuchsia/ui/a11y/cpp/fidl.h>
+#include <fuchsia/ui/views_v1/cpp/fidl.h>
+
+#include "garnet/examples/ui/shapes_a11y/a11y_client_app.h"
+#include "lib/app/cpp/service_provider_impl.h"
+#include "lib/fxl/macros.h"
+#include "lib/svc/cpp/services.h"
+#include "lib/ui/scenic/client/resources.h"
+#include "lib/ui/view_framework/base_view.h"
+
+class SkCanvas;
+
+namespace examples {
+
+class ShapesA11yView : public mozart::BaseView {
+ public:
+  ShapesA11yView(
+      fuchsia::ui::views_v1::ViewManagerPtr view_manager,
+      fidl::InterfaceRequest<fuchsia::ui::views_v1_token::ViewOwner> view_owner_request);
+
+  ~ShapesA11yView() override;
+
+ private:
+  void StartA11yClient();
+
+  // |BaseView|:
+  void OnSceneInvalidated(fuchsia::images::PresentationInfo presentation_info) override;
+
+  scenic_lib::ShapeNode background_node_;
+
+  fuchsia::sys::ServiceProviderImpl a11y_provider_;
+  fuchsia::sys::ComponentControllerPtr controller_;
+
+  examples::A11yClientApp a11y_client_app_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(ShapesA11yView);
+};
+
+}  // namespace examples
+
+#endif  // GARNET_EXAMPLES_UI_SHAPES_SHAPES_A11Y_VIEW_H_
diff --git a/examples/ui/tile/BUILD.gn b/examples/ui/tile/BUILD.gn
index 0d093e7..677d4b1 100644
--- a/examples/ui/tile/BUILD.gn
+++ b/examples/ui/tile/BUILD.gn
@@ -19,7 +19,7 @@
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/svc/cpp",
     "//garnet/public/lib/ui/gfx/fidl",
-    "//garnet/public/lib/ui/presentation/fidl",
+    "//garnet/public/lib/ui/policy/fidl",
     "//garnet/public/lib/ui/view_framework:view_provider",
     "//garnet/public/lib/ui/views/cpp",
     "//garnet/public/lib/ui/views/fidl:v1",
diff --git a/examples/ui/tile/tile_view.cc b/examples/ui/tile/tile_view.cc
index 3c7acd5..3fd8d62 100644
--- a/examples/ui/tile/tile_view.cc
+++ b/examples/ui/tile/tile_view.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/examples/ui/tile/tile_view.h"
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
 #include "lib/fidl/cpp/optional.h"
@@ -34,7 +34,7 @@
 void TileView::Present(
     fidl::InterfaceHandle<::fuchsia::ui::views_v1_token::ViewOwner>
         child_view_owner,
-    fidl::InterfaceRequest<presentation::Presentation> presentation) {
+    fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation) {
   const std::string empty_url;
   AddChildView(std::move(child_view_owner), empty_url, nullptr);
 }
@@ -72,8 +72,8 @@
   env_->GetLauncher(env_launcher_.NewRequest());
 
   // Add a binding for the presenter service
-  service_provider_bridge_.AddService<presentation::Presenter>(
-      [this](fidl::InterfaceRequest<presentation::Presenter> request) {
+  service_provider_bridge_.AddService<fuchsia::ui::policy::Presenter>(
+      [this](fidl::InterfaceRequest<fuchsia::ui::policy::Presenter> request) {
         presenter_bindings_.AddBinding(this, std::move(request));
       });
 
diff --git a/examples/ui/tile/tile_view.h b/examples/ui/tile/tile_view.h
index 1fa1af8..a1d6581 100644
--- a/examples/ui/tile/tile_view.h
+++ b/examples/ui/tile/tile_view.h
@@ -10,7 +10,7 @@
 
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include "garnet/examples/ui/tile/tile_params.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/fidl/cpp/binding_set.h"
@@ -21,7 +21,7 @@
 
 namespace examples {
 
-class TileView : public mozart::BaseView, public presentation::Presenter {
+class TileView : public mozart::BaseView, public fuchsia::ui::policy::Presenter {
  public:
   TileView(::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
            fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner>
@@ -59,7 +59,7 @@
   void Present(
       fidl::InterfaceHandle<::fuchsia::ui::views_v1_token::ViewOwner>
           view_owner,
-      fidl::InterfaceRequest<presentation::Presentation> presentation) override;
+      fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation) override;
   void HACK_SetRendererParams(
       bool enable_clipping,
       ::fidl::VectorPtr<fuchsia::ui::gfx::RendererParam> params) override{};
@@ -98,7 +98,7 @@
   // Map from keys to |ViewData|
   std::map<uint32_t, std::unique_ptr<ViewData>> views_;
 
-  fidl::BindingSet<presentation::Presenter> presenter_bindings_;
+  fidl::BindingSet<fuchsia::ui::policy::Presenter> presenter_bindings_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(TileView);
 };
diff --git a/examples/ui/video_display/BUILD.gn b/examples/ui/video_display/BUILD.gn
index a9644e5..04dc50b 100644
--- a/examples/ui/video_display/BUILD.gn
+++ b/examples/ui/video_display/BUILD.gn
@@ -28,7 +28,6 @@
     "//garnet/public/lib/fidl/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/media/timeline:timeline",
-    "//garnet/public/lib/ui/presentation/fidl",
     "//garnet/public/lib/ui/scenic:client",
     "//garnet/public/lib/ui/scenic:fidl_helpers",
     "//garnet/public/lib/ui/scenic/fidl",
@@ -38,6 +37,7 @@
     "//zircon/public/lib/fbl",
     "//zircon/public/lib/fit",
     "//zircon/public/lib/trace-provider",
+    "//zircon/public/lib/vmo-utils",
   ]
 
   include_dirs = [
diff --git a/examples/ui/video_display/buffer.cc b/examples/ui/video_display/buffer.cc
index 70ec608..9e4d7e2 100644
--- a/examples/ui/video_display/buffer.cc
+++ b/examples/ui/video_display/buffer.cc
@@ -5,7 +5,7 @@
 #include <garnet/examples/ui/video_display/buffer.h>
 
 #include <fcntl.h>
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <stdio.h>
 #include <unistd.h>
 
diff --git a/examples/ui/video_display/buffer.h b/examples/ui/video_display/buffer.h
index cc17574..5ea524e 100644
--- a/examples/ui/video_display/buffer.h
+++ b/examples/ui/video_display/buffer.h
@@ -6,7 +6,7 @@
 
 #include <stdint.h>
 
-#include <fbl/vmo_mapper.h>
+#include <lib/vmo-utils/vmo_mapper.h>
 #include <lib/fsl/tasks/message_loop.h>
 #include <zircon/status.h>
 #include <zx/event.h>
@@ -17,7 +17,7 @@
 // Encapsulates a part of a VMO.
 // A Buffer represents one frame, mapping it into memory to allow the process to
 // write into it. Buffer also keeps track of the locked state of the memory.
-class Buffer : public fbl::VmoMapper {
+class Buffer : public vmo_utils::VmoMapper {
  protected:
   enum class BufferState { kInvalid = 0, kAvailable, kReadLocked };
 
diff --git a/examples/ui/video_display/camera_client.cc b/examples/ui/video_display/camera_client.cc
index 8c93d36..1c9680f 100644
--- a/examples/ui/video_display/camera_client.cc
+++ b/examples/ui/video_display/camera_client.cc
@@ -12,7 +12,7 @@
 #include <fbl/algorithm.h>
 #include <fbl/auto_call.h>
 #include <fbl/limits.h>
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <lib/fsl/tasks/message_loop.h>
 #include <zircon/assert.h>
 #include <zircon/device/audio.h>
diff --git a/examples/ui/video_display/fenced_buffer.cc b/examples/ui/video_display/fenced_buffer.cc
index 475a043..09a4d11 100644
--- a/examples/ui/video_display/fenced_buffer.cc
+++ b/examples/ui/video_display/fenced_buffer.cc
@@ -10,7 +10,7 @@
 
 #include <utility>
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <lib/fxl/command_line.h>
 #include <lib/fxl/log_settings_command_line.h>
 #include <lib/fxl/logging.h>
diff --git a/examples/ui/video_display/main.cc b/examples/ui/video_display/main.cc
index 9887a53..e0ae8e3 100644
--- a/examples/ui/video_display/main.cc
+++ b/examples/ui/video_display/main.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include <lib/async-loop/cpp/loop.h>
-#include <presentation/cpp/fidl.h>
+#include <fuchsia/ui/policy/cpp/fidl.h>
 #include <trace-provider/provider.h>
 
 #include "garnet/examples/ui/video_display/view.h"
diff --git a/examples/ui/video_display/view.cc b/examples/ui/video_display/view.cc
index 9342947..2e5e5d5 100644
--- a/examples/ui/video_display/view.cc
+++ b/examples/ui/video_display/view.cc
@@ -219,7 +219,7 @@
   FXL_VLOG(4) << "Creating View";
   // Create an ImagePipe and pass one end to the Session:
   uint32_t image_pipe_id = session()->AllocResourceId();
-  session()->Enqueue(scenic_lib::NewCreateImagePipeCommand(
+  session()->Enqueue(scenic_lib::NewCreateImagePipeCmd(
       image_pipe_id, image_pipe_.NewRequest()));
 
   // Create a material that has our image pipe mapped onto it:
diff --git a/go/src/amber/BUILD.gn b/go/src/amber/BUILD.gn
index 2fa1088..58dd773 100644
--- a/go/src/amber/BUILD.gn
+++ b/go/src/amber/BUILD.gn
@@ -41,6 +41,18 @@
     package = "github.com/golang/snappy"
     source = "//third_party/golibs/github.com/golang/snappy"
   },
+  {
+    package = "golang.org/x/net"
+    source = "//third_party/golibs/golang.org/x/net"
+  },
+  {
+    package = "golang.org/x/oauth2"
+    source = "//third_party/golibs/golang.org/x/oauth2"
+  },
+  {
+    package = "github.com/rjw57/oauth2device"
+    source = "//third_party/golibs/github.com/rjw57/oauth2device"
+  },
 ]
 
 amber_target_binaries = [
@@ -229,5 +241,9 @@
       dest = "sysmgr/amber.config"
       path = rebase_path("startup.config")
     },
+    {
+      dest = "amber/sources/localhost/config.json"
+      path = rebase_path("etc/sources/localhost/config.json")
+    },
   ]
 }
diff --git a/go/src/amber/cmd/amber/amber.go b/go/src/amber/cmd/amber/amber.go
index 503f6be..4ba7fad 100644
--- a/go/src/amber/cmd/amber/amber.go
+++ b/go/src/amber/cmd/amber/amber.go
@@ -5,16 +5,19 @@
 package main
 
 import (
+	"bufio"
 	"crypto/sha512"
 	"encoding/hex"
+	"encoding/json"
 	"flag"
 	"fmt"
 	"hash"
 	"io"
+	"io/ioutil"
 	"log"
-	"net/url"
 	"os"
 	"path/filepath"
+	"strings"
 	"time"
 
 	"amber/daemon"
@@ -26,19 +29,16 @@
 
 	"app/context"
 	"syscall/zx"
-
-	tuf_data "github.com/flynn/go-tuf/data"
 )
 
-const lhIP = "http://127.0.0.1"
-const port = 8083
+const (
+	defaultSourceDir = "/system/data/amber/sources"
+)
 
 var (
 	// TODO(jmatt) replace hard-coded values with something better/more flexible
 	usage      = "usage: amber [-k=<path>] [-s=<path>] [-u=<url>]"
-	store      = flag.String("s", "/data/amber/tuf", "The path to the local file store")
-	addr       = flag.String("u", fmt.Sprintf("%s:%d", lhIP, port), "The URL (including port if not using port 80)  of the update server.")
-	keys       = flag.String("k", "/pkg/data/keys", "Path to use to initialize the client's keys. This is only needed the first time the command is run.")
+	store      = flag.String("s", "/data/amber/store", "The path to the local file store")
 	delay      = flag.Duration("d", 0*time.Second, "Set a delay before Amber does its work")
 	autoUpdate = flag.Bool("a", false, "Automatically update and restart the system as updates become available")
 
@@ -51,61 +51,119 @@
 		flag.CommandLine.PrintDefaults()
 	}
 
-	flag.Parse()
 	log.SetPrefix("amber: ")
 	log.SetFlags(log.Ltime)
+
+	readExtraFlags()
+
+	flag.Parse()
 	time.Sleep(*delay)
 
-	srvUrl, err := url.Parse(*addr)
+	// The source dir is where we store our database of sources. Because we
+	// don't currently have a mechanism to run "post-install" scripts,
+	// we'll use the existence of the data dir to signify if we need to
+	// load in the default sources.
+	storeExists, err := exists(*store)
 	if err != nil {
-		log.Fatalf("bad address for update server %s", err)
+		log.Fatal(err)
 	}
 
-	keys, err := source.LoadKeys(*keys)
+	d, err := startupDaemon(*store)
 	if err != nil {
-		log.Fatalf("loading root keys failed %s", err)
+		log.Fatalf("failed to start daemon: %s", err)
 	}
-
-	d := startupDaemon(srvUrl, *store, keys)
-	if *autoUpdate {
-		go func() {
-			supMon := daemon.NewSystemUpdateMonitor(d)
-			supMon.Start()
-			log.Println("system update monitor exited")
-		}()
-	}
-
-	startFIDLSvr(d)
-
 	defer d.CancelAll()
 
+	// Now that the daemon is up and running, we can register all of the
+	// system configured sources.
+	//
+	// TODO(etryzelaar): Since these sources are only installed once,
+	// there's currently no way to upgrade them. PKG-82 is tracking coming
+	// up with a plan to address this.
+	if !storeExists {
+		log.Printf("initializing store: %s", *store)
+
+		if err := addDefaultSourceConfigs(d, defaultSourceDir); err != nil {
+			log.Fatalf("failed to register default sources: %s", err)
+		}
+	}
+
+	supMon := daemon.NewSystemUpdateMonitor(d, *autoUpdate)
+	go func(s *daemon.SystemUpdateMonitor) {
+		s.Start()
+		log.Println("system update monitor exited")
+	}(supMon)
+
+	startFIDLSvr(d, supMon)
+
 	//block forever
 	select {}
 }
 
-func startFIDLSvr(d *daemon.Daemon) {
+// LoadSourceConfigs install source configs from a directory.  The directory
+// structure looks like:
+//
+//     $dir/source1/config.json
+//     $dir/source2/config.json
+//     ...
+func addDefaultSourceConfigs(d *daemon.Daemon, dir string) error {
+	files, err := ioutil.ReadDir(dir)
+	if err != nil {
+		return err
+	}
+
+	for _, file := range files {
+		p := filepath.Join(dir, file.Name(), "config.json")
+		log.Printf("loading source config %s", p)
+
+		cfg, err := loadSourceConfig(p)
+		if err != nil {
+			return err
+		}
+
+		if err := d.AddTUFSource(cfg); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func loadSourceConfig(path string) (*amber_fidl.SourceConfig, error) {
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	var cfg amber_fidl.SourceConfig
+	if err := json.NewDecoder(f).Decode(&cfg); err != nil {
+		return nil, err
+	}
+
+	return &cfg, nil
+}
+
+func startFIDLSvr(d *daemon.Daemon, s *daemon.SystemUpdateMonitor) {
 	cxt := context.CreateFromStartupInfo()
-	apiSrvr := ipcserver.NewControlSrvr(d)
+	apiSrvr := ipcserver.NewControlSrvr(d, s)
 	cxt.OutgoingService.AddService(amber_fidl.ControlName, func(c zx.Channel) error {
 		return apiSrvr.Bind(c)
 	})
 	cxt.Serve()
 }
 
-func startupDaemon(srvURL *url.URL, store string, keys []*tuf_data.Key) *daemon.Daemon {
-
+func startupDaemon(store string) (*daemon.Daemon, error) {
 	reqSet := newPackageSet([]string{"/pkg/bin/app"})
 
-	tufSrc := source.NewTUFSource(srvURL.String(), store, keys, 0, 0)
-
-	checker := daemon.NewDaemon(reqSet, daemon.ProcessPackage, []source.Source{tufSrc})
-
-	blobURL := *srvURL
-	blobURL.Path = filepath.Join(blobURL.Path, "blobs")
-	checker.AddBlobRepo(daemon.BlobRepo{Address: blobURL.String(), Interval: time.Second * 5})
+	d, err := daemon.NewDaemon(store, reqSet, daemon.ProcessPackage, []source.Source{})
+	if err != nil {
+		return nil, err
+	}
 
 	log.Println("monitoring for updates")
-	return checker
+
+	return d, err
 }
 
 func newPackageSet(files []string) *pkg.PackageSet {
@@ -142,3 +200,62 @@
 	}
 	return hash.Sum(nil), nil
 }
+
+var flagsDir = filepath.Join("/system", "data", "amber", "flags")
+
+func readExtraFlags() {
+	d, err := os.Open(flagsDir)
+	if err != nil {
+		if !os.IsNotExist(err) {
+			log.Println("unexpected error reading %q: %s", flagsDir, err)
+		}
+		return
+	}
+	defer d.Close()
+
+	files, err := d.Readdir(0)
+	if err != nil {
+		log.Printf("error listing flags directory %s", err)
+		return
+	}
+	for _, f := range files {
+		if f.IsDir() || f.Size() == 0 {
+			continue
+		}
+
+		fPath := filepath.Join(d.Name(), f.Name())
+		file, err := os.Open(fPath)
+		if err != nil {
+			log.Printf("flags file %q could not be opened: %s", fPath, err)
+			continue
+		}
+		r := bufio.NewReader(file)
+		for {
+			line, err := r.ReadString('\n')
+			if err != nil && err != io.EOF {
+				log.Printf("flags file %q had read error: %s", fPath, err)
+				break
+			}
+
+			line = strings.TrimSpace(line)
+			os.Args = append(os.Args, line)
+			if err == io.EOF {
+				break
+			}
+		}
+		file.Close()
+	}
+}
+
+// Check if a path exists.
+func exists(path string) (bool, error) {
+	if _, err := os.Stat(path); err != nil {
+		if os.IsNotExist(err) {
+			return false, nil
+		} else {
+			return false, err
+		}
+	}
+
+	return true, nil
+}
diff --git a/go/src/amber/cmd/ctl/amber-control.go b/go/src/amber/cmd/ctl/amber-control.go
index 80cb470..7c2a8c3 100644
--- a/go/src/amber/cmd/ctl/amber-control.go
+++ b/go/src/amber/cmd/ctl/amber-control.go
@@ -8,9 +8,11 @@
 	"amber/ipcserver"
 	"app/context"
 	"encoding/hex"
+	"encoding/json"
 	"fidl/amber"
 	"flag"
 	"fmt"
+	"log"
 	"net/url"
 	"os"
 	"strings"
@@ -36,7 +38,9 @@
         -i: content ID of the blob
 
     add_src   - add a source to the list we can use
+        -f: path to a source config file
         -s: location of the package source
+        -b: location of the blob source
         -k: the hex string of the public ED25519 key for the source
         -l: requests per period that can be made to the source (0 for unlimited)
         -p: length of time (in milliseconds) over which the limit passed to
@@ -53,10 +57,12 @@
 
 var (
 	fs         = flag.NewFlagSet("default", flag.ExitOnError)
-	pkgName    = fs.String("n", "", "Name of a package")
+	pkgFile    = fs.String("f", "", "Path to a source config file")
+	name       = fs.String("n", "", "Name of a source or package")
 	pkgVersion = fs.String("v", "", "Version of a package")
 	srcUrl     = fs.String("s", "", "The location of a package source")
-	rateLimit  = fs.Uint("l", 0, "Maximum number of requests allowable in a time period.")
+	blobUrl    = fs.String("b", "", "The location of the blob source")
+	rateLimit  = fs.Uint64("l", 0, "Maximum number of requests allowable in a time period.")
 	srcKey     = fs.String("k", "", "Root key for the source, this can be either the key itself or a http[s]:// or file:// URL to the key")
 	blobID     = fs.String("i", "", "Content ID of the blob")
 	noWait     = fs.Bool("nowait", false, "Return once installation has started, package will not yet be available.")
@@ -74,14 +80,16 @@
 	return string(e)
 }
 
-func doTest(pxy *amber.ControlInterface) {
+func doTest(pxy *amber.ControlInterface) error {
 	v := int32(42)
 	resp, err := pxy.DoTest(v)
 	if err != nil {
 		fmt.Println(err)
-	} else {
-		fmt.Printf("Response: %s\n", resp)
+		return err
 	}
+
+	fmt.Printf("Response: %s\n", resp)
+	return nil
 }
 
 func connect(ctx *context.Context) (*amber.ControlInterface, amber.ControlInterfaceRequest) {
@@ -94,36 +102,69 @@
 }
 
 func addSource(a *amber.ControlInterface) error {
-	if len(strings.TrimSpace(*srcUrl)) == 0 {
-		fmt.Println("No repository URL provided")
-		return os.ErrInvalid
-	}
-	if _, err := url.ParseRequestURI(*srcUrl); err != nil {
-		fmt.Printf("Provided URL %q is not valid\n", *srcUrl)
-		return err
-	}
+	var cfg amber.SourceConfig
 
-	if len(strings.TrimSpace(*srcKey)) == 0 {
-		fmt.Println("No repository key provided")
-		return os.ErrInvalid
-	}
-	if _, err := hex.DecodeString(*srcKey); err != nil {
-		fmt.Printf("Provided repository key %q contains invalid characters\n", *srcKey)
-		return os.ErrInvalid
-	}
+	if len(*pkgFile) == 0 {
+		name := strings.TrimSpace(*name)
+		if len(name) == 0 {
+			fmt.Println("No source id provided")
+			return os.ErrInvalid
+		}
 
-	added, err := a.AddSrc(amber.SourceConfig{
-		RepoUrl:    *srcUrl,
-		RequestUrl: *srcUrl,
-		RateLimit:  int32(*rateLimit),
-		RatePeriod: int32(*period),
-		RootKeys: []amber.KeyConfig{
-			amber.KeyConfig{
-				Type:  "ed25519",
-				Value: *srcKey,
+		srcUrl := strings.TrimSpace(*srcUrl)
+		if len(srcUrl) == 0 {
+			fmt.Println("No repository URL provided")
+			return os.ErrInvalid
+		}
+		if _, err := url.ParseRequestURI(srcUrl); err != nil {
+			fmt.Printf("Provided URL %q is not valid\n", srcUrl)
+			return err
+		}
+
+		blobUrl := strings.TrimSpace(*blobUrl)
+		if blobUrl != "" {
+			if _, err := url.ParseRequestURI(blobUrl); err != nil {
+				fmt.Printf("Provided URL %q is not valid\n", blobUrl)
+				return err
+			}
+		}
+
+		srcKey := strings.TrimSpace(*srcKey)
+		if len(srcKey) == 0 {
+			fmt.Println("No repository key provided")
+			return os.ErrInvalid
+		}
+		if _, err := hex.DecodeString(srcKey); err != nil {
+			fmt.Printf("Provided repository key %q contains invalid characters\n", srcKey)
+			return os.ErrInvalid
+		}
+
+		cfg = amber.SourceConfig{
+			Id:          name,
+			RepoUrl:     srcUrl,
+			BlobRepoUrl: blobUrl,
+			RateLimit:   *rateLimit,
+			RatePeriod:  int32(*period),
+			RootKeys: []amber.KeyConfig{
+				amber.KeyConfig{
+					Type:  "ed25519",
+					Value: srcKey,
+				},
 			},
-		},
-	})
+		}
+	} else {
+		f, err := os.Open(*pkgFile)
+		if err != nil {
+			log.Fatalf("failed to open file: %v", err)
+		}
+		defer f.Close()
+
+		if err := json.NewDecoder(f).Decode(&cfg); err != nil {
+			log.Fatalf("failed to parse source config: %v", err)
+		}
+	}
+
+	added, err := a.AddSrc(cfg)
 	if !added {
 		fmt.Println("Call succeeded, but source not added")
 		return fmt.Errorf("Request arguments properly formatted, but possibly otherwise invalid")
@@ -134,6 +175,64 @@
 	return err
 }
 
+func getUp(a *amber.ControlInterface) error {
+	// the amber daemon wants package names that start with "/", if not present
+	// add this as a prefix
+	if strings.Index(*name, "/") != 0 {
+		*name = fmt.Sprintf("/%s", *name)
+	}
+	if *pkgVersion == "" {
+		*pkgVersion = "0"
+	}
+	// combine name and 'version' here, because the FIDL interface is talking
+	// about an amber version as opposed to human version. the human version is
+	// part of the package name
+	*name = fmt.Sprintf("%s/%s", *name, *pkgVersion)
+	if *noWait {
+		blobID, err := a.GetUpdate(*name, nil, merkle)
+		if err != nil {
+			fmt.Printf("Error getting update %s\n", err)
+			return err
+		}
+
+		fmt.Printf("Wrote update to blob %s\n", *blobID)
+	} else {
+		var err error
+		for i := 0; i < 3; i++ {
+			err = getUpdateComplete(a, name, merkle)
+			if err == nil {
+				break
+			}
+			fmt.Printf("Update failed with error %s, retrying...\n", err)
+			time.Sleep(2 * time.Second)
+		}
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func listSources(a *amber.ControlInterface) error {
+	srcs, err := a.ListSrcs()
+	if err != nil {
+		fmt.Printf("failed to list sources: %s\n", err)
+		return err
+	}
+
+	for _, src := range srcs {
+		encoder := json.NewEncoder(os.Stdout)
+		encoder.SetIndent("", "    ")
+		if err := encoder.Encode(src); err != nil {
+			fmt.Printf("failed to encode source into json: %s\n", err)
+			return err
+		}
+	}
+
+	return nil
+}
+
 func main() {
 	if len(os.Args) < 2 {
 		fmt.Printf("Error: no command provided\n%s", usage)
@@ -146,38 +245,13 @@
 
 	switch os.Args[1] {
 	case "get_up":
-		// the amber daemon wants package names that start with "/", if not present
-		// add this as a prefix
-		if strings.Index(*pkgName, "/") != 0 {
-			*pkgName = fmt.Sprintf("/%s", *pkgName)
-		}
-		if *pkgVersion == "" {
-			*pkgVersion = "0"
-		}
-		// combine name and 'version' here, because the FIDL interface is talking
-		// about an amber version as opposed to human version. the human version is
-		// part of the package name
-		*pkgName = fmt.Sprintf("%s/%s", *pkgName, *pkgVersion)
-		if *noWait {
-			blobID, err := proxy.GetUpdate(*pkgName, nil, merkle)
-			if err == nil {
-				fmt.Printf("Wrote update to blob %s\n", *blobID)
-			} else {
-				fmt.Printf("Error getting update %s\n", err)
-			}
-		} else {
-			for i := 0; i < 3; i++ {
-				err := getUpdateComplete(proxy, pkgName, merkle)
-				if err == nil {
-					break
-				}
-				fmt.Printf("Update failed with error %s, retrying...\n", err)
-				time.Sleep(2 * time.Second)
-			}
+		if err := getUp(proxy); err != nil {
+			os.Exit(1)
 		}
 	case "get_blob":
 		if err := proxy.GetBlob(*blobID); err != nil {
 			fmt.Printf("Error getting content blob %s\n", err)
+			os.Exit(1)
 		}
 	case "add_src":
 		if err := addSource(proxy); err != nil {
@@ -185,12 +259,37 @@
 		}
 	case "rm_src":
 		fmt.Printf("%q not yet supported\n", os.Args[1])
+		os.Exit(1)
 	case "list_srcs":
-		fmt.Printf("%q not yet supported\n", os.Args[1])
+		if err := listSources(proxy); err != nil {
+			os.Exit(1)
+		}
 	case "check":
 		fmt.Printf("%q not yet supported\n", os.Args[1])
+		os.Exit(1)
 	case "test":
-		doTest(proxy)
+		if err := doTest(proxy); err != nil {
+			os.Exit(1)
+		}
+	case "system_update":
+		configured, err := proxy.CheckForSystemUpdate()
+		if err != nil {
+			fmt.Printf("error checking for system update: %s\n", err)
+			os.Exit(1)
+		}
+
+		if configured {
+			fmt.Printf("triggered a system update check\n")
+		} else {
+			fmt.Printf("system update is not configured\n")
+		}
+	case "login":
+		device, err := proxy.Login(*name)
+		if err != nil {
+			fmt.Printf("failed to login: %s", err)
+			os.Exit(1)
+		}
+		fmt.Printf("On your computer go to:\n\n\t%v\n\nand enter\n\n\t%v\n\n", device.VerificationUrl, device.UserCode)
 	default:
 		fmt.Printf("Error, %q is not a recognized command\n%s",
 			os.Args[1], usage)
diff --git a/go/src/amber/cmd/publish/publish.go b/go/src/amber/cmd/publish/publish.go
index 57a6d8e..2cc102e 100644
--- a/go/src/amber/cmd/publish/publish.go
+++ b/go/src/amber/cmd/publish/publish.go
@@ -50,6 +50,7 @@
 	keySrc       = flag.String("k", fuchsiaBuildDir, "Directory containing the signing keys.")
 	verbose      = flag.Bool("v", false, "Print out more informational messages.")
 	verTime      = flag.Bool("vt", false, "Set repo versioning based on time rather than a monotonic increment")
+	commitStaged = flag.Bool("po", false, "Publish only, commit any staged updates to the update repo.")
 )
 
 func main() {
@@ -69,7 +70,8 @@
 	}
 
 	modeCheck := false
-	for _, v := range []bool{*tufFile, *packageSet, *regFile, *blobSet, *manifestFile} {
+	for _, v := range []bool{*tufFile, *packageSet, *regFile, *blobSet, *manifestFile,
+		*commitStaged} {
 		if v {
 			if modeCheck {
 				log.Fatal("Only one mode, -p, -ps, -b, -bs, or -m may be selected")
@@ -82,7 +84,7 @@
 		log.Fatal("A mode, -p, -ps, -b, or -m must be selected")
 	}
 
-	if len(filePaths) == 0 {
+	if !*commitStaged && len(filePaths) == 0 {
 		log.Fatal("No file path supplied.")
 	}
 	for _, k := range filePaths {
@@ -181,6 +183,10 @@
 				return
 			}
 		}
+	} else if *commitStaged {
+		if err := repo.CommitUpdates(*verTime); err != nil {
+			fmt.Printf("Error committing updates: %s", err)
+		}
 	} else {
 		if len(filePaths) != 1 {
 			log.Fatalf("Too many file paths supplied.")
diff --git a/go/src/amber/daemon/blob_fetcher.go b/go/src/amber/daemon/blob_fetcher.go
index f2622ea..a4487a6 100644
--- a/go/src/amber/daemon/blob_fetcher.go
+++ b/go/src/amber/daemon/blob_fetcher.go
@@ -14,9 +14,12 @@
 	"path/filepath"
 	"sync"
 	"time"
+
+	"amber/source"
 )
 
 type BlobRepo struct {
+	Source   source.Source
 	Address  string
 	Interval time.Duration
 }
@@ -25,10 +28,8 @@
 	muRun.Lock()
 	defer muRun.Unlock()
 
-	httpC := &http.Client{}
-
 	for i := range repos {
-		reader, sz, err := FetchBlobFromRepo(repos[i], blob, httpC)
+		reader, sz, err := FetchBlobFromRepo(repos[i], blob)
 		if err != nil {
 			log.Printf("Got error trying to get blob\n")
 			continue
@@ -45,7 +46,15 @@
 
 // FetchBlobFromRepo attempts to pull the set of blobs requested from the supplied
 // BlobRepo. FetchBlob returns the list of blobs successfully stored.
-func FetchBlobFromRepo(r BlobRepo, blob string, client *http.Client) (io.ReadCloser, int64, error) {
+func FetchBlobFromRepo(r BlobRepo, blob string) (io.ReadCloser, int64, error) {
+	var client *http.Client
+	if r.Source != nil {
+		client = r.Source.GetHttpClient()
+	}
+	if client == nil {
+		client = http.DefaultClient
+	}
+
 	u, err := url.Parse(r.Address)
 	if err != nil {
 		return nil, -1, err
@@ -59,14 +68,17 @@
 		return nil, -1, err
 	}
 
-	if r, err := client.Get(srcAddr.String()); err == nil {
-		if r.StatusCode == 200 {
-			return r.Body, r.ContentLength, nil
-		}
-		r.Body.Close()
-		return nil, -1, fmt.Errorf("fetch failed with status %s", r.StatusCode)
+	resp, err := client.Get(srcAddr.String())
+	if err != nil {
+		return nil, -1, err
 	}
-	return nil, -1, err
+
+	if resp.StatusCode == 200 {
+		return resp.Body, resp.ContentLength, nil
+	} else {
+		resp.Body.Close()
+		return nil, -1, fmt.Errorf("fetch failed with status %s", resp.StatusCode)
+	}
 }
 
 func WriteBlob(name string, sz int64, con io.ReadCloser) error {
diff --git a/go/src/amber/daemon/daemon.go b/go/src/amber/daemon/daemon.go
index cb33324..7e811b9 100644
--- a/go/src/amber/daemon/daemon.go
+++ b/go/src/amber/daemon/daemon.go
@@ -8,7 +8,9 @@
 	"errors"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"log"
+	"net/url"
 	"os"
 	"path/filepath"
 	"strings"
@@ -17,6 +19,8 @@
 
 	"amber/pkg"
 	"amber/source"
+
+	"fidl/amber"
 )
 
 var DstUpdate = "/pkgfs/install/pkg"
@@ -37,9 +41,10 @@
 // Execution contexts sharing a single Daemon instance should mediate access
 // to all calls into the Daemon.
 type Daemon struct {
+	store    string
 	srcMons  []*SourceMonitor
 	muSrcs   sync.Mutex
-	srcs     []source.Source
+	srcs     map[string]source.Source
 	pkgs     *pkg.PackageSet
 	runCount sync.WaitGroup
 	// takes an update Package, an original Package and a Source to get the
@@ -57,11 +62,14 @@
 }
 
 // NewDaemon creates a Daemon with the given SourceSet
-func NewDaemon(r *pkg.PackageSet, f func(*GetResult, *pkg.PackageSet) error,
-	s []source.Source) *Daemon {
-	d := &Daemon{pkgs: r,
+func NewDaemon(store string, r *pkg.PackageSet, f func(*GetResult, *pkg.PackageSet) error,
+	s []source.Source) (*Daemon, error) {
+	d := &Daemon{
+		store:     store,
+		pkgs:      r,
 		runCount:  sync.WaitGroup{},
 		srcMons:   []*SourceMonitor{},
+		srcs:      make(map[string]source.Source),
 		processor: f,
 		repos:     []BlobRepo{},
 		muInProg:  sync.Mutex{},
@@ -76,26 +84,113 @@
 		mon.Run()
 		d.runCount.Done()
 	}()
-	return d
+
+	// Ignore if the directory doesn't exist
+	if err := d.loadSourcesFromPath(store); err != nil && !os.IsNotExist(err) {
+		return nil, err
+	}
+
+	return d, nil
+}
+
+// loadSourcesFromPath loads sources from a directory, where each source gets
+// it's own directory.  The actual directory structure is source dependent.
+func (d *Daemon) loadSourcesFromPath(dir string) error {
+	files, err := ioutil.ReadDir(dir)
+	if err != nil {
+		return err
+	}
+
+	for _, f := range files {
+		p := filepath.Join(dir, f.Name())
+		src, err := source.LoadTUFSourceFromPath(p)
+		if err != nil {
+			return err
+		}
+
+		d.addSrc(src)
+	}
+
+	return nil
 }
 
 func (d *Daemon) addSrc(s source.Source) {
 	d.muSrcs.Lock()
 	defer d.muSrcs.Unlock()
-	s = NewSourceKeeper(s)
-	d.srcs = append(d.srcs, s)
+
+	id := s.GetId()
+
+	if _, ok := d.srcs[id]; ok {
+		log.Printf("overwriting source: %s", id)
+	}
+
+	d.srcs[id] = NewSourceKeeper(s)
+
+	log.Printf("added source: %s", id)
 }
 
-// AddSource is called to add a Source that can be used to get updates. When the
-// Source is added, the Daemon will start polling it at the interval from
-// Source.GetInterval()
-func (d *Daemon) AddSource(s source.Source) {
-	d.addSrc(s)
+// AddTUFSource is called to add a Source that can be used to get updates. When
+// the TUFSource is added, the Daemon will start polling it at the interval
+// from TUFSource.GetInterval()
+func (d *Daemon) AddTUFSource(cfg *amber.SourceConfig) error {
+	// Make sure the id is safe to be written to disk.
+	store := filepath.Join(d.store, url.PathEscape(cfg.Id))
+
+	src, err := source.NewTUFSource(store, cfg)
+	if err != nil {
+		log.Printf("failed to create TUF source: %v: %s", cfg.Id, err)
+		return err
+	}
+
+	// Save the config.
+	if err := src.Save(); err != nil {
+		log.Printf("failed to save TUF config: %v: %s", cfg.Id, err)
+		return err
+	}
+
+	// Add the source's blob repo. If not specified, assume the blobs are
+	// found under $RepoURL/blobs.
+	blobRepoUrl := cfg.BlobRepoUrl
+	if blobRepoUrl == "" {
+		blobRepoUrl = filepath.Join(cfg.RepoUrl, "blobs")
+	}
+
+	blobRepo := BlobRepo{
+		Source:   src,
+		Address:  cfg.BlobRepoUrl,
+		Interval: time.Second * 5,
+	}
+
+	if err := d.AddBlobRepo(blobRepo); err != nil {
+		return err
+	}
+
+	// If we made it to this point, we're ready to actually add the source.
+	d.addSrc(src)
+
 	// after the source is added, let the monitor(s) know so they can decide if they
 	// want to look again for updates
 	for _, m := range d.srcMons {
 		m.SourcesAdded()
 	}
+
+	log.Printf("added TUF source %s %v\n", cfg.Id, cfg.RepoUrl)
+
+	return nil
+}
+
+func (d *Daemon) Login(srcId string) (*amber.DeviceCode, error) {
+	log.Printf("logging into %s", srcId)
+	d.muSrcs.Lock()
+	src, ok := d.srcs[srcId]
+	d.muSrcs.Unlock()
+
+	if !ok {
+		log.Printf("unknown source id: %v", srcId)
+		return nil, fmt.Errorf("unknown source: %v", srcId)
+	}
+
+	return src.Login()
 }
 
 func (d *Daemon) blobRepos() []BlobRepo {
@@ -106,10 +201,19 @@
 	return c
 }
 
-func (d *Daemon) AddBlobRepo(br BlobRepo) {
+func (d *Daemon) AddBlobRepo(br BlobRepo) error {
+	if _, err := url.ParseRequestURI(br.Address); err != nil {
+		log.Printf("Provided URL %q is not valid", br.Address)
+		return err
+	}
+
 	d.muRepos.Lock()
 	d.repos = append(d.repos, br)
 	d.muRepos.Unlock()
+
+	log.Printf("added blob repo: %v\n", br.Address)
+
+	return nil
 }
 
 // GetBlob is a blocking call which tries to get all requested blobs
@@ -290,15 +394,16 @@
 func (d *Daemon) getUpdates(rec *upRec) map[pkg.Package]*GetResult {
 	fetchRecs := []*pkgSrcPair{}
 
-	d.muSrcs.Lock()
-	srcs := make([]source.Source, len(d.srcs))
-	copy(srcs, d.srcs)
-	d.muSrcs.Unlock()
+	srcs := d.GetSources()
 
 	unfoundPkgs := rec.pkgs
 	// TODO thread-safe access for sources?
-	for i := 0; i < len(srcs) && len(unfoundPkgs) > 0; i++ {
-		updates, err := srcs[i].AvailableUpdates(unfoundPkgs)
+	for _, src := range srcs {
+		if len(unfoundPkgs) == 0 {
+			break
+		}
+
+		updates, err := src.AvailableUpdates(unfoundPkgs)
 		if len(updates) == 0 || err != nil {
 			if err == ErrRateExceeded {
 				log.Printf("daemon: source rate limit exceeded\n")
@@ -312,7 +417,7 @@
 
 		pkgsToSrc := pkgSrcPair{
 			pkgs: make(map[pkg.Package]pkg.Package),
-			src:  srcs[i],
+			src:  src,
 		}
 		fetchRecs = append(fetchRecs, &pkgsToSrc)
 
@@ -379,9 +484,12 @@
 func (d *Daemon) RemoveSource(src source.Source) error {
 	d.muSrcs.Lock()
 	defer d.muSrcs.Unlock()
-	for i, m := range d.srcs {
+
+	id := src.GetId()
+
+	if m, ok := d.srcs[id]; ok {
 		if m.Equals(src) {
-			d.srcs = append(d.srcs[:i], d.srcs[i+1:]...)
+			delete(d.srcs, id)
 			return nil
 		}
 	}
@@ -389,6 +497,18 @@
 	return ErrSrcNotFound
 }
 
+func (d *Daemon) GetSources() map[string]source.Source {
+	d.muSrcs.Lock()
+	defer d.muSrcs.Unlock()
+
+	srcs := make(map[string]source.Source)
+	for key, value := range d.srcs {
+		srcs[key] = value
+	}
+
+	return srcs
+}
+
 // CancelAll stops all update retrieval operations, blocking until any
 // in-progress operations complete.
 func (d *Daemon) CancelAll() {
diff --git a/go/src/amber/daemon/daemon_test.go b/go/src/amber/daemon/daemon_test.go
index 704f212..bfef1d6 100644
--- a/go/src/amber/daemon/daemon_test.go
+++ b/go/src/amber/daemon/daemon_test.go
@@ -6,7 +6,9 @@
 
 import (
 	"fmt"
+	"io/ioutil"
 	"math/rand"
+	"net/http"
 	"os"
 	"sync"
 	"testing"
@@ -14,6 +16,8 @@
 
 	"amber/pkg"
 	"amber/source"
+
+	"fidl/amber"
 )
 
 var letters = []rune("1234567890abcdef")
@@ -30,6 +34,7 @@
 
 type testSrc struct {
 	mu         sync.Mutex
+	id         string
 	UpdateReqs map[string]int
 	getReqs    map[pkg.Package]*struct{}
 	interval   time.Duration
@@ -38,6 +43,22 @@
 	limit      uint64
 }
 
+func (t *testSrc) GetId() string {
+	return t.id
+}
+
+func (t *testSrc) GetConfig() *amber.SourceConfig {
+	return nil
+}
+
+func (t *testSrc) GetHttpClient() *http.Client {
+	return nil
+}
+
+func (t *testSrc) Login() (*amber.DeviceCode, error) {
+	return nil, fmt.Errorf("Login() is not implemented")
+}
+
 func (t *testSrc) AvailableUpdates(pkgs []*pkg.Package) (map[pkg.Package]pkg.Package, error) {
 	t.mu.Lock()
 	time.Sleep(t.replyDelay)
@@ -85,6 +106,10 @@
 	return t.limit
 }
 
+func (t *testSrc) Save() error {
+	return nil
+}
+
 type testTicker struct {
 	i    time.Duration
 	last time.Time
@@ -144,7 +169,17 @@
 		src.interval = 1 * time.Nanosecond
 		sources = append(sources, src)
 	}
-	d := NewDaemon(pkgSet, processPackage, sources)
+
+	store, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Error(err)
+	}
+	defer os.RemoveAll(store)
+
+	d, err := NewDaemon(store, pkgSet, processPackage, sources)
+	if err != nil {
+		t.Error(err)
+	}
 
 	tickerGroup.Wait()
 	// protect against improper test rewrites
@@ -178,20 +213,25 @@
 	pkgs[emailPkg.Name] = struct{}{}
 	pkgs[videoPkg.Name] = struct{}{}
 	srcRateLimit := time.Millisecond * 1
-	tSrc := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: srcRateLimit,
-		pkgs:     pkgs,
-		limit:    1}
+	tSrc := testSrc{
+		id:         "src",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   srcRateLimit,
+		pkgs:       pkgs,
+		limit:      1}
 
 	pkgs = make(map[string]struct{})
 	pkgs[videoPkg.Name] = struct{}{}
 	pkgs[srchPkg.Name] = struct{}{}
-	tSrc2 := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: srcRateLimit,
-		pkgs:     pkgs,
-		limit:    1}
+	tSrc2 := testSrc{
+		id:         "src2",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   srcRateLimit,
+		pkgs:       pkgs,
+		limit:      1,
+	}
 	sources := []source.Source{&tSrc, &tSrc2}
 
 	tickers := []testTicker{}
@@ -206,7 +246,17 @@
 
 	tickerGroup.Add(1)
 
-	d := NewDaemon(pkg.NewPackageSet(), processPackage, sources)
+	store, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Error(err)
+	}
+	defer os.RemoveAll(store)
+
+	d, err := NewDaemon(store, pkg.NewPackageSet(), processPackage, sources)
+	if err != nil {
+		t.Error(err)
+	}
+
 	tickerGroup.Wait()
 
 	pkgSet := pkg.NewPackageSet()
@@ -227,11 +277,14 @@
 
 func TestRateLimit(t *testing.T) {
 	srcRateLimit := 20 * time.Millisecond
-	tSrc := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: srcRateLimit,
-		pkgs:     make(map[string]struct{}),
-		limit:    1}
+	tSrc := testSrc{
+		id:         "src",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   srcRateLimit,
+		pkgs:       make(map[string]struct{}),
+		limit:      1,
+	}
 	wrapped := NewSourceKeeper(&tSrc)
 	dummy := []*pkg.Package{&pkg.Package{Name: "None", Version: "aaaaaa"}}
 
@@ -265,20 +318,26 @@
 	pkgs[videoPkg.Name] = struct{}{}
 	srcRateLimit := time.Millisecond
 	replyDelay := 20 * time.Millisecond
-	tSrc := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: srcRateLimit,
-		pkgs:     pkgs,
-		limit:    1}
+	tSrc := testSrc{
+		id:         "src",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   srcRateLimit,
+		pkgs:       pkgs,
+		limit:      1,
+	}
 
 	pkgs = make(map[string]struct{})
 	pkgs[videoPkg.Name] = struct{}{}
 	pkgs[srchPkg.Name] = struct{}{}
-	tSrc2 := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: srcRateLimit,
-		pkgs:     pkgs,
-		limit:    1}
+	tSrc2 := testSrc{
+		id:         "src2",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   srcRateLimit,
+		pkgs:       pkgs,
+		limit:      1,
+	}
 	sources := []source.Source{&tSrc, &tSrc2}
 	testSrcs := []*testSrc{&tSrc, &tSrc2}
 
@@ -299,7 +358,17 @@
 		// simultaneously
 		src.replyDelay = replyDelay
 	}
-	d := NewDaemon(pkg.NewPackageSet(), processPackage, sources)
+
+	store, err := ioutil.TempDir("", "")
+	if err != nil {
+		t.Error(err)
+	}
+	defer os.RemoveAll(store)
+
+	d, err := NewDaemon(store, pkg.NewPackageSet(), processPackage, sources)
+	if err != nil {
+		t.Error(err)
+	}
 
 	tickerGroup.Wait()
 
@@ -345,20 +414,26 @@
 	pkgs := make(map[string]struct{})
 	pkgs["email"] = struct{}{}
 	pkgs["video"] = struct{}{}
-	tSrc := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: time.Millisecond * 3,
-		pkgs:     pkgs,
-		limit:    1}
+	tSrc := testSrc{
+		id:         "src",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   time.Millisecond * 3,
+		pkgs:       pkgs,
+		limit:      1,
+	}
 
 	pkgs = make(map[string]struct{})
 	pkgs["video"] = struct{}{}
 	pkgs["search"] = struct{}{}
-	tSrc2 := testSrc{UpdateReqs: make(map[string]int),
-		getReqs:  make(map[pkg.Package]*struct{}),
-		interval: time.Millisecond * 5,
-		pkgs:     pkgs,
-		limit:    1}
+	tSrc2 := testSrc{
+		id:         "src2",
+		UpdateReqs: make(map[string]int),
+		getReqs:    make(map[pkg.Package]*struct{}),
+		interval:   time.Millisecond * 5,
+		pkgs:       pkgs,
+		limit:      1,
+	}
 	return []*testSrc{&tSrc, &tSrc2}
 }
 
diff --git a/go/src/amber/daemon/source_seq.go b/go/src/amber/daemon/source_seq.go
index 9f5273b..01f2f2b 100644
--- a/go/src/amber/daemon/source_seq.go
+++ b/go/src/amber/daemon/source_seq.go
@@ -7,12 +7,15 @@
 import (
 	"fmt"
 	"log"
+	"net/http"
 	"os"
 	"sync"
 	"time"
 
 	"amber/pkg"
 	"amber/source"
+
+	"fidl/amber"
 )
 
 // SourceKeeper wraps a Source and performs admission control for operations on
@@ -35,6 +38,22 @@
 	}
 }
 
+func (k *SourceKeeper) GetId() string {
+	return k.src.GetId()
+}
+
+func (k *SourceKeeper) GetConfig() *amber.SourceConfig {
+	return k.src.GetConfig()
+}
+
+func (k *SourceKeeper) GetHttpClient() *http.Client {
+	return k.src.GetHttpClient()
+}
+
+func (k *SourceKeeper) Login() (*amber.DeviceCode, error) {
+	return k.src.Login()
+}
+
 func (k *SourceKeeper) AvailableUpdates(pkgs []*pkg.Package) (map[pkg.Package]pkg.Package, error) {
 	k.mu.Lock()
 	defer k.mu.Unlock()
@@ -82,3 +101,7 @@
 func (k *SourceKeeper) CheckLimit() uint64 {
 	return k.src.CheckLimit()
 }
+
+func (k *SourceKeeper) Save() error {
+	return k.src.Save()
+}
diff --git a/go/src/amber/daemon/sys_update.go b/go/src/amber/daemon/sys_update.go
index 9a44381..58a2578 100644
--- a/go/src/amber/daemon/sys_update.go
+++ b/go/src/amber/daemon/sys_update.go
@@ -20,12 +20,16 @@
 	"fuchsia.googlesource.com/merkle"
 )
 
-const updaterDir = "/pkgfs/packages/system_updater"
-const updaterBin = "bin/app"
+var updaterDir = filepath.Join("/pkgfs", "packages", "update")
+var updaterBin = filepath.Join("bin", "app")
 
 type SystemUpdateMonitor struct {
-	halt   uint32
-	daemon *Daemon
+	halt     uint32
+	daemon   *Daemon
+	checkNow chan struct{}
+	// if auto is allowed to be reset after instantiation, changes must be made
+	// in the run loop to avoid a panic
+	auto bool
 }
 
 type ErrNoUpdater string
@@ -38,14 +42,21 @@
 	return ""
 }
 
-func NewSystemUpdateMonitor(d *Daemon) *SystemUpdateMonitor {
-	return &SystemUpdateMonitor{daemon: d, halt: 0}
+func NewSystemUpdateMonitor(d *Daemon, a bool) *SystemUpdateMonitor {
+	return &SystemUpdateMonitor{daemon: d, halt: 0, checkNow: make(chan struct{}), auto: a}
 }
 
 func (upMon *SystemUpdateMonitor) Stop() {
 	atomic.StoreUint32(&upMon.halt, 1)
 }
 
+func (upMon *SystemUpdateMonitor) Check() {
+	if atomic.LoadUint32(&upMon.halt) == 1 {
+		return
+	}
+	upMon.checkNow <- struct{}{}
+}
+
 func (upMon *SystemUpdateMonitor) Start() {
 	path, err := latestSystemUpdater()
 	var contentsPath string
@@ -72,16 +83,28 @@
 	}
 
 	timerDur := 3 * time.Hour
-	// do the first check almost immediately
-	timer := time.NewTimer(time.Second)
+	var timer *time.Timer
+	if upMon.auto {
+		// do the first check almost immediately
+		timer = time.NewTimer(time.Second)
+	}
+
 	for {
-		<-timer.C
-		timer.Reset(timerDur)
+		if upMon.auto {
+			select {
+			case <-timer.C:
+				timer.Reset(timerDur)
+			case <-upMon.checkNow:
+			}
+		} else {
+			<-upMon.checkNow
+		}
+
 		if atomic.LoadUint32(&upMon.halt) == 1 {
 			return
 		}
 
-		updatePkg := &pkg.Package{Name: fmt.Sprintf("/system_updater/%d", 0)}
+		updatePkg := &pkg.Package{Name: fmt.Sprintf("/update/%d", 0)}
 		if err = fetchPackage(updatePkg, amber); err != nil {
 			log.Printf("sys_upd_mon: unable to fetch package update: %s", err)
 			continue
@@ -106,6 +129,8 @@
 			// TODO(jmatt) find a way to invoke the new updater directly
 			c := exec.Command("run", "system_updater")
 			c.Start()
+		} else {
+			log.Println("sys_upd_mon: no newer system version available")
 		}
 		merkle = newMerkle
 	}
diff --git a/go/src/amber/etc/sources/localhost/config.json b/go/src/amber/etc/sources/localhost/config.json
new file mode 100644
index 0000000..4a43e17
--- /dev/null
+++ b/go/src/amber/etc/sources/localhost/config.json
@@ -0,0 +1,13 @@
+{
+    "id": "localhost",
+    "repoUrl": "http://127.0.0.1:8083",
+    "blobRepoUrl": "http://127.0.0.1:8083/blobs",
+    "rateLimit": 0,
+    "ratePeriod": 0,
+    "rootKeys": [
+        {
+            "type": "ed25519",
+            "value": "be0b983f7396da675c40c6b93e47fced7c1e9ea8a32a1fe952ba8f519760b307"
+        }
+    ]
+}
diff --git a/go/src/amber/ipcserver/control_server.go b/go/src/amber/ipcserver/control_server.go
index 3e35e64..d0dbf11 100644
--- a/go/src/amber/ipcserver/control_server.go
+++ b/go/src/amber/ipcserver/control_server.go
@@ -5,12 +5,9 @@
 package ipcserver
 
 import (
-	"encoding/hex"
 	"fmt"
-	"io/ioutil"
 	"strings"
 	"sync"
-	"time"
 
 	"fidl/amber"
 	"fidl/bindings"
@@ -18,11 +15,8 @@
 	"amber/daemon"
 	"amber/lg"
 	"amber/pkg"
-	"amber/source"
 
 	"syscall/zx"
-
-	tuf_data "github.com/flynn/go-tuf/data"
 )
 
 type ControlSrvr struct {
@@ -33,11 +27,12 @@
 	activations chan<- string
 	compReqs    chan<- *completeUpdateRequest
 	writeReqs   chan<- *startUpdateRequest
+	sysUpdate   *daemon.SystemUpdateMonitor
 }
 
 const ZXSIO_DAEMON_ERROR = zx.SignalUser0
 
-func NewControlSrvr(d *daemon.Daemon) *ControlSrvr {
+func NewControlSrvr(d *daemon.Daemon, s *daemon.SystemUpdateMonitor) *ControlSrvr {
 	go bindings.Serve()
 	a := make(chan string, 5)
 	c := make(chan *completeUpdateRequest, 1)
@@ -51,6 +46,7 @@
 		activations: a,
 		compReqs:    c,
 		writeReqs:   w,
+		sysUpdate:   s,
 	}
 }
 
@@ -60,36 +56,21 @@
 }
 
 func (c *ControlSrvr) AddSrc(cfg amber.SourceConfig) (bool, error) {
-	keys := make([]*tuf_data.Key, len(cfg.RootKeys))
-
-	for i, key := range cfg.RootKeys {
-		if key.Type != "ed25519" {
-			return false, fmt.Errorf("Unsupported key type %s", key.Type)
-		}
-
-		keyHex, err := hex.DecodeString(key.Value)
-		if err != nil {
-			return false, err
-		}
-
-		keys[i] = &tuf_data.Key{
-			Type:  key.Type,
-			Value: tuf_data.KeyValue{tuf_data.HexBytes(keyHex)},
-		}
-	}
-
-	dir, err := ioutil.TempDir("", "amber")
-	if err != nil {
+	if err := c.daemon.AddTUFSource(&cfg); err != nil {
 		return false, err
 	}
 
-	tufSource := source.NewTUFSource(cfg.RequestUrl, dir, keys,
-		time.Millisecond*time.Duration(cfg.RatePeriod), uint64(cfg.RateLimit))
-	c.daemon.AddSource(tufSource)
-
 	return true, nil
 }
 
+func (c *ControlSrvr) CheckForSystemUpdate() (bool, error) {
+	if c.sysUpdate != nil {
+		c.sysUpdate.Check()
+		return true, nil
+	}
+	return false, nil
+}
+
 func (c *ControlSrvr) RemoveSrc(url string) (bool, error) {
 	return true, nil
 }
@@ -99,7 +80,13 @@
 }
 
 func (c *ControlSrvr) ListSrcs() ([]amber.SourceConfig, error) {
-	return []amber.SourceConfig{}, nil
+	m := c.daemon.GetSources()
+	v := make([]amber.SourceConfig, 0, len(m))
+	for _, src := range m {
+		v = append(v, *src.GetConfig())
+	}
+
+	return v, nil
 }
 
 func (c *ControlSrvr) getAndWaitForUpdate(name string, version, merkle *string, ch *zx.Channel) {
@@ -207,3 +194,7 @@
 	_, err := c.bs.Add(&s, ch, nil)
 	return err
 }
+
+func (c *ControlSrvr) Login(srcId string) (*amber.DeviceCode, error) {
+	return c.daemon.Login(srcId)
+}
diff --git a/go/src/amber/ota_config/BUILD.gn b/go/src/amber/ota_config/BUILD.gn
new file mode 100644
index 0000000..000a5c1
--- /dev/null
+++ b/go/src/amber/ota_config/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+
+package("amber_flags") {
+  deprecated_system_image = true
+  package_name = "amber_auto_ota_flags"
+  resources = [
+    {
+      dest = "amber/flags/auto.flags"
+      path = rebase_path("auto-apply.flags")
+    },
+  ]
+}
\ No newline at end of file
diff --git a/go/src/amber/ota_config/auto-apply.flags b/go/src/amber/ota_config/auto-apply.flags
new file mode 100644
index 0000000..66af866
--- /dev/null
+++ b/go/src/amber/ota_config/auto-apply.flags
@@ -0,0 +1 @@
+-a
diff --git a/go/src/amber/source/source.go b/go/src/amber/source/source.go
index 2c23f40..06cc746 100644
--- a/go/src/amber/source/source.go
+++ b/go/src/amber/source/source.go
@@ -6,10 +6,13 @@
 
 import (
 	"errors"
+	"net/http"
 	"os"
 	"time"
 
 	"amber/pkg"
+
+	"fidl/amber"
 )
 
 // ErrNoUpdate is returned if no update is available
@@ -26,6 +29,16 @@
 // Source provides a way to get information about a package update and a way
 // to get that update.
 type Source interface {
+	// A unique identifier that distinquishes this source from others.
+	GetId() string
+
+	// The config definition for this source.
+	GetConfig() *amber.SourceConfig
+
+	// TODO(etryzelaar) This is a bit of a hack, but the blob fetcher also
+	// needs an authenticated http.Client. This really ought to be refactored.
+	GetHttpClient() *http.Client
+
 	// AvailableUpdates takes a list of packages and returns update metadata
 	// for any updates available for those packages.
 	AvailableUpdates(pkg []*pkg.Package) (map[pkg.Package]pkg.Package, error)
@@ -45,4 +58,10 @@
 
 	// Equals should return true if the provide Source is the same as the receiver.
 	Equals(s Source) bool
+
+	Save() error
+
+	// Log into the TUF remote server and return the oauth2 device flow
+	// code to complete the authentication process.
+	Login() (*amber.DeviceCode, error)
 }
diff --git a/go/src/amber/source/tuf_source.go b/go/src/amber/source/tuf_source.go
index b41a21c..6feb7b2 100644
--- a/go/src/amber/source/tuf_source.go
+++ b/go/src/amber/source/tuf_source.go
@@ -5,36 +5,84 @@
 package source
 
 import (
+	"encoding/hex"
 	"encoding/json"
 	"errors"
 	"fmt"
 	"io/ioutil"
+	"log"
+	"net/http"
+	"net/url"
 	"os"
+	"path/filepath"
+	"sync"
 	"time"
 
 	"amber/lg"
 	"amber/pkg"
 
+	"fidl/amber"
+
 	tuf "github.com/flynn/go-tuf/client"
 	tuf_data "github.com/flynn/go-tuf/data"
+	"github.com/rjw57/oauth2device"
+	"golang.org/x/oauth2"
+
 	"github.com/flynn/go-tuf/verify"
 )
 
+const (
+	configFileName = "config.json"
+)
+
 // ErrTufSrcNoHash is returned if the TUF entry doesn't have a SHA512 hash
 var ErrTufSrcNoHash = errors.New("tufsource: hash missing or wrong type")
 
-type Config struct {
-	URL       string
-	LocalPath string
-	Keys      []*tuf_data.Key
+type tufSourceConfig struct {
+	Config *amber.SourceConfig
+
+	Oauth2Token *oauth2.Token
+}
+
+func newTUFSourceConfig(cfg *amber.SourceConfig) (tufSourceConfig, error) {
+	if cfg.Id == "" {
+		return tufSourceConfig{}, fmt.Errorf("tuf source id cannot be empty")
+	}
+
+	if _, err := url.ParseRequestURI(cfg.RepoUrl); err != nil {
+		return tufSourceConfig{}, err
+	}
+
+	if len(cfg.RootKeys) == 0 {
+		return tufSourceConfig{}, fmt.Errorf("no root keys provided")
+	}
+
+	return tufSourceConfig{
+		Config: cfg,
+	}, nil
 }
 
 // TUFSource wraps a TUF Client into the Source interface
 type TUFSource struct {
-	Client   *tuf.Client
-	Interval time.Duration
-	Limit    uint64
-	Config   *Config
+	cfg tufSourceConfig
+
+	dir string
+
+	// `initialized` is set after we initialize in order to save us from
+	// doing unnecessary network accesses.
+	initialized bool
+
+	// We save a reference to the tuf local store so that when we update
+	// the tuf client, we can reuse the store. This avoids us from having
+	// multiple database connections to the same file, which could corrupt
+	// the TUF database.
+	localStore tuf.LocalStore
+
+	httpClient *http.Client
+
+	keys      []*tuf_data.Key
+	tufClient *tuf.Client
+	mu        sync.Mutex
 }
 
 type merkle struct {
@@ -49,69 +97,253 @@
 	error
 }
 
-func LoadKeys(path string) ([]*tuf_data.Key, error) {
-	f, err := os.Open(path)
-	defer f.Close()
+func NewTUFSource(dir string, c *amber.SourceConfig) (*TUFSource, error) {
+	if dir == "" {
+		return nil, fmt.Errorf("tuf source directory cannot be an empty string")
+	}
+
+	cfg, err := newTUFSourceConfig(c)
 	if err != nil {
 		return nil, err
 	}
 
-	var keys []*tuf_data.Key
-	err = json.NewDecoder(f).Decode(&keys)
-	return keys, err
+	src := TUFSource{
+		cfg: cfg,
+		dir: dir,
+	}
+
+	if err := src.initSource(); err != nil {
+		return nil, err
+	}
+
+	return &src, nil
 }
 
-func NewTUFSource(url string, path string, keys []*tuf_data.Key, interval time.Duration,
-	limit uint64) *TUFSource {
-	c := Config{
-		URL:       url,
-		LocalPath: path,
-		Keys:      keys,
+func LoadTUFSourceFromPath(dir string) (*TUFSource, error) {
+	log.Printf("loading source from %s", dir)
+
+	f, err := os.Open(filepath.Join(dir, configFileName))
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	var cfg tufSourceConfig
+	if err := json.NewDecoder(f).Decode(&cfg); err != nil {
+		return nil, err
 	}
 
 	src := TUFSource{
-		Interval: interval,
-		Limit:    limit,
-		Config:   &c,
+		cfg: cfg,
+		dir: dir,
 	}
 
-	return &src
+	if err := src.initSource(); err != nil {
+		return nil, err
+	}
+
+	return &src, nil
 }
 
-func (f *TUFSource) initSrc() error {
-	if f.Client != nil {
-		return nil
-	}
+// This function finishes initializing the TUFSource by parsing out the config
+// data to create the derived fields, like the TUFClient.
+func (f *TUFSource) initSource() error {
+	f.mu.Lock()
+	defer f.mu.Unlock()
 
-	client, store, err := newTUFClient(f.Config.URL, f.Config.LocalPath)
-
+	keys, err := newTUFKeys(f.cfg.Config.RootKeys)
 	if err != nil {
 		return err
 	}
+	f.keys = keys
 
-	needs, err := needsInit(store)
+	// We might have multiple things in the store directory, so put tuf in
+	// it's own directory.
+	localStore, err := tuf.FileLocalStore(filepath.Join(f.dir, "tuf"))
+	if err != nil {
+		return IOError{fmt.Errorf("couldn't open datastore: %s", err)}
+	}
+	f.localStore = localStore
+
+	if err := f.updateTUFClientLocked(); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func oauth2deviceConfig(c *amber.OAuth2Config) *oauth2device.Config {
+	if c == nil {
+		return nil
+	}
+
+	return &oauth2device.Config{
+		Config: &oauth2.Config{
+			ClientID:     c.ClientId,
+			ClientSecret: c.ClientSecret,
+			Endpoint: oauth2.Endpoint{
+				AuthURL:  c.AuthUrl,
+				TokenURL: c.TokenUrl,
+			},
+			Scopes: c.Scopes,
+		},
+		DeviceEndpoint: oauth2device.DeviceEndpoint{
+			CodeURL: c.DeviceCodeUrl,
+		},
+	}
+
+}
+
+// Initialize (or reinitialize) the TUFClient. This is especially useful when
+// logging in, or modifying any of the http settings since there's no way to
+// change settings in place, so we need to replace it with a new tuf.Client.
+//
+// NOTE: It's the responsibility of the caller to hold the mutex before calling
+// this function.
+func (f *TUFSource) updateTUFClientLocked() error {
+	if c := oauth2deviceConfig(f.cfg.Config.Oauth2Config); c == nil {
+		f.httpClient = http.DefaultClient
+	} else {
+		f.httpClient = c.Client(nil, f.cfg.Oauth2Token)
+	}
+
+	remoteStore, err := tuf.HTTPRemoteStore(f.cfg.Config.RepoUrl, nil, f.httpClient)
+	if err != nil {
+		return RemoteStoreError{fmt.Errorf("server address not understood: %s", err)}
+	}
+
+	f.tufClient = tuf.NewClient(f.localStore, remoteStore)
+
+	return nil
+}
+
+// Note, the mutex should be held when this is called.
+func (f *TUFSource) initLocalStoreLocked() error {
+	if f.initialized {
+		return nil
+	}
+
+	needs, err := needsInit(f.localStore)
 	if err != nil {
 		return fmt.Errorf("source status check failed: %s", err)
 	}
 
 	if needs {
-		err := client.Init(f.Config.Keys, len(f.Config.Keys))
+		err := f.tufClient.Init(f.keys, len(f.keys))
 		if err != nil {
 			return fmt.Errorf("TUF init failed: %s", err)
 		}
 	}
 
-	f.Client = client
+	f.initialized = true
+
 	return nil
 }
 
+func newTUFKeys(cfg []amber.KeyConfig) ([]*tuf_data.Key, error) {
+	keys := make([]*tuf_data.Key, len(cfg))
+
+	for i, key := range cfg {
+		if key.Type != "ed25519" {
+			return nil, fmt.Errorf("unsupported key type %s", key.Type)
+		}
+
+		keyHex, err := hex.DecodeString(key.Value)
+		if err != nil {
+			return nil, fmt.Errorf("invalid key value: %s", err)
+		}
+
+		keys[i] = &tuf_data.Key{
+			Type:  key.Type,
+			Value: tuf_data.KeyValue{tuf_data.HexBytes(keyHex)},
+		}
+	}
+
+	return keys, nil
+}
+
+func (f *TUFSource) GetId() string {
+	return f.cfg.Config.Id
+}
+
+func (f *TUFSource) GetConfig() *amber.SourceConfig {
+	return f.cfg.Config
+}
+
+func (f *TUFSource) GetHttpClient() *http.Client {
+	return f.httpClient
+}
+
+func (f *TUFSource) Login() (*amber.DeviceCode, error) {
+	log.Printf("logging into tuf source: %s", f.cfg.Config.Id)
+
+	c := oauth2deviceConfig(f.cfg.Config.Oauth2Config)
+	if c == nil {
+		log.Printf("source is not configured for oauth2")
+		return nil, fmt.Errorf("source is not configured for oauth2")
+	}
+
+	code, err := oauth2device.RequestDeviceCode(http.DefaultClient, c)
+	if err != nil {
+		log.Printf("failed to get device code: %s", err)
+		return nil, fmt.Errorf("failed to get device code: %s", err)
+	}
+
+	// Wait for the device authorization in a separate thread so we don't
+	// block the response. This thread will eventually time out if the user
+	// does not enter in the code.
+	go f.waitForDeviceAuthorization(c, code)
+
+	return &amber.DeviceCode{
+		VerificationUrl: code.VerificationURL,
+		UserCode:        code.UserCode,
+		ExpiresIn:       code.ExpiresIn,
+	}, nil
+}
+
+// Wait for the oauth2 server to authorize us to access the TUF repository. If
+// we are denied access, we will log the error, but otherwise do nothing.
+func (f *TUFSource) waitForDeviceAuthorization(config *oauth2device.Config, code *oauth2device.DeviceCode) {
+	log.Printf("waiting for device authorization: %s", f.cfg.Config.Id)
+
+	token, err := oauth2device.WaitForDeviceAuthorization(http.DefaultClient, config, code)
+	if err != nil {
+		log.Printf("failed to get device authorization token: %s", err)
+		return
+	}
+
+	log.Printf("token received for remote store: %s", f.cfg.Config.Id)
+
+	// Now that we have a token, grab the lock, and update our client.
+	f.mu.Lock()
+	defer f.mu.Unlock()
+
+	f.cfg.Oauth2Token = token
+
+	if err := f.updateTUFClientLocked(); err != nil {
+		log.Printf("failed to update tuf client: %s", err)
+		return
+	}
+
+	if err := f.saveLocked(); err != nil {
+		log.Printf("failed to save config: %s", err)
+		return
+	}
+
+	log.Printf("remote store updated: %s", f.cfg.Config.Id)
+}
+
 // AvailableUpdates takes a list of Packages and returns a map from those Packages
 // to any available update Package
 func (f *TUFSource) AvailableUpdates(pkgs []*pkg.Package) (map[pkg.Package]pkg.Package, error) {
-	if err := f.initSrc(); err != nil {
+	f.mu.Lock()
+	defer f.mu.Unlock()
+
+	if err := f.initLocalStoreLocked(); err != nil {
 		return nil, fmt.Errorf("tuf_source: source could not be initialized: %s", err)
 	}
-	_, err := f.Client.Update()
+
+	_, err := f.tufClient.Update()
 	if err != nil && !tuf.IsLatestSnapshot(err) {
 		if _, ok := err.(tuf.ErrDecodeFailed); ok {
 			e := err.(tuf.ErrDecodeFailed)
@@ -125,7 +357,7 @@
 
 	// TODO(jmatt) seems like 'm' should be the same as returned from
 	// Client.Update, but empirically this seems untrue, investigate
-	m, err := f.Client.Targets()
+	m, err := f.tufClient.Targets()
 
 	if err != nil {
 		return nil, err
@@ -177,7 +409,10 @@
 
 // FetchPkg gets the content for the requested Package
 func (f *TUFSource) FetchPkg(pkg *pkg.Package) (*os.File, error) {
-	if err := f.initSrc(); err != nil {
+	f.mu.Lock()
+	defer f.mu.Unlock()
+
+	if err := f.initLocalStoreLocked(); err != nil {
 		return nil, fmt.Errorf("tuf_source: source could not be initialized: %s", err)
 	}
 	lg.Log.Printf("tuf_source: requesting download for: %s\n", pkg.Name)
@@ -186,7 +421,7 @@
 		return nil, err
 	}
 
-	err = f.Client.Download(pkg.Name, &delFile{tmp})
+	err = f.tufClient.Download(pkg.Name, &delFile{tmp})
 	if err != nil {
 		return nil, ErrNoUpdateContent
 	}
@@ -204,11 +439,11 @@
 func (f *TUFSource) CheckInterval() time.Duration {
 	// TODO(jmatt) figure out how to establish a real value from the
 	// Client we wrap
-	return f.Interval
+	return time.Millisecond * time.Duration(f.cfg.Config.RatePeriod)
 }
 
 func (f *TUFSource) CheckLimit() uint64 {
-	return f.Limit
+	return f.cfg.Config.RateLimit
 }
 
 // Equals returns true if the Source passed in is a pointer to this instance
@@ -221,18 +456,58 @@
 	}
 }
 
-func newTUFClient(url string, path string) (*tuf.Client, tuf.LocalStore, error) {
-	tufStore, err := tuf.FileLocalStore(path)
+func (f *TUFSource) Save() error {
+	f.mu.Lock()
+	defer f.mu.Unlock()
+
+	return f.saveLocked()
+}
+
+// Actually save the config.
+
+// NOTE: It's the responsibility of the caller to hold the mutex before calling
+// this function.
+func (f *TUFSource) saveLocked() error {
+	err := os.MkdirAll(f.dir, os.ModePerm)
 	if err != nil {
-		return nil, nil, IOError{fmt.Errorf("couldn't open datastore: %s", err)}
+		return err
 	}
 
-	server, err := tuf.HTTPRemoteStore(url, nil, nil)
+	p := filepath.Join(f.dir, configFileName)
+
+	// We want to atomically write the config, so we'll first write it to a
+	// temp file, then do an atomic rename to overwrite the target.
+
+	file, err := ioutil.TempFile(f.dir, configFileName)
 	if err != nil {
-		return nil, nil, RemoteStoreError{fmt.Errorf("server address not understood: %s", err)}
+		return err
+	}
+	defer file.Close()
+
+	// Make sure to clean up the temp file if there's an error.
+	defer func() {
+		if err != nil {
+			os.Remove(file.Name())
+		}
+	}()
+
+	// Encode the cfg as a pretty printed json.
+	encoder := json.NewEncoder(file)
+	encoder.SetIndent("", "    ")
+
+	if err = encoder.Encode(f.cfg); err != nil {
+		return err
 	}
 
-	return tuf.NewClient(tufStore, server), tufStore, nil
+	if err = file.Close(); err != nil {
+		return err
+	}
+
+	if err = os.Rename(file.Name(), p); err != nil {
+		return err
+	}
+
+	return nil
 }
 
 func needsInit(s tuf.LocalStore) (bool, error) {
diff --git a/go/src/device_settings/device_settings_test.go b/go/src/device_settings/device_settings_test.go
index 6b87ef8..4f74fd1 100644
--- a/go/src/device_settings/device_settings_test.go
+++ b/go/src/device_settings/device_settings_test.go
@@ -8,7 +8,7 @@
 	"testing"
 
 	"app/context"
-	"fidl/device_settings"
+	"fidl/fuchsia/devicesettings"
 )
 
 const (
@@ -17,7 +17,7 @@
 
 func TestDeviceSettingsSimple(t *testing.T) {
 	ctx := context.CreateFromStartupInfo()
-	req, dm, err := device_settings.NewDeviceSettingsManagerInterfaceRequest()
+	req, dm, err := devicesettings.NewDeviceSettingsManagerInterfaceRequest()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -30,7 +30,7 @@
 	}
 	if i, s, err := dm.GetInteger(TestSettingKey); err != nil {
 		t.Fatal(err)
-	} else if s != device_settings.StatusOk {
+	} else if s != devicesettings.StatusOk {
 		t.Fatalf("got err status: %s", s)
 	} else if i != 10 {
 		t.Fatalf("expected 10 got : %d", i)
@@ -43,7 +43,7 @@
 	}
 	if str, s, err := dm.GetString(TestSettingKey); err != nil {
 		t.Fatal(err)
-	} else if s != device_settings.StatusOk {
+	} else if s != devicesettings.StatusOk {
 		t.Fatalf("got err status: %s", s)
 	} else if str != "somestring" {
 		t.Fatalf("expected 'somestring' got : %q", str)
diff --git a/go/src/fidl/compiler/backend/backend.go b/go/src/fidl/compiler/backend/backend.go
index fb8ffe7..b430a8b 100644
--- a/go/src/fidl/compiler/backend/backend.go
+++ b/go/src/fidl/compiler/backend/backend.go
@@ -5,14 +5,13 @@
 package main
 
 import (
-	"encoding/json"
+	"fidl/compiler/backend/cmdline"
 	"fidl/compiler/backend/cpp"
 	"fidl/compiler/backend/dart"
 	"fidl/compiler/backend/golang"
 	"fidl/compiler/backend/rust"
 	"fidl/compiler/backend/types"
 	"flag"
-	"io/ioutil"
 	"log"
 	"os"
 )
@@ -29,59 +28,30 @@
 }
 
 func main() {
-	jsonPath := flag.String("json", "",
-		"relative path to the FIDL intermediate representation.")
-	outputBase := flag.String("output-base", "",
-		"the base file name for files generated by this generator.")
-	includeBase := flag.String("include-base", "",
-		"the directory to which C and C++ includes should be relative.")
+	baseFlags := cmdline.BaseFlags()
 	var generatorNames CommaSeparatedList
 	flag.Var(&generatorNames, "generators",
 		"Comma-separated list of names of generators to run")
 	flag.Parse()
 
-	if !flag.Parsed() {
+	if !flag.Parsed() || !baseFlags.Valid() {
 		flag.PrintDefaults()
 		os.Exit(1)
 	}
 
-	if *jsonPath == "" || *outputBase == "" || *includeBase == "" {
-		flag.PrintDefaults()
-		os.Exit(1)
-	}
-
-	bytes, err := ioutil.ReadFile(*jsonPath)
-	if err != nil {
-		log.Fatalf("Error reading from %s: %v", *jsonPath, err)
-	}
-
-	var fidl types.Root
-	err = json.Unmarshal(bytes, &fidl)
-	if err != nil {
-		log.Fatalf("Error parsing JSON as FIDL data: %v", err)
-	}
-
-	for _, l := range fidl.Libraries {
-		for k, v := range l.Decls {
-			fidl.Decls[types.EnsureLibrary(l.Name, k)] = v
-		}
-	}
+	fidl := baseFlags.FidlTypes()
+	config := baseFlags.Config()
 
 	running := 0
 	results := make(chan error)
 	didError := false
 	generatorNames = []string(generatorNames)
 
-	config := &types.Config{
-		*outputBase,
-		*includeBase,
-	}
-
 	for _, generatorName := range generatorNames {
 		if generator, ok := generators[generatorName]; ok {
 			running++
 			go func() {
-				results <- generator.GenerateFidl(fidl, config)
+				results <- generator.GenerateFidl(fidl, &config)
 			}()
 		} else {
 			log.Printf("Error: generator %s not found", generatorName)
@@ -90,7 +60,7 @@
 	}
 
 	for running > 0 {
-		err = <-results
+		err := <-results
 		if err != nil {
 			log.Printf("Error running generator: %v", err)
 			didError = true
diff --git a/go/src/fidl/compiler/backend/cmdline/flags.go b/go/src/fidl/compiler/backend/cmdline/flags.go
new file mode 100644
index 0000000..0340d86
--- /dev/null
+++ b/go/src/fidl/compiler/backend/cmdline/flags.go
@@ -0,0 +1,67 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package cmdline
+
+import (
+	"encoding/json"
+	"fidl/compiler/backend/types"
+	"flag"
+	"io/ioutil"
+	"log"
+)
+
+// Flags common to all FIDL backends.
+type Flags struct {
+	jsonPath    *string
+	outputBase  *string
+	includeBase *string
+}
+
+// BaseFlags returns the common set of flags for FIDL backends.
+func BaseFlags() Flags {
+	return Flags{
+		flag.String("json", "",
+			"relative path to the FIDL intermediate representation."),
+		flag.String("output-base", "",
+			"the base file name for files generated by this generator."),
+		flag.String("include-base", "",
+			"the directory to which C and C++ includes should be relative."),
+	}
+}
+
+// Valid returns true if the parsed flags are valid.
+func (f Flags) Valid() bool {
+	return *f.jsonPath != "" && *f.outputBase != "" && *f.includeBase != ""
+}
+
+// FidlTypes returns the root FIDL type information from the JSON file specified as an argument.
+func (f Flags) FidlTypes() types.Root {
+	bytes, err := ioutil.ReadFile(*f.jsonPath)
+	if err != nil {
+		log.Fatalf("Error reading from %s: %v", *f.jsonPath, err)
+	}
+
+	var fidl types.Root
+	err = json.Unmarshal(bytes, &fidl)
+	if err != nil {
+		log.Fatalf("Error parsing JSON as FIDL data: %v", err)
+	}
+
+	for _, l := range fidl.Libraries {
+		for k, v := range l.Decls {
+			fidl.Decls[types.EnsureLibrary(l.Name, k)] = v
+		}
+	}
+
+	return fidl
+}
+
+// Config returns the Config object for the supplied flags.
+func (f Flags) Config() types.Config {
+	return types.Config{
+		OutputBase:  *f.outputBase,
+		IncludeBase: *f.includeBase,
+	}
+}
diff --git a/go/src/fidl/compiler/backend/cpp/ir/ir.go b/go/src/fidl/compiler/backend/cpp/ir/ir.go
index 37ec3c3..bde4c31 100644
--- a/go/src/fidl/compiler/backend/cpp/ir/ir.go
+++ b/go/src/fidl/compiler/backend/cpp/ir/ir.go
@@ -7,6 +7,7 @@
 import (
 	"fidl/compiler/backend/common"
 	"fidl/compiler/backend/types"
+	"flag"
 	"fmt"
 	"io"
 	"log"
@@ -14,6 +15,9 @@
 	"text/template"
 )
 
+var legacyCallbacks = flag.Bool("cpp-legacy-callbacks", false,
+	"use std::function instead of fit::function in C++ callbacks")
+
 type Decl interface {
 	ForwardDeclaration(*template.Template, io.Writer) error
 	Declaration(*template.Template, io.Writer) error
@@ -113,10 +117,11 @@
 }
 
 type Root struct {
-	PrimaryHeader string
-	Headers       []string
-	Library       types.LibraryIdentifier
-	Decls         []Decl
+	PrimaryHeader   string
+	Headers         []string
+	Library         types.LibraryIdentifier
+	LibraryReversed types.LibraryIdentifier
+	Decls           []Decl
 }
 
 func (c *Const) ForwardDeclaration(tmpls *template.Template, wr io.Writer) error {
@@ -199,6 +204,13 @@
 	return tmpls.ExecuteTemplate(wr, "InterfaceDefinition", i)
 }
 
+func (m *Method) CallbackWrapper() string {
+	if *legacyCallbacks {
+		return "std::function"
+	}
+	return "fit::function"
+}
+
 var reservedWords = map[string]bool{
 	"alignas":          true,
 	"alignof":          true,
@@ -647,6 +659,14 @@
 	}
 
 	root.Library = library
+	libraryReversed := make(types.LibraryIdentifier, len(library))
+	for i, j := 0, len(library)-1; i < len(library); i, j = i+1, j-1 {
+		libraryReversed[i] = library[j]
+	}
+	for i, identifier := range library {
+		libraryReversed[len(libraryReversed)-i-1] = identifier
+	}
+	root.LibraryReversed = libraryReversed
 
 	decls := map[types.EncodedCompoundIdentifier]Decl{}
 
diff --git a/go/src/fidl/compiler/backend/cpp/templates/enum.tmpl.go b/go/src/fidl/compiler/backend/cpp/templates/enum.tmpl.go
index 7857a5d..1e5d373 100644
--- a/go/src/fidl/compiler/backend/cpp/templates/enum.tmpl.go
+++ b/go/src/fidl/compiler/backend/cpp/templates/enum.tmpl.go
@@ -23,11 +23,11 @@
   static constexpr size_t encoded_size = sizeof({{ .Namespace }}::{{ .Name }});
   static void Encode(Encoder* encoder, {{ .Namespace }}::{{ .Name }}* value, size_t offset) {
     {{ .Type }} underlying = static_cast<{{ .Type }}>(*value);
-    fidl::Encode(encoder, &underlying, offset);
+    ::fidl::Encode(encoder, &underlying, offset);
   }
   static void Decode(Decoder* decoder, {{ .Namespace }}::{{ .Name }}* value, size_t offset) {
     {{ .Type }} underlying = {};
-    fidl::Decode(decoder, &underlying, offset);
+    ::fidl::Decode(decoder, &underlying, offset);
     *value = static_cast<{{ .Namespace }}::{{ .Name }}>(underlying);
   }
 };
diff --git a/go/src/fidl/compiler/backend/cpp/templates/header.tmpl.go b/go/src/fidl/compiler/backend/cpp/templates/header.tmpl.go
index 996d6bb..fb0fdae 100644
--- a/go/src/fidl/compiler/backend/cpp/templates/header.tmpl.go
+++ b/go/src/fidl/compiler/backend/cpp/templates/header.tmpl.go
@@ -26,8 +26,8 @@
 {{ end }}
 
 {{- define "GenerateHeaderPostamble" -}}
-{{- range .Library }}
-}
+{{- range .LibraryReversed }}
+}  // namespace {{ . }}
 {{- end }}
 {{ end }}
 
diff --git a/go/src/fidl/compiler/backend/cpp/templates/implementation.impl.go b/go/src/fidl/compiler/backend/cpp/templates/implementation.impl.go
index 40eb528..0b58e2e 100644
--- a/go/src/fidl/compiler/backend/cpp/templates/implementation.impl.go
+++ b/go/src/fidl/compiler/backend/cpp/templates/implementation.impl.go
@@ -22,8 +22,8 @@
 {{ end }}
 
 {{- define "GenerateImplementationPostamble" -}}
-{{- range .Library }}
-}
+{{- range .LibraryReversed }}
+}  // namespace {{ . }}
 {{- end }}
 {{ end }}
 `
diff --git a/go/src/fidl/compiler/backend/cpp/templates/interface.tmpl.go b/go/src/fidl/compiler/backend/cpp/templates/interface.tmpl.go
index 04312fe..d61c9c4 100644
--- a/go/src/fidl/compiler/backend/cpp/templates/interface.tmpl.go
+++ b/go/src/fidl/compiler/backend/cpp/templates/interface.tmpl.go
@@ -69,7 +69,7 @@
   {{- range .Methods }}
     {{- if .HasResponse }}
   using {{ .CallbackType }} =
-      std::function<void({{ template "ParamTypes" .Response }})>;
+      {{ .CallbackWrapper }}<void({{ template "ParamTypes" .Response }})>;
     {{- end }}
     {{- if .HasRequest }}
   virtual void {{ template "RequestMethodSignature" . }} = 0;
diff --git a/go/src/fidl/compiler/backend/cpp/templates/union.tmpl.go b/go/src/fidl/compiler/backend/cpp/templates/union.tmpl.go
index 279384a..2067db9 100644
--- a/go/src/fidl/compiler/backend/cpp/templates/union.tmpl.go
+++ b/go/src/fidl/compiler/backend/cpp/templates/union.tmpl.go
@@ -158,7 +158,7 @@
   switch (lhs.tag_) {
     {{- range $index, $member := .Members }}
     case {{ $index }}:
-      return fidl::Equals(lhs.{{ .StorageName }}, rhs.{{ .StorageName }});
+      return ::fidl::Equals(lhs.{{ .StorageName }}, rhs.{{ .StorageName }});
     {{- end }}
     case ::std::numeric_limits<::fidl_union_tag_t>::max():
       return true;
diff --git a/go/src/fidl/compiler/backend/dart/generator.go b/go/src/fidl/compiler/backend/dart/generator.go
index 66d70ba..b137c257 100644
--- a/go/src/fidl/compiler/backend/dart/generator.go
+++ b/go/src/fidl/compiler/backend/dart/generator.go
@@ -37,6 +37,10 @@
 	template.Must(tmpls.Parse(templates.Struct))
 	template.Must(tmpls.Parse(templates.Union))
 
-	libraryPath := config.OutputBase
-	return writeFile(libraryPath, "GenerateLibraryFile", tmpls, tree)
+	err := writeFile(config.OutputBase+"/fidl.dart", "GenerateLibraryFile", tmpls, tree)
+	if err != nil {
+		return err
+	}
+
+	return writeFile(config.OutputBase+"/fidl_async.dart", "GenerateAsyncFile", tmpls, tree)
 }
diff --git a/go/src/fidl/compiler/backend/dart/ir/ir.go b/go/src/fidl/compiler/backend/dart/ir/ir.go
index 729f080..a75fc0c 100644
--- a/go/src/fidl/compiler/backend/dart/ir/ir.go
+++ b/go/src/fidl/compiler/backend/dart/ir/ir.go
@@ -15,6 +15,7 @@
 
 type Type struct {
 	Decl          string
+	SyncDecl      string
 	Nullable      bool
 	declType      types.DeclType
 	typedDataDecl string
@@ -81,30 +82,35 @@
 }
 
 type Method struct {
-	Ordinal      types.Ordinal
-	OrdinalName  string
-	Name         string
-	HasRequest   bool
-	Request      []Parameter
-	RequestSize  int
-	HasResponse  bool
-	Response     []Parameter
-	ResponseSize int
-	CallbackType string
-	TypeSymbol   string
-	TypeExpr     string
+	Ordinal            types.Ordinal
+	OrdinalName        string
+	Name               string
+	HasRequest         bool
+	Request            []Parameter
+	RequestSize        int
+	HasResponse        bool
+	Response           []Parameter
+	ResponseSize       int
+	AsyncResponseClass string
+	AsyncResponseType  string
+	CallbackType       string
+	TypeSymbol         string
+	TypeExpr           string
 }
 
 type Parameter struct {
 	Type     Type
 	Name     string
 	Offset   int
+	Convert  string
 	typeExpr string
 }
 
 type Import struct {
-	Url       string
-	LocalName string
+	Url            string
+	LocalName      string
+	AsyncUrl       string
+	AsyncLocalName string
 }
 
 type Root struct {
@@ -122,6 +128,7 @@
 // back but also make the code generator smarter about escaping
 // reserved words to avoid style violations in various contexts.
 var reservedWords = map[string]bool{
+	// "Error":      true,
 	"abstract":   true,
 	"as":         true,
 	"assert":     true,
@@ -426,6 +433,9 @@
 			r.Decl = t.typedDataDecl
 		} else {
 			r.Decl = fmt.Sprintf("List<%s>", t.Decl)
+			if t.SyncDecl != "" {
+				r.SyncDecl = fmt.Sprintf("List<%s>", t.SyncDecl)
+			}
 		}
 		elementStr := fmt.Sprintf("element: %s", t.typeExpr)
 		elementCountStr := fmt.Sprintf("elementCount: %s", formatInt(val.ElementCount))
@@ -436,6 +446,9 @@
 			r.Decl = t.typedDataDecl
 		} else {
 			r.Decl = fmt.Sprintf("List<%s>", t.Decl)
+			if t.SyncDecl != "" {
+				r.SyncDecl = fmt.Sprintf("List<%s>", t.SyncDecl)
+			}
 		}
 		elementStr := fmt.Sprintf("element: %s", t.typeExpr)
 		maybeElementCountStr := fmt.Sprintf("maybeElementCount: %s", formatInt(val.ElementCount))
@@ -460,8 +473,14 @@
 		r.typeExpr = fmt.Sprintf("const $fidl.%sType(nullable: %s)",
 			r.Decl, formatBool(val.Nullable))
 	case types.RequestType:
-		t := c.compileUpperCamelCompoundIdentifier(types.ParseCompoundIdentifier(val.RequestSubtype), "")
+		compound := types.ParseCompoundIdentifier(val.RequestSubtype)
+		t := c.compileUpperCamelCompoundIdentifier(compound, "")
 		r.Decl = fmt.Sprintf("$fidl.InterfaceRequest<%s>", t)
+		if c.inExternalLibrary(compound) {
+			r.SyncDecl = fmt.Sprintf("$fidl.InterfaceRequest<sync$%s>", t)
+		} else {
+			r.SyncDecl = fmt.Sprintf("$fidl.InterfaceRequest<$sync.%s>", t)
+		}
 		r.typeExpr = fmt.Sprintf("const $fidl.InterfaceRequestType<%s>(nullable: %s)",
 			t, formatBool(val.Nullable))
 	case types.PrimitiveType:
@@ -469,7 +488,8 @@
 		r.typedDataDecl = typedDataDecl[val.PrimitiveSubtype]
 		r.typeExpr = typeExprForPrimitiveSubtype(val.PrimitiveSubtype)
 	case types.IdentifierType:
-		t := c.compileUpperCamelCompoundIdentifier(types.ParseCompoundIdentifier(val.Identifier), "")
+		compound := types.ParseCompoundIdentifier(val.Identifier)
+		t := c.compileUpperCamelCompoundIdentifier(compound, "")
 		declType, ok := (*c.decls)[val.Identifier]
 		if !ok {
 			log.Fatal("Unknown identifier: ", val.Identifier)
@@ -484,6 +504,12 @@
 			fallthrough
 		case types.UnionDeclType:
 			r.Decl = t
+			if c.inExternalLibrary(compound) {
+				r.SyncDecl = fmt.Sprintf("sync$%s", t)
+
+			} else {
+				r.SyncDecl = fmt.Sprintf("$sync.%s", t)
+			}
 			r.typeExpr = c.typeSymbolForCompoundIdentifier(types.ParseCompoundIdentifier(val.Identifier))
 			if val.Nullable {
 				r.typeExpr = fmt.Sprintf("const $fidl.PointerType<%s>(element: %s)",
@@ -491,6 +517,12 @@
 			}
 		case types.InterfaceDeclType:
 			r.Decl = fmt.Sprintf("$fidl.InterfaceHandle<%s>", t)
+			if c.inExternalLibrary(compound) {
+				r.SyncDecl = fmt.Sprintf("$fidl.InterfaceHandle<sync$%s>", t)
+
+			} else {
+				r.SyncDecl = fmt.Sprintf("$fidl.InterfaceHandle<$sync.%s>", t)
+			}
 			r.typeExpr = fmt.Sprintf("const $fidl.InterfaceHandleType<%s>(nullable: %s)",
 				t, formatBool(val.Nullable))
 		default:
@@ -539,11 +571,19 @@
 		t := c.compileType(v.Type)
 		typeStr := fmt.Sprintf("type: %s", t.typeExpr)
 		offsetStr := fmt.Sprintf("offset: %v", v.Offset)
+		name := c.compileLowerCamelIdentifier(v.Name)
+		convert := ""
+		if t.declType == types.InterfaceDeclType {
+			convert = "_convertInterfaceHandle"
+		} else if v.Type.Kind == types.RequestType {
+			convert = "_convertInterfaceRequest"
+		}
 		p := Parameter{
-			t,
-			c.compileLowerCamelIdentifier(v.Name),
-			v.Offset,
-			fmt.Sprintf("const $fidl.MemberType<%s>(%s, %s)", t.Decl, typeStr, offsetStr),
+			Type:     t,
+			Name:     name,
+			Offset:   v.Offset,
+			Convert:  convert,
+			typeExpr: fmt.Sprintf("const $fidl.MemberType<%s>(%s, %s)", t.Decl, typeStr, offsetStr),
 		}
 		r = append(r, p)
 	}
@@ -571,6 +611,25 @@
 		name := c.compileLowerCamelIdentifier(v.Name)
 		request := c.compileParameterArray(v.Request)
 		response := c.compileParameterArray(v.Response)
+		asyncResponseClass := ""
+		if len(response) > 1 {
+			asyncResponseClass = fmt.Sprintf("_%s$%s$Response", r.Name, v.Name)
+		}
+		asyncResponseType := ""
+		if v.HasResponse {
+			if len(response) == 0 {
+				asyncResponseType = "Null"
+			} else if len(response) == 1 {
+				responseType := response[0].Type
+				if responseType.SyncDecl != "" {
+					asyncResponseType = responseType.SyncDecl
+				} else {
+					asyncResponseType = responseType.Decl
+				}
+			} else {
+				asyncResponseType = asyncResponseClass
+			}
+		}
 		m := Method{
 			v.Ordinal,
 			fmt.Sprintf("_k%s_%s_Ordinal", r.Name, v.Name),
@@ -581,6 +640,8 @@
 			v.HasResponse,
 			response,
 			v.ResponseSize,
+			asyncResponseClass,
+			asyncResponseType,
 			fmt.Sprintf("%s%sCallback", r.Name, v.Name),
 			fmt.Sprintf("_k%s_%s_Type", r.Name, v.Name),
 			typeExprForMethod(request, response),
@@ -702,8 +763,9 @@
 		}
 		library := types.ParseLibraryName(l.Name)
 		root.Imports = append(root.Imports, Import{
-			fmt.Sprintf("package:fidl_%s/fidl.dart", formatLibraryName(library)),
-			libraryPrefix(library),
+			Url:       fmt.Sprintf("package:fidl_%s/fidl.dart", formatLibraryName(library)),
+			LocalName: libraryPrefix(library),
+			AsyncUrl:  fmt.Sprintf("package:fidl_%s/fidl_async.dart", formatLibraryName(library)),
 		})
 	}
 
diff --git a/go/src/fidl/compiler/backend/dart/templates/interface.tmpl.go b/go/src/fidl/compiler/backend/dart/templates/interface.tmpl.go
index 1193acc..abf7b4b 100644
--- a/go/src/fidl/compiler/backend/dart/templates/interface.tmpl.go
+++ b/go/src/fidl/compiler/backend/dart/templates/interface.tmpl.go
@@ -252,4 +252,294 @@
 }
 
 {{ end }}
+
+{{- define "AsyncReturn" -}}
+{{- if .HasResponse -}}
+Future<{{ .AsyncResponseType }}>
+{{- else -}}
+Future<Null>
+{{- end -}}
+{{- end -}}
+
+{{- define "ForwardParams" -}}
+{{ range $index, $param := . }}{{ if $index }}, {{ end }}{{ $param.Name }}{{ end }}
+{{- end -}}
+
+{{- define "ForwardParamsConvert" -}}
+  {{- range $index, $param := . -}}
+    {{- if $index }}, {{ end -}}
+    {{- if $param.Convert -}}
+      {{- $param.Convert -}}({{- $param.Name -}})
+    {{- else -}}
+      {{- $param.Name -}}
+    {{- end -}}
+  {{- end }}
+{{- end -}}
+
+{{- define "ForwardResponseParams" -}}
+  {{- if .AsyncResponseClass -}}
+    {{- range $index, $param := .Response }}{{ if $index }}, {{ end }}_response.{{ $param.Name }}{{ end -}}
+  {{- else -}}
+    {{- if .AsyncResponseType -}}
+      _response
+    {{- end -}}
+  {{- end -}}
+{{- end -}}
+
+{{- define "ForwardResponseParamsConvert" -}}
+  {{- if .AsyncResponseClass -}}
+    {{- range $index, $param := .Response -}}
+      {{- if $index }}, {{ end -}}
+      {{- if $param.Convert -}}
+        {{- $param.Convert }}(_response.{{ $param.Name -}})
+      {{- else -}}
+        _response.{{ $param.Name -}}
+      {{- end -}}
+    {{- end -}}
+  {{- else -}}
+    {{- if .AsyncResponseType -}}
+      {{- with $param := index .Response 0 -}}
+        {{- if $param.Convert -}}
+          {{- $param.Convert }}(_response)
+        {{- else -}}
+          _response
+        {{- end -}}
+      {{- end -}}
+    {{- end -}}
+  {{- end -}}
+{{- end -}}
+
+{{- define "FuturizeParams" -}}
+  {{- range $index, $param := . -}}
+    {{- if $index }}, {{ end -}}
+    {{- if $param.Type.SyncDecl -}}
+      {{- $param.Type.SyncDecl -}}
+    {{- else -}}
+      {{- $param.Type.Decl -}}
+    {{- end }} {{ $param.Name }}
+  {{- end -}}
+{{ end }}
+
+{{- define "FuturizeRequestMethodSignature" -}}
+  {{- if .HasResponse -}}
+{{ .Name }}({{ template "FuturizeParams" .Request }}{{ if .Request }}, {{ end }}void callback({{ template "FuturizeParams" .Response }}))
+  {{- else -}}
+{{ .Name }}({{ template "FuturizeParams" .Request }})
+  {{- end -}}
+{{ end -}}
+
+{{- define "InterfaceAsyncDeclaration" -}}
+{{- range .Methods }}
+  {{- if .AsyncResponseClass }}
+class {{ .AsyncResponseClass }} {
+    {{- range .Response }}
+  final {{ .Type.Decl }} {{ .Name }};
+    {{- end }}
+  {{ .AsyncResponseClass }}(
+    {{- range .Response }}
+      this.{{ .Name }},
+    {{- end -}}
+    );
+}
+  {{- end }}
+{{- end }}
+
+abstract class {{ .Name }} {
+  static const String $serviceName = {{ .ServiceName }};
+
+{{- range .Methods }}
+  {{- if .HasRequest }}
+  {{ template "AsyncReturn" . }} {{ .Name }}({{ template "Params" .Request }});
+  {{- else }}
+  Stream<{{ .AsyncResponseType}}> get {{ .Name }};
+  {{- end }}
+{{- end }}
+}
+
+class {{ .Name }}Proxy implements {{ .Name }} {
+  final $sync.{{ .Name }}Proxy _syncProxy;
+  $fidl.ProxyControllerWrapper<{{ .Name }}, $sync.{{ .Name }}> _ctrl;
+  final _completers = new Set<Completer<dynamic>>();
+  {{ .Name }}Proxy() : _syncProxy = new $sync.{{ .Name }}Proxy()
+  {
+    _ctrl = new $fidl.ProxyControllerWrapper<{{ .Name }}, $sync.{{ .Name }}>(_syncProxy.ctrl);
+    {{- range .Methods }}
+      {{- if not .HasRequest }}
+        _syncProxy.{{ .Name }} = ({{ template "Params" .Response }}) =>
+          _{{ .Name }}EventStreamController.add(
+            {{- if .AsyncResponseClass -}}
+              new {{ .AsyncResponseClass }}({{ template "ForwardParams" .Response }})
+            {{- else -}}
+              {{- if .Response -}}
+                {{- template "ForwardParams" .Response -}}
+              {{- else -}}
+                null
+              {{- end -}}
+            {{- end -}});
+      {{- end }}
+    {{- end }}
+    _syncProxy.ctrl.error.then(_errorOccurred);
+  }
+
+  $fidl.ProxyControllerWrapper<{{ .Name }}, $sync.{{ .Name }}> get ctrl => _ctrl;
+
+  void _errorOccurred($fidl.ProxyError err) {
+    // Make a copy of the set of completers and then clear it.
+    final errorCompleters = new List<Completer<dynamic>>.from(_completers);
+    _completers.clear();
+    // Dispatch the error to all of the completers.
+    for (var c in errorCompleters) {
+      c.completeError(err);
+    }
+    // Ask for the next error.
+    _syncProxy.ctrl.error.then(_errorOccurred);
+  }
+
+{{- range .Methods }}
+  {{- if .HasRequest }}
+  @override
+  {{ template "AsyncReturn" . }} {{ .Name }}({{ template "Params" .Request }}) {
+    {{- if .HasResponse }}
+    final _completer = new Completer<{{ .AsyncResponseType }}>();
+    _completers.add(_completer);
+    void _call() {
+        _syncProxy.{{ .Name }}({{ template "ForwardParamsConvert" .Request -}}
+        {{- if .Request }}, {{ end -}}
+        ({{ template "FuturizeParams" .Response }}) {
+          _completers.remove(_completer);
+          _completer.complete(
+        {{- if .AsyncResponseClass -}}
+          new {{ .AsyncResponseClass }}({{ template "ForwardParamsConvert" .Response }})
+        {{- else -}}
+          {{- template "ForwardParamsConvert" .Response -}}
+        {{- end -}}
+        );
+      });
+    }
+    try {
+      if (_syncProxy.ctrl.isBound) {
+        _call();
+      } else {
+        _syncProxy.ctrl.bound.then((_) =>_call());
+      }
+    } catch(err) {
+      _completers.remove(_completer);
+      _completer.completeError(err);
+    }
+    return _completer.future;
+    {{- else }}
+    final _completer = new Completer<Null>();
+    _completers.add(_completer);
+    if (_syncProxy.ctrl.isBound) {
+      _syncProxy.{{ .Name }}({{ template "ForwardParamsConvert" .Request}});
+      _completers.remove(_completer);
+      _completer.complete();
+    } else {
+      _syncProxy.ctrl.bound.then((_) {
+        _syncProxy.{{ .Name }}({{ template "ForwardParamsConvert" .Request}});
+        _completers.remove(_completer);
+        _completer.complete();
+      }, onError: (dynamic error, StackTrace stackTrace) {
+        _completers.remove(_completer);
+        _completer.completeError(error, stackTrace);
+      });
+    }
+    return _completer.future;
+    {{- end }}
+  }
+  {{ else }}
+  final _{{ .Name }}EventStreamController = new StreamController<{{ .AsyncResponseType }}>.broadcast();
+  @override
+  Stream<{{ .AsyncResponseType}}> get {{ .Name }} => _{{ .Name }}EventStreamController.stream;
+  {{ end }}
+{{- end }}
+}
+
+class _{{ .Name }}Futurize implements $sync.{{ .Name }} {
+  final {{ .Name }} _inner;
+  _{{ .Name }}Futurize(this._inner);
+
+{{- range .Methods }}
+  {{- if .HasRequest }}
+  @override
+  void {{ template "FuturizeRequestMethodSignature" . }} =>
+    {{- if .HasResponse }}
+    _inner.{{ .Name }}({{ template "ForwardParamsConvert" .Request }}).then(
+  ({{ if .AsyncResponseType }}{{ .AsyncResponseType }} _response{{ end }}) =>
+  callback(
+      {{- if .Response -}}
+        {{- template "ForwardResponseParamsConvert" . -}}
+      {{- end -}}));
+    {{- else }}
+    _inner.{{ .Name }}({{ template "ForwardParamsConvert" .Request}});
+    {{- end }}
+  {{- else }}
+  {{- end }}
+{{- end }}
+}
+
+class {{ .Name }}Binding {
+  final $sync.{{ .Name }}Binding _syncBinding;
+  {{ .Name }}Binding() : _syncBinding = new $sync.{{ .Name }}Binding();
+
+  _VoidCallback get onBind => _syncBinding.onBind;
+  set onBind(_VoidCallback f) => _syncBinding.onBind = f;
+  _VoidCallback get onUnbind => _syncBinding.onUnbind;
+  set onUnbind(_VoidCallback f) => _syncBinding.onUnbind = f;
+  _VoidCallback get onClose => _syncBinding.onClose;
+  set onClose(_VoidCallback f) => _syncBinding.onClose = f;
+  _VoidCallback get onConnectionError => _syncBinding.onConnectionError;
+  set onConnectionError(_VoidCallback f) => _syncBinding.onConnectionError = f;
+
+  $fidl.InterfaceHandle<{{ .Name }}> wrap({{ .Name }} impl) {
+    final handle = new $fidl.InterfaceHandle<{{ .Name }}>(_syncBinding.wrap(new _{{ .Name }}Futurize(impl)).passChannel());
+    _bind(impl);
+    return handle;
+  }
+
+  void bind({{ .Name }} impl, $fidl.InterfaceRequest<{{ .Name }}> interfaceRequest) {
+    _syncBinding.bind(new _{{ .Name }}Futurize(impl), new $fidl.InterfaceRequest<$sync.{{ .Name }}>(interfaceRequest.passChannel()));
+    _bind(impl);
+   }
+
+  $fidl.InterfaceRequest<{{ .Name }}> unbind() {
+    final req = new $fidl.InterfaceRequest<{{ .Name }}>(_syncBinding.unbind().passChannel());
+    _unbind();
+    return req;
+  }
+
+  bool get isBound => _syncBinding.isBound;
+
+  {{- range .Methods }}
+  {{- if not .HasRequest }}
+  StreamSubscription<{{ .AsyncResponseType }}> _{{ .Name }}_subscription;
+  {{- end }}
+  {{- end }}
+
+  void _bind({{ .Name }} impl) {
+    {{- range .Methods }}
+    {{- if not .HasRequest }}
+    _{{ .Name }}_subscription = impl.{{ .Name }}.listen(
+  ({{ if .AsyncResponseType }}{{ .AsyncResponseType }} _response{{ end }}) =>
+  _syncBinding.events.{{ .Name }}({{ if .Response }}{{ template "ForwardResponseParams" . }}{{ end }}));
+    {{- end }}
+    {{- end }}
+  }
+
+  void _unbind() {
+    {{- range .Methods }}
+    {{- if not .HasRequest }}
+    _{{ .Name }}_subscription.cancel();
+    _{{ .Name }}_subscription = null;
+    {{- end }}
+    {{- end }}
+  }
+
+  void close() {
+    _unbind();
+    _syncBinding.close();
+  }
+}
+
+{{ end }}
 `
diff --git a/go/src/fidl/compiler/backend/dart/templates/library.tmpl.go b/go/src/fidl/compiler/backend/dart/templates/library.tmpl.go
index 729ec90..8e10789 100644
--- a/go/src/fidl/compiler/backend/dart/templates/library.tmpl.go
+++ b/go/src/fidl/compiler/backend/dart/templates/library.tmpl.go
@@ -61,4 +61,85 @@
 {{ template "InterfaceDeclaration" $interface }}
 {{ end -}}
 {{- end -}}
+
+{{- define "ExportNames" -}}
+{{ if . }}
+import 'fidl.dart' show {{ range $index, $item := . }}
+{{- if $index }}, {{ end -}}
+{{ .Name -}}
+{{ end -}};
+export 'fidl.dart' show {{ range $index, $item := . }}
+{{- if $index }}, {{ end -}}
+{{ .Name -}}
+{{ end -}};
+{{ end -}}
+{{- end -}}
+
+{{- define "GenerateAsyncFile" -}}
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WARNING: This file is machine generated by fidlgen.
+
+library {{ .LibraryName }}$async;
+
+import 'dart:async';
+import 'dart:typed_data';
+
+import 'package:fidl/fidl.dart' as $fidl;
+import 'package:meta/meta.dart';
+import 'package:zircon/zircon.dart';
+
+{{ range .Imports -}}
+import '{{ .Url }}' as sync${{ .LocalName }};
+import '{{ .AsyncUrl }}' as {{ .LocalName }};
+{{ end -}}
+
+import 'fidl.dart' as $sync;
+
+// ignore_for_file: always_specify_types
+// ignore_for_file: avoid_positional_boolean_parameters
+// ignore_for_file: avoid_returning_null
+// ignore_for_file: cascade_invocations
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: one_member_abstracts
+// ignore_for_file: prefer_constructors_over_static_methods
+// ignore_for_file: prefer_single_quotes
+// ignore_for_file: public_member_api_docs
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: library_prefixes
+// ignore_for_file: prefer_typing_uninitialized_variables
+// ignore_for_file: avoid_js_rounded_ints
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: prefer_generic_function_type_aliases
+// ignore_for_file: prefer_equal_for_default_values
+// ignore_for_file: avoid_catches_without_on_clauses
+// ignore_for_file: unused_shown_name
+// ignore_for_file: directives_ordering
+// ignore_for_file: unnecessary_lambdas
+
+{{ template "ExportNames" .Consts -}}
+{{ template "ExportNames" .Enums -}}
+{{ template "ExportNames" .Unions -}}
+{{ template "ExportNames" .Structs -}}
+
+// ignore: unused_element, avoid_private_typedef_functions
+typedef _VoidCallback = void Function();
+
+// Converters between interface handle / request types.
+// ignore: unused_element
+$fidl.InterfaceHandle<NEW> _convertInterfaceHandle<OLD, NEW>($fidl.InterfaceHandle<OLD> old) => new $fidl.InterfaceHandle<NEW>(old.passChannel());
+// ignore: unused_element
+$fidl.InterfaceRequest<NEW> _convertInterfaceRequest<OLD, NEW>($fidl.InterfaceRequest<OLD> old) => new $fidl.InterfaceRequest<NEW>(old.passChannel());
+
+{{ range $interface := .Interfaces -}}
+{{ template "InterfaceAsyncDeclaration" $interface }}
+{{ end -}}
+
+{{- end -}}
+
 `
diff --git a/go/src/fidl/compiler/backend/golang/ir/ir.go b/go/src/fidl/compiler/backend/golang/ir/ir.go
index f108178..1f3b836 100644
--- a/go/src/fidl/compiler/backend/golang/ir/ir.go
+++ b/go/src/fidl/compiler/backend/golang/ir/ir.go
@@ -361,7 +361,7 @@
 
 var primitiveTypes = map[types.PrimitiveSubtype]string{
 	types.Bool:    "bool",
-	types.Status:  "int32",
+	types.Status:  "_zx.Status",
 	types.Int8:    "int8",
 	types.Int16:   "int16",
 	types.Int32:   "int32",
@@ -469,7 +469,11 @@
 	}
 }
 
-func (_ *compiler) compilePrimitiveSubtype(val types.PrimitiveSubtype) Type {
+func (c *compiler) compilePrimitiveSubtype(val types.PrimitiveSubtype) Type {
+	if val == types.Status {
+		// The Status type is defined in syscall/zx.
+		c.usedLibraryDeps[SyscallZxPackage] = SyscallZxAlias
+	}
 	t, ok := primitiveTypes[val]
 	if !ok {
 		log.Fatal("Unknown primitive type: ", val)
diff --git a/go/src/fidl/compiler/backend/golang/templates/interface.tmpl.go b/go/src/fidl/compiler/backend/golang/templates/interface.tmpl.go
index 42d0b7a..d668f6d 100644
--- a/go/src/fidl/compiler/backend/golang/templates/interface.tmpl.go
+++ b/go/src/fidl/compiler/backend/golang/templates/interface.tmpl.go
@@ -93,8 +93,8 @@
 	)
 	{{- if .Response -}}
 	{{- if len .Response.Members }} (
-	{{- range .Response.Members }}{{ .PrivateName }} {{ .Type }}, {{ end -}}
-		err_ error)
+	{{- range .Response.Members }}{{ .Type }}, {{ end -}}
+		error)
 	{{- else }} error{{ end -}}
 	{{- else }} error{{ end }}
 	{{- end }}
diff --git a/go/src/fidl/compiler/backend/rust/templates/interface.tmpl.go b/go/src/fidl/compiler/backend/rust/templates/interface.tmpl.go
index 553e415..ccf5a40 100644
--- a/go/src/fidl/compiler/backend/rust/templates/interface.tmpl.go
+++ b/go/src/fidl/compiler/backend/rust/templates/interface.tmpl.go
@@ -32,6 +32,7 @@
 
 impl fidl::endpoints2::ServiceMarker for {{ $interface.Name }}Marker {
 	type Proxy = {{ $interface.Name }}Proxy;
+	type RequestStream = {{ $interface.Name }}RequestStream;
 	const NAME: &'static str = "{{ $interface.ServiceName }}";
 }
 
@@ -186,7 +187,7 @@
 				)))
 			}
 			{{- end -}}
-			{{- end -}}
+			{{- end }}
 			_ => Err(fidl::Error::UnknownOrdinal {
 				ordinal: tx_header.ordinal,
 				service_name: <{{ $interface.Name }}Marker as fidl::endpoints2::ServiceMarker>::NAME,
@@ -197,12 +198,12 @@
 
 #[derive(Debug)]
 pub enum {{ $interface.Name }}Event {
-	{{- range $method := $interface.Methods }}
-	{{- if not $method.HasRequest }}
+	{{ range $method := $interface.Methods }}
+	{{ if not $method.HasRequest }}
 	{{ $method.CamelName }} {
-		{{- range $param := $method.Response -}}
-		{{- $param.Name -}}: {{ $param.Type -}},
-		{{- end -}}
+		{{ range $param := $method.Response }}
+		{{ $param.Name }}: {{ $param.Type }},
+		{{ end }}
 	},
 	{{- end -}}
 	{{- end -}}
@@ -329,40 +330,40 @@
 
 			match header.ordinal {
 				{{- range $method := $interface.Methods }}
-				{{- if $method.HasRequest }}
-				{{ $method.Ordinal }} => {
-					let mut req: (
-						{{- range $index, $param := $method.Request -}}
-						{{- if ne 0 $index -}}, {{- $param.Type -}}
-						{{- else -}} {{- $param.Type -}}
-						{{- end -}}
-						{{- end -}}
-					) = fidl::encoding2::Decodable::new_empty();
-					fidl::encoding2::Decoder::decode_into(body_bytes, handles, &mut req)?;
-					let control_handle = {{ $interface.Name }}ControlHandle {
-						inner: self.inner.clone(),
-					};
-					self.{{ $method.Name }}_futures.push(
-						self.server.{{ $method.Name }}(
+					{{- if $method.HasRequest }}
+					{{ $method.Ordinal }} => {
+						let mut req: (
 							{{- range $index, $param := $method.Request -}}
-							{{- if ne 1 (len $method.Request) -}}
-							req.{{ $index }},
-							{{- else -}}
-							req,
+								{{- if ne 0 $index -}}, {{- $param.Type -}}
+								{{- else -}} {{- $param.Type -}}
+								{{- end -}}
 							{{- end -}}
-							{{- end -}}
-							{{- if $method.HasResponse -}}
-							{{- $interface.Name -}}{{- $method.CamelName -}}Responder {
-								control_handle,
-								tx_id: header.tx_id,
-							}
-							{{- else -}}
-							control_handle
-							{{- end -}}
-						)
-					);
-				}
-				{{- end }}
+						) = fidl::encoding2::Decodable::new_empty();
+						fidl::encoding2::Decoder::decode_into(body_bytes, handles, &mut req)?;
+						let control_handle = {{ $interface.Name }}ControlHandle {
+							inner: self.inner.clone(),
+						};
+						self.{{ $method.Name }}_futures.push(
+							self.server.{{ $method.Name }}(
+								{{- range $index, $param := $method.Request -}}
+									{{- if ne 1 (len $method.Request) -}}
+									req.{{ $index }},
+									{{- else -}}
+									req,
+									{{- end -}}
+								{{- end -}}
+								{{- if $method.HasResponse -}}
+									{{- $interface.Name -}}{{- $method.CamelName -}}Responder {
+										control_handle,
+										tx_id: header.tx_id,
+									}
+									{{- else -}}
+									control_handle
+								{{- end -}}
+							)
+						);
+					}
+					{{- end }}
 				{{- end }}
 				// TODO(cramertj) handle control/fileio messages
 				_ => return Err(fidl::Error::UnknownOrdinal {
@@ -375,6 +376,113 @@
 	}}
 }
 
+pub struct {{ $interface.Name }}RequestStream {
+	inner: ::std::sync::Arc<fidl::ServeInner>,
+	msg_buf: zx::MessageBuf,
+}
+
+impl fidl::endpoints2::RequestStream for {{ $interface.Name }}RequestStream {
+	fn from_channel(channel: async::Channel) -> Self {
+		Self {
+			inner: ::std::sync::Arc::new(fidl::ServeInner::new(channel)),
+			msg_buf: zx::MessageBuf::new(),
+		}
+	}
+
+	type ControlHandle = {{ $interface.Name }}ControlHandle;
+	fn control_handle(&self) -> Self::ControlHandle {
+		{{ $interface.Name }}ControlHandle { inner: self.inner.clone() }
+	}
+}
+
+impl Stream for {{ $interface.Name }}RequestStream {
+	type Item = {{ $interface.Name }}Request;
+	type Error = fidl::Error;
+	fn poll_next(&mut self, cx: &mut futures::task::Context)
+		-> futures::Poll<Option<Self::Item>, Self::Error>
+	{
+		if self.inner.poll_shutdown(cx) {
+			return Ok(futures::Async::Ready(None));
+		}
+		match self.inner.channel().recv_from(&mut self.msg_buf, cx) {
+			Ok(futures::Async::Ready(())) => {},
+			Ok(futures::Async::Pending) => return Ok(futures::Async::Pending),
+			Err(zx::Status::PEER_CLOSED) => {
+				return Ok(futures::Async::Ready(None));
+			}
+			Err(e) => return Err(fidl::Error::ServerRequestRead(e)),
+		}
+
+		let res = {
+			// A message has been received from the channel
+			let (bytes, handles) = self.msg_buf.split_mut();
+			let (header, body_bytes) = fidl::encoding2::decode_transaction_header(bytes)?;
+
+			Ok(futures::Async::Ready(Some(match header.ordinal {
+				{{- range $method := $interface.Methods }}
+				{{- if $method.HasRequest }}
+				{{ $method.Ordinal }} => {
+					let mut req: (
+						{{- range $index, $param := $method.Request -}}
+							{{- if ne 0 $index -}}, {{- $param.Type -}}
+							{{- else -}} {{- $param.Type -}}
+							{{- end -}}
+						{{- end -}}
+					) = fidl::encoding2::Decodable::new_empty();
+					fidl::encoding2::Decoder::decode_into(body_bytes, handles, &mut req)?;
+					let control_handle = {{ $interface.Name }}ControlHandle {
+						inner: self.inner.clone(),
+					};
+
+					{{ $interface.Name }}Request::{{ $method.CamelName }} {
+						{{- range $index, $param := $method.Request -}}
+							{{- if ne 1 (len $method.Request) -}}
+							{{ $param.Name }}: req.{{ $index }},
+							{{- else -}}
+							{{ $param.Name }}: req,
+							{{- end -}}
+						{{- end -}}
+						{{- if $method.HasResponse -}}
+							responder: {{- $interface.Name -}}{{- $method.CamelName -}}Responder {
+								control_handle,
+								tx_id: header.tx_id,
+							},
+							{{- else -}}
+							control_handle,
+						{{- end -}}
+					}
+				}
+				{{- end }}
+				{{- end }}
+				_ => return Err(fidl::Error::UnknownOrdinal {
+					ordinal: header.ordinal,
+					service_name: <{{ $interface.Name }}Marker as fidl::endpoints2::ServiceMarker>::NAME,
+				}),
+			})))
+		};
+
+		self.msg_buf.clear();
+		res
+	}
+}
+
+pub enum {{ $interface.Name }}Request {
+	{{- range $method := $interface.Methods }}
+	{{- if $method.HasRequest }}
+	{{ $method.CamelName }} {
+		{{ range $index, $param := $method.Request }}
+		{{ $param.Name }}: {{ $param.Type }},
+		{{ end -}}
+		{{- if $method.HasResponse -}}
+		responder: {{ $interface.Name }}{{ $method.CamelName }}Responder,
+		{{- else -}}
+		control_handle: {{ $interface.Name }}ControlHandle,
+		{{- end -}}
+	},
+	{{- end }}
+	{{- end }}
+}
+
 pub struct {{ $interface.Name }}Impl<
 	{{ template "GenerateImplGenerics" $interface }}
 > {
diff --git a/go/src/fidl/examples/BUILD.gn b/go/src/fidl/examples/BUILD.gn
index 349461e..421fc12 100644
--- a/go/src/fidl/examples/BUILD.gn
+++ b/go/src/fidl/examples/BUILD.gn
@@ -12,6 +12,7 @@
       nick = invoker.nick
     }
     name = "fidl.examples.$nick"
+    cpp_legacy_callbacks = true
 
     sources = [
       "//zircon/system/host/fidl/examples/${target_name}.fidl"
@@ -39,6 +40,7 @@
 
 fidl("point") {
   name = "fidl.examples.libraryA"
+  cpp_legacy_callbacks = true
 
   sources = [
     "//zircon/system/host/fidl/examples/library-a/point.fidl"
@@ -47,6 +49,7 @@
 
 fidl("view") {
   name = "fidl.examples.libraryB"
+  cpp_legacy_callbacks = true
 
   sources = [
     "//zircon/system/host/fidl/examples/library-b/view.fidl"
diff --git a/go/src/netstack/fdio.go b/go/src/netstack/fdio.go
index 05c7993..3ee1f56 100644
--- a/go/src/netstack/fdio.go
+++ b/go/src/netstack/fdio.go
@@ -18,7 +18,7 @@
 	"time"
 
 	"app/context"
-	"fidl/device_settings"
+	"fidl/fuchsia/devicesettings"
 
 	"github.com/google/netstack/dns"
 	"github.com/google/netstack/tcpip"
@@ -959,18 +959,18 @@
 			log.Printf("ioctlNetcGetNodename: error accessing device settings: %s\n", err)
 			nodename = defaultNodename // defined in netstack.go
 		}
-		if status != device_settings.StatusOk {
+		if status != devicesettings.StatusOk {
 			var reportStatus string
 			switch status {
-			case device_settings.StatusErrNotSet:
+			case devicesettings.StatusErrNotSet:
 				reportStatus = "key not set"
-			case device_settings.StatusErrInvalidSetting:
+			case devicesettings.StatusErrInvalidSetting:
 				reportStatus = "invalid setting"
-			case device_settings.StatusErrRead:
+			case devicesettings.StatusErrRead:
 				reportStatus = "error reading key"
-			case device_settings.StatusErrIncorrectType:
+			case devicesettings.StatusErrIncorrectType:
 				reportStatus = "value type was incorrect"
-			case device_settings.StatusErrUnknown:
+			case devicesettings.StatusErrUnknown:
 				reportStatus = "unknown"
 			}
 			log.Println("ioctlNetcGetNodename: falling back to default nodename.")
diff --git a/go/src/netstack/ifconfig/ifconfig.go b/go/src/netstack/ifconfig/ifconfig.go
index 0095680..b0e4227 100644
--- a/go/src/netstack/ifconfig/ifconfig.go
+++ b/go/src/netstack/ifconfig/ifconfig.go
@@ -13,8 +13,8 @@
 
 	"app/context"
 
-	"fidl/netstack"
-	"fidl/wlan_service"
+	"fidl/fuchsia/netstack"
+	wlan_service "fidl/fuchsia/wlan/service"
 )
 
 type netstackClientApp struct {
diff --git a/go/src/netstack/ifinfo/ifinfo.go b/go/src/netstack/ifinfo/ifinfo.go
index 0171e41..1195215 100644
--- a/go/src/netstack/ifinfo/ifinfo.go
+++ b/go/src/netstack/ifinfo/ifinfo.go
@@ -13,7 +13,7 @@
 
 	"app/context"
 
-	"fidl/netstack"
+	"fidl/fuchsia/netstack"
 
 	"github.com/google/netstack/tcpip"
 )
diff --git a/go/src/netstack/link/eth/arena.go b/go/src/netstack/link/eth/arena.go
index eb3c7c4..532b428 100644
--- a/go/src/netstack/link/eth/arena.go
+++ b/go/src/netstack/link/eth/arena.go
@@ -42,6 +42,7 @@
 	if err != nil {
 		return nil, fmt.Errorf("eth: cannot allocate I/O VMO: %v", err)
 	}
+	iovmo.Handle().SetProperty(zx.PropName, []byte("eth-arena"))
 
 	iobuf, err := zx.VMARRoot.Map(0, iovmo, 0, iosize, zx.VMFlagPermRead|zx.VMFlagPermWrite)
 	if err != nil {
diff --git a/go/src/netstack/link/stats/stats.go b/go/src/netstack/link/stats/stats.go
index eaba49f..d984b16 100644
--- a/go/src/netstack/link/stats/stats.go
+++ b/go/src/netstack/link/stats/stats.go
@@ -14,7 +14,7 @@
 	"log"
 	"time"
 
-	nsfidl "fidl/netstack"
+	nsfidl "fidl/fuchsia/netstack"
 	"netstack/netiface"
 
 	"github.com/google/netstack/tcpip"
diff --git a/go/src/netstack/main.go b/go/src/netstack/main.go
index 1dbbe6a..ed68deb 100644
--- a/go/src/netstack/main.go
+++ b/go/src/netstack/main.go
@@ -13,7 +13,7 @@
 	"netstack/watcher"
 
 	"fidl/bindings"
-	"fidl/device_settings"
+	"fidl/fuchsia/devicesettings"
 
 	"github.com/google/netstack/tcpip"
 	"github.com/google/netstack/tcpip/network/arp"
@@ -59,7 +59,7 @@
 		log.Fatalf("ethernet: %v", err)
 	}
 
-	req, ds, err := device_settings.NewDeviceSettingsManagerInterfaceRequest()
+	req, ds, err := devicesettings.NewDeviceSettingsManagerInterfaceRequest()
 	if err != nil {
 		log.Printf("could not connect to device settings service: %s", err)
 	}
diff --git a/go/src/netstack/netstack.go b/go/src/netstack/netstack.go
index e53a3a1..2e54efb 100644
--- a/go/src/netstack/netstack.go
+++ b/go/src/netstack/netstack.go
@@ -13,7 +13,7 @@
 	"strings"
 	"sync"
 
-	"fidl/device_settings"
+	"fidl/fuchsia/devicesettings"
 	"netstack/filter"
 	"netstack/link/eth"
 	"netstack/link/stats"
@@ -41,7 +41,7 @@
 	stack      *stack.Stack
 	dispatcher *socketServer
 
-	deviceSettings *device_settings.DeviceSettingsManagerInterface
+	deviceSettings *devicesettings.DeviceSettingsManagerInterface
 
 	mu       sync.Mutex
 	nodename string
diff --git a/go/src/netstack/netstack_service.go b/go/src/netstack/netstack_service.go
index 0adf430..0fe5981 100644
--- a/go/src/netstack/netstack_service.go
+++ b/go/src/netstack/netstack_service.go
@@ -15,7 +15,7 @@
 	"netstack/link/eth"
 	"syscall/zx"
 
-	nsfidl "fidl/netstack"
+	nsfidl "fidl/fuchsia/netstack"
 
 	"github.com/google/netstack/tcpip"
 	"github.com/google/netstack/tcpip/network/ipv4"
diff --git a/go/src/netstack/netstack_service_test/main.go b/go/src/netstack/netstack_service_test/main.go
index e635a99..29412d2 100644
--- a/go/src/netstack/netstack_service_test/main.go
+++ b/go/src/netstack/netstack_service_test/main.go
@@ -16,7 +16,7 @@
 	"app/context"
 	"fidl/bindings"
 
-	"fidl/netstack"
+	"fidl/fuchsia/netstack"
 )
 
 type testApp struct {
diff --git a/go/src/netstack/netstat/netstat.go b/go/src/netstack/netstat/netstat.go
index 2dc8224..6c0f1d8 100644
--- a/go/src/netstack/netstat/netstat.go
+++ b/go/src/netstack/netstat/netstat.go
@@ -13,7 +13,7 @@
 
 	"app/context"
 
-	"fidl/netstack"
+	"fidl/fuchsia/netstack"
 )
 
 type netstatApp struct {
diff --git a/go/src/netstack/tests/automated/netstack_loopback_test/loopbacktest.cc b/go/src/netstack/tests/automated/netstack_loopback_test/loopbacktest.cc
index 0188468..3376bf5 100644
--- a/go/src/netstack/tests/automated/netstack_loopback_test/loopbacktest.cc
+++ b/go/src/netstack/tests/automated/netstack_loopback_test/loopbacktest.cc
@@ -15,9 +15,9 @@
 #include <string>
 #include <thread>
 
-#include <fdio/io.h>
-#include <fdio/private.h>
-#include <fdio/util.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/private.h>
+#include <lib/fdio/util.h>
 
 #include <zircon/syscalls.h>
 
diff --git a/go/src/netstack/tests/manual/closetest.c b/go/src/netstack/tests/manual/closetest.c
index 1c3920c..5e1f368 100644
--- a/go/src/netstack/tests/manual/closetest.c
+++ b/go/src/netstack/tests/manual/closetest.c
@@ -4,7 +4,7 @@
 
 #include <arpa/inet.h>
 #include <errno.h>
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <stdio.h>
diff --git a/go/src/netstack/tests/manual/passfdtest.c b/go/src/netstack/tests/manual/passfdtest.c
index d11b566..0a523a9 100644
--- a/go/src/netstack/tests/manual/passfdtest.c
+++ b/go/src/netstack/tests/manual/passfdtest.c
@@ -5,7 +5,7 @@
 #include <arpa/inet.h>
 #include <ctype.h>
 #include <errno.h>
-#include <fdio/spawn.h>
+#include <lib/fdio/spawn.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <stdio.h>
diff --git a/go/src/power_manager/power_manager_test.go b/go/src/power_manager/power_manager_test.go
index 10d85b5..9f61b5e 100644
--- a/go/src/power_manager/power_manager_test.go
+++ b/go/src/power_manager/power_manager_test.go
@@ -12,25 +12,25 @@
 	"app/context"
 	"fidl/bindings"
 
-	"fidl/power_manager"
+	"fidl/fuchsia/power"
 )
 
 type ClientMock struct {
-	pm *power_manager.PowerManagerInterface
+	pm *power.PowerManagerInterface
 }
 
 type WatcherMock struct {
 	called uint32
 }
 
-func (pmw *WatcherMock) OnChangeBatteryStatus(bs power_manager.BatteryStatus) error {
+func (pmw *WatcherMock) OnChangeBatteryStatus(bs power.BatteryStatus) error {
 	atomic.AddUint32(&pmw.called, 1)
 	return nil
 }
 
 func TestPowerManager(t *testing.T) {
 	ctx := context.CreateFromStartupInfo()
-	req, iface, err := power_manager.NewPowerManagerInterfaceRequest()
+	req, iface, err := power.NewPowerManagerInterfaceRequest()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -46,7 +46,7 @@
 
 func TestPowerManagerWatcher(t *testing.T) {
 	ctx := context.CreateFromStartupInfo()
-	r, p, err := power_manager.NewPowerManagerInterfaceRequest()
+	r, p, err := power.NewPowerManagerInterfaceRequest()
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -54,13 +54,13 @@
 	pmClient.pm = p
 	ctx.ConnectToEnvService(r)
 
-	rw, pw, err := power_manager.NewPowerManagerWatcherInterfaceRequest()
+	rw, pw, err := power.NewPowerManagerWatcherInterfaceRequest()
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	pmWatcher := &WatcherMock{called: 0}
-	s := power_manager.PowerManagerWatcherStub{Impl: pmWatcher}
+	s := power.PowerManagerWatcherStub{Impl: pmWatcher}
 	bs := bindings.BindingSet{}
 	bs.Add(&s, rw.Channel, nil)
 	go bindings.Serve()
diff --git a/go/src/system_update_package/BUILD.gn b/go/src/system_update_package/BUILD.gn
index 9716e03..f7eb975 100644
--- a/go/src/system_update_package/BUILD.gn
+++ b/go/src/system_update_package/BUILD.gn
@@ -47,18 +47,6 @@
       path = rebase_path("images")
       dest = "images"
     },
-    {
-      path = rebase_path("packages")
-      dest = "packages"
-    },
-    {
-      path = rebase_path("efi")
-      dest = "efi"
-    },
-    {
-      path = rebase_path("kernc")
-      dest = "kernc"
-    }
   ]
   meta = [
     {
diff --git a/go/src/system_update_package/cmd/updater/meta/system_updater.cmx b/go/src/system_update_package/cmd/updater/meta/system_updater.cmx
index 2288b41..12e2424 100644
--- a/go/src/system_update_package/cmd/updater/meta/system_updater.cmx
+++ b/go/src/system_update_package/cmd/updater/meta/system_updater.cmx
@@ -3,6 +3,7 @@
         "binary": "bin/app"
     },
     "sandbox": {
-        "features": [ "shell" ]
+        "features": [ "shell" ],
+        "pkgfs": [ "packages" ]
     }
 }
diff --git a/go/src/system_update_package/cmd/updater/updater.go b/go/src/system_update_package/cmd/updater/updater.go
index 043e475..4203c8f 100644
--- a/go/src/system_update_package/cmd/updater/updater.go
+++ b/go/src/system_update_package/cmd/updater/updater.go
@@ -16,7 +16,9 @@
 	log.SetPrefix("system_updater: ")
 	log.SetFlags(log.Ltime)
 
-	pFile, err := os.Open(filepath.Join("/pkg", "data", "packages"))
+	dataPath := filepath.Join("/pkgfs", "packages", "update", "0")
+
+	pFile, err := os.Open(filepath.Join(dataPath, "packages"))
 	if err != nil {
 		log.Fatalf("error opening packages data file! %s", err)
 	}
@@ -43,7 +45,7 @@
 		log.Fatalf("failed getting packages: %s", err)
 	}
 
-	if err := system_update_package.WriteImgs(imgs); err != nil {
+	if err := system_update_package.WriteImgs(imgs, dataPath); err != nil {
 		log.Fatalf("error writing image file: %s", err)
 	}
 
diff --git a/go/src/system_update_package/processor.go b/go/src/system_update_package/processor.go
index 6b6af83..c97b39f 100644
--- a/go/src/system_update_package/processor.go
+++ b/go/src/system_update_package/processor.go
@@ -119,7 +119,7 @@
 	return nil
 }
 
-func WriteImgs(imgs []string) error {
+func WriteImgs(imgs []string, imgsPath string) error {
 	for _, img := range imgs {
 		var c *exec.Cmd
 		switch img {
@@ -131,7 +131,7 @@
 			return fmt.Errorf("unrecognized image %q", img)
 		}
 
-		err := writeImg(c, filepath.Join("/pkg", "data", img))
+		err := writeImg(c, filepath.Join(imgsPath, img))
 		if err != nil {
 			return err
 		}
diff --git a/go/src/thinfs/fs/msdosfs/fs.go b/go/src/thinfs/fs/msdosfs/fs.go
index 69343e1..da61f2f 100644
--- a/go/src/thinfs/fs/msdosfs/fs.go
+++ b/go/src/thinfs/fs/msdosfs/fs.go
@@ -17,7 +17,6 @@
 	"thinfs/fs/msdosfs/direntry"
 	"thinfs/fs/msdosfs/node"
 	"thinfs/thinio"
-	"github.com/golang/glog"
 )
 
 const (
@@ -41,7 +40,6 @@
 
 // New returns a new FAT filesystem.
 func New(path string, dev block.Device, opts fs.FileSystemOptions) (fs.FileSystem, error) {
-	glog.V(0).Infof("Creating a new FAT fs at %s\n", path)
 	f := fsFAT{
 		opts: opts,
 		info: &node.Metadata{
@@ -86,7 +84,6 @@
 
 // Close unmounts the FAT filesystem.
 func (f *fsFAT) Close() error {
-	glog.V(0).Info("Closing filesystem")
 	f.Lock()
 	defer f.Unlock()
 	if f.unmounted {
@@ -119,7 +116,6 @@
 
 // RootDirectory returns the root directory.
 func (f *fsFAT) RootDirectory() fs.Directory {
-	glog.V(0).Info("Getting root directory")
 	f.RLock()
 	defer f.RUnlock()
 	if f.unmounted {
diff --git a/go/src/thinfs/fs/msdosfs/ops.go b/go/src/thinfs/fs/msdosfs/ops.go
index c001cc4..57ef4a9 100644
--- a/go/src/thinfs/fs/msdosfs/ops.go
+++ b/go/src/thinfs/fs/msdosfs/ops.go
@@ -193,9 +193,9 @@
 	if dstName == "." || dstName == ".." {
 		return fs.ErrIsActive
 	}
-	// Verify that dst is not src (same directory, same name)
+	// If dst is src (same directory, same name), end early.
 	if srcParent.ID() == dstParent.ID() && srcName == dstName {
-		return fs.ErrIsActive
+		return nil
 	}
 
 	// If we are moving a directory to a new directory dst...
diff --git a/go/src/thinfs/zircon/rpc/rpc.go b/go/src/thinfs/zircon/rpc/rpc.go
index eccda58..f22118f 100644
--- a/go/src/thinfs/zircon/rpc/rpc.go
+++ b/go/src/thinfs/zircon/rpc/rpc.go
@@ -614,11 +614,19 @@
 	return zx.ErrNotSupported
 }
 
-func (vfs *ThinVFS) fdioServer(msg *fdio.Msg, rh zx.Handle, cookie int64) zx.Status {
+func (vfs *ThinVFS) fdioServer(msg *fdio.Msg, rh zx.Handle, cookie int64) (status zx.Status) {
 	// Dispatching must take ownership of handles and explicitly set handles in msg
 	// to 0 in order to avoid them being closed after dispatching. This guard
 	// extensively prevents leaked handles from dispatching.
-	defer msg.DiscardHandles()
+	//
+	// Handles may still be returned (since the wrapper around fdioServer will
+	// transmit |msg| back to the client) but only when provided a successful
+	// return status.
+	defer func() {
+		if status < 0 {
+			msg.DiscardHandles()
+		}
+	}()
 
 	// Incoming number of handles must match message type
 	if msg.Hcount != msg.OpHandleCount() {
diff --git a/go/src/wlan/eapol/definitions.go b/go/src/wlan/eapol/definitions.go
index b4a2f3a..eca3eaa 100644
--- a/go/src/wlan/eapol/definitions.go
+++ b/go/src/wlan/eapol/definitions.go
@@ -5,7 +5,7 @@
 package eapol
 
 import (
-	mlme "fidl/wlan_mlme"
+	"fidl/fuchsia/wlan/mlme"
 	"wlan/wlan/sme"
 
 	"bytes"
diff --git a/go/src/wlan/eapol/handshake/fourway.go b/go/src/wlan/eapol/handshake/fourway.go
index 138ee4c..2376c33 100644
--- a/go/src/wlan/eapol/handshake/fourway.go
+++ b/go/src/wlan/eapol/handshake/fourway.go
@@ -8,7 +8,7 @@
 	"bytes"
 	"encoding/hex"
 	"fmt"
-	mlme "fidl/wlan_mlme"
+	"fidl/fuchsia/wlan/mlme"
 	"log"
 	"math/big"
 	"wlan/eapol"
@@ -371,7 +371,9 @@
 	}
 	// IEEE Std 802.11-2016, 12.7.6.2
 	if isFirstMsg && !isZero(f.MIC[:]) {
-		return false, fmt.Errorf("invalid MIC, must be zero")
+		// Some routers don't zero the MIC in the first message of the handshake. Rather than refusing the
+		// handshake entirely, fix the glitch ourselves (NET-927).
+		f.MIC = make([]byte, len(f.MIC))
 	}
 
 	// IEEE Std 802.11-2016, 12.7.2 b.8) & b.9)
diff --git a/go/src/wlan/eapol/handshake/fourway_test.go b/go/src/wlan/eapol/handshake/fourway_test.go
index aef2cd9..3ece9ca 100644
--- a/go/src/wlan/eapol/handshake/fourway_test.go
+++ b/go/src/wlan/eapol/handshake/fourway_test.go
@@ -12,7 +12,7 @@
 	"bytes"
 	"encoding/hex"
 	"errors"
-	mlme "fidl/wlan_mlme"
+	"fidl/fuchsia/wlan/mlme"
 	"testing"
 	"wlan/eapol"
 	"wlan/eapol/crypto"
@@ -124,6 +124,24 @@
 	}
 }
 
+// NET-927: Some routers don't zero the MIC of the first message of the handshake. Rather than refusing the handshake
+// the MIC should be zeroed by the Supplicant.
+func TestSupplicant_RespondToNonZeroedMic(t *testing.T) {
+	for _, table := range inputTables {
+		env := NewEnv(t, table)
+
+		// Send message 1 to Supplicant.
+		msg1 := env.CreateValidMessage1()
+		copy(msg1.MIC, []uint8{0xFF})
+		err := env.SendToTestSubject(msg1)
+		if err != nil {
+			t.Fatal("Unexpected error:", err)
+		}
+		msg2 := env.RetrieveTestSubjectResponse()
+		env.ExpectValidMessage2(msg1, msg2)
+	}
+}
+
 // Send two valid message 1 to the Supplicant. Supplicant's responses should be IEEE compliant and
 // the sNonce should not be reused.
 func TestSupplicant_ResponseToValidReplayedMessage1(t *testing.T) {
@@ -270,25 +288,6 @@
 			t.Fatal("Expected error with MIC bit set")
 		}
 
-		// MIC bit and MIC set.
-		f = env.CreateValidMessage1()
-		f.Info = f.Info.Update(0, eapol.KeyInfo_MIC)
-		copy(f.MIC, []uint8{3}) // Note: We cannot compute a valid MIC since we have no key
-		err = env.SendToTestSubject(f)
-		resp = env.RetrieveTestSubjectResponse()
-		if err == nil || resp != nil {
-			t.Fatal("Expected error with MIC set")
-		}
-
-		// MIC set.
-		f = env.CreateValidMessage1()
-		copy(f.MIC, []uint8{3}) // Note: We cannot compute a valid MIC since we have no key
-		err = env.SendToTestSubject(f)
-		resp = env.RetrieveTestSubjectResponse()
-		if err == nil || resp != nil {
-			t.Fatal("Expected error with MIC set")
-		}
-
 		// Secure bit set.
 		f = env.CreateValidMessage1()
 		f.Info = f.Info.Update(0, eapol.KeyInfo_Secure)
diff --git a/go/src/wlan/wlan/ap.go b/go/src/wlan/wlan/ap.go
index bc9d933..de704aa 100644
--- a/go/src/wlan/wlan/ap.go
+++ b/go/src/wlan/wlan/ap.go
@@ -5,7 +5,7 @@
 package wlan
 
 import (
-	mlme "fidl/wlan_mlme"
+	"fidl/fuchsia/wlan/mlme"
 	"fmt"
 	"sort"
 	"strings"
diff --git a/go/src/wlan/wlan/api.go b/go/src/wlan/wlan/api.go
index bc1cc2c..f819c7e 100644
--- a/go/src/wlan/wlan/api.go
+++ b/go/src/wlan/wlan/api.go
@@ -5,7 +5,7 @@
 package wlan
 
 import (
-	mlme "fidl/wlan_mlme"
+	"fidl/fuchsia/wlan/mlme"
 	"fmt"
 	"log"
 )
diff --git a/go/src/wlan/wlan/states.go b/go/src/wlan/wlan/states.go
index 68c71fc..6ec7403 100644
--- a/go/src/wlan/wlan/states.go
+++ b/go/src/wlan/wlan/states.go
@@ -5,8 +5,8 @@
 package wlan
 
 import (
-	mlme "fidl/wlan_mlme"
-	"fidl/wlan_service"
+	"fidl/fuchsia/wlan/mlme"
+	wlan_service "fidl/fuchsia/wlan/service"
 	"wlan/eapol"
 	"wlan/eapol/handshake"
 	"wlan/wlan/elements"
diff --git a/go/src/wlan/wlan/wlan.go b/go/src/wlan/wlan/wlan.go
index 35c38d4..eba6c00 100644
--- a/go/src/wlan/wlan/wlan.go
+++ b/go/src/wlan/wlan/wlan.go
@@ -6,8 +6,8 @@
 
 import (
 	bindings "fidl/bindings"
-	mlme "fidl/wlan_mlme"
-	"fidl/wlan_service"
+	"fidl/fuchsia/wlan/mlme"
+	wlan_service "fidl/fuchsia/wlan/service"
 	"fmt"
 	"log"
 	"os"
diff --git a/go/src/wlan/wlan/wlan_test.go b/go/src/wlan/wlan/wlan_test.go
index dc30c7c..7c904d3 100644
--- a/go/src/wlan/wlan/wlan_test.go
+++ b/go/src/wlan/wlan/wlan_test.go
@@ -5,7 +5,7 @@
 package wlan_test
 
 import (
-	mlme "fidl/wlan_mlme"
+	"fidl/fuchsia/wlan/mlme"
 	"testing"
 	. "wlan/wlan"
 )
diff --git a/go/src/wlan/wlanstack/main.go b/go/src/wlan/wlanstack/main.go
index d690d72..b73ecf1 100644
--- a/go/src/wlan/wlanstack/main.go
+++ b/go/src/wlan/wlanstack/main.go
@@ -8,7 +8,7 @@
 	"app/context"
 	"fidl/bindings"
 
-	"fidl/wlan_service"
+	wlan_service "fidl/fuchsia/wlan/service"
 	"netstack/watcher"
 	"wlan/wlan"
 
diff --git a/go/src/wlan/wlantool/wlantool.go b/go/src/wlan/wlantool/wlantool.go
index 03ff612..d4c3500 100644
--- a/go/src/wlan/wlantool/wlantool.go
+++ b/go/src/wlan/wlantool/wlantool.go
@@ -12,8 +12,8 @@
 
 	"app/context"
 
-	"fidl/wlan_mlme"
-	"fidl/wlan_service"
+	"fidl/fuchsia/wlan/mlme"
+	wlan_service "fidl/fuchsia/wlan/service"
 )
 
 const (
@@ -31,26 +31,26 @@
 }
 
 // LINT.IfChange
-func CbwToStr(cbw wlan_mlme.Cbw) string {
+func CbwToStr(cbw mlme.Cbw) string {
 	switch cbw {
-	case wlan_mlme.CbwCbw20:
+	case mlme.CbwCbw20:
 		return " "
-	case wlan_mlme.CbwCbw40:
+	case mlme.CbwCbw40:
 		return "+"
-	case wlan_mlme.CbwCbw40Below:
+	case mlme.CbwCbw40Below:
 		return "-"
-	case wlan_mlme.CbwCbw80:
+	case mlme.CbwCbw80:
 		return "V"
-	case wlan_mlme.CbwCbw160:
+	case mlme.CbwCbw160:
 		return "W"
-	case wlan_mlme.CbwCbw80P80:
+	case mlme.CbwCbw80P80:
 		return "P"
 	default:
 		return "(unknown CBW)"
 	}
 }
 
-func ChanToStr(ch wlan_mlme.WlanChan) string {
+func ChanToStr(ch mlme.WlanChan) string {
 	return fmt.Sprintf("%3d%s", ch.Primary, CbwToStr(ch.Cbw))
 }
 
diff --git a/lib/bluetooth/fidl/BUILD.gn b/lib/bluetooth/fidl/BUILD.gn
index 52a4a22..6d22921 100644
--- a/lib/bluetooth/fidl/BUILD.gn
+++ b/lib/bluetooth/fidl/BUILD.gn
@@ -5,14 +5,15 @@
 import("//build/fidl/fidl.gni")
 
 fidl("bluetooth_host") {
+  name = "fuchsia.bluetooth.host"
   sources = [
     "host.fidl",
   ]
-
-   public_deps = [
-     "//garnet/public/lib/bluetooth/fidl:bluetooth",
-     "//garnet/public/lib/bluetooth/fidl:bluetooth_control",
-     "//garnet/public/lib/bluetooth/fidl:bluetooth_gatt",
-     "//garnet/public/lib/bluetooth/fidl:bluetooth_low_energy",
-   ]
+  cpp_legacy_callbacks = true
+  public_deps = [
+    "//garnet/public/lib/bluetooth/fidl:bluetooth",
+    "//garnet/public/lib/bluetooth/fidl:bluetooth_control",
+    "//garnet/public/lib/bluetooth/fidl:bluetooth_gatt",
+    "//garnet/public/lib/bluetooth/fidl:bluetooth_low_energy",
+  ]
 }
diff --git a/lib/bluetooth/fidl/host.fidl b/lib/bluetooth/fidl/host.fidl
index 200caf1..ecb01f1 100644
--- a/lib/bluetooth/fidl/host.fidl
+++ b/lib/bluetooth/fidl/host.fidl
@@ -2,16 +2,31 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library bluetooth_host;
+library fuchsia.bluetooth.host;
 
-// Interface for interacting with a local Bluetooth adapter.
-// TODO(NET-666): Merge this into Host
-interface Adapter {
-  // Returns information about this adapter, including its state.
-  1: GetInfo() -> (bluetooth_control.AdapterInfo @info);
+using fuchsia.bluetooth;
+using fuchsia.bluetooth.control;
+using fuchsia.bluetoth.gatt;
+using fuchsia.bluetooth.le;
+
+// Interface for interacting with a Bluetooth host device (bt-host)
+interface Host {
+  // The following methods fulfill a given interface request. bt-host device
+  // will start processing FIDL messages. If the request cannot be fulfilled,
+  // the bt-host device will close its end of the given channel.
+  1: RequestLowEnergyCentral(request<fuchsia.bluetooth.le.Central> central);
+  2: RequestLowEnergyPeripheral(request<fuchsia.bluetooth.le.Peripheral> peripheral);
+  3: RequestGattServer(request<fuchsia.bluetooth.gatt.Server> server);
+
+  // Closes all FIDL interface handles that are associated with this bt-host
+  // device (excluding any Host interface handles).
+  4: Close();
+
+  // Returns information about the Bluetooth adapter managed by this host.
+  5: GetInfo() -> (fuchsia.bluetooth.control.AdapterInfo @info);
 
   // Sets the local name for this adapter.
-  2: SetLocalName(string local_name) -> (bluetooth.Status @status);
+  6: SetLocalName(string local_name) -> (fuchsia.bluetooth.Status @status);
 
   // Initiates a general discovery procedure for BR/EDR and LE devices. On success, discovered
   // devices will be reported via AdapterDelegate.OnDeviceDiscovered().
@@ -20,7 +35,7 @@
   //
   // Discovery will continue until it is terminated via StopDiscovery() or if the proxy to the
   // Adapter gets disconnected.
-  3: StartDiscovery() -> (bluetooth.Status @status);
+  7: StartDiscovery() -> (fuchsia.bluetooth.Status @status);
 
   // Terminates discovery if one was started via StartDiscovery(). The AdapterDelegate will stop
   // receiving device discovery notifications.
@@ -28,33 +43,15 @@
   // NOTE: If another client is performing discovery (e.g. via its own Adapter interface handle),
   // then the system will continue performing device discovery even if this method results in
   // success.
-  6: StopDiscovery() -> (bluetooth.Status @status);
+  8: StopDiscovery() -> (fuchsia.bluetooth.Status @status);
 
   // Sets whether this host should be connectable.
-  7: SetConnectable(bool enabled) -> (bluetooth.Status @status);
+  9: SetConnectable(bool enabled) -> (fuchsia.bluetooth.Status @status);
 
   // Sets whether this host should be discoverable.
-  8: SetDiscoverable(bool enabled) -> (bluetooth.Status @status);
+  10: SetDiscoverable(bool enabled) -> (fuchsia.bluetooth.Status @status);
 
   // Events
-  1000: -> OnAdapterStateChanged(bluetooth_control.AdapterState state);
-  1001: -> OnDeviceDiscovered(bluetooth_control.RemoteDevice device);
-};
-
-// Management interface implemented by bt-host devices.
-interface Host {
-  // Returns information about the Bluetooth adapter managed by this host.
-  1: GetInfo() -> (bluetooth_control.AdapterInfo @info);
-
-  // The following methods fulfill a given interface request. bt-host device
-  // will start processing FIDL messages. If the request cannot be fulfilled,
-  // the bt-host device will close its end of the given channel.
-  2: RequestAdapter(request<Adapter> adapter);
-  3: RequestLowEnergyCentral(request<bluetooth_low_energy.Central> central);
-  4: RequestLowEnergyPeripheral(request<bluetooth_low_energy.Peripheral> peripheral);
-  5: RequestGattServer(request<bluetooth_gatt.Server> server);
-
-  // Closes all FIDL interface handles that are associated with this bt-host
-  // device (exluding any Host interface handles).
-  6: Close();
+  101: -> OnHostStateChanged(fuchsia.bluetooth.control.AdapterState state);
+  102: -> OnDeviceDiscovered(fuchsia.bluetooth.control.RemoteDevice device);
 };
diff --git a/lib/debug_ipc/helper/BUILD.gn b/lib/debug_ipc/helper/BUILD.gn
index af35d16..8e8c422 100644
--- a/lib/debug_ipc/helper/BUILD.gn
+++ b/lib/debug_ipc/helper/BUILD.gn
@@ -12,6 +12,8 @@
     "message_loop.h",
     "stream_buffer.cc",
     "stream_buffer.h",
+    "test_stream_buffer.cc",
+    "test_stream_buffer.h",
   ]
 
   public_deps = [
diff --git a/lib/debug_ipc/helper/message_loop_zircon.cc b/lib/debug_ipc/helper/message_loop_zircon.cc
index 82e9bb6..477433f 100644
--- a/lib/debug_ipc/helper/message_loop_zircon.cc
+++ b/lib/debug_ipc/helper/message_loop_zircon.cc
@@ -4,8 +4,8 @@
 
 #include "garnet/lib/debug_ipc/helper/message_loop_zircon.h"
 
-#include <fdio/io.h>
-#include <fdio/private.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/private.h>
 #include <zircon/syscalls/exception.h>
 #include <zircon/syscalls/port.h>
 
diff --git a/lib/debug_ipc/helper/test_stream_buffer.cc b/lib/debug_ipc/helper/test_stream_buffer.cc
new file mode 100644
index 0000000..d273a0f
--- /dev/null
+++ b/lib/debug_ipc/helper/test_stream_buffer.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "garnet/lib/debug_ipc/helper/test_stream_buffer.h"
+
+namespace debug_ipc {
+
+TestStreamBuffer::TestStreamBuffer() { stream_.set_writer(this); }
+
+TestStreamBuffer::~TestStreamBuffer() = default;
+
+size_t TestStreamBuffer::ConsumeStreamBufferData(const char* data, size_t len) {
+  write_sink_.insert(write_sink_.end(), &data[0], &data[len]);
+  return len;
+}
+
+}  // namespace debug_ipc
diff --git a/lib/debug_ipc/helper/test_stream_buffer.h b/lib/debug_ipc/helper/test_stream_buffer.h
new file mode 100644
index 0000000..eeb6940
--- /dev/null
+++ b/lib/debug_ipc/helper/test_stream_buffer.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <deque>
+
+#include "garnet/lib/debug_ipc/helper/stream_buffer.h"
+#include "garnet/public/lib/fxl/macros.h"
+
+namespace debug_ipc {
+
+// An implementation of StreamBuffer that provides the simplest-possible
+// buffering to memory for test purposes.
+//
+// The stream buffer is bidirectional and has a buffer going both ways:
+//
+//   Writing to the stream buffer: stream().Write(...)
+//   will come out in write_sink().
+//
+//   Reading from the stream buffer: stream().Read(...) or ...Peek();
+//   data is provided by stream().AddReadData(...).
+class TestStreamBuffer : public StreamBuffer::Writer {
+ public:
+  TestStreamBuffer();
+  ~TestStreamBuffer();
+
+  StreamBuffer& stream() { return stream_; }
+  const StreamBuffer& stream() const { return stream_; }
+
+  // Where data that is written to the stream buffer ends up. This emulates
+  // what would normally be the system-specific destination (file, etc.).
+  const std::deque<char>& write_sink() const { return write_sink_; }
+  std::deque<char>& write_sink() { return write_sink_; }
+
+ private:
+  // StreamBuffer::Writer implementation.
+  size_t ConsumeStreamBufferData(const char* data, size_t len) override;
+
+  StreamBuffer stream_;
+
+  std::deque<char> write_sink_;
+
+  FXL_DISALLOW_COPY_AND_ASSIGN(TestStreamBuffer);
+};
+
+}  // namespace debug_ipc
diff --git a/lib/far/far_vmo.cc b/lib/far/far_vmo.cc
index 5239ab7..5698813 100644
--- a/lib/far/far_vmo.cc
+++ b/lib/far/far_vmo.cc
@@ -4,7 +4,7 @@
 
 #include "garnet/lib/far/far.h"
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <zircon/syscalls.h>
 
 bool far_reader_read_vmo(far_reader_t reader, zx_handle_t vmo) {
diff --git a/lib/inferior_control/BUILD.gn b/lib/inferior_control/BUILD.gn
index 6fb7ff2..87dd0ab 100644
--- a/lib/inferior_control/BUILD.gn
+++ b/lib/inferior_control/BUILD.gn
@@ -59,6 +59,7 @@
 
   public_deps = [
     "//zircon/public/lib/launchpad",
+    "//zircon/public/lib/fit"
   ]
 
   include_dirs = [ ".." ]
diff --git a/lib/inferior_control/exception_port.cc b/lib/inferior_control/exception_port.cc
index 8aa3ea9..26a8b70 100644
--- a/lib/inferior_control/exception_port.cc
+++ b/lib/inferior_control/exception_port.cc
@@ -9,6 +9,7 @@
 
 #include <lib/async/cpp/task.h>
 #include <lib/async/default.h>
+#include <lib/fit/function.h>
 #include <zircon/syscalls.h>
 #include <zircon/syscalls/port.h>
 
@@ -74,7 +75,7 @@
   FXL_DCHECK(eport_handle_);
 
   keep_running_ = true;
-  io_thread_ = std::thread(std::bind(&ExceptionPort::Worker, this));
+  io_thread_ = std::thread(fit::bind_member(this, &ExceptionPort::Worker));
 
   return true;
 }
@@ -105,7 +106,7 @@
 }
 
 ExceptionPort::Key ExceptionPort::Bind(zx_handle_t process_handle,
-                                       const Callback& callback) {
+                                       Callback callback) {
   FXL_DCHECK(process_handle != ZX_HANDLE_INVALID);
   FXL_DCHECK(callback);
   FXL_DCHECK(eport_handle_);
@@ -151,7 +152,7 @@
   // |next_key| should not have been used before.
   FXL_DCHECK(callbacks_.find(next_key) == callbacks_.end());
 
-  callbacks_[next_key] = BindData(process_handle, process_koid, callback);
+  callbacks_[next_key] = BindData(process_handle, process_koid, std::move(callback));
   ++g_key_counter;
 
   FXL_VLOG(1) << "Exception port bound to process handle " << process_handle
diff --git a/lib/inferior_control/exception_port.h b/lib/inferior_control/exception_port.h
index 6aca423..5824f8c 100644
--- a/lib/inferior_control/exception_port.h
+++ b/lib/inferior_control/exception_port.h
@@ -6,12 +6,12 @@
 
 #include <atomic>
 #include <cstdio>
-#include <functional>
 #include <mutex>
 #include <thread>
 #include <unordered_map>
 
 #include <lib/async/dispatcher.h>
+#include <lib/fit/function.h>
 #include <lib/zx/port.h>
 #include <zircon/syscalls/exception.h>
 #include <zircon/types.h>
@@ -35,7 +35,7 @@
   // Handler callback invoked when the kernel reports an exception. For more
   // information about the possible values and fields of the |type| and
   // |context| parameters, see <zircon/syscalls/exception.h>.
-  using Callback = std::function<void(const zx_port_packet_t& packet,
+  using Callback = fit::function<void(const zx_port_packet_t& packet,
                                       const zx_exception_context_t& context)>;
 
   explicit ExceptionPort(async_t* async);
@@ -59,7 +59,7 @@
   // created.
   //
   // This must be called AFTER a successful call to Run().
-  Key Bind(const zx_handle_t process_handle, const Callback& callback);
+  Key Bind(const zx_handle_t process_handle, Callback callback);
 
   // Unbinds a previously bound exception port and returns true on success.
   // This must be called AFTER a successful call to Run().
@@ -69,10 +69,10 @@
   struct BindData {
     BindData() = default;
     BindData(zx_handle_t process_handle, zx_koid_t process_koid,
-             const Callback& callback)
+             Callback callback)
         : process_handle(process_handle),
           process_koid(process_koid),
-          callback(callback) {}
+          callback(std::move(callback)) {}
 
     zx_handle_t process_handle;
     zx_koid_t process_koid;
diff --git a/lib/inferior_control/io_loop.cc b/lib/inferior_control/io_loop.cc
index a720c80..57afcdf 100644
--- a/lib/inferior_control/io_loop.cc
+++ b/lib/inferior_control/io_loop.cc
@@ -7,6 +7,7 @@
 #include <unistd.h>
 
 #include <lib/async/cpp/task.h>
+#include <lib/fit/function.h>
 
 #include "garnet/lib/debugger_utils/util.h"
 #include "lib/fsl/handles/object_info.h"
@@ -41,7 +42,7 @@
   // Posts an asynchronous task on to listen for an incoming packet. This
   // initiates a loop that always reads for incoming packets. Called from
   // Run().
-  async::PostTask(read_loop_.async(), std::bind(&IOLoop::OnReadTask, this));
+  async::PostTask(read_loop_.async(), fit::bind_member(this, &IOLoop::OnReadTask));
 }
 
 void IOLoop::Quit() {
diff --git a/lib/inferior_control/io_loop.h b/lib/inferior_control/io_loop.h
index a289a2a..ef81996 100644
--- a/lib/inferior_control/io_loop.h
+++ b/lib/inferior_control/io_loop.h
@@ -10,7 +10,6 @@
 
 #include <lib/async-loop/cpp/loop.h>
 
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_ptr.h"
 #include "lib/fxl/strings/string_view.h"
diff --git a/lib/inferior_control/process.cc b/lib/inferior_control/process.cc
index c8715f7..bb16a4e 100644
--- a/lib/inferior_control/process.cc
+++ b/lib/inferior_control/process.cc
@@ -7,8 +7,9 @@
 #include <link.h>
 #include <cinttypes>
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <launchpad/vmo.h>
+#include <lib/fit/function.h>
 #include <zircon/syscalls.h>
 #include <zircon/syscalls/object.h>
 
@@ -367,8 +368,7 @@
 
 bool Process::BindExceptionPort() {
   ExceptionPort::Key key = server_->exception_port().Bind(
-      handle_, std::bind(&Process::OnExceptionOrSignal, this,
-                         std::placeholders::_1, std::placeholders::_2));
+      handle_, fit::bind_member(this, &Process::OnExceptionOrSignal));
   if (!key) return false;
   eport_key_ = key;
   return true;
diff --git a/lib/inferior_control/process.h b/lib/inferior_control/process.h
index 1933836..b35ddd5 100644
--- a/lib/inferior_control/process.h
+++ b/lib/inferior_control/process.h
@@ -157,7 +157,7 @@
   // Iterates through all cached threads and invokes |callback| for each of
   // them. |callback| is guaranteed to get called only before ForEachThread()
   // returns, so it is safe to bind local variables to |callback|.
-  using ThreadCallback = std::function<void(Thread*)>;
+  using ThreadCallback = fit::function<void(Thread*)>;
   void ForEachThread(const ThreadCallback& callback);
   // Same as ForEachThread except ignores State::Gone threads.
   void ForEachLiveThread(const ThreadCallback& callback);
diff --git a/lib/inferior_control/test_server.h b/lib/inferior_control/test_server.h
index 32786ea..b708339 100644
--- a/lib/inferior_control/test_server.h
+++ b/lib/inferior_control/test_server.h
@@ -5,7 +5,6 @@
 #pragma once
 
 #include <cstdint>
-#include <functional>
 #include <string>
 
 #include <lib/zx/channel.h>
diff --git a/lib/machina/block_dispatcher.cc b/lib/machina/block_dispatcher.cc
index 2a27575..5ab58aa 100644
--- a/lib/machina/block_dispatcher.cc
+++ b/lib/machina/block_dispatcher.cc
@@ -13,7 +13,7 @@
 #include <fbl/auto_lock.h>
 #include <fbl/unique_fd.h>
 #include <fbl/unique_ptr.h>
-#include <fdio/watcher.h>
+#include <lib/fdio/watcher.h>
 #include <trace/event.h>
 #include <virtio/virtio_ids.h>
 #include <virtio/virtio_ring.h>
diff --git a/lib/machina/hid_event_source.cc b/lib/machina/hid_event_source.cc
index 70990a6..3c3fecd 100644
--- a/lib/machina/hid_event_source.cc
+++ b/lib/machina/hid_event_source.cc
@@ -10,7 +10,7 @@
 
 #include <fbl/auto_lock.h>
 #include <fbl/unique_fd.h>
-#include <fdio/watcher.h>
+#include <lib/fdio/watcher.h>
 #include <hid/hid.h>
 #include <zircon/compiler.h>
 #include <zircon/device/input.h>
diff --git a/lib/machina/virtio_vsock.cc b/lib/machina/virtio_vsock.cc
index fd28676..24339c9 100644
--- a/lib/machina/virtio_vsock.cc
+++ b/lib/machina/virtio_vsock.cc
@@ -282,7 +282,9 @@
 
   // If the socket is writable, wait on the Virtio transmit queue.
   if (signal->observed & ZX_SOCKET_WRITABLE) {
-    status = WaitOnQueueLocked(key, &writable_, &tx_stream_);
+    // TODO(tjdetwiler): Since space has been made available in the socket
+    // buffer, we should send a credit update to the guest to indicate transmits
+    // may resume.
   }
 
   if (status != ZX_OK) {
@@ -392,7 +394,7 @@
       // We are sending a connection request, therefore we move to waiting
       // for response.
       conn->op = VIRTIO_VSOCK_OP_RESPONSE;
-      return WaitOnQueueLocked(key, &writable_, &tx_stream_);
+      return ZX_OK;
     }
     case VIRTIO_VSOCK_OP_RESPONSE:
     case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
@@ -436,7 +438,7 @@
         // ready to read/write.
         conn->op = VIRTIO_VSOCK_OP_RW;
       }
-      return WaitOnQueueLocked(key, &writable_, &tx_stream_);
+      return ZX_OK;
     default:
     case VIRTIO_VSOCK_OP_RST:
       // We are sending a connection reset, therefore remove the connection.
@@ -489,12 +491,6 @@
         status = AddConnectionLocked(key, std::move(new_conn));
         set_shutdown(header);
         FXL_LOG(ERROR) << "Connection does not exist";
-      } else if (writable_.find(key) == writable_.end()) {
-        // There was a write, but the socket is not ready. If the guest is
-        // respecting the credit update messages this should not happen.
-        FXL_LOG(ERROR) << "Received write to a socket that is not wriable!"
-                       << "Data will be lost.";
-        continue;
       } else if (conn->op == VIRTIO_VSOCK_OP_RW &&
                  conn->flags & VIRTIO_VSOCK_FLAG_SHUTDOWN_SEND) {
         // We are receiving a write, but send was shutdown.
@@ -568,7 +564,6 @@
             FXL_LOG(ERROR) << "Failed to write to connection socket " << status
                            << ". Attempted to write  " << len
                            << "b but only wrote " << actual << "b.";
-            writable_.erase(key);
             if (status == ZX_ERR_SHOULD_WAIT) {
               status = ZX_OK;
             }
diff --git a/lib/machina/virtio_vsock.h b/lib/machina/virtio_vsock.h
index c22e42e..2c8c843 100644
--- a/lib/machina/virtio_vsock.h
+++ b/lib/machina/virtio_vsock.h
@@ -143,7 +143,6 @@
   mutable fbl::Mutex mutex_;
   ConnectionMap connections_ __TA_GUARDED(mutex_);
   ConnectionSet readable_ __TA_GUARDED(mutex_);
-  ConnectionSet writable_ __TA_GUARDED(mutex_);
   // NOTE(abdulla): We ignore the event queue, as we don't support VM migration.
 
   fidl::BindingSet<fuchsia::guest::SocketAcceptor> acceptor_bindings_;
diff --git a/lib/magma/BUILD.gn b/lib/magma/BUILD.gn
index 563cc87..69dea3a 100644
--- a/lib/magma/BUILD.gn
+++ b/lib/magma/BUILD.gn
@@ -5,169 +5,17 @@
 import("//build/package.gni")
 import("//garnet/lib/magma/gnbuild/magma.gni")
 
-if (have_prebuilt_libvulkan_arm) {
-  libvulkan_gen_path = "$target_gen_dir/libvulkan"
-}
-
-# This target is not built but ensures that the packages don't reference
-# driver directories that are invalid for the current platform.
-group("platform_driver_nodeps") {
-  testonly = true
-  assert_no_deps = []
-  if (!build_intel_gen) {
-    assert_no_deps += [ "//third_party/mesa/*" ]
-  }
-  if (build_libvulkan_arm_mali == []) {
-    assert_no_deps += [ "//third_party/arm-mali-bifrost/*" ]
-  }
-  deps = [
-    ":magma",
-    "tests:magma-test",
-    "tests:magma-test-build-only",
-  ]
-}
-
-icd_list = []
-if (build_intel_gen) {
-  icd_list += [
-    {
-      name = "libvulkan_intel"
-    },
-  ]
-}
-
-if (build_libvulkan_arm_mali != []) {
-  foreach(entry, build_libvulkan_arm_mali) {
-    icd_list += [
-      {
-        name = get_label_info(entry, "name")
-      },
-    ]
-  }
-} else if (have_prebuilt_libvulkan_arm) {
-  icd_list += [
-    {
-      name = "libvulkan_arm"
-      library_path = "$libvulkan_gen_path/libvulkan_arm.so"
-    },
-  ]
-}
-
-foreach(entry, icd_list) {
-  icd_name = entry.name
-  filename = "$target_gen_dir/vulkan/icd.d/$icd_name.json"
-  icd_data = []
-  icd_data = [
-    "{",
-    "\"file_format_version\": \"1.0.0\",",
-    "\"ICD\": {",
-    "\"library_path\": \"$icd_name.so\",",
-    "\"api_version\": \"1.0.68\"",
-    "}",
-    "}",
-  ]
-  write_file(filename, icd_data)
-}
-
-package("magma") {
+# TODO(MA-416): should libmagma be a source set?
+package("libmagma") {
   deprecated_system_image = true
-  if (magma_enable_developer_build) {
-    testonly = true
-  }
-
   deps = [
-    ":libmagma",
+    "//garnet/lib/magma/src/libmagma",
   ]
   libraries = [
     {
       name = "libmagma.so"
     },
   ]
-
-  resources = []
-  drivers = []
-
-  if (have_libvulkan) {
-    deps += [ ":libvulkan" ]
-  }
-
-  if (build_intel_gen) {
-    if (magma_enable_developer_build) {
-      deps += [ "$msd_intel_gen_build_root:msd_intel_test" ]
-      drivers += [
-        {
-          name = "libmsd_intel_test.so"
-        },
-      ]
-    } else {
-      deps += [ "$msd_intel_gen_build_root:msd_intel" ]
-      drivers += [
-        {
-          name = "libmsd_intel.so"
-        },
-      ]
-    }
-  }
-
-  if (build_msd_arm_mali) {
-    if (magma_enable_developer_build) {
-      deps += [ "//garnet/drivers/gpu/msd-arm-mali:msd_arm_test" ]
-      drivers += [
-        {
-          name = "libmsd_arm_test.so"
-        },
-      ]
-    } else {
-      deps += [ "//garnet/drivers/gpu/msd-arm-mali:msd_arm" ]
-      drivers += [
-        {
-          name = "libmsd_arm.so"
-        },
-      ]
-    }
-  }
-
-  if (build_msd_vsl_gc) {
-    if (magma_enable_developer_build) {
-      deps += [ "//garnet/drivers/gpu/msd-vsl-gc:msd_vsl_test" ]
-      drivers += [
-        {
-          name = "libmsd_vsl_test.so"
-        },
-      ]
-    } else {
-      deps += [ "//garnet/drivers/gpu/msd-vsl-gc:msd_vsl" ]
-      drivers += [
-        {
-          name = "libmsd_vsl.so"
-        },
-      ]
-    }
-  }
-
-  foreach(entry, icd_list) {
-    icd_name = entry.name
-    resources += [
-      {
-        path = rebase_path("$target_gen_dir/vulkan/icd.d/$icd_name.json")
-        dest = "vulkan/icd.d/$icd_name.json"
-      },
-    ]
-    if (defined(entry.library_path)) {
-      libraries += [
-        {
-          source = entry.library_path
-          name = "$icd_name.so"
-        },
-      ]
-    } else {
-      libraries += [
-        {
-          name = "$icd_name.so"
-        },
-      ]
-    }
-  }
 }
 
 package("magma-tools") {
@@ -210,41 +58,6 @@
   include_dirs = [ "tests" ]
 }
 
-group("libmagma") {
-  public_deps = [
-    "src/libmagma",
-  ]
-}
-
-if (build_intel_gen) {
-  group("libvulkan") {
-    public_deps = [
-      "$mesa_build_root:magma_vulkan",
-    ]
-  }
-} else if (build_libvulkan_arm_mali != []) {
-  group("libvulkan") {
-    public_deps = build_libvulkan_arm_mali
-  }
-} else if (have_prebuilt_libvulkan_arm) {
-  config("libvulkan_config") {
-    libs = [ "vulkan_arm" ]
-    lib_dirs = [ libvulkan_gen_path ]
-  }
-  copy("libvulkan") {
-    public_configs = [ ":libvulkan_config" ]
-    sources = [
-      prebuilt_libvulkan_arm_path,
-    ]
-    outputs = [
-      "$libvulkan_gen_path/libvulkan_arm.so",
-    ]
-    deps = [
-      "//third_party/zlib",
-    ]
-  }
-}
-
 group("tools") {
   public_deps = [
     "src/tools",
diff --git a/lib/magma/gnbuild/magma-arm-mali/BUILD.gn b/lib/magma/gnbuild/magma-arm-mali/BUILD.gn
new file mode 100644
index 0000000..242df78
--- /dev/null
+++ b/lib/magma/gnbuild/magma-arm-mali/BUILD.gn
@@ -0,0 +1,175 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+import("//garnet/lib/magma/gnbuild/magma.gni")
+
+if (have_prebuilt_libvulkan_arm) {
+  libvulkan_gen_path = "$target_gen_dir/libvulkan"
+}
+
+icd_list = []
+
+if (build_libvulkan != []) {
+  foreach(entry, build_libvulkan) {
+    icd_list += [
+      {
+        name = get_label_info(entry, "name")
+      },
+    ]
+  }
+} else if (have_prebuilt_libvulkan_arm) {
+  icd_list += [
+    {
+      name = "libvulkan_arm"
+      library_path = "$libvulkan_gen_path/libvulkan_arm.so"
+    },
+  ]
+}
+
+package("magma-arm-mali") {
+  if (build_msd_arm_mali) {
+    deprecated_system_image = true
+    if (magma_enable_developer_build) {
+      testonly = true
+    }
+
+    if (magma_enable_developer_build) {
+      deps = [ "//garnet/drivers/gpu/msd-arm-mali:msd_arm_test" ]
+      drivers = [
+        {
+          name = "libmsd_arm_test.so"
+        },
+      ]
+    } else {
+      deps = [ "//garnet/drivers/gpu/msd-arm-mali:msd_arm" ]
+      drivers = [
+        {
+          name = "libmsd_arm.so"
+        },
+      ]
+    }
+
+    if (have_libvulkan) {
+      deps += [ ":libvulkan" ]
+
+      foreach(entry, icd_list) {
+        icd_name = entry.name
+        filename = "$target_gen_dir/vulkan/icd.d/$icd_name.json"
+        icd_data = []
+        icd_data = [
+          "{",
+          "\"file_format_version\": \"1.0.0\",",
+          "\"ICD\": {",
+          "\"library_path\": \"$icd_name.so\",",
+          "\"api_version\": \"1.0.68\"",
+          "}",
+          "}",
+        ]
+        write_file(filename, icd_data)
+      }
+    }
+
+    resources = []
+    libraries = []
+
+    foreach(entry, icd_list) {
+      icd_name = entry.name
+      resources += [
+        {
+          path = rebase_path("$target_gen_dir/vulkan/icd.d/$icd_name.json")
+          dest = "vulkan/icd.d/$icd_name.json"
+        },
+      ]
+      if (defined(entry.library_path)) {
+        libraries += [
+          {
+            source = entry.library_path
+            name = "$icd_name.so"
+          },
+        ]
+      } else {
+        libraries += [
+          {
+            name = "$icd_name.so"
+          },
+        ]
+      }
+    }
+  }
+}
+
+if (build_libvulkan != []) {
+  group("libvulkan") {
+    public_deps = build_libvulkan
+  }
+} else if (have_prebuilt_libvulkan_arm) {
+  config("libvulkan_config") {
+    libs = [ "vulkan_arm" ]
+    lib_dirs = [ libvulkan_gen_path ]
+  }
+  copy("libvulkan") {
+    public_configs = [ ":libvulkan_config" ]
+    sources = [
+      prebuilt_libvulkan_arm_path,
+    ]
+    outputs = [
+      "$libvulkan_gen_path/libvulkan_arm.so",
+    ]
+    deps = [
+      "//third_party/zlib",
+    ]
+  }
+}
+
+package("nonhardware-tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  if (build_msd_arm_mali) {
+    deps = [
+      "//garnet/drivers/gpu/msd-arm-mali:tests",
+    ]
+
+    tests = [
+      {
+        name = "msd_arm_mali_nonhardware_tests"
+      },
+    ]
+  }
+}
+
+package("tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  if (build_msd_arm_mali) {
+    deps = [
+      ":autorun_mali",
+      "//garnet/drivers/gpu/msd-arm-mali/tests/integration",
+    ]
+
+    tests = [
+      {
+        name = "msd_arm_mali_integration_tests"
+      },
+    ]
+
+    binaries = [
+      {
+        name = "autorun_mali"
+        dest = "magma_autorun"
+      },
+    ]
+  }
+}
+
+copy("autorun_mali") {
+  sources = [
+    "//garnet/lib/magma/scripts/autorun_mali",
+  ]
+  outputs = [
+    "$root_out_dir/autorun_mali",
+  ]
+}
diff --git a/lib/magma/gnbuild/magma-intel-gen/BUILD.gn b/lib/magma/gnbuild/magma-intel-gen/BUILD.gn
new file mode 100644
index 0000000..e32b98f
--- /dev/null
+++ b/lib/magma/gnbuild/magma-intel-gen/BUILD.gn
@@ -0,0 +1,128 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+import("//garnet/lib/magma/gnbuild/magma.gni")
+
+package("magma-intel-gen") {
+  if (build_intel_gen) {
+    deprecated_system_image = true
+    if (magma_enable_developer_build) {
+      testonly = true
+    }
+
+    deps = build_libvulkan
+
+    filename = "$target_gen_dir/vulkan/icd.d/libvulkan_intel.json"
+    icd_data = [
+      "{",
+      "\"file_format_version\": \"1.0.0\",",
+      "\"ICD\": {",
+      "\"library_path\": \"libvulkan_intel.so\",",
+      "\"api_version\": \"1.0.68\"",
+      "}",
+      "}",
+    ]
+    write_file(filename, icd_data)
+
+    resources = [
+      {
+        path = rebase_path("$target_gen_dir/vulkan/icd.d/libvulkan_intel.json")
+        dest = "vulkan/icd.d/libvulkan_intel.json"
+      },
+    ]
+    libraries = [
+      {
+        name = "libvulkan_intel.so"
+      },
+    ]
+
+    if (magma_enable_developer_build) {
+      deps += [ "$msd_intel_gen_build_root:msd_intel_test" ]
+      drivers = [
+        {
+          name = "libmsd_intel_test.so"
+        },
+      ]
+    } else {
+      deps += [ "$msd_intel_gen_build_root:msd_intel" ]
+      drivers = [
+        {
+          name = "libmsd_intel.so"
+        },
+      ]
+    }
+  }
+}
+
+package("nonhardware-tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  if (build_intel_gen) {
+    deps = [
+      "$mesa_build_root:tests",
+      "$msd_intel_gen_build_root:tests",
+    ]
+
+    tests = [
+      {
+        name = "msd_intel_gen_nonhardware_tests"
+      },
+      {
+        name = "mesa_unit_tests"
+      },
+      {
+        name = "state_pool"
+      },
+      {
+        name = "state_pool_free_list_only"
+      },
+      {
+        name = "state_pool_no_free"
+      },
+      {
+        name = "block_pool_no_free"
+      },
+    ]
+  }
+}
+
+package("tests") {
+  testonly = true
+  deprecated_system_image = true
+
+  if (build_intel_gen) {
+    deps = [
+      ":autorun",
+      "$mesa_build_root:tests",
+      "//garnet/drivers/gpu/msd-intel-gen/tests/integration",
+    ]
+
+    tests = [
+      {
+        name = "test_wsi_magma"
+      },
+      {
+        name = "msd_intel_gen_integration_tests"
+      },
+    ]
+
+    binaries = [
+      {
+        name = "autorun"
+        dest = "magma_autorun"
+      },
+    ]
+  }
+}
+
+copy("autorun") {
+  sources = [
+    "$magma_build_root/scripts/autorun",
+  ]
+  outputs = [
+    "$root_out_dir/autorun",
+  ]
+}
diff --git a/lib/magma/gnbuild/magma-vsl-gc/BUILD.gn b/lib/magma/gnbuild/magma-vsl-gc/BUILD.gn
new file mode 100644
index 0000000..1896cc2
--- /dev/null
+++ b/lib/magma/gnbuild/magma-vsl-gc/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+import("//garnet/lib/magma/gnbuild/magma.gni")
+
+package("magma-vsl-gc") {
+  if (build_vsl_gc) {
+    deprecated_system_image = true
+    if (magma_enable_developer_build) {
+      testonly = true
+    }
+
+    deps = []
+
+    if (magma_enable_developer_build) {
+      deps += [ "//garnet/drivers/gpu/msd-vsl-gc:msd_vsl_test" ]
+      drivers = [
+        {
+          name = "libmsd_vsl_test.so"
+        },
+      ]
+    } else {
+      deps += [ "//garnet/drivers/gpu/msd-vsl-gc:msd_vsl" ]
+      drivers = [
+        {
+          name = "libmsd_vsl.so"
+        },
+      ]
+    }
+  }
+}
diff --git a/lib/magma/gnbuild/magma.gni b/lib/magma/gnbuild/magma.gni
index 5148571..ed3373e 100644
--- a/lib/magma/gnbuild/magma.gni
+++ b/lib/magma/gnbuild/magma.gni
@@ -18,24 +18,13 @@
   # automatically when the driver starts.
   magma_enable_developer_build = false
 
-  # This is a list of targets that will be built as drivers. If more than one
-  # target is given then use_vulkan_loader_for_tests must be set to true, as
-  # otherwise tests won't know which libvulkan to use. Example gn arg:
-  # build_libvulkan_arm_mali =
-  # ["//third_party/arm-mali-bifrost:libvulkan_arm"]
-  build_libvulkan_arm_mali = []
-
   build_msd_arm_mali = target_cpu == "arm64"
-  build_msd_vsl_gc = false
+  build_vsl_gc = target_cpu == "arm64"
   build_intel_gen = target_cpu == "x64"
-
+  
   prebuilt_libvulkan_arm_path = ""
 }
 
-have_prebuilt_libvulkan_arm = prebuilt_libvulkan_arm_path != ""
-have_libvulkan = build_intel_gen || build_libvulkan_arm_mali != [] ||
-                 have_prebuilt_libvulkan_arm
-
 declare_args() {
   # Mesa doesn't properly handle loader-less operation;
   # their GetInstanceProcAddr implementation returns 0 for some interfaces.
@@ -43,11 +32,20 @@
   # to.
   use_vulkan_loader_for_tests = true
 
+  # This is a list of targets that will be built as vulkan ICDS. If more than one
+  # target is given then use_vulkan_loader_for_tests must be set to true, as
+  # otherwise tests won't know which libvulkan to use.
+  build_libvulkan = []
+
   if (build_intel_gen) {
     mesa_build_root = "//third_party/mesa"
+    build_libvulkan += [ "//third_party/mesa:magma_vulkan" ]
   }
 }
 
+have_prebuilt_libvulkan_arm = prebuilt_libvulkan_arm_path != ""
+have_libvulkan = build_libvulkan != [] || have_prebuilt_libvulkan_arm
+
 template("magma_pci_entry") {
   source_set(target_name) {
     assert(defined(invoker.pci_vendor_id), "pci_vendor_id not defined")
diff --git a/lib/magma/scripts/build-gfxbench.sh b/lib/magma/scripts/build-gfxbench.sh
deleted file mode 100755
index 8eef776..0000000
--- a/lib/magma/scripts/build-gfxbench.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-
-# Copyright 2017 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-fuchsia_root=`pwd`
-
-zircon_platform=${1:-x64}
-
-if [[ $zircon_platform == *"arm64" ]]; then
-	platform=arm64
-	shared_path=arm64
-	system_processor=aarch64
-else
-	platform=x64
-	shared_path=x64
-	system_processor=x86_64
-fi
-
-export VULKAN_INCLUDE_DIR=$fuchsia_root/third_party/vulkan_loader_and_validation_layers/include
-export VULKAN_LIB_PATH=$fuchsia_root/out/debug-$platform/$shared_path-shared
-export VULKAN_LIBRARY=$VULKAN_LIB_PATH/libvulkan.so
-unset EDITOR
-
-# CONFIG environment variable can be overridden.
-: "${CONFIG:=Debug}"
-ninja_path=$fuchsia_root/buildtools/ninja
-
-FUCHSIA_PLATFORM_OPTIONS="-DCMAKE_MAKE_PROGRAM=$ninja_path -DFUCHSIA_SYSTEM_PROCESSOR=$system_processor -DFUCHSIA_SYSROOT=$fuchsia_root/out/build-zircon/build-$zircon_platform/sysroot -DVULKAN_INCLUDE_DIR=$VULKAN_INCLUDE_DIR -DVULKAN_LIBRARY=$VULKAN_LIBRARY"
-
-cd third_party/gfxbench
-WORKSPACE=${PWD} PLATFORM=fuchsia CONFIG=$CONFIG FUCHSIA_TOOLCHAIN_FILE=$fuchsia_root/build/Fuchsia.cmake NG_CMAKE_GENERATOR="Ninja" NG_CMAKE_PLATFORM_OPT=$FUCHSIA_PLATFORM_OPTIONS scripts/build-3rdparty.sh
-WORKSPACE=${PWD} PLATFORM=fuchsia CONFIG=$CONFIG FUCHSIA_TOOLCHAIN_FILE=$fuchsia_root/build/Fuchsia.cmake NG_CMAKE_GENERATOR="Ninja" NG_CMAKE_PLATFORM_OPT=$FUCHSIA_PLATFORM_OPTIONS DISPLAY_PROTOCOL=MAGMA NO_GL=1 scripts/build.sh
-cd -
-
-echo --------------------------------------------------------------------------
-echo BUILD COMPLETE
-echo
-echo 'Copy to persistent storage on device (release build):'
-echo 'scp -r -F out/release-$platform/ssh-keys/ssh_config third_party/gfxbench/tfw-pkg [`out/build-zircon/tools/netaddr --fuchsia`]:/data'
-echo
-echo 'And execute:'
-echo "out/build-zircon/tools/netruncmd : '/data/tfw-pkg/bin/testfw_app -t vulkan_5_normal'"
-echo
-echo --------------------------------------------------------------------------
diff --git a/lib/magma/scripts/build.sh b/lib/magma/scripts/build.sh
deleted file mode 100755
index 46c2528..0000000
--- a/lib/magma/scripts/build.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-
-# Copyright 2016 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-fuchsia_root=`pwd`
-tools_path=$fuchsia_root/buildtools
-zircon_build_dir=$fuchsia_root/out/build-zircon/build-x64
-build=debug
-bootfs=$fuchsia_root/out/user.bootfs
-
-if [ "$1" == "--debug" ]; then
-	build=debug
-else
-if [ "$1" == "--release" ]; then
-	build=release
-else
-if [ "$1" != "" ]; then
-	echo Unrecognized arg: $1
-	exit 1
-fi
-fi
-fi
-
-build_dir=$fuchsia_root/out/$build-x64
-
-args="msd_intel_wait_for_flip=true"
-args="$args magma_enable_tracing=false"
-
-packages="magma-dev"
-
-rm -f $bootfs
-cd $fuchsia_root
-$fuchsia_root/build/gn/gen.py --packages $packages --$build --args="$args" --ignore-skia --goma
-$fuchsia_root/buildtools/ninja -C $build_dir
-cp $build_dir/user.bootfs $bootfs
-
-echo "Recommended bootserver command:"
-echo ""
-echo "$zircon_build_dir/tools/bootserver $zircon_build_dir/zircon.bin $fuchsia_root/out/user.bootfs -- zircon.autorun.system=/system/bin/magma_autorun"
-echo ""
-echo "Recommended loglistener command:"
-echo ""
-echo "$zircon_build_dir/tools/loglistener | grep --line-buffered -F -f $fuchsia_root/magma/scripts/test_patterns.txt"
-echo ""
diff --git a/lib/magma/scripts/reboot.sh b/lib/magma/scripts/reboot.sh
deleted file mode 100755
index bced4e9..0000000
--- a/lib/magma/scripts/reboot.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-# Copyright 2016 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-fuchsia_root=`pwd`
-zircon_build_dir=$fuchsia_root/out/build-zircon/build-x64
-netcp=$zircon_build_dir/tools/netcp
-netruncmd=$zircon_build_dir/tools/netruncmd
-
-$netruncmd : 'dm reboot'
diff --git a/lib/magma/scripts/test_patterns.txt b/lib/magma/scripts/test_patterns.txt
deleted file mode 100644
index 4342388..0000000
--- a/lib/magma/scripts/test_patterns.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-[  FAILED  ]
-[  PASSED  ]
-[==========]
-[APP START=]
-[SYS START=]
-[DRV START=]
-[ABI START=]
-[MESA START]
-[APP END===]
-[SYS END===]
-[DRV END===]
-[ABI END===]
-[MESA END==]
-Assertion failed:
-<== fatal exception
-<== fatal page fault
\ No newline at end of file
diff --git a/lib/magma/scripts/vulkancts/README.md b/lib/magma/scripts/vulkancts/README.md
deleted file mode 100644
index fd377bc..0000000
--- a/lib/magma/scripts/vulkancts/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
-1. Ensure cmake is in your path
-
-2. Create /data persistent storage filesystem on Acer internal ssd
-
-NOTE: assumes you have a usb device at /dev/class/block/000
-
-netruncmd zircon 'minfs /dev/class/block/001 mkfs'
-
-then reboot
-
-3. Build and copy binaries
-
-magma/scripts/vulkancts/build.sh && magma/scripts/vulkancts/copy.sh
-
-4. Make sure netstack is running
-
-netstack&
-
-5. Execute
-
-netruncmd : '/data/vulkancts/run.sh'
diff --git a/lib/magma/scripts/vulkancts/build.sh b/lib/magma/scripts/vulkancts/build.sh
deleted file mode 100755
index c1620c2..0000000
--- a/lib/magma/scripts/vulkancts/build.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/bash
-
-# Copyright 2016 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-fuchsia_root=`pwd`
-tools_path=$fuchsia_root/buildtools
-build=${1:-debug-x64}
-build_dir=$fuchsia_root/out/build-vulkancts-$build
-cc=$fuchsia_root/`find buildtools -type l -name "clang"`
-cxx=$fuchsia_root/`find buildtools -type l -name "clang++"`
-objcopy=$fuchsia_root/`find buildtools -name "llvm-objcopy"`
-ar=$fuchsia_root/`find buildtools -name "llvm-ar"`
-ranlib=$fuchsia_root/`find buildtools -name "llvm-ranlib"`
-sysroot=$fuchsia_root/out/$build/sdks/zircon_sysroot/sysroot
-
-if [ ! -d "$sysroot" ]; then
-	echo "Can't find sysroot: $sysroot"
-	exit 1
-fi
-
-if [[ $build == *"arm64" ]]; then
-	extra_args="-DFUCHSIA_SYSTEM_PROCESSOR=aarch64 -DDE_CPU=DE_CPU_ARM_64 -DDE_PTR_SIZE=8"
-else
-	extra_args="-DFUCHSIA_SYSTEM_PROCESSOR=x86_64"
-fi
-
-pushd $fuchsia_root/third_party/vulkan-cts
-python external/fetch_sources.py
-popd
-
-# builds the test executable for the host in order to write out test cases
-pushd $fuchsia_root/third_party/vulkan-cts
-mkdir -p cases
-python scripts/build_caselists.py cases
-popd
-
-mkdir -p $build_dir
-pushd $build_dir
-cmake $fuchsia_root/third_party/vulkan-cts -GNinja  -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=$tools_path/ninja -DFUCHSIA_SYSROOT=$sysroot -DCMAKE_TOOLCHAIN_FILE=$fuchsia_root/build/Fuchsia.cmake -DDE_OS=DE_OS_FUCHSIA -DDEQP_TARGET=fuchsia $extra_args
-$tools_path/ninja
-$objcopy --strip-sections $build_dir/external/vulkancts/modules/vulkan/deqp-vk $build_dir/external/vulkancts/modules/vulkan/deqp-vk-stripped
-popd
diff --git a/lib/magma/scripts/vulkancts/copy.sh b/lib/magma/scripts/vulkancts/copy.sh
deleted file mode 100755
index 6787ef9..0000000
--- a/lib/magma/scripts/vulkancts/copy.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-# Copyright 2016 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-fuchsia_root=`pwd`
-tools_path=$fuchsia_root/buildtools
-build=${1:-debug-x64}
-build_dir=$fuchsia_root/out/build-vulkancts-$build
-dest_dir=/data/vulkancts
-netaddr=$fuchsia_root/out/build-zircon/tools/netaddr
-
-ssh_config="-F $fuchsia_root/out/$build/ssh-keys/ssh_config"
-
-ssh $ssh_config `$netaddr --fuchsia` mkdir -p $dest_dir
-scp $ssh_config $build_dir/external/vulkancts/modules/vulkan/deqp-vk-stripped [`$netaddr --fuchsia`]:$dest_dir/deqp-vk
-scp $ssh_config third_party/vulkan-cts/external/vulkancts/mustpass/1.0.2/vk-default.txt [`$netaddr --fuchsia`]:$dest_dir/vk-default.txt
-scp $ssh_config -pr $fuchsia_root/third_party/vulkan-cts/external/vulkancts/data/* [`$netaddr --fuchsia`]:$dest_dir
-scp $ssh_config $fuchsia_root/garnet/lib/magma/scripts/vulkancts/run.sh [`$netaddr --fuchsia`]:$dest_dir
-scp $ssh_config $build_dir/executor/executor [`$netaddr --fuchsia`]:$dest_dir
-scp $ssh_config $build_dir/execserver/execserver [`$netaddr --fuchsia`]:$dest_dir
-scp $ssh_config third_party/vulkan-cts/cases/dEQP-VK-cases.xml [`$netaddr --fuchsia`]:$dest_dir/
diff --git a/lib/magma/scripts/vulkancts/run.sh b/lib/magma/scripts/vulkancts/run.sh
deleted file mode 100755
index 23f74d0..0000000
--- a/lib/magma/scripts/vulkancts/run.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/boot/bin/sh
-
-# Copyright 2016 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-set -e
-common='/data/vulkancts/executor -s /data/vulkancts/execserver -b /data/vulkancts/deqp-vk --caselistdir=/data/vulkancts'
-
-$common --testset=dEQP-VK.info.*
-$common --testset=dEQP-VK.api.smoke.*
-$common --testset=dEQP-VK.api.info.*
-$common --testset=dEQP-VK.api.device_init.*
-$common --testset=dEQP-VK.api.object_management.*
-$common --testset=dEQP-VK.api.buffer.*
-$common --testset=dEQP-VK.api.buffer_view.*
-$common --testset=dEQP-VK.api.command_buffers.*
-$common --testset=dEQP-VK.api.copy_and_blit.*
-$common --testset=dEQP-VK.api.image_clearing.*
-$common --testset=dEQP-VK.api.fill_and_update_buffer.*
-$common --testset=dEQP-VK.api.descriptor_pool.*
-$common --testset=dEQP-VK.memory.*
-$common --testset=dEQP-VK.pipeline.*
-$common --testset=dEQP-VK.binding_model.*
-$common --testset=dEQP-VK.spirv_assembly.*
-$common --testset=dEQP-VK.glsl.*
-$common --testset=dEQP-VK.renderpass.*
-$common --testset=dEQP-VK.ubo.*
-$common --testset=dEQP-VK.ssbo.*
-$common --testset=dEQP-VK.query_pool.*
-$common --testset=dEQP-VK.draw.*
-$common --testset=dEQP-VK.compute.*
-$common --testset=dEQP-VK.image.*
-$common --testset=dEQP-VK.wsi.*
-$common --testset=dEQP-VK.synchronization.*
-$common --testset=dEQP-VK.sparse_resources.*
-$common --testset=dEQP-VK.tessellation.*
-$common --testset=dEQP-VK.rasterization.*
-$common --testset=dEQP-VK.clipping.*
diff --git a/lib/magma/src/libmagma/BUILD.gn b/lib/magma/src/libmagma/BUILD.gn
index 2630ea3..cfca87f 100644
--- a/lib/magma/src/libmagma/BUILD.gn
+++ b/lib/magma/src/libmagma/BUILD.gn
@@ -5,8 +5,6 @@
 import("//garnet/lib/magma/gnbuild/magma.gni")
 
 shared_library("libmagma") {
-  visibility = [ "$magma_build_root:libmagma" ]
-
   output_name = "magma"
 
   public_deps = [
diff --git a/lib/magma/src/magma_util/platform/zircon/zircon_platform_buffer.cc b/lib/magma/src/magma_util/platform/zircon/zircon_platform_buffer.cc
index 90ef280..a75d506 100644
--- a/lib/magma/src/magma_util/platform/zircon/zircon_platform_buffer.cc
+++ b/lib/magma/src/magma_util/platform/zircon/zircon_platform_buffer.cc
@@ -3,14 +3,15 @@
 // found in the LICENSE file.
 
 #include "zircon_platform_buffer.h"
-#include "fdio/io.h"
+
 #include "platform_trace.h"
 #include "zircon_platform_handle.h"
 #include <ddk/driver.h>
-#include <limits.h> // PAGE_SIZE
-#include <map>
+#include <lib/fdio/io.h>
 #include <lib/zx/vmar.h>
 #include <lib/zx/vmo.h>
+#include <limits.h> // PAGE_SIZE
+#include <map>
 #include <vector>
 
 namespace magma {
diff --git a/lib/magma/src/magma_util/platform/zircon/zircon_platform_connection.cc b/lib/magma/src/magma_util/platform/zircon/zircon_platform_connection.cc
index 457ebca..82cde02 100644
--- a/lib/magma/src/magma_util/platform/zircon/zircon_platform_connection.cc
+++ b/lib/magma/src/magma_util/platform/zircon/zircon_platform_connection.cc
@@ -7,7 +7,7 @@
 
 #include <list>
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <lib/zx/channel.h>
 #include <zircon/syscalls.h>
 #include <zircon/types.h>
diff --git a/lib/magma/tests/BUILD.gn b/lib/magma/tests/BUILD.gn
index 1b9264a..24cc7d0 100644
--- a/lib/magma/tests/BUILD.gn
+++ b/lib/magma/tests/BUILD.gn
@@ -9,212 +9,101 @@
   testonly = true
   deprecated_system_image = true
 
-  deps = []
+  deps = [
+    "unit_tests",
+  ]
 
   if (have_libvulkan || use_vulkan_loader_for_tests) {
-    deps += [ ":tests" ]
-    if (build_intel_gen) {
-      deps += [
-        "$mesa_build_root:tests",
-        "$msd_intel_gen_build_root:msd_intel_test",
-        "$msd_intel_gen_build_root:tests",
-        "//garnet/drivers/gpu/msd-intel-gen/tests/integration",
-      ]
-    }
-  }
-  if (build_msd_arm_mali) {
     deps += [
-      "unit_tests:magma_unit_tests",
-      "//garnet/drivers/gpu/msd-arm-mali:tests",
-      "//garnet/drivers/gpu/msd-arm-mali/tests/integration",
-    ]
-  }
-}
-
-package("magma-nonhardware-tests") {
-  testonly = true
-  deprecated_system_image = true
-
-  deps = []
-  tests = []
-
-  # Tests that only depend on the msd.
-  if (build_msd_arm_mali || build_intel_gen) {
-    deps += [ "unit_tests:magma_unit_tests" ]
-
-    tests += [
-      {
-        name = "magma_unit_tests"
-      },
+      "benchmark",
+      "vkcube",
+      "vkext",
+      "vkloop",
+      "vkreadback",
     ]
   }
 
   if (build_intel_gen) {
     deps += [
       "$mesa_build_root:tests",
+      "$msd_intel_gen_build_root:msd_intel_test",
       "$msd_intel_gen_build_root:tests",
-    ]
-
-    tests += [
-      {
-        name = "msd_intel_gen_nonhardware_tests"
-      },
-      {
-        name = "mesa_unit_tests"
-      },
-      {
-        name = "state_pool"
-      },
-      {
-        name = "state_pool_free_list_only"
-      },
-      {
-        name = "state_pool_no_free"
-      },
-      {
-        name = "block_pool_no_free"
-      },
+      "//garnet/drivers/gpu/msd-intel-gen/tests/integration",
     ]
   }
-
   if (build_msd_arm_mali) {
-    deps += [ "//garnet/drivers/gpu/msd-arm-mali:tests" ]
-    tests += [
-      {
-        name = "msd_arm_mali_nonhardware_tests"
-      },
+    deps += [
+      "//garnet/drivers/gpu/msd-arm-mali:msd_arm_test",
+      "//garnet/drivers/gpu/msd-arm-mali:tests",
+      "//garnet/drivers/gpu/msd-arm-mali/tests/integration",
+    ]
+  }
+  if (build_vsl_gc) {
+    deps += [
+      "//garnet/drivers/gpu/msd-vsl-gc:msd_vsl_test",
     ]
   }
 }
 
-package("magma-test") {
+package("nonhardware-tests") {
   testonly = true
   deprecated_system_image = true
 
-  deps = []
-  tests = []
+  deps = [
+    "unit_tests",
+  ]
 
-  # Tests that only depend on the msd.
-  if (build_msd_arm_mali || build_intel_gen) {
-    deps += [
-      "integration",
-      "unit_tests:magma_unit_tests",
-    ]
+  tests = [
+    {
+      name = "magma_unit_tests"
+    },
+  ]
+}
 
-    tests += [
-      {
-        name = "magma_abi_conformance_tests"
-      },
-    ]
-  }
+package("tests") {
+  testonly = true
+  deprecated_system_image = true
 
-  # Tests that depend on libvulkan existing.
+  deps = [
+    "integration",
+  ]
+
+  tests = [
+    {
+      name = "magma_abi_conformance_tests"
+    },
+  ]
+}
+
+package("vulkan-tests") {
+  testonly = true
+  deprecated_system_image = true
+
   if (have_libvulkan || use_vulkan_loader_for_tests) {
-    deps += [ ":tests" ]
-
-    tests += [
-      {
-        name = "magma_memcpy"
-      },
-
-      {
-        name = "vkreadback"
-      },
-
-      {
-        name = "vkloop"
-      },
-
-      {
-        name = "vkext"
-      },
-
-      {
-        name = "vkcopy"
-      },
-    ]
-
-    if (build_intel_gen) {
-      deps += [
-        ":autorun",
-        "$mesa_build_root:tests",
-        "//garnet/drivers/gpu/msd-intel-gen/tests/integration",
-      ]
-
-      tests += [
-        {
-          name = "test_wsi_magma"
-        },
-
-        {
-          name = "msd_intel_gen_integration_tests"
-        },
-      ]
-
-      binaries = [
-        {
-          name = "autorun"
-          dest = "magma_autorun"
-        },
-      ]
-    }
-  }
-
-  if (build_msd_arm_mali) {
-    deps += [
-      ":autorun_mali",
-      "//garnet/drivers/gpu/msd-arm-mali/tests/integration",
-    ]
-    tests += [
-      {
-        name = "msd_arm_mali_integration_tests"
-      },
-    ]
-
-    binaries = [
-      {
-        name = "autorun_mali"
-        dest = "magma_autorun"
-      },
-    ]
-  }
-}
-
-if (build_msd_arm_mali) {
-  copy("autorun_mali") {
-    sources = [
-      "//garnet/lib/magma/scripts/autorun_mali",
-    ]
-    outputs = [
-      "$root_out_dir/autorun_mali",
-    ]
-  }
-}
-
-if (build_intel_gen) {
-  copy("autorun") {
-    sources = [
-      "$magma_build_root/scripts/autorun",
-    ]
-    outputs = [
-      "$root_out_dir/autorun",
-    ]
-  }
-}
-
-if (have_libvulkan || use_vulkan_loader_for_tests) {
-  group("tests") {
-    testonly = true
-
-    public_configs = [ "$magma_build_root:magma_tests_include_config" ]
-
-    public_deps = [
+    deps = [
       "benchmark",
-      "unit_tests:magma_unit_tests",
       "vkcube",
       "vkext",
       "vkloop",
       "vkreadback",
     ]
+
+    tests = [
+      {
+        name = "magma_memcpy"
+      },
+      {
+        name = "vkreadback"
+      },
+      {
+        name = "vkloop"
+      },
+      {
+        name = "vkext"
+      },
+      {
+        name = "vkcopy"
+      },
+    ]
   }
 }
diff --git a/lib/magma/tests/integration/BUILD.gn b/lib/magma/tests/integration/BUILD.gn
index aca906d..97822a5 100644
--- a/lib/magma/tests/integration/BUILD.gn
+++ b/lib/magma/tests/integration/BUILD.gn
@@ -22,7 +22,7 @@
   ]
 
   deps = [
-    "$magma_build_root:libmagma",
+    "$magma_build_root/src/libmagma",
     "$magma_build_root/include:magma_abi",
     "$magma_build_root/src/magma_util/platform:buffer",
     "//third_party/googletest:gtest",
diff --git a/lib/magma/tests/unit_tests/BUILD.gn b/lib/magma/tests/unit_tests/BUILD.gn
index 2c0e930..9e4495c 100644
--- a/lib/magma/tests/unit_tests/BUILD.gn
+++ b/lib/magma/tests/unit_tests/BUILD.gn
@@ -4,8 +4,9 @@
 
 import("//garnet/lib/magma/gnbuild/magma.gni")
 
-executable("magma_unit_tests") {
+executable("unit_tests") {
   testonly = true
+  output_name = "magma_unit_tests"
 
   sources = [
     "main.cc",
diff --git a/lib/magma/tests/vkreadback/vkreadback.cc b/lib/magma/tests/vkreadback/vkreadback.cc
index 561c9d5..35ede46 100644
--- a/lib/magma/tests/vkreadback/vkreadback.cc
+++ b/lib/magma/tests/vkreadback/vkreadback.cc
@@ -8,6 +8,7 @@
 #else
 #include <vulkan/vulkan.h>
 #endif
+#include <lib/fdio/io.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -15,7 +16,6 @@
 #include <vector>
 #include <zircon/syscalls.h>
 
-#include "fdio/io.h"
 #include "magma_util/dlog.h"
 #include "magma_util/macros.h"
 
diff --git a/lib/magma/tests/vulkan_shim/BUILD.gn b/lib/magma/tests/vulkan_shim/BUILD.gn
index 2312665..fd5bef8 100644
--- a/lib/magma/tests/vulkan_shim/BUILD.gn
+++ b/lib/magma/tests/vulkan_shim/BUILD.gn
@@ -7,7 +7,9 @@
 config("vulkan_shim_config") {
   include_dirs = [ "." ]
   defines = [ "MAGMA_USE_SHIM" ]
-  configs = [ "//third_party/vulkan_loader_and_validation_layers:vulkan_build_config" ]
+  configs = [
+    "//third_party/vulkan_loader_and_validation_layers:vulkan_build_config",
+  ]
 }
 
 source_set("vulkan_shim") {
@@ -18,7 +20,5 @@
     "vulkan_shim.h",
   ]
 
-  public_deps = [
-    "$magma_build_root:libvulkan",
-  ]
+  public_deps = build_libvulkan
 }
diff --git a/lib/media/client/audio_output_stream.cc b/lib/media/client/audio_output_stream.cc
index 2b88cba..208e349 100644
--- a/lib/media/client/audio_output_stream.cc
+++ b/lib/media/client/audio_output_stream.cc
@@ -12,7 +12,7 @@
 #include "garnet/lib/media/client/audio_output_device.h"
 #include "garnet/lib/media/client/audio_output_manager.h"
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include "lib/app/cpp/environment_services.h"
 #include "lib/fidl/cpp/synchronous_interface_ptr.h"
 #include "lib/fxl/logging.h"
@@ -58,7 +58,7 @@
 };
 
 bool AudioOutputStream::AcquireRenderer() {
-  media::AudioServerSyncPtr audio_server;
+  fuchsia::media::AudioServerSyncPtr audio_server;
   fuchsia::sys::ConnectToEnvironmentService(audio_server.NewRequest());
 
   if (!audio_server->CreateRenderer(audio_renderer_.NewRequest(),
@@ -71,10 +71,12 @@
 }
 
 bool AudioOutputStream::SetMediaType(int num_channels, int sample_rate) {
-  if ((num_channels < static_cast<int>(media::kMinLpcmChannelCount)) ||
-      (num_channels > static_cast<int>(media::kMaxLpcmChannelCount)) ||
-      (sample_rate < static_cast<int>(media::kMinLpcmFramesPerSecond)) ||
-      (sample_rate > static_cast<int>(media::kMaxLpcmFramesPerSecond))) {
+  if ((num_channels < static_cast<int>(fuchsia::media::kMinLpcmChannelCount)) ||
+      (num_channels > static_cast<int>(fuchsia::media::kMaxLpcmChannelCount)) ||
+      (sample_rate <
+       static_cast<int>(fuchsia::media::kMinLpcmFramesPerSecond)) ||
+      (sample_rate >
+       static_cast<int>(fuchsia::media::kMaxLpcmFramesPerSecond))) {
     FXL_LOG(ERROR) << "Media type (" << num_channels << "-chan, " << sample_rate
                    << " Hz) out of range";
     return false;
@@ -82,14 +84,14 @@
 
   FXL_DCHECK(media_renderer_);
 
-  media::AudioMediaTypeDetails details;
-  details.sample_format = media::AudioSampleFormat::FLOAT;
+  fuchsia::media::AudioMediaTypeDetails details;
+  details.sample_format = fuchsia::media::AudioSampleFormat::FLOAT;
   details.channels = num_channels;
   details.frames_per_second = sample_rate;
 
-  media::MediaType media_type;
-  media_type.medium = media::MediaTypeMedium::AUDIO;
-  media_type.encoding = media::kAudioEncodingLpcm;
+  fuchsia::media::MediaType media_type;
+  media_type.medium = fuchsia::media::MediaTypeMedium::AUDIO;
+  media_type.encoding = fuchsia::media::kAudioEncodingLpcm;
   media_type.details.set_audio(std::move(details));
 
   if (!media_renderer_->SetMediaType(std::move(media_type))) {
@@ -161,10 +163,9 @@
       (current_sample_offset_ + num_samples) % total_mapping_samples_;
 }
 
-media::MediaPacket AudioOutputStream::CreateMediaPacket(zx_time_t pts,
-                                                        size_t payload_offset,
-                                                        size_t payload_size) {
-  media::MediaPacket packet;
+fuchsia::media::MediaPacket AudioOutputStream::CreateMediaPacket(
+    zx_time_t pts, size_t payload_offset, size_t payload_size) {
+  fuchsia::media::MediaPacket packet;
 
   packet.pts_rate_ticks = sample_rate_;
   packet.pts_rate_seconds = 1;
@@ -177,7 +178,7 @@
   return packet;
 }
 
-bool AudioOutputStream::SendMediaPacket(media::MediaPacket packet) {
+bool AudioOutputStream::SendMediaPacket(fuchsia::media::MediaPacket packet) {
   FXL_DCHECK(packet_consumer_);
 
   return packet_consumer_->SupplyPacketNoReply(std::move(packet));
@@ -199,7 +200,7 @@
     return ZX_ERR_CONNECTION_ABORTED;
   }
 
-  if (db_gain > media::kMaxGain) {
+  if (db_gain > fuchsia::media::kMaxGain) {
     return ZX_ERR_OUT_OF_RANGE;
   }
 
@@ -221,9 +222,11 @@
   FXL_DCHECK(num_samples > 0);
   FXL_DCHECK(num_samples % num_channels_ == 0);
 
-  if (!active_) return ZX_ERR_CONNECTION_ABORTED;
+  if (!active_)
+    return ZX_ERR_CONNECTION_ABORTED;
 
-  if (num_samples > total_mapping_samples_) return ZX_ERR_OUT_OF_RANGE;
+  if (num_samples > total_mapping_samples_)
+    return ZX_ERR_OUT_OF_RANGE;
 
   if (pres_time == FUCHSIA_AUDIO_NO_TIMESTAMP && !received_first_frame_)
     return ZX_ERR_BAD_STATE;
@@ -242,7 +245,7 @@
 
   // On first packet, establish a timeline starting at given presentation time.
   // Others get kNoTimestamp, indicating 'play without gap after the previous'.
-  zx_time_t subject_time = media::kNoTimestamp;
+  zx_time_t subject_time = fuchsia::media::kNoTimestamp;
   if (!received_first_frame_) {
     subject_time = 0;
     start_time_ = pres_time;
@@ -274,10 +277,10 @@
 }
 
 bool AudioOutputStream::Start() {
-  media::TimelineConsumerSyncPtr timeline_consumer;
+  fuchsia::media::TimelineConsumerSyncPtr timeline_consumer;
   timeline_control_point_->GetTimelineConsumer(timeline_consumer.NewRequest());
 
-  media::TimelineTransform transform;
+  fuchsia::media::TimelineTransform transform;
   transform.reference_time = start_time_;
   transform.subject_time = 0;
   transform.reference_delta = 1;
@@ -290,12 +293,12 @@
   received_first_frame_ = false;
   active_ = false;
 
-  media::TimelineConsumerSyncPtr timeline_consumer;
+  fuchsia::media::TimelineConsumerSyncPtr timeline_consumer;
   timeline_control_point_->GetTimelineConsumer(timeline_consumer.NewRequest());
 
-  media::TimelineTransform transform;
-  transform.reference_time = media::kUnspecifiedTime;
-  transform.subject_time = media::kUnspecifiedTime;
+  fuchsia::media::TimelineTransform transform;
+  transform.reference_time = fuchsia::media::kUnspecifiedTime;
+  transform.subject_time = fuchsia::media::kUnspecifiedTime;
   transform.reference_delta = 1;
   transform.subject_delta = 0;
 
diff --git a/lib/media/client/audio_output_stream.h b/lib/media/client/audio_output_stream.h
index d87f7ba..093c233 100644
--- a/lib/media/client/audio_output_stream.h
+++ b/lib/media/client/audio_output_stream.h
@@ -9,7 +9,7 @@
 
 #include "garnet/lib/media/client/audio_output_device.h"
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include "lib/media/c/audio.h"
 
 namespace media_client {
@@ -36,14 +36,15 @@
   bool GetDelays();
 
   void PullFromClientBuffer(float* client_buffer, int num_samples);
-  media::MediaPacket CreateMediaPacket(zx_time_t pts, size_t payload_offset,
-                                       size_t payload_size);
-  bool SendMediaPacket(media::MediaPacket packet);
+  fuchsia::media::MediaPacket CreateMediaPacket(zx_time_t pts,
+                                                size_t payload_offset,
+                                                size_t payload_size);
+  bool SendMediaPacket(fuchsia::media::MediaPacket packet);
 
-  media::AudioRendererSyncPtr audio_renderer_;
-  media::MediaRendererSyncPtr media_renderer_;
-  media::MediaPacketConsumerSyncPtr packet_consumer_;
-  media::MediaTimelineControlPointSyncPtr timeline_control_point_;
+  fuchsia::media::AudioRendererSyncPtr audio_renderer_;
+  fuchsia::media::MediaRendererSyncPtr media_renderer_;
+  fuchsia::media::MediaPacketConsumerSyncPtr packet_consumer_;
+  fuchsia::media::MediaTimelineControlPointSyncPtr timeline_control_point_;
 
   zx::vmo vmo_;
   int total_mapping_samples_ = 0;
diff --git a/lib/media/wav_writer/wav_writer.cc b/lib/media/wav_writer/wav_writer.cc
index a663046..2b982a7 100644
--- a/lib/media/wav_writer/wav_writer.cc
+++ b/lib/media/wav_writer/wav_writer.cc
@@ -5,7 +5,7 @@
 #include "garnet/lib/media/wav_writer/wav_writer.h"
 #include <endian.h>
 #include <fcntl.h>
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <unistd.h>
 #include <zircon/compiler.h>
 #include <iomanip>
@@ -126,7 +126,8 @@
 // cursor is positioned immediately after the headers, at the correct location
 // to write any audio samples we are given.
 // This private function assumes the given file_desc is valid.
-zx_status_t WriteNewHeader(int file_desc, AudioSampleFormat sample_format,
+zx_status_t WriteNewHeader(int file_desc,
+                           fuchsia::media::AudioSampleFormat sample_format,
                            uint32_t channel_count, uint32_t frame_rate,
                            uint16_t bits_per_sample) {
   if (channel_count > std::numeric_limits<uint16_t>::max()) {
@@ -142,13 +143,14 @@
     return ZX_ERR_IO;
   }
 
-  if (sample_format == AudioSampleFormat::FLOAT) {
+  if (sample_format == fuchsia::media::AudioSampleFormat::FLOAT) {
     FXL_DCHECK(bits_per_sample == 32);
   }
 
   WavHeader wave_header;
   wave_header.format =
-      (sample_format == AudioSampleFormat::FLOAT) ? FORMAT_FLOAT : FORMAT_LPCM;
+      (sample_format == fuchsia::media::AudioSampleFormat::FLOAT) ? FORMAT_FLOAT
+                                                                  : FORMAT_LPCM;
   wave_header.channel_count = channel_count;
   wave_header.frame_rate = frame_rate;
   wave_header.frame_size = (bits_per_sample >> 3) * channel_count;
@@ -227,10 +229,10 @@
 // TODO(mpuryear): leverage utility code elsewhere for bytes-per-sample lookup,
 // for either FIDL-defined sample types and/or driver defined sample packings.
 template <bool enabled>
-bool WavWriter<enabled>::Initialize(const char* const file_name,
-                                    AudioSampleFormat sample_format,
-                                    uint32_t channel_count, uint32_t frame_rate,
-                                    uint32_t bits_per_sample) {
+bool WavWriter<enabled>::Initialize(
+    const char* const file_name,
+    fuchsia::media::AudioSampleFormat sample_format, uint32_t channel_count,
+    uint32_t frame_rate, uint32_t bits_per_sample) {
   // Open our output file.
   uint32_t instance_count = instance_count_.fetch_add(1);
   if (file_name == nullptr || strlen(file_name) == 0) {
diff --git a/lib/media/wav_writer/wav_writer.h b/lib/media/wav_writer/wav_writer.h
index 6022502..06853e4 100644
--- a/lib/media/wav_writer/wav_writer.h
+++ b/lib/media/wav_writer/wav_writer.h
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef GARNET_LIB_MEDIA_WAV_WRITER_WAV_WRITER_H_
+#define GARNET_LIB_MEDIA_WAV_WRITER_WAV_WRITER_H_
 
 #include <fbl/atomic.h>
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include <stdint.h>
 #include <zircon/types.h>
 #include <string>
@@ -42,7 +43,8 @@
 template <bool enabled = true>
 class WavWriter {
  public:
-  bool Initialize(const char* const file_name, AudioSampleFormat sample_format,
+  bool Initialize(const char* const file_name,
+                  fuchsia::media::AudioSampleFormat sample_format,
                   uint32_t channel_count, uint32_t frame_rate,
                   uint32_t bits_per_sample);
 
@@ -53,7 +55,7 @@
   bool Delete();
 
  private:
-  AudioSampleFormat sample_format_;
+  fuchsia::media::AudioSampleFormat sample_format_;
   uint32_t channel_count_ = 0;
   uint32_t frame_rate_ = 0;
   uint32_t bits_per_sample_ = 0;
@@ -68,8 +70,8 @@
 template <>
 class WavWriter<false> {
  public:
-  bool Initialize(const char* const, AudioSampleFormat, uint32_t, uint32_t,
-                  uint32_t) {
+  bool Initialize(const char* const, fuchsia::media::AudioSampleFormat,
+                  uint32_t, uint32_t, uint32_t) {
     return true;
   };
   bool Write(void* const, uint32_t) { return true; };
@@ -81,3 +83,5 @@
 
 }  // namespace audio
 }  // namespace media
+
+#endif  // GARNET_LIB_MEDIA_WAV_WRITER_WAV_WRITER_H_
diff --git a/lib/rust/crates/eapol/src/lib.rs b/lib/rust/crates/eapol/src/lib.rs
index bd59993..56148e7 100644
--- a/lib/rust/crates/eapol/src/lib.rs
+++ b/lib/rust/crates/eapol/src/lib.rs
@@ -8,6 +8,7 @@
 extern crate bitfield;
 extern crate byteorder;
 extern crate bytes;
+#[macro_use]
 extern crate failure;
 #[macro_use]
 extern crate nom;
@@ -27,7 +28,7 @@
 
 #[derive(Debug)]
 pub enum Frame {
-    Key(KeyFrame)
+    Key(KeyFrame),
 }
 
 // IEEE Std 802.1X-2010, 11.9, Table 11-5
@@ -116,13 +117,19 @@
 }
 
 impl KeyFrame {
-    pub fn to_bytes(&self, clear_mic: bool) -> BytesMut {
+    pub fn len(&self) -> usize {
         let static_part_len: usize = 35;
         let dynamic_part_len: usize =
             self.key_nonce.len() + self.key_iv.len() + self.key_mic.len() + self.key_data.len();
+        static_part_len + dynamic_part_len
+    }
 
-        let frame_len: usize = static_part_len + dynamic_part_len;
-        let mut buf = BytesMut::with_capacity(frame_len);
+    pub fn as_bytes(&self, clear_mic: bool, buf: &mut BytesMut) -> Result<(), failure::Error> {
+        let frame_len = self.len();
+        if buf.remaining_mut() < frame_len {
+            return Err(ErrorBufferTooSmall(frame_len, buf.remaining_mut()).into());
+        }
+
         buf.put_u8(self.version);
         buf.put_u8(self.packet_type);
         buf.put_u16_be(self.packet_body_len);
@@ -142,11 +149,13 @@
         }
         buf.put_u16_be(self.key_data_len);
         buf.put_slice(&self.key_data[..]);
-        buf
+        Ok(())
     }
 }
 
-fn to_array<A>(slice: &[u8]) -> A where A: Sized + Default + AsMut<[u8]>
+fn to_array<A>(slice: &[u8]) -> A
+    where
+        A: Sized + Default + AsMut<[u8]>,
 {
     let mut array = Default::default();
     <A as AsMut<[u8]>>::as_mut(&mut array).clone_from_slice(slice);
@@ -189,6 +198,10 @@
     )
 );
 
+#[derive(Debug, Fail)]
+#[fail(display = "buffer too small; required: {}, available: {}", _0, _1)]
+struct ErrorBufferTooSmall(usize, usize);
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -228,7 +241,7 @@
             0x00,
         ];
         let result = key_frame_from_bytes(&frame, 16);
-        assert_eq!(result.is_done(), false);
+        assert!(!result.is_done());
     }
 
     #[test]
@@ -244,7 +257,7 @@
             0x03, 0x01, 0x02, 0x03, 0x04,
         ];
         let result = key_frame_from_bytes(&frame, 16);
-        assert_eq!(result.is_done(), false);
+        assert!(!result.is_done());
     }
 
     #[test]
@@ -260,7 +273,7 @@
             0x03, 0x01,
         ];
         let result = key_frame_from_bytes(&frame, 16);
-        assert_eq!(result.is_done(), false);
+        assert!(!result.is_done());
     }
 
     #[test]
@@ -277,11 +290,11 @@
             0x00, 0x00, 0x03, 0x01, 0x02, 0x03,
         ];
         let result = key_frame_from_bytes(&frame, 32);
-        assert_eq!(result.is_done(), true);
+        assert!(result.is_done());
     }
 
     #[test]
-    fn test_to_bytes() {
+    fn test_as_bytes() {
         let frame: Vec<u8> = vec![
             0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
@@ -293,13 +306,40 @@
             0x03, 0x01, 0x02, 0x03,
         ];
         let result = key_frame_from_bytes(&frame, 16);
-        assert_eq!(result.is_done(), true);
+        assert!(result.is_done());
         let keyframe: KeyFrame = result.unwrap().1;
-        assert_eq!(frame, keyframe.to_bytes(false));
+        verify_as_bytes_result(keyframe, false, &frame[..]);
     }
 
     #[test]
-    fn test_to_bytes_dynamic_mic_size() {
+    fn test_as_bytes_too_small() {
+        let frame: Vec<u8> = vec![
+            0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x39, 0x5c, 0xc7, 0x6e, 0x1a, 0xe9, 0x9f, 0xa0, 0xb1, 0x22, 0x79,
+            0xfe, 0xc3, 0xb9, 0xa9, 0x9e, 0x1d, 0x9a, 0x21, 0xb8, 0x47, 0x51, 0x38, 0x98, 0x25,
+            0xf8, 0xc7, 0xca, 0x55, 0x86, 0xbc, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x03, 0x01, 0x02, 0x03,
+        ];
+        let result = key_frame_from_bytes(&frame, 16);
+        assert!(result.is_done());
+        let keyframe: KeyFrame = result.unwrap().1;
+
+        // Buffer is too small to write entire frame to.
+        let mut buf = BytesMut::with_capacity(frame.len() - 1);
+        let result = keyframe.as_bytes(false, &mut buf);
+        assert!(result.is_err());
+
+        // Sufficiently large buffer should work.
+        let mut buf = BytesMut::with_capacity(frame.len());
+        let result = keyframe.as_bytes(false, &mut buf);
+        assert!(result.is_ok());
+    }
+
+    #[test]
+    fn test_as_bytes_dynamic_mic_size() {
         let frame: Vec<u8> = vec![
             0x01, 0x03, 0x00, 0x6f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
@@ -312,13 +352,13 @@
             0x00, 0x00, 0x03, 0x01, 0x02, 0x03,
         ];
         let result = key_frame_from_bytes(&frame, 32);
-        assert_eq!(result.is_done(), true);
+        assert!(result.is_done());
         let keyframe: KeyFrame = result.unwrap().1;
-        assert_eq!(frame, keyframe.to_bytes(false));
+        verify_as_bytes_result(keyframe, false, &frame[..]);
     }
 
     #[test]
-    fn test_to_bytes_clear_mic() {
+    fn test_as_bytes_clear_mic() {
         #[cfg_attr(rustfmt, rustfmt_skip)]
         let frame: Vec<u8> = vec![
             0x01, 0x03, 0x00, 0x5f, 0x02, 0x00, 0x8a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -333,7 +373,7 @@
             0x00, 0x03, 0x01, 0x02, 0x03,
         ];
         let result = key_frame_from_bytes(&frame, 16);
-        assert_eq!(result.is_done(), true);
+        assert!(result.is_done());
         let keyframe: KeyFrame = result.unwrap().1;
 
         #[cfg_attr(rustfmt, rustfmt_skip)]
@@ -349,7 +389,17 @@
             0x00, 0x00,
             0x00, 0x03, 0x01, 0x02, 0x03,
         ];
-        assert_eq!(expected, keyframe.to_bytes(true));
+        verify_as_bytes_result(keyframe, true, &expected[..]);
+    }
+
+    fn verify_as_bytes_result(keyframe: KeyFrame, clear_mic: bool, expected: &[u8]) {
+        let mut buf = BytesMut::with_capacity(128);
+        let result = keyframe.as_bytes(clear_mic, &mut buf);
+        assert!(result.is_ok());
+        let written = buf.len();
+        let left_over = buf.split_off(written);
+        assert_eq!(&buf[..], expected);
+        assert!(left_over.iter().all(|b| *b == 0));
     }
 
     #[test]
@@ -365,7 +415,7 @@
             0x03, 0x01, 0x02, 0x03,
         ];
         let result = key_frame_from_bytes(&frame, 16);
-        assert_eq!(result.is_done(), true);
+        assert!(result.is_done());
         let keyframe: KeyFrame = result.unwrap().1;
         assert_eq!(keyframe.version, 1);
         assert_eq!(keyframe.packet_type, 3);
@@ -373,7 +423,7 @@
         assert_eq!(keyframe.descriptor_type, 2);
         assert_eq!(keyframe.key_info.value(), 0x008a);
         assert_eq!(keyframe.key_info.key_descriptor_version(), 2);
-        assert_eq!(keyframe.key_info.key_ack(), true);
+        assert!(keyframe.key_info.key_ack());
         assert_eq!(keyframe.key_len, 16);
         assert_eq!(keyframe.key_replay_counter, 1);
         let nonce: Vec<u8> = vec![
diff --git a/lib/rust/crates/fuchsia-bluetooth/src/error.rs b/lib/rust/crates/fuchsia-bluetooth/src/error.rs
index 47df8cf..4118c40 100644
--- a/lib/rust/crates/fuchsia-bluetooth/src/error.rs
+++ b/lib/rust/crates/fuchsia-bluetooth/src/error.rs
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use fidl_bluetooth;
+use fidl_fuchsia_bluetooth as bt;
 
 /// Error type that can be constructed from a Bluetooth FIDL Error or from on its own.
 #[derive(Debug, Fail)]
@@ -18,8 +18,8 @@
     }
 }
 
-impl From<fidl_bluetooth::Error> for Error {
-    fn from(err: fidl_bluetooth::Error) -> Error {
+impl From<bt::Error> for Error {
+    fn from(err: bt::Error) -> Error {
         Error {
             message: match err.description {
                 Some(d) => d,
diff --git a/lib/rust/crates/fuchsia-bluetooth/src/lib.rs b/lib/rust/crates/fuchsia-bluetooth/src/lib.rs
index 011e74e..3acb00e 100644
--- a/lib/rust/crates/fuchsia-bluetooth/src/lib.rs
+++ b/lib/rust/crates/fuchsia-bluetooth/src/lib.rs
@@ -15,8 +15,8 @@
 extern crate rand;
 
 extern crate fuchsia_zircon as zircon;
-extern crate fidl_bluetooth;
-extern crate fidl_bluetooth_control;
+extern crate fidl_fuchsia_bluetooth;
+extern crate fidl_fuchsia_bluetooth_control;
 
 /// Bluetooth Error type
 pub mod error;
diff --git a/lib/rust/crates/fuchsia-bluetooth/src/types.rs b/lib/rust/crates/fuchsia-bluetooth/src/types.rs
index 5ed8056..d4ba7ee 100644
--- a/lib/rust/crates/fuchsia-bluetooth/src/types.rs
+++ b/lib/rust/crates/fuchsia-bluetooth/src/types.rs
@@ -2,21 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use fidl_bluetooth;
+use fidl_fuchsia_bluetooth;
 use std::fmt;
 
 macro_rules! bt_fidl_wrap {
     ( $x:ident) => {
-            /// Wrapper for mapping fidl_bluetooth::$x to fuchsia_bluetooth::$x
-            pub struct $x(fidl_bluetooth::$x);
+            /// Wrapper for mapping fidl_fuchsia_bluetooth::$x to fuchsia_bluetooth::$x
+            pub struct $x(fidl_fuchsia_bluetooth::$x);
 
-            impl From<fidl_bluetooth::$x> for $x {
-                fn from(b: fidl_bluetooth::$x) -> $x {
+            impl From<fidl_fuchsia_bluetooth::$x> for $x {
+                fn from(b: fidl_fuchsia_bluetooth::$x) -> $x {
                     $x(b)
                 }
             }
-            impl Into<fidl_bluetooth::$x> for $x {
-                fn into(self) -> fidl_bluetooth::$x {
+            impl Into<fidl_fuchsia_bluetooth::$x> for $x {
+                fn into(self) -> fidl_fuchsia_bluetooth::$x {
                     self.0
                 }
             }
diff --git a/lib/rust/crates/fuchsia-bluetooth/src/util.rs b/lib/rust/crates/fuchsia-bluetooth/src/util.rs
index 44da7ce..10a0e9a 100644
--- a/lib/rust/crates/fuchsia-bluetooth/src/util.rs
+++ b/lib/rust/crates/fuchsia-bluetooth/src/util.rs
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use fidl_bluetooth;
-use fidl_bluetooth_control::{AdapterInfo, AdapterState};
+use fidl_fuchsia_bluetooth;
+use fidl_fuchsia_bluetooth_control::{AdapterInfo, AdapterState};
 
 /// Macro to help make cloning host dispatchers nicer
 #[macro_export]
@@ -19,30 +19,30 @@
 /// Two Args is the error type & a description
 #[macro_export]
 macro_rules! bt_fidl_status {
-    () => (fidl_bluetooth::Status { error: None } );
+    () => (fidl_fuchsia_bluetooth::Status { error: None } );
 
-    ($error_code:ident) => (fidl_bluetooth::Status { error: Some(Box::new(
-                    fidl_bluetooth::Error {
+    ($error_code:ident) => (fidl_fuchsia_bluetooth::Status { error: Some(Box::new(
+                    fidl_fuchsia_bluetooth::Error {
                         description: None,
                         protocol_error_code: 0,
-                        error_code: fidl_bluetooth::ErrorCode::$error_code,
+                        error_code: fidl_fuchsia_bluetooth::ErrorCode::$error_code,
                     }))
     });
 
-    ($error_code:ident, $description:expr) => (fidl_bluetooth::Status { error: Some(Box::new(
-                    fidl_bluetooth::Error {
+    ($error_code:ident, $description:expr) => (fidl_fuchsia_bluetooth::Status { error: Some(Box::new(
+                    fidl_fuchsia_bluetooth::Error {
                         description: Some($description.to_string()),
                         protocol_error_code: 0,
-                        error_code: fidl_bluetooth::ErrorCode::$error_code,
+                        error_code: fidl_fuchsia_bluetooth::ErrorCode::$error_code,
                     }))
     });
 }
 
 /// Clone Adapter Info
 /// Only here until Rust bindings can derive `Clone`
-pub fn clone_adapter_info(a: &AdapterInfo) -> AdapterInfo {
+pub fn clone_host_info(a: &AdapterInfo) -> AdapterInfo {
     let state = match a.state {
-        Some(ref s) => Some(Box::new(clone_adapter_state(&**s))),
+        Some(ref s) => Some(Box::new(clone_host_state(&**s))),
         None => None,
     };
     AdapterInfo {
@@ -55,13 +55,13 @@
 
 /// Clone Bluetooth Fidl bool type
 /// Only here until Rust bindings can derive `Clone`
-pub fn clone_bt_fidl_bool(a: &fidl_bluetooth::Bool) -> fidl_bluetooth::Bool {
-    fidl_bluetooth::Bool { value: a.value }
+pub fn clone_bt_fidl_bool(a: &fidl_fuchsia_bluetooth::Bool) -> fidl_fuchsia_bluetooth::Bool {
+    fidl_fuchsia_bluetooth::Bool { value: a.value }
 }
 
 /// Clone Adapter State
 /// Only here until Rust bindings can derive `Clone`
-pub fn clone_adapter_state(a: &AdapterState) -> AdapterState {
+pub fn clone_host_state(a: &AdapterState) -> AdapterState {
     let discoverable = match a.discoverable {
         Some(ref disc) => Some(Box::new(clone_bt_fidl_bool(disc))),
         None => None,
diff --git a/lib/rust/crates/fuchsia-wlan-dev/src/lib.rs b/lib/rust/crates/fuchsia-wlan-dev/src/lib.rs
index 915a1e4..fabfae4 100644
--- a/lib/rust/crates/fuchsia-wlan-dev/src/lib.rs
+++ b/lib/rust/crates/fuchsia-wlan-dev/src/lib.rs
@@ -9,7 +9,7 @@
 
 #[macro_use]
 extern crate fdio;
-extern crate fidl_wlan_device as wlan;
+extern crate fidl_fuchsia_wlan_device as wlan;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
 
diff --git a/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/mod.rs b/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/mod.rs
index e308b45..d9300eb 100644
--- a/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/mod.rs
+++ b/lib/rust/crates/wlan-rsn/src/key/exchange/handshake/fourway/mod.rs
@@ -18,6 +18,7 @@
 use rsna::{Role, SecAssocResult, SecAssocUpdate};
 use rsne::Rsne;
 use std::rc::Rc;
+use bytes::BytesMut;
 
 enum RoleHandler {
     Authenticator(Authenticator),
@@ -234,10 +235,13 @@
             match self.ptk.as_ref() {
                 None => Err(Error::UnexpectedMic.into()),
                 Some(ptk) => {
-                    let frame_bytes = frame.to_bytes(true);
+                    let mut buf = BytesMut::with_capacity(frame.len());
+                    frame.as_bytes(true, &mut buf)?;
+                    let written = buf.len();
+                    buf.truncate(written);
                     let valid_mic = akm.integrity_algorithm()
                         .ok_or(Error::UnsupportedAkmSuite)?
-                        .verify(ptk.kck(), &frame_bytes[..], &frame.key_mic[..]);
+                        .verify(ptk.kck(), &buf[..], &frame.key_mic[..]);
                     if !valid_mic {
                         Err(Error::InvalidMic)
                     } else {
diff --git a/lib/rust/crates/wlan-rsn/src/rsne.rs b/lib/rust/crates/wlan-rsn/src/rsne.rs
index c1c7f17..9f610c9 100644
--- a/lib/rust/crates/wlan-rsn/src/rsne.rs
+++ b/lib/rust/crates/wlan-rsn/src/rsne.rs
@@ -3,7 +3,8 @@
 // found in the LICENSE file.
 
 use akm;
-use bytes::Bytes;
+use bytes::{BufMut, Bytes, BytesMut};
+use failure::Error;
 use cipher;
 use pmkid;
 use suite_selector;
@@ -14,6 +15,16 @@
   ($i:expr, $f:expr) => ( cond!($i, $i.len() !=0, call!($f)); );
 );
 
+macro_rules! check_remaining (
+  ($required:expr, $remaining:expr) => {
+    if $remaining < $required {
+        return Err(ErrorBufferTooSmall($required, $remaining).into());
+    }
+  };
+);
+
+
+
 pub const ID: u8 = 48;
 
 // IEEE 802.11-2016, 9.4.2.25.1
@@ -25,14 +36,77 @@
     pub group_data_cipher_suite: Option<cipher::Cipher>,
     pub pairwise_cipher_suites: Vec<cipher::Cipher>,
     pub akm_suites: Vec<akm::Akm>,
-    pub rsn_capabilities: u16,
+    pub rsn_capabilities: Option<u16>,
     pub pmkids: Vec<pmkid::Pmkid>,
     pub group_mgmt_cipher_suite: Option<cipher::Cipher>,
 }
 
+impl Rsne {
+    pub fn as_bytes(&self, buf: &mut BytesMut) -> Result<(), Error> {
+        check_remaining!(4, buf.remaining_mut());
+        buf.put_u8(self.element_id);
+        buf.put_u8(self.length);
+        buf.put_u16_le(self.version);
+
+        match self.group_data_cipher_suite.as_ref() {
+            None => return Ok(()),
+            Some(cipher) => {
+                check_remaining!(4, buf.remaining_mut());
+                buf.put_slice(&cipher.oui[..]);
+                buf.put_u8(cipher.suite_type);
+            }
+        };
+
+        if self.pairwise_cipher_suites.is_empty() {
+            return Ok(());
+        }
+        check_remaining!(2 + 4 * self.pairwise_cipher_suites.len(), buf.remaining_mut());
+        buf.put_u16_le(self.pairwise_cipher_suites.len() as u16);
+        for cipher in &self.pairwise_cipher_suites {
+            buf.put_slice(&cipher.oui[..]);
+            buf.put_u8(cipher.suite_type);
+        }
+
+        if self.akm_suites.is_empty() {
+            return Ok(());
+        }
+        check_remaining!(2 + 4 * self.akm_suites.len(), buf.remaining_mut());
+        buf.put_u16_le(self.akm_suites.len() as u16);
+        for akm in &self.akm_suites {
+            buf.put_slice(&akm.oui[..]);
+            buf.put_u8(akm.suite_type);
+        }
+
+        match self.rsn_capabilities.as_ref() {
+            None => return Ok(()),
+            Some(caps) => {
+                check_remaining!(2, buf.remaining_mut());
+                buf.put_u16_le(*caps)
+            },
+        };
+
+        if self.pmkids.is_empty() {
+            return Ok(());
+        }
+        check_remaining!(2 + 16 * self.pmkids.len(), buf.remaining_mut());
+        buf.put_u16_le(self.pmkids.len() as u16);
+        for pmkid in &self.pmkids {
+            buf.put_slice(&pmkid[..]);
+        }
+
+        if let Some(cipher) = self.group_mgmt_cipher_suite.as_ref() {
+            check_remaining!(4, buf.remaining_mut());
+            buf.put_slice(&cipher.oui[..]);
+            buf.put_u8(cipher.suite_type);
+        }
+
+        Ok(())
+    }
+}
+
 fn read_suite_selector<'a, T>(input: &'a [u8]) -> IResult<&'a [u8], T>
-where
-    T: suite_selector::Factory<Suite = T>,
+    where
+        T: suite_selector::Factory<Suite = T>,
 {
     let (i1, bytes) = try_parse!(input, take!(4));
     let oui = Bytes::from(&bytes[0..3]);
@@ -72,13 +146,17 @@
                 group_data_cipher_suite: group_cipher,
                 pairwise_cipher_suites: pairwise_list,
                 akm_suites: akm_list,
-                rsn_capabilities: rsn_capabilities.unwrap_or(0),
+                rsn_capabilities: rsn_capabilities,
                 pmkids: pmkid_list,
                 group_mgmt_cipher_suite: group_mgmt_cipher_suite
            })
     )
 );
 
+#[derive(Debug, Fail)]
+#[fail(display = "buffer too small; required: {}, available: {}", _0, _1)]
+struct ErrorBufferTooSmall(usize, usize);
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -95,5 +173,38 @@
         b.iter(|| from_bytes(&frame));
     }
 
-    // TODO(hahnr): Add tests.
-}
+    #[test]
+    fn test_as_bytes() {
+        let frame: Vec<u8> = vec![
+            0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04,
+            0x01, 0x00, 0x00, 0x0f, 0xac, 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04,
+            0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x00, 0x0f,
+            0xac, 0x04,
+        ];
+        let mut buf = BytesMut::with_capacity(128);
+        let result = from_bytes(&frame);
+        assert!(result.is_done());
+        let rsne = result.unwrap().1;
+        let result = rsne.as_bytes(&mut buf);
+        assert!(result.is_ok());
+        let rsne_len = buf.len();
+        let left_over = buf.split_off(rsne_len);
+        assert_eq!(&buf[..], &frame[..]);
+        assert!(left_over.iter().all(|b| *b == 0));
+    }
+
+    #[test]
+    fn test_short_buffer() {
+        let frame: Vec<u8> = vec![
+            0x30, 0x14, 0x01, 0x00, 0x00, 0x0f, 0xac, 0x04, 0x07, 0x00, 0x00, 0x0f, 0xac, 0x04,
+            0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f,
+            0xac, 0x04, 0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f, 0xac, 0x04,
+        ];
+        let mut buf = BytesMut::with_capacity(32);
+        let result = from_bytes(&frame);
+        assert!(result.is_done());
+        let rsne = result.unwrap().1;
+        let result = rsne.as_bytes(&mut buf);
+        assert!(result.is_err());
+    }
+}
\ No newline at end of file
diff --git a/lib/rust/crates/wlan-sme/src/lib.rs b/lib/rust/crates/wlan-sme/src/lib.rs
index 414fd02..d89e82f 100644
--- a/lib/rust/crates/wlan-sme/src/lib.rs
+++ b/lib/rust/crates/wlan-sme/src/lib.rs
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-extern crate fidl_wlan_mlme as fidl_mlme;
+extern crate fidl_fuchsia_wlan_mlme as fidl_mlme;
 extern crate fuchsia_zircon as zx;
 #[macro_use] extern crate failure;
 extern crate futures;
diff --git a/lib/rust/crates/wlantap-client/BUILD.gn b/lib/rust/crates/wlantap-client/BUILD.gn
index e4b9bac..b93e3d8 100644
--- a/lib/rust/crates/wlantap-client/BUILD.gn
+++ b/lib/rust/crates/wlantap-client/BUILD.gn
@@ -9,7 +9,6 @@
   version = "0.1.0"
 
   deps = [
-    "//garnet/lib/wlan/fidl:fidl-rustc",
     "//garnet/lib/wlan/fidl:wlantap-rustc",
     "//garnet/public/lib/fidl/rust/fidl",
     "//garnet/public/rust/crates/fdio",
diff --git a/lib/rust/crates/wlantap-client/src/lib.rs b/lib/rust/crates/wlantap-client/src/lib.rs
index 0f04d17..d9a0bc3 100644
--- a/lib/rust/crates/wlantap-client/src/lib.rs
+++ b/lib/rust/crates/wlantap-client/src/lib.rs
@@ -8,8 +8,7 @@
 extern crate failure;
 #[macro_use] extern crate fdio;
 extern crate fidl;
-extern crate fidl_wlan_device;
-extern crate fidl_wlantap;
+extern crate fidl_fuchsia_wlan_tap as wlantap;
 extern crate fuchsia_async as async;
 extern crate fuchsia_zircon as zx;
 extern crate futures;
@@ -36,8 +35,8 @@
         })
     }
 
-    pub fn create_phy(&self, mut config: fidl_wlantap::WlantapPhyConfig)
-        -> Result<fidl_wlantap::WlantapPhyProxy, Error>
+    pub fn create_phy(&self, mut config: wlantap::WlantapPhyConfig)
+        -> Result<wlantap::WlantapPhyProxy, Error>
     {
         let (encoded_config, handles) = (&mut vec![], &mut vec![]);
         Encoder::encode(encoded_config, handles, &mut config)?;
@@ -60,7 +59,7 @@
         }
         // Release ownership of the remote handle
         mem::forget(remote);
-        Ok(fidl_wlantap::WlantapPhyProxy::new(async::Channel::from_channel(local)?))
+        Ok(wlantap::WlantapPhyProxy::new(async::Channel::from_channel(local)?))
     }
 
 }
diff --git a/lib/ui/gfx/BUILD.gn b/lib/ui/gfx/BUILD.gn
index 53aeb7d..f2973fa 100644
--- a/lib/ui/gfx/BUILD.gn
+++ b/lib/ui/gfx/BUILD.gn
@@ -6,7 +6,7 @@
   # 0 - use normal swapchain
   # 1 - use vulkan swapchain, but wait for real display
   # 2 - use vulkan swapchain with fixed-size fake display
-  scene_manager_vulkan_swapchain = 0
+  scenic_vulkan_swapchain = 0
 }
 
 config("common_include_dirs") {
@@ -141,7 +141,7 @@
     "util/wrap.h",
   ]
 
-  defines = [ "SCENE_MANAGER_VULKAN_SWAPCHAIN=$scene_manager_vulkan_swapchain" ]
+  defines = [ "SCENIC_VULKAN_SWAPCHAIN=$scenic_vulkan_swapchain" ]
 
   public_configs = [ ":common_include_dirs" ]
 
@@ -156,10 +156,11 @@
     "//garnet/public/lib/ui/geometry/fidl",
     "//garnet/public/lib/ui/gfx/fidl",
     "//garnet/public/lib/vulkan",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
-    "//garnet/lib/magma:libmagma",
+    "//garnet/lib/magma/src/libmagma",
     "//garnet/public/lib/escher/util:check_vulkan_support",
     "//garnet/public/lib/ui/scenic:fidl_helpers",
     "//zircon/public/fidl/display:display",
diff --git a/lib/ui/gfx/displays/display_manager.cc b/lib/ui/gfx/displays/display_manager.cc
index e7dc9aa..d54b452 100644
--- a/lib/ui/gfx/displays/display_manager.cc
+++ b/lib/ui/gfx/displays/display_manager.cc
@@ -24,14 +24,14 @@
   }
 }
 
-void DisplayManager::WaitForDefaultDisplay(fxl::Closure callback) {
+void DisplayManager::WaitForDefaultDisplay(fit::closure callback) {
   FXL_DCHECK(!default_display_);
 
   display_available_cb_ = std::move(callback);
   display_watcher_.WaitForDisplay(
       [this](fxl::UniqueFD fd, zx::channel dc_handle) {
   // See declare_args() in lib/ui/gfx/BUILD.gn
-#if SCENE_MANAGER_VULKAN_SWAPCHAIN == 2
+#if SCENIC_VULKAN_SWAPCHAIN == 2
         // This is just for testing, so notify that there's a fake display
         // that's 800x608. Without a display the scene manager won't try to draw
         // anything.
@@ -103,7 +103,7 @@
         fuchsia::ui::scenic::displayNotOwnedSignal);
 
     // See declare_args() in lib/ui/gfx/BUILD.gn.
-#if SCENE_MANAGER_VULKAN_SWAPCHAIN != 0
+#if SCENIC_VULKAN_SWAPCHAIN != 0
     // Vulkan swapchains don't necessarily support the concurrent
     // connection to the display controller.
     wait_.Cancel();
diff --git a/lib/ui/gfx/displays/display_manager.h b/lib/ui/gfx/displays/display_manager.h
index 552ed41..decd578 100644
--- a/lib/ui/gfx/displays/display_manager.h
+++ b/lib/ui/gfx/displays/display_manager.h
@@ -12,9 +12,9 @@
 #include "garnet/lib/ui/gfx/displays/display_watcher.h"
 #include "lib/async/cpp/wait.h"
 #include "lib/fidl/cpp/synchronous_interface_ptr.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
+#include <lib/fit/function.h>
 #include <zircon/pixelformat.h>
 #include <zx/event.h>
 
@@ -29,7 +29,7 @@
 
   // Waits for the default display to become available then invokes the
   // callback.
-  void WaitForDefaultDisplay(fxl::Closure callback);
+  void WaitForDefaultDisplay(fit::closure callback);
 
   zx::vmo AllocateDisplayMemory(int32_t size);
   // Fetches the necessary linear stride (in px) from the display controller.
@@ -80,7 +80,7 @@
   uint64_t next_event_id_ = fuchsia::display::invalidId + 1;
 
   DisplayWatcher display_watcher_;
-  fxl::Closure display_available_cb_;
+  fit::closure display_available_cb_;
   std::unique_ptr<Display> default_display_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(DisplayManager);
diff --git a/lib/ui/gfx/displays/display_watcher.cc b/lib/ui/gfx/displays/display_watcher.cc
index e6788e3..b75adb2 100644
--- a/lib/ui/gfx/displays/display_watcher.cc
+++ b/lib/ui/gfx/displays/display_watcher.cc
@@ -24,14 +24,15 @@
 void DisplayWatcher::WaitForDisplay(DisplayReadyCallback callback) {
   FXL_DCHECK(!device_watcher_);
   // See declare_args() in lib/ui/gfx/BUILD.gn
-#if SCENE_MANAGER_VULKAN_SWAPCHAIN == 2
+#if SCENIC_VULKAN_SWAPCHAIN == 2
   // This is just for testing, so notify that there's a fake display.
   callback(fxl::UniqueFD(-1), ZX_HANDLE_INVALID, ZX_HANDLE_INVALID);
 #else
   device_watcher_ = fsl::DeviceWatcher::Create(
       kDisplayDir,
-      std::bind(&DisplayWatcher::HandleDevice, this, std::move(callback),
-                std::placeholders::_1, std::placeholders::_2));
+      [this, callback = std::move(callback)](int dir_fd, std::string filename) mutable {
+        HandleDevice(std::move(callback), dir_fd, filename);
+      });
 #endif
 }
 
diff --git a/lib/ui/gfx/displays/display_watcher.h b/lib/ui/gfx/displays/display_watcher.h
index b6d3137..7ba8383 100644
--- a/lib/ui/gfx/displays/display_watcher.h
+++ b/lib/ui/gfx/displays/display_watcher.h
@@ -7,6 +7,8 @@
 
 #include <memory>
 
+#include <lib/fit/function.h>
+
 #include "lib/fsl/io/device_watcher.h"
 #include "lib/fxl/macros.h"
 #include "lib/zx/event.h"
@@ -21,7 +23,7 @@
   // Callback that accepts display metrics.
   // |metrics| may be null if the display was not successfully acquired.
   using DisplayReadyCallback =
-      std::function<void(fxl::UniqueFD fd, zx::channel dc_handle)>;
+      fit::function<void(fxl::UniqueFD fd, zx::channel dc_handle)>;
 
   DisplayWatcher();
   ~DisplayWatcher();
diff --git a/lib/ui/gfx/engine/engine.cc b/lib/ui/gfx/engine/engine.cc
index f67fc7b..439d3a2 100644
--- a/lib/ui/gfx/engine/engine.cc
+++ b/lib/ui/gfx/engine/engine.cc
@@ -24,7 +24,6 @@
 #include "lib/escher/impl/vulkan_utils.h"
 #include "lib/escher/renderer/paper_renderer.h"
 #include "lib/escher/renderer/shadow_map_renderer.h"
-#include "lib/fxl/functional/make_copyable.h"
 
 namespace scenic {
 namespace gfx {
@@ -115,13 +114,13 @@
     // Apply update immediately.  This is done for tests.
     FXL_LOG(WARNING)
         << "No FrameScheduler available; applying update immediately";
-    RenderFrame(FrameTimingsPtr(), presentation_time, 0);
+    RenderFrame(FrameTimingsPtr(), presentation_time, 0, false);
   }
 }
 
 std::unique_ptr<Swapchain> Engine::CreateDisplaySwapchain(Display* display) {
   FXL_DCHECK(!display->is_claimed());
-#if SCENE_MANAGER_VULKAN_SWAPCHAIN
+#if SCENIC_VULKAN_SWAPCHAIN
   return std::make_unique<VulkanDisplaySwapchain>(display, event_timestamper(),
                                                   escher());
 #else
@@ -132,13 +131,15 @@
 
 bool Engine::RenderFrame(const FrameTimingsPtr& timings,
                          uint64_t presentation_time,
-                         uint64_t presentation_interval) {
+                         uint64_t presentation_interval, bool force_render) {
   TRACE_DURATION("gfx", "RenderFrame", "frame_number", timings->frame_number(),
                  "time", presentation_time, "interval", presentation_interval);
 
   if (!session_manager_->ApplyScheduledSessionUpdates(presentation_time,
-                                                      presentation_interval))
+                                                      presentation_interval) &&
+      !force_render) {
     return false;
+  }
 
   UpdateAndDeliverMetrics(presentation_time);
 
diff --git a/lib/ui/gfx/engine/engine.h b/lib/ui/gfx/engine/engine.h
index 2ee18c1..d83933a 100644
--- a/lib/ui/gfx/engine/engine.h
+++ b/lib/ui/gfx/engine/engine.h
@@ -120,7 +120,7 @@
 
   // |FrameSchedulerDelegate|:
   bool RenderFrame(const FrameTimingsPtr& frame, uint64_t presentation_time,
-                   uint64_t presentation_interval) override;
+                   uint64_t presentation_interval, bool force_render) override;
 
   void InitializeFrameScheduler();
 
diff --git a/lib/ui/gfx/engine/frame_scheduler.cc b/lib/ui/gfx/engine/frame_scheduler.cc
index 95d9e15..ececf02 100644
--- a/lib/ui/gfx/engine/frame_scheduler.cc
+++ b/lib/ui/gfx/engine/frame_scheduler.cc
@@ -192,7 +192,8 @@
     auto frame_timings = fxl::MakeRefCounted<FrameTimings>(
         this, ++frame_number_, presentation_time);
     if (delegate_->RenderFrame(frame_timings, presentation_time,
-                               display_->GetVsyncInterval())) {
+                               display_->GetVsyncInterval(),
+                               render_continuously_)) {
       outstanding_frames_.push_back(frame_timings);
     }
   }
@@ -213,10 +214,6 @@
   // TODO(MZ-400): This needs to be generalized for multi-display support.
   display_->set_last_vsync_time(timings->actual_presentation_time());
 
-  if (render_continuously_) {
-    RequestFrame(0);
-  }
-
   // Log trace data.
   // TODO(MZ-400): just pass the whole Frame to a listener.
   int64_t target_vs_actual_usecs =
@@ -252,6 +249,10 @@
       ScheduleFrame();
     }
   }
+
+  if (render_continuously_) {
+    RequestFrame(0);
+  }
 }
 
 bool FrameScheduler::TooMuchBackPressure() {
diff --git a/lib/ui/gfx/engine/frame_scheduler.h b/lib/ui/gfx/engine/frame_scheduler.h
index 76b3606..05f036d 100644
--- a/lib/ui/gfx/engine/frame_scheduler.h
+++ b/lib/ui/gfx/engine/frame_scheduler.h
@@ -40,7 +40,8 @@
   // frames are in flight and back off.
   virtual bool RenderFrame(const FrameTimingsPtr& frame_timings,
                            uint64_t presentation_time,
-                           uint64_t presentation_interval) = 0;
+                           uint64_t presentation_interval,
+                           bool force_render) = 0;
 };
 
 // The FrameScheduler is responsible for scheduling frames to be drawn in
diff --git a/lib/ui/gfx/engine/resource_linker.cc b/lib/ui/gfx/engine/resource_linker.cc
index c75fb26..4276611 100644
--- a/lib/ui/gfx/engine/resource_linker.cc
+++ b/lib/ui/gfx/engine/resource_linker.cc
@@ -239,12 +239,12 @@
 }
 
 void ResourceLinker::SetOnExpiredCallback(OnExpiredCallback callback) {
-  expiration_callback_ = callback;
+  expiration_callback_ = std::move(callback);
 }
 
 void ResourceLinker::SetOnImportResolvedCallback(
     OnImportResolvedCallback callback) {
-  import_resolved_callback_ = callback;
+  import_resolved_callback_ = std::move(callback);
 }
 
 size_t ResourceLinker::NumExportsForSession(Session* session) {
diff --git a/lib/ui/gfx/engine/resource_linker.h b/lib/ui/gfx/engine/resource_linker.h
index 7c5a3cd..658802f 100644
--- a/lib/ui/gfx/engine/resource_linker.h
+++ b/lib/ui/gfx/engine/resource_linker.h
@@ -9,6 +9,8 @@
 #include <unordered_set>
 
 #include <lib/async/cpp/wait.h>
+#include <lib/fit/function.h>
+
 #include "lib/fsl/handles/object_info.h"
 
 #include <fuchsia/ui/gfx/cpp/fidl.h>
@@ -44,7 +46,7 @@
   ~ResourceLinker();
 
   // Register a |resource| so that it can be imported into a different session
-  // via ImportResourceCommand with the peer of |export_token|.
+  // via ImportResourceCmd with the peer of |export_token|.
   //
   // Returns true if there are no errors.
   bool ExportResource(Resource* resource, zx::eventpair export_token);
@@ -70,10 +72,10 @@
     kExportTokenClosed,
     kResourceDestroyed,
   };
-  using OnExpiredCallback = std::function<void(Resource*, ExpirationCause)>;
+  using OnExpiredCallback = fit::function<void(Resource*, ExpirationCause)>;
   void SetOnExpiredCallback(OnExpiredCallback callback);
   using OnImportResolvedCallback =
-      std::function<void(Import*, Resource*, ImportResolutionResult)>;
+      fit::function<void(Import*, Resource*, ImportResolutionResult)>;
   void SetOnImportResolvedCallback(OnImportResolvedCallback callback);
 
   size_t NumExportsForSession(Session* session);
diff --git a/lib/ui/gfx/engine/session.cc b/lib/ui/gfx/engine/session.cc
index 689defd..d472104 100644
--- a/lib/ui/gfx/engine/session.cc
+++ b/lib/ui/gfx/engine/session.cc
@@ -58,8 +58,7 @@
     {::fuchsia::ui::gfx::Value::Tag::kVector1,
      ::fuchsia::ui::gfx::Value::Tag::kVariableId}};
 
-// Converts the provided vector of scene_manager hits into a fidl array of
-// HitPtrs.
+// Converts the provided vector of Hits into a fidl array of HitPtrs.
 fidl::VectorPtr<::fuchsia::ui::gfx::Hit> WrapHits(
     const std::vector<Hit>& hits) {
   fidl::VectorPtr<::fuchsia::ui::gfx::Hit> wrapped_hits;
@@ -96,97 +95,97 @@
 bool Session::ApplyCommand(::fuchsia::ui::gfx::Command command) {
   switch (command.Which()) {
     case ::fuchsia::ui::gfx::Command::Tag::kCreateResource:
-      return ApplyCreateResourceCommand(std::move(command.create_resource()));
+      return ApplyCreateResourceCmd(std::move(command.create_resource()));
     case ::fuchsia::ui::gfx::Command::Tag::kReleaseResource:
-      return ApplyReleaseResourceCommand(std::move(command.release_resource()));
+      return ApplyReleaseResourceCmd(std::move(command.release_resource()));
     case ::fuchsia::ui::gfx::Command::Tag::kExportResource:
-      return ApplyExportResourceCommand(std::move(command.export_resource()));
+      return ApplyExportResourceCmd(std::move(command.export_resource()));
     case ::fuchsia::ui::gfx::Command::Tag::kImportResource:
-      return ApplyImportResourceCommand(std::move(command.import_resource()));
+      return ApplyImportResourceCmd(std::move(command.import_resource()));
     case ::fuchsia::ui::gfx::Command::Tag::kAddChild:
-      return ApplyAddChildCommand(std::move(command.add_child()));
+      return ApplyAddChildCmd(std::move(command.add_child()));
     case ::fuchsia::ui::gfx::Command::Tag::kAddPart:
-      return ApplyAddPartCommand(std::move(command.add_part()));
+      return ApplyAddPartCmd(std::move(command.add_part()));
     case ::fuchsia::ui::gfx::Command::Tag::kDetach:
-      return ApplyDetachCommand(std::move(command.detach()));
+      return ApplyDetachCmd(std::move(command.detach()));
     case ::fuchsia::ui::gfx::Command::Tag::kDetachChildren:
-      return ApplyDetachChildrenCommand(std::move(command.detach_children()));
+      return ApplyDetachChildrenCmd(std::move(command.detach_children()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetTag:
-      return ApplySetTagCommand(std::move(command.set_tag()));
+      return ApplySetTagCmd(std::move(command.set_tag()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetTranslation:
-      return ApplySetTranslationCommand(std::move(command.set_translation()));
+      return ApplySetTranslationCmd(std::move(command.set_translation()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetScale:
-      return ApplySetScaleCommand(std::move(command.set_scale()));
+      return ApplySetScaleCmd(std::move(command.set_scale()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetRotation:
-      return ApplySetRotationCommand(std::move(command.set_rotation()));
+      return ApplySetRotationCmd(std::move(command.set_rotation()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetAnchor:
-      return ApplySetAnchorCommand(std::move(command.set_anchor()));
+      return ApplySetAnchorCmd(std::move(command.set_anchor()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetSize:
-      return ApplySetSizeCommand(std::move(command.set_size()));
+      return ApplySetSizeCmd(std::move(command.set_size()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetShape:
-      return ApplySetShapeCommand(std::move(command.set_shape()));
+      return ApplySetShapeCmd(std::move(command.set_shape()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetMaterial:
-      return ApplySetMaterialCommand(std::move(command.set_material()));
+      return ApplySetMaterialCmd(std::move(command.set_material()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetClip:
-      return ApplySetClipCommand(std::move(command.set_clip()));
+      return ApplySetClipCmd(std::move(command.set_clip()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetHitTestBehavior:
-      return ApplySetHitTestBehaviorCommand(
+      return ApplySetHitTestBehaviorCmd(
           std::move(command.set_hit_test_behavior()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetSpaceProperties:
-      return ApplySetSpacePropertiesCommand(
+      return ApplySetSpacePropertiesCmd(
           std::move(command.set_space_properties()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetCamera:
-      return ApplySetCameraCommand(std::move(command.set_camera()));
+      return ApplySetCameraCmd(std::move(command.set_camera()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetCameraTransform:
-      return ApplySetCameraTransformCommand(
+      return ApplySetCameraTransformCmd(
           std::move(command.set_camera_transform()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetCameraProjection:
-      return ApplySetCameraProjectionCommand(
+      return ApplySetCameraProjectionCmd(
           std::move(command.set_camera_projection()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetStereoCameraProjection:
-      return ApplySetStereoCameraProjectionCommand(
+      return ApplySetStereoCameraProjectionCmd(
           std::move(command.set_stereo_camera_projection()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetCameraPoseBuffer:
-      return ApplySetCameraPoseBufferCommand(
+      return ApplySetCameraPoseBufferCmd(
           std::move(command.set_camera_pose_buffer()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetLightColor:
-      return ApplySetLightColorCommand(std::move(command.set_light_color()));
+      return ApplySetLightColorCmd(std::move(command.set_light_color()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetLightDirection:
-      return ApplySetLightDirectionCommand(
+      return ApplySetLightDirectionCmd(
           std::move(command.set_light_direction()));
     case ::fuchsia::ui::gfx::Command::Tag::kAddLight:
-      return ApplyAddLightCommand(std::move(command.add_light()));
+      return ApplyAddLightCmd(std::move(command.add_light()));
     case ::fuchsia::ui::gfx::Command::Tag::kDetachLight:
-      return ApplyDetachLightCommand(std::move(command.detach_light()));
+      return ApplyDetachLightCmd(std::move(command.detach_light()));
     case ::fuchsia::ui::gfx::Command::Tag::kDetachLights:
-      return ApplyDetachLightsCommand(std::move(command.detach_lights()));
+      return ApplyDetachLightsCmd(std::move(command.detach_lights()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetTexture:
-      return ApplySetTextureCommand(std::move(command.set_texture()));
+      return ApplySetTextureCmd(std::move(command.set_texture()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetColor:
-      return ApplySetColorCommand(std::move(command.set_color()));
+      return ApplySetColorCmd(std::move(command.set_color()));
     case ::fuchsia::ui::gfx::Command::Tag::kBindMeshBuffers:
-      return ApplyBindMeshBuffersCommand(
+      return ApplyBindMeshBuffersCmd(
           std::move(command.bind_mesh_buffers()));
     case ::fuchsia::ui::gfx::Command::Tag::kAddLayer:
-      return ApplyAddLayerCommand(std::move(command.add_layer()));
+      return ApplyAddLayerCmd(std::move(command.add_layer()));
     case ::fuchsia::ui::gfx::Command::Tag::kRemoveLayer:
-      return ApplyRemoveLayerCommand(std::move(command.remove_layer()));
+      return ApplyRemoveLayerCmd(std::move(command.remove_layer()));
     case ::fuchsia::ui::gfx::Command::Tag::kRemoveAllLayers:
-      return ApplyRemoveAllLayersCommand(
+      return ApplyRemoveAllLayersCmd(
           std::move(command.remove_all_layers()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetLayerStack:
-      return ApplySetLayerStackCommand(std::move(command.set_layer_stack()));
+      return ApplySetLayerStackCmd(std::move(command.set_layer_stack()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetRenderer:
-      return ApplySetRendererCommand(std::move(command.set_renderer()));
+      return ApplySetRendererCmd(std::move(command.set_renderer()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetRendererParam:
-      return ApplySetRendererParamCommand(
+      return ApplySetRendererParamCmd(
           std::move(command.set_renderer_param()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetEventMask:
-      return ApplySetEventMaskCommand(std::move(command.set_event_mask()));
+      return ApplySetEventMaskCmd(std::move(command.set_event_mask()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetLabel:
-      return ApplySetLabelCommand(std::move(command.set_label()));
+      return ApplySetLabelCmd(std::move(command.set_label()));
     case ::fuchsia::ui::gfx::Command::Tag::kSetDisableClipping:
-      return ApplySetDisableClippingCommand(
+      return ApplySetDisableClippingCmd(
           std::move(command.set_disable_clipping()));
     case ::fuchsia::ui::gfx::Command::Tag::Invalid:
       // FIDL validation should make this impossible.
@@ -195,12 +194,12 @@
   }
 }
 
-bool Session::ApplyCreateResourceCommand(
-    ::fuchsia::ui::gfx::CreateResourceCommand command) {
+bool Session::ApplyCreateResourceCmd(
+    ::fuchsia::ui::gfx::CreateResourceCmd command) {
   const scenic::ResourceId id = command.id;
   if (id == 0) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplyCreateResourceCommand(): invalid ID: "
+        << "scenic::gfx::Session::ApplyCreateResourceCmd(): invalid ID: "
         << command;
     return false;
   }
@@ -272,16 +271,16 @@
   }
 }
 
-bool Session::ApplyReleaseResourceCommand(
-    ::fuchsia::ui::gfx::ReleaseResourceCommand command) {
+bool Session::ApplyReleaseResourceCmd(
+    ::fuchsia::ui::gfx::ReleaseResourceCmd command) {
   return resources_.RemoveResource(command.id);
 }
 
-bool Session::ApplyExportResourceCommand(
-    ::fuchsia::ui::gfx::ExportResourceCommand command) {
+bool Session::ApplyExportResourceCmd(
+    ::fuchsia::ui::gfx::ExportResourceCmd command) {
   if (!command.token) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplyExportResourceCommand(): "
+        << "scenic::gfx::Session::ApplyExportResourceCmd(): "
            "no token provided.";
     return false;
   }
@@ -292,11 +291,11 @@
   return false;
 }
 
-bool Session::ApplyImportResourceCommand(
-    ::fuchsia::ui::gfx::ImportResourceCommand command) {
+bool Session::ApplyImportResourceCmd(
+    ::fuchsia::ui::gfx::ImportResourceCmd command) {
   if (!command.token) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplyImportResourceCommand(): "
+        << "scenic::gfx::Session::ApplyImportResourceCmd(): "
            "no token provided.";
     return false;
   }
@@ -307,8 +306,8 @@
          resources_.AddResource(command.id, std::move(import));
 }
 
-bool Session::ApplyAddChildCommand(
-    ::fuchsia::ui::gfx::AddChildCommand command) {
+bool Session::ApplyAddChildCmd(
+    ::fuchsia::ui::gfx::AddChildCmd command) {
   // Find the parent and child nodes.
   if (auto parent_node = resources_.FindResource<Node>(command.node_id)) {
     if (auto child_node = resources_.FindResource<Node>(command.child_id)) {
@@ -318,7 +317,7 @@
   return false;
 }
 
-bool Session::ApplyAddPartCommand(::fuchsia::ui::gfx::AddPartCommand command) {
+bool Session::ApplyAddPartCmd(::fuchsia::ui::gfx::AddPartCmd command) {
   // Find the parent and part nodes.
   if (auto parent_node = resources_.FindResource<Node>(command.node_id)) {
     if (auto part_node = resources_.FindResource<Node>(command.part_id)) {
@@ -328,30 +327,30 @@
   return false;
 }
 
-bool Session::ApplyDetachCommand(::fuchsia::ui::gfx::DetachCommand command) {
+bool Session::ApplyDetachCmd(::fuchsia::ui::gfx::DetachCmd command) {
   if (auto resource = resources_.FindResource<Resource>(command.id)) {
     return resource->Detach();
   }
   return false;
 }
 
-bool Session::ApplyDetachChildrenCommand(
-    ::fuchsia::ui::gfx::DetachChildrenCommand command) {
+bool Session::ApplyDetachChildrenCmd(
+    ::fuchsia::ui::gfx::DetachChildrenCmd command) {
   if (auto node = resources_.FindResource<Node>(command.node_id)) {
     return node->DetachChildren();
   }
   return false;
 }
 
-bool Session::ApplySetTagCommand(::fuchsia::ui::gfx::SetTagCommand command) {
+bool Session::ApplySetTagCmd(::fuchsia::ui::gfx::SetTagCmd command) {
   if (auto node = resources_.FindResource<Node>(command.node_id)) {
     return node->SetTagValue(command.tag_value);
   }
   return false;
 }
 
-bool Session::ApplySetTranslationCommand(
-    ::fuchsia::ui::gfx::SetTranslationCommand command) {
+bool Session::ApplySetTranslationCmd(
+    ::fuchsia::ui::gfx::SetTranslationCmd command) {
   if (auto node = resources_.FindResource<Node>(command.id)) {
     if (IsVariable(command.value)) {
       if (auto variable = resources_.FindVariableResource<Vector3Variable>(
@@ -365,8 +364,8 @@
   return false;
 }
 
-bool Session::ApplySetScaleCommand(
-    ::fuchsia::ui::gfx::SetScaleCommand command) {
+bool Session::ApplySetScaleCmd(
+    ::fuchsia::ui::gfx::SetScaleCmd command) {
   if (auto node = resources_.FindResource<Node>(command.id)) {
     if (IsVariable(command.value)) {
       if (auto variable = resources_.FindVariableResource<Vector3Variable>(
@@ -380,8 +379,8 @@
   return false;
 }
 
-bool Session::ApplySetRotationCommand(
-    ::fuchsia::ui::gfx::SetRotationCommand command) {
+bool Session::ApplySetRotationCmd(
+    ::fuchsia::ui::gfx::SetRotationCmd command) {
   if (auto node = resources_.FindResource<Node>(command.id)) {
     if (IsVariable(command.value)) {
       if (auto variable = resources_.FindVariableResource<QuaternionVariable>(
@@ -395,8 +394,8 @@
   return false;
 }
 
-bool Session::ApplySetAnchorCommand(
-    ::fuchsia::ui::gfx::SetAnchorCommand command) {
+bool Session::ApplySetAnchorCmd(
+    ::fuchsia::ui::gfx::SetAnchorCmd command) {
   if (auto node = resources_.FindResource<Node>(command.id)) {
     if (IsVariable(command.value)) {
       if (auto variable = resources_.FindVariableResource<Vector3Variable>(
@@ -409,11 +408,11 @@
   return false;
 }
 
-bool Session::ApplySetSizeCommand(::fuchsia::ui::gfx::SetSizeCommand command) {
+bool Session::ApplySetSizeCmd(::fuchsia::ui::gfx::SetSizeCmd command) {
   if (auto layer = resources_.FindResource<Layer>(command.id)) {
     if (IsVariable(command.value)) {
       error_reporter_->ERROR()
-          << "scenic::gfx::Session::ApplySetSizeCommand(): "
+          << "scenic::gfx::Session::ApplySetSizeCmd(): "
              "unimplemented for variable value.";
       return false;
     }
@@ -422,8 +421,8 @@
   return false;
 }
 
-bool Session::ApplySetShapeCommand(
-    ::fuchsia::ui::gfx::SetShapeCommand command) {
+bool Session::ApplySetShapeCmd(
+    ::fuchsia::ui::gfx::SetShapeCmd command) {
   if (auto node = resources_.FindResource<ShapeNode>(command.node_id)) {
     if (auto shape = resources_.FindResource<Shape>(command.shape_id)) {
       node->SetShape(std::move(shape));
@@ -433,8 +432,8 @@
   return false;
 }
 
-bool Session::ApplySetMaterialCommand(
-    ::fuchsia::ui::gfx::SetMaterialCommand command) {
+bool Session::ApplySetMaterialCmd(
+    ::fuchsia::ui::gfx::SetMaterialCmd command) {
   if (auto node = resources_.FindResource<ShapeNode>(command.node_id)) {
     if (auto material =
             resources_.FindResource<Material>(command.material_id)) {
@@ -445,11 +444,11 @@
   return false;
 }
 
-bool Session::ApplySetClipCommand(::fuchsia::ui::gfx::SetClipCommand command) {
+bool Session::ApplySetClipCmd(::fuchsia::ui::gfx::SetClipCmd command) {
   if (command.clip_id != 0) {
     // TODO(MZ-167): Support non-zero clip_id.
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetClipCommand(): only "
+        << "scenic::gfx::Session::ApplySetClipCmd(): only "
            "clip_to_self is implemented.";
     return false;
   }
@@ -461,8 +460,8 @@
   return false;
 }
 
-bool Session::ApplySetHitTestBehaviorCommand(
-    ::fuchsia::ui::gfx::SetHitTestBehaviorCommand command) {
+bool Session::ApplySetHitTestBehaviorCmd(
+    ::fuchsia::ui::gfx::SetHitTestBehaviorCmd command) {
   if (auto node = resources_.FindResource<Node>(command.node_id)) {
     return node->SetHitTestBehavior(command.hit_test_behavior);
   }
@@ -470,14 +469,14 @@
   return false;
 }
 
-bool Session::ApplySetSpacePropertiesCommand(
-    ::fuchsia::ui::gfx::SetSpacePropertiesCommand command) {
-  error_reporter()->ERROR() << "SetSpacePropertiesCommand not implemented.";
+bool Session::ApplySetSpacePropertiesCmd(
+    ::fuchsia::ui::gfx::SetSpacePropertiesCmd command) {
+  error_reporter()->ERROR() << "SetSpacePropertiesCmd not implemented.";
   return false;
 }
 
-bool Session::ApplySetCameraCommand(
-    ::fuchsia::ui::gfx::SetCameraCommand command) {
+bool Session::ApplySetCameraCmd(
+    ::fuchsia::ui::gfx::SetCameraCmd command) {
   if (auto renderer = resources_.FindResource<Renderer>(command.renderer_id)) {
     if (command.camera_id == 0) {
       renderer->SetCamera(nullptr);
@@ -491,8 +490,8 @@
   return false;
 }
 
-bool Session::ApplySetTextureCommand(
-    ::fuchsia::ui::gfx::SetTextureCommand command) {
+bool Session::ApplySetTextureCmd(
+    ::fuchsia::ui::gfx::SetTextureCmd command) {
   if (auto material = resources_.FindResource<Material>(command.material_id)) {
     if (command.texture_id == 0) {
       material->SetTexture(nullptr);
@@ -506,12 +505,12 @@
   return false;
 }
 
-bool Session::ApplySetColorCommand(
-    ::fuchsia::ui::gfx::SetColorCommand command) {
+bool Session::ApplySetColorCmd(
+    ::fuchsia::ui::gfx::SetColorCmd command) {
   if (auto material = resources_.FindResource<Material>(command.material_id)) {
     if (IsVariable(command.color)) {
       error_reporter_->ERROR()
-          << "scenic::gfx::Session::ApplySetColorCommand(): "
+          << "scenic::gfx::Session::ApplySetColorCmd(): "
              "unimplemented for variable color.";
       return false;
     }
@@ -527,8 +526,8 @@
   return false;
 }
 
-bool Session::ApplyBindMeshBuffersCommand(
-    ::fuchsia::ui::gfx::BindMeshBuffersCommand command) {
+bool Session::ApplyBindMeshBuffersCmd(
+    ::fuchsia::ui::gfx::BindMeshBuffersCmd command) {
   auto mesh = resources_.FindResource<MeshShape>(command.mesh_id);
   auto index_buffer = resources_.FindResource<Buffer>(command.index_buffer_id);
   auto vertex_buffer =
@@ -543,8 +542,8 @@
   return false;
 }
 
-bool Session::ApplyAddLayerCommand(
-    ::fuchsia::ui::gfx::AddLayerCommand command) {
+bool Session::ApplyAddLayerCmd(
+    ::fuchsia::ui::gfx::AddLayerCmd command) {
   auto layer_stack =
       resources_.FindResource<LayerStack>(command.layer_stack_id);
   auto layer = resources_.FindResource<Layer>(command.layer_id);
@@ -554,8 +553,8 @@
   return false;
 }
 
-bool Session::ApplyRemoveLayerCommand(
-    ::fuchsia::ui::gfx::RemoveLayerCommand command) {
+bool Session::ApplyRemoveLayerCmd(
+    ::fuchsia::ui::gfx::RemoveLayerCmd command) {
   auto layer_stack =
       resources_.FindResource<LayerStack>(command.layer_stack_id);
   auto layer = resources_.FindResource<Layer>(command.layer_id);
@@ -565,8 +564,8 @@
   return false;
 }
 
-bool Session::ApplyRemoveAllLayersCommand(
-    ::fuchsia::ui::gfx::RemoveAllLayersCommand command) {
+bool Session::ApplyRemoveAllLayersCmd(
+    ::fuchsia::ui::gfx::RemoveAllLayersCmd command) {
   auto layer_stack =
       resources_.FindResource<LayerStack>(command.layer_stack_id);
   if (layer_stack) {
@@ -575,8 +574,8 @@
   return false;
 }
 
-bool Session::ApplySetLayerStackCommand(
-    ::fuchsia::ui::gfx::SetLayerStackCommand command) {
+bool Session::ApplySetLayerStackCmd(
+    ::fuchsia::ui::gfx::SetLayerStackCmd command) {
   auto compositor = resources_.FindResource<Compositor>(command.compositor_id);
   auto layer_stack =
       resources_.FindResource<LayerStack>(command.layer_stack_id);
@@ -586,8 +585,8 @@
   return false;
 }
 
-bool Session::ApplySetRendererCommand(
-    ::fuchsia::ui::gfx::SetRendererCommand command) {
+bool Session::ApplySetRendererCmd(
+    ::fuchsia::ui::gfx::SetRendererCmd command) {
   auto layer = resources_.FindResource<Layer>(command.layer_id);
   auto renderer = resources_.FindResource<Renderer>(command.renderer_id);
 
@@ -597,8 +596,8 @@
   return false;
 }
 
-bool Session::ApplySetRendererParamCommand(
-    ::fuchsia::ui::gfx::SetRendererParamCommand command) {
+bool Session::ApplySetRendererParamCmd(
+    ::fuchsia::ui::gfx::SetRendererParamCmd command) {
   auto renderer = resources_.FindResource<Renderer>(command.renderer_id);
   if (renderer) {
     switch (command.param.Which()) {
@@ -611,28 +610,28 @@
         return true;
       case ::fuchsia::ui::gfx::RendererParam::Tag::Invalid:
         error_reporter_->ERROR()
-            << "scenic::gfx::Session::ApplySetRendererParamCommand(): "
+            << "scenic::gfx::Session::ApplySetRendererParamCmd(): "
                "invalid param.";
     }
   }
   return false;
 }
 
-bool Session::ApplySetEventMaskCommand(
-    ::fuchsia::ui::gfx::SetEventMaskCommand command) {
+bool Session::ApplySetEventMaskCmd(
+    ::fuchsia::ui::gfx::SetEventMaskCmd command) {
   if (auto r = resources_.FindResource<Resource>(command.id)) {
     return r->SetEventMask(command.event_mask);
   }
   return false;
 }
 
-bool Session::ApplySetCameraTransformCommand(
-    ::fuchsia::ui::gfx::SetCameraTransformCommand command) {
+bool Session::ApplySetCameraTransformCmd(
+    ::fuchsia::ui::gfx::SetCameraTransformCmd command) {
   // TODO(MZ-123): support variables.
   if (IsVariable(command.eye_position) || IsVariable(command.eye_look_at) ||
       IsVariable(command.eye_up)) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraTransformCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraTransformCmd(): "
            "unimplemented: variable properties.";
     return false;
   } else if (auto camera = resources_.FindResource<Camera>(command.camera_id)) {
@@ -644,12 +643,12 @@
   return false;
 }
 
-bool Session::ApplySetCameraProjectionCommand(
-    ::fuchsia::ui::gfx::SetCameraProjectionCommand command) {
+bool Session::ApplySetCameraProjectionCmd(
+    ::fuchsia::ui::gfx::SetCameraProjectionCmd command) {
   // TODO(MZ-123): support variables.
   if (IsVariable(command.fovy)) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraProjectionCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraProjectionCmd(): "
            "unimplemented: variable properties.";
     return false;
   } else if (auto camera = resources_.FindResource<Camera>(command.camera_id)) {
@@ -659,12 +658,12 @@
   return false;
 }
 
-bool Session::ApplySetStereoCameraProjectionCommand(
-    ::fuchsia::ui::gfx::SetStereoCameraProjectionCommand command) {
+bool Session::ApplySetStereoCameraProjectionCmd(
+    ::fuchsia::ui::gfx::SetStereoCameraProjectionCmd command) {
   if (IsVariable(command.left_projection) ||
       IsVariable(command.right_projection)) {
     error_reporter_->ERROR()
-        << "scene_manager::Session::ApplySetStereoCameraProjectionOp(): "
+        << "scenic::gfx::Session::ApplySetStereoCameraProjectionOp(): "
            "unimplemented: variable properties.";
     return false;
   } else if (auto stereo_camera =
@@ -676,11 +675,11 @@
   return false;
 }
 
-bool Session::ApplySetCameraPoseBufferCommand(
-    ::fuchsia::ui::gfx::SetCameraPoseBufferCommand command) {
+bool Session::ApplySetCameraPoseBufferCmd(
+    ::fuchsia::ui::gfx::SetCameraPoseBufferCmd command) {
   if (zx::time(command.base_time) > zx::clock::get(ZX_CLOCK_MONOTONIC)) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraPoseBufferCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraPoseBufferCmd(): "
            "base time not in the past";
     return false;
   }
@@ -688,21 +687,21 @@
   auto buffer = resources_.FindResource<Buffer>(command.buffer_id);
   if (!buffer) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraPoseBufferCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraPoseBufferCmd(): "
            "invalid buffer ID";
     return false;
   }
 
   if (command.num_entries < 1) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraPoseBufferCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraPoseBufferCmd(): "
            "must have at least one entry in the pose buffer";
     return false;
   }
 
   if (buffer->size() < command.num_entries * sizeof(escher::hmd::Pose)) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraPoseBufferCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraPoseBufferCmd(): "
            "buffer is not large enough";
     return false;
   }
@@ -710,7 +709,7 @@
   auto camera = resources_.FindResource<Camera>(command.camera_id);
   if (!camera) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetCameraPoseBufferCommand(): "
+        << "scenic::gfx::Session::ApplySetCameraPoseBufferCmd(): "
            "invalid camera ID";
     return false;
   }
@@ -721,12 +720,12 @@
   return true;
 }
 
-bool Session::ApplySetLightColorCommand(
-    ::fuchsia::ui::gfx::SetLightColorCommand command) {
+bool Session::ApplySetLightColorCmd(
+    ::fuchsia::ui::gfx::SetLightColorCmd command) {
   // TODO(MZ-123): support variables.
   if (command.color.variable_id) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetLightColorCommand(): "
+        << "scenic::gfx::Session::ApplySetLightColorCmd(): "
            "unimplemented: variable color.";
     return false;
   } else if (auto light = resources_.FindResource<Light>(command.light_id)) {
@@ -735,12 +734,12 @@
   return false;
 }
 
-bool Session::ApplySetLightDirectionCommand(
-    ::fuchsia::ui::gfx::SetLightDirectionCommand command) {
+bool Session::ApplySetLightDirectionCmd(
+    ::fuchsia::ui::gfx::SetLightDirectionCmd command) {
   // TODO(MZ-123): support variables.
   if (command.direction.variable_id) {
     error_reporter_->ERROR()
-        << "scenic::gfx::Session::ApplySetLightDirectionCommand(): "
+        << "scenic::gfx::Session::ApplySetLightDirectionCmd(): "
            "unimplemented: variable direction.";
     return false;
   } else if (auto light =
@@ -750,8 +749,8 @@
   return false;
 }
 
-bool Session::ApplyAddLightCommand(
-    ::fuchsia::ui::gfx::AddLightCommand command) {
+bool Session::ApplyAddLightCmd(
+    ::fuchsia::ui::gfx::AddLightCmd command) {
   if (auto scene = resources_.FindResource<Scene>(command.scene_id)) {
     if (auto light = resources_.FindResource<Light>(command.light_id)) {
       return scene->AddLight(std::move(light));
@@ -759,34 +758,34 @@
   }
 
   error_reporter_->ERROR()
-      << "scenic::gfx::Session::ApplyAddLightCommand(): unimplemented.";
+      << "scenic::gfx::Session::ApplyAddLightCmd(): unimplemented.";
   return false;
 }
 
-bool Session::ApplyDetachLightCommand(
-    ::fuchsia::ui::gfx::DetachLightCommand command) {
+bool Session::ApplyDetachLightCmd(
+    ::fuchsia::ui::gfx::DetachLightCmd command) {
   error_reporter_->ERROR()
-      << "scenic::gfx::Session::ApplyDetachLightCommand(): unimplemented.";
+      << "scenic::gfx::Session::ApplyDetachLightCmd(): unimplemented.";
   return false;
 }
 
-bool Session::ApplyDetachLightsCommand(
-    ::fuchsia::ui::gfx::DetachLightsCommand command) {
+bool Session::ApplyDetachLightsCmd(
+    ::fuchsia::ui::gfx::DetachLightsCmd command) {
   error_reporter_->ERROR()
-      << "scenic::gfx::Session::ApplyDetachLightsCommand(): unimplemented.";
+      << "scenic::gfx::Session::ApplyDetachLightsCmd(): unimplemented.";
   return false;
 }
 
-bool Session::ApplySetLabelCommand(
-    ::fuchsia::ui::gfx::SetLabelCommand command) {
+bool Session::ApplySetLabelCmd(
+    ::fuchsia::ui::gfx::SetLabelCmd command) {
   if (auto r = resources_.FindResource<Resource>(command.id)) {
     return r->SetLabel(command.label.get());
   }
   return false;
 }
 
-bool Session::ApplySetDisableClippingCommand(
-    ::fuchsia::ui::gfx::SetDisableClippingCommand command) {
+bool Session::ApplySetDisableClippingCmd(
+    ::fuchsia::ui::gfx::SetDisableClippingCmd command) {
   if (auto r = resources_.FindResource<Renderer>(command.renderer_id)) {
     r->DisableClipping(command.disable_clipping);
     return true;
diff --git a/lib/ui/gfx/engine/session.h b/lib/ui/gfx/engine/session.h
index c51413d..276c074 100644
--- a/lib/ui/gfx/engine/session.h
+++ b/lib/ui/gfx/engine/session.h
@@ -58,7 +58,7 @@
 
   // Return the number of resources that a client can identify via a
   // scenic::ResourceId. This number is decremented when a
-  // ReleaseResourceCommand is applied.  However, the resource may continue to
+  // ReleaseResourceCmd is applied.  However, the resource may continue to
   // exist if it is referenced by other resources.
   size_t GetMappedResourceCount() const { return resources_.size(); }
 
@@ -121,71 +121,71 @@
   // Called internally to initiate teardown.
   void BeginTearDown();
 
-  // Commanderation application functions, called by ApplyCommand().
-  bool ApplyCreateResourceCommand(
-      ::fuchsia::ui::gfx::CreateResourceCommand command);
-  bool ApplyReleaseResourceCommand(
-      ::fuchsia::ui::gfx::ReleaseResourceCommand command);
-  bool ApplyExportResourceCommand(
-      ::fuchsia::ui::gfx::ExportResourceCommand command);
-  bool ApplyImportResourceCommand(
-      ::fuchsia::ui::gfx::ImportResourceCommand command);
-  bool ApplyAddChildCommand(::fuchsia::ui::gfx::AddChildCommand command);
-  bool ApplyAddPartCommand(::fuchsia::ui::gfx::AddPartCommand command);
-  bool ApplyDetachCommand(::fuchsia::ui::gfx::DetachCommand command);
-  bool ApplyDetachChildrenCommand(
-      ::fuchsia::ui::gfx::DetachChildrenCommand command);
-  bool ApplySetTagCommand(::fuchsia::ui::gfx::SetTagCommand command);
-  bool ApplySetTranslationCommand(
-      ::fuchsia::ui::gfx::SetTranslationCommand command);
-  bool ApplySetScaleCommand(::fuchsia::ui::gfx::SetScaleCommand command);
-  bool ApplySetRotationCommand(::fuchsia::ui::gfx::SetRotationCommand command);
-  bool ApplySetAnchorCommand(::fuchsia::ui::gfx::SetAnchorCommand command);
-  bool ApplySetSizeCommand(::fuchsia::ui::gfx::SetSizeCommand command);
-  bool ApplySetShapeCommand(::fuchsia::ui::gfx::SetShapeCommand command);
-  bool ApplySetMaterialCommand(::fuchsia::ui::gfx::SetMaterialCommand command);
-  bool ApplySetClipCommand(::fuchsia::ui::gfx::SetClipCommand command);
-  bool ApplySetSpacePropertiesCommand(
-      ::fuchsia::ui::gfx::SetSpacePropertiesCommand command);
-  bool ApplySetHitTestBehaviorCommand(
-      ::fuchsia::ui::gfx::SetHitTestBehaviorCommand command);
-  bool ApplySetCameraCommand(::fuchsia::ui::gfx::SetCameraCommand command);
-  bool ApplySetCameraTransformCommand(
-      ::fuchsia::ui::gfx::SetCameraTransformCommand command);
-  bool ApplySetCameraProjectionCommand(
-      ::fuchsia::ui::gfx::SetCameraProjectionCommand command);
-  bool ApplySetStereoCameraProjectionCommand(
-      ::fuchsia::ui::gfx::SetStereoCameraProjectionCommand command);
-  bool ApplySetCameraPoseBufferCommand(
-      ::fuchsia::ui::gfx::SetCameraPoseBufferCommand command);
-  bool ApplySetLightColorCommand(
-      ::fuchsia::ui::gfx::SetLightColorCommand command);
-  bool ApplySetLightDirectionCommand(
-      ::fuchsia::ui::gfx::SetLightDirectionCommand command);
-  bool ApplyAddLightCommand(::fuchsia::ui::gfx::AddLightCommand command);
-  bool ApplyDetachLightCommand(::fuchsia::ui::gfx::DetachLightCommand command);
-  bool ApplyDetachLightsCommand(
-      ::fuchsia::ui::gfx::DetachLightsCommand command);
-  bool ApplySetTextureCommand(::fuchsia::ui::gfx::SetTextureCommand command);
-  bool ApplySetColorCommand(::fuchsia::ui::gfx::SetColorCommand command);
-  bool ApplyBindMeshBuffersCommand(
-      ::fuchsia::ui::gfx::BindMeshBuffersCommand command);
-  bool ApplyAddLayerCommand(::fuchsia::ui::gfx::AddLayerCommand command);
-  bool ApplyRemoveLayerCommand(::fuchsia::ui::gfx::RemoveLayerCommand command);
-  bool ApplyRemoveAllLayersCommand(
-      ::fuchsia::ui::gfx::RemoveAllLayersCommand command);
-  bool ApplySetLayerStackCommand(
-      ::fuchsia::ui::gfx::SetLayerStackCommand command);
-  bool ApplySetRendererCommand(::fuchsia::ui::gfx::SetRendererCommand command);
-  bool ApplySetRendererParamCommand(
-      ::fuchsia::ui::gfx::SetRendererParamCommand command);
-  bool ApplySetEventMaskCommand(
-      ::fuchsia::ui::gfx::SetEventMaskCommand command);
-  bool ApplySetLabelCommand(::fuchsia::ui::gfx::SetLabelCommand command);
-  bool ApplySetDisableClippingCommand(
-      ::fuchsia::ui::gfx::SetDisableClippingCommand command);
+  // Cmderation application functions, called by ApplyCommand().
+  bool ApplyCreateResourceCmd(
+      ::fuchsia::ui::gfx::CreateResourceCmd command);
+  bool ApplyReleaseResourceCmd(
+      ::fuchsia::ui::gfx::ReleaseResourceCmd command);
+  bool ApplyExportResourceCmd(
+      ::fuchsia::ui::gfx::ExportResourceCmd command);
+  bool ApplyImportResourceCmd(
+      ::fuchsia::ui::gfx::ImportResourceCmd command);
+  bool ApplyAddChildCmd(::fuchsia::ui::gfx::AddChildCmd command);
+  bool ApplyAddPartCmd(::fuchsia::ui::gfx::AddPartCmd command);
+  bool ApplyDetachCmd(::fuchsia::ui::gfx::DetachCmd command);
+  bool ApplyDetachChildrenCmd(
+      ::fuchsia::ui::gfx::DetachChildrenCmd command);
+  bool ApplySetTagCmd(::fuchsia::ui::gfx::SetTagCmd command);
+  bool ApplySetTranslationCmd(
+      ::fuchsia::ui::gfx::SetTranslationCmd command);
+  bool ApplySetScaleCmd(::fuchsia::ui::gfx::SetScaleCmd command);
+  bool ApplySetRotationCmd(::fuchsia::ui::gfx::SetRotationCmd command);
+  bool ApplySetAnchorCmd(::fuchsia::ui::gfx::SetAnchorCmd command);
+  bool ApplySetSizeCmd(::fuchsia::ui::gfx::SetSizeCmd command);
+  bool ApplySetShapeCmd(::fuchsia::ui::gfx::SetShapeCmd command);
+  bool ApplySetMaterialCmd(::fuchsia::ui::gfx::SetMaterialCmd command);
+  bool ApplySetClipCmd(::fuchsia::ui::gfx::SetClipCmd command);
+  bool ApplySetSpacePropertiesCmd(
+      ::fuchsia::ui::gfx::SetSpacePropertiesCmd command);
+  bool ApplySetHitTestBehaviorCmd(
+      ::fuchsia::ui::gfx::SetHitTestBehaviorCmd command);
+  bool ApplySetCameraCmd(::fuchsia::ui::gfx::SetCameraCmd command);
+  bool ApplySetCameraTransformCmd(
+      ::fuchsia::ui::gfx::SetCameraTransformCmd command);
+  bool ApplySetCameraProjectionCmd(
+      ::fuchsia::ui::gfx::SetCameraProjectionCmd command);
+  bool ApplySetStereoCameraProjectionCmd(
+      ::fuchsia::ui::gfx::SetStereoCameraProjectionCmd command);
+  bool ApplySetCameraPoseBufferCmd(
+      ::fuchsia::ui::gfx::SetCameraPoseBufferCmd command);
+  bool ApplySetLightColorCmd(
+      ::fuchsia::ui::gfx::SetLightColorCmd command);
+  bool ApplySetLightDirectionCmd(
+      ::fuchsia::ui::gfx::SetLightDirectionCmd command);
+  bool ApplyAddLightCmd(::fuchsia::ui::gfx::AddLightCmd command);
+  bool ApplyDetachLightCmd(::fuchsia::ui::gfx::DetachLightCmd command);
+  bool ApplyDetachLightsCmd(
+      ::fuchsia::ui::gfx::DetachLightsCmd command);
+  bool ApplySetTextureCmd(::fuchsia::ui::gfx::SetTextureCmd command);
+  bool ApplySetColorCmd(::fuchsia::ui::gfx::SetColorCmd command);
+  bool ApplyBindMeshBuffersCmd(
+      ::fuchsia::ui::gfx::BindMeshBuffersCmd command);
+  bool ApplyAddLayerCmd(::fuchsia::ui::gfx::AddLayerCmd command);
+  bool ApplyRemoveLayerCmd(::fuchsia::ui::gfx::RemoveLayerCmd command);
+  bool ApplyRemoveAllLayersCmd(
+      ::fuchsia::ui::gfx::RemoveAllLayersCmd command);
+  bool ApplySetLayerStackCmd(
+      ::fuchsia::ui::gfx::SetLayerStackCmd command);
+  bool ApplySetRendererCmd(::fuchsia::ui::gfx::SetRendererCmd command);
+  bool ApplySetRendererParamCmd(
+      ::fuchsia::ui::gfx::SetRendererParamCmd command);
+  bool ApplySetEventMaskCmd(
+      ::fuchsia::ui::gfx::SetEventMaskCmd command);
+  bool ApplySetLabelCmd(::fuchsia::ui::gfx::SetLabelCmd command);
+  bool ApplySetDisableClippingCmd(
+      ::fuchsia::ui::gfx::SetDisableClippingCmd command);
 
-  // Resource creation functions, called by ApplyCreateResourceCommand().
+  // Resource creation functions, called by ApplyCreateResourceCmd().
   bool ApplyCreateMemory(scenic::ResourceId id,
                          ::fuchsia::ui::gfx::MemoryArgs args);
   bool ApplyCreateImage(scenic::ResourceId id,
diff --git a/lib/ui/gfx/engine/session_handler.cc b/lib/ui/gfx/engine/session_handler.cc
index 27592cd..fe7106a 100644
--- a/lib/ui/gfx/engine/session_handler.cc
+++ b/lib/ui/gfx/engine/session_handler.cc
@@ -5,7 +5,6 @@
 #include "garnet/lib/ui/gfx/engine/session_handler.h"
 
 #include "garnet/lib/ui/scenic/session.h"
-#include "lib/fxl/functional/make_copyable.h"
 #include "lib/ui/scenic/fidl_helpers.h"
 
 namespace scenic {
diff --git a/lib/ui/gfx/gfx_system.cc b/lib/ui/gfx/gfx_system.cc
index f0aaa41..92cb794 100644
--- a/lib/ui/gfx/gfx_system.cc
+++ b/lib/ui/gfx/gfx_system.cc
@@ -12,7 +12,6 @@
 #include "garnet/public/lib/escher/util/check_vulkan_support.h"
 #include "lib/app/cpp/startup_context.h"
 #include "lib/escher/escher_process_init.h"
-#include "lib/fxl/functional/make_copyable.h"
 #include "public/lib/syslog/cpp/logger.h"
 
 namespace scenic {
diff --git a/lib/ui/gfx/gfx_system.h b/lib/ui/gfx/gfx_system.h
index 2c0e344..946dba7 100644
--- a/lib/ui/gfx/gfx_system.h
+++ b/lib/ui/gfx/gfx_system.h
@@ -68,7 +68,7 @@
 
   // TODO(MZ-452): Remove this when we externalize Displays.
   bool initialized_ = false;
-  std::vector<fxl::Closure> run_after_initialized_;
+  std::vector<fit::closure> run_after_initialized_;
 
   escher::VulkanInstancePtr vulkan_instance_;
   escher::VulkanDeviceQueuesPtr vulkan_device_queues_;
diff --git a/lib/ui/gfx/resources/camera.h b/lib/ui/gfx/resources/camera.h
index 570480a..e2be2f2 100644
--- a/lib/ui/gfx/resources/camera.h
+++ b/lib/ui/gfx/resources/camera.h
@@ -32,7 +32,7 @@
 
   void SetProjection(const float fovy);
 
-  // Sets the buffer for this camera. For details see SetCameraPoseBufferCommand
+  // Sets the buffer for this camera. For details see SetCameraPoseBufferCmd
   // in //garnet/public/lib/ui/gfx/fidl/commands.fidl
   void SetPoseBuffer(fxl::RefPtr<Buffer> buffer, uint32_t num_entries,
                      uint64_t base_time, uint64_t time_interval);
diff --git a/lib/ui/gfx/resources/compositor/compositor.h b/lib/ui/gfx/resources/compositor/compositor.h
index c79c51f..066423c 100644
--- a/lib/ui/gfx/resources/compositor/compositor.h
+++ b/lib/ui/gfx/resources/compositor/compositor.h
@@ -47,7 +47,7 @@
 
   ~Compositor() override;
 
-  // SetLayerStackCommand.
+  // SetLayerStackCmd.
   bool SetLayerStack(LayerStackPtr layer_stack);
   const LayerStackPtr& layer_stack() const { return layer_stack_; }
 
diff --git a/lib/ui/gfx/resources/compositor/layer.h b/lib/ui/gfx/resources/compositor/layer.h
index a8828f3..53d9370 100644
--- a/lib/ui/gfx/resources/compositor/layer.h
+++ b/lib/ui/gfx/resources/compositor/layer.h
@@ -37,19 +37,19 @@
   // | Resource |
   void Accept(class ResourceVisitor* visitor) override;
 
-  // SetRendererCommand.
+  // SetRendererCmd.
   bool SetRenderer(RendererPtr renderer);
   const RendererPtr& renderer() const { return renderer_; }
 
-  // SetSizeCommand.
+  // SetSizeCmd.
   bool SetSize(const escher::vec2& size);
   const escher::vec2& size() const { return size_; }
 
-  // SetColorCommand.
+  // SetColorCmd.
   bool SetColor(const escher::vec4& color);
   const escher::vec4& color() const { return color_; }
 
-  // |Resource|, DetachCommand.
+  // |Resource|, DetachCmd.
   bool Detach() override;
 
   // Add the scene rendered by this layer, if any, to |scenes_out|.
diff --git a/lib/ui/gfx/resources/compositor/layer_stack.h b/lib/ui/gfx/resources/compositor/layer_stack.h
index 04a16ac..a5f0d31 100644
--- a/lib/ui/gfx/resources/compositor/layer_stack.h
+++ b/lib/ui/gfx/resources/compositor/layer_stack.h
@@ -33,11 +33,11 @@
   // |session| is a pointer to the session that initiated the hit test.
   std::vector<Hit> HitTest(const escher::ray4& ray, Session* session) const;
 
-  // AddLayerCommand.
+  // AddLayerCmd.
   bool AddLayer(LayerPtr layer);
-  // RemoveLayerCommand.
+  // RemoveLayerCmd.
   bool RemoveLayer(LayerPtr layer);
-  // RemoveAllLayersCommand.
+  // RemoveAllLayersCmd.
   bool RemoveAllLayers();
 
   const std::unordered_set<LayerPtr>& layers() const { return layers_; }
diff --git a/lib/ui/gfx/resources/import.h b/lib/ui/gfx/resources/import.h
index 37fd0bd..f8b5146 100644
--- a/lib/ui/gfx/resources/import.h
+++ b/lib/ui/gfx/resources/import.h
@@ -5,9 +5,9 @@
 #ifndef GARNET_LIB_UI_GFX_RESOURCES_IMPORT_H_
 #define GARNET_LIB_UI_GFX_RESOURCES_IMPORT_H_
 
-#include <lib/zx/eventpair.h>
-
 #include <fuchsia/ui/gfx/cpp/fidl.h>
+#include <lib/fit/function.h>
+#include <lib/zx/eventpair.h>
 
 #include "garnet/lib/ui/gfx/resources/resource.h"
 #include "lib/fxl/macros.h"
@@ -28,7 +28,7 @@
                                 // occur.
 };
 using OnImportResolvedCallback =
-    std::function<void(Resource*, ImportResolutionResult)>;
+    fit::function<void(Resource*, ImportResolutionResult)>;
 
 /// Acts as a placeholder for resources imported from other sessions. Once a
 /// binding between the import and the resource has been established, the
diff --git a/lib/ui/gfx/resources/nodes/node.h b/lib/ui/gfx/resources/nodes/node.h
index e27f45b..d15e243 100644
--- a/lib/ui/gfx/resources/nodes/node.h
+++ b/lib/ui/gfx/resources/nodes/node.h
@@ -66,7 +66,7 @@
     reported_metrics_ = metrics;
   }
 
-  // |Resource|, DetachCommand.
+  // |Resource|, DetachCmd.
   bool Detach() override;
 
   Node* parent() const { return parent_; }
diff --git a/lib/ui/gfx/resources/nodes/variable_binding.cc b/lib/ui/gfx/resources/nodes/variable_binding.cc
index 741ad17..792f965 100644
--- a/lib/ui/gfx/resources/nodes/variable_binding.cc
+++ b/lib/ui/gfx/resources/nodes/variable_binding.cc
@@ -4,15 +4,17 @@
 
 #include "garnet/lib/ui/gfx/resources/nodes/variable_binding.h"
 
+#include <lib/fit/function.h>
+
 namespace scenic {
 namespace gfx {
 
 template <::fuchsia::ui::gfx::Value::Tag VT, typename T>
 TypedVariableBinding<VT, T>::TypedVariableBinding(
     fxl::RefPtr<TypedVariable<VT, T>> variable,
-    std::function<void(T value)> on_value_changed_callback)
+    fit::function<void(T value)> on_value_changed_callback)
     : variable_(variable),
-      on_value_changed_callback_(on_value_changed_callback) {
+      on_value_changed_callback_(std::move(on_value_changed_callback)) {
   on_value_changed_callback_(variable_->value());
   variable_->AddListener(this);
 }
diff --git a/lib/ui/gfx/resources/nodes/variable_binding.h b/lib/ui/gfx/resources/nodes/variable_binding.h
index 34b4398..6b022b9 100644
--- a/lib/ui/gfx/resources/nodes/variable_binding.h
+++ b/lib/ui/gfx/resources/nodes/variable_binding.h
@@ -7,6 +7,8 @@
 
 #include "garnet/lib/ui/gfx/resources/variable.h"
 
+#include <lib/fit/function.h>
+
 namespace scenic {
 namespace gfx {
 
@@ -25,14 +27,14 @@
                              public OnVariableValueChangedListener<VT, T> {
  public:
   TypedVariableBinding(fxl::RefPtr<TypedVariable<VT, T>> variable,
-                       std::function<void(T value)> on_value_changed_callback);
+                       fit::function<void(T value)> on_value_changed_callback);
   virtual ~TypedVariableBinding();
 
  private:
   void OnVariableValueChanged(TypedVariable<VT, T>* v) override;
 
   fxl::RefPtr<TypedVariable<VT, T>> variable_;
-  std::function<void(T value)> on_value_changed_callback_;
+  fit::function<void(T value)> on_value_changed_callback_;
 };
 
 using Vector3VariableBinding =
diff --git a/lib/ui/gfx/resources/resource.h b/lib/ui/gfx/resources/resource.h
index 3026a1a..1f675c6 100644
--- a/lib/ui/gfx/resources/resource.h
+++ b/lib/ui/gfx/resources/resource.h
@@ -25,7 +25,7 @@
 class Session;
 
 // Resource is the base class for all client-created objects (i.e. those that
-// are created in response to a CreateResourceCommand).
+// are created in response to a CreateResourceCmd).
 // TODO: use unsafe ref-counting for better performance (our architecture
 // guarantees that this is safe).
 class Resource : public fxl::RefCountedThreadSafe<Resource> {
diff --git a/lib/ui/gfx/resources/shapes/mesh_shape.h b/lib/ui/gfx/resources/shapes/mesh_shape.h
index 3803af3..05e8b5e 100644
--- a/lib/ui/gfx/resources/shapes/mesh_shape.h
+++ b/lib/ui/gfx/resources/shapes/mesh_shape.h
@@ -22,7 +22,7 @@
 
   MeshShape(Session* session, scenic::ResourceId id);
 
-  // These correspond to BindMeshBuffersCommand in commands.fidl.
+  // These correspond to BindMeshBuffersCmd in commands.fidl.
   bool BindBuffers(BufferPtr index_buffer,
                    ::fuchsia::ui::gfx::MeshIndexFormat index_format,
                    uint64_t index_offset, uint32_t index_count,
diff --git a/lib/ui/gfx/screenshotter.cc b/lib/ui/gfx/screenshotter.cc
index 08e2ebf..911537d 100644
--- a/lib/ui/gfx/screenshotter.cc
+++ b/lib/ui/gfx/screenshotter.cc
@@ -34,6 +34,7 @@
 
   constexpr uint32_t kBytesPerPixel = 4u;
   std::vector<uint8_t> imgvec;
+  const size_t kImgVecElementSize = sizeof(decltype(imgvec)::value_type);
   imgvec.resize(kBytesPerPixel * width * height);
 
   const uint8_t* row = image->memory()->mapped_ptr();
@@ -41,13 +42,14 @@
   row += sr_layout.offset;
   if (width == sr_layout.rowPitch) {
     uint32_t num_bytes = width * height * kBytesPerPixel;
-    FXL_DCHECK(num_bytes <= imgvec.size());
+    FXL_DCHECK(num_bytes <= kImgVecElementSize * imgvec.size());
     memcpy(imgvec.data(), row, num_bytes);
   } else {
     uint8_t* imgvec_ptr = imgvec.data();
     for (uint32_t y = 0; y < height; y++) {
       uint32_t num_bytes = width * kBytesPerPixel;
-      FXL_DCHECK(num_bytes <= &imgvec.back() - imgvec_ptr);
+      FXL_DCHECK(num_bytes <=
+                 kImgVecElementSize * (1 + &imgvec.back() - imgvec_ptr));
       memcpy(imgvec_ptr, row, num_bytes);
       row += sr_layout.rowPitch;
       imgvec_ptr += num_bytes;
diff --git a/lib/ui/gfx/swapchain/swapchain.h b/lib/ui/gfx/swapchain/swapchain.h
index 17c5772..cc211c7 100644
--- a/lib/ui/gfx/swapchain/swapchain.h
+++ b/lib/ui/gfx/swapchain/swapchain.h
@@ -5,7 +5,7 @@
 #ifndef GARNET_LIB_UI_GFX_SWAPCHAIN_SWAPCHAIN_H_
 #define GARNET_LIB_UI_GFX_SWAPCHAIN_SWAPCHAIN_H_
 
-#include <functional>
+#include <lib/fit/function.h>
 
 #include "lib/fxl/memory/ref_ptr.h"
 
@@ -31,7 +31,7 @@
   // - the semaphore to wait upon before rendering into the framebuffer
   // - the semaphore to signal when rendering is complete.
   using DrawCallback =
-      std::function<void(const escher::ImagePtr&, const escher::SemaphorePtr&,
+      fit::function<void(const escher::ImagePtr&, const escher::SemaphorePtr&,
                          const escher::SemaphorePtr&)>;
 
   // Returns false if the frame could not be drawn.  Otherwise,
diff --git a/lib/ui/gfx/tests/gfx_apptest.cc b/lib/ui/gfx/tests/gfx_apptest.cc
index df61c55..0ea6543 100644
--- a/lib/ui/gfx/tests/gfx_apptest.cc
+++ b/lib/ui/gfx/tests/gfx_apptest.cc
@@ -71,9 +71,9 @@
   {
     ::fidl::VectorPtr<fuchsia::ui::scenic::Command> commands;
     commands.push_back(
-        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCommand(1, 50.f)));
+        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCmd(1, 50.f)));
     commands.push_back(
-        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCommand(2, 25.f)));
+        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCmd(2, 25.f)));
 
     session->Enqueue(std::move(commands));
   }
@@ -116,9 +116,9 @@
   {
     ::fidl::VectorPtr<fuchsia::ui::scenic::Command> commands;
     commands.push_back(
-        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCommand(1, 50.f)));
+        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCmd(1, 50.f)));
     commands.push_back(
-        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCommand(2, 25.f)));
+        scenic_lib::NewCommand(scenic_lib::NewCreateCircleCmd(2, 25.f)));
 
     session->Enqueue(std::move(commands));
   }
diff --git a/lib/ui/gfx/tests/hittest_unittest.cc b/lib/ui/gfx/tests/hittest_unittest.cc
index 012549a..8ac7cba 100644
--- a/lib/ui/gfx/tests/hittest_unittest.cc
+++ b/lib/ui/gfx/tests/hittest_unittest.cc
@@ -59,48 +59,48 @@
   void SetUp() override {
     SessionTest::SetUp();
 
-    Apply(scenic_lib::NewCreateRectangleCommand(20, 8.f, 8.f));
+    Apply(scenic_lib::NewCreateRectangleCmd(20, 8.f, 8.f));
 
-    Apply(scenic_lib::NewCreateEntityNodeCommand(1));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(1));
 
-    Apply(scenic_lib::NewCreateEntityNodeCommand(2));
-    Apply(scenic_lib::NewSetTagCommand(2, 100));
-    Apply(scenic_lib::NewAddChildCommand(1, 2));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(2));
+    Apply(scenic_lib::NewSetTagCmd(2, 100));
+    Apply(scenic_lib::NewAddChildCmd(1, 2));
 
-    Apply(scenic_lib::NewCreateEntityNodeCommand(3));
-    Apply(scenic_lib::NewSetTagCommand(3, 25));
-    Apply(scenic_lib::NewSetTranslationCommand(3, (float[3]){4.f, 4.f, 0.f}));
-    Apply(scenic_lib::NewAddChildCommand(2, 3));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(3));
+    Apply(scenic_lib::NewSetTagCmd(3, 25));
+    Apply(scenic_lib::NewSetTranslationCmd(3, (float[3]){4.f, 4.f, 0.f}));
+    Apply(scenic_lib::NewAddChildCmd(2, 3));
 
-    Apply(scenic_lib::NewCreateShapeNodeCommand(4));
-    Apply(scenic_lib::NewSetTagCommand(4, 10));
-    Apply(scenic_lib::NewSetShapeCommand(4, 20));
-    Apply(scenic_lib::NewSetTranslationCommand(4, (float[3]){0.f, 0.f, 2.f}));
-    Apply(scenic_lib::NewAddChildCommand(3, 4));
+    Apply(scenic_lib::NewCreateShapeNodeCmd(4));
+    Apply(scenic_lib::NewSetTagCmd(4, 10));
+    Apply(scenic_lib::NewSetShapeCmd(4, 20));
+    Apply(scenic_lib::NewSetTranslationCmd(4, (float[3]){0.f, 0.f, 2.f}));
+    Apply(scenic_lib::NewAddChildCmd(3, 4));
 
-    Apply(scenic_lib::NewCreateEntityNodeCommand(5));
-    Apply(scenic_lib::NewSetTagCommand(5, 20));
-    Apply(scenic_lib::NewSetTranslationCommand(5, (float[3]){5.f, 5.f, 1.f}));
-    Apply(scenic_lib::NewAddChildCommand(3, 5));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(5));
+    Apply(scenic_lib::NewSetTagCmd(5, 20));
+    Apply(scenic_lib::NewSetTranslationCmd(5, (float[3]){5.f, 5.f, 1.f}));
+    Apply(scenic_lib::NewAddChildCmd(3, 5));
 
-    Apply(scenic_lib::NewCreateShapeNodeCommand(6));
-    Apply(scenic_lib::NewSetShapeCommand(6, 20));
-    Apply(scenic_lib::NewAddChildCommand(5, 6));
+    Apply(scenic_lib::NewCreateShapeNodeCmd(6));
+    Apply(scenic_lib::NewSetShapeCmd(6, 20));
+    Apply(scenic_lib::NewAddChildCmd(5, 6));
 
-    Apply(scenic_lib::NewCreateEntityNodeCommand(7));
-    Apply(scenic_lib::NewSetTagCommand(7, 35));
-    Apply(scenic_lib::NewSetTranslationCommand(7, (float[3]){10.f, 0.f, 1.f}));
-    Apply(scenic_lib::NewAddChildCommand(2, 7));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(7));
+    Apply(scenic_lib::NewSetTagCmd(7, 35));
+    Apply(scenic_lib::NewSetTranslationCmd(7, (float[3]){10.f, 0.f, 1.f}));
+    Apply(scenic_lib::NewAddChildCmd(2, 7));
 
-    Apply(scenic_lib::NewCreateShapeNodeCommand(8));
-    Apply(scenic_lib::NewSetTagCommand(8, 30));
-    Apply(scenic_lib::NewSetShapeCommand(8, 20));
-    Apply(scenic_lib::NewSetTranslationCommand(8, (float[3]){4.f, 4.f, 0.f}));
-    Apply(scenic_lib::NewAddChildCommand(7, 8));
+    Apply(scenic_lib::NewCreateShapeNodeCmd(8));
+    Apply(scenic_lib::NewSetTagCmd(8, 30));
+    Apply(scenic_lib::NewSetShapeCmd(8, 20));
+    Apply(scenic_lib::NewSetTranslationCmd(8, (float[3]){4.f, 4.f, 0.f}));
+    Apply(scenic_lib::NewAddChildCmd(7, 8));
 
-    Apply(scenic_lib::NewCreateEntityNodeCommand(9));
-    Apply(scenic_lib::NewSetTagCommand(9, 1));
-    Apply(scenic_lib::NewAddChildCommand(1, 9));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(9));
+    Apply(scenic_lib::NewSetTagCmd(9, 1));
+    Apply(scenic_lib::NewAddChildCmd(1, 9));
   }
 
  protected:
@@ -252,7 +252,7 @@
 }
 
 TEST_F(HitTestTest, SuppressNode25FromNode1) {
-  Apply(scenic_lib::NewSetHitTestBehaviorCommand(
+  Apply(scenic_lib::NewSetHitTestBehaviorCmd(
       3, ::fuchsia::ui::gfx::HitTestBehavior::kSuppress));
 
   // While we would have hit 20 and 25, we suppressed node 3 so neither appears.
@@ -267,20 +267,20 @@
   // to a rectangle added as a part in 25, which contains 10.
   // We move this part around and turn clipping on and off to see what happens
   // when the clip is intersected or not.
-  Apply(scenic_lib::NewCreateEntityNodeCommand(11));
-  Apply(scenic_lib::NewAddPartCommand(3, 11));
-  Apply(scenic_lib::NewCreateShapeNodeCommand(12));
-  Apply(scenic_lib::NewSetShapeCommand(12, 20));
-  Apply(scenic_lib::NewAddChildCommand(11, 12));
+  Apply(scenic_lib::NewCreateEntityNodeCmd(11));
+  Apply(scenic_lib::NewAddPartCmd(3, 11));
+  Apply(scenic_lib::NewCreateShapeNodeCmd(12));
+  Apply(scenic_lib::NewSetShapeCmd(12, 20));
+  Apply(scenic_lib::NewAddChildCmd(11, 12));
 
   // Initially, position the clip shape someplace far away from the content.
   // This causes 10 to be outside of its containing clip region.
-  Apply(scenic_lib::NewSetTranslationCommand(11, (float[3]){20.f, 20.f, 0.f}));
-  Apply(scenic_lib::NewSetClipCommand(3, 0, true));
+  Apply(scenic_lib::NewSetTranslationCmd(11, (float[3]){20.f, 20.f, 0.f}));
+  Apply(scenic_lib::NewSetClipCmd(3, 0, true));
   ExpectHits(1, vec3(0.f, 0.f, 10.f), kDownVector, {});
 
   // Now disable clipping and try again.
-  Apply(scenic_lib::NewSetClipCommand(3, 0, false));
+  Apply(scenic_lib::NewSetClipCmd(3, 0, false));
   ExpectHits(1, vec3(0.f, 0.f, 10.f), kDownVector,
              {{.tag = 10, .tx = -4.f, .ty = -4.f, .tz = -2.f, .d = 8.f},
               {.tag = 25, .tx = -4.f, .ty = -4.f, .tz = 0.f, .d = 8.f},
@@ -288,8 +288,8 @@
 
   // Move the clip shape so it covers the part of 10 that we're hitting
   // and reenable clipping.
-  Apply(scenic_lib::NewSetTranslationCommand(11, (float[3]){-4.f, -4.f, 0.f}));
-  Apply(scenic_lib::NewSetClipCommand(3, 0, true));
+  Apply(scenic_lib::NewSetTranslationCmd(11, (float[3]){-4.f, -4.f, 0.f}));
+  Apply(scenic_lib::NewSetClipCmd(3, 0, true));
   ExpectHits(1, vec3(0.f, 0.f, 10.f), kDownVector,
              {{.tag = 10, .tx = -4.f, .ty = -4.f, .tz = -2.f, .d = 8.f},
               {.tag = 25, .tx = -4.f, .ty = -4.f, .tz = 0.f, .d = 8.f},
diff --git a/lib/ui/gfx/tests/import_unittest.cc b/lib/ui/gfx/tests/import_unittest.cc
index d54233a..0a7da85 100644
--- a/lib/ui/gfx/tests/import_unittest.cc
+++ b/lib/ui/gfx/tests/import_unittest.cc
@@ -8,7 +8,6 @@
 #include "garnet/lib/ui/gfx/resources/nodes/entity_node.h"
 #include "garnet/lib/ui/gfx/tests/session_test.h"
 #include "garnet/lib/ui/gfx/tests/util.h"
-#include "lib/fxl/functional/make_copyable.h"
 #include "lib/ui/scenic/fidl_helpers.h"
 
 namespace scenic {
@@ -17,7 +16,7 @@
 
 using ImportTest = SessionTest;
 
-TEST_F(ImportTest, ExportsResourceViaCommand) {
+TEST_F(ImportTest, ExportsResourceViaCmd) {
   // Create the event pair.
   zx::eventpair source, destination;
   ASSERT_EQ(ZX_OK, zx::eventpair::create(0, &source, &destination));
@@ -26,23 +25,23 @@
   scenic::ResourceId resource_id = 1;
 
   // Create an entity node.
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(resource_id)));
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(resource_id)));
 
   // Assert that the entity node was correctly mapped in.
   ASSERT_EQ(1u, session_->GetMappedResourceCount());
 
   // Apply the export command.
   ASSERT_TRUE(Apply(
-      scenic_lib::NewExportResourceCommand(resource_id, std::move(source))));
+      scenic_lib::NewExportResourceCmd(resource_id, std::move(source))));
 }
 
-TEST_F(ImportTest, ImportsUnlinkedImportViaCommand) {
+TEST_F(ImportTest, ImportsUnlinkedImportViaCmd) {
   // Create the event pair.
   zx::eventpair source, destination;
   ASSERT_EQ(ZX_OK, zx::eventpair::create(0, &source, &destination));
 
   // Apply the import command.
-  ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+  ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
       1 /* import resource ID */,
       ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
       std::move(destination))               /* endpoint */
@@ -72,7 +71,7 @@
   // Perform the import
   {
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         1 /* import resource ID */,
         ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         std::move(destination))               /* endpoint */
@@ -100,14 +99,14 @@
   // Perform the export
   {
     // Create an entity node.
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(2)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(2)));
 
     // Assert that the entity node was correctly mapped in.
     ASSERT_EQ(2u, session_->GetMappedResourceCount());
 
     // Apply the export command.
     ASSERT_TRUE(
-        Apply(scenic_lib::NewExportResourceCommand(2, std::move(source))));
+        Apply(scenic_lib::NewExportResourceCmd(2, std::move(source))));
   }
 
   // Bindings should have been resolved.
@@ -147,8 +146,8 @@
   }
 
   // Export an entity node with a dead handle.
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1)));
-  EXPECT_FALSE(Apply(scenic_lib::NewExportResourceCommand(
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1)));
+  EXPECT_FALSE(Apply(scenic_lib::NewExportResourceCmd(
       1 /* resource id */, std::move(source_out))));
 }
 
@@ -165,8 +164,8 @@
   }
 
   // Import an entity node with a dead handle.
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1)));
-  EXPECT_FALSE(Apply(scenic_lib::NewImportResourceCommand(
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1)));
+  EXPECT_FALSE(Apply(scenic_lib::NewImportResourceCmd(
       1 /* resource id */, ::fuchsia::ui::gfx::ImportSpec::NODE,
       std::move(destination_out))));
 }
@@ -179,15 +178,15 @@
   // Export an entity node.
   scenic::ResourceId node_id = 1;
   scenic::ResourceId import_node = 2;
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(node_id)));
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(node_id)));
   EXPECT_TRUE(
-      Apply(scenic_lib::NewExportResourceCommand(node_id, std::move(source))));
-  EXPECT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+      Apply(scenic_lib::NewExportResourceCmd(node_id, std::move(source))));
+  EXPECT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
       import_node, ::fuchsia::ui::gfx::ImportSpec::NODE,
       std::move(destination))));
 
   // Release the entity node.
-  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(node_id)));
+  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(node_id)));
 
   // Run the message loop until we get an event.
   RunLoopUntilIdle();
@@ -209,15 +208,15 @@
   // Export an entity node.
   scenic::ResourceId node_id = 1;
   scenic::ResourceId import_node = 2;
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(node_id)));
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(node_id)));
   EXPECT_TRUE(
-      Apply(scenic_lib::NewExportResourceCommand(node_id, std::move(source))));
+      Apply(scenic_lib::NewExportResourceCmd(node_id, std::move(source))));
 
   // Release the entity node.
-  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(node_id)));
+  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(node_id)));
 
   // Try to import after the entity node has been released.
-  EXPECT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+  EXPECT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
       import_node, ::fuchsia::ui::gfx::ImportSpec::NODE,
       std::move(destination))));
 
@@ -249,7 +248,7 @@
     ASSERT_EQ(ZX_OK, zx::eventpair::create(0, &source, &destination));
 
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         1 /* import resource ID */,
         ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         std::move(destination))               /* endpoint */
@@ -276,7 +275,7 @@
 
     // Release the import resource.
     ASSERT_TRUE(Apply(
-        scenic_lib::NewReleaseResourceCommand(1 /* import resource ID */)));
+        scenic_lib::NewReleaseResourceCmd(1 /* import resource ID */)));
   });
 
   // Make sure the expiry handle tells us that the resource has expired.
@@ -324,18 +323,18 @@
 
   async::PostTask(dispatcher(), [&]() {
     // Create the resource being exported.
-    Apply(scenic_lib::NewCreateEntityNodeCommand(exported_node_id));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(exported_node_id));
     auto exported_node = FindResource<EntityNode>(exported_node_id);
     ASSERT_TRUE(exported_node);
     ASSERT_EQ(false, exported_node->is_exported());
 
     // Apply the export command.
-    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCommand(exported_node_id,
+    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCmd(exported_node_id,
                                                            std::move(source))));
     ASSERT_EQ(true, exported_node->is_exported());
 
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         import_node_id, ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         CopyEventPair(destination))                           /* endpoint */
                       ));
@@ -354,7 +353,7 @@
     async::PostTask(dispatcher(), [&]() {
       // Release the only import bound to the exported node.
       import_node_released = true;
-      EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(import_node_id)));
+      EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(import_node_id)));
 
       async::PostTask(dispatcher(), [&]() {
         // Exported node should still be marked as exported.
@@ -413,18 +412,18 @@
 
   async::PostTask(dispatcher(), [&]() {
     // Create the resource being exported.
-    Apply(scenic_lib::NewCreateEntityNodeCommand(exported_node_id));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(exported_node_id));
     auto exported_node = FindResource<EntityNode>(exported_node_id);
     ASSERT_TRUE(exported_node);
     ASSERT_EQ(false, exported_node->is_exported());
 
     // Apply the export command.
-    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCommand(exported_node_id,
+    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCmd(exported_node_id,
                                                            std::move(source))));
     ASSERT_EQ(true, exported_node->is_exported());
 
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         import_node_id, ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         CopyEventPair(destination))                           /* endpoint */
                       ));
@@ -454,7 +453,7 @@
         // Release the only import bound to the exported node.
         import_node_released = true;
         EXPECT_TRUE(
-            Apply(scenic_lib::NewReleaseResourceCommand(import_node_id)));
+            Apply(scenic_lib::NewReleaseResourceCmd(import_node_id)));
       });
     });
   });
@@ -505,18 +504,18 @@
 
   async::PostTask(dispatcher(), [&]() {
     // Create the resource being exported.
-    Apply(scenic_lib::NewCreateEntityNodeCommand(exported_node_id));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(exported_node_id));
     auto exported_node = FindResource<EntityNode>(exported_node_id);
     ASSERT_TRUE(exported_node);
     ASSERT_EQ(false, exported_node->is_exported());
 
     // Apply the export command.
-    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCommand(exported_node_id,
+    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCmd(exported_node_id,
                                                            std::move(source))));
     ASSERT_EQ(true, exported_node->is_exported());
 
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         import_node_id, ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         CopyEventPair(destination1))                          /* endpoint */
                       ));
@@ -549,7 +548,7 @@
         // Release the only import bound to the exported node.
         import_node_released = true;
         EXPECT_TRUE(
-            Apply(scenic_lib::NewReleaseResourceCommand(import_node_id)));
+            Apply(scenic_lib::NewReleaseResourceCmd(import_node_id)));
 
         async::PostTask(dispatcher(), [&]() {
           // Exported node should still be marked as exported.
@@ -616,22 +615,22 @@
 
   async::PostTask(dispatcher(), [&]() {
     // Create the resource being exported.
-    Apply(scenic_lib::NewCreateEntityNodeCommand(exported_node_id));
+    Apply(scenic_lib::NewCreateEntityNodeCmd(exported_node_id));
     auto exported_node = FindResource<EntityNode>(exported_node_id);
     ASSERT_TRUE(exported_node);
     ASSERT_EQ(false, exported_node->is_exported());
 
     // Apply the export command.
-    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCommand(exported_node_id,
+    ASSERT_TRUE(Apply(scenic_lib::NewExportResourceCmd(exported_node_id,
                                                            std::move(source))));
     ASSERT_EQ(true, exported_node->is_exported());
 
     // Apply the import commands.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         import_node_id1, ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         CopyEventPair(destination1))                           /* endpoint */
                       ));
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         import_node_id2, ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         CopyEventPair(destination1))                           /* endpoint */
                       ));
@@ -667,7 +666,7 @@
         // Release the only import bound to the exported node.
         import_node1_released = true;
         EXPECT_TRUE(
-            Apply(scenic_lib::NewReleaseResourceCommand(import_node_id1)));
+            Apply(scenic_lib::NewReleaseResourceCmd(import_node_id1)));
 
         async::PostTask(dispatcher(), [&]() {
           // Exported node should still be marked as exported.
@@ -690,7 +689,7 @@
 
             import_node2_released = true;
             EXPECT_TRUE(
-                Apply(scenic_lib::NewReleaseResourceCommand(import_node_id2)));
+                Apply(scenic_lib::NewReleaseResourceCmd(import_node_id2)));
           });
         });
       });
@@ -709,7 +708,7 @@
   ASSERT_EQ(ZX_OK, zx::eventpair::create(0, &source, &destination));
 
   // Apply the import command.
-  ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+  ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
       1 /* import resource ID */,
       ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
       std::move(destination))               /* endpoint */
@@ -754,7 +753,7 @@
     ASSERT_EQ(ZX_OK, zx::eventpair::create(0, &source, &destination));
 
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         1 /* import resource ID */,
         ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         std::move(destination))               /* endpoint */
@@ -780,10 +779,10 @@
   {
     // Create the entity node.
     ASSERT_TRUE(Apply(
-        scenic_lib::NewCreateEntityNodeCommand(2 /* child resource id */)));
+        scenic_lib::NewCreateEntityNodeCmd(2 /* child resource id */)));
 
     // Add the entity node to the import.
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(
         1 /* unlinked import resource */, 2 /* child resource */)));
   }
 }
@@ -796,7 +795,7 @@
   // Perform the import
   {
     // Apply the import command.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         1 /* import resource ID */,
         ::fuchsia::ui::gfx::ImportSpec::NODE, /* spec */
         std::move(destination))               /* endpoint */
@@ -824,14 +823,14 @@
   // Perform the export
   {
     // Create an entity node.
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(2)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(2)));
 
     // Assert that the entity node was correctly mapped in.
     ASSERT_EQ(2u, session_->GetMappedResourceCount());
 
     // Apply the export command.
     ASSERT_TRUE(
-        Apply(scenic_lib::NewExportResourceCommand(2, std::move(source))));
+        Apply(scenic_lib::NewExportResourceCmd(2, std::move(source))));
   }
 
   // Bindings should have been resolved.
@@ -852,10 +851,10 @@
   {
     // Create the entity node.
     ASSERT_TRUE(Apply(
-        scenic_lib::NewCreateEntityNodeCommand(3 /* child resource id */)));
+        scenic_lib::NewCreateEntityNodeCmd(3 /* child resource id */)));
 
     // Add the entity node to the import.
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(
         1 /* unlinked import resource */, 3 /* child resource */)));
   }
 }
@@ -893,30 +892,30 @@
 
   // Embedder.
   {
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateSceneCommand(1)));
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(2)));
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(3)));
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(1, 2)));
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(2, 3)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateSceneCmd(1)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(2)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(3)));
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(1, 2)));
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(2, 3)));
 
     // Export.
     ASSERT_TRUE(Apply(
-        scenic_lib::NewExportResourceCommand(1, std::move(export_token))));
+        scenic_lib::NewExportResourceCmd(1, std::move(export_token))));
     ASSERT_EQ(1u, engine_->resource_linker()->NumExports());
   }
 
   // Embeddee.
   {
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1001)));
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1002)));
-    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1003)));
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(1001, 1002)));
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(1002, 1003)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1001)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1002)));
+    ASSERT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1003)));
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(1001, 1002)));
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(1002, 1003)));
 
     // Import.
-    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCommand(
+    ASSERT_TRUE(Apply(scenic_lib::NewImportResourceCmd(
         500, ::fuchsia::ui::gfx::ImportSpec::NODE, std::move(import_token))));
-    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCommand(500, 1001)));
+    ASSERT_TRUE(Apply(scenic_lib::NewAddChildCmd(500, 1001)));
   }
 
   // Check that the scene has an item in its imports. That is how the visitor
diff --git a/lib/ui/gfx/tests/node_unittest.cc b/lib/ui/gfx/tests/node_unittest.cc
index daf8724..40a7300 100644
--- a/lib/ui/gfx/tests/node_unittest.cc
+++ b/lib/ui/gfx/tests/node_unittest.cc
@@ -18,12 +18,12 @@
 TEST_F(NodeTest, Tagging) {
   const scenic::ResourceId kNodeId = 1;
 
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(kNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(kNodeId)));
   auto shape_node = FindResource<ShapeNode>(kNodeId);
   EXPECT_EQ(0u, shape_node->tag_value());
-  EXPECT_TRUE(Apply(scenic_lib::NewSetTagCommand(kNodeId, 42u)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetTagCmd(kNodeId, 42u)));
   EXPECT_EQ(42u, shape_node->tag_value());
-  EXPECT_TRUE(Apply(scenic_lib::NewSetTagCommand(kNodeId, 0u)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetTagCmd(kNodeId, 0u)));
   EXPECT_EQ(0u, shape_node->tag_value());
 }
 
@@ -32,14 +32,14 @@
   const scenic::ResourceId kMaterialId = 2;
   const scenic::ResourceId kShapeId = 3;
 
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(kNodeId)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateMaterialCommand(kMaterialId)));
-  EXPECT_TRUE(Apply(scenic_lib::NewSetTextureCommand(kMaterialId, 0)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(kNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateMaterialCmd(kMaterialId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetTextureCmd(kMaterialId, 0)));
   EXPECT_TRUE(
-      Apply(scenic_lib::NewSetColorCommand(kMaterialId, 255, 100, 100, 255)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateCircleCommand(kShapeId, 50.f)));
-  EXPECT_TRUE(Apply(scenic_lib::NewSetMaterialCommand(kNodeId, kMaterialId)));
-  EXPECT_TRUE(Apply(scenic_lib::NewSetShapeCommand(kNodeId, kShapeId)));
+      Apply(scenic_lib::NewSetColorCmd(kMaterialId, 255, 100, 100, 255)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateCircleCmd(kShapeId, 50.f)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetMaterialCmd(kNodeId, kMaterialId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetShapeCmd(kNodeId, kShapeId)));
   auto shape_node = FindResource<ShapeNode>(kNodeId);
   auto material = FindResource<Material>(kMaterialId);
   auto circle = FindResource<Shape>(kShapeId);
@@ -53,50 +53,50 @@
 TEST_F(NodeTest, NodesWithChildren) {
   // Child node that we will attach to various types of nodes.
   const scenic::ResourceId kChildNodeId = 1;
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(kChildNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(kChildNodeId)));
   auto child_node = FindResource<Node>(kChildNodeId);
 
   // OK to detach a child that hasn't been attached.
-  EXPECT_TRUE(Apply(scenic_lib::NewDetachCommand(kChildNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewDetachCmd(kChildNodeId)));
 
   const scenic::ResourceId kEntityNodeId = 10;
   const scenic::ResourceId kShapeNodeId = 11;
   // TODO: const scenic::ResourceId kClipNodeId = 12;
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(kEntityNodeId)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(kShapeNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(kEntityNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(kShapeNodeId)));
   // TODO:
-  // EXPECT_TRUE(Apply(scenic_lib::NewCreateClipNodeCommand(kClipNodeId)));
+  // EXPECT_TRUE(Apply(scenic_lib::NewCreateClipNodeCmd(kClipNodeId)));
   auto entity_node = FindResource<EntityNode>(kEntityNodeId);
   auto shape_node = FindResource<ShapeNode>(kShapeNodeId);
   // auto clip_node = FindResource<ClipNode>(kClipNodeId);
 
   // We expect to be able to add children to these types.
   EXPECT_TRUE(
-      Apply(scenic_lib::NewAddChildCommand(kEntityNodeId, kChildNodeId)));
+      Apply(scenic_lib::NewAddChildCmd(kEntityNodeId, kChildNodeId)));
   EXPECT_EQ(entity_node.get(), child_node->parent());
-  EXPECT_TRUE(Apply(scenic_lib::NewDetachCommand(kChildNodeId)));
-  // EXPECT_TRUE(Apply(scenic_lib::NewDetachCommand(kChildNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewDetachCmd(kChildNodeId)));
+  // EXPECT_TRUE(Apply(scenic_lib::NewDetachCmd(kChildNodeId)));
 
   // We do not expect to be able to add children to these types.
   // TODO:
-  // EXPECT_FALSE(Apply(scenic_lib::NewAddChildCommand(kClipNodeId,
+  // EXPECT_FALSE(Apply(scenic_lib::NewAddChildCmd(kClipNodeId,
   // kChildNodeId))); EXPECT_EQ(nullptr, child_node->parent());
   // EXPECT_EQ(nullptr, child_node->parent());
   EXPECT_FALSE(
-      Apply(scenic_lib::NewAddChildCommand(kShapeNodeId, kChildNodeId)));
+      Apply(scenic_lib::NewAddChildCmd(kShapeNodeId, kChildNodeId)));
   EXPECT_EQ(nullptr, child_node->parent());
 }
 
 TEST_F(NodeTest, SettingHitTestBehavior) {
   const scenic::ResourceId kNodeId = 1;
 
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(kNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(kNodeId)));
 
   auto shape_node = FindResource<ShapeNode>(kNodeId);
   EXPECT_EQ(::fuchsia::ui::gfx::HitTestBehavior::kDefault,
             shape_node->hit_test_behavior());
 
-  EXPECT_TRUE(Apply(scenic_lib::NewSetHitTestBehaviorCommand(
+  EXPECT_TRUE(Apply(scenic_lib::NewSetHitTestBehaviorCmd(
       kNodeId, ::fuchsia::ui::gfx::HitTestBehavior::kSuppress)));
   EXPECT_EQ(::fuchsia::ui::gfx::HitTestBehavior::kSuppress,
             shape_node->hit_test_behavior());
diff --git a/lib/ui/gfx/tests/pose_buffer_unit_test.cc b/lib/ui/gfx/tests/pose_buffer_unit_test.cc
index 05515f3..1c1fd56 100644
--- a/lib/ui/gfx/tests/pose_buffer_unit_test.cc
+++ b/lib/ui/gfx/tests/pose_buffer_unit_test.cc
@@ -21,8 +21,8 @@
   const scenic::ResourceId memory_id = 3;
   const scenic::ResourceId buffer_id = 4;
 
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateSceneCommand(scene_id)));
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateCameraCommand(camera_id, scene_id)));
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateSceneCmd(scene_id)));
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateCameraCmd(camera_id, scene_id)));
 
   uint64_t vmo_size = PAGE_SIZE;
   zx::vmo vmo;
@@ -33,36 +33,36 @@
   uint64_t time_interval = 1024 * 1024;  // 1 ms
   uint32_t num_entries = 1;
 
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateMemoryCommand(
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateMemoryCmd(
       memory_id, std::move(vmo),
       fuchsia::images::MemoryType::VK_DEVICE_MEMORY)));
   ASSERT_TRUE(Apply(
-      scenic_lib::NewCreateBufferCommand(buffer_id, memory_id, 0, vmo_size)));
+      scenic_lib::NewCreateBufferCmd(buffer_id, memory_id, 0, vmo_size)));
 
   // Actual Tests
 
   // Basic case: all arguments valid
-  EXPECT_TRUE(Apply(scenic_lib::NewSetCameraPoseBufferCommand(
+  EXPECT_TRUE(Apply(scenic_lib::NewSetCameraPoseBufferCmd(
       camera_id, buffer_id, num_entries, base_time, time_interval)));
 
   // Invalid base time in the future
-  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCommand(
+  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCmd(
       camera_id, buffer_id, num_entries, UINT64_MAX, time_interval)));
 
   // Invalid buffer id
-  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCommand(
+  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCmd(
       camera_id, invalid_id, num_entries, base_time, time_interval)));
 
   // Invalid camera id
-  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCommand(
+  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCmd(
       invalid_id, buffer_id, num_entries, base_time, time_interval)));
 
   // num_entries too small
-  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCommand(
+  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCmd(
       camera_id, buffer_id, 0, base_time, time_interval)));
 
   // num_entries too large
-  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCommand(
+  EXPECT_FALSE(Apply(scenic_lib::NewSetCameraPoseBufferCmd(
       camera_id, buffer_id, UINT32_MAX, base_time, time_interval)));
 }
 
diff --git a/lib/ui/gfx/tests/session_test.h b/lib/ui/gfx/tests/session_test.h
index 238777e..2ca814e 100644
--- a/lib/ui/gfx/tests/session_test.h
+++ b/lib/ui/gfx/tests/session_test.h
@@ -5,6 +5,8 @@
 #ifndef GARNET_LIB_UI_GFX_TESTS_SESSION_TEST_H_
 #define GARNET_LIB_UI_GFX_TESTS_SESSION_TEST_H_
 
+#include <lib/fit/function.h>
+
 #include "garnet/lib/ui/gfx/engine/engine.h"
 #include "garnet/lib/ui/gfx/engine/session.h"
 #include "garnet/lib/ui/gfx/tests/mocks.h"
diff --git a/lib/ui/gfx/tests/session_unittest.cc b/lib/ui/gfx/tests/session_unittest.cc
index cbb9508..bd0def0 100644
--- a/lib/ui/gfx/tests/session_unittest.cc
+++ b/lib/ui/gfx/tests/session_unittest.cc
@@ -44,35 +44,35 @@
 }
 
 TEST_F(SessionTest, ResourceIdAlreadyUsed) {
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(2)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(2)));
   ExpectLastReportedError(nullptr);
-  EXPECT_FALSE(Apply(scenic_lib::NewCreateShapeNodeCommand(2)));
+  EXPECT_FALSE(Apply(scenic_lib::NewCreateShapeNodeCmd(2)));
   ExpectLastReportedError(
       "scenic::gfx::ResourceMap::AddResource(): resource with ID 2 already "
       "exists.");
 }
 
 TEST_F(SessionTest, AddAndRemoveResource) {
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCommand(1)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(2)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(3)));
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(4)));
-  EXPECT_TRUE(Apply(scenic_lib::NewAddChildCommand(1, 2)));
-  EXPECT_TRUE(Apply(scenic_lib::NewAddPartCommand(1, 3)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateEntityNodeCmd(1)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(2)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(3)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(4)));
+  EXPECT_TRUE(Apply(scenic_lib::NewAddChildCmd(1, 2)));
+  EXPECT_TRUE(Apply(scenic_lib::NewAddPartCmd(1, 3)));
   EXPECT_EQ(4U, session_->GetTotalResourceCount());
   EXPECT_EQ(4U, session_->GetMappedResourceCount());
 
   // Even though we release node 2 and 3, they continue to exist because they
   // referenced by node 1.  Only node 4 is destroyed.
-  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(2)));
-  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(3)));
-  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(4)));
+  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(2)));
+  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(3)));
+  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(4)));
   EXPECT_EQ(3U, session_->GetTotalResourceCount());
   EXPECT_EQ(1U, session_->GetMappedResourceCount());
 
   // Releasing node 1 causes nodes 1-3 to be destroyed.
-  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCommand(1)));
+  EXPECT_TRUE(Apply(scenic_lib::NewReleaseResourceCmd(1)));
   EXPECT_EQ(0U, session_->GetTotalResourceCount());
   EXPECT_EQ(0U, session_->GetMappedResourceCount());
 }
@@ -85,17 +85,17 @@
   const std::string kTooLongLabel =
       std::string(::fuchsia::ui::gfx::kLabelMaxLength + 1, '?');
 
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCommand(kNodeId)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateShapeNodeCmd(kNodeId)));
   auto shape_node = FindResource<ShapeNode>(kNodeId);
   EXPECT_TRUE(shape_node->label().empty());
-  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCommand(kNodeId, kShortLabel)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCmd(kNodeId, kShortLabel)));
   EXPECT_EQ(kShortLabel, shape_node->label());
-  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCommand(kNodeId, kLongLabel)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCmd(kNodeId, kLongLabel)));
   EXPECT_EQ(kLongLabel, shape_node->label());
-  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCommand(kNodeId, kTooLongLabel)));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCmd(kNodeId, kTooLongLabel)));
   EXPECT_EQ(kTooLongLabel.substr(0, ::fuchsia::ui::gfx::kLabelMaxLength),
             shape_node->label());
-  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCommand(kNodeId, "")));
+  EXPECT_TRUE(Apply(scenic_lib::NewSetLabelCmd(kNodeId, "")));
   EXPECT_TRUE(shape_node->label().empty());
 
   // Bypass the truncation performed by session helpers.
diff --git a/lib/ui/gfx/tests/shape_unittest.cc b/lib/ui/gfx/tests/shape_unittest.cc
index 8c6e4eb..e5ef970 100644
--- a/lib/ui/gfx/tests/shape_unittest.cc
+++ b/lib/ui/gfx/tests/shape_unittest.cc
@@ -33,7 +33,7 @@
 
 TEST_F(ShapeTest, Circle) {
   const scenic::ResourceId id = 1;
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateCircleCommand(id, 50.f)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateCircleCmd(id, 50.f)));
 
   auto circle = FindResource<CircleShape>(id);
   ASSERT_NE(nullptr, circle.get());
@@ -92,7 +92,7 @@
 
 TEST_F(ShapeTest, Rectangle) {
   const scenic::ResourceId id = 1;
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateRectangleCommand(id, 30.f, 40.f)));
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateRectangleCmd(id, 30.f, 40.f)));
 
   auto rectangle = FindResource<RectangleShape>(id);
   ASSERT_NE(nullptr, rectangle.get());
@@ -155,7 +155,7 @@
 // not currently available in the engine for tests.
 TEST_F(ShapeTest, DISABLED_RoundedRectangle) {
   const scenic::ResourceId id = 1;
-  EXPECT_TRUE(Apply(scenic_lib::NewCreateRoundedRectangleCommand(
+  EXPECT_TRUE(Apply(scenic_lib::NewCreateRoundedRectangleCmd(
       id, 30.f, 40.f, 2.f, 4.f, 6.f, 8.f)));
 
   auto rounded_rectangle = FindResource<RoundedRectangleShape>(id);
diff --git a/lib/ui/gfx/tests/stereo_camera_unittest.cc b/lib/ui/gfx/tests/stereo_camera_unittest.cc
index 2e7b323..fe3833b 100644
--- a/lib/ui/gfx/tests/stereo_camera_unittest.cc
+++ b/lib/ui/gfx/tests/stereo_camera_unittest.cc
@@ -25,17 +25,17 @@
   const scenic::ResourceId invalid_id = 0;
   const scenic::ResourceId scene_id = 1;
   const scenic::ResourceId camera_id = 2;
-  ASSERT_TRUE(Apply(scenic_lib::NewCreateSceneCommand(scene_id)));
+  ASSERT_TRUE(Apply(scenic_lib::NewCreateSceneCmd(scene_id)));
   EXPECT_TRUE(
-      Apply(scenic_lib::NewCreateStereoCameraCommand(camera_id, scene_id)));
+      Apply(scenic_lib::NewCreateStereoCameraCmd(camera_id, scene_id)));
   EXPECT_FALSE(
-      Apply(scenic_lib::NewCreateStereoCameraCommand(camera_id, invalid_id)));
+      Apply(scenic_lib::NewCreateStereoCameraCmd(camera_id, invalid_id)));
 
   // Not really projection matrices but we're just testing the setters
   glm::mat4 left_projection = glm::mat4(2);
   glm::mat4 right_projection = glm::mat4(3);
 
-  EXPECT_TRUE(Apply(scenic_lib::NewSetStereoCameraProjectionCommand(
+  EXPECT_TRUE(Apply(scenic_lib::NewSetStereoCameraProjectionCmd(
       camera_id, glm::value_ptr(left_projection),
       glm::value_ptr(right_projection))));
 
diff --git a/lib/ui/gfx/util/event_timestamper.h b/lib/ui/gfx/util/event_timestamper.h
index 1c490f1..acbe43a 100644
--- a/lib/ui/gfx/util/event_timestamper.h
+++ b/lib/ui/gfx/util/event_timestamper.h
@@ -5,11 +5,10 @@
 #ifndef GARNET_LIB_UI_GFX_UTIL_EVENT_TIMESTAMPER_H_
 #define GARNET_LIB_UI_GFX_UTIL_EVENT_TIMESTAMPER_H_
 
-#include <functional>
-
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async/cpp/task.h>
 #include <lib/async/cpp/wait.h>
+#include <lib/fit/function.h>
 #include <lib/zx/event.h>
 
 #include "lib/fxl/logging.h"
@@ -29,7 +28,7 @@
   class Waiter;
 
  public:
-  using Callback = std::function<void(zx_time_t timestamp)>;
+  using Callback = fit::function<void(zx_time_t timestamp)>;
 
   EventTimestamper();
   ~EventTimestamper();
diff --git a/lib/ui/scenic/scenic.cc b/lib/ui/scenic/scenic.cc
index 475fb95..9e34384 100644
--- a/lib/ui/scenic/scenic.cc
+++ b/lib/ui/scenic/scenic.cc
@@ -5,7 +5,6 @@
 #include "garnet/lib/ui/scenic/scenic.h"
 
 #include "lib/app/cpp/startup_context.h"
-#include "lib/fxl/functional/make_copyable.h"
 
 namespace scenic {
 
@@ -53,11 +52,11 @@
     CreateSessionImmediately(std::move(session_request), std::move(listener));
   } else {
     run_after_all_systems_initialized_.push_back(
-        fxl::MakeCopyable([this, session_request = std::move(session_request),
+        [this, session_request = std::move(session_request),
                            listener = std::move(listener)]() mutable {
           CreateSessionImmediately(std::move(session_request),
                                    std::move(listener));
-        }));
+        });
   }
 }
 
diff --git a/lib/ui/scenic/scenic.h b/lib/ui/scenic/scenic.h
index 1ca402b..f8a3b6d 100644
--- a/lib/ui/scenic/scenic.h
+++ b/lib/ui/scenic/scenic.h
@@ -13,7 +13,6 @@
 #include "garnet/lib/ui/scenic/session.h"
 #include "garnet/lib/ui/scenic/system.h"
 #include "lib/fidl/cpp/binding_set.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
 namespace scenic {
@@ -64,7 +63,7 @@
   std::set<System*> uninitialized_systems_;
 
   // Closures that will be run when all systems are initialized.
-  std::vector<fxl::Closure> run_after_all_systems_initialized_;
+  std::vector<fit::closure> run_after_all_systems_initialized_;
 
   void CreateSessionImmediately(
       ::fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session_request,
diff --git a/lib/ui/scenic/session.cc b/lib/ui/scenic/session.cc
index e130a5d..dfebc87 100644
--- a/lib/ui/scenic/session.cc
+++ b/lib/ui/scenic/session.cc
@@ -22,7 +22,7 @@
   for (auto& cmd : *cmds) {
     // TODO(SCN-710): This dispatch is far from optimal in terms of performance.
     // We need to benchmark it to figure out whether it matters.
-    System::TypeId type_id = SystemTypeForCommand(cmd);
+    System::TypeId type_id = SystemTypeForCmd(cmd);
     auto dispatcher = type_id != System::TypeId::kInvalid
                           ? dispatchers_[type_id].get()
                           : nullptr;
diff --git a/lib/ui/scenic/session.h b/lib/ui/scenic/session.h
index 0312107..5c33d98 100644
--- a/lib/ui/scenic/session.h
+++ b/lib/ui/scenic/session.h
@@ -6,11 +6,12 @@
 #define GARNET_LIB_UI_SCENIC_SESSION_H_
 
 #include <array>
-#include <functional>
 #include <memory>
 #include <string>
 
 #include <fuchsia/ui/gfx/cpp/fidl.h>
+#include <lib/fit/function.h>
+
 #include "garnet/lib/ui/scenic/event_reporter.h"
 #include "garnet/lib/ui/scenic/forward_declarations.h"
 #include "garnet/lib/ui/scenic/scenic.h"
@@ -74,14 +75,13 @@
   ErrorReporter* error_reporter() { return this; }
 
   // For tests.  See FlushEvents() below.
-  void set_event_callback(
-      std::function<void(fuchsia::ui::scenic::Event)> callback) {
-    event_callback_ = callback;
+  void set_event_callback(fit::function<void(fuchsia::ui::scenic::Event)> callback) {
+    event_callback_ = std::move(callback);
   }
 
   // For tests.  Called by ReportError().
-  void set_error_callback(std::function<void(std::string)> callback) {
-    error_callback_ = callback;
+  void set_error_callback(fit::function<void(std::string)> callback) {
+    error_callback_ = std::move(callback);
   }
 
  private:
@@ -101,8 +101,8 @@
   fidl::VectorPtr<fuchsia::ui::scenic::Event> buffered_events_;
 
   // Callbacks for testing.
-  std::function<void(fuchsia::ui::scenic::Event)> event_callback_;
-  std::function<void(std::string)> error_callback_;
+  fit::function<void(fuchsia::ui::scenic::Event)> event_callback_;
+  fit::function<void(std::string)> error_callback_;
 
   fxl::WeakPtrFactory<Session> weak_factory_;
 
diff --git a/lib/ui/scenic/system.h b/lib/ui/scenic/system.h
index a5715e5..2580348 100644
--- a/lib/ui/scenic/system.h
+++ b/lib/ui/scenic/system.h
@@ -5,6 +5,8 @@
 #ifndef GARNET_LIB_UI_SCENIC_SYSTEM_H_
 #define GARNET_LIB_UI_SCENIC_SYSTEM_H_
 
+#include <lib/fit/function.h>
+
 #include "garnet/lib/ui/scenic/command_dispatcher.h"
 
 #include <lib/fit/function.h>
@@ -62,7 +64,7 @@
     kInvalid = kMaxSystems,
   };
 
-  using OnInitializedCallback = std::function<void(System* system)>;
+  using OnInitializedCallback = fit::function<void(System* system)>;
 
   // If |initialized_after_construction| is false, the System must call
   // SetToInitialized() after initialization is complete.
@@ -79,7 +81,7 @@
 
   void set_on_initialized_callback(OnInitializedCallback callback) {
     FXL_DCHECK(!on_initialized_callback_);
-    on_initialized_callback_ = callback;
+    on_initialized_callback_ = std::move(callback);
   }
 
  protected:
@@ -111,7 +113,7 @@
 
 // Return the system type that knows how to handle the specified command.
 // Used by Session to choose a CommandDispatcher.
-inline System::TypeId SystemTypeForCommand(
+inline System::TypeId SystemTypeForCmd(
     const fuchsia::ui::scenic::Command& command) {
   switch (command.Which()) {
     case fuchsia::ui::scenic::Command::Tag::kGfx:
diff --git a/lib/ui/scenic/util/print_command.cc b/lib/ui/scenic/util/print_command.cc
index fcc9f31..7b619bc 100644
--- a/lib/ui/scenic/util/print_command.cc
+++ b/lib/ui/scenic/util/print_command.cc
@@ -105,8 +105,8 @@
 
 std::ostream& operator<<(
     std::ostream& stream,
-    const fuchsia::ui::gfx::CreateResourceCommand& command) {
-  stream << "CreateResourceCommand(id:" << command.id << " ";
+    const fuchsia::ui::gfx::CreateResourceCmd& command) {
+  stream << "CreateResourceCmd(id:" << command.id << " ";
   switch (command.resource.Which()) {
     case ResourceArgs::Tag::kMemory:
       stream << "Memory";
@@ -192,8 +192,8 @@
 
 std::ostream& operator<<(
     std::ostream& stream,
-    const fuchsia::ui::gfx::SetRendererParamCommand& command) {
-  stream << "SetRendererParamCommand(id=" << command.renderer_id << " ";
+    const fuchsia::ui::gfx::SetRendererParamCmd& command) {
+  stream << "SetRendererParamCmd(id=" << command.renderer_id << " ";
   switch (command.param.Which()) {
     case RendererParam::Tag::kShadowTechnique:
       stream << "shadow_technique=";
@@ -230,15 +230,15 @@
 }
 
 std::ostream& operator<<(std::ostream& stream,
-                         const fuchsia::ui::gfx::SetTextureCommand& command) {
-  stream << "SetTextureCommand(id:" << command.material_id
+                         const fuchsia::ui::gfx::SetTextureCmd& command) {
+  stream << "SetTextureCmd(id:" << command.material_id
          << " texture: " << command.texture_id;
   return stream << ")";
 }
 
 std::ostream& operator<<(std::ostream& stream,
-                         const fuchsia::ui::gfx::SetColorCommand& command) {
-  stream << "SetColorCommand(id:" << command.material_id;
+                         const fuchsia::ui::gfx::SetColorCmd& command) {
+  stream << "SetColorCmd(id:" << command.material_id;
   return stream << ")";
 }
 
diff --git a/lib/ui/scenic/util/print_command.h b/lib/ui/scenic/util/print_command.h
index 8b6a98e..586127a 100644
--- a/lib/ui/scenic/util/print_command.h
+++ b/lib/ui/scenic/util/print_command.h
@@ -13,10 +13,10 @@
                          const fuchsia::ui::gfx::Command& command);
 std::ostream& operator<<(
     std::ostream& stream,
-    const fuchsia::ui::gfx::CreateResourceCommand& command);
+    const fuchsia::ui::gfx::CreateResourceCmd& command);
 std::ostream& operator<<(
     std::ostream& stream,
-    const fuchsia::ui::gfx::SetRendererParamCommand& command);
+    const fuchsia::ui::gfx::SetRendererParamCmd& command);
 std::ostream& operator<<(std::ostream& stream,
                          const fuchsia::ui::gfx::Value::Tag& tag);
 
diff --git a/lib/vulkan/src/swapchain/image_pipe_swapchain_layer.cc b/lib/vulkan/src/swapchain/image_pipe_swapchain_layer.cc
index 0a3abf9..735b745 100644
--- a/lib/vulkan/src/swapchain/image_pipe_swapchain_layer.cc
+++ b/lib/vulkan/src/swapchain/image_pipe_swapchain_layer.cc
@@ -23,6 +23,10 @@
 
 namespace image_pipe_swapchain {
 
+// Useful for testing app performance without external restriction
+// (due to composition, vsync, etc.)
+constexpr bool kSkipPresent = false;
+
 // Zero is a invalid ID in the ImagePipe interface, so offset index by one
 static inline uint32_t ImageIdFromIndex(uint32_t index) { return index + 1; }
 
@@ -126,21 +130,25 @@
   uint32_t physical_device_count;
   result = instance_dispatch_table->EnumeratePhysicalDevices(
       instance, &physical_device_count, nullptr);
-  if (result != VK_SUCCESS) return result;
+  if (result != VK_SUCCESS)
+    return result;
 
-  if (physical_device_count < 1) return VK_ERROR_DEVICE_LOST;
+  if (physical_device_count < 1)
+    return VK_ERROR_DEVICE_LOST;
 
   std::vector<VkPhysicalDevice> physical_devices(physical_device_count);
   result = instance_dispatch_table->EnumeratePhysicalDevices(
       instance, &physical_device_count, physical_devices.data());
-  if (result != VK_SUCCESS) return VK_ERROR_DEVICE_LOST;
+  if (result != VK_SUCCESS)
+    return VK_ERROR_DEVICE_LOST;
 
   bool external_semaphore_extension_available = false;
   for (auto physical_device : physical_devices) {
     uint32_t device_extension_count;
     result = instance_dispatch_table->EnumerateDeviceExtensionProperties(
         physical_device, nullptr, &device_extension_count, nullptr);
-    if (result != VK_SUCCESS) return VK_ERROR_DEVICE_LOST;
+    if (result != VK_SUCCESS)
+      return VK_ERROR_DEVICE_LOST;
 
     if (device_extension_count > 0) {
       std::vector<VkExtensionProperties> device_extensions(
@@ -148,7 +156,8 @@
       result = instance_dispatch_table->EnumerateDeviceExtensionProperties(
           physical_device, nullptr, &device_extension_count,
           device_extensions.data());
-      if (result != VK_SUCCESS) return VK_ERROR_DEVICE_LOST;
+      if (result != VK_SUCCESS)
+        return VK_ERROR_DEVICE_LOST;
 
       for (uint32_t i = 0; i < device_extension_count; i++) {
         if (!strcmp(VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_EXTENSION_NAME,
@@ -160,7 +169,8 @@
     }
   }
 
-  if (!external_semaphore_extension_available) return VK_ERROR_SURFACE_LOST_KHR;
+  if (!external_semaphore_extension_available)
+    return VK_ERROR_SURFACE_LOST_KHR;
 
   VkFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
 
@@ -171,14 +181,16 @@
 
     result = instance_dispatch_table->EnumerateInstanceExtensionProperties(
         nullptr, &instance_extension_count, nullptr);
-    if (result != VK_SUCCESS) return result;
+    if (result != VK_SUCCESS)
+      return result;
 
     if (instance_extension_count > 0) {
       std::vector<VkExtensionProperties> instance_extensions(
           instance_extension_count);
       result = instance_dispatch_table->EnumerateInstanceExtensionProperties(
           nullptr, &instance_extension_count, instance_extensions.data());
-      if (result != VK_SUCCESS) return result;
+      if (result != VK_SUCCESS)
+        return result;
 
       for (uint32_t i = 0; i < instance_extension_count; i++) {
         if (!strcmp(VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME,
@@ -274,8 +286,8 @@
     image_info.tiling = fuchsia::images::Tiling::GPU_OPTIMAL;
 
     image_pipe_->AddImage(ImageIdFromIndex(i), std::move(image_info),
-                          std::move(vmo), fuchsia::images::MemoryType::VK_DEVICE_MEMORY,
-                          0);
+                          std::move(vmo),
+                          fuchsia::images::MemoryType::VK_DEVICE_MEMORY, 0);
 
     available_ids_.push_back(i);
 
@@ -328,8 +340,10 @@
   VkLayerDispatchTable* pDisp =
       GetLayerDataPtr(get_dispatch_key(device), layer_data_map)
           ->device_dispatch_table;
-  for (auto image : images_) pDisp->DestroyImage(device, image, pAllocator);
-  for (auto memory : memories_) pDisp->FreeMemory(device, memory, pAllocator);
+  for (auto image : images_)
+    pDisp->DestroyImage(device, image, pAllocator);
+  for (auto memory : memories_)
+    pDisp->FreeMemory(device, memory, pAllocator);
   for (auto semaphore : semaphores_)
     pDisp->DestroySemaphore(device, semaphore, pAllocator);
 }
@@ -344,7 +358,8 @@
 
 VkResult ImagePipeSwapchain::GetSwapchainImages(uint32_t* pCount,
                                                 VkImage* pSwapchainImages) {
-  if (image_pipe_closed_) return VK_ERROR_DEVICE_LOST;
+  if (image_pipe_closed_)
+    return VK_ERROR_DEVICE_LOST;
 
   if (pSwapchainImages == NULL) {
     *pCount = images_.size();
@@ -374,7 +389,8 @@
     // only way this can happen is if there are 0 images or if the client has
     // already acquired all images
     FXL_DCHECK(!pending_images_.empty());
-    if (timeout_ns == 0) return VK_NOT_READY;
+    if (timeout_ns == 0)
+      return VK_NOT_READY;
     // wait for image to become available
     zx_signals_t pending;
 
@@ -399,7 +415,8 @@
   acquired_ids_.push_back(*pImageIndex);
 
   if (semaphore != VK_NULL_HANDLE) {
-    if (acquire_events_.size() == 0) acquire_events_.resize(images_.size());
+    if (acquire_events_.size() == 0)
+      acquire_events_.resize(images_.size());
 
     if (!acquire_events_[*pImageIndex]) {
       zx_status_t status = zx::event::create(0, &acquire_events_[*pImageIndex]);
@@ -453,7 +470,8 @@
 VkResult ImagePipeSwapchain::Present(VkQueue queue, uint32_t index,
                                      uint32_t waitSemaphoreCount,
                                      const VkSemaphore* pWaitSemaphores) {
-  if (image_pipe_closed_) return VK_ERROR_DEVICE_LOST;
+  if (image_pipe_closed_)
+    return VK_ERROR_DEVICE_LOST;
 
   VkLayerDispatchTable* pDisp =
       GetLayerDataPtr(get_dispatch_key(queue), layer_data_map)
@@ -473,7 +491,7 @@
     return VK_ERROR_SURFACE_LOST_KHR;
   }
 
-  auto acquire_fences = fidl::VectorPtr<zx::event>::New(1);
+  zx::event acquire_fence;
 
   VkSemaphoreGetFuchsiaHandleInfoKHR semaphore_info = {
       .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FUCHSIA_HANDLE_INFO_KHR,
@@ -481,7 +499,7 @@
       .semaphore = semaphores_[index],
       .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR};
   result = pDisp->GetSemaphoreFuchsiaHandleKHR(
-      device_, &semaphore_info, acquire_fences->at(0).reset_and_get_address());
+      device_, &semaphore_info, acquire_fence.reset_and_get_address());
   if (result != VK_SUCCESS) {
     FXL_DLOG(ERROR) << "GetSemaphoreFuchsiaHandleKHR failed with result "
                     << result;
@@ -492,31 +510,38 @@
   FXL_DCHECK(iter != acquired_ids_.end());
   acquired_ids_.erase(iter);
 
-  zx::event release_fence;
-  zx_status_t status;
+  if (kSkipPresent) {
+    pending_images_.push_back({std::move(acquire_fence), index});
+  } else {
+    zx::event release_fence;
 
-  status = zx::event::create(0, &release_fence);
-  if (status != ZX_OK) return VK_ERROR_DEVICE_LOST;
+    zx_status_t status = zx::event::create(0, &release_fence);
+    if (status != ZX_OK)
+      return VK_ERROR_DEVICE_LOST;
 
-  zx::event image_release_fence;
-  status = release_fence.duplicate(ZX_RIGHT_SAME_RIGHTS, &image_release_fence);
-  if (status != ZX_OK) {
-    FXL_DLOG(ERROR) << "failed to duplicate release fence, "
-                       "zx::event::duplicate() failed with status "
-                    << status;
-    return VK_ERROR_DEVICE_LOST;
+    zx::event image_release_fence;
+    status = release_fence.duplicate(ZX_RIGHT_SAME_RIGHTS, &image_release_fence);
+    if (status != ZX_OK) {
+      FXL_DLOG(ERROR) << "failed to duplicate release fence, "
+                         "zx::event::duplicate() failed with status "
+                      << status;
+      return VK_ERROR_DEVICE_LOST;
+    }
+
+    pending_images_.push_back({std::move(image_release_fence), index});
+
+    fidl::VectorPtr<zx::event> acquire_fences;
+    acquire_fences.push_back(std::move(acquire_fence));
+
+    fidl::VectorPtr<zx::event> release_fences;
+    release_fences.push_back(std::move(release_fence));
+
+    fuchsia::images::PresentationInfo info;
+    image_pipe_->PresentImage(ImageIdFromIndex(index), 0,
+                              std::move(acquire_fences),
+                              std::move(release_fences), &info);
   }
 
-  pending_images_.push_back({std::move(image_release_fence), index});
-
-  fidl::VectorPtr<zx::event> release_fences;
-  release_fences.push_back(std::move(release_fence));
-
-  fuchsia::images::PresentationInfo info;
-  image_pipe_->PresentImage(ImageIdFromIndex(index), 0,
-                            std::move(acquire_fences),
-                            std::move(release_fences), &info);
-
   return VK_SUCCESS;
 }
 
@@ -643,7 +668,8 @@
   chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
 
   VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
-  if (result != VK_SUCCESS) return result;
+  if (result != VK_SUCCESS)
+    return result;
 
   LayerData* my_data =
       GetLayerDataPtr(get_dispatch_key(*pInstance), layer_data_map);
@@ -754,7 +780,8 @@
 GetInstanceProcAddr(VkInstance instance, const char* funcName);
 
 static inline PFN_vkVoidFunction layer_intercept_proc(const char* name) {
-  if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
+  if (!name || name[0] != 'v' || name[1] != 'k')
+    return NULL;
   name += 2;
   if (!strcmp(name, "GetDeviceProcAddr"))
     return reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr);
@@ -792,7 +819,8 @@
 
 static inline PFN_vkVoidFunction layer_intercept_instance_proc(
     const char* name) {
-  if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
+  if (!name || name[0] != 'v' || name[1] != 'k')
+    return NULL;
   name += 2;
   if (!strcmp(name, "GetInstanceProcAddr"))
     return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
@@ -835,7 +863,8 @@
 
   VkLayerDispatchTable* pTable = dev_data->device_dispatch_table;
 
-  if (pTable->GetDeviceProcAddr == NULL) return NULL;
+  if (pTable->GetDeviceProcAddr == NULL)
+    return NULL;
   return pTable->GetDeviceProcAddr(device, funcName);
 }
 
@@ -845,7 +874,8 @@
   LayerData* my_data;
 
   addr = layer_intercept_instance_proc(funcName);
-  if (!addr) addr = layer_intercept_proc(funcName);
+  if (!addr)
+    addr = layer_intercept_proc(funcName);
   if (addr) {
     return addr;
   }
@@ -872,7 +902,8 @@
   my_data = GetLayerDataPtr(get_dispatch_key(instance), layer_data_map);
   VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
 
-  if (pTable->GetPhysicalDeviceProcAddr == NULL) return NULL;
+  if (pTable->GetPhysicalDeviceProcAddr == NULL)
+    return NULL;
   return pTable->GetPhysicalDeviceProcAddr(instance, funcName);
 }
 
diff --git a/lib/vulkan/tests/vkcube/BUILD.gn b/lib/vulkan/tests/vkcube/BUILD.gn
index cc9a6c1..6f42255 100644
--- a/lib/vulkan/tests/vkcube/BUILD.gn
+++ b/lib/vulkan/tests/vkcube/BUILD.gn
@@ -45,4 +45,8 @@
     "//garnet/public/lib/ui/scenic",
     "//garnet/public/lib/ui/scenic:client",
   ]
+
+  public_deps = [
+    "//zircon/public/lib/fit",
+  ]
 }
diff --git a/lib/vulkan/tests/vkcube/vkcube_view.cc b/lib/vulkan/tests/vkcube/vkcube_view.cc
index 9633f28..26b2e93 100644
--- a/lib/vulkan/tests/vkcube/vkcube_view.cc
+++ b/lib/vulkan/tests/vkcube/vkcube_view.cc
@@ -9,14 +9,11 @@
 VkCubeView::VkCubeView(
     ::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
     fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request,
-    std::function<
-        void(float width, float height,
-             fidl::InterfaceHandle<fuchsia::images::ImagePipe> interface_request)>
-        resize_callback)
+    ResizeCallback resize_callback)
     : BaseView(std::move(view_manager), std::move(view_owner_request),
                "vkcube"),
       pane_node_(session()),
-      resize_callback_(resize_callback) {}
+      resize_callback_(std::move(resize_callback)) {}
 
 VkCubeView::~VkCubeView() {}
 
@@ -43,7 +40,7 @@
   zx::channel::create(0, &endpoint0, &endpoint1);
 
   uint32_t image_pipe_id = session()->AllocResourceId();
-  session()->Enqueue(scenic_lib::NewCreateImagePipeCommand(
+  session()->Enqueue(scenic_lib::NewCreateImagePipeCmd(
       image_pipe_id,
       fidl::InterfaceRequest<fuchsia::images::ImagePipe>(std::move(endpoint1))));
   pane_material.SetTexture(image_pipe_id);
diff --git a/lib/vulkan/tests/vkcube/vkcube_view.h b/lib/vulkan/tests/vkcube/vkcube_view.h
index a8db549..a93201f 100644
--- a/lib/vulkan/tests/vkcube/vkcube_view.h
+++ b/lib/vulkan/tests/vkcube/vkcube_view.h
@@ -8,6 +8,7 @@
 #include <fuchsia/images/cpp/fidl.h>
 #include <fuchsia/ui/gfx/cpp/fidl.h>
 #include <fuchsia/ui/views_v1_token/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include "lib/fxl/macros.h"
 #include "lib/ui/scenic/client/resources.h"
@@ -15,13 +16,14 @@
 
 class VkCubeView : public mozart::BaseView {
  public:
+  using ResizeCallback = fit::function<void(
+        float width, float height,
+        fidl::InterfaceHandle<fuchsia::images::ImagePipe> interface_request)>;
+
   VkCubeView(
       ::fuchsia::ui::views_v1::ViewManagerPtr view_manager,
       fidl::InterfaceRequest<::fuchsia::ui::views_v1_token::ViewOwner> view_owner_request,
-      std::function<
-          void(float width, float height,
-               fidl::InterfaceHandle<fuchsia::images::ImagePipe> interface_request)>
-          resize_callback);
+      ResizeCallback resize_callback);
   ~VkCubeView() override;
 
  private:
@@ -31,10 +33,7 @@
   fuchsia::math::SizeF size_;
   fuchsia::math::Size physical_size_;
   scenic_lib::ShapeNode pane_node_;
-  std::function<void(
-      float width, float height,
-      fidl::InterfaceHandle<fuchsia::images::ImagePipe> interface_request)>
-      resize_callback_;
+  ResizeCallback resize_callback_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(VkCubeView);
 };
diff --git a/lib/vulkan/third_party/vkcube/cube.h b/lib/vulkan/third_party/vkcube/cube.h
index e5860b7..f84fecc 100644
--- a/lib/vulkan/third_party/vkcube/cube.h
+++ b/lib/vulkan/third_party/vkcube/cube.h
@@ -91,6 +91,8 @@
   uint32_t num_frames = 60;
   uint32_t elapsed_frames = 0;
   std::chrono::time_point<std::chrono::high_resolution_clock> t0{};
+
+  FuchsiaState() : loop(&kAsyncLoopConfigMakeDefault) {}
 };
 #endif
 
diff --git a/lib/wlan/common/channel.cpp b/lib/wlan/common/channel.cpp
index e1a03a4..1ba1627 100644
--- a/lib/wlan/common/channel.cpp
+++ b/lib/wlan/common/channel.cpp
@@ -12,6 +12,8 @@
 namespace wlan {
 namespace common {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 const char* kCbwStr[] = {"CBW20", "CBW40", "CBW40B", "CBW80", "CBW160", "CBW80P80", "CBW_INV"};
 
 const char* kCbwSuffix[] = {
diff --git a/lib/wlan/common/include/wlan/common/channel.h b/lib/wlan/common/include/wlan/common/channel.h
index ce2e106..6c2f3f26 100644
--- a/lib/wlan/common/include/wlan/common/channel.h
+++ b/lib/wlan/common/include/wlan/common/channel.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <wlan/protocol/mac.h>
 
@@ -47,7 +47,7 @@
     // See IEEE Std 802.11-2016 19.3.15
 };
 
-wlan_channel_t FromFidl(const wlan_mlme::WlanChan& fidl_chan);
+wlan_channel_t FromFidl(const ::fuchsia::wlan::mlme::WlanChan& fidl_chan);
 
 }  // namespace common
 }  // namespace wlan
diff --git a/lib/wlan/common/include/wlan/common/mac_frame.h b/lib/wlan/common/include/wlan/common/mac_frame.h
index dae4456..829c210 100644
--- a/lib/wlan/common/include/wlan/common/mac_frame.h
+++ b/lib/wlan/common/include/wlan/common/mac_frame.h
@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <endian.h>
 #include <fbl/algorithm.h>
 #include <fbl/type_support.h>
 #include <lib/zx/time.h>
@@ -14,8 +15,6 @@
 #include <zircon/compiler.h>
 #include <zircon/types.h>
 
-#include <wlan_mlme/cpp/fidl.h>
-
 #include <cstdint>
 
 namespace wlan {
@@ -649,26 +648,31 @@
     // Note this is the same as the IEEE 802.3 frame format.
     common::MacAddr da;
     common::MacAddr sa;
-    uint16_t msdu_len;
+    uint16_t msdu_len_be;  // Stored in network byte order. Use accessors.
+
+    uint16_t msdu_len() const { return be16toh(msdu_len_be); }
+
+    void set_msdu_len(uint16_t msdu_len) { msdu_len_be = htobe16(msdu_len); }
 } __PACKED;
 
 // IEEE Std 802.11-2016, 9.3.2.2.3
 // Non-DMG stations do not transmit in this form.
 struct AmsduSubframeHeaderShort {
-    uint16_t msdu_len;
+    uint16_t msdu_len_be;
 } __PACKED;
 
 struct AmsduSubframe {
     AmsduSubframeHeader hdr;
     uint8_t msdu[];
-    // uint8_t padding[];
+    // msdu[] is followed by conditional zero-padding for alignment of the amsdu subframe by 4
+    // bytes.
 
     const LlcHeader* get_msdu() const { return reinterpret_cast<const LlcHeader*>(msdu); }
 
     size_t PaddingLen(bool is_last_subframe) const {
-        return (is_last_subframe) ? 0 : (fbl::round_up(hdr.msdu_len, 4u) - hdr.msdu_len);
+        size_t base_len = sizeof(AmsduSubframeHeader) + hdr.msdu_len();
+        return (is_last_subframe) ? 0 : (fbl::round_up(base_len, 4u) - base_len);
     }
-
 } __PACKED;
 
 // RFC 1042
diff --git a/lib/wlan/common/include/wlan/common/macaddr.h b/lib/wlan/common/include/wlan/common/macaddr.h
index 7793551..386cb95 100644
--- a/lib/wlan/common/include/wlan/common/macaddr.h
+++ b/lib/wlan/common/include/wlan/common/macaddr.h
@@ -9,7 +9,6 @@
 
 #include <algorithm>
 #include <cstddef>
-#include <functional>
 #include <string>
 
 namespace wlan {
diff --git a/lib/wlan/common/include/wlan/common/stats.h b/lib/wlan/common/include/wlan/common/stats.h
index 8515e0a..b9b90a9 100644
--- a/lib/wlan/common/include/wlan/common/stats.h
+++ b/lib/wlan/common/include/wlan/common/stats.h
@@ -4,13 +4,15 @@
 
 #pragma once
 
-#include <wlan_stats/c/fidl.h>
+#include <fuchsia/wlan/stats/cpp/fidl.h>
 
 #include <atomic>
 #include <string>
 
 namespace wlan {
 
+namespace wlan_stats = ::fuchsia::wlan::stats;
+
 constexpr bool kStatsDebugEnabled = false;
 
 #define WLAN_STATS_ADD(i, v)                                                        \
@@ -31,10 +33,10 @@
 struct Counter {
     std::atomic_uint64_t count{0};
     std::string name;  // Dynamically set at run-time
-    const wlan_stats_Counter ToFidl() const {
-        return wlan_stats_Counter{
+    const wlan_stats::Counter ToFidl() const {
+        return wlan_stats::Counter{
             .count = count.load(),
-            .name = fidl_string_t{.size = name.length(), .data = strdup(name.c_str())}};
+            .name = name};
     };
     uint64_t Inc(uint64_t i) { return count.fetch_add(i, std::memory_order_relaxed); }
 };
@@ -43,8 +45,8 @@
     Counter in;
     Counter out;
     Counter drop;
-    const wlan_stats_PacketCounter ToFidl() const {
-        return wlan_stats_PacketCounter{
+    const wlan_stats::PacketCounter ToFidl() const {
+        return wlan_stats::PacketCounter{
             .in = in.ToFidl(), .out = out.ToFidl(), .drop = drop.ToFidl()};
     };
 };
@@ -55,8 +57,8 @@
     PacketCounter mgmt_frame;
     PacketCounter ctrl_frame;
     PacketCounter data_frame;
-    const wlan_stats_DispatcherStats ToFidl() const {
-        return wlan_stats_DispatcherStats{.any_packet = any_packet.ToFidl(),
+    wlan_stats::DispatcherStats ToFidl() const {
+        return wlan_stats::DispatcherStats{.any_packet = any_packet.ToFidl(),
                                           .mgmt_frame = mgmt_frame.ToFidl(),
                                           .ctrl_frame = ctrl_frame.ToFidl(),
                                           .data_frame = data_frame.ToFidl()};
@@ -67,8 +69,8 @@
     PacketCounter svc_msg;
     PacketCounter data_frame;
     PacketCounter mgmt_frame;
-    const wlan_stats_ClientMlmeStats ToFidl() const {
-        return wlan_stats_ClientMlmeStats{.svc_msg = svc_msg.ToFidl(),
+    wlan_stats::ClientMlmeStats ToFidl() const {
+        return wlan_stats::ClientMlmeStats{.svc_msg = svc_msg.ToFidl(),
                                           .data_frame = data_frame.ToFidl(),
                                           .mgmt_frame = mgmt_frame.ToFidl()};
     };
@@ -78,7 +80,7 @@
 template <typename T, typename U> class WlanStats {
    public:
     T stats;
-    const U ToFidl() const { return stats.toFidl(); };
+    U ToFidl() const { return stats.ToFidl(); };
 };
 
 }  // namespace common
diff --git a/lib/wlan/fidl/BUILD.gn b/lib/wlan/fidl/BUILD.gn
index c16b975..8858ad0 100644
--- a/lib/wlan/fidl/BUILD.gn
+++ b/lib/wlan/fidl/BUILD.gn
@@ -5,7 +5,8 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "wlan_device"
+  name = "fuchsia.wlan.device"
+  cpp_legacy_callbacks = true
 
   sources = [
     "iface.fidl",
@@ -14,7 +15,8 @@
 }
 
 fidl("sme") {
-  name = "wlan_sme"
+  name = "fuchsia.wlan.sme"
+  cpp_legacy_callbacks = true
 
   sources = [
     "sme.fidl"
@@ -22,7 +24,8 @@
 }
 
 fidl("service") {
-  name = "wlan_device_service"
+  name = "fuchsia.wlan.device.service"
+  cpp_legacy_callbacks = true
 
   sources = [
     "service.fidl"
@@ -35,7 +38,8 @@
 }
 
 fidl("wlantap") {
-  name = "wlantap"
+  name = "fuchsia.wlan.tap"
+  cpp_legacy_callbacks = true
 
   sources = [
     "wlantap.fidl"
diff --git a/lib/wlan/fidl/iface.fidl b/lib/wlan/fidl/iface.fidl
index a30fe48..7aef018 100644
--- a/lib/wlan/fidl/iface.fidl
+++ b/lib/wlan/fidl/iface.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_device;
+library fuchsia.wlan.device;
 
 struct IfaceInfo {
     uint16 id;
diff --git a/lib/wlan/fidl/phy.fidl b/lib/wlan/fidl/phy.fidl
index 6380108..ed1a4e3 100644
--- a/lib/wlan/fidl/phy.fidl
+++ b/lib/wlan/fidl/phy.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_device;
+library fuchsia.wlan.device;
 
 enum ChannelBandwidth {
   CBW20 = 0;
diff --git a/lib/wlan/fidl/service.fidl b/lib/wlan/fidl/service.fidl
index 7422161..2a3d702 100644
--- a/lib/wlan/fidl/service.fidl
+++ b/lib/wlan/fidl/service.fidl
@@ -2,12 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_device_service;
+library fuchsia.wlan.device.service;
 
-using wlan_device;
+using fuchsia.wlan.device;
+using fuchsia.wlan.sme;
+
+struct PhyListItem {
+    uint16 phy_id;
+    string path;
+};
 
 struct ListPhysResponse {
-    vector<wlan_device.PhyInfo> phys;
+    vector<PhyListItem> phys;
 };
 
 struct QueryPhyRequest {
@@ -15,16 +21,16 @@
 };
 
 struct QueryPhyResponse {
-    wlan_device.PhyInfo info;
+    fuchsia.wlan.device.PhyInfo info;
 };
 
 struct ListIfacesResponse {
-    vector<wlan_device.IfaceInfo> ifaces;
+    vector<fuchsia.wlan.device.IfaceInfo> ifaces;
 };
 
 struct CreateIfaceRequest {
     uint16 phy_id;
-    wlan_device.MacRole role;
+    fuchsia.wlan.device.MacRole role;
 };
 
 struct CreateIfaceResponse {
@@ -36,6 +42,13 @@
     uint16 iface_id;
 };
 
+interface DeviceWatcher {
+    1: -> OnPhyAdded(uint16 phy_id);
+    2: -> OnPhyRemoved(uint16 phy_id);
+    3: -> OnIfaceAdded(uint16 iface_id);
+    4: -> OnIfaceRemoved(uint16 iface_id);
+};
+
 [Discoverable]
 interface DeviceService {
   // Phy methods
@@ -50,11 +63,7 @@
   // 19: reserved for StartIface
   // 20: reserved for StopIface
   21: DestroyIface(DestroyIfaceRequest req) -> (int32 @status);
-  22: GetClientSme(uint16 iface_id, request<wlan_sme.ClientSme> sme) -> (bool ok);
+  22: GetClientSme(uint16 iface_id, request<fuchsia.wlan.sme.ClientSme> sme) -> (bool ok);
 
-  // Device events
-  0x1000: -> OnPhyAdded(uint16 id);
-  0x1001: -> OnPhyRemoved(uint16 id);
-  0x1002: -> OnIfaceAdded(uint16 id);
-  0x1003: -> OnIfaceRemoved(uint16 id);
+  100: WatchDevices(request<DeviceWatcher> watcher);
 };
diff --git a/lib/wlan/fidl/sme.fidl b/lib/wlan/fidl/sme.fidl
index 36406ff..d94a4fa 100644
--- a/lib/wlan/fidl/sme.fidl
+++ b/lib/wlan/fidl/sme.fidl
@@ -1,4 +1,8 @@
-library wlan_sme;
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library fuchsia.wlan.sme;
 
 struct ScanResult {
     array<uint8>:6 bssid;
@@ -27,4 +31,4 @@
 
 interface ClientSme {
     1: Scan(ScanRequest req, request<ScanTransaction> txn);
-};
\ No newline at end of file
+};
diff --git a/lib/wlan/fidl/wlantap.fidl b/lib/wlan/fidl/wlantap.fidl
index 2d8536b..0f35972 100644
--- a/lib/wlan/fidl/wlantap.fidl
+++ b/lib/wlan/fidl/wlantap.fidl
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlantap;
+library fuchsia.wlan.tap;
 
-using wlan_device;
+using fuchsia.wlan.device;
 
 struct WlantapPhyConfig {
-  wlan_device.PhyInfo phy_info;
+  fuchsia.wlan.device.PhyInfo phy_info;
   string name;
 };
 
@@ -17,7 +17,7 @@
   uint32 valid_fields;
   uint16 phy;
   uint32 data_rate;
-  wlan_device.Channel chan;
+  fuchsia.wlan.device.Channel chan;
   uint8 mcs;
   int8 rssi_dbm;
   int16 rcpi_dbmh;
@@ -77,7 +77,7 @@
 
 struct SetChannelArgs {
   uint16 wlanmac_id;
-  wlan_device.Channel chan;
+  fuchsia.wlan.device.Channel chan;
 };
 
 struct ConfigureBssArgs {
diff --git a/lib/wlan/mlme/ap/ap_mlme.cpp b/lib/wlan/mlme/ap/ap_mlme.cpp
index ada9c7a..f1beb35 100644
--- a/lib/wlan/mlme/ap/ap_mlme.cpp
+++ b/lib/wlan/mlme/ap/ap_mlme.cpp
@@ -10,6 +10,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 ApMlme::ApMlme(DeviceInterface* device) : device_(device) {}
 
 ApMlme::~ApMlme() {
diff --git a/lib/wlan/mlme/ap/beacon_sender.cpp b/lib/wlan/mlme/ap/beacon_sender.cpp
index e7c9214..c3fc93c 100644
--- a/lib/wlan/mlme/ap/beacon_sender.cpp
+++ b/lib/wlan/mlme/ap/beacon_sender.cpp
@@ -11,12 +11,14 @@
 #include <wlan/mlme/mac_frame.h>
 #include <wlan/mlme/packet.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <zircon/assert.h>
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 BeaconSender::BeaconSender(DeviceInterface* device) : device_(device) {}
 
 BeaconSender::~BeaconSender() {
diff --git a/lib/wlan/mlme/ap/infra_bss.cpp b/lib/wlan/mlme/ap/infra_bss.cpp
index d1a439e..ce7a939 100644
--- a/lib/wlan/mlme/ap/infra_bss.cpp
+++ b/lib/wlan/mlme/ap/infra_bss.cpp
@@ -14,6 +14,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 InfraBss::InfraBss(DeviceInterface* device, fbl::unique_ptr<BeaconSender> bcn_sender,
                    const common::MacAddr& bssid)
     : bssid_(bssid), device_(device), bcn_sender_(fbl::move(bcn_sender)) {
diff --git a/lib/wlan/mlme/ap/remote_client.cpp b/lib/wlan/mlme/ap/remote_client.cpp
index a4bbbcc..985c246 100644
--- a/lib/wlan/mlme/ap/remote_client.cpp
+++ b/lib/wlan/mlme/ap/remote_client.cpp
@@ -11,6 +11,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 // BaseState implementation.
 
 template <typename S, typename... Args> void BaseState::MoveToState(Args&&... args) {
diff --git a/lib/wlan/mlme/client/bss.cpp b/lib/wlan/mlme/client/bss.cpp
index f5044f3..300061e 100644
--- a/lib/wlan/mlme/client/bss.cpp
+++ b/lib/wlan/mlme/client/bss.cpp
@@ -10,6 +10,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 // TODO(NET-500): This file needs some clean-up.
 
 zx_status_t Bss::ProcessBeacon(const Beacon& beacon, size_t frame_len,
@@ -118,6 +120,8 @@
     uint8_t ie_cnt = 0;
     uint8_t ie_unparsed_cnt = 0;
 
+    has_dsss_param_set_chan_ = false;
+
     char dbgmsghdr[128];
     while (reader.is_valid()) {
         ie_cnt++;
@@ -162,6 +166,7 @@
                 return ZX_ERR_INTERNAL;
             }
 
+            has_dsss_param_set_chan_ = true;
             dsss_param_set_chan_ = ie->current_chan;
             debugbcn("%s Current channel: %u\n", dbgmsghdr, ie->current_chan);
             break;
@@ -242,7 +247,13 @@
     fidl.beacon_period = bcn_interval_;  // TODO(porce): consistent naming.
     fidl.timestamp = timestamp_;
 
-    fidl.chan.primary = bcn_rx_chan_.primary;
+    if (has_dsss_param_set_chan_ == true) {
+        // Channel was explicitly announced by the AP
+        fidl.chan.primary = dsss_param_set_chan_;
+    } else {
+        // Fallback to the inference
+        fidl.chan.primary = bcn_rx_chan_.primary;
+    }
     fidl.chan.cbw = static_cast<wlan_mlme::CBW>(bcn_rx_chan_.cbw);
 
     // Stats
diff --git a/lib/wlan/mlme/client/client_mlme.cpp b/lib/wlan/mlme/client/client_mlme.cpp
index 4455484..13abc0c 100644
--- a/lib/wlan/mlme/client/client_mlme.cpp
+++ b/lib/wlan/mlme/client/client_mlme.cpp
@@ -14,7 +14,7 @@
 #include <wlan/mlme/timer.h>
 #include <wlan/mlme/wlan.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <lib/zx/time.h>
 #include <zircon/assert.h>
@@ -26,6 +26,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 ClientMlme::ClientMlme(DeviceInterface* device) : device_(device) {
     debugfn();
 }
@@ -108,4 +110,8 @@
     return ZX_OK;
 }
 
+wlan_stats::ClientMlmeStats ClientMlme::GetClientMlmeStats() const {
+    return sta_->stats();
+}
+
 }  // namespace wlan
diff --git a/lib/wlan/mlme/client/remote_ap.cpp b/lib/wlan/mlme/client/remote_ap.cpp
index 7556cb9..c0e1a8f 100644
--- a/lib/wlan/mlme/client/remote_ap.cpp
+++ b/lib/wlan/mlme/client/remote_ap.cpp
@@ -3,12 +3,17 @@
 // found in the LICENSE file.
 
 #include <wlan/common/channel.h>
+#include <wlan/common/mac_frame.h>
 #include <wlan/mlme/client/remote_ap.h>
+#include <wlan/mlme/debug.h>
 #include <wlan/mlme/packet.h>
 #include <wlan/mlme/service.h>
 #include <wlan/mlme/timer.h>
 
 namespace wlan {
+namespace remote_ap {
+
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
 
 // RemoteAp implementation.
 
@@ -105,6 +110,11 @@
     return chan;
 }
 
+bool RemoteAp::IsHTReady() const {
+    // TODO(porce): Test capabilites and configurations of the client and its BSS.
+    return true;
+}
+
 bool RemoteAp::IsCbw40RxReady() const {
     // TODO(porce): Test capabilites and configurations of the client and its BSS.
     return true;
@@ -116,6 +126,106 @@
     return false;
 }
 
+bool RemoteAp::IsQosReady() const {
+    // TODO(NET-567,NET-599): Determine for each outbound data frame,
+    // given the result of the dynamic capability negotiation, data frame
+    // classification, and QoS policy.
+
+    // Aruba / Ubiquiti are confirmed to be compatible with QoS field for the BlockAck session,
+    // independently of 40MHz operation.
+    return true;
+}
+
+bool RemoteAp::IsAmsduRxReady() const {
+    // [Interop]
+    // IEEE Std 802.11-2016 9.4.1.14's wording is ambiguous, and it can cause interop issue.
+    // In particular, a peer may tear off BlockAck session if interpretation of the field
+    // "A-MSDU Supported" in Block Ack Parameter set of ADDBA Request and Response is different.
+    // Declare such that Fuchsia "can do" AMSDU. This hints the peer that
+    // peer may assume that this Fuchsia device can process inbound A-MSDU data frame.
+    // Since the presence of A-MSDU frame is indicated in the "amsdu_present" field of
+    // QoS field in MPDU header, and the use of A-MSDU frame is optional in flight-time,
+    // setting "A-MSDU Supported" both in ADDBA Request and Response is deemed to be most
+    // interoperable way.
+    return false;
+}
+
+HtCapabilities RemoteAp::BuildHtCapabilities() {
+    // Static cooking for Proof-of-Concept
+    HtCapabilities htc;
+    HtCapabilityInfo& hci = htc.ht_cap_info;
+
+    hci.set_ldpc_coding_cap(0);  // Ralink RT5370 is incapable of LDPC.
+
+    if (IsCbw40RxReady()) {
+        hci.set_chan_width_set(HtCapabilityInfo::TWENTY_FORTY);
+    } else {
+        hci.set_chan_width_set(HtCapabilityInfo::TWENTY_ONLY);
+    }
+
+    hci.set_sm_power_save(HtCapabilityInfo::DISABLED);
+    hci.set_greenfield(0);
+    hci.set_short_gi_20(1);
+    hci.set_short_gi_40(1);
+    hci.set_tx_stbc(0);  // No plan to support STBC Tx
+    hci.set_rx_stbc(1);  // one stream.
+    hci.set_delayed_block_ack(0);
+    hci.set_max_amsdu_len(HtCapabilityInfo::OCTETS_7935);  // Aruba
+    // hci.set_max_amsdu_len(HtCapabilityInfo::OCTETS_3839);  // TP-Link
+    hci.set_dsss_in_40(0);
+    hci.set_intolerant_40(0);
+    hci.set_lsig_txop_protect(0);
+
+    AmpduParams& ampdu = htc.ampdu_params;
+    ampdu.set_exponent(3);                                // 65535 bytes
+    ampdu.set_min_start_spacing(AmpduParams::FOUR_USEC);  // Aruba
+    // ampdu.set_min_start_spacing(AmpduParams::EIGHT_USEC);  // TP-Link
+    // ampdu.set_min_start_spacing(AmpduParams::SIXTEEN_USEC);
+
+    SupportedMcsSet& mcs = htc.mcs_set;
+    mcs.rx_mcs_head.set_bitmask(0xff);  // MCS 0-7
+    // mcs.rx_mcs_head.set_bitmask(0xffff);  // MCS 0-15
+    mcs.tx_mcs.set_set_defined(1);  // Aruba
+
+    HtExtCapabilities& hec = htc.ht_ext_cap;
+    hec.set_pco(0);
+    hec.set_pco_transition(HtExtCapabilities::PCO_RESERVED);
+    hec.set_mcs_feedback(HtExtCapabilities::MCS_NOFEEDBACK);
+    hec.set_htc_ht_support(0);
+    hec.set_rd_responder(0);
+
+    TxBfCapability& txbf = htc.txbf_cap;
+    txbf.set_implicit_rx(0);
+    txbf.set_rx_stag_sounding(0);
+    txbf.set_tx_stag_sounding(0);
+    txbf.set_rx_ndp(0);
+    txbf.set_tx_ndp(0);
+    txbf.set_implicit(0);
+    txbf.set_calibration(TxBfCapability::CALIBRATION_NONE);
+    txbf.set_csi(0);
+    txbf.set_noncomp_steering(0);
+    txbf.set_comp_steering(0);
+    txbf.set_csi_feedback(TxBfCapability::FEEDBACK_NONE);
+    txbf.set_noncomp_feedback(TxBfCapability::FEEDBACK_NONE);
+    txbf.set_comp_feedback(TxBfCapability::FEEDBACK_NONE);
+    txbf.set_min_grouping(TxBfCapability::MIN_GROUP_ONE);
+    txbf.set_csi_antennas_human(1);           // 1 antenna
+    txbf.set_noncomp_steering_ants_human(1);  // 1 antenna
+    txbf.set_comp_steering_ants_human(1);     // 1 antenna
+    txbf.set_csi_rows_human(1);               // 1 antenna
+    txbf.set_chan_estimation_human(1);        // # space-time stream
+
+    AselCapability& asel = htc.asel_cap;
+    asel.set_asel(0);
+    asel.set_csi_feedback_tx_asel(0);
+    asel.set_explicit_csi_feedback(0);
+    asel.set_antenna_idx_feedback(0);
+    asel.set_rx_asel(0);
+    asel.set_tx_sounding_ppdu(0);
+
+    return htc;  // 28 bytes.
+}
+
 // BaseState implementation.
 
 template <typename S, typename... Args> void RemoteAp::BaseState::MoveToState(Args&&... args) {
@@ -192,4 +302,305 @@
 
 JoinedState::JoinedState(RemoteAp* ap) : RemoteAp::BaseState(ap) {}
 
-}  // namespace wlan
\ No newline at end of file
+zx_status_t JoinedState::HandleMlmeAuthReq(const wlan_mlme::AuthenticateRequest& req) {
+    debugfn();
+
+    debugjoin("[ap] [%s] received MLME-AUTHENTICATION.request\n", ap_->bssid_str());
+
+    // TODO(tkilbourn): better result codes
+    common::MacAddr peer_sta_addr(req.peer_sta_address.data());
+    if (ap_->bssid() != peer_sta_addr) {
+        errorf("[ap] [%s] received authentication request for other BSS\n", ap_->bssid_str());
+        return service::SendAuthConfirm(ap_->device(), ap_->bssid(),
+                                        wlan_mlme::AuthenticateResultCodes::REFUSED);
+    }
+
+    if (req.auth_type != wlan_mlme::AuthenticationTypes::OPEN_SYSTEM) {
+        // TODO(tkilbourn): support other authentication types
+        // TODO(tkilbourn): set the auth_alg_ when we support other authentication types
+        errorf("[ap] [%s] only OpenSystem authentication is supported\n", ap_->bssid_str());
+        return service::SendAuthConfirm(ap_->device(), ap_->bssid(),
+                                        wlan_mlme::AuthenticateResultCodes::REFUSED);
+    }
+
+    MgmtFrame<Authentication> frame;
+    auto status = BuildMgmtFrame(&frame);
+    if (status != ZX_OK) {
+        errorf("[ap] [%s] authing: failed to build a frame\n", ap_->bssid_str());
+        return service::SendAuthConfirm(ap_->device(), ap_->bssid(),
+                                        wlan_mlme::AuthenticateResultCodes::REFUSED);
+    }
+
+    auto hdr = frame.hdr();
+    const common::MacAddr& client_addr = ap_->device()->GetState()->address();
+    hdr->addr1 = ap_->bssid();
+    hdr->addr2 = client_addr;
+    hdr->addr3 = ap_->bssid();
+    SetSeqNo(hdr, ap_->seq());
+    frame.FillTxInfo();
+
+    // Only Open System authentication is supported so far.
+    auto auth = frame.body();
+    auth->auth_algorithm_number = AuthAlgorithm::kOpenSystem;
+    auth->auth_txn_seq_number = 1;
+    auth->status_code = 0;  // Reserved: set to 0
+
+    finspect("Outbound Mgmt Frame(Auth): %s\n", debug::Describe(*hdr).c_str());
+    status = ap_->device()->SendWlan(frame.take());
+    if (status != ZX_OK) {
+        errorf("[ap] [%s] could not send auth packet: %d\n", ap_->bssid_str(), status);
+        service::SendAuthConfirm(ap_->device(), ap_->bssid(),
+                                 wlan_mlme::AuthenticateResultCodes::REFUSED);
+        return status;
+    }
+
+    MoveToState<AuthenticatingState>(AuthAlgorithm::kOpenSystem, req.auth_failure_timeout);
+    return status;
+}
+
+// AuthenticatingState implementation.
+
+AuthenticatingState::AuthenticatingState(RemoteAp* ap, AuthAlgorithm auth_alg,
+                                         wlan_tu_t auth_timeout_tu)
+    : RemoteAp::BaseState(ap), auth_alg_(auth_alg) {
+    auth_deadline_ = ap_->CreateTimerDeadline(auth_timeout_tu);
+    auto status = ap_->StartTimer(auth_deadline_);
+    if (status != ZX_OK) {
+        errorf("[ap] [%s] could not set auth timer: %d\n", ap_->bssid_str(), status);
+
+        // This is the wrong result code, but we need to define our own codes at some later time.
+        MoveOn<JoinedState>(wlan_mlme::AuthenticateResultCodes::AUTHENTICATION_REJECTED);
+    }
+}
+
+void AuthenticatingState::OnExit() {
+    ap_->CancelTimer();
+}
+
+void AuthenticatingState::HandleTimeout() {
+    if (ap_->IsDeadlineExceeded(auth_deadline_)) {
+        auth_deadline_ = zx::time();
+        ap_->CancelTimer();
+
+        MoveOn<JoinedState>(wlan_mlme::AuthenticateResultCodes::AUTH_FAILURE_TIMEOUT);
+    }
+}
+
+zx_status_t AuthenticatingState::HandleAuthentication(const MgmtFrame<Authentication>& frame) {
+    debugfn();
+
+    // Received Authentication response; cancel timeout
+    auth_deadline_ = zx::time();
+    ap_->CancelTimer();
+
+    auto auth = frame.body();
+    if (auth->auth_algorithm_number != auth_alg_) {
+        errorf("[ap] [%s] mismatched authentication algorithm (expected %u, got %u)\n",
+               ap_->bssid_str(), auth_alg_, auth->auth_algorithm_number);
+        MoveOn<JoinedState>(wlan_mlme::AuthenticateResultCodes::AUTHENTICATION_REJECTED);
+        return ZX_ERR_BAD_STATE;
+    }
+
+    // TODO(tkilbourn): this only makes sense for Open System.
+    if (auth->auth_txn_seq_number != 2) {
+        errorf("[ap] [%s] unexpected auth txn sequence number (expected 2, got %u)\n",
+               ap_->bssid_str(), auth->auth_txn_seq_number);
+        MoveOn<JoinedState>(wlan_mlme::AuthenticateResultCodes::AUTHENTICATION_REJECTED);
+        return ZX_ERR_BAD_STATE;
+    }
+
+    if (auth->status_code != status_code::kSuccess) {
+        errorf("[ap] [%s] authentication failed (status code=%u)\n", ap_->bssid_str(),
+               auth->status_code);
+        // TODO(tkilbourn): is this the right result code?
+        MoveOn<JoinedState>(wlan_mlme::AuthenticateResultCodes::AUTHENTICATION_REJECTED);
+        return ZX_ERR_BAD_STATE;
+    }
+
+    debugjoin("[ap] [%s] authenticated\n", ap_->bssid_str());
+    MoveOn<AuthenticatedState>(wlan_mlme::AuthenticateResultCodes::SUCCESS);
+    return ZX_OK;
+}
+
+template <typename State>
+void AuthenticatingState::MoveOn(wlan_mlme::AuthenticateResultCodes result_code) {
+    service::SendAuthConfirm(ap_->device(), ap_->bssid(), result_code);
+    MoveToState<State>();
+}
+
+// AuthenticatedState implementation.
+
+AuthenticatedState::AuthenticatedState(RemoteAp* ap) : RemoteAp::BaseState(ap) {}
+
+zx_status_t AuthenticatedState::HandleMlmeAssocReq(const wlan_mlme::AssociateRequest& req) {
+    debugfn();
+
+    // TODO(tkilbourn): better result codes
+    common::MacAddr peer_sta_addr(req.peer_sta_address.data());
+    if (ap_->bssid() != peer_sta_addr) {
+        errorf("bad peer STA address for association\n");
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return ZX_OK;
+    }
+
+    debugjoin("associating to %s\n", ap_->bssid_str());
+
+    size_t body_payload_len = 128;
+    MgmtFrame<AssociationRequest> frame;
+    auto status = BuildMgmtFrame(&frame, body_payload_len);
+    if (status != ZX_OK) {
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return ZX_ERR_NO_RESOURCES;
+    }
+
+    // TODO(tkilbourn): a lot of this is hardcoded for now. Use device capabilities to set up the
+    // request.
+    auto hdr = frame.hdr();
+    const common::MacAddr& client_addr = ap_->device()->GetState()->address();
+    hdr->addr1 = ap_->bssid();
+    hdr->addr2 = client_addr;
+    hdr->addr3 = ap_->bssid();
+    SetSeqNo(hdr, ap_->seq());
+    frame.FillTxInfo();
+
+    auto assoc = frame.body();
+    assoc->cap.set_ess(1);
+    assoc->cap.set_short_preamble(0);  // For robustness. TODO(porce): Enforce Ralink
+    assoc->listen_interval = 0;
+
+    ElementWriter w(assoc->elements, frame.body_len() - sizeof(AssociationRequest));
+    if (!w.write<SsidElement>(ap_->bss().ssid->data())) {
+        errorf("could not write ssid \"%s\" to association request\n", ap_->bss().ssid->data());
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return ZX_ERR_IO;
+    }
+
+    // TODO(tkilbourn): determine these rates based on hardware and the AP
+    std::vector<uint8_t> rates = {0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24};
+    if (!w.write<SupportedRatesElement>(fbl::move(rates))) {
+        errorf("could not write supported rates\n");
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return ZX_ERR_IO;
+    }
+
+    std::vector<uint8_t> ext_rates = {0x30, 0x48, 0x60, 0x6c};
+    if (!w.write<ExtendedSupportedRatesElement>(fbl::move(ext_rates))) {
+        errorf("could not write extended supported rates\n");
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return ZX_ERR_IO;
+    }
+
+    // Write RSNE from MLME-Association.request if available.
+    if (req.rsn) {
+        if (!w.write<RsnElement>(req.rsn->data(), req.rsn->size())) {
+            errorf("could not write RSNE\n");
+            service::SendAssocConfirm(ap_->device(),
+                                      wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+            return ZX_ERR_IO;
+        }
+    }
+
+    if (ap_->IsHTReady()) {
+        HtCapabilities htc = ap_->BuildHtCapabilities();
+        if (!w.write<HtCapabilities>(htc.ht_cap_info, htc.ampdu_params, htc.mcs_set, htc.ht_ext_cap,
+                                     htc.txbf_cap, htc.asel_cap)) {
+            errorf("could not write HtCapabilities\n");
+            service::SendAssocConfirm(ap_->device(),
+                                      wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+            return ZX_ERR_IO;
+        }
+    }
+
+    // Validate the request in debug mode
+    ZX_DEBUG_ASSERT(assoc->Validate(w.size()));
+
+    size_t body_len = sizeof(AssociationRequest) + w.size();
+    status = frame.set_body_len(body_len);
+    if (status != ZX_OK) {
+        errorf("could not set body length to %zu: %d\n", body_len, status);
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return status;
+    }
+
+    finspect("Outbound Mgmt Frame (AssocReq): %s\n", debug::Describe(*hdr).c_str());
+    status = ap_->device()->SendWlan(frame.take());
+    if (status != ZX_OK) {
+        errorf("could not send assoc packet: %d\n", status);
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        return status;
+    }
+
+    MoveToState<AssociatingState>();
+    return status;
+}
+
+// AssociatingState implementation.
+
+AssociatingState::AssociatingState(RemoteAp* ap) : RemoteAp::BaseState(ap) {
+    // TODO(tkilbourn): get the assoc timeout from somewhere
+    assoc_deadline_ = ap_->CreateTimerDeadline(kAssocTimeoutTu);
+    auto status = ap_->StartTimer(assoc_deadline_);
+    if (status != ZX_OK) {
+        errorf("could not set auth timer: %d\n", status);
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        MoveToState<AuthenticatedState>();
+    }
+}
+
+void AssociatingState::OnExit() {
+    ap_->CancelTimer();
+}
+
+void AssociatingState::HandleTimeout() {
+    if (ap_->IsDeadlineExceeded(assoc_deadline_)) {
+        assoc_deadline_ = zx::time();
+        ap_->CancelTimer();
+
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        MoveToState<AuthenticatedState>();
+    }
+}
+
+zx_status_t AssociatingState::HandleAssociationResponse(
+    const MgmtFrame<AssociationResponse>& frame) {
+    debugfn();
+
+    // Associations response received; cancel timer and evaluate response.
+    assoc_deadline_ = zx::time();
+    ap_->CancelTimer();
+
+    auto assoc = frame.body();
+    if (assoc->status_code != status_code::kSuccess) {
+        errorf("association failed (status code=%u)\n", assoc->status_code);
+        // TODO(tkilbourn): map to the correct result code
+        service::SendAssocConfirm(ap_->device(),
+                                  wlan_mlme::AssociateResultCodes::REFUSED_REASON_UNSPECIFIED);
+        MoveToState<AuthenticatedState>();
+        return ZX_OK;
+    }
+
+    aid_t aid = assoc->aid & kAidMask;
+    service::SendAssocConfirm(ap_->device(), wlan_mlme::AssociateResultCodes::SUCCESS);
+    MoveToState<AssociatedState>(aid);
+    return ZX_OK;
+}
+
+// AssociatedState implementation.
+
+AssociatedState::AssociatedState(RemoteAp* ap, aid_t aid) : RemoteAp::BaseState(ap) {
+    infof("associated to: %zu\n", aid);
+
+    // TODO(hahnr): Setup link status, signal report and send ADDBA request.
+}
+
+}  // namespace remote_ap
+}  // namespace wlan
diff --git a/lib/wlan/mlme/client/scanner.cpp b/lib/wlan/mlme/client/scanner.cpp
index 207ff98..1dc8153 100644
--- a/lib/wlan/mlme/client/scanner.cpp
+++ b/lib/wlan/mlme/client/scanner.cpp
@@ -13,7 +13,7 @@
 #include <wlan/mlme/timer.h>
 #include <wlan/mlme/wlan.h>
 
-#include <wlan_mlme/c/fidl.h>
+#include <fuchsia/wlan/mlme/c/fidl.h>
 #include "lib/fidl/cpp/vector.h"
 
 #include <fbl/unique_ptr.h>
@@ -25,6 +25,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 // TODO(NET-500): The way we handle Beacons and ProbeResponses in here is kinda gross. Refactor.
 
 Scanner::Scanner(DeviceInterface* device, fbl::unique_ptr<Timer> timer)
@@ -352,7 +354,7 @@
 
     auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
     packet->set_peer(Packet::Peer::kService);
-    zx_status_t status = SerializeServiceMsg(packet.get(), wlan_mlme_MLMEScanConfOrdinal, resp_.get());
+    zx_status_t status = SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEScanConfOrdinal, resp_.get());
     if (status != ZX_OK) {
         errorf("could not serialize ScanResponse: %d\n", status);
     } else {
diff --git a/lib/wlan/mlme/client/station.cpp b/lib/wlan/mlme/client/station.cpp
index 2e8360a..7b2e510 100644
--- a/lib/wlan/mlme/client/station.cpp
+++ b/lib/wlan/mlme/client/station.cpp
@@ -16,14 +16,16 @@
 #include <wlan/mlme/service.h>
 #include <wlan/mlme/timer.h>
 
-#include <wlan_mlme/c/fidl.h>
-#include <wlan_stats/c/fidl.h>
+#include <fuchsia/wlan/mlme/c/fidl.h>
 
 #include <cstring>
 #include <utility>
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+using common::dBm;
+
 // TODO(hahnr): Revisit frame construction to reduce boilerplate code.
 
 static constexpr size_t kAssocBcnCountTimeout = 20;
@@ -50,7 +52,7 @@
 zx_status_t Station::HandleMlmeMessage(uint32_t ordinal) {
     WLAN_STATS_INC(svc_msg.in);
     // Always allow MLME-JOIN.request.
-    if (ordinal == wlan_mlme_MLMEJoinReqOrdinal) { return ZX_OK; }
+    if (ordinal == fuchsia_wlan_mlme_MLMEJoinReqOrdinal) { return ZX_OK; }
     // Drop other MLME requests if there is no BSSID set yet.
     return (bssid() == nullptr ? ZX_ERR_STOP : ZX_OK);
 }
@@ -374,7 +376,7 @@
     debugfn();
     ZX_DEBUG_ASSERT(bss_ != nullptr);
 
-    avg_rssi_dbm_.add(frame.rx_info()->rssi_dbm);
+    avg_rssi_dbm_.add(dBm(frame.rx_info()->rssi_dbm));
 
     // TODO(tkilbourn): update any other info (like rolling average of rssi)
     last_seen_ = timer_->Now();
@@ -504,7 +506,7 @@
     signal_report_timeout_ = deadline_after_bcn_period(kSignalReportBcnCountTimeout);
     timer_->SetTimer(signal_report_timeout_);
     avg_rssi_dbm_.reset();
-    avg_rssi_dbm_.add(frame.rx_info()->rssi_dbm);
+    avg_rssi_dbm_.add(dBm(frame.rx_info()->rssi_dbm));
     service::SendSignalReportIndication(device_, common::dBm(frame.rx_info()->rssi_dbm));
 
     // Open port if user connected to an open network.
@@ -633,7 +635,7 @@
     ZX_DEBUG_ASSERT(state_ == WlanState::kAssociated);
 
     // Take signal strength into account.
-    avg_rssi_dbm_.add(frame.rx_info()->rssi_dbm);
+    avg_rssi_dbm_.add(dBm(frame.rx_info()->rssi_dbm));
 
     // Some AP's such as Netgear Routers send periodic NULL data frames to test whether a client
     // timed out. The client must respond with a NULL data frame itself to not get
@@ -668,7 +670,7 @@
     }
 
     // Take signal strength into account.
-    avg_rssi_dbm_.add(frame.rx_info()->rssi_dbm);
+    avg_rssi_dbm_.add(dBm(frame.rx_info()->rssi_dbm));
 
     auto hdr = frame.hdr();
     auto llc = frame.body();
@@ -695,6 +697,12 @@
     // PS-POLL if there are more buffered unicast frames.
     if (hdr->fc.more_data() && hdr->addr1.IsUcast()) { SendPsPoll(); }
 
+    if (frame.hdr()->fc.subtype() == DataSubtype::kQosdata &&
+        hdr->qos_ctrl()->amsdu_present() == 1) {
+        // TODO(porce): Adopt FrameHandler 2.0
+        return HandleAmsduFrame(frame);
+    }
+
     ZX_DEBUG_ASSERT(frame.body_len() >= sizeof(LlcHeader));
     if (frame.body_len() < sizeof(LlcHeader)) {
         errorf("Inbound LLC frame too short (%zu bytes). Drop.", frame.body_len());
@@ -707,6 +715,11 @@
                                     const common::MacAddr& dest, const common::MacAddr& src) {
     auto llc_payload_len = llc_frame_len - sizeof(LlcHeader);
 
+    finspect("Inbound LLC frame: len %zu\n", llc_frame_len);
+    finspect("  llc hdr: %s\n", debug::Describe(llc_frame).c_str());
+    auto payload = reinterpret_cast<const uint8_t*>(&llc_frame) + sizeof(LlcHeader);
+    finspect("  llc payload: %s\n", debug::HexDump(payload, llc_payload_len).c_str());
+
     // Prepare a packet
     const size_t eth_len = llc_payload_len + sizeof(EthernetII);
     auto buffer = GetBuffer(eth_len);
@@ -728,6 +741,7 @@
 }
 
 zx_status_t Station::HandleAmsduFrame(const DataFrame<LlcHeader>& frame) {
+    // TODO(porce): Define A-MSDU or MSDU signature, and avoid forceful conversion.
     debugfn();
 
     ZX_DEBUG_ASSERT(frame.hdr()->fc.subtype() >= DataSubtype::kQosdata);
@@ -745,15 +759,15 @@
         return ZX_ERR_STOP;
     }
 
+    // LLC frame should be interpreted as A-MSDU
     auto amsdu = reinterpret_cast<const uint8_t*>(frame.body());
 
-    size_t offset = 0;        // Tracks up to which point of byte stream is parsed.
-    size_t offset_prev = -1;  // For debugging. Catch buggy situation
+    finspect("Inbound AMSDU: len %zu\n", amsdu_len);
+
+    size_t offset = 0;  // Tracks up to which point of byte stream is parsed.
 
     while (offset < amsdu_len) {
-        ZX_DEBUG_ASSERT(offset > offset_prev);  // Otherwise infinite loop
-        offset_prev = offset;
-
+        size_t offset_prev = offset;
         auto subframe = reinterpret_cast<const AmsduSubframe*>(amsdu + offset);
 
         if (!(offset + sizeof(AmsduSubframeHeader) <= amsdu_len)) {
@@ -763,8 +777,15 @@
                 amsdu_len, offset, offset_prev, sizeof(AmsduSubframeHeader));
             return ZX_ERR_STOP;
         }
+
+        finspect("amsdu subframe: %s\n", debug::Describe(*subframe).c_str());
+        finspect(
+            "amsdu subframe dump: %s\n",
+            debug::HexDump(reinterpret_cast<const uint8_t*>(subframe), sizeof(AmsduSubframeHeader))
+                .c_str());
+
         offset += sizeof(AmsduSubframeHeader);
-        auto msdu_len = subframe->hdr.msdu_len;
+        auto msdu_len = subframe->hdr.msdu_len();
 
         // Note: msdu_len == 0 is valid
 
@@ -785,6 +806,8 @@
         // Skip by zero-padding
         bool is_last_subframe = (offset == amsdu_len);
         offset += subframe->PaddingLen(is_last_subframe);
+
+        ZX_DEBUG_ASSERT(offset > offset_prev);  // Otherwise infinite loop
     }
 
     return ZX_OK;
@@ -927,7 +950,7 @@
         state_ == WlanState::kAssociated) {
         signal_report_timeout_ = deadline_after_bcn_period(kSignalReportBcnCountTimeout);
         timer_->SetTimer(signal_report_timeout_);
-        service::SendSignalReportIndication(device_, common::dBm(avg_rssi_dbm_.avg()));
+        service::SendSignalReportIndication(device_, common::to_dBm(avg_rssi_dbm_.avg()));
     }
 
     return ZX_OK;
@@ -1132,6 +1155,7 @@
 }
 
 void Station::DumpDataFrame(const DataFrame<LlcHeader>& frame) {
+    // TODO(porce): Should change the API signature to MSDU
     const common::MacAddr& mymac = device_->GetState()->address();
 
     auto hdr = frame.hdr();
@@ -1147,13 +1171,11 @@
 
     if (!is_interesting) { return; }
 
-    size_t payload_len = frame.body_len() - sizeof(LlcHeader);
-    auto llc = frame.body();
+    auto msdu = reinterpret_cast<const uint8_t*>(frame.body());
 
     finspect("Inbound data frame: len %zu\n", frame.len());
     finspect("  wlan hdr: %s\n", debug::Describe(*hdr).c_str());
-    finspect("  llc  hdr: %s\n", debug::Describe(*llc).c_str());
-    finspect("  payload : %s\n", debug::HexDump(llc->payload, payload_len).c_str());
+    finspect("  msdu    : %s\n", debug::HexDump(msdu, frame.body_len()).c_str());
 }
 
 zx_status_t Station::SetPowerManagementMode(bool ps_mode) {
@@ -1262,7 +1284,7 @@
     // QoS field in MPDU header, and the use of A-MSDU frame is optional in flight-time,
     // setting "A-MSDU Supported" both in ADDBA Request and Response is deemed to be most
     // interoperable way.
-    return false;
+    return true;
 }
 
 HtCapabilities Station::BuildHtCapabilities() const {
@@ -1361,4 +1383,8 @@
 uint8_t Station::GetTid(const EthFrame& frame) {
     return GetTid();
 }
+
+const wlan_stats::ClientMlmeStats& Station::stats() {
+  return std::move(stats_.ToFidl());
+}
 }  // namespace wlan
diff --git a/lib/wlan/mlme/debug.cpp b/lib/wlan/mlme/debug.cpp
index 3c1f29b..316a372 100644
--- a/lib/wlan/mlme/debug.cpp
+++ b/lib/wlan/mlme/debug.cpp
@@ -312,6 +312,14 @@
     return std::string(buf);
 }
 
+std::string Describe(const AmsduSubframe& s) {
+    char buf[128];
+    size_t offset = 0;
+    BUFFER("[da] %s [sa] %s [msdu_len] %u", s.hdr.da.ToString().c_str(),
+           s.hdr.sa.ToString().c_str(), s.hdr.msdu_len());
+    return std::string(buf);
+}
+
 std::string DescribeSuppressed(const Packet& p) {
     auto hdr = p.field<FrameHeader>(0);
 
diff --git a/lib/wlan/mlme/dispatcher.cpp b/lib/wlan/mlme/dispatcher.cpp
index ff2515a..87feb8d 100644
--- a/lib/wlan/mlme/dispatcher.cpp
+++ b/lib/wlan/mlme/dispatcher.cpp
@@ -16,11 +16,11 @@
 #include <wlan/mlme/packet.h>
 #include <wlan/mlme/service.h>
 #include <wlan/protocol/mac.h>
+#include <zircon/fidl.h>
 #include <zircon/types.h>
 
-#include <wlan_mlme/c/fidl.h>
-#include <wlan_mlme/cpp/fidl.h>
-#include <wlan_stats/c/fidl.h>
+#include <fuchsia/wlan/mlme/c/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <atomic>
 #include <cinttypes>
@@ -29,6 +29,8 @@
 
 namespace wlan {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 Dispatcher::Dispatcher(DeviceInterface* device, fbl::unique_ptr<Mlme> mlme)
     : device_(device), mlme_(std::move(mlme)) {
     debugfn();
@@ -363,36 +365,40 @@
     }
     debughdr("service packet txid=%u flags=%u ordinal=%u\n", hdr->txid, hdr->flags, hdr->ordinal);
 
-    if (hdr->ordinal == wlan_mlme_MLMEDeviceQueryReqOrdinal) {
+    if (hdr->ordinal == fuchsia_wlan_mlme_MLMEDeviceQueryReqOrdinal) {
         return HandleMlmeMethod<wlan_mlme::DeviceQueryRequest>(fbl::move(packet), hdr->ordinal);
     }
 
+    if (hdr->ordinal == fuchsia_wlan_mlme_MLMEStatsQueryReqOrdinal) {
+        return HandleMlmeStats(hdr->ordinal);
+    }
+
     switch (hdr->ordinal) {
-    case wlan_mlme_MLMEResetReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEResetReqOrdinal:
         infof("resetting MLME\n");
         HandleMlmeMethod<wlan_mlme::ResetRequest>(fbl::move(packet), hdr->ordinal);
         return ZX_OK;
-    case wlan_mlme_MLMEStartReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEStartReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::StartRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEStopReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEStopReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::StopRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEScanReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEScanReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::ScanRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEJoinReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEJoinReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::JoinRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEAuthenticateReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEAuthenticateReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::AuthenticateRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEAuthenticateRespOrdinal:
+    case fuchsia_wlan_mlme_MLMEAuthenticateRespOrdinal:
         return HandleMlmeMethod<wlan_mlme::AuthenticateResponse>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEDeauthenticateReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEDeauthenticateReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::DeauthenticateRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEAssociateReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEAssociateReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::AssociateRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEAssociateRespOrdinal:
+    case fuchsia_wlan_mlme_MLMEAssociateRespOrdinal:
         return HandleMlmeMethod<wlan_mlme::AssociateResponse>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMEEapolReqOrdinal:
+    case fuchsia_wlan_mlme_MLMEEapolReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::EapolRequest>(fbl::move(packet), hdr->ordinal);
-    case wlan_mlme_MLMESetKeysReqOrdinal:
+    case fuchsia_wlan_mlme_MLMESetKeysReqOrdinal:
         return HandleMlmeMethod<wlan_mlme::SetKeysRequest>(fbl::move(packet), hdr->ordinal);
     default:
         warnf("unknown MLME method %u\n", hdr->ordinal);
@@ -411,11 +417,29 @@
     return mlme_->HandleFrame(ordinal, msg);
 }
 
+template <typename T> zx_status_t Dispatcher::SendServiceMessage(uint32_t ordinal, T* msg) const {
+  // fidl2 doesn't have a way to get the serialized size yet. 4096 bytes should be enough for
+  // everyone.
+  size_t buf_len = 4096;
+  // size_t buf_len = sizeof(fidl_message_header_t) + resp->GetSerializedSize();
+  fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
+  if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }
+
+  auto packet = fbl::make_unique<Packet>(std::move(buffer), buf_len);
+  packet->set_peer(Packet::Peer::kService);
+  zx_status_t status = SerializeServiceMsg(packet.get(), ordinal, msg);
+  if (status != ZX_OK) {
+    errorf("could not serialize message with ordinal %d: %d\n", ordinal, status);
+    return status;
+  }
+  return device_->SendService(std::move(packet));
+}
+
 template <>
 zx_status_t Dispatcher::HandleMlmeMethod<wlan_mlme::DeviceQueryRequest>(fbl::unique_ptr<Packet> _,
                                                                         uint32_t ordinal) {
     debugfn();
-    ZX_DEBUG_ASSERT(ordinal == wlan_mlme_MLMEDeviceQueryReqOrdinal);
+    ZX_DEBUG_ASSERT(ordinal == fuchsia_wlan_mlme_MLMEDeviceQueryReqOrdinal);
 
     wlan_mlme::DeviceQueryConfirm resp;
     const wlanmac_info_t& info = device_->GetWlanInfo();
@@ -455,23 +479,29 @@
         resp.bands->push_back(std::move(band));
     }
 
-    // fidl2 doesn't have a way to get the serialized size yet. 4096 bytes should be enough for
-    // everyone.
-    size_t buf_len = 4096;
-    // size_t buf_len = sizeof(fidl_message_header_t) + resp->GetSerializedSize();
-    fbl::unique_ptr<Buffer> buffer = GetBuffer(buf_len);
-    if (buffer == nullptr) { return ZX_ERR_NO_RESOURCES; }
+    return SendServiceMessage(fuchsia_wlan_mlme_MLMEDeviceQueryConfOrdinal, &resp);
+}
 
-    auto packet = fbl::unique_ptr<Packet>(new Packet(std::move(buffer), buf_len));
-    packet->set_peer(Packet::Peer::kService);
-    zx_status_t status =
-        SerializeServiceMsg(packet.get(), wlan_mlme_MLMEDeviceQueryConfOrdinal, &resp);
-    if (status != ZX_OK) {
-        errorf("could not serialize DeviceQueryResponse: %d\n", status);
-        return status;
+zx_status_t Dispatcher::HandleMlmeStats(uint32_t ordinal) const {
+    debugfn();
+    ZX_DEBUG_ASSERT(ordinal == fuchsia_wlan_mlme_MLMEStatsQueryReqOrdinal);
+
+    wlan_mlme::StatsQueryResponse resp;
+    const wlanmac_info_t& info = device_->GetWlanInfo();
+
+    resp.dispatcher_stats = stats_.ToFidl();
+
+    switch (info.mac_role) {
+    case WLAN_MAC_ROLE_CLIENT:
+        resp.mlme_stats.client_mlme_stats() = mlme_->GetClientMlmeStats();
+        break;
+    // TODO: Add stats for AP
+    case WLAN_MAC_ROLE_AP:
+        break;
+    default:
+        break;
     }
-
-    return device_->SendService(std::move(packet));
+    return SendServiceMessage(fuchsia_wlan_mlme_MLMEStatsQueryRespOrdinal, &resp);
 }
 
 zx_status_t Dispatcher::PreChannelChange(wlan_channel_t chan) {
diff --git a/lib/wlan/mlme/include/wlan/mlme/ap/ap_mlme.h b/lib/wlan/mlme/include/wlan/mlme/ap/ap_mlme.h
index 4bb1a9f..cfe3b9c 100644
--- a/lib/wlan/mlme/include/wlan/mlme/ap/ap_mlme.h
+++ b/lib/wlan/mlme/include/wlan/mlme/ap/ap_mlme.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 #include <wlan/mlme/ap/beacon_sender.h>
 #include <wlan/mlme/ap/infra_bss.h>
 #include <wlan/mlme/mlme.h>
@@ -22,8 +22,8 @@
     ~ApMlme();
 
     // FrameHandler methods.
-    zx_status_t HandleMlmeStartReq(const wlan_mlme::StartRequest& req) override;
-    zx_status_t HandleMlmeStopReq(const wlan_mlme::StopRequest& req) override;
+    zx_status_t HandleMlmeStartReq(const ::fuchsia::wlan::mlme::StartRequest& req) override;
+    zx_status_t HandleMlmeStopReq(const ::fuchsia::wlan::mlme::StopRequest& req) override;
 
     // Mlme interface methods.
     zx_status_t Init() override;
diff --git a/lib/wlan/mlme/include/wlan/mlme/ap/beacon_sender.h b/lib/wlan/mlme/include/wlan/mlme/ap/beacon_sender.h
index 3c4104f..d2e24a9 100644
--- a/lib/wlan/mlme/include/wlan/mlme/ap/beacon_sender.h
+++ b/lib/wlan/mlme/include/wlan/mlme/ap/beacon_sender.h
@@ -7,7 +7,7 @@
 #include <wlan/mlme/device_interface.h>
 #include <wlan/mlme/frame_handler.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <zircon/types.h>
 
@@ -22,7 +22,7 @@
     BeaconSender(DeviceInterface* device);
     ~BeaconSender();
 
-    void Start(BssInterface* bss, const PsCfg& ps_cfg, const wlan_mlme::StartRequest& req);
+    void Start(BssInterface* bss, const PsCfg& ps_cfg, const ::fuchsia::wlan::mlme::StartRequest& req);
     void Stop();
     zx_status_t UpdateBeacon(const PsCfg& ps_cfg);
     zx_status_t HandleProbeRequest(const MgmtFrame<ProbeRequest>& frame) override;
@@ -40,7 +40,7 @@
     bool IsStarted();
 
     DeviceInterface* const device_;
-    wlan_mlme::StartRequest req_;
+    ::fuchsia::wlan::mlme::StartRequest req_;
     BssInterface* bss_ = nullptr;
     // Buffer to write the Partial Virtual Bitmap to which was derived from a
     // Traffic Indication Map.
diff --git a/lib/wlan/mlme/include/wlan/mlme/ap/bss_interface.h b/lib/wlan/mlme/include/wlan/mlme/ap/bss_interface.h
index fb770ff..af0ad1c 100644
--- a/lib/wlan/mlme/include/wlan/mlme/ap/bss_interface.h
+++ b/lib/wlan/mlme/include/wlan/mlme/ap/bss_interface.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 #include <wlan/mlme/ap/tim.h>
 #include <wlan/mlme/device_interface.h>
 #include <wlan/mlme/mac_frame.h>
@@ -65,7 +65,7 @@
     virtual uint64_t timestamp() = 0;
 
     // Starts the BSS. Beacons will be sent and incoming frames are processed.
-    virtual void Start(const wlan_mlme::StartRequest& req) = 0;
+    virtual void Start(const ::fuchsia::wlan::mlme::StartRequest& req) = 0;
     // Stops the BSS. All incoming frames are dropped and Beacons are not sent
     // anymore.
     virtual void Stop() = 0;
diff --git a/lib/wlan/mlme/include/wlan/mlme/ap/infra_bss.h b/lib/wlan/mlme/include/wlan/mlme/ap/infra_bss.h
index ffc5740..9c90489 100644
--- a/lib/wlan/mlme/include/wlan/mlme/ap/infra_bss.h
+++ b/lib/wlan/mlme/include/wlan/mlme/ap/infra_bss.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 #include <wlan/mlme/ap/beacon_sender.h>
 #include <wlan/mlme/ap/bss_client_map.h>
 #include <wlan/mlme/ap/bss_interface.h>
@@ -36,7 +36,7 @@
     // BssInterface implementation
     const common::MacAddr& bssid() const override;
     uint64_t timestamp() override;
-    void Start(const wlan_mlme::StartRequest& req) override;
+    void Start(const ::fuchsia::wlan::mlme::StartRequest& req) override;
     void Stop() override;
     zx_status_t AssignAid(const common::MacAddr& client, aid_t* out_aid) override;
     zx_status_t ReleaseAid(const common::MacAddr& client) override;
@@ -99,7 +99,7 @@
     wlan_channel_t chan_;
     // MLME-START.request holds all information required to correctly configure
     // and start a BSS.
-    wlan_mlme::StartRequest start_req_;
+    ::fuchsia::wlan::mlme::StartRequest start_req_;
 };
 
 }  // namespace wlan
diff --git a/lib/wlan/mlme/include/wlan/mlme/ap/remote_client.h b/lib/wlan/mlme/include/wlan/mlme/ap/remote_client.h
index de6cb98..3aea1df 100644
--- a/lib/wlan/mlme/include/wlan/mlme/ap/remote_client.h
+++ b/lib/wlan/mlme/include/wlan/mlme/ap/remote_client.h
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 #include <wlan/mlme/ap/bss_interface.h>
 #include <wlan/mlme/ap/remote_client_interface.h>
 #include <wlan/mlme/device_interface.h>
@@ -204,8 +204,8 @@
     zx_status_t HandleDisassociation(const MgmtFrame<Disassociation>& frame) override;
     zx_status_t HandleCtrlFrame(const FrameControl& fc) override;
     zx_status_t HandlePsPollFrame(const CtrlFrame<PsPollFrame>& frame) override;
-    zx_status_t HandleMlmeEapolReq(const wlan_mlme::EapolRequest& req) override;
-    zx_status_t HandleMlmeSetKeysReq(const wlan_mlme::SetKeysRequest& req) override;
+    zx_status_t HandleMlmeEapolReq(const ::fuchsia::wlan::mlme::EapolRequest& req) override;
+    zx_status_t HandleMlmeSetKeysReq(const ::fuchsia::wlan::mlme::SetKeysRequest& req) override;
     zx_status_t HandleAddBaRequestFrame(const MgmtFrame<AddBaRequestFrame>& frame) override;
     zx_status_t HandleAddBaResponseFrame(const MgmtFrame<AddBaResponseFrame>& frame) override;
 
diff --git a/lib/wlan/mlme/include/wlan/mlme/client/bss.h b/lib/wlan/mlme/include/wlan/mlme/client/bss.h
index 3573829..0c3fbd3 100644
--- a/lib/wlan/mlme/include/wlan/mlme/client/bss.h
+++ b/lib/wlan/mlme/include/wlan/mlme/client/bss.h
@@ -10,7 +10,7 @@
 #include <wlan/mlme/mac_frame.h>
 #include <wlan/mlme/macaddr_map.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <fbl/macros.h>
 #include <fbl/ref_counted.h>
@@ -39,22 +39,22 @@
     std::string SsidToString() const;
     std::string SupportedRatesToString() const;
 
-    wlan_mlme::BSSTypes GetBssType() const {
+    ::fuchsia::wlan::mlme::BSSTypes GetBssType() const {
         // Note. This is in Beacon / Probe Response frames context.
         // IEEE Std 802.11-2016, 9.4.1.4
         if (cap_.ess() == 0x1 && cap_.ibss() == 0x0) {
-            return wlan_mlme::BSSTypes::INFRASTRUCTURE;
+            return ::fuchsia::wlan::mlme::BSSTypes::INFRASTRUCTURE;
         } else if (cap_.ess() == 0x0 && cap_.ibss() == 0x1) {
-            return wlan_mlme::BSSTypes::INDEPENDENT;
+            return ::fuchsia::wlan::mlme::BSSTypes::INDEPENDENT;
         } else if (cap_.ess() == 0x0 && cap_.ibss() == 0x0) {
-            return wlan_mlme::BSSTypes::MESH;
+            return ::fuchsia::wlan::mlme::BSSTypes::MESH;
         } else {
             // Undefined
-            return wlan_mlme::BSSTypes::ANY_BSS;
+            return ::fuchsia::wlan::mlme::BSSTypes::ANY_BSS;
         }
     }
 
-    wlan_mlme::BSSDescription ToFidl();
+    ::fuchsia::wlan::mlme::BSSDescription ToFidl();
     fidl::StringPtr SsidToFidlString();
     const common::MacAddr& bssid() { return bssid_; }
     zx::time ts_refreshed() { return ts_refreshed_; }
@@ -99,7 +99,11 @@
     uint8_t ssid_[SsidElement::kMaxLen]{0};
     size_t ssid_len_{0};
     std::vector<uint8_t> supported_rates_{0};
-    uint8_t dsss_param_set_chan_;  // TODO(porce): Clarify where this information is to be used
+
+    // Conditionally present. See IEEE Std 802.11-2016, 9.3.3.3 Table 9-27
+    bool has_dsss_param_set_chan_ = false;
+    uint8_t dsss_param_set_chan_;
+
     std::string country_{""};
     std::unique_ptr<uint8_t[]> rsne_;
     size_t rsne_len_{0};
diff --git a/lib/wlan/mlme/include/wlan/mlme/client/client_mlme.h b/lib/wlan/mlme/include/wlan/mlme/client/client_mlme.h
index 32feeee..6b3a095 100644
--- a/lib/wlan/mlme/include/wlan/mlme/client/client_mlme.h
+++ b/lib/wlan/mlme/include/wlan/mlme/client/client_mlme.h
@@ -7,6 +7,8 @@
 #include <wlan/mlme/mlme.h>
 
 #include <fbl/ref_ptr.h>
+
+#include <fuchsia/wlan/stats/cpp/fidl.h>
 #include <wlan/protocol/mac.h>
 #include <zircon/types.h>
 
@@ -29,7 +31,8 @@
     zx_status_t PostChannelChange() override;
     zx_status_t HandleTimeout(const ObjectId id) override;
     // MLME-JOIN.request will initialize a Station and starts the association flow.
-    zx_status_t HandleMlmeJoinReq(const wlan_mlme::JoinRequest& msg) override;
+    zx_status_t HandleMlmeJoinReq(const ::fuchsia::wlan::mlme::JoinRequest& msg) override;
+    ::fuchsia::wlan::stats::ClientMlmeStats GetClientMlmeStats() const override final;
 
     bool IsStaValid() const;
 
diff --git a/lib/wlan/mlme/include/wlan/mlme/client/remote_ap.h b/lib/wlan/mlme/include/wlan/mlme/client/remote_ap.h
index 22c72d5..4b182f5 100644
--- a/lib/wlan/mlme/include/wlan/mlme/client/remote_ap.h
+++ b/lib/wlan/mlme/include/wlan/mlme/client/remote_ap.h
@@ -8,7 +8,7 @@
 #include <wlan/mlme/frame_handler.h>
 #include <wlan/mlme/mac_frame.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <fbl/unique_ptr.h>
 #include <zircon/types.h>
@@ -18,6 +18,8 @@
 class Packet;
 class Timer;
 
+namespace remote_ap {
+
 class RemoteAp : public FrameHandler {
    public:
     class BaseState : public FrameHandler {
@@ -38,14 +40,15 @@
     };
 
     RemoteAp(DeviceInterface* device, fbl::unique_ptr<Timer> timer,
-             const wlan_mlme::BSSDescription& bssid);
+             const ::fuchsia::wlan::mlme::BSSDescription& bssid);
     ~RemoteAp();
 
     DeviceInterface* device() { return device_; }
     const common::MacAddr& bssid() { return bssid_; }
     const char* bssid_str() { return bssid_.ToString().c_str(); }
-    const wlan_mlme::BSSDescription& bss() { return *bss_.get(); }
+    const ::fuchsia::wlan::mlme::BSSDescription& bss() { return *bss_.get(); }
     const wlan_channel_t& bss_chan() { return bss_chan_; }
+    Sequence* seq() { return &seq_; }
 
     zx_status_t StartTimer(zx::time deadline);
     zx_status_t CancelTimer();
@@ -54,20 +57,29 @@
     void HandleTimeout();
     void MoveToState(fbl::unique_ptr<BaseState> to);
 
-   private:
-    zx_status_t HandleMgmtFrame(const MgmtFrameHeader& hdr) override;
-
-    wlan_channel_t SanitizeChannel(wlan_channel_t chan);
     // Stub functions filled with logic in the future.
+    bool IsHTReady() const;
     bool IsCbw40RxReady() const;
     bool IsCbw40TxReady() const;
+    bool IsQosReady() const;
+    bool IsAmsduRxReady() const;
+    // TODO(porce): Find intersection of:
+    // - BSS capabilities
+    // - Client radio capabilities
+    // - Client configuration
+    HtCapabilities BuildHtCapabilities();
+
+   private:
+    zx_status_t HandleMgmtFrame(const MgmtFrameHeader& hdr) override;
+    wlan_channel_t SanitizeChannel(wlan_channel_t chan);
 
     DeviceInterface* device_;
     fbl::unique_ptr<Timer> timer_;
     common::MacAddr bssid_;
-    wlan_mlme::BSSDescriptionPtr bss_;
+    ::fuchsia::wlan::mlme::BSSDescriptionPtr bss_;
     wlan_channel_t bss_chan_;
     fbl::unique_ptr<BaseState> state_;
+    Sequence seq_;
 };
 
 class InitState : public RemoteAp::BaseState {
@@ -83,7 +95,7 @@
    private:
     zx_status_t HandleBeacon(const MgmtFrame<Beacon>& frame) override;
     zx_status_t HandleProbeResponse(const MgmtFrame<ProbeResponse>& frame) override;
-    zx_status_t HandleMlmeJoinReq(const wlan_mlme::JoinRequest& req) override;
+    zx_status_t HandleMlmeJoinReq(const ::fuchsia::wlan::mlme::JoinRequest& req) override;
 
     void OnExit() override;
     void MoveToJoinedState();
@@ -98,6 +110,69 @@
     explicit JoinedState(RemoteAp* ap);
 
     const char* name() const override { return kName; }
+
+   private:
+    zx_status_t HandleMlmeAuthReq(const ::fuchsia::wlan::mlme::AuthenticateRequest& req) override;
 };
 
+class AuthenticatingState : public RemoteAp::BaseState {
+   public:
+    static constexpr const char* kName = "Authenticating";
+
+    explicit AuthenticatingState(RemoteAp* ap, AuthAlgorithm auth_alg, wlan_tu_t auth_timeout_tu);
+
+    void HandleTimeout() override;
+    const char* name() const override { return kName; }
+
+   private:
+    void OnExit() override;
+
+    zx_status_t HandleAuthentication(const MgmtFrame<Authentication>& frame) override;
+    template <typename State> void MoveOn(::fuchsia::wlan::mlme::AuthenticateResultCodes result_code);
+
+    zx::time auth_deadline_;
+    AuthAlgorithm auth_alg_;
+};
+
+class AuthenticatedState : public RemoteAp::BaseState {
+   public:
+    static constexpr const char* kName = "Authenticated";
+
+    explicit AuthenticatedState(RemoteAp* ap);
+
+    const char* name() const override { return kName; }
+
+   private:
+    zx_status_t HandleMlmeAssocReq(const ::fuchsia::wlan::mlme::AssociateRequest& req) override;
+};
+
+class AssociatingState : public RemoteAp::BaseState {
+   public:
+    static constexpr const char* kName = "Associating";
+
+    explicit AssociatingState(RemoteAp* ap);
+
+    const char* name() const override { return kName; }
+
+   private:
+    static constexpr size_t kAssocTimeoutTu = 500;  // ~500ms
+
+    void OnExit() override;
+    void HandleTimeout() override;
+
+    zx_status_t HandleAssociationResponse(const MgmtFrame<AssociationResponse>& frame) override;
+
+    zx::time assoc_deadline_;
+};
+
+class AssociatedState : public RemoteAp::BaseState {
+   public:
+    static constexpr const char* kName = "Associated";
+
+    explicit AssociatedState(RemoteAp* ap, aid_t aid);
+
+    const char* name() const override { return kName; }
+};
+
+}  // namespace remote_ap
 }  // namespace wlan
diff --git a/lib/wlan/mlme/include/wlan/mlme/client/scanner.h b/lib/wlan/mlme/include/wlan/mlme/client/scanner.h
index eab2f69..d90cfe9 100644
--- a/lib/wlan/mlme/include/wlan/mlme/client/scanner.h
+++ b/lib/wlan/mlme/include/wlan/mlme/client/scanner.h
@@ -7,7 +7,7 @@
 #include <wlan/mlme/client/bss.h>
 #include <wlan/mlme/frame_handler.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <fbl/unique_ptr.h>
 #include <lib/zx/time.h>
@@ -33,14 +33,14 @@
         kActive,
     };
 
-    zx_status_t Start(const wlan_mlme::ScanRequest& req);
+    zx_status_t Start(const ::fuchsia::wlan::mlme::ScanRequest& req);
     void Reset();
 
     bool IsRunning() const;
     Type ScanType() const;
     wlan_channel_t ScanChannel() const;
 
-    zx_status_t HandleMlmeScanReq(const wlan_mlme::ScanRequest& req) override;
+    zx_status_t HandleMlmeScanReq(const ::fuchsia::wlan::mlme::ScanRequest& req) override;
     zx_status_t HandleMgmtFrame(const MgmtFrameHeader& hdr) override;
     zx_status_t HandleBeacon(const MgmtFrame<Beacon>& frame) override;
     zx_status_t HandleProbeResponse(const MgmtFrame<ProbeResponse>& frame) override;
@@ -66,8 +66,8 @@
 
     DeviceInterface* device_;
     fbl::unique_ptr<Timer> timer_;
-    wlan_mlme::ScanRequestPtr req_ = nullptr;
-    wlan_mlme::ScanConfirmPtr resp_ = nullptr;
+    ::fuchsia::wlan::mlme::ScanRequestPtr req_ = nullptr;
+    ::fuchsia::wlan::mlme::ScanConfirmPtr resp_ = nullptr;
 
     size_t channel_index_ = 0;
     zx::time channel_start_;
diff --git a/lib/wlan/mlme/include/wlan/mlme/client/station.h b/lib/wlan/mlme/include/wlan/mlme/client/station.h
index 0df3f74..487a1b4 100644
--- a/lib/wlan/mlme/include/wlan/mlme/client/station.h
+++ b/lib/wlan/mlme/include/wlan/mlme/client/station.h
@@ -10,8 +10,8 @@
 #include <wlan/mlme/mac_frame.h>
 #include <wlan/mlme/sequence.h>
 
-#include <wlan_mlme/cpp/fidl.h>
-#include <wlan_stats/c/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
+#include <fuchsia/wlan/stats/cpp/fidl.h>
 
 #include <fbl/unique_ptr.h>
 #include <wlan/common/macaddr.h>
@@ -76,12 +76,12 @@
     zx_status_t SendKeepAliveResponse();
 
     zx_status_t HandleMlmeMessage(uint32_t ordinal) override;
-    zx_status_t HandleMlmeJoinReq(const wlan_mlme::JoinRequest& req) override;
-    zx_status_t HandleMlmeAuthReq(const wlan_mlme::AuthenticateRequest& req) override;
-    zx_status_t HandleMlmeDeauthReq(const wlan_mlme::DeauthenticateRequest& req) override;
-    zx_status_t HandleMlmeAssocReq(const wlan_mlme::AssociateRequest& req) override;
-    zx_status_t HandleMlmeEapolReq(const wlan_mlme::EapolRequest& req) override;
-    zx_status_t HandleMlmeSetKeysReq(const wlan_mlme::SetKeysRequest& req) override;
+    zx_status_t HandleMlmeJoinReq(const ::fuchsia::wlan::mlme::JoinRequest& req) override;
+    zx_status_t HandleMlmeAuthReq(const ::fuchsia::wlan::mlme::AuthenticateRequest& req) override;
+    zx_status_t HandleMlmeDeauthReq(const ::fuchsia::wlan::mlme::DeauthenticateRequest& req) override;
+    zx_status_t HandleMlmeAssocReq(const ::fuchsia::wlan::mlme::AssociateRequest& req) override;
+    zx_status_t HandleMlmeEapolReq(const ::fuchsia::wlan::mlme::EapolRequest& req) override;
+    zx_status_t HandleMlmeSetKeysReq(const ::fuchsia::wlan::mlme::SetKeysRequest& req) override;
 
     zx_status_t HandleDataFrame(const DataFrameHeader& hdr) override;
     zx_status_t HandleBeacon(const MgmtFrame<Beacon>& frame) override;
@@ -109,6 +109,8 @@
 
     const Timer& timer() const { return *timer_; }
 
+    const ::fuchsia::wlan::stats::ClientMlmeStats& stats();
+
    private:
     zx_status_t SendAddBaRequestFrame();
 
@@ -128,7 +130,7 @@
 
     DeviceInterface* device_;
     fbl::unique_ptr<Timer> timer_;
-    wlan_mlme::BSSDescriptionPtr bss_;
+    ::fuchsia::wlan::mlme::BSSDescriptionPtr bss_;
     common::MacAddr bssid_;
     Sequence seq_;
 
@@ -139,12 +141,12 @@
     zx::time signal_report_timeout_;
     zx::time last_seen_;
     uint16_t aid_ = 0;
-    common::MovingAverage<int8_t, int16_t, 20> avg_rssi_dbm_;
+    common::MovingAverageDbm<20> avg_rssi_dbm_;
     AuthAlgorithm auth_alg_ = AuthAlgorithm::kOpenSystem;
     eapol::PortState controlled_port_ = eapol::PortState::kBlocked;
 
     wlan_channel_t join_chan_;
-    common::WlanStats<common::ClientMlmeStats, wlan_stats_ClientMlmeStats> stats_;
+    common::WlanStats<common::ClientMlmeStats, ::fuchsia::wlan::stats::ClientMlmeStats> stats_;
 };
 
 }  // namespace wlan
diff --git a/lib/wlan/mlme/include/wlan/mlme/debug.h b/lib/wlan/mlme/include/wlan/mlme/debug.h
index 0be2b24..0b64d27 100644
--- a/lib/wlan/mlme/include/wlan/mlme/debug.h
+++ b/lib/wlan/mlme/include/wlan/mlme/debug.h
@@ -28,6 +28,7 @@
 std::string Describe(const wlan_rx_info_t& rxinfo);
 std::string Describe(Packet::Peer peer);
 std::string Describe(const Packet& packet);
+std::string Describe(const AmsduSubframe& s);
 
 std::string DescribeSuppressed(const Packet& p);
 }  // namespace debug
diff --git a/lib/wlan/mlme/include/wlan/mlme/dispatcher.h b/lib/wlan/mlme/include/wlan/mlme/dispatcher.h
index 013163f..40e4195 100644
--- a/lib/wlan/mlme/include/wlan/mlme/dispatcher.h
+++ b/lib/wlan/mlme/include/wlan/mlme/dispatcher.h
@@ -5,14 +5,13 @@
 #pragma once
 
 #include <fbl/unique_ptr.h>
+#include <fuchsia/wlan/stats/cpp/fidl.h>
 #include <wlan/common/stats.h>
 #include <wlan/mlme/mac_frame.h>
 #include <wlan/mlme/mlme.h>
 #include <wlan/protocol/mac.h>
 #include <zircon/types.h>
 
-#include <wlan_stats/c/fidl.h>
-
 namespace wlan {
 
 // The Dispatcher converts Packets, forwarded by the Device, into concrete frames, such as
@@ -33,7 +32,7 @@
     zx_status_t PostChannelChange();
     // Called when the hardware reports an indication such as Pre-TBTT.
     void HwIndication(uint32_t ind);
-    common::WlanStats<common::DispatcherStats, wlan_stats_DispatcherStats> stats_;
+    common::WlanStats<common::DispatcherStats, ::fuchsia::wlan::stats::DispatcherStats> stats_;
 
    private:
     // MAC frame handlers
@@ -45,6 +44,9 @@
     template <typename Message>
     zx_status_t HandleMlmeMethod(fbl::unique_ptr<Packet> packet, uint32_t ordinal);
     zx_status_t HandleActionPacket(MgmtFrame<ActionFrame> action, const wlan_rx_info_t* rxinfo);
+    zx_status_t HandleMlmeStats(uint32_t ordinal) const;
+    template <typename T>
+    zx_status_t SendServiceMessage(uint32_t ordinal, T* msg) const;
 
     DeviceInterface* device_;
     // The MLME that will handle requests for this dispatcher. This field will be set upon querying
diff --git a/lib/wlan/mlme/include/wlan/mlme/frame_handler.h b/lib/wlan/mlme/include/wlan/mlme/frame_handler.h
index 2fdace1..0367009 100644
--- a/lib/wlan/mlme/include/wlan/mlme/frame_handler.h
+++ b/lib/wlan/mlme/include/wlan/mlme/frame_handler.h
@@ -6,7 +6,7 @@
 
 #include <wlan/mlme/mac_frame.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <fbl/ref_counted.h>
 #include <fbl/ref_ptr.h>
@@ -17,10 +17,10 @@
     virtual zx_status_t methodName(args) { return ZX_OK; }
 
 #define WLAN_DECL_FUNC_HANDLE_MLME(methodName, mlmeMsgType) \
-    WLAN_DECL_VIRT_FUNC_HANDLE(methodName, const wlan_mlme::mlmeMsgType&)
+    WLAN_DECL_VIRT_FUNC_HANDLE(methodName, const ::fuchsia::wlan::mlme::mlmeMsgType&)
 
 #define WLAN_DECL_FUNC_INTERNAL_HANDLE_MLME(methodName, mlmeMsgType)                    \
-    zx_status_t HandleMlmeFrameInternal(uint32_t ordinal, const wlan_mlme::mlmeMsgType& msg) { \
+    zx_status_t HandleMlmeFrameInternal(uint32_t ordinal, const ::fuchsia::wlan::mlme::mlmeMsgType& msg) { \
         return methodName(msg);                                                         \
     }
 
diff --git a/lib/wlan/mlme/include/wlan/mlme/macaddr_map.h b/lib/wlan/mlme/include/wlan/mlme/macaddr_map.h
index 1282467..9129dc5 100644
--- a/lib/wlan/mlme/include/wlan/mlme/macaddr_map.h
+++ b/lib/wlan/mlme/include/wlan/mlme/macaddr_map.h
@@ -43,7 +43,9 @@
         return true;
     }
 
-    size_type RemoveIf(std::function<bool(V v)> p) {
+    // Predicate signature is bool(V v).
+    template <typename Predicate>
+    size_type RemoveIf(Predicate p) {
         size_type removed = 0;
         for (auto iter = begin(map_); iter != end(map_);) {
             if (p(iter->second)) {
@@ -57,7 +59,9 @@
         return removed;
     }
 
-    void ForEach(std::function<void(V v)> f) {
+    // Function signature is void(V v).
+    template <typename Function>
+    void ForEach(Function f) {
         for (auto iter = begin(map_); iter != end(map_); iter++) {
             f(iter->second);
         }
diff --git a/lib/wlan/mlme/include/wlan/mlme/mlme.h b/lib/wlan/mlme/include/wlan/mlme/mlme.h
index 526eb2a..b53407e 100644
--- a/lib/wlan/mlme/include/wlan/mlme/mlme.h
+++ b/lib/wlan/mlme/include/wlan/mlme/mlme.h
@@ -4,12 +4,10 @@
 
 #pragma once
 
+#include <fuchsia/wlan/stats/cpp/fidl.h>
+#include <wlan/common/bitfield.h>
 #include <wlan/mlme/frame_handler.h>
 #include <wlan/mlme/mac_frame.h>
-
-#include <wlan_mlme/cpp/fidl.h>
-
-#include <wlan/common/bitfield.h>
 #include <wlan/protocol/mac.h>
 #include <zircon/types.h>
 
@@ -57,6 +55,7 @@
     virtual zx_status_t HandleTimeout(const ObjectId id) = 0;
     // Called when the hardware reports an indication such as Pre-TBTT.
     virtual void HwIndication(uint32_t ind) {};
+    virtual ::fuchsia::wlan::stats::ClientMlmeStats GetClientMlmeStats() const { return ::fuchsia::wlan::stats::ClientMlmeStats{}; }
 };
 
 }  // namespace wlan
diff --git a/lib/wlan/mlme/include/wlan/mlme/service.h b/lib/wlan/mlme/include/wlan/mlme/service.h
index f7f9156..8d1247a 100644
--- a/lib/wlan/mlme/include/wlan/mlme/service.h
+++ b/lib/wlan/mlme/include/wlan/mlme/service.h
@@ -10,7 +10,7 @@
 #include <wlan/mlme/packet.h>
 #include <zircon/fidl.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 #include <lib/fidl/cpp/decoder.h>
 #include <lib/fidl/cpp/message.h>
@@ -79,20 +79,20 @@
 
 namespace service {
 
-zx_status_t SendJoinConfirm(DeviceInterface* device, wlan_mlme::JoinResultCodes result_code);
+zx_status_t SendJoinConfirm(DeviceInterface* device, ::fuchsia::wlan::mlme::JoinResultCodes result_code);
 zx_status_t SendAuthConfirm(DeviceInterface* device, const common::MacAddr& peer_sta,
-                            wlan_mlme::AuthenticateResultCodes code);
+                            ::fuchsia::wlan::mlme::AuthenticateResultCodes code);
 zx_status_t SendDeauthConfirm(DeviceInterface* device, const common::MacAddr& peer_sta);
 zx_status_t SendDeauthIndication(DeviceInterface* device, const common::MacAddr& peer_sta,
-                                 wlan_mlme::ReasonCode code);
-zx_status_t SendAssocConfirm(DeviceInterface* device, wlan_mlme::AssociateResultCodes code,
+                                 ::fuchsia::wlan::mlme::ReasonCode code);
+zx_status_t SendAssocConfirm(DeviceInterface* device, ::fuchsia::wlan::mlme::AssociateResultCodes code,
                              uint16_t aid = 0);
 zx_status_t SendDisassociateIndication(DeviceInterface* device, const common::MacAddr& peer_sta,
                                        uint16_t code);
 
 zx_status_t SendSignalReportIndication(DeviceInterface* device, common::dBm rssi_dbm);
 
-zx_status_t SendEapolConfirm(DeviceInterface* device, wlan_mlme::EapolResultCodes result_code);
+zx_status_t SendEapolConfirm(DeviceInterface* device, ::fuchsia::wlan::mlme::EapolResultCodes result_code);
 zx_status_t SendEapolIndication(DeviceInterface* device, const EapolFrame& eapol,
                                 const common::MacAddr& src, const common::MacAddr& dst);
 }  // namespace service
diff --git a/lib/wlan/mlme/service.cpp b/lib/wlan/mlme/service.cpp
index b7728dd..658490f 100644
--- a/lib/wlan/mlme/service.cpp
+++ b/lib/wlan/mlme/service.cpp
@@ -5,12 +5,13 @@
 #include <wlan/mlme/service.h>
 
 #include <wlan/mlme/device_interface.h>
-#include <wlan_mlme/c/fidl.h>
+#include <fuchsia/wlan/mlme/c/fidl.h>
 
 namespace wlan {
-
 namespace service {
 
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 zx_status_t SendJoinConfirm(DeviceInterface* device, wlan_mlme::JoinResultCodes result_code) {
     debugfn();
 
@@ -25,7 +26,7 @@
 
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
-    auto status = SerializeServiceMsg(packet.get(), wlan_mlme_MLMEJoinConfOrdinal, resp.get());
+    auto status = SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEJoinConfOrdinal, resp.get());
     if (status != ZX_OK) {
         errorf("could not serialize JoinConfirm: %d\n", status);
     } else {
@@ -54,7 +55,7 @@
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
     auto status =
-        SerializeServiceMsg(packet.get(), wlan_mlme_MLMEAuthenticateConfOrdinal, resp.get());
+        SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEAuthenticateConfOrdinal, resp.get());
     if (status != ZX_OK) {
         errorf("could not serialize AuthenticateConfirm: %d\n", status);
     } else {
@@ -79,7 +80,7 @@
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
     auto status =
-        SerializeServiceMsg(packet.get(), wlan_mlme_MLMEDeauthenticateConfOrdinal, resp.get());
+        SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEDeauthenticateConfOrdinal, resp.get());
     if (status != ZX_OK) {
         errorf("could not serialize DeauthenticateConfirm: %d\n", status);
     } else {
@@ -106,7 +107,7 @@
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
     auto status =
-        SerializeServiceMsg(packet.get(), wlan_mlme_MLMEDeauthenticateIndOrdinal, ind.get());
+        SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEDeauthenticateIndOrdinal, ind.get());
     if (status != ZX_OK) {
         errorf("could not serialize DeauthenticateIndication: %d\n", status);
     } else {
@@ -133,7 +134,7 @@
 
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
-    auto status = SerializeServiceMsg(packet.get(), wlan_mlme_MLMEAssociateConfOrdinal, resp.get());
+    auto status = SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEAssociateConfOrdinal, resp.get());
     if (status != ZX_OK) {
         errorf("could not serialize AssociateConfirm: %d\n", status);
     } else {
@@ -160,7 +161,7 @@
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
     auto status =
-        SerializeServiceMsg(packet.get(), wlan_mlme_MLMEDisassociateIndOrdinal, ind.get());
+        SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEDisassociateIndOrdinal, ind.get());
     if (status != ZX_OK) {
         errorf("could not serialize DisassociateIndication: %d\n", status);
     } else {
@@ -184,7 +185,7 @@
 
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
-    auto status = SerializeServiceMsg(packet.get(), wlan_mlme_MLMESignalReportOrdinal, ind.get());
+    auto status = SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMESignalReportOrdinal, ind.get());
     if (status != ZX_OK) {
         errorf("could not serialize SignalReportIndication: %d\n", status);
     } else {
@@ -208,7 +209,7 @@
 
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
-    auto status = SerializeServiceMsg(packet.get(), wlan_mlme_MLMEEapolConfOrdinal, resp.get());
+    auto status = SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEEapolConfOrdinal, resp.get());
     if (status != ZX_OK) {
         errorf("could not serialize EapolConfirm: %d\n", status);
     } else {
@@ -242,7 +243,7 @@
 
     auto packet = fbl::make_unique<Packet>(fbl::move(buffer), buf_len);
     packet->set_peer(Packet::Peer::kService);
-    auto status = SerializeServiceMsg(packet.get(), wlan_mlme_MLMEEapolIndOrdinal, ind.get());
+    auto status = SerializeServiceMsg(packet.get(), fuchsia_wlan_mlme_MLMEEapolIndOrdinal, ind.get());
     if (status != ZX_OK) {
         errorf("could not serialize MLME-Eapol.indication: %d\n", status);
     } else {
diff --git a/lib/wlan/mlme/tests/BUILD.gn b/lib/wlan/mlme/tests/BUILD.gn
index 2788fee..90c0dc5 100644
--- a/lib/wlan/mlme/tests/BUILD.gn
+++ b/lib/wlan/mlme/tests/BUILD.gn
@@ -84,6 +84,7 @@
     ":test_main",
     "//garnet/lib/wlan/mlme",
     "//third_party/googletest:gtest",
+    "//zircon/public/lib/fit",
   ]
 
   configs += [ "//garnet/lib/wlan/mlme:wlan_mlme_config" ]
diff --git a/lib/wlan/mlme/tests/dispatcher_unittest.cpp b/lib/wlan/mlme/tests/dispatcher_unittest.cpp
index 3d8119e..20ada08 100644
--- a/lib/wlan/mlme/tests/dispatcher_unittest.cpp
+++ b/lib/wlan/mlme/tests/dispatcher_unittest.cpp
@@ -14,14 +14,17 @@
 #include <fbl/ref_ptr.h>
 #include <fbl/unique_ptr.h>
 #include <gtest/gtest.h>
-#include <functional>
+#include <lib/fit/function.h>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 namespace wlan {
+
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 namespace {
 
-template <typename Frame> using FrameCallback = std::function<void(const Frame&)>;
+template <typename Frame> using FrameCallback = fit::function<void(const Frame&)>;
 using EthFrameCallback = FrameCallback<EthFrame>;
 
 struct MockMlme : public Mlme {
@@ -36,7 +39,7 @@
         return ZX_OK;
     }
 
-    void SetFrameCallback(EthFrameCallback eth_cb) { eth_cb_ = eth_cb; }
+    void SetFrameCallback(EthFrameCallback eth_cb) { eth_cb_ = std::move(eth_cb); }
 
    private:
     EthFrameCallback eth_cb_;
@@ -48,7 +51,7 @@
     bool HandlePacket(fbl::unique_ptr<Packet> packet, FrameCallback<Frame> cb) {
         bool handled = false;
         auto mock_mlme = fbl::make_unique<MockMlme>();
-        mock_mlme->SetFrameCallback([&handled, cb](const Frame& frame) mutable {
+        mock_mlme->SetFrameCallback([&handled, cb = std::move(cb)](const Frame& frame) mutable {
             handled = true;
             cb(frame);
         });
diff --git a/lib/wlan/mlme/tests/scanner_unittest.cpp b/lib/wlan/mlme/tests/scanner_unittest.cpp
index 220667d..c048d31 100644
--- a/lib/wlan/mlme/tests/scanner_unittest.cpp
+++ b/lib/wlan/mlme/tests/scanner_unittest.cpp
@@ -18,12 +18,15 @@
 #include <fbl/ref_ptr.h>
 #include <fbl/unique_ptr.h>
 #include <gtest/gtest.h>
-#include <wlan_mlme/c/fidl.h>
+#include <fuchsia/wlan/mlme/c/fidl.h>
 #include <cstring>
 
-#include <wlan_mlme/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
 
 namespace wlan {
+
+namespace wlan_mlme = ::fuchsia::wlan::mlme;
+
 namespace {
 
 const uint8_t kBeacon[] = {
@@ -50,7 +53,7 @@
     zx_status_t Start() { return scanner_.Start(*req_); }
 
     zx_status_t DeserializeScanResponse() {
-        return mock_dev_.GetQueuedServiceMsg(wlan_mlme_MLMEScanConfOrdinal, &resp_);
+        return mock_dev_.GetQueuedServiceMsg(fuchsia_wlan_mlme_MLMEScanConfOrdinal, &resp_);
     }
 
     wlan_mlme::ScanRequestPtr req_;
diff --git a/manifest/garnet b/manifest/garnet
index e1ce319..e7fa9dc 100644
--- a/manifest/garnet
+++ b/manifest/garnet
@@ -6,14 +6,14 @@
     <import remote="https://fuchsia.googlesource.com/build"
             manifest="manifest/build"
             name="build"
-            revision="10b1fa91ebdb5169f9f1fa5fa5b66c5ada7285fc"/>
+            revision="e0ed947da4f83ff947c09393aee38df83c901383"/>
     <import remote="https://fuchsia.googlesource.com/scripts"
             manifest="manifest/scripts"
             name="scripts"
-            revision="d43f9c3cdfb98cb4c0ad9dd9226f99288d6ab8ac"/>
+            revision="ce3a1403adf3ba631a825b0053cabbe27ec48d0e"/>
     <import remote="https://fuchsia.googlesource.com/zircon"
             manifest="manifest/zircon"
             name="zircon"
-            revision="8752afeea257bb446799c0deefaa67ffd8356789"/>
+            revision="4cae5b1e720f9b0a5f9152943192ebe3ff89798e"/>
     </imports>
 </manifest>
diff --git a/manifest/third_party b/manifest/third_party
index bdff4e6..37eff36 100644
--- a/manifest/third_party
+++ b/manifest/third_party
@@ -23,10 +23,26 @@
              remote="https://fuchsia.googlesource.com/libc-tests"
              gerrithost="https://fuchsia-review.googlesource.com"
              revision="f61897ea129c33a7d864696bf9d26e9af997ae29"/>
+    <project name="third_party/android/platform/external/aac"
+             path="third_party/android/platform/external/aac"
+             remote="https://fuchsia.googlesource.com/third_party/android/platform/external/aac"
+             revision="a3e0aa5f25908d92535e045bbde73c9a3d19adc7"/>
+    <project name="third_party/android/platform/frameworks/av"
+             path="third_party/android/platform/frameworks/av"
+             remote="https://fuchsia.googlesource.com/third_party/android/platform/frameworks/av"
+             revision="d31b6e37f0b04a19ce084ffd60cd1c210241d24b"/>
+    <project name="third_party/android/platform/frameworks/native"
+             path="third_party/android/platform/frameworks/native"
+             remote="https://fuchsia.googlesource.com/third_party/android/platform/frameworks/native"
+             revision="266790e13c68c0cf6b9ef7dde14034619ed74916"/>
+    <project name="third_party/android/platform/system/core"
+             path="third_party/android/platform/system/core"
+             remote="https://fuchsia.googlesource.com/third_party/android/platform/system/core"
+             revision="5e041a4f45c72e1f2c283af21a40880fbb938d26"/>
     <project name="third_party/angle"
              path="third_party/angle"
              remote="https://chromium.googlesource.com/angle/angle"
-             revision="bf7b95db6b6f039f6c8797f1f4b930d46a761828"/>
+             revision="a4a3c19a4367f64b6a5db1d2cd9b3c32ab663d4d"/>
     <project name="third_party/asio"
              path="third_party/asio"
              remote="https://fuchsia.googlesource.com/third_party/asio"
@@ -45,18 +61,23 @@
     <project name="cobalt"
              path="third_party/cobalt"
              remote="https://fuchsia.googlesource.com/cobalt"
-             revision="8c4265134c74507c8d33cd867004dcbd586664a4"
+             revision="182c4f8c894593f925f081299c70ffa579e0812b"
              gerrithost="https://fuchsia-review.googlesource.com"/>
     <project name="cobalt_config"
              path="third_party/cobalt_config"
              remote="https://cobalt-analytics.googlesource.com/config"
-             revision="fa45c54d318cee8d77aafffc6c52b3c539f74372"
+             revision="6bd26b320a059b808733cf8db4ee712b09dba052"
              gerrithost="https://cobalt-analytics-review.googlesource.com"/>
     <project name="third_party/crashpad"
              path="third_party/crashpad"
              remote="https://chromium.googlesource.com/crashpad/crashpad"
              revision="3033802ed4ad78c343b85f3b5b1c22762c66e976"
              gerrithost="https://fuchsia-review.googlesource.com"/>
+    <project name="third_party/curl"
+             path="third_party/curl"
+             remote="https://fuchsia.googlesource.com/third_party/curl"
+             gerrithost="https://fuchsia-review.googlesource.com"
+             revision="8b3d7e5dbce3607c7a735e9cd84b47da991fbbfd"/>
     <project name="third_party/expat"
              path="third_party/expat"
              remote="https://fuchsia.googlesource.com/third_party/expat"
@@ -99,13 +120,28 @@
     <project name="third_party/go"
              remote="https://fuchsia.googlesource.com/third_party/go"
              gerrithost="https://fuchsia-review.googlesource.com"
-             revision="91f7a080883d5da947cc08a4dcd0d286e56d7dd5"
+             revision="90236c09ba7893aaefaa28297c0f72c1884f3cce"
              path="third_party/go"/>
     <project name="go_x_crypto"
              path="third_party/golang/crypto"
              remote="https://fuchsia.googlesource.com/third_party/golang/crypto"
              gerrithost="https://fuchsia-review.googlesource.com"
              revision="c78caca803c95773f48a844d3dcab04b9bc4d6dd"/>
+    <project name="third_party/golibs/golang.org/x/net"
+             path="third_party/golibs/golang.org/x/net"
+             remote="https://fuchsia.googlesource.com/third_party/golang.org/x/net"
+             gerrithost="https://fuchsia-review.googlesource.com"
+             revision="a04bdaca5b32abe1c069418fb7088ae607de5bd0"/>
+    <project name="third_party/golibs/golang.org/x/oauth2"
+             path="third_party/golibs/golang.org/x/oauth2"
+             remote="https://fuchsia.googlesource.com/third_party/golang.org/x/oauth2"
+             gerrithost="https://fuchsia-review.googlesource.com"
+             revision="bb50c06baba3d0c76f9d125c0719093e315b5b44"/>
+    <project name="third_party/golibs/github.com/rjw57/oauth2device"
+             path="third_party/golibs/github.com/rjw57/oauth2device"
+             remote="https://fuchsia.googlesource.com/third_party/github.com/rjw57/oauth2device"
+             gerrithost="https://fuchsia-review.googlesource.com"
+             revision="b258d5df36ce010053017146a79f287d8a31e874"/>
     <project name="third_party/golibs/github.com/google/subcommands"
              path="third_party/golibs/github.com/google/subcommands"
              remote="https://fuchsia.googlesource.com/third_party/github.com/google/subcommands"
@@ -185,7 +221,7 @@
     <project name="third_party/mesa"
              path="third_party/mesa"
              remote="https://fuchsia.googlesource.com/third_party/mesa"
-             revision="8daccbac6f710bc19d4b3d52316b8ea31df0a637"
+             revision="0df237e41d4fc839e2dfdf0356bd58279198572c"
              gerrithost="https://fuchsia-review.googlesource.com"/>
     <project name="third_party/mini_chromium"
              path="third_party/crashpad/third_party/mini_chromium/mini_chromium"
@@ -195,7 +231,7 @@
     <project name="third_party/netstack"
              path="third_party/netstack"
              remote="https://fuchsia.googlesource.com/third_party/netstack"
-             revision="7d9f264c872baf145b5bf48e5ba32faddb4db909"
+             revision="7120fac20a0811e662e74d6c209052966beae6d4"
              gerrithost="https://fuchsia-review.googlesource.com"/>
     <project name="third_party/processor-trace"
              path="third_party/processor-trace"
@@ -216,7 +252,7 @@
     <project name="rust-crates"
              path="third_party/rust-crates"
              remote="https://fuchsia.googlesource.com/third_party/rust-crates"
-             revision="599f8ec830e59a95986e044295fb2a5cf188f1d6"
+             revision="c7bb35e183541c1b0362861f16d0d7eb8a43358b"
              gerrithost="https://fuchsia-review.googlesource.com"/>
     <project name="third_party/cargo-vendor"
              path="third_party/rust-mirrors/cargo-vendor"
@@ -282,12 +318,12 @@
              path="third_party/syzkaller"
              remote="https://fuchsia.googlesource.com/third_party/syzkaller"
              gerrithost="https://fuchsia-review.googlesource.com"
-             revision="6a93ca61dfee6289292edea763b14e531cbcefd2"/>
+             revision="1b7c2ca3f9973abdb15446a42187ccff37d3e308"/>
     <project name="third_party/openssh-portable"
              path="third_party/openssh-portable"
              remote="https://fuchsia.googlesource.com/third_party/openssh-portable"
              gerrithost="https://fuchsia-review.googlesource.com"
-             revision="83479ea601ed5743622dbf3aaa1d750d39ee8223"/>
+             revision="539314429b59eac392d640acc3f3245de56c5b1d"/>
     <project name="third_party/vim"
              path="third_party/vim"
              remote="https://fuchsia.googlesource.com/third_party/vim"
@@ -297,11 +333,11 @@
              path="third_party/vulkan-cts"
              remote="https://fuchsia.googlesource.com/third_party/vulkan-cts"
              gerrithost="https://fuchsia-review.googlesource.com"
-             revision="0b0bcc6588eca26b451e49d6a8769011fadcda18"/>
+             revision="91152294f8cae38b96a1bd9074ca308f30b3b6ae"/>
     <project name="third_party/vulkan_loader_and_validation_layers"
              path="third_party/vulkan_loader_and_validation_layers"
              remote="https://fuchsia.googlesource.com/third_party/vulkan_loader_and_validation_layers"
-             revision="ae8aa1c4e396b2d9d27a141c5abfc9afb21d7386"
+             revision="f8fa14623eab00dd97aa8c88071a166dededc69f"
              gerrithost="https://fuchsia-review.googlesource.com"/>
     <project name="third_party/yasm"
              path="third_party/yasm"
diff --git a/packages/config/amber_auto_ota b/packages/config/amber_auto_ota
new file mode 100644
index 0000000..2c105e8
--- /dev/null
+++ b/packages/config/amber_auto_ota
@@ -0,0 +1,5 @@
+{
+    "packages": {
+        "ota_config": "//garnet/go/src/amber/ota_config:amber_flags"
+    }
+}
diff --git a/packages/examples/all b/packages/examples/all
index 9a969f8..3e5ea9f 100644
--- a/packages/examples/all
+++ b/packages/examples/all
@@ -5,10 +5,10 @@
         "garnet/packages/examples/bluetooth",
         "garnet/packages/examples/escher",
         "garnet/packages/examples/fidl",
+        "garnet/packages/examples/http",
         "garnet/packages/examples/media",
         "garnet/packages/examples/netconnector",
         "garnet/packages/examples/netstack",
-        "garnet/packages/examples/network",
         "garnet/packages/examples/rust",
         "garnet/packages/examples/scenic",
         "garnet/packages/examples/vkcube",
diff --git a/packages/examples/http b/packages/examples/http
new file mode 100644
index 0000000..6520b4e
--- /dev/null
+++ b/packages/examples/http
@@ -0,0 +1,10 @@
+{
+    "imports": [
+        "garnet/packages/prod/network"
+    ],
+    "packages": {
+        "httpget_cpp": "//garnet/examples/http/httpget_cpp",
+        "httpget_rust": "//garnet/examples/http/httpget_rust",
+        "postfile": "//garnet/examples/http/postfile"
+    }
+}
diff --git a/packages/examples/network b/packages/examples/network
deleted file mode 100644
index 94a33cc..0000000
--- a/packages/examples/network
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "imports": [
-        "garnet/packages/prod/network"
-    ],
-    "packages": {
-        "postfile": "//garnet/examples/network/postfile",
-        "wget": "//garnet/examples/network/wget",
-        "wget-rs": "//garnet/examples/network/wget-rs"
-    }
-}
diff --git a/packages/examples/scenic b/packages/examples/scenic
index 52af117..ab79bf0 100644
--- a/packages/examples/scenic
+++ b/packages/examples/scenic
@@ -9,6 +9,7 @@
         "hello_stereo": "//garnet/examples/ui:hello_stereo",
         "shadertoy_client": "//garnet/examples/ui:shadertoy_client",
         "shadertoy_service": "//garnet/examples/ui:shadertoy_service",
+        "shapes_a11y_view": "//garnet/examples/ui:shapes_a11y_view",
         "shapes_view": "//garnet/examples/ui:shapes_view",
         "sketchy_client": "//garnet/examples/ui:sketchy_client",
         "sketchy_service": "//garnet/bin/ui/sketchy:sketchy_service",
diff --git a/packages/experimental/tests_magma b/packages/experimental/tests_magma
index 34a5080..45eb7b0 100644
--- a/packages/experimental/tests_magma
+++ b/packages/experimental/tests_magma
@@ -3,6 +3,9 @@
         "garnet/packages/prod/sbase"
     ],
     "packages": {
-        "magma-test": "//garnet/lib/magma/tests:magma-test"
+        "magma-tests": "//garnet/lib/magma/tests:tests",
+        "vulkan-tests": "//garnet/lib/magma/tests:vulkan-tests",
+        "magma-intel-gen-tests": "//garnet/lib/magma/gnbuild/magma-intel-gen:tests",
+        "magma-arm-mali-tests": "//garnet/lib/magma/gnbuild/magma-arm-mali:tests"
     }
 }
diff --git a/packages/prod/magma b/packages/prod/magma
index dad1d52..99eb163 100644
--- a/packages/prod/magma
+++ b/packages/prod/magma
@@ -1,5 +1,8 @@
 {
     "packages": {
-        "magma": "//garnet/lib/magma"
+        "libmagma": "//garnet/lib/magma:libmagma",
+        "magma-intel-gen": "//garnet/lib/magma/gnbuild/magma-intel-gen",
+        "magma-arm-mali": "//garnet/lib/magma/gnbuild/magma-arm-mali",
+        "magma-vsl-gc": "//garnet/lib/magma/gnbuild/magma-vsl-gc"
     }
 }
diff --git a/packages/prod/network b/packages/prod/network
index a950c2f..f624d8f 100644
--- a/packages/prod/network
+++ b/packages/prod/network
@@ -3,6 +3,6 @@
         "garnet/packages/prod/netstack"
     ],
     "packages": {
-        "network": "//garnet/bin/network"
+        "network": "//garnet/bin/http"
     }
 }
diff --git a/packages/tests/all b/packages/tests/all
index f504d26..d1a4793 100644
--- a/packages/tests/all
+++ b/packages/tests/all
@@ -15,6 +15,8 @@
         "garnet/packages/tests/dhcpd",
         "garnet/packages/tests/escher",
         "garnet/packages/tests/fidl",
+        "garnet/packages/tests/fidl_compatibility_test",
+        "garnet/packages/tests/fidl_compatibility_test_bin",
         "garnet/packages/tests/fidl_compatibility_test_server_cpp",
         "garnet/packages/tests/fsl",
         "garnet/packages/tests/fxl",
@@ -41,7 +43,9 @@
         "garnet/packages/tests/scenic",
         "garnet/packages/tests/svc",
         "garnet/packages/tests/syslog",
-	"garnet/packages/tests/syzkaller",
+        "garnet/packages/tests/sysmgr",
+        "garnet/packages/tests/sysmgr_tests",
+        "garnet/packages/tests/syzkaller",
         "garnet/packages/tests/tracing",
         "garnet/packages/tests/url",
         "garnet/packages/tests/vulkan",
diff --git a/packages/tests/fidl b/packages/tests/fidl
index 7bfdbde..852d0ba 100644
--- a/packages/tests/fidl
+++ b/packages/tests/fidl
@@ -1,5 +1,6 @@
 {
     "packages": {
-        "fidl_tests": "//garnet/public/lib/fidl/cpp:fidl_tests"
+        "fidl_tests": "//garnet/public/lib/fidl/cpp:fidl_tests",
+        "echo2_server_cpp_tests": "//garnet/examples/fidl/echo2_server_cpp:echo2_server_cpp_tests"
     }
 }
diff --git a/packages/tests/fidl_compatibility_test b/packages/tests/fidl_compatibility_test
new file mode 100644
index 0000000..0abcb16
--- /dev/null
+++ b/packages/tests/fidl_compatibility_test
@@ -0,0 +1,9 @@
+{
+    "imports": [
+        "garnet/packages/tests/fidl_compatibility_test_bin",
+        "garnet/packages/tests/fidl_compatibility_test_server_cpp"
+    ],
+    "packages": {
+        "fidl_compatibility_test": "//garnet/bin/fidl_compatibility_test:package"
+    }
+}
diff --git a/packages/tests/fidl_compatibility_test_bin b/packages/tests/fidl_compatibility_test_bin
new file mode 100644
index 0000000..c1eb072
--- /dev/null
+++ b/packages/tests/fidl_compatibility_test_bin
@@ -0,0 +1,5 @@
+{
+    "packages": {
+        "fidl_compatibility_test_bin": "//garnet/bin/fidl_compatibility_test:fidl_compatibility_test_bin"
+    }
+}
diff --git a/packages/tests/magma_non_hardware b/packages/tests/magma_non_hardware
index 6444045..2424cde 100644
--- a/packages/tests/magma_non_hardware
+++ b/packages/tests/magma_non_hardware
@@ -3,6 +3,8 @@
         "garnet/packages/prod/sbase"
     ],
     "packages": {
-        "magma-nonhardware-tests": "//garnet/lib/magma/tests:magma-nonhardware-tests"
+        "magma-nonhardware-tests": "//garnet/lib/magma/tests:nonhardware-tests",
+        "magma-intel-gen-nonhardware-tests": "//garnet/lib/magma/gnbuild/magma-intel-gen:nonhardware-tests",
+        "magma-arm-mali-nonhardware-tests": "//garnet/lib/magma/gnbuild/magma-arm-mali:nonhardware-tests"
     }
 }
diff --git a/packages/tests/network b/packages/tests/network
index dfe8bdb..8900089 100644
--- a/packages/tests/network
+++ b/packages/tests/network
@@ -3,7 +3,7 @@
         "garnet/packages/prod/network"
     ],
     "packages": {
-        "mwget": "//garnet/bin/network/tests/manual/mwget",
-        "network_service_tests": "//garnet/bin/network:network_service_tests"
+        "mwget": "//garnet/bin/http/tests/manual/mwget",
+        "network_service_tests": "//garnet/bin/http:http_service_tests"
     }
 }
diff --git a/packages/tests/runtime b/packages/tests/runtime
index f3422e4..53797bd 100644
--- a/packages/tests/runtime
+++ b/packages/tests/runtime
@@ -3,6 +3,7 @@
         "garnet/packages/prod/runtime"
     ],
     "packages": {
-        "appmgr_tests": "//garnet/bin/appmgr:appmgr_tests"
+        "appmgr_unittests": "//garnet/bin/appmgr:appmgr_unittests",
+        "appmgr_integrationtests": "//garnet/bin/appmgr:appmgr_integrationtests"
     }
 }
diff --git a/packages/tests/scenic b/packages/tests/scenic
index 7fd0ee1..c3e9709 100644
--- a/packages/tests/scenic
+++ b/packages/tests/scenic
@@ -3,6 +3,7 @@
         "garnet/packages/prod/scenic"
     ],
     "packages": {
-        "scenic_tests": "//garnet/bin/ui:scenic_tests"
+        "scenic_tests": "//garnet/bin/ui:scenic_tests",
+        "scenic_benchmarks": "//garnet/bin/ui/tests/performance:scenic_benchmarks"
     }
 }
diff --git a/packages/tests/sysmgr b/packages/tests/sysmgr
new file mode 100644
index 0000000..428e1ec
--- /dev/null
+++ b/packages/tests/sysmgr
@@ -0,0 +1,8 @@
+{
+    "imports": [
+       "garnet/packages/prod/sysmgr"
+    ],
+    "packages": {
+        "sysmgr_tests": "//garnet/bin/sysmgr/integration_tests"
+    }
+}
diff --git a/packages/tests/sysmgr_tests b/packages/tests/sysmgr_tests
new file mode 100644
index 0000000..de6721a
--- /dev/null
+++ b/packages/tests/sysmgr_tests
@@ -0,0 +1,5 @@
+{
+    "packages": {
+        "sysmgr_tests": "//garnet/bin/sysmgr/test:sysmgr_tests"
+    }
+}
\ No newline at end of file
diff --git a/packages/tests/wlan b/packages/tests/wlan
index 3f8d702..09d8094 100644
--- a/packages/tests/wlan
+++ b/packages/tests/wlan
@@ -1,6 +1,7 @@
 {
     "packages": {
         "wlanstack_test": "//garnet/go/src/wlan:wlanstack_test",
-        "wlan_tests": "//garnet/lib/wlan/mlme/tests:wlan_tests"
+        "wlan_tests": "//garnet/lib/wlan/mlme/tests:wlan_tests",
+        "wlanstack2_tests": "//garnet/bin/wlanstack:wlanstack2-tests"
     }
 }
diff --git a/packages/tools/all b/packages/tools/all
index 4e576f1..acf2d98 100644
--- a/packages/tools/all
+++ b/packages/tools/all
@@ -1,5 +1,6 @@
 {
     "imports": [
+        "garnet/packages/tools/curl",
         "garnet/packages/tools/iperf",
         "garnet/packages/tools/make-efi",
         "garnet/packages/tools/make-fuchsia-vol",
diff --git a/packages/tools/curl b/packages/tools/curl
new file mode 100644
index 0000000..b3af437
--- /dev/null
+++ b/packages/tools/curl
@@ -0,0 +1,5 @@
+{
+    "packages": {
+        "curl": "//third_party/curl"
+    }
+}
diff --git a/public/lib/amber/fidl/BUILD.gn b/public/lib/amber/fidl/BUILD.gn
index 089997f..81fc1e4 100644
--- a/public/lib/amber/fidl/BUILD.gn
+++ b/public/lib/amber/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "amber"
+  cpp_legacy_callbacks = true
 
   sources = [ "amber.fidl" ]
-}
\ No newline at end of file
+}
diff --git a/public/lib/amber/fidl/amber.fidl b/public/lib/amber/fidl/amber.fidl
index b0a1804..220a2bc 100644
--- a/public/lib/amber/fidl/amber.fidl
+++ b/public/lib/amber/fidl/amber.fidl
@@ -4,6 +4,23 @@
 
 library amber;
 
+struct OAuth2Config {
+  string clientId;
+
+  string clientSecret = "";
+
+  string authUrl;
+  string tokenUrl;
+  vector<string> scopes;
+  string deviceCodeUrl;
+};
+
+struct DeviceCode {
+  string userCode;
+  string verificationUrl;
+  int64 expiresIn;
+};
+
 struct KeyConfig {
   // Supported TUF key types. The only supported algorithm is ed25519.
   string type;
@@ -13,15 +30,19 @@
 };
 
 struct SourceConfig {
+  // A unique identifier that distinquishes this source from others.
+  string id;
+
   // The canonical URL for the TUF repository.
   string repoUrl;
 
-  // Download packages from this TUF repository mirror.
-  string requestUrl;
+  // Optionally download package blobs from this repository. If not specified,
+  // blobs will be fetched from `$repoUrl/blobs`.
+  string blobRepoUrl = "";
 
   // The rate limit indicates the number of requests per rateReriod, expressed
   // in milliseconds. A limit or period of zero means there is no limit.
-  int32 rateLimit;
+  uint64 rateLimit;
 
   // How frequently to poll the TUF server.
   int32 ratePeriod;
@@ -29,6 +50,8 @@
   // A vector of public keys. These keys must match one of the trusted keys
   // known to the system.
   vector<KeyConfig> rootKeys;
+
+  OAuth2Config? oauth2Config;
 };
 
 
@@ -65,4 +88,10 @@
   8: PackagesActivated(vector<string> merkle);
 
   9: GetUpdateComplete(string name, string? version, string? merkle) -> (handle<channel> rplyChan);
+
+  10: CheckForSystemUpdate() -> (bool res);
+
+  // Log into the source specified by the source id. Returns the oauth2 device
+  // flow code if the source is configured for authentication, or null if not.
+  11: Login(string sourceId) -> (DeviceCode? device);
 };
diff --git a/public/lib/app/cpp/BUILD.gn b/public/lib/app/cpp/BUILD.gn
index 9191daa..94b0f57 100644
--- a/public/lib/app/cpp/BUILD.gn
+++ b/public/lib/app/cpp/BUILD.gn
@@ -20,5 +20,6 @@
     "//garnet/public/lib/fidl/cpp",
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/svc/cpp",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/public/lib/app/cpp/environment_services.cc b/public/lib/app/cpp/environment_services.cc
index a1080fb..c8edf89 100644
--- a/public/lib/app/cpp/environment_services.cc
+++ b/public/lib/app/cpp/environment_services.cc
@@ -4,7 +4,7 @@
 
 #include "lib/app/cpp/environment_services.h"
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 
 namespace fuchsia {
 namespace sys {
diff --git a/public/lib/app/cpp/outgoing.cc b/public/lib/app/cpp/outgoing.cc
index eac6239..4798987 100644
--- a/public/lib/app/cpp/outgoing.cc
+++ b/public/lib/app/cpp/outgoing.cc
@@ -4,7 +4,7 @@
 
 #include "lib/app/cpp/outgoing.h"
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <lib/async/default.h>
 #include <zircon/process.h>
 #include <zircon/processargs.h>
diff --git a/public/lib/app/cpp/outgoing.h b/public/lib/app/cpp/outgoing.h
index a108afc..720dabe 100644
--- a/public/lib/app/cpp/outgoing.h
+++ b/public/lib/app/cpp/outgoing.h
@@ -7,6 +7,7 @@
 
 #include <fs/pseudo-dir.h>
 #include <fs/service.h>
+#include <lib/fit/function.h>
 
 #include <memory>
 
@@ -69,7 +70,7 @@
   // by the interface).
   template <typename Interface>
   using InterfaceRequestHandler =
-      std::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
+      fit::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
 
   // Adds the specified interface to the set of public interfaces.
   //
@@ -90,7 +91,7 @@
       const std::string& service_name = Interface::Name_) const {
     return public_dir()->AddEntry(
         service_name.c_str(),
-        fbl::AdoptRef(new fs::Service([handler](zx::channel channel) {
+        fbl::AdoptRef(new fs::Service([handler = std::move(handler)](zx::channel channel) {
           handler(fidl::InterfaceRequest<Interface>(std::move(channel)));
           return ZX_OK;
         })));
diff --git a/public/lib/app/cpp/service_provider_impl.cc b/public/lib/app/cpp/service_provider_impl.cc
index 3fa68c2..7e658da 100644
--- a/public/lib/app/cpp/service_provider_impl.cc
+++ b/public/lib/app/cpp/service_provider_impl.cc
@@ -6,8 +6,6 @@
 
 #include <utility>
 
-#include "lib/fxl/functional/make_copyable.h"
-
 namespace fuchsia {
 namespace sys {
 
@@ -50,7 +48,7 @@
 
 void ServiceProviderImpl::SetDefaultServiceConnector(
     DefaultServiceConnector connector) {
-  default_service_connector_ = connector;
+  default_service_connector_ = std::move(connector);
 }
 
 void ServiceProviderImpl::SetDefaultServiceProvider(
@@ -60,11 +58,11 @@
     return;
   }
 
-  default_service_connector_ = fxl::MakeCopyable(
+  default_service_connector_ =
       [provider = std::move(provider)](std::string service_name,
                                        zx::channel client_handle) {
         provider->ConnectToService(service_name, std::move(client_handle));
-      });
+      };
 }
 
 }  // namespace sys
diff --git a/public/lib/app/cpp/service_provider_impl.h b/public/lib/app/cpp/service_provider_impl.h
index b02bf9d..4e63524 100644
--- a/public/lib/app/cpp/service_provider_impl.h
+++ b/public/lib/app/cpp/service_provider_impl.h
@@ -5,9 +5,9 @@
 #ifndef LIB_APP_CPP_SERVICE_PROVIDER_IMPL_H_
 #define LIB_APP_CPP_SERVICE_PROVIDER_IMPL_H_
 
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
-#include <functional>
 #include <string>
 #include <unordered_map>
 #include <utility>
@@ -26,13 +26,13 @@
   // |ServiceConnector| is the generic, type-unsafe interface for objects used
   // by |ServiceProviderImpl| to connect generic "interface requests" (i.e.,
   // just channels) specified by service name to service implementations.
-  using ServiceConnector = std::function<void(zx::channel)>;
+  using ServiceConnector = fit::function<void(zx::channel)>;
 
   // |DefaultServiceConnector| is the default last resort service connector
   // which is called when the service provider does not recognize a particular
   // service name.  This may be used to implement service provider delegation
   // or more complex name-based service resolution strategies.
-  using DefaultServiceConnector = std::function<void(std::string, zx::channel)>;
+  using DefaultServiceConnector = fit::function<void(std::string, zx::channel)>;
 
   // A |InterfaceRequestHandler<Interface>| is simply a function that
   // handles an interface request for |Interface|. If it determines that the
@@ -41,7 +41,7 @@
   // by the interface).
   template <typename Interface>
   using InterfaceRequestHandler =
-      std::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
+      fit::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
 
   // Constructs this service provider implementation in an unbound state.
   ServiceProviderImpl();
@@ -83,7 +83,7 @@
   void AddService(InterfaceRequestHandler<Interface> handler,
                   const std::string& service_name = Interface::Name_) {
     AddServiceForName(
-        [handler](zx::channel channel) {
+        [handler = std::move(handler)](zx::channel channel) {
           handler(fidl::InterfaceRequest<Interface>(std::move(channel)));
         },
         service_name);
diff --git a/public/lib/app/cpp/startup_context.cc b/public/lib/app/cpp/startup_context.cc
index 4a39b50..8e6944f 100644
--- a/public/lib/app/cpp/startup_context.cc
+++ b/public/lib/app/cpp/startup_context.cc
@@ -4,7 +4,7 @@
 
 #include "lib/app/cpp/startup_context.h"
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <lib/async/default.h>
 #include <zircon/process.h>
 #include <zircon/processargs.h>
diff --git a/public/lib/app/cpp/testing/BUILD.gn b/public/lib/app/cpp/testing/BUILD.gn
new file mode 100644
index 0000000..5b66518
--- /dev/null
+++ b/public/lib/app/cpp/testing/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2016 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("testing") {
+  testonly = true
+
+  sources = [
+    "startup_context_for_test.cc",
+    "startup_context_for_test.h",
+  ]
+
+  deps = [
+    "//garnet/public/lib/app/cpp",
+  ]
+}
diff --git a/public/lib/app/cpp/testing/startup_context_for_test.cc b/public/lib/app/cpp/testing/startup_context_for_test.cc
new file mode 100644
index 0000000..8167df4
--- /dev/null
+++ b/public/lib/app/cpp/testing/startup_context_for_test.cc
@@ -0,0 +1,40 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <lib/fdio/util.h>
+#include <lib/fxl/logging.h>
+
+#include "startup_context_for_test.h"
+
+namespace fuchsia {
+namespace sys {
+namespace testing {
+
+StartupContextForTest::StartupContextForTest(
+    zx::channel service_root_client, zx::channel service_root_server,
+    zx::channel directory_request_client, zx::channel directory_request_server)
+    : StartupContext(std::move(service_root_client),
+                     std::move(directory_request_server)) {
+  zx::channel public_dir_client, public_dir_server;
+  FXL_CHECK(zx::channel::create(0, &public_dir_client, &public_dir_server) ==
+            ZX_OK);
+  FXL_CHECK(fdio_service_connect_at(directory_request_client.get(), "public",
+                                    public_dir_server.release()) == ZX_OK);
+  services_.Bind(std::move(public_dir_client));
+}
+
+std::unique_ptr<StartupContextForTest> StartupContextForTest::Create() {
+  // TODO(CP-46): implement /svc instrumentation
+  zx::channel service_root_client, service_root_server;
+  zx::channel::create(0, &service_root_client, &service_root_server);
+  zx::channel directory_request_client, directory_request_server;
+  zx::channel::create(0, &directory_request_client, &directory_request_server);
+  return std::make_unique<StartupContextForTest>(
+      std::move(service_root_client), std::move(service_root_server),
+      std::move(directory_request_client), std::move(directory_request_server));
+}
+
+}  // namespace testing
+}  // namespace sys
+}  // namespace fuchsia
diff --git a/public/lib/app/cpp/testing/startup_context_for_test.h b/public/lib/app/cpp/testing/startup_context_for_test.h
new file mode 100644
index 0000000..7698d0d
--- /dev/null
+++ b/public/lib/app/cpp/testing/startup_context_for_test.h
@@ -0,0 +1,39 @@
+// Copyright 2016 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_APP_CPP_TESTING_STARTUP_CONTEXT_FOR_TEST_H_
+#define LIB_APP_CPP_TESTING_STARTUP_CONTEXT_FOR_TEST_H_
+
+#include <fuchsia/sys/cpp/fidl.h>
+
+#include "lib/app/cpp/startup_context.h"
+#include "lib/svc/cpp/services.h"
+
+namespace fuchsia {
+namespace sys {
+namespace testing {
+
+// A fake |StartupContext| for testing.
+// Does not allow publishing or accessing services outside of the test
+// environment. Exposes controllers that can be used by test cases to verify
+// context interactions under test.
+class StartupContextForTest : public StartupContext {
+ public:
+  StartupContextForTest(zx::channel service_root_client,
+                        zx::channel service_root_server,
+                        zx::channel directory_request_client,
+                        zx::channel directory_request_server);
+  static std::unique_ptr<StartupContextForTest> Create();
+
+  const Services& services() const { return services_; }
+
+ private:
+  fuchsia::sys::Services services_;
+};
+
+}  // namespace testing
+}  // namespace sys
+}  // namespace fuchsia
+
+#endif  // LIB_APP_CPP_TESTING_STARTUP_CONTEXT_FOR_TEST_H_
diff --git a/public/lib/app/fidl/BUILD.gn b/public/lib/app/fidl/BUILD.gn
index e961a80..65cb923 100644
--- a/public/lib/app/fidl/BUILD.gn
+++ b/public/lib/app/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.sys"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/audio_policy/fidl/BUILD.gn b/public/lib/audio_policy/fidl/BUILD.gn
index d327b9a..c159362 100644
--- a/public/lib/audio_policy/fidl/BUILD.gn
+++ b/public/lib/audio_policy/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "audio_policy"
+  cpp_legacy_callbacks = true
 
   sources = [
     "audio_policy.fidl",
diff --git a/public/lib/auth/fidl/BUILD.gn b/public/lib/auth/fidl/BUILD.gn
index 0714ee8..e86d52c 100644
--- a/public/lib/auth/fidl/BUILD.gn
+++ b/public/lib/auth/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "auth"
+  cpp_legacy_callbacks = true
   sources = [
     "auth_provider.fidl",
     "auth_provider_factory.fidl",
diff --git a/public/lib/backoff/BUILD.gn b/public/lib/backoff/BUILD.gn
index abc07db..3d0ca17 100644
--- a/public/lib/backoff/BUILD.gn
+++ b/public/lib/backoff/BUILD.gn
@@ -11,6 +11,7 @@
 
   public_deps = [
     "//garnet/public/lib/fxl",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/zx",
   ]
 }
diff --git a/public/lib/backoff/exponential_backoff.cc b/public/lib/backoff/exponential_backoff.cc
index ea21ac1..e1a1091 100644
--- a/public/lib/backoff/exponential_backoff.cc
+++ b/public/lib/backoff/exponential_backoff.cc
@@ -10,13 +10,13 @@
 
 namespace backoff {
 
-ExponentialBackoff::ExponentialBackoff(std::function<uint64_t()> seed_generator)
-    : ExponentialBackoff(zx::msec(100), 2u, zx::sec(60 * 60), seed_generator) {}
+ExponentialBackoff::ExponentialBackoff(fit::function<uint64_t()> seed_generator)
+    : ExponentialBackoff(zx::msec(100), 2u, zx::sec(60 * 60), std::move(seed_generator)) {}
 
 ExponentialBackoff::ExponentialBackoff(zx::duration initial_delay,
                                        uint32_t retry_factor,
                                        zx::duration max_delay,
-                                       std::function<uint64_t()> seed_generator)
+                                       fit::function<uint64_t()> seed_generator)
     : initial_delay_(initial_delay),
       retry_factor_(retry_factor),
       max_delay_(max_delay),
diff --git a/public/lib/backoff/exponential_backoff.h b/public/lib/backoff/exponential_backoff.h
index 81e245e..4989fd4 100644
--- a/public/lib/backoff/exponential_backoff.h
+++ b/public/lib/backoff/exponential_backoff.h
@@ -7,6 +7,8 @@
 
 #include <random>
 
+#include <lib/fit/function.h>
+
 #include "lib/backoff/backoff.h"
 #include "lib/fxl/random/rand.h"
 
@@ -19,10 +21,10 @@
 class ExponentialBackoff : public Backoff {
  public:
   explicit ExponentialBackoff(
-      std::function<uint64_t()> seed_generator = fxl::RandUint64);
+      fit::function<uint64_t()> seed_generator = fxl::RandUint64);
   ExponentialBackoff(
       zx::duration initial_delay, uint32_t retry_factor, zx::duration max_delay,
-      std::function<uint64_t()> seed_generator = fxl::RandUint64);
+      fit::function<uint64_t()> seed_generator = fxl::RandUint64);
   ~ExponentialBackoff() override;
 
   zx::duration GetNext() override;
diff --git a/public/lib/backoff/testing/BUILD.gn b/public/lib/backoff/testing/BUILD.gn
index b0f02db..31f08cc 100644
--- a/public/lib/backoff/testing/BUILD.gn
+++ b/public/lib/backoff/testing/BUILD.gn
@@ -12,6 +12,7 @@
 
   public_deps = [
     "//garnet/public/lib/backoff",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/public/lib/backoff/testing/test_backoff.cc b/public/lib/backoff/testing/test_backoff.cc
index a4ebd47..ff01d8d 100644
--- a/public/lib/backoff/testing/test_backoff.cc
+++ b/public/lib/backoff/testing/test_backoff.cc
@@ -20,8 +20,8 @@
 
 void TestBackoff::Reset() { reset_count++; }
 
-void TestBackoff::SetOnGetNext(fxl::Closure on_get_next) {
-  on_get_next_ = on_get_next;
+void TestBackoff::SetOnGetNext(fit::closure on_get_next) {
+  on_get_next_ = std::move(on_get_next);
 }
 
 }  // namespace backoff
diff --git a/public/lib/backoff/testing/test_backoff.h b/public/lib/backoff/testing/test_backoff.h
index b919e72..1a78596 100644
--- a/public/lib/backoff/testing/test_backoff.h
+++ b/public/lib/backoff/testing/test_backoff.h
@@ -5,8 +5,9 @@
 #ifndef LIB_BACKOFF_TESTING_TEST_BACKOFF_H_
 #define LIB_BACKOFF_TESTING_TEST_BACKOFF_H_
 
+#include <lib/fit/function.h>
+
 #include "lib/backoff/backoff.h"
-#include "lib/fxl/functional/closure.h"
 
 namespace backoff {
 
@@ -19,7 +20,7 @@
   zx::duration GetNext() override;
   void Reset() override;
 
-  void SetOnGetNext(fxl::Closure on_get_next);
+  void SetOnGetNext(fit::closure on_get_next);
 
   zx::duration backoff_to_return = zx::sec(0);
 
@@ -27,7 +28,7 @@
   int reset_count = 0;
 
  private:
-  fxl::Closure on_get_next_;
+  fit::closure on_get_next_;
   FXL_DISALLOW_COPY_AND_ASSIGN(TestBackoff);
 };
 
diff --git a/public/lib/bluetooth/fidl/BUILD.gn b/public/lib/bluetooth/fidl/BUILD.gn
index 5e3b174..e34dd92 100644
--- a/public/lib/bluetooth/fidl/BUILD.gn
+++ b/public/lib/bluetooth/fidl/BUILD.gn
@@ -14,13 +14,16 @@
 }
 
 fidl("bluetooth") {
-
+  cpp_legacy_callbacks = true
+  name = "fuchsia.bluetooth"
   sources = [
     "common.fidl",
   ]
 }
 
 fidl("bluetooth_control") {
+  cpp_legacy_callbacks = true
+  name = "fuchsia.bluetooth.control"
   sources = [
     "control.fidl",
   ]
@@ -28,6 +31,8 @@
 }
 
 fidl("bluetooth_gatt") {
+  cpp_legacy_callbacks = true
+  name = "fuchsia.bluetooth.gatt"
   sources = [
     "gatt.fidl",
   ]
@@ -35,6 +40,8 @@
 }
 
 fidl("bluetooth_low_energy") {
+  cpp_legacy_callbacks = true
+  name = "fuchsia.bluetooth.le"
   sources = [
     "low_energy.fidl",
   ]
diff --git a/public/lib/bluetooth/fidl/common.fidl b/public/lib/bluetooth/fidl/common.fidl
index dfc704a..06b40cb 100644
--- a/public/lib/bluetooth/fidl/common.fidl
+++ b/public/lib/bluetooth/fidl/common.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library bluetooth;
+library fuchsia.bluetooth;
 
 enum ErrorCode {
   UNKNOWN = 0;
diff --git a/public/lib/bluetooth/fidl/control.fidl b/public/lib/bluetooth/fidl/control.fidl
index cc053c3..a59d8e5 100644
--- a/public/lib/bluetooth/fidl/control.fidl
+++ b/public/lib/bluetooth/fidl/control.fidl
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library bluetooth_control;
+library fuchsia.bluetooth.control;
+
+using fuchsia.bluetooth;
 
 // Possible values for the LE Appearance property which describes the external
 // appearance of a
@@ -116,10 +118,10 @@
   Appearance appearance;
 
   // The most recently obtained advertising signal strength for this device.
-  bluetooth.Int8? rssi;
+  fuchsia.bluetooth.Int8? rssi;
 
   // The most recently obtained transmission power for this device.
-  bluetooth.Int8? tx_power;
+  fuchsia.bluetooth.Int8? tx_power;
 
   // Whether or not a BR/EDR and/or LE connection exists between the local
   // adapter and this device.
@@ -140,10 +142,10 @@
 
   // Whether or not the local adapter is currently discoverable over BR/EDR and
   // LE physical channels.
-  bluetooth.Bool? discoverable;
+  fuchsia.bluetooth.Bool? discoverable;
 
   // Whether or not device discovery is currently being performed.
-  bluetooth.Bool? discovering;
+  fuchsia.bluetooth.Bool? discovering;
 
   // Service UUIDs of all local services that are published and available to
   // other devices via this adapter. These services are usually registered
@@ -200,7 +202,7 @@
 
   // Sets the local adapter with the given |identifier| to act as the backing
   // adapter for all Bluetooth interfaces.
-  5: SetActiveAdapter(string identifier) -> (bluetooth.Status @status);
+  5: SetActiveAdapter(string identifier) -> (fuchsia.bluetooth.Status @status);
 
   // Returns information on the current active adapter, if it exists.
   6: GetActiveAdapterInfo() -> (AdapterInfo? @adapter);
@@ -212,7 +214,7 @@
   //
   // Discovery may be active when not reqested.
   // If an error occurs when starting discovery, it is reflected in |status|.
-  8: RequestDiscovery(bool discovery) -> (bluetooth.Status @status);
+  8: RequestDiscovery(bool discovery) -> (fuchsia.bluetooth.Status @status);
 
   // Retrieve the set of known remote devices.
   // Note: These devices are not guaranteed to still be reachable.
@@ -220,22 +222,22 @@
 
   // Sets the public Bluetooth name for this device, or resets to the default
   // name if |name| is not present.
-  10: SetName(string? name) -> (bluetooth.Status @status);
+  10: SetName(string? name) -> (fuchsia.bluetooth.Status @status);
 
   // Set the discoverability of this device.
-  11: SetDiscoverable(bool discoverable) -> (bluetooth.Status @status);
+  11: SetDiscoverable(bool discoverable) -> (fuchsia.bluetooth.Status @status);
 
   // Attempt to connect to the remote |device_id|.
   // If |bond| is set, try to bond to this device as well.
-  12: Connect(string device_id, bool bond) -> (bluetooth.Status @status);
+  12: Connect(string device_id, bool bond) -> (fuchsia.bluetooth.Status @status);
 
   // Disconnect a previously-connected device.
   // Note: This does not remove a device bond, see Control::Forget.
-  13: Disconnect(string device_id) -> (bluetooth.Status @status);
+  13: Disconnect(string device_id) -> (fuchsia.bluetooth.Status @status);
 
   // Forgets |device_id| completely, removing all bonding information.
   // This will disconnect a device if it is connected.
-  14: Forget(string device_id) -> (bluetooth.Status @status);
+  14: Forget(string device_id) -> (fuchsia.bluetooth.Status @status);
 
   // Events
 
diff --git a/public/lib/bluetooth/fidl/gatt.fidl b/public/lib/bluetooth/fidl/gatt.fidl
index aef784a..e986687 100644
--- a/public/lib/bluetooth/fidl/gatt.fidl
+++ b/public/lib/bluetooth/fidl/gatt.fidl
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library bluetooth_gatt;
+library fuchsia.bluetooth.gatt;
+
+using fuchsia.bluetooth;
 
 // Codes that can be returned in the |protocol_error_code| field of a
 // bluetooth.Error.
@@ -192,17 +194,17 @@
   //
   // Returns the success or failure @status of the call and a unique identifier
   // that can be used to unregister the service.
-  1: PublishService(ServiceInfo info, LocalServiceDelegate delegate, request<LocalService> service) -> (bluetooth.Status @status);
+  1: PublishService(ServiceInfo info, LocalServiceDelegate delegate, request<LocalService> service) -> (fuchsia.bluetooth.Status @status);
 };
 
 interface RemoteService {
   // Returns the characteristics and characteristic descriptors that belong to
   // this service.
-  1: DiscoverCharacteristics() -> (bluetooth.Status @status, vector<Characteristic> characteristics);
+  1: DiscoverCharacteristics() -> (fuchsia.bluetooth.Status @status, vector<Characteristic> characteristics);
 
   // Reads the value of the characteristic with |id| and return it in the reply.
   // If |status| indicates an error |value| will be empty.
-  2: ReadCharacteristic(uint64 id, uint16 offset) -> (bluetooth.Status @status, vector<uint8> value);
+  2: ReadCharacteristic(uint64 id, uint16 offset) -> (fuchsia.bluetooth.Status @status, vector<uint8> value);
 
   // Writes |value| to the characteristic with |id|. The ATT protocol method is
   // selected based on the input parameters and properties of the
@@ -216,7 +218,7 @@
   //      procedure will be used.
   //   c. If the characteristic does not claim to support the selected
   //      procedure, the request will fail with ErrorCode.NotSupported.
-  3: WriteCharacteristic(uint64 id, uint16 offset, vector<uint8> value) -> (bluetooth.Status @status);
+  3: WriteCharacteristic(uint64 id, uint16 offset, vector<uint8> value) -> (fuchsia.bluetooth.Status @status);
 
   // Subscribe or unsubscribe to notifications/indications from the characteristic with
   // the given |id|. Notifications or indications will be enabled if |enable| is
@@ -234,7 +236,7 @@
   // On success, the OnCharacteristicValueUpdated event will be sent whenever
   // the peer sends a notification or indication. The local host will
   // automically confirm indications.
-  4: NotifyCharacteristic(uint64 id, bool enable) -> (bluetooth.Status @status);
+  4: NotifyCharacteristic(uint64 id, bool enable) -> (fuchsia.bluetooth.Status @status);
 
   // Events:
   // Called when a characteristic value notification or indication is received.
@@ -249,7 +251,7 @@
   //
   // To further interact with services, clients must obtain a RemoteService
   // handle by calling ConnectToService().
-  1: ListServices(vector<string>? uuids) -> (bluetooth.Status @status, vector<ServiceInfo> services);
+  1: ListServices(vector<string>? uuids) -> (fuchsia.bluetooth.Status @status, vector<ServiceInfo> services);
 
   // Connects the RemoteService with the given identifier.
   2: ConnectToService(uint64 id, request<RemoteService> service);
diff --git a/public/lib/bluetooth/fidl/low_energy.fidl b/public/lib/bluetooth/fidl/low_energy.fidl
index c168386..c732070 100644
--- a/public/lib/bluetooth/fidl/low_energy.fidl
+++ b/public/lib/bluetooth/fidl/low_energy.fidl
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library bluetooth_low_energy;
+library fuchsia.bluetooth.le;
+
+using fuchsia.bluetooth;
+using fuchsia.bluetooth.gatt;
 
 struct ServiceDataEntry {
   string uuid;
@@ -20,10 +23,10 @@
   string? name;
 
   // The radio transmission power level reported in the advertisement.
-  bluetooth.Int8? tx_power_level;
+  fuchsia.bluetooth.Int8? tx_power_level;
 
   // The appearance reported in the advertisemet.
-  bluetooth.UInt16? appearance;
+  fuchsia.bluetooth.UInt16? appearance;
 
   // List of service UUIDs reported in the advertisement.
   vector<string>? service_uuids;
@@ -54,7 +57,7 @@
   bool connectable;
 
   // The last known RSSI of this device, if known.
-  bluetooth.Int8? rssi;
+  fuchsia.bluetooth.Int8? rssi;
 
   // Advertising data broadcast by this device if this device is a broadcaster or peripheral.
   AdvertisingData? advertising_data;
@@ -74,12 +77,12 @@
   // Filter based on a company identifier present in the manufacturer data. If this filter parameter
   // is set, then the advertising payload must contain manufacturer specific data with the provided
   // company identifier to satisfy this filter.
-  bluetooth.UInt16? manufacturer_identifier;
+  fuchsia.bluetooth.UInt16? manufacturer_identifier;
 
   // Filter based on whether or not a device is connectable. For example, a client that is only
   // interested in peripherals that it can connect to can set this to true. Similarly a client can
   // scan only for braodcasters by setting this to false.
-  bluetooth.Bool? connectable;
+  fuchsia.bluetooth.Bool? connectable;
 
   // Filter results based on a portion of the advertised device name.
   string? name_substring;
@@ -89,7 +92,7 @@
   //   1. Radio transmission power level and received signal strength must be available for the path
   //      loss calculation;
   //   2. The calculated path loss value must be less than, or equal to, |max_path_loss|.
-  bluetooth.Int8? max_path_loss;
+  fuchsia.bluetooth.Int8? max_path_loss;
 };
 
 interface CentralDelegate {
@@ -131,7 +134,7 @@
   // will be notified for all discoverable devices that are found. This is not recommended; clients
   // should generally filter results by at least one of |filter.service_uuids|,
   // |filter.service_data|, and/or |filter.manufacturer_identifier|.
-  4: StartScan(ScanFilter? filter) -> (bluetooth.Status @status);
+  4: StartScan(ScanFilter? filter) -> (fuchsia.bluetooth.Status @status);
 
   // Terminate a previously started scan session.
   5: StopScan();
@@ -142,10 +145,10 @@
   // On success, |gatt_client| will be bound and can be used for GATT client
   // role procedures. On failure, |gatt_client| will be closed and |status| will
   // indicate an error.
-  6: ConnectPeripheral(string identifier, request<bluetooth_gatt.Client> gatt_client) -> (bluetooth.Status @status);
+  6: ConnectPeripheral(string identifier, request<fuchsia.bluetooth.gatt.Client> gatt_client) -> (fuchsia.bluetooth.Status @status);
 
   // Disconnects this Central's connection to the peripheral with the given identifier.
-  7: DisconnectPeripheral(string identifier) -> (bluetooth.Status @status);
+  7: DisconnectPeripheral(string identifier) -> (fuchsia.bluetooth.Status @status);
 };
 
 interface PeripheralDelegate {
@@ -194,8 +197,8 @@
   //   - If |anonymous| advertising is requested but the controller cannot support it.
   1: StartAdvertising(AdvertisingData advertising_data, AdvertisingData? scan_result,
                       PeripheralDelegate? delegate, uint32 interval_ms, bool anonymous) ->
-                      (bluetooth.Status @status, string? advertisement_id);
+                      (fuchsia.bluetooth.Status @status, string? advertisement_id);
 
   // Stop a an advertising session that was previously started by this application.
-  2: StopAdvertising(string advertisement_id) -> (bluetooth.Status @status);
+  2: StopAdvertising(string advertisement_id) -> (fuchsia.bluetooth.Status @status);
 };
diff --git a/public/lib/bluetooth/fidl/storage.fidl b/public/lib/bluetooth/fidl/storage.fidl
deleted file mode 100644
index d111e7b..0000000
--- a/public/lib/bluetooth/fidl/storage.fidl
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2018 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library bluetooth_storage;
-
-
-struct Key {
-
-  bool auth;
-
-  array<uint8>:16 value;
-
-
-};
-
-
-struct LTK {
-
-  Key key;
-
-  uint8 key_size;
-
-  // TODO legacy stuff
-};
-
-struct LEData {
-  string address;
-
-  bool resolvable;
-
-  bool master;
-
-//   LEConnectionParamaters?
-
-  vector<string> gatt_services;
-
-  LTK? ltk;
-
-  Key? irk;
-
-  Key? csrk;
-};
-
-struct BondData {
-  string name;
-//BREDR
-  LEData? le;
-};
-
-interface Storage {
-  1: AddBondedDevice(string local_id, vector<BondData> bonds) -> (bluetooth.Status available);
-
-  1000: -> OnPai(string local_id);
-};
diff --git a/public/lib/device_settings/fidl/BUILD.gn b/public/lib/device_settings/fidl/BUILD.gn
index 06b7c5f..d95af70 100644
--- a/public/lib/device_settings/fidl/BUILD.gn
+++ b/public/lib/device_settings/fidl/BUILD.gn
@@ -5,8 +5,9 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "device_settings"
+  name = "fuchsia.devicesettings"
+  cpp_legacy_callbacks = true
   sources = [
-    "device_settings.fidl",
+    "devicesettings.fidl",
   ]
 }
diff --git a/public/lib/device_settings/fidl/device_settings.fidl b/public/lib/device_settings/fidl/devicesettings.fidl
similarity index 97%
rename from public/lib/device_settings/fidl/device_settings.fidl
rename to public/lib/device_settings/fidl/devicesettings.fidl
index 2d8e34f..05281ba 100644
--- a/public/lib/device_settings/fidl/device_settings.fidl
+++ b/public/lib/device_settings/fidl/devicesettings.fidl
@@ -1,7 +1,7 @@
 // Copyright 2017 The Fuchsia Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-library device_settings;
+library fuchsia.devicesettings;
 
 enum Status: uint8 {
   ok = 1;
diff --git a/public/lib/escher/BUILD.gn b/public/lib/escher/BUILD.gn
index d1a9d07..47cea1f 100644
--- a/public/lib/escher/BUILD.gn
+++ b/public/lib/escher/BUILD.gn
@@ -280,6 +280,8 @@
     "util/stack_allocator.h",
     "util/stopwatch.h",
     "util/trace_macros.h",
+    "util/tracer.cc",
+    "util/tracer.h",
     "vk/buffer.cc",
     "vk/buffer.h",
     "vk/buffer_factory.cc",
@@ -330,6 +332,20 @@
       "flib/fence_set_listener.h",
       "flib/release_fence_signaller.cc",
       "flib/release_fence_signaller.h",
+      "util/fuchsia_utils.cc",
+      "util/fuchsia_utils.h",
+    ]
+    public_deps += [
+      "//garnet/public/lib/images/fidl",
+      "//zircon/public/lib/fit",
+    ]
+    deps += [ "//zircon/public/lib/trace" ]
+  }
+
+  if (is_linux) {
+    sources += [
+      "util/impl/trace_macros_impl.cc",
+      "util/impl/trace_macros_impl.h",
     ]
   }
 
@@ -342,18 +358,6 @@
     ":glm_config",
     ":thread_safety_warning",
   ]
-
-  if (is_fuchsia) {
-    public_deps += [
-      "//garnet/public/lib/images/fidl",
-      "//zircon/public/lib/fit",
-    ]
-    deps += [ "//zircon/public/lib/trace" ]
-    sources += [
-      "util/fuchsia_utils.cc",
-      "util/fuchsia_utils.h",
-    ]
-  }
 }
 
 group("unittests") {
diff --git a/public/lib/escher/util/impl/trace_macros_impl.cc b/public/lib/escher/util/impl/trace_macros_impl.cc
new file mode 100644
index 0000000..e2ae480
--- /dev/null
+++ b/public/lib/escher/util/impl/trace_macros_impl.cc
@@ -0,0 +1,25 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "lib/escher/util/impl/trace_macros_impl.h"
+
+#include "lib/fxl/logging.h"
+
+namespace escher {
+namespace impl {
+
+void TraceEndOnScopeClose::Initialize(const char* category, const char* name) {
+  FXL_DCHECK(category && name);
+  category_ = category;
+  name_ = name;
+}
+
+TraceEndOnScopeClose::~TraceEndOnScopeClose() {
+  if (category_) {
+    AddTraceEvent(TRACE_EVENT_PHASE_END, category_, name_);
+  }
+}
+
+}  // namespace impl
+}  // namespace escher
diff --git a/public/lib/escher/util/impl/trace_macros_impl.h b/public/lib/escher/util/impl/trace_macros_impl.h
new file mode 100644
index 0000000..b947a5a
--- /dev/null
+++ b/public/lib/escher/util/impl/trace_macros_impl.h
@@ -0,0 +1,62 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_ESCHER_UTIL_IMPL_TRACE_MACROS_IMPL_H_
+#define LIB_ESCHER_UTIL_IMPL_TRACE_MACROS_IMPL_H_
+
+#include "lib/escher/util/tracer.h"
+#include "lib/fxl/build_config.h"
+
+#ifdef OS_FUCHSIA
+#error Should only be included on Linux.
+#endif
+
+#include <atomic>
+
+// Keep overhead low by using temporary variables. The variable names are based
+// on line numbers in order to prevent name collisions.
+#define TRACE_INTERNAL_EVENT_UID3(a, b) trace_event_unique_##a##b
+#define TRACE_INTERNAL_EVENT_UID2(a, b) TRACE_INTERNAL_EVENT_UID3(a, b)
+#define TRACE_INTERNAL_EVENT_UID(name_prefix) \
+  TRACE_INTERNAL_EVENT_UID2(name_prefix, __LINE__)
+
+// For this simple implementation, all categories are always enabled.
+//
+// TODO(ES-85): Add support for additional trace arguments. Currently, they are
+// silently dropped.
+#define TRACE_INTERNAL_DURATION(category, name, args...)                     \
+  escher::impl::TraceEndOnScopeClose TRACE_INTERNAL_EVENT_UID(profileScope); \
+  escher::impl::AddTraceEvent(TRACE_EVENT_PHASE_BEGIN, category, name);      \
+  TRACE_INTERNAL_EVENT_UID(profileScope).Initialize(category, name);
+
+#define TRACE_EVENT_PHASE_BEGIN ('B')
+#define TRACE_EVENT_PHASE_END ('E')
+
+namespace escher {
+namespace impl {
+
+// Used by TRACE_* macros. Do not use directly.
+class TraceEndOnScopeClose {
+ public:
+  TraceEndOnScopeClose() {}
+  ~TraceEndOnScopeClose();
+
+  void Initialize(const char* category_enabled, const char* name);
+
+ private:
+  const char* category_ = nullptr;
+  const char* name_ = nullptr;
+};
+
+static inline void AddTraceEvent(char phase, const char* category,
+                                 const char* name) {
+  if (auto tracer = GetTracer()) {
+    tracer->AddTraceEvent(phase, category, name);
+  }
+}
+
+}  // namespace impl
+}  // namespace escher
+
+#endif  // LIB_ESCHER_UTIL_IMPL_TRACE_MACROS_IMPL_H_
diff --git a/public/lib/escher/util/trace_macros.h b/public/lib/escher/util/trace_macros.h
index b07592b..63931af 100644
--- a/public/lib/escher/util/trace_macros.h
+++ b/public/lib/escher/util/trace_macros.h
@@ -2,11 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef LIB_ESCHER_UTIL_TRACE_MACROS_H_
+#define LIB_ESCHER_UTIL_TRACE_MACROS_H_
+
+// See <trace/event.h> for usage documentation.
+
 #include "lib/fxl/build_config.h"
 
 #ifdef OS_FUCHSIA
 #include <trace/event.h>
 #else
-// No-op placeholders.
-#define TRACE_DURATION(category, name, args...)
+#include "lib/escher/util/impl/trace_macros_impl.h"
+
+#define TRACE_DURATION(category_literal, name_literal, args...) \
+  TRACE_INTERNAL_DURATION((category_literal), (name_literal), args)
 #endif
+
+#endif  // LIB_ESCHER_UTIL_TRACE_MACROS_H_
diff --git a/public/lib/escher/util/tracer.cc b/public/lib/escher/util/tracer.cc
new file mode 100644
index 0000000..554fafc
--- /dev/null
+++ b/public/lib/escher/util/tracer.cc
@@ -0,0 +1,60 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "lib/escher/util/tracer.h"
+
+#include <iostream>
+#include <sstream>
+
+#include "lib/fxl/files/file.h"
+
+namespace escher {
+
+namespace {
+Tracer* g_tracer = nullptr;
+}  // anonymous namespace
+
+Tracer::Tracer() {
+  FXL_DCHECK(!g_tracer);
+  g_tracer = this;
+  events_.reserve(10000000);
+}
+
+inline void WriteEvent(std::ostream& str, const Tracer::Event& event) {
+  str << "\t\t{ \"name\": \"" << event.name << "\", \"cat\": \""
+      << event.category << "\", \"ph\": \"" << event.phase << "\", \"pid\": \""
+      << 1 << "\", \"tid\": \"" << 1 << "\", \"ts\": \"" << event.microseconds
+      << "\" }";
+}
+
+Tracer::~Tracer() {
+  FXL_DCHECK(g_tracer == this);
+  g_tracer = nullptr;
+
+  std::ostringstream str;
+
+  str << "{\n\t\"traceEvents\": [\n";
+
+  const size_t count = events_.size();
+  for (size_t i = 0; i < count - 1; ++i) {
+    WriteEvent(str, events_[i]);
+    str << ",\n";
+  }
+  WriteEvent(str, events_[count - 1]);
+  str << "\n\t],"
+      << "\n\t\"displayTimeUnit\": \"ms\""
+      << "\n}\n";
+
+  files::WriteFile("escher.trace", str.str().data(), str.str().length());
+  FXL_LOG(INFO) << "Wrote trace file: escher.trace";
+}
+
+void Tracer::AddTraceEvent(char phase, const char* category, const char* name) {
+  events_.push_back(
+      {phase, category, name, stopwatch_.GetElapsedMicroseconds()});
+}
+
+Tracer* GetTracer() { return g_tracer; }
+
+}  // namespace escher
diff --git a/public/lib/escher/util/tracer.h b/public/lib/escher/util/tracer.h
new file mode 100644
index 0000000..a624fa0
--- /dev/null
+++ b/public/lib/escher/util/tracer.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIB_ESCHER_UTIL_TRACER_H_
+#define LIB_ESCHER_UTIL_TRACER_H_
+
+#include <vector>
+
+#include "lib/escher/util/stopwatch.h"
+
+namespace escher {
+
+// Trace support for Escher-on-Linux, used by the macros in trace_macros_impl.h.
+// It can be instantiated on Fuchsia, but it won't be used.  Upon construction,
+// registers itself as a global, which can be obtained via GetTracer().  Upon
+// destruction, writes an "escher.trace" JSON file, in the format expected by
+// chrome://tracing.
+class Tracer {
+ public:
+  Tracer();
+  ~Tracer();
+  void AddTraceEvent(char phase, const char* category, const char* name);
+
+  struct Event {
+    char phase;
+    const char* category;
+    const char* name;
+    uint64_t microseconds;
+  };
+
+ private:
+  Stopwatch stopwatch_;
+  std::vector<Event> events_;
+};
+
+Tracer* GetTracer();
+
+}  // namespace escher
+
+#endif  // LIB_ESCHER_UTIL_TRACER_H_
diff --git a/public/lib/fidl/compatibility_test/BUILD.gn b/public/lib/fidl/compatibility_test/BUILD.gn
index de23258..da5b6ad 100644
--- a/public/lib/fidl/compatibility_test/BUILD.gn
+++ b/public/lib/fidl/compatibility_test/BUILD.gn
@@ -7,6 +7,7 @@
 
 fidl("compatibility_test_service") {
   name = "fidl.test.compatibility"
+  cpp_legacy_callbacks = true
 
   sources = [
     "compatibility_test_service.fidl",
diff --git a/public/lib/fidl/compatibility_test/compatibility_test_service.fidl b/public/lib/fidl/compatibility_test/compatibility_test_service.fidl
index 0fae72d..d4044cc 100644
--- a/public/lib/fidl/compatibility_test/compatibility_test_service.fidl
+++ b/public/lib/fidl/compatibility_test/compatibility_test_service.fidl
@@ -360,12 +360,18 @@
   structs structs;
   unions unions;
   bool b;
-  // Non-null means the recipient should act as a proxy for the other server.
-  // Null means just echo it back.
-  string? forward_to_server;
 };
 
 [Discoverable]
 interface Echo {
-  1: EchoStruct(Struct value) -> (Struct value);
+  // If |forward_to_server| is empty, just returns |value|.
+  // If |forward_to_server| is not empty, it is treated as the URL of a server
+  // which implements this interface. The server that recieves the non-empty
+  // |forward_to_server| arg acts as a proxy for that other server.
+  1: EchoStruct(Struct value, string forward_to_server) -> (Struct value);
+
+  // Same as the above, but the server should use the event to return the
+  // response, rather than a return value.
+  2: EchoStructNoRetVal(Struct value, string forward_to_server);
+  3: -> EchoEvent(Struct value);
 };
diff --git a/public/lib/fidl/cpp/BUILD.gn b/public/lib/fidl/cpp/BUILD.gn
index 386a538..f779859 100644
--- a/public/lib/fidl/cpp/BUILD.gn
+++ b/public/lib/fidl/cpp/BUILD.gn
@@ -84,6 +84,7 @@
 
 fidl("fidl_test") {
   name = "fidl.test.misc"
+  cpp_legacy_callbacks = true
 
   testonly = true
 
diff --git a/public/lib/fidl/cpp/interface_ptr.h b/public/lib/fidl/cpp/interface_ptr.h
index 6652791..2bdd8ad 100644
--- a/public/lib/fidl/cpp/interface_ptr.h
+++ b/public/lib/fidl/cpp/interface_ptr.h
@@ -215,6 +215,11 @@
   // Events for unbound callbacks are ignored.
   Proxy& events() const { return impl_->proxy; }
 
+#ifdef FIDL_ENABLE_LEGACY_WAIT_FOR_RESPONSE
+
+  // DEPRECATED: Using InterfaceSyncPtr instead. If used in a test, consider
+  // spinning the async::Loop instead.
+  //
   // Blocks the calling thread until either a message arrives on the previously
   // bound channel or an error occurs.
   //
@@ -229,6 +234,9 @@
     return WaitForResponseUntil(zx::time::infinite());
   }
 
+  // DEPRECATED: Using InterfaceSyncPtr instead. If used in a test, consider
+  // spinning the async::Loop instead.
+  //
   // Blocks the calling thread until either a message arrives on the previously
   // bound channel, an error occurs, or the |deadline| is exceeded.
   //
@@ -244,6 +252,7 @@
   zx_status_t WaitForResponseUntil(zx::time deadline) {
     return impl_->controller.reader().WaitAndDispatchOneMessageUntil(deadline);
   }
+#endif
 
   // Sets an error handler that will be called if an error causes the
   // underlying channel to be closed.
diff --git a/public/lib/fidl/cpp/interface_ptr_unittest.cc b/public/lib/fidl/cpp/interface_ptr_unittest.cc
index 557f476..47bc8d7 100644
--- a/public/lib/fidl/cpp/interface_ptr_unittest.cc
+++ b/public/lib/fidl/cpp/interface_ptr_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#define FIDL_ENABLE_LEGACY_WAIT_FOR_RESPONSE
+
 #include "lib/fidl/cpp/interface_ptr.h"
 
 #include <lib/fidl/cpp/message_buffer.h>
diff --git a/public/lib/fidl/cpp/internal/header.h b/public/lib/fidl/cpp/internal/header.h
index eb1cc68..50e8b8c 100644
--- a/public/lib/fidl/cpp/internal/header.h
+++ b/public/lib/fidl/cpp/internal/header.h
@@ -9,6 +9,7 @@
 #include <ostream>
 
 #include <lib/fidl/cpp/array.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 #include <lib/zx/event.h>
 #include <lib/zx/eventpair.h>
diff --git a/public/lib/fidl/cpp/test/BUILD.gn b/public/lib/fidl/cpp/test/BUILD.gn
index 9d5fa16..32464e9 100644
--- a/public/lib/fidl/cpp/test/BUILD.gn
+++ b/public/lib/fidl/cpp/test/BUILD.gn
@@ -30,6 +30,7 @@
 
 fidl("frobinator") {
   name = "fidl.test.frobinator"
+  cpp_legacy_callbacks = true
 
   sources = [
     "frobinator.fidl"
diff --git a/public/lib/fidl/go/src/fidl/bindings/bindings_test/BUILD.gn b/public/lib/fidl/go/src/fidl/bindings/bindings_test/BUILD.gn
index a94e4b3..c988988 100644
--- a/public/lib/fidl/go/src/fidl/bindings/bindings_test/BUILD.gn
+++ b/public/lib/fidl/go/src/fidl/bindings/bindings_test/BUILD.gn
@@ -8,6 +8,7 @@
 
 fidl("test_fidl") {
   name = "fidl.test.gobindings"
+  cpp_legacy_callbacks = true
   sources = [
     "test.fidl",
   ]
diff --git a/public/lib/fidl/rust/fidl/src/endpoints2.rs b/public/lib/fidl/rust/fidl/src/endpoints2.rs
index 735a18f..b90b8cb 100644
--- a/public/lib/fidl/rust/fidl/src/endpoints2.rs
+++ b/public/lib/fidl/rust/fidl/src/endpoints2.rs
@@ -16,6 +16,9 @@
     /// Queries made against the proxy are sent to the paired `ServerEnd`.
     type Proxy: Proxy;
 
+    /// The type of the stream of requests coming into a server.
+    type RequestStream: RequestStream;
+
     /// The name of the service (to be used for service lookup and discovery).
     const NAME: &'static str;
 }
@@ -26,6 +29,19 @@
     fn from_channel(inner: async::Channel) -> Self;
 }
 
+/// A stream of requests coming into a FIDL server over a channel.
+pub trait RequestStream: Sized {
+    /// A type that can be used to send events and shut down the request stream.
+    type ControlHandle;
+
+    /// Returns a copy of the `ControlHandle` for the given stream.
+    /// This handle can be used to send events and shut down the request stream.
+    fn control_handle(&self) -> Self::ControlHandle;
+
+    /// Create a request stream from the given channel.
+    fn from_channel(inner: async::Channel) -> Self;
+}
+
 /// The `Client` end of a FIDL connection.
 #[derive(Eq, PartialEq, Hash)]
 pub struct ClientEnd<T> {
@@ -109,6 +125,26 @@
     pub fn into_channel(self) -> zx::Channel {
         self.inner
     }
+
+    /// Create a stream of requests off of the channel.
+    pub fn into_stream(self) -> Result<T::RequestStream, Error>
+        where T: ServiceMarker,
+    {
+        Ok(T::RequestStream::from_channel(
+            async::Channel::from_channel(self.inner)
+                .map_err(Error::AsyncChannel)?))
+    }
+
+    /// Create a stream of requests and an event-sending handle
+    /// from the channel.
+    pub fn into_stream_and_control_handle(self)
+        -> Result<(T::RequestStream, <T::RequestStream as RequestStream>::ControlHandle), Error>
+        where T: ServiceMarker,
+    {
+        let stream = self.into_stream()?;
+        let control_handle = stream.control_handle();
+        Ok((stream, control_handle))
+    }
 }
 
 impl<T> zx::AsHandleRef for ServerEnd<T> {
@@ -150,3 +186,14 @@
 impl<T> zx::HandleBased for ServerEnd<T> {}
 
 handle_based_codable![ClientEnd :- <T,>, ServerEnd :- <T,>,];
+
+/// Create a server endpoint and a client proxy connected to it by a channel.
+///
+/// Useful for sending channel handles to calls that take arguments
+/// of type `request<SomeInterface>`
+pub fn create_endpoints<T: ServiceMarker>() -> Result<(T::Proxy, ServerEnd<T>), Error> {
+    let (client, server) = zx::Channel::create().map_err(Error::ChannelPairCreate)?;
+    let proxy = ClientEnd::<T>::new(client).into_proxy()?;
+    let server_end = ServerEnd::new(server);
+    Ok((proxy, server_end))
+}
diff --git a/public/lib/fonts/fidl/BUILD.gn b/public/lib/fonts/fidl/BUILD.gn
index 90874a2..2a74320 100644
--- a/public/lib/fonts/fidl/BUILD.gn
+++ b/public/lib/fonts/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fonts"
+  cpp_legacy_callbacks = true
 
   sources = [
     "font_provider.fidl",
diff --git a/public/lib/fsl/BUILD.gn b/public/lib/fsl/BUILD.gn
index 0d632b1..0745fec 100644
--- a/public/lib/fsl/BUILD.gn
+++ b/public/lib/fsl/BUILD.gn
@@ -68,7 +68,6 @@
 
 package("package") {
   testonly = true
-  deprecated_system_image = true
 
   package_name = "fsl"
 
diff --git a/public/lib/fsl/io/BUILD.gn b/public/lib/fsl/io/BUILD.gn
index 7b74404..17d1684 100644
--- a/public/lib/fsl/io/BUILD.gn
+++ b/public/lib/fsl/io/BUILD.gn
@@ -20,6 +20,7 @@
     "//garnet/public/lib/fsl/tasks",
     "//garnet/public/lib/fxl",
     "//zircon/public/lib/fdio",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/zx",
   ]
 }
diff --git a/public/lib/fsl/io/device_watcher.cc b/public/lib/fsl/io/device_watcher.cc
index 4228726..9ab310e 100644
--- a/public/lib/fsl/io/device_watcher.cc
+++ b/public/lib/fsl/io/device_watcher.cc
@@ -8,7 +8,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <lib/async/default.h>
 #include <zircon/device/vfs.h>
 
diff --git a/public/lib/fsl/io/device_watcher.h b/public/lib/fsl/io/device_watcher.h
index 12a8c46..5d4edd6 100644
--- a/public/lib/fsl/io/device_watcher.h
+++ b/public/lib/fsl/io/device_watcher.h
@@ -6,9 +6,9 @@
 #define LIB_FSL_IO_DEVICE_WATCHER_H_
 
 #include <lib/async/cpp/wait.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
-#include <functional>
 #include <memory>
 #include <string>
 
@@ -28,7 +28,7 @@
   // Callback function which is invoked whenever a device is found.
   // |dir_fd| is the file descriptor of the directory (use for openat()).
   // |filename| is the name of the file relative to the directory.
-  using Callback = std::function<void(int dir_fd, std::string filename)>;
+  using Callback = fit::function<void(int dir_fd, std::string filename)>;
 
   ~DeviceWatcher() = default;
 
diff --git a/public/lib/fsl/io/fd.cc b/public/lib/fsl/io/fd.cc
index 2b94e46..c6e1d53 100644
--- a/public/lib/fsl/io/fd.cc
+++ b/public/lib/fsl/io/fd.cc
@@ -4,8 +4,8 @@
 
 #include "lib/fsl/io/fd.h"
 
-#include <fdio/limits.h>
-#include <fdio/util.h>
+#include <lib/fdio/limits.h>
+#include <lib/fdio/util.h>
 #include <zircon/processargs.h>
 
 namespace fsl {
diff --git a/public/lib/fsl/tasks/fd_waiter.h b/public/lib/fsl/tasks/fd_waiter.h
index d6ba0b0..19d3e76 100644
--- a/public/lib/fsl/tasks/fd_waiter.h
+++ b/public/lib/fsl/tasks/fd_waiter.h
@@ -7,7 +7,7 @@
 
 #include <functional>
 
-#include <fdio/private.h>
+#include <lib/fdio/private.h>
 #include <lib/async/cpp/wait.h>
 #include <lib/async/default.h>
 #include <zircon/types.h>
diff --git a/public/lib/fsl/tasks/message_loop_unittest.cc b/public/lib/fsl/tasks/message_loop_unittest.cc
index 508cdea..de6aea8 100644
--- a/public/lib/fsl/tasks/message_loop_unittest.cc
+++ b/public/lib/fsl/tasks/message_loop_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "lib/fsl/tasks/message_loop.h"
 
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <lib/zx/channel.h>
 #include <lib/zx/event.h>
 
diff --git a/public/lib/fsl/vmo/file.cc b/public/lib/fsl/vmo/file.cc
index 739b1be..cb72e22 100644
--- a/public/lib/fsl/vmo/file.cc
+++ b/public/lib/fsl/vmo/file.cc
@@ -5,7 +5,7 @@
 #include "lib/fsl/vmo/file.h"
 
 #include <fcntl.h>
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
 #include <sys/stat.h>
 #include <unistd.h>
 
diff --git a/public/lib/fxl/functional/auto_call.h b/public/lib/fxl/functional/auto_call.h
index 7754ddf..6f2bf94 100644
--- a/public/lib/fxl/functional/auto_call.h
+++ b/public/lib/fxl/functional/auto_call.h
@@ -39,8 +39,11 @@
   }
 
   AutoCall& operator=(AutoCall&& c) {
+    call();
     call_ = std::move(c.call_);
+    active_ = c.active_;
     c.cancel();
+    return *this;
   }
 
   // no copy, assign, but allow move
diff --git a/public/lib/fxl/functional/auto_call_unittest.cc b/public/lib/fxl/functional/auto_call_unittest.cc
index 2f4652b..3bbddb5 100644
--- a/public/lib/fxl/functional/auto_call_unittest.cc
+++ b/public/lib/fxl/functional/auto_call_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "lib/fxl/functional/auto_call.h"
 
+#include "lib/fxl/functional/closure.h"
+
 #include <memory>
 
 #include "gtest/gtest.h"
@@ -11,39 +13,187 @@
 namespace fxl {
 namespace {
 
-void reset_arg(int* p) { *p = 0; }
-
-void helper_basic(int* var_ptr) {
-  auto reset = fxl::MakeAutoCall([var_ptr]() { reset_arg(var_ptr); });
-}
+void incr_arg(int* p) { *p += 1; }
 
 TEST(AutoCallTest, Basic) {
-  int var = 42;
-  helper_basic(&var);
-  EXPECT_EQ(var, 0);
-}
-
-void helper_cancel(int* var_ptr) {
-  auto reset = fxl::MakeAutoCall([var_ptr]() { reset_arg(var_ptr); });
-  reset.cancel();
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall([&var]() { incr_arg(&var); });
+    EXPECT_EQ(var, 0);
+  }
+  EXPECT_EQ(var, 1);
 }
 
 TEST(AutoCallTest, Cancel) {
-  int var = 42;
-  helper_cancel(&var);
-  EXPECT_EQ(var, 42);
-}
-
-void helper_call(int* var_ptr) {
-  auto reset = fxl::MakeAutoCall([var_ptr]() { reset_arg(var_ptr); });
-  reset.call();
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall([&var]() { incr_arg(&var); });
+    EXPECT_EQ(var, 0);
+    do_incr.cancel();
+    EXPECT_EQ(var, 0);
+    // Once cancelled, call has no effect.
+    do_incr.call();
+    EXPECT_EQ(var, 0);
+  }
+  EXPECT_EQ(var, 0);
 }
 
 TEST(AutoCallTest, Call) {
-  int var = 42;
-  helper_call(&var);
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall([&var]() { incr_arg(&var); });
+    EXPECT_EQ(var, 0);
+    do_incr.call();
+    EXPECT_EQ(var, 1);
+    // Call is effective only once.
+    do_incr.call();
+    EXPECT_EQ(var, 1);
+  }
+  EXPECT_EQ(var, 1);
+}
+
+TEST(AutoCallTest, RecursiveCall) {
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall<fxl::Closure>([]() { /* no-op */ });
+    do_incr = fxl::MakeAutoCall<fxl::Closure>([&do_incr, &var]() {
+      incr_arg(&var);
+      do_incr.call();
+    });
+    EXPECT_EQ(var, 0);
+    do_incr.call();
+    EXPECT_EQ(var, 1);
+  }
+  EXPECT_EQ(var, 1);
+}
+
+TEST(AutoCallTest, MoveConstructBasic) {
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall([&var]() { incr_arg(&var); });
+    auto do_incr2(std::move(do_incr));
+    EXPECT_EQ(var, 0);
+  }
+  EXPECT_EQ(var, 1);
+}
+
+TEST(AutoCallTest, MoveConstructFromCancelled) {
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall([&var]() { incr_arg(&var); });
+    do_incr.cancel();
+    auto do_incr2(std::move(do_incr));
+    EXPECT_EQ(var, 0);
+  }
   EXPECT_EQ(var, 0);
 }
 
+TEST(AutoCallTest, MoveConstructFromCalled) {
+  int var = 0;
+  {
+    auto do_incr = fxl::MakeAutoCall([&var]() { incr_arg(&var); });
+    EXPECT_EQ(var, 0);
+    do_incr.call();
+    EXPECT_EQ(var, 1);
+    // Must not be called again, since do_incr has triggered already.
+    auto do_incr2(std::move(do_incr));
+  }
+  EXPECT_EQ(var, 1);
+}
+
+TEST(AutoCallTest, MoveAssignBasic) {
+  int var1 = 0, var2 = 0;
+  {
+    auto do_incr =
+        fxl::MakeAutoCall<fxl::Closure>([&var1]() { incr_arg(&var1); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    auto do_incr2 =
+        fxl::MakeAutoCall<fxl::Closure>([&var2]() { incr_arg(&var2); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    // do_incr2 is moved-to, so its associated function is called.
+    do_incr2 = std::move(do_incr);
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 1);
+  }
+  EXPECT_EQ(var1, 1);
+  EXPECT_EQ(var2, 1);
+}
+
+TEST(AutoCallTest, MoveAssignWiderScope) {
+  int var1 = 0, var2 = 0;
+  {
+    auto do_incr =
+        fxl::MakeAutoCall<fxl::Closure>([&var1]() { incr_arg(&var1); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    {
+      auto do_incr2 =
+          fxl::MakeAutoCall<fxl::Closure>([&var2]() { incr_arg(&var2); });
+      EXPECT_EQ(var1, 0);
+      EXPECT_EQ(var2, 0);
+      // do_incr is moved-to, so its associated function is called.
+      do_incr = std::move(do_incr2);
+      EXPECT_EQ(var1, 1);
+      EXPECT_EQ(var2, 0);
+    }
+    // do_incr2 is out of scope but has been moved so its function is not
+    // called.
+    EXPECT_EQ(var1, 1);
+    EXPECT_EQ(var2, 0);
+  }
+  EXPECT_EQ(var1, 1);
+  EXPECT_EQ(var2, 1);
+}
+
+TEST(AutoCallTest, MoveAssignFromCancelled) {
+  int var1 = 0, var2 = 0;
+  {
+    auto do_incr =
+        fxl::MakeAutoCall<fxl::Closure>([&var1]() { incr_arg(&var1); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    auto do_incr2 =
+        fxl::MakeAutoCall<fxl::Closure>([&var2]() { incr_arg(&var2); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    do_incr.cancel();
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    // do_incr2 is moved-to, so its associated function is called.
+    do_incr2 = std::move(do_incr);
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 1);
+  }
+  // do_incr was cancelled, this state is preserved by the move.
+  EXPECT_EQ(var1, 0);
+  EXPECT_EQ(var2, 1);
+}
+
+TEST(AutoCallTest, MoveAssignFromCalled) {
+  int var1 = 0, var2 = 0;
+  {
+    auto do_incr =
+        fxl::MakeAutoCall<fxl::Closure>([&var1]() { incr_arg(&var1); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    auto do_incr2 =
+        fxl::MakeAutoCall<fxl::Closure>([&var2]() { incr_arg(&var2); });
+    EXPECT_EQ(var1, 0);
+    EXPECT_EQ(var2, 0);
+    do_incr.call();
+    EXPECT_EQ(var1, 1);
+    EXPECT_EQ(var2, 0);
+    // do_incr2 is moved-to, so its associated function is called.
+    do_incr2 = std::move(do_incr);
+    EXPECT_EQ(var1, 1);
+    EXPECT_EQ(var2, 1);
+  }
+  // do_incr was called already, this state is preserved by the move.
+  EXPECT_EQ(var1, 1);
+  EXPECT_EQ(var2, 1);
+}
+
 }  // namespace
 }  // namespace fxl
diff --git a/public/lib/gralloc/fidl/BUILD.gn b/public/lib/gralloc/fidl/BUILD.gn
index 02008c7..55ea7ad 100644
--- a/public/lib/gralloc/fidl/BUILD.gn
+++ b/public/lib/gralloc/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.gralloc"
+  cpp_legacy_callbacks = true
 
   sources = [
     "gralloc.fidl",
diff --git a/public/lib/gtest/BUILD.gn b/public/lib/gtest/BUILD.gn
index de0f1c3..56e175c 100644
--- a/public/lib/gtest/BUILD.gn
+++ b/public/lib/gtest/BUILD.gn
@@ -18,6 +18,7 @@
     "//garnet/public/lib/fxl",
     "//third_party/googletest:gtest",
     "//zircon/public/lib/async-testutils",
+    "//zircon/public/lib/fit",
   ]
 }
 
diff --git a/public/lib/gtest/test_with_message_loop.cc b/public/lib/gtest/test_with_message_loop.cc
index 19daa4f..6427cdf 100644
--- a/public/lib/gtest/test_with_message_loop.cc
+++ b/public/lib/gtest/test_with_message_loop.cc
@@ -41,7 +41,7 @@
 }
 
 bool RunGivenLoopUntilWithTimeout(fsl::MessageLoop* message_loop,
-                                  std::function<bool()> condition,
+                                  fit::function<bool()> condition,
                                   fxl::TimeDelta timeout,
                                   fxl::TimeDelta step) {
   const fxl::TimePoint deadline = timeout == fxl::TimeDelta::FromSeconds(0)
@@ -71,14 +71,14 @@
 }
 
 bool TestWithMessageLoop::RunLoopUntilWithTimeout(
-    std::function<bool()> condition,
+    fit::function<bool()> condition,
     fxl::TimeDelta timeout,
     fxl::TimeDelta step) {
   return RunGivenLoopUntilWithTimeout(&message_loop_, std::move(condition),
                                       timeout, step);
 }
 
-bool TestWithMessageLoop::RunLoopUntil(std::function<bool()> condition,
+bool TestWithMessageLoop::RunLoopUntil(fit::function<bool()> condition,
                                        fxl::TimeDelta step) {
   return RunGivenLoopUntilWithTimeout(&message_loop_, std::move(condition),
                                       fxl::TimeDelta::FromSeconds(0), step);
diff --git a/public/lib/gtest/test_with_message_loop.h b/public/lib/gtest/test_with_message_loop.h
index 7ff55a6..bf716d2 100644
--- a/public/lib/gtest/test_with_message_loop.h
+++ b/public/lib/gtest/test_with_message_loop.h
@@ -5,7 +5,7 @@
 #ifndef LIB_GTEST_TEST_WITH_MESSAGE_LOOP_H_
 #define LIB_GTEST_TEST_WITH_MESSAGE_LOOP_H_
 
-#include <functional>
+#include <lib/fit/function.h>
 
 #include "gtest/gtest.h"
 #include "lib/fsl/tasks/message_loop.h"
@@ -64,14 +64,14 @@
   // reached.
   // TODO(qsr): When existing usage have been migrated to
   // |RunLoopUntilWithTimeout|, remove the timeout from this method.
-  bool RunLoopUntil(std::function<bool()> condition,
+  bool RunLoopUntil(fit::function<bool()> condition,
                     fxl::TimeDelta step = fxl::TimeDelta::FromMilliseconds(10));
 
   // Runs the loop until the condition returns true or the timeout is reached.
   // Returns |true| if the condition was met, and |false| if the timeout was
   // reached.
   bool RunLoopUntilWithTimeout(
-      std::function<bool()> condition,
+      fit::function<bool()> condition,
       fxl::TimeDelta timeout = fxl::TimeDelta::FromSeconds(1),
       fxl::TimeDelta step = fxl::TimeDelta::FromMilliseconds(10));
 
diff --git a/public/lib/guest/fidl/BUILD.gn b/public/lib/guest/fidl/BUILD.gn
index 23ed45b..e6f2adb 100644
--- a/public/lib/guest/fidl/BUILD.gn
+++ b/public/lib/guest/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.guest"
+  cpp_legacy_callbacks = true
 
   sources = [
     "guest_controller.fidl",
diff --git a/public/lib/icu_data/cpp/icu_data.cc b/public/lib/icu_data/cpp/icu_data.cc
index c4f2d08..2f65e19 100644
--- a/public/lib/icu_data/cpp/icu_data.cc
+++ b/public/lib/icu_data/cpp/icu_data.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#define FIDL_ENABLE_LEGACY_WAIT_FOR_RESPONSE
+
 #include "lib/icu_data/cpp/icu_data.h"
 
 #include <lib/zx/vmar.h>
diff --git a/public/lib/icu_data/fidl/BUILD.gn b/public/lib/icu_data/fidl/BUILD.gn
index d1b7303..af0c74c 100644
--- a/public/lib/icu_data/fidl/BUILD.gn
+++ b/public/lib/icu_data/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "icu_data"
+  cpp_legacy_callbacks = true
 
   sources = [
     "icu_data.fidl",
diff --git a/public/lib/images/fidl/BUILD.gn b/public/lib/images/fidl/BUILD.gn
index 6103afa..8880023e3 100644
--- a/public/lib/images/fidl/BUILD.gn
+++ b/public/lib/images/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.images"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/mdns/cpp/BUILD.gn b/public/lib/mdns/cpp/BUILD.gn
index ca6df0a..54108ac 100644
--- a/public/lib/mdns/cpp/BUILD.gn
+++ b/public/lib/mdns/cpp/BUILD.gn
@@ -8,8 +8,9 @@
     "service_subscriber.h",
   ]
 
-  deps = [
+  public_deps = [
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/mdns/fidl",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/public/lib/mdns/cpp/service_subscriber.cc b/public/lib/mdns/cpp/service_subscriber.cc
index 8afa748..b648c32 100644
--- a/public/lib/mdns/cpp/service_subscriber.cc
+++ b/public/lib/mdns/cpp/service_subscriber.cc
@@ -10,14 +10,12 @@
 
 ServiceSubscriber::ServiceSubscriber() {}
 
-ServiceSubscriber::~ServiceSubscriber() {
-  Reset();
-}
+ServiceSubscriber::~ServiceSubscriber() { Reset(); }
 
 void ServiceSubscriber::Init(MdnsServiceSubscriptionPtr subscription,
-                             const UpdateCallback& callback) {
+                             UpdateCallback callback) {
   subscription_ = std::move(subscription);
-  callback_ = callback;
+  callback_ = std::move(callback);
   HandleInstanceUpdates();
 }
 
@@ -28,8 +26,7 @@
 }
 
 void ServiceSubscriber::HandleInstanceUpdates(
-    uint64_t version,
-    fidl::VectorPtr<MdnsServiceInstance> instances) {
+    uint64_t version, fidl::VectorPtr<MdnsServiceInstance> instances) {
   FXL_DCHECK(subscription_);
 
   if (instances) {
diff --git a/public/lib/mdns/cpp/service_subscriber.h b/public/lib/mdns/cpp/service_subscriber.h
index bbdc5fb..f3a3ccf 100644
--- a/public/lib/mdns/cpp/service_subscriber.h
+++ b/public/lib/mdns/cpp/service_subscriber.h
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MDNS_CPP_SERVICE_SUBSCRIBER_H_
+#define LIB_MDNS_CPP_SERVICE_SUBSCRIBER_H_
 
-#include <functional>
+#include <lib/fit/function.h>
+#include <mdns/cpp/fidl.h>
 
 #include "lib/fxl/macros.h"
-#include <mdns/cpp/fidl.h>
 
 namespace mdns {
 
@@ -19,8 +20,8 @@
   // describing the new service. When a service is lost, the callback is called
   // with a null |to| value and |from| value describing the lost service. When
   // a service changes, |from| is the old description, and |to| is the new one.
-  using UpdateCallback =
-      std::function<void(const MdnsServiceInstance* from, const MdnsServiceInstance* to)>;
+  using UpdateCallback = fit::function<void(const MdnsServiceInstance* from,
+                                            const MdnsServiceInstance* to)>;
 
   ServiceSubscriber();
 
@@ -28,8 +29,7 @@
 
   // Initializes the subscriber with the specified subscription. The callback
   // is optional.
-  void Init(MdnsServiceSubscriptionPtr subscription,
-            const UpdateCallback& callback);
+  void Init(MdnsServiceSubscriptionPtr subscription, UpdateCallback callback);
 
   // Returns this subscriber to its initial state, releasing the callback and
   // returning the unique subscription. The subscription can be ignored, in
@@ -61,3 +61,5 @@
 };
 
 }  // namespace mdns
+
+#endif  // LIB_MDNS_CPP_SERVICE_SUBSCRIBER_H_
diff --git a/public/lib/mdns/fidl/BUILD.gn b/public/lib/mdns/fidl/BUILD.gn
index a082c3b..4e5e09e 100644
--- a/public/lib/mdns/fidl/BUILD.gn
+++ b/public/lib/mdns/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "mdns"
+  cpp_legacy_callbacks = true
 
   sources = [
     "mdns.fidl",
diff --git a/public/lib/mdns/fidl/mdns.fidl b/public/lib/mdns/fidl/mdns.fidl
index 3981829..8c49489 100644
--- a/public/lib/mdns/fidl/mdns.fidl
+++ b/public/lib/mdns/fidl/mdns.fidl
@@ -4,13 +4,15 @@
 
 library mdns;
 
+using fuchsia.netstack;
+
 // mDNS service interface.
 [Discoverable]
 interface MdnsService {
   // Gets the addresses for the specified host name. |host_name| may not end in
   // a '.'.
   1: ResolveHostName(string host_name, uint32 timeout_ms) ->
-    (netstack.SocketAddress? v4_address, netstack.SocketAddress? v6_address);
+    (fuchsia.netstack.SocketAddress? v4_address, fuchsia.netstack.SocketAddress? v6_address);
 
   // Subscribes to a service. The subscription lasts until |subscription| is
   // unbound. |service_name| must end in '._tcp.' or '._udp.'.
@@ -96,8 +98,8 @@
 struct MdnsServiceInstance {
   string service_name;
   string instance_name;
-  netstack.SocketAddress? v4_address;
-  netstack.SocketAddress? v6_address;
+  fuchsia.netstack.SocketAddress? v4_address;
+  fuchsia.netstack.SocketAddress? v6_address;
   vector<string>? text;
 };
 
diff --git a/public/lib/media/audio/perceived_level.cc b/public/lib/media/audio/perceived_level.cc
index 74a831c..b14e781 100644
--- a/public/lib/media/audio/perceived_level.cc
+++ b/public/lib/media/audio/perceived_level.cc
@@ -7,8 +7,9 @@
 #include <algorithm>
 #include <cmath>
 
+#include <fuchsia/media/cpp/fidl.h>
+
 #include "lib/fxl/logging.h"
-#include <media/cpp/fidl.h>
 
 namespace media {
 namespace {
@@ -34,7 +35,7 @@
 // static
 float PerceivedLevel::LevelToGain(float level) {
   if (level <= 0.0f) {
-    return kMutedGain;
+    return fuchsia::media::kMutedGain;
   }
 
   if (level >= 1.0f) {
@@ -64,7 +65,7 @@
   FXL_DCHECK(max_level > 0);
 
   if (level <= 0) {
-    return kMutedGain;
+    return fuchsia::media::kMutedGain;
   }
 
   if (level >= max_level) {
diff --git a/public/lib/media/audio/perceived_level.h b/public/lib/media/audio/perceived_level.h
index b606c95..57deef7 100644
--- a/public/lib/media/audio/perceived_level.h
+++ b/public/lib/media/audio/perceived_level.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_AUDIO_PERCEIVED_LEVEL_H_
+#define LIB_MEDIA_AUDIO_PERCEIVED_LEVEL_H_
 
 namespace media {
 
@@ -34,3 +35,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_AUDIO_PERCEIVED_LEVEL_H_
diff --git a/public/lib/media/audio/types.cc b/public/lib/media/audio/types.cc
index aa3a6e1..66fb9d6 100644
--- a/public/lib/media/audio/types.cc
+++ b/public/lib/media/audio/types.cc
@@ -6,37 +6,37 @@
 
 namespace media {
 
-uint32_t BytesPerSample(AudioSampleFormat sample_format) {
+uint32_t BytesPerSample(fuchsia::media::AudioSampleFormat sample_format) {
   switch (sample_format) {
-    case AudioSampleFormat::NONE:
-    case AudioSampleFormat::ANY:
+    case fuchsia::media::AudioSampleFormat::NONE:
+    case fuchsia::media::AudioSampleFormat::ANY:
       return 0;
-    case AudioSampleFormat::UNSIGNED_8:
+    case fuchsia::media::AudioSampleFormat::UNSIGNED_8:
       return sizeof(uint8_t);
-    case AudioSampleFormat::SIGNED_16:
+    case fuchsia::media::AudioSampleFormat::SIGNED_16:
       return sizeof(int16_t);
-    case AudioSampleFormat::SIGNED_24_IN_32:
+    case fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32:
       return sizeof(int32_t);
-    case AudioSampleFormat::FLOAT:
+    case fuchsia::media::AudioSampleFormat::FLOAT:
       return sizeof(float);
   }
 }
 
-MediaType CreateLpcmMediaType(AudioSampleFormat sample_format,
-                              uint32_t channel_count,
-                              uint32_t frames_per_second) {
-  AudioMediaTypeDetails audio_details;
+fuchsia::media::MediaType CreateLpcmMediaType(
+    fuchsia::media::AudioSampleFormat sample_format, uint32_t channel_count,
+    uint32_t frames_per_second) {
+  fuchsia::media::AudioMediaTypeDetails audio_details;
   audio_details.sample_format = sample_format;
   audio_details.channels = channel_count;
   audio_details.frames_per_second = frames_per_second;
 
-  MediaTypeDetails media_details;
+  fuchsia::media::MediaTypeDetails media_details;
   media_details.set_audio(std::move(audio_details));
 
-  MediaType media_type;
-  media_type.medium = MediaTypeMedium::AUDIO;
+  fuchsia::media::MediaType media_type;
+  media_type.medium = fuchsia::media::MediaTypeMedium::AUDIO;
   media_type.details = std::move(media_details);
-  media_type.encoding = kAudioEncodingLpcm;
+  media_type.encoding = fuchsia::media::kAudioEncodingLpcm;
 
   return media_type;
 }
diff --git a/public/lib/media/audio/types.h b/public/lib/media/audio/types.h
index 14965fc..c497d60 100644
--- a/public/lib/media/audio/types.h
+++ b/public/lib/media/audio/types.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_AUDIO_TYPES_H_
+#define LIB_MEDIA_AUDIO_TYPES_H_
 
 #include <cstdint>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 
 namespace media {
 
@@ -16,34 +17,37 @@
 
 template <>
 struct SampleTypeTraits<uint8_t> {
-  static constexpr AudioSampleFormat kSampleFormat =
-      AudioSampleFormat::UNSIGNED_8;
+  static constexpr fuchsia::media::AudioSampleFormat kSampleFormat =
+      fuchsia::media::AudioSampleFormat::UNSIGNED_8;
 };
 
 template <>
 struct SampleTypeTraits<int16_t> {
-  static constexpr AudioSampleFormat kSampleFormat =
-      AudioSampleFormat::SIGNED_16;
+  static constexpr fuchsia::media::AudioSampleFormat kSampleFormat =
+      fuchsia::media::AudioSampleFormat::SIGNED_16;
 };
 
 template <>
 struct SampleTypeTraits<int32_t> {
-  static constexpr AudioSampleFormat kSampleFormat =
-      AudioSampleFormat::SIGNED_24_IN_32;
+  static constexpr fuchsia::media::AudioSampleFormat kSampleFormat =
+      fuchsia::media::AudioSampleFormat::SIGNED_24_IN_32;
 };
 
 template <>
 struct SampleTypeTraits<float> {
-  static constexpr AudioSampleFormat kSampleFormat = AudioSampleFormat::FLOAT;
+  static constexpr fuchsia::media::AudioSampleFormat kSampleFormat =
+      fuchsia::media::AudioSampleFormat::FLOAT;
 };
 
 // Returns the size in bytes of samples of the specified format.
-uint32_t BytesPerSample(AudioSampleFormat format);
+uint32_t BytesPerSample(fuchsia::media::AudioSampleFormat format);
 
 // Creates a |MediaType| for LPCM audio.
 // TODO(dalesat): Need to add channel configuration.
-MediaType CreateLpcmMediaType(AudioSampleFormat sample_format,
-                              uint32_t channel_count,
-                              uint32_t frames_per_second);
+fuchsia::media::MediaType CreateLpcmMediaType(
+    fuchsia::media::AudioSampleFormat sample_format, uint32_t channel_count,
+    uint32_t frames_per_second);
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_AUDIO_TYPES_H_
diff --git a/public/lib/media/c/audio.h b/public/lib/media/c/audio.h
index 6a288c0..c859436 100644
--- a/public/lib/media/c/audio.h
+++ b/public/lib/media/c/audio.h
@@ -5,7 +5,8 @@
 // Refer to the accompanying README.md file for detailed API documentation
 // (functions, structs and constants).
 
-#pragma once
+#ifndef LIB_MEDIA_C_AUDIO_H_
+#define LIB_MEDIA_C_AUDIO_H_
 
 #include <stdint.h>
 #include <zircon/types.h>
@@ -52,13 +53,11 @@
 
 MEDIA_CLIENT_EXPORT int
 fuchsia_audio_manager_get_output_device_default_parameters(
-    fuchsia_audio_manager* audio_manager,
-    char* device_id,
+    fuchsia_audio_manager* audio_manager, char* device_id,
     fuchsia_audio_parameters* params_out);
 
 MEDIA_CLIENT_EXPORT int fuchsia_audio_manager_create_output_stream(
-    fuchsia_audio_manager* audio_manager,
-    char* device_id,
+    fuchsia_audio_manager* audio_manager, char* device_id,
     fuchsia_audio_parameters* stream_params,
     fuchsia_audio_output_stream** stream_out);
 
@@ -66,17 +65,15 @@
     fuchsia_audio_output_stream* stream);
 
 MEDIA_CLIENT_EXPORT int fuchsia_audio_output_stream_get_min_delay(
-    fuchsia_audio_output_stream* stream,
-    zx_duration_t* delay_nsec_out);
+    fuchsia_audio_output_stream* stream, zx_duration_t* delay_nsec_out);
 
 MEDIA_CLIENT_EXPORT int fuchsia_audio_output_stream_set_gain(
-    fuchsia_audio_output_stream* stream,
-    float db_gain);
+    fuchsia_audio_output_stream* stream, float db_gain);
 
 MEDIA_CLIENT_EXPORT int fuchsia_audio_output_stream_write(
-    fuchsia_audio_output_stream* stream,
-    float* sample_buffer,
-    int num_samples,
+    fuchsia_audio_output_stream* stream, float* sample_buffer, int num_samples,
     zx_time_t pres_time);
 
 __END_CDECLS
+
+#endif  // LIB_MEDIA_C_AUDIO_H_
diff --git a/public/lib/media/c/test/audio_test.cc b/public/lib/media/c/test/audio_test.cc
index 972a000..cc4e730 100644
--- a/public/lib/media/c/test/audio_test.cc
+++ b/public/lib/media/c/test/audio_test.cc
@@ -2,28 +2,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <zircon/syscalls.h>
 #include <iostream>
 #include <vector>
 
-#include "gtest/gtest.h"
+#include <zircon/syscalls.h>
 
 #include "garnet/public/lib/media/c/audio.h"
+#include "gtest/gtest.h"
 
 extern "C" {
 fuchsia_audio_manager* audio_manager_create();
 void audio_manager_free(fuchsia_audio_manager* manager);
 int audio_manager_get_output_devices(
-    fuchsia_audio_manager* manager,
-    fuchsia_audio_device_description* desc_buff,
+    fuchsia_audio_manager* manager, fuchsia_audio_device_description* desc_buff,
     int num_device_descriptions);
 int audio_manager_get_output_device_default_parameters(
-    fuchsia_audio_manager* manager,
-    char* device_id,
+    fuchsia_audio_manager* manager, char* device_id,
     fuchsia_audio_parameters* params_out);
 int audio_manager_create_output_stream(
-    fuchsia_audio_manager* manager,
-    char* device_id,
+    fuchsia_audio_manager* manager, char* device_id,
     fuchsia_audio_parameters* stream_params,
     fuchsia_audio_output_stream** stream_out);
 int audio_output_stream_free(fuchsia_audio_output_stream* stream);
@@ -32,8 +29,7 @@
 int audio_output_stream_set_gain(fuchsia_audio_output_stream* stream,
                                  float db_gain);
 int audio_output_stream_write(fuchsia_audio_output_stream* stream,
-                              float* sample_buffer,
-                              int num_samples,
+                              float* sample_buffer, int num_samples,
                               zx_time_t pres_time);
 }
 
@@ -53,7 +49,7 @@
 // that the API provided at least some value, instead of leaving the variable in
 // its potentially uninitialized state..
 constexpr zx_duration_t INVALID_MIN_DELAY =
-  std::numeric_limits<zx_duration_t>::max();
+    std::numeric_limits<zx_duration_t>::max();
 
 //
 // Utility functions
diff --git a/public/lib/media/fidl/BUILD.gn b/public/lib/media/fidl/BUILD.gn
index 16b6261..2a1bb7f 100644
--- a/public/lib/media/fidl/BUILD.gn
+++ b/public/lib/media/fidl/BUILD.gn
@@ -5,7 +5,8 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "media"
+  name = "fuchsia.media"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
@@ -13,7 +14,6 @@
     "audio_capturer.fidl",
     "audio_renderer.fidl",
     "audio_server.fidl",
-    "media_capturer.fidl",
     "media_renderer.fidl",
     "media_result.fidl",
     "media_transport.fidl",
@@ -24,12 +24,12 @@
 }
 
 fidl("media_player") {
-  name = "media_player"
+  name = "fuchsia.mediaplayer"
+  cpp_legacy_callbacks = true
 
   sources = [
     "media_metadata.fidl",
     "media_player.fidl",
-    "media_source.fidl",
     "net_media_service.fidl",
     "problem.fidl",
     "seeking_reader.fidl",
@@ -45,12 +45,13 @@
 
 fidl("media_codec") {
   name = "media_codec"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
   sources = [
+    "codec.fidl",
     "codec_common.fidl",
     "codec_factory.fidl",
-    "codec.fidl",
   ]
 }
diff --git a/public/lib/media/fidl/audio_capturer.fidl b/public/lib/media/fidl/audio_capturer.fidl
index bc2b78b..5b6fb47 100644
--- a/public/lib/media/fidl/audio_capturer.fidl
+++ b/public/lib/media/fidl/audio_capturer.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 // AudioCapturer
 //
diff --git a/public/lib/media/fidl/audio_renderer.fidl b/public/lib/media/fidl/audio_renderer.fidl
index b798f34..1ee1961 100644
--- a/public/lib/media/fidl/audio_renderer.fidl
+++ b/public/lib/media/fidl/audio_renderer.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 // A special value which will always cause an audio renderer to become
 // explicitly muted.
diff --git a/public/lib/media/fidl/audio_server.fidl b/public/lib/media/fidl/audio_server.fidl
index b870782..3bc7e23 100644
--- a/public/lib/media/fidl/audio_server.fidl
+++ b/public/lib/media/fidl/audio_server.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 [Discoverable]
 interface AudioServer {
diff --git a/public/lib/media/fidl/codec.fidl b/public/lib/media/fidl/codec.fidl
index 3e0543d..7c6e251 100644
--- a/public/lib/media/fidl/codec.fidl
+++ b/public/lib/media/fidl/codec.fidl
@@ -198,10 +198,10 @@
   // support single-buffer mode on output.  Nearly all video decoders will set
   // this to false for their output.
   //
-  // All decoder inputs: Servers must support single-buffer mode on fuchsia.ui.input.  The
-  // client is responsible for managing the input buffer space such that filling
-  // an input packet doesn't over-write any portion of an input packet already
-  // in flight to the codec.
+  // All decoder inputs: Servers must support single-buffer mode on input.  The
+  // client is responsible for managing the input buffer space such that
+  // filling an input packet doesn't over-write any portion of an input packet
+  // already in flight to the codec.
   //
   // Encoder inputs: Server support for single-buffer mode on encoder input is
   // optional.  This is more often useful for audio than for video.
@@ -330,6 +330,46 @@
   CodecFormatDetails format_details;
 };
 
+// Default values for input and output 
+// CodecBufferConstraints.default_settings.packet_count_for_codec.
+//
+// These are defined as "const" in FIDL to avoid all server implementations
+// needing to separately define their own values, and these should be
+// reasonable as default values, but strictly speaking this is not intended to
+// promise that this value won't change from build to build.  If a client cares
+// about a specific number, the client should separately define what that
+// number is and ensure that CodecPortBufferSettings.packet_count_for_client is
+// at least large enough.
+//
+// In contrast to packet_count_for_client, the packet_count_for_codec is much
+// more codec-specific, so this file has no numbers for that - each codec will
+// set those as appropriate for the specific codec.
+//
+// These are not "recommended" values, only "default" values, in the sense that
+// the codec doesn't really know what the correct setting for these values is
+// for a given client, and if the default is not appropriate for a client,
+// large problems could result such as deadlock.  See the comments on
+// packet_count_for_client.
+//
+// Despite these defaults, every client should ideally care about the
+// packet_count_for_client setting and should ensure that the setting is at
+// least large enough to cover the number of packets the client might ever need
+// to camp on for any non-transient duration concurrently.  The defaults are
+// only intended to be plausible for some clients, not all clients.
+//
+// One for the client to be filling and one in transit.
+const uint32 kDefaultInputPacketCountForClient = 2;
+// One for the client to be rendering, and one in transit.
+const uint32 kDefaultOutputPacketCountForClient = 2;
+
+// For input, this is the default on a fairly arbitrary basis.
+//
+// TODO(dustingreen): Do we want the default for audio encoding to be
+// single_buffer_mode true instead?  If so, we may split this up by audio/video
+// encoder/decoder.
+const bool kDefaultInputIsSingleBufferMode = false;
+const bool kDefaultOutputIsSingleBufferMode = false;
+
 // CodecPortBufferSettings
 //
 // See relevant corresponding constraints in CodecBufferConstraints.  The
@@ -337,6 +377,9 @@
 //
 // The client informs the codec of these settings and then separately informs
 // the codec of each buffer.
+//
+// TODO(dustingreen): Rename from CodecPortBufferSettings to CodecBufferSettings
+// in a separate CL (after some other stuff is out of the way first).
 struct CodecPortBufferSettings {
   // buffer_lifetime_ordinal
   //
@@ -533,7 +576,7 @@
   // one byte beyond the end of the VMO if desired.  In other words, this can
   // be equal to the VMO's size, to indicate that the last byte of the VMO is
   // usable (and possibly many byte before that, depending on
-  // vmo_offset_begin).
+  // vmo_usable_start).
   uint64 vmo_usable_size;
 };
 
@@ -719,7 +762,7 @@
   // for the life of the Codec.
   //
   // The "max" values for buffer size and count are large enough to support the
-  // most demanding format the server supports on fuchsia.ui.input.  The "recommended"
+  // most demanding format the server supports on input.  The "recommended"
   // values should be workable for use with the input CodecFormatDetails
   // conveyed during Codec creation.  The "recommended" values are not
   // necessarily suitable if the client uses QueueInputFormatDetails() to
diff --git a/public/lib/media/fidl/media_capturer.fidl b/public/lib/media/fidl/media_capturer.fidl
deleted file mode 100644
index b33976a..0000000
--- a/public/lib/media/fidl/media_capturer.fidl
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library media;
-
-// Models a service that captures content.
-interface MediaCapturer {
-  // Gets the list of supported media types.
-  1: GetSupportedMediaTypes() -> (vector<MediaTypeSet> supported_media_types);
-
-  // Sets the media type of the stream to be delivered.
-  2: SetMediaType(MediaType media_type);
-
-  // Gets the packet producer for the stream to be delivered.
-  3: GetPacketProducer(request<MediaPacketProducer> packet_producer);
-
-  // Starts capture.
-  4: Start();
-
-  // Stops capture.
-  5: Stop();
-
-  // A no-op call which immediately calls the user's supplied callback.  May be
-  // used to synchronize with other operations which are in flight on the
-  // channel.
-  6: Synchronize() -> ();
-};
diff --git a/public/lib/media/fidl/media_metadata.fidl b/public/lib/media/fidl/media_metadata.fidl
index 2842cc2..a70ec9f 100644
--- a/public/lib/media/fidl/media_metadata.fidl
+++ b/public/lib/media/fidl/media_metadata.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media_player;
+library fuchsia.mediaplayer;
 
 // Describes media.
 struct MediaMetadata {
diff --git a/public/lib/media/fidl/media_player.fidl b/public/lib/media/fidl/media_player.fidl
index a28fa38..8063e0b 100644
--- a/public/lib/media/fidl/media_player.fidl
+++ b/public/lib/media/fidl/media_player.fidl
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media_player;
+library fuchsia.mediaplayer;
 
 using fuchsia.math;
-using media;
+using fuchsia.media;
 using fuchsia.ui.views_v1_token;
 
 // Plays media.
@@ -41,7 +41,7 @@
   // Sets the audio renderer to use. The audio renderer can only be set on a
   // new player for which none of the SetXxxSource methods or SetAudioRenderer
   // itself have been called. This method is ignored otherwise.
-  9: SetAudioRenderer(media.AudioRenderer2? audio_renderer);
+  9: SetAudioRenderer(fuchsia.media.AudioRenderer2? audio_renderer);
 
   // Adds a new binding to this MediaPlayer.
   10: AddBinding(request<MediaPlayer> media_player);
@@ -55,7 +55,7 @@
 struct MediaPlayerStatus {
   // Transform translating local time to presentation time. Reverse translation
   // (presentation time to local time) is only valid when media is playing.
-  media.TimelineTransform? timeline_transform;
+  fuchsia.media.TimelineTransform? timeline_transform;
 
   // Indicates whether presentation has reached end-of-stream.
   bool end_of_stream;
diff --git a/public/lib/media/fidl/media_renderer.fidl b/public/lib/media/fidl/media_renderer.fidl
index 304913c..7096cc7 100644
--- a/public/lib/media/fidl/media_renderer.fidl
+++ b/public/lib/media/fidl/media_renderer.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 // Models a service that renders content.
 interface MediaRenderer {
diff --git a/public/lib/media/fidl/media_result.fidl b/public/lib/media/fidl/media_result.fidl
index 787d5eb..b55033b 100644
--- a/public/lib/media/fidl/media_result.fidl
+++ b/public/lib/media/fidl/media_result.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 enum MediaResult : int32 {
   OK                     = 0;
diff --git a/public/lib/media/fidl/media_source.fidl b/public/lib/media/fidl/media_source.fidl
deleted file mode 100644
index ac4befc..0000000
--- a/public/lib/media/fidl/media_source.fidl
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library media_player;
-
-using media;
-
-// Produces media streams delivered from a specified origin.
-interface MediaSource {
-  // Describes the source.
-  1: Describe() -> (vector<media.MediaType> stream_types);
-
-  // Gets the packet producer for the specified stream.
-  2: GetPacketProducer(uint32 stream_index, request<media.MediaPacketProducer> packet_producer);
-
-  // Gets the status. To get the status immediately, call
-  // GetStatus(kInitialStatus). To get updates thereafter, pass the version
-  // sent in the previous callback.
-  3: GetStatus(uint64 version_last_seen)
-      -> (uint64 version, MediaSourceStatus @status);
-
-  // Flushes the source and downstream components. |hold_frame| indicates
-  // whether a video renderer (if any) should continue to display the last
-  // displayed frame.
-  4: Flush(bool hold_frame) -> ();
-
-  // Seeks to the specified position, specified in nanoseconds.
-  5: Seek(int64 position) -> ();
-};
-
-// Describes the status of the media source.
-struct MediaSourceStatus {
-  // Indicates whether an audio stream producer is currently connected. This
-  // value will be false if the content contains no audio or if no audio stream
-  // producer is connected (possibly because the audio stream media type isn't
-  // supported).
-  bool audio_connected;
-
-  // Indicates whether a video stream producer is currently connected. This
-  // value will be false if the content contains no video or if no video stream
-  // producer is connected (possibly because the video stream media type isn't
-  // supported).
-  bool video_connected;
-
-  // Describes the media.
-  MediaMetadata? metadata;
-
-  // Indicates a problem preventing intended operation.
-  Problem? problem;
-};
diff --git a/public/lib/media/fidl/media_transport.fidl b/public/lib/media/fidl/media_transport.fidl
index 8664fe9..d53adda 100644
--- a/public/lib/media/fidl/media_transport.fidl
+++ b/public/lib/media/fidl/media_transport.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 // A special value which may be written into the PTS field in certain
 // circumstances.  For example, depending on the specific scenario,
diff --git a/public/lib/media/fidl/media_types.fidl b/public/lib/media/fidl/media_types.fidl
index 4a25728..7fd9c34 100644
--- a/public/lib/media/fidl/media_types.fidl
+++ b/public/lib/media/fidl/media_types.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 const string kMediaEncodingUnsupported = "unsupported";
 
diff --git a/public/lib/media/fidl/net_media_service.fidl b/public/lib/media/fidl/net_media_service.fidl
index e8f2060..a624fd1 100644
--- a/public/lib/media/fidl/net_media_service.fidl
+++ b/public/lib/media/fidl/net_media_service.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media_player;
+library fuchsia.mediaplayer;
 
 // Network media service definition.
 [Discoverable]
diff --git a/public/lib/media/fidl/problem.fidl b/public/lib/media/fidl/problem.fidl
index 8fb49ac..561da58 100644
--- a/public/lib/media/fidl/problem.fidl
+++ b/public/lib/media/fidl/problem.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media_player;
+library fuchsia.mediaplayer;
 
 const string kProblemInternal = "ProblemInternal";
 const string kProblemAssetNotFound = "ProblemAssetNotFound";
diff --git a/public/lib/media/fidl/seeking_reader.fidl b/public/lib/media/fidl/seeking_reader.fidl
index d74b71d..b8a2acc 100644
--- a/public/lib/media/fidl/seeking_reader.fidl
+++ b/public/lib/media/fidl/seeking_reader.fidl
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media_player;
+library fuchsia.mediaplayer;
 
-using media;
+using fuchsia.media;
 
 const uint64 kUnknownSize = 0xffffffffffffffff;
 
@@ -16,7 +16,8 @@
   // |NOT_FOUND|     - The content could not be found.
   // |UNKNOWN_ERROR| - Some other error occurred.
   // A |size| value of |kUnknownSize| if the size of the content isn't known.
-  1: Describe() -> (media.MediaResult result, uint64 size, bool can_seek);
+  1: Describe() ->
+      (fuchsia.media.MediaResult result, uint64 size, bool can_seek);
 
   // Reads into a socket starting at a specified position. If the reader
   // can't seek, position must be 0. The |result| callback parameter is |OK|
@@ -24,5 +25,6 @@
   // |NOT_FOUND|        - The content could not be found.
   // |INVALID_ARGUMENT| - The reader can't seek and |position| was non-zero.
   // |UNKNOWN_ERROR|    - Some other error occurred.
-  2: ReadAt(uint64 position) -> (media.MediaResult result, handle<socket>? socket);
+  2: ReadAt(uint64 position) ->
+      (fuchsia.media.MediaResult result, handle<socket>? socket);
 };
diff --git a/public/lib/media/fidl/timeline_controller.fidl b/public/lib/media/fidl/timeline_controller.fidl
index d4a7194..e431296 100644
--- a/public/lib/media/fidl/timeline_controller.fidl
+++ b/public/lib/media/fidl/timeline_controller.fidl
@@ -2,16 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
-
-// Timing controller for a media graph.
-interface MediaTimelineController {
-  // Associates a control point with the controller.
-  1: AddControlPoint(MediaTimelineControlPoint control_point);
-
-  // Gets a timeline control point interface for the controller.
-  2: GetControlPoint(request<MediaTimelineControlPoint> control_point);
-};
+library fuchsia.media;
 
 // Media graph component controlled by a MediaTimelineController.
 interface MediaTimelineControlPoint {
diff --git a/public/lib/media/fidl/timelines.fidl b/public/lib/media/fidl/timelines.fidl
index 50583a3..fafd3c3 100644
--- a/public/lib/media/fidl/timelines.fidl
+++ b/public/lib/media/fidl/timelines.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library media;
+library fuchsia.media;
 
 // Used as a placeholder for unspecified time values.
 const int64 kUnspecifiedTime = 0x7fffffffffffffff;
diff --git a/public/lib/media/timeline/test/timeline_function_test.cc b/public/lib/media/timeline/test/timeline_function_test.cc
index 3b6c899..6a5bc66 100644
--- a/public/lib/media/timeline/test/timeline_function_test.cc
+++ b/public/lib/media/timeline/test/timeline_function_test.cc
@@ -11,10 +11,8 @@
 
 // Verifies that the given TimelineFunction instantiated with the given
 // arguments has the expected properties.
-void VerifyBasics(const TimelineFunction& under_test,
-                  int64_t subject_time,
-                  int64_t reference_time,
-                  uint32_t subject_delta,
+void VerifyBasics(const TimelineFunction& under_test, int64_t subject_time,
+                  int64_t reference_time, uint32_t subject_delta,
                   uint32_t reference_delta) {
   TimelineRate::Reduce(&subject_delta, &reference_delta);
   EXPECT_EQ(reference_time, under_test.reference_time());
@@ -27,10 +25,8 @@
 
 // Verifies that a TimelineFunction instantiated in three different ways with
 // the given arguments has the expected properties.
-void VerifyBasics(int64_t subject_time,
-                  int64_t reference_time,
-                  uint32_t subject_delta,
-                  uint32_t reference_delta) {
+void VerifyBasics(int64_t subject_time, int64_t reference_time,
+                  uint32_t subject_delta, uint32_t reference_delta) {
   TimelineFunction under_test_1(subject_time, reference_time, subject_delta,
                                 reference_delta);
   VerifyBasics(under_test_1, subject_time, reference_time, subject_delta,
@@ -64,10 +60,8 @@
 
 // Verifies that the inverse of a TimelineFunction instantiated in three
 // different ways with the given arguments has the expected properties.
-void VerifyInverse(int64_t subject_time,
-                   int64_t reference_time,
-                   uint32_t subject_delta,
-                   uint32_t reference_delta) {
+void VerifyInverse(int64_t subject_time, int64_t reference_time,
+                   uint32_t subject_delta, uint32_t reference_delta) {
   TimelineFunction under_test_1(subject_time, reference_time, subject_delta,
                                 reference_delta);
   VerifyBasics(under_test_1.Inverse(), reference_time, subject_time,
@@ -84,12 +78,9 @@
 
 // Verifies that TimelineFunction::Apply, in its various forms, works as
 // expected for the given arguments.
-void VerifyApply(int64_t subject_time,
-                 int64_t reference_time,
-                 uint32_t subject_delta,
-                 uint32_t reference_delta,
-                 int64_t reference_input,
-                 int64_t expected_result) {
+void VerifyApply(int64_t subject_time, int64_t reference_time,
+                 uint32_t subject_delta, uint32_t reference_delta,
+                 int64_t reference_input, int64_t expected_result) {
   // Verify the static method.
   EXPECT_EQ(expected_result,
             TimelineFunction::Apply(
@@ -107,12 +98,9 @@
 
 // Verifies that TimelineFunction::ApplyInverse, in its various forms, works
 // as expected for the given arguments.
-void VerifyApplyInverse(int64_t subject_time,
-                        int64_t reference_time,
-                        uint32_t subject_delta,
-                        uint32_t reference_delta,
-                        int64_t subject_input,
-                        int64_t expected_result) {
+void VerifyApplyInverse(int64_t subject_time, int64_t reference_time,
+                        uint32_t subject_delta, uint32_t reference_delta,
+                        int64_t subject_input, int64_t expected_result) {
   // Verify the static method.
   EXPECT_EQ(expected_result,
             TimelineFunction::ApplyInverse(
@@ -127,10 +115,8 @@
 
 // Verifies that TimelineFunction::Compose works as expected with the given
 // inputs.
-void VerifyCompose(const TimelineFunction& a,
-                   const TimelineFunction& b,
-                   bool exact,
-                   const TimelineFunction& expected_result) {
+void VerifyCompose(const TimelineFunction& a, const TimelineFunction& b,
+                   bool exact, const TimelineFunction& expected_result) {
   // Verify the static method.
   EXPECT_EQ(expected_result, TimelineFunction::Compose(a, b, exact));
 }
diff --git a/public/lib/media/timeline/test/timeline_rate_test.cc b/public/lib/media/timeline/test/timeline_rate_test.cc
index 3976ac8..69c3316 100644
--- a/public/lib/media/timeline/test/timeline_rate_test.cc
+++ b/public/lib/media/timeline/test/timeline_rate_test.cc
@@ -24,8 +24,7 @@
 // subject_delta * common_factor / reference_delta * common_factor is reduced
 // to subject_delta / reference_delta. subject_delta and reference_delta need
 // to be relatively prime for this to work.
-void VerifyReduce(uint32_t subject_delta,
-                  uint32_t reference_delta,
+void VerifyReduce(uint32_t subject_delta, uint32_t reference_delta,
                   uint32_t common_factor) {
   // Make sure subject_delta and reference_delta are relatively prime.
   EXPECT_EQ(1u, gcd(subject_delta, reference_delta));
@@ -47,10 +46,8 @@
 // Verifies the TimelineRate::Scale methods by scaling value by subject_delta
 // /
 // reference_delta and verifying the result.
-void VerifyScale(int64_t value,
-                 uint32_t subject_delta,
-                 uint32_t reference_delta,
-                 int64_t result) {
+void VerifyScale(int64_t value, uint32_t subject_delta,
+                 uint32_t reference_delta, int64_t result) {
   // Test the instance method.
   EXPECT_EQ(result, TimelineRate(subject_delta, reference_delta).Scale(value));
 
@@ -67,13 +64,10 @@
 
 // Verifies the TimelineRate::Product methods by multiplying the given a and b
 // rates and checking the result against the expected rate.
-void VerifyProduct(uint32_t a_subject_delta,
-                   uint32_t a_reference_delta,
-                   uint32_t b_subject_delta,
-                   uint32_t b_reference_delta,
+void VerifyProduct(uint32_t a_subject_delta, uint32_t a_reference_delta,
+                   uint32_t b_subject_delta, uint32_t b_reference_delta,
                    uint32_t expected_subject_delta,
-                   uint32_t expected_reference_delta,
-                   bool exact) {
+                   uint32_t expected_reference_delta, bool exact) {
   // Test the first static method.
   uint32_t actual_subject_delta;
   uint32_t actual_reference_delta;
diff --git a/public/lib/media/timeline/timeline.h b/public/lib/media/timeline/timeline.h
index dc6e332..54ab0f6 100644
--- a/public/lib/media/timeline/timeline.h
+++ b/public/lib/media/timeline/timeline.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TIMELINE_TIMELINE_H_
+#define LIB_MEDIA_TIMELINE_TIMELINE_H_
 
 #include "lib/fxl/time/time_delta.h"
 #include "lib/fxl/time/time_point.h"
@@ -54,3 +55,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TIMELINE_TIMELINE_H_
diff --git a/public/lib/media/timeline/timeline_function.cc b/public/lib/media/timeline/timeline_function.cc
index 20752dd..449d708 100644
--- a/public/lib/media/timeline/timeline_function.cc
+++ b/public/lib/media/timeline/timeline_function.cc
@@ -13,8 +13,7 @@
 
 // static
 int64_t TimelineFunction::Apply(
-    int64_t subject_time,
-    int64_t reference_time,
+    int64_t subject_time, int64_t reference_time,
     TimelineRate rate,  // subject_delta / reference_delta
     int64_t reference_input) {
   return rate.Scale(reference_input - reference_time) + subject_time;
@@ -33,13 +32,15 @@
                           TimelineRate::Product(ab.rate(), bc.rate(), exact));
 }
 
-TimelineFunction::TimelineFunction(const TimelineTransform& from)
+TimelineFunction::TimelineFunction(
+    const fuchsia::media::TimelineTransform& from)
     : subject_time_(from.subject_time),
       reference_time_(from.reference_time),
       rate_(TimelineRate(from.subject_delta, from.reference_delta)) {}
 
-TimelineTransform TimelineFunction::ToTimelineTransform() const {
-  TimelineTransform result;
+fuchsia::media::TimelineTransform TimelineFunction::ToTimelineTransform()
+    const {
+  fuchsia::media::TimelineTransform result;
   result.subject_time = subject_time();
   result.reference_time = reference_time();
   result.subject_delta = subject_delta();
diff --git a/public/lib/media/timeline/timeline_function.h b/public/lib/media/timeline/timeline_function.h
index 58c3b3a..f92ed0e 100644
--- a/public/lib/media/timeline/timeline_function.h
+++ b/public/lib/media/timeline/timeline_function.h
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TIMELINE_TIMELINE_FUNCTION_H_
+#define LIB_MEDIA_TIMELINE_TIMELINE_FUNCTION_H_
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 #include "lib/fxl/logging.h"
 #include "lib/media/timeline/timeline_rate.h"
 
@@ -22,15 +23,13 @@
 class TimelineFunction {
  public:
   // Applies a timeline function.
-  static int64_t Apply(int64_t subject_time,
-                       int64_t reference_time,
+  static int64_t Apply(int64_t subject_time, int64_t reference_time,
                        TimelineRate rate,  // subject_delta / reference_delta
                        int64_t reference_input);
 
   // Applies the inverse of a timeline function.
   static int64_t ApplyInverse(
-      int64_t subject_time,
-      int64_t reference_time,
+      int64_t subject_time, int64_t reference_time,
       TimelineRate rate,  // subject_delta / reference_delta
       int64_t subject_input) {
     FXL_DCHECK(rate.reference_delta() != 0u);
@@ -45,16 +44,13 @@
 
   TimelineFunction() : subject_time_(0), reference_time_(0) {}
 
-  TimelineFunction(int64_t subject_time,
-                   int64_t reference_time,
-                   uint32_t subject_delta,
-                   uint32_t reference_delta)
+  TimelineFunction(int64_t subject_time, int64_t reference_time,
+                   uint32_t subject_delta, uint32_t reference_delta)
       : subject_time_(subject_time),
         reference_time_(reference_time),
         rate_(subject_delta, reference_delta) {}
 
-  TimelineFunction(int64_t subject_time,
-                   int64_t reference_time,
+  TimelineFunction(int64_t subject_time, int64_t reference_time,
                    TimelineRate rate)
       : subject_time_(subject_time),
         reference_time_(reference_time),
@@ -63,9 +59,9 @@
   explicit TimelineFunction(TimelineRate rate)
       : subject_time_(0), reference_time_(0), rate_(rate) {}
 
-  explicit TimelineFunction(const TimelineTransform& from);
+  explicit TimelineFunction(const fuchsia::media::TimelineTransform& from);
 
-  TimelineTransform ToTimelineTransform() const;
+  fuchsia::media::TimelineTransform ToTimelineTransform() const;
 
   // Determines whether this |TimelineFunction| is invertable.
   bool invertable() const { return rate_.invertable(); }
@@ -130,3 +126,5 @@
 }
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TIMELINE_TIMELINE_FUNCTION_H_
diff --git a/public/lib/media/timeline/timeline_rate.cc b/public/lib/media/timeline/timeline_rate.cc
index 776e310..0e2523e 100644
--- a/public/lib/media/timeline/timeline_rate.cc
+++ b/public/lib/media/timeline/timeline_rate.cc
@@ -84,11 +84,8 @@
 // Scales a uint64_t value by the ratio of two uint32_t values. If round_up is
 // true, the result is rounded up rather than down. overflow is set to indicate
 // overflow.
-uint64_t ScaleUInt64(uint64_t value,
-                     uint32_t subject_delta,
-                     uint32_t reference_delta,
-                     bool round_up,
-                     bool* overflow) {
+uint64_t ScaleUInt64(uint64_t value, uint32_t subject_delta,
+                     uint32_t reference_delta, bool round_up, bool* overflow) {
   FXL_DCHECK(reference_delta != 0u);
   FXL_DCHECK(overflow != nullptr);
 
@@ -153,13 +150,10 @@
 }
 
 // static
-void TimelineRate::Product(uint32_t a_subject_delta,
-                           uint32_t a_reference_delta,
-                           uint32_t b_subject_delta,
-                           uint32_t b_reference_delta,
+void TimelineRate::Product(uint32_t a_subject_delta, uint32_t a_reference_delta,
+                           uint32_t b_subject_delta, uint32_t b_reference_delta,
                            uint32_t* product_subject_delta,
-                           uint32_t* product_reference_delta,
-                           bool exact) {
+                           uint32_t* product_reference_delta, bool exact) {
   FXL_DCHECK(a_reference_delta != 0);
   FXL_DCHECK(b_reference_delta != 0);
   FXL_DCHECK(product_subject_delta != nullptr);
@@ -197,8 +191,7 @@
 }
 
 // static
-int64_t TimelineRate::Scale(int64_t value,
-                            uint32_t subject_delta,
+int64_t TimelineRate::Scale(int64_t value, uint32_t subject_delta,
                             uint32_t reference_delta) {
   static constexpr uint64_t abs_of_min_int64 =
       static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1;
diff --git a/public/lib/media/timeline/timeline_rate.h b/public/lib/media/timeline/timeline_rate.h
index 80a424d..c7350af 100644
--- a/public/lib/media/timeline/timeline_rate.h
+++ b/public/lib/media/timeline/timeline_rate.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TIMELINE_TIMELINE_RATE_H_
+#define LIB_MEDIA_TIMELINE_TIMELINE_RATE_H_
 
 #include <stdint.h>
 
@@ -34,24 +35,19 @@
 
   // Produces the product of the rates. If exact is true, DCHECKs on loss of
   // precision.
-  static void Product(uint32_t a_subject_delta,
-                      uint32_t a_reference_delta,
-                      uint32_t b_subject_delta,
-                      uint32_t b_reference_delta,
+  static void Product(uint32_t a_subject_delta, uint32_t a_reference_delta,
+                      uint32_t b_subject_delta, uint32_t b_reference_delta,
                       uint32_t* product_subject_delta,
-                      uint32_t* product_reference_delta,
-                      bool exact = true);
+                      uint32_t* product_reference_delta, bool exact = true);
 
   // Produces the product of the rates and the int64_t as an int64_t. Returns
   // kOverflow on overflow.
-  static int64_t Scale(int64_t value,
-                       uint32_t subject_delta,
+  static int64_t Scale(int64_t value, uint32_t subject_delta,
                        uint32_t reference_delta);
 
   // Returns the product of the rates. If exact is true, DCHECKs on loss of
   // precision.
-  static TimelineRate Product(TimelineRate a,
-                              TimelineRate b,
+  static TimelineRate Product(TimelineRate a, TimelineRate b,
                               bool exact = true) {
     uint32_t result_subject_delta;
     uint32_t result_reference_delta;
@@ -133,9 +129,7 @@
 }
 
 // Tests two rates for inequality.
-inline bool operator!=(TimelineRate a, TimelineRate b) {
-  return !(a == b);
-}
+inline bool operator!=(TimelineRate a, TimelineRate b) { return !(a == b); }
 
 // Returns the ratio of the two rates. DCHECKs on loss of precision.
 inline TimelineRate operator/(TimelineRate a, TimelineRate b) {
@@ -149,15 +143,11 @@
 
 // Returns the product of the rate and the int64_t. Returns kOverflow on
 // overflow.
-inline int64_t operator*(TimelineRate a, int64_t b) {
-  return a.Scale(b);
-}
+inline int64_t operator*(TimelineRate a, int64_t b) { return a.Scale(b); }
 
 // Returns the product of the rate and the int64_t. Returns kOverflow on
 // overflow.
-inline int64_t operator*(int64_t a, TimelineRate b) {
-  return b.Scale(a);
-}
+inline int64_t operator*(int64_t a, TimelineRate b) { return b.Scale(a); }
 
 // Returns the the int64_t divided by the rate. Returns kOverflow on
 // overflow.
@@ -166,3 +156,5 @@
 }
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TIMELINE_TIMELINE_RATE_H_
diff --git a/public/lib/media/transport/BUILD.gn b/public/lib/media/transport/BUILD.gn
index ffa3b23..af3c4cb 100644
--- a/public/lib/media/transport/BUILD.gn
+++ b/public/lib/media/transport/BUILD.gn
@@ -22,6 +22,7 @@
 
   public_deps = [
     "//garnet/public/lib/app/cpp",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/public/lib/media/transport/fifo_allocator.cc b/public/lib/media/transport/fifo_allocator.cc
index d1e058d..90c3e77 100644
--- a/public/lib/media/transport/fifo_allocator.cc
+++ b/public/lib/media/transport/fifo_allocator.cc
@@ -186,8 +186,7 @@
   }
 }
 
-FifoAllocator::Region* FifoAllocator::get_free(bool allocated,
-                                               uint64_t size,
+FifoAllocator::Region* FifoAllocator::get_free(bool allocated, uint64_t size,
                                                uint64_t offset) {
   FXL_DCHECK(size <= size_);
   FXL_DCHECK(offset <= size_ - size);
diff --git a/public/lib/media/transport/fifo_allocator.h b/public/lib/media/transport/fifo_allocator.h
index 9ea0dea..9256f5d 100644
--- a/public/lib/media/transport/fifo_allocator.h
+++ b/public/lib/media/transport/fifo_allocator.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TRANSPORT_FIFO_ALLOCATOR_H_
+#define LIB_MEDIA_TRANSPORT_FIFO_ALLOCATOR_H_
 
 #include <cstdint>
 #include <limits>
@@ -141,3 +142,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TRANSPORT_FIFO_ALLOCATOR_H_
diff --git a/public/lib/media/transport/mapped_shared_buffer.cc b/public/lib/media/transport/mapped_shared_buffer.cc
index 41996a9..5bf4d4a 100644
--- a/public/lib/media/transport/mapped_shared_buffer.cc
+++ b/public/lib/media/transport/mapped_shared_buffer.cc
@@ -4,11 +4,11 @@
 
 #include "lib/media/transport/mapped_shared_buffer.h"
 
+#include <fuchsia/media/cpp/fidl.h>
 #include <lib/zx/vmar.h>
 #include <lib/zx/vmo.h>
 #include <zircon/types.h>
 
-#include <media/cpp/fidl.h>
 #include "lib/fxl/logging.h"
 #include "lib/media/transport/fifo_allocator.h"
 
@@ -16,9 +16,7 @@
 
 MappedSharedBuffer::MappedSharedBuffer() {}
 
-MappedSharedBuffer::~MappedSharedBuffer() {
-  Reset();
-}
+MappedSharedBuffer::~MappedSharedBuffer() { Reset(); }
 
 zx_status_t MappedSharedBuffer::InitNew(uint64_t size, uint32_t map_flags) {
   FXL_DCHECK(size > 0);
@@ -55,7 +53,7 @@
     return status;
   }
 
-  if (size == 0 || size > kMaxBufferLen) {
+  if (size == 0 || size > fuchsia::media::kMaxBufferLen) {
     FXL_LOG(ERROR) << "zx::vmo::get_size returned invalid size " << size;
     return ZX_ERR_OUT_OF_RANGE;
   }
@@ -80,9 +78,7 @@
   return ZX_OK;
 }
 
-bool MappedSharedBuffer::initialized() const {
-  return buffer_ptr_ != nullptr;
-}
+bool MappedSharedBuffer::initialized() const { return buffer_ptr_ != nullptr; }
 
 void MappedSharedBuffer::Reset() {
   if (buffer_ptr_ != nullptr) {
@@ -97,9 +93,7 @@
   vmo_.reset();
 }
 
-uint64_t MappedSharedBuffer::size() const {
-  return size_;
-}
+uint64_t MappedSharedBuffer::size() const { return size_; }
 
 zx::vmo MappedSharedBuffer::GetDuplicateVmo(zx_rights_t rights) const {
   FXL_DCHECK(initialized());
diff --git a/public/lib/media/transport/mapped_shared_buffer.h b/public/lib/media/transport/mapped_shared_buffer.h
index 1e13786..fa40e4e 100644
--- a/public/lib/media/transport/mapped_shared_buffer.h
+++ b/public/lib/media/transport/mapped_shared_buffer.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TRANSPORT_MAPPED_SHARED_BUFFER_H_
+#define LIB_MEDIA_TRANSPORT_MAPPED_SHARED_BUFFER_H_
 
 #include <memory>
 
@@ -74,3 +75,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TRANSPORT_MAPPED_SHARED_BUFFER_H_
diff --git a/public/lib/media/transport/media_packet_consumer_base.cc b/public/lib/media/transport/media_packet_consumer_base.cc
index db81472..ef11fe7 100644
--- a/public/lib/media/transport/media_packet_consumer_base.cc
+++ b/public/lib/media/transport/media_packet_consumer_base.cc
@@ -41,7 +41,7 @@
 }
 
 void MediaPacketConsumerBase::Bind(
-    fidl::InterfaceRequest<MediaPacketConsumer> request) {
+    fidl::InterfaceRequest<fuchsia::media::MediaPacketConsumer> request) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
   binding_.Bind(std::move(request));
   binding_.set_error_handler([this]() { Reset(); });
@@ -49,7 +49,7 @@
 }
 
 void MediaPacketConsumerBase::Bind(
-    fidl::InterfaceHandle<MediaPacketConsumer>* handle) {
+    fidl::InterfaceHandle<fuchsia::media::MediaPacketConsumer>* handle) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
   binding_.Bind(handle->NewRequest());
   binding_.set_error_handler([this]() { Reset(); });
@@ -94,7 +94,7 @@
   }
 
   demand_.min_packets_outstanding = 0;
-  demand_.min_pts = kNoTimestamp;
+  demand_.min_pts = fuchsia::media::kNoTimestamp;
 
   get_demand_update_callback_ = nullptr;
 
@@ -141,7 +141,8 @@
     // that the client doesn't know what it's doing.
     FXL_DLOG(WARNING) << "PullDemandUpdate was called when another "
                          "PullDemandUpdate call was pending";
-    get_demand_update_callback_(std::make_unique<MediaPacketDemand>(demand_));
+    get_demand_update_callback_(
+        std::make_unique<fuchsia::media::MediaPacketDemand>(demand_));
   }
 
   get_demand_update_callback_ = callback;
@@ -163,8 +164,8 @@
   counter_->buffer_set().RemoveBuffer(payload_buffer_id);
 }
 
-void MediaPacketConsumerBase::SupplyPacket(MediaPacket media_packet,
-                                           SupplyPacketCallback callback) {
+void MediaPacketConsumerBase::SupplyPacket(
+    fuchsia::media::MediaPacket media_packet, SupplyPacketCallback callback) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
 
   if (media_packet.revised_media_type && !accept_revised_media_type_) {
@@ -195,7 +196,8 @@
       label, std::move(media_packet), payload, callback, counter_)));
 }
 
-void MediaPacketConsumerBase::SupplyPacketNoReply(MediaPacket media_packet) {
+void MediaPacketConsumerBase::SupplyPacketNoReply(
+    fuchsia::media::MediaPacket media_packet) {
   SupplyPacket(std::move(media_packet), SupplyPacketCallback());
 }
 
@@ -203,7 +205,7 @@
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
 
   demand_.min_packets_outstanding = 0;
-  demand_.min_pts = kNoTimestamp;
+  demand_.min_pts = fuchsia::media::kNoTimestamp;
 
   flush_pending_ = true;
 
@@ -224,12 +226,13 @@
   }
 
   demand_update_required_ = false;
-  get_demand_update_callback_(std::make_unique<MediaPacketDemand>(demand_));
+  get_demand_update_callback_(
+      std::make_unique<fuchsia::media::MediaPacketDemand>(demand_));
   get_demand_update_callback_ = nullptr;
 }
 
-MediaPacketDemandPtr MediaPacketConsumerBase::GetDemandForPacketDeparture(
-    uint64_t label) {
+fuchsia::media::MediaPacketDemandPtr
+MediaPacketConsumerBase::GetDemandForPacketDeparture(uint64_t label) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
 
   // Note that we're returning a packet so that MaybeCompletePullDemandUpdate
@@ -244,10 +247,11 @@
   }
 
   demand_update_required_ = false;
-  return std::make_unique<MediaPacketDemand>(demand_);
+  return std::make_unique<fuchsia::media::MediaPacketDemand>(demand_);
 }
 
-void MediaPacketConsumerBase::SetPacketPtsRate(MediaPacket* packet) {
+void MediaPacketConsumerBase::SetPacketPtsRate(
+    fuchsia::media::MediaPacket* packet) {
   if (pts_rate_ == TimelineRate::Zero) {
     return;
   }
@@ -268,9 +272,7 @@
 }
 
 MediaPacketConsumerBase::SuppliedPacket::SuppliedPacket(
-    uint64_t label,
-    MediaPacket packet,
-    void* payload,
+    uint64_t label, fuchsia::media::MediaPacket packet, void* payload,
     SupplyPacketCallback callback,
     std::shared_ptr<SuppliedPacketCounter> counter)
     : label_(label),
diff --git a/public/lib/media/transport/media_packet_consumer_base.h b/public/lib/media/transport/media_packet_consumer_base.h
index 07e5834..913d442 100644
--- a/public/lib/media/transport/media_packet_consumer_base.h
+++ b/public/lib/media/transport/media_packet_consumer_base.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TRANSPORT_MEDIA_PACKET_CONSUMER_BASE_H_
+#define LIB_MEDIA_TRANSPORT_MEDIA_PACKET_CONSUMER_BASE_H_
 
 #include <atomic>
 
-#include <media/cpp/fidl.h>
+#include <fuchsia/media/cpp/fidl.h>
 
 #include "lib/fidl/cpp/binding.h"
 #include "lib/fxl/logging.h"
@@ -17,7 +18,7 @@
 namespace media {
 
 // Base class that implements MediaPacketConsumer.
-class MediaPacketConsumerBase : public MediaPacketConsumer {
+class MediaPacketConsumerBase : public fuchsia::media::MediaPacketConsumer {
  private:
   class SuppliedPacketCounter;
 
@@ -33,20 +34,18 @@
    public:
     ~SuppliedPacket();
 
-    const MediaPacket& packet() { return packet_; }
+    const fuchsia::media::MediaPacket& packet() { return packet_; }
     void* payload() { return payload_; }
     uint64_t payload_size() { return packet_.payload_size; }
     uint64_t label() { return label_; }
 
    private:
-    SuppliedPacket(uint64_t label,
-                   MediaPacket packet,
-                   void* payload,
-                   SupplyPacketCallback callback,
+    SuppliedPacket(uint64_t label, fuchsia::media::MediaPacket packet,
+                   void* payload, SupplyPacketCallback callback,
                    std::shared_ptr<SuppliedPacketCounter> counter);
 
     uint64_t label_;
-    MediaPacket packet_;
+    fuchsia::media::MediaPacket packet_;
     void* payload_;
     SupplyPacketCallback callback_;
     std::shared_ptr<SuppliedPacketCounter> counter_;
@@ -58,10 +57,11 @@
   };
 
   // Binds to this MediaPacketConsumer.
-  void Bind(fidl::InterfaceRequest<MediaPacketConsumer> request);
+  void Bind(
+      fidl::InterfaceRequest<fuchsia::media::MediaPacketConsumer> request);
 
   // Binds to this MediaPacketConsumer.
-  void Bind(fidl::InterfaceHandle<MediaPacketConsumer>* handle);
+  void Bind(fidl::InterfaceHandle<fuchsia::media::MediaPacketConsumer>* handle);
 
   // Determines if the consumer is bound to a channel.
   bool is_bound();
@@ -74,12 +74,12 @@
   // Indicates that revised media type is to be accepted.
   void AcceptRevisedMediaType() { accept_revised_media_type_ = true; }
 
-  const MediaPacketDemand& current_demand() { return demand_; }
+  const fuchsia::media::MediaPacketDemand& current_demand() { return demand_; }
 
   // Sets the demand, which is communicated back to the producer at the first
   // opportunity (in response to PullDemandUpdate or SupplyPacket).
   void SetDemand(uint32_t min_packets_outstanding,
-                 int64_t min_pts = kNoTimestamp);
+                 int64_t min_pts = fuchsia::media::kNoTimestamp);
 
   // Shuts down the consumer.
   void Reset();
@@ -122,9 +122,10 @@
 
   void RemovePayloadBuffer(uint32_t payload_buffer_id) final;
 
-  void SupplyPacket(MediaPacket packet, SupplyPacketCallback callback) final;
+  void SupplyPacket(fuchsia::media::MediaPacket packet,
+                    SupplyPacketCallback callback) final;
 
-  void SupplyPacketNoReply(MediaPacket packet) final;
+  void SupplyPacketNoReply(fuchsia::media::MediaPacket packet) final;
 
   void Flush(bool hold_frame, FlushCallback callback) final;
 
@@ -155,7 +156,7 @@
 
     // Records the departure of a packet and returns the current demand update,
     // if any.
-    MediaPacketDemandPtr OnPacketDeparture(uint64_t label) {
+    fuchsia::media::MediaPacketDemandPtr OnPacketDeparture(uint64_t label) {
       FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
       --packets_outstanding_;
       return (owner_ == nullptr) ? nullptr
@@ -183,15 +184,16 @@
 
   // Returns the demand update, if any, to be included in a SupplyPacket
   // callback.
-  MediaPacketDemandPtr GetDemandForPacketDeparture(uint64_t label);
+  fuchsia::media::MediaPacketDemandPtr GetDemandForPacketDeparture(
+      uint64_t label);
 
   // Sets the PTS rate of the packet to pts_rate_ unless pts_rate_ is zero.
   // Does nothing if pts_rate_ is zero.
-  void SetPacketPtsRate(MediaPacket* packet);
+  void SetPacketPtsRate(fuchsia::media::MediaPacket* packet);
 
-  fidl::Binding<MediaPacketConsumer> binding_;
+  fidl::Binding<fuchsia::media::MediaPacketConsumer> binding_;
   bool accept_revised_media_type_ = false;
-  MediaPacketDemand demand_;
+  fuchsia::media::MediaPacketDemand demand_;
   bool demand_update_required_ = false;
   bool returning_packet_ = false;
   PullDemandUpdateCallback get_demand_update_callback_;
@@ -205,3 +207,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TRANSPORT_MEDIA_PACKET_CONSUMER_BASE_H_
diff --git a/public/lib/media/transport/media_packet_producer_base.cc b/public/lib/media/transport/media_packet_producer_base.cc
index bba33ab..52bf29d 100644
--- a/public/lib/media/transport/media_packet_producer_base.cc
+++ b/public/lib/media/transport/media_packet_producer_base.cc
@@ -4,6 +4,7 @@
 
 #include "lib/media/transport/media_packet_producer_base.h"
 
+#include "lib/fxl/functional/make_copyable.h"
 #include "lib/fxl/logging.h"
 
 namespace media {
@@ -27,8 +28,8 @@
 }
 
 void MediaPacketProducerBase::Connect(
-    MediaPacketConsumerPtr consumer,
-    const MediaPacketProducer::ConnectCallback& callback) {
+    fuchsia::media::MediaPacketConsumerPtr consumer,
+    const fuchsia::media::MediaPacketProducer::ConnectCallback& callback) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
   FXL_DCHECK(consumer);
 
@@ -57,7 +58,7 @@
 
 void MediaPacketProducerBase::FlushConsumer(
     bool hold_frame,
-    const MediaPacketConsumer::FlushCallback& callback) {
+    const fuchsia::media::MediaPacketConsumer::FlushCallback& callback) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
   FXL_DCHECK(consumer_.is_bound());
 
@@ -66,9 +67,9 @@
     end_of_stream_ = false;
   }
 
-  MediaPacketDemand demand;
+  fuchsia::media::MediaPacketDemand demand;
   demand.min_packets_outstanding = 0;
-  demand.min_pts = kNoTimestamp;
+  demand.min_pts = fuchsia::media::kNoTimestamp;
   UpdateDemand(demand);
 
   flush_in_progress_ = true;
@@ -87,14 +88,10 @@
 }
 
 void MediaPacketProducerBase::ProducePacket(
-    void* payload,
-    size_t size,
-    int64_t pts,
-    TimelineRate pts_rate,
-    bool keyframe,
-    bool end_of_stream,
-    MediaTypePtr revised_media_type,
-    const ProducePacketCallback& callback) {
+    void* payload, size_t size, int64_t pts, TimelineRate pts_rate,
+    bool keyframe, bool end_of_stream,
+    fuchsia::media::MediaTypePtr revised_media_type,
+    ProducePacketCallback callback) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
   FXL_DCHECK(size == 0 || payload != nullptr);
 
@@ -105,12 +102,12 @@
 
   SharedBufferSet::Locator locator = allocator_.LocatorFromPtr(payload);
 
-  MediaPacket media_packet;
+  fuchsia::media::MediaPacket media_packet;
   media_packet.pts = pts;
   media_packet.pts_rate_ticks = pts_rate.subject_delta();
   media_packet.pts_rate_seconds = pts_rate.reference_delta();
-  media_packet.flags =
-      (keyframe ? kFlagKeyframe : 0) | (end_of_stream ? kFlagEos : 0);
+  media_packet.flags = (keyframe ? fuchsia::media::kFlagKeyframe : 0) |
+                       (end_of_stream ? fuchsia::media::kFlagEos : 0);
   media_packet.revised_media_type = std::move(revised_media_type);
   media_packet.payload_buffer_id = locator.buffer_id();
   media_packet.payload_offset = locator.offset();
@@ -135,7 +132,9 @@
   }
 
   consumer_->SupplyPacket(
-      std::move(media_packet), [this, callback](MediaPacketDemandPtr demand) {
+      std::move(media_packet),
+      fxl::MakeCopyable([this, callback = std::move(callback)](
+                            fuchsia::media::MediaPacketDemandPtr demand) {
         FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
 
         {
@@ -148,7 +147,7 @@
         }
 
         callback();
-      });
+      }));
 }
 
 bool MediaPacketProducerBase::ShouldProducePacket(
@@ -167,7 +166,7 @@
   }
 
   // See if a higher PTS is demanded.
-  return demand_.min_pts != kNoTimestamp &&
+  return demand_.min_pts != fuchsia::media::kNoTimestamp &&
          demand_.min_pts > pts_last_produced_;
 }
 
@@ -179,24 +178,27 @@
   std::lock_guard<std::mutex> locker(mutex_);
   packets_outstanding_ = 0;
   demand_.min_packets_outstanding = 0;
-  demand_.min_pts = kNoTimestamp;
+  demand_.min_pts = fuchsia::media::kNoTimestamp;
 }
 
-void MediaPacketProducerBase::HandleDemandUpdate(MediaPacketDemandPtr demand) {
+void MediaPacketProducerBase::HandleDemandUpdate(
+    fuchsia::media::MediaPacketDemandPtr demand) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
   if (demand) {
     UpdateDemand(*demand);
   }
 
   if (consumer_.is_bound()) {
-    consumer_->PullDemandUpdate([this](MediaPacketDemandPtr demand) {
-      FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
-      HandleDemandUpdate(std::move(demand));
-    });
+    consumer_->PullDemandUpdate(
+        [this](fuchsia::media::MediaPacketDemandPtr demand) {
+          FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
+          HandleDemandUpdate(std::move(demand));
+        });
   }
 }
 
-void MediaPacketProducerBase::UpdateDemand(const MediaPacketDemand& demand) {
+void MediaPacketProducerBase::UpdateDemand(
+    const fuchsia::media::MediaPacketDemand& demand) {
   FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
 
   if (flush_in_progress_) {
diff --git a/public/lib/media/transport/media_packet_producer_base.h b/public/lib/media/transport/media_packet_producer_base.h
index 17dd407..8172968 100644
--- a/public/lib/media/transport/media_packet_producer_base.h
+++ b/public/lib/media/transport/media_packet_producer_base.h
@@ -8,9 +8,11 @@
 #include <limits>
 #include <mutex>
 
+#include <fuchsia/media/cpp/fidl.h>
+#include <lib/fit/function.h>
+
 #include "lib/fxl/synchronization/thread_annotations.h"
 #include "lib/fxl/synchronization/thread_checker.h"
-#include <media/cpp/fidl.h>
 #include "lib/media/timeline/timeline_rate.h"
 #include "lib/media/transport/shared_buffer_set_allocator.h"
 
@@ -19,7 +21,7 @@
 // Base class for clients of MediaPacketConsumer.
 class MediaPacketProducerBase {
  public:
-  using ProducePacketCallback = std::function<void()>;
+  using ProducePacketCallback = fit::closure;
 
   MediaPacketProducerBase();
 
@@ -30,8 +32,9 @@
   void SetFixedBufferSize(uint64_t size);
 
   // Connects to the indicated consumer.
-  void Connect(MediaPacketConsumerPtr consumer,
-               const MediaPacketProducer::ConnectCallback& callback);
+  void Connect(
+      fuchsia::media::MediaPacketConsumerPtr consumer,
+      const fuchsia::media::MediaPacketProducer::ConnectCallback& callback);
 
   // Disconnects from the consumer.
   void Disconnect();
@@ -43,8 +46,9 @@
   void Reset();
 
   // Flushes the consumer.
-  void FlushConsumer(bool hold_frame,
-                     const MediaPacketConsumer::FlushCallback& callback);
+  void FlushConsumer(
+      bool hold_frame,
+      const fuchsia::media::MediaPacketConsumer::FlushCallback& callback);
 
   // Allocates a payload buffer of the specified size.
   void* AllocatePayloadBuffer(size_t size);
@@ -53,17 +57,13 @@
   void ReleasePayloadBuffer(void* buffer);
 
   // Produces a packet and supplies it to the consumer.
-  void ProducePacket(void* payload,
-                     size_t size,
-                     int64_t pts,
-                     TimelineRate pts_rate,
-                     bool keyframe,
-                     bool end_of_stream,
-                     MediaTypePtr revised_media_type,
-                     const ProducePacketCallback& callback);
+  void ProducePacket(void* payload, size_t size, int64_t pts,
+                     TimelineRate pts_rate, bool keyframe, bool end_of_stream,
+                     fuchsia::media::MediaTypePtr revised_media_type,
+                     ProducePacketCallback callback);
 
   // Gets the current demand.
-  const MediaPacketDemand& demand() const { return demand_; }
+  const fuchsia::media::MediaPacketDemand& demand() const { return demand_; }
 
   // Determines whether the consumer is currently demanding a packet. The
   // |additional_packets_outstanding| parameter indicates the number of packets
@@ -89,18 +89,19 @@
 
   // Handles a demand update callback or, if called with default parameters,
   // initiates demand update requests.
-  void HandleDemandUpdate(MediaPacketDemandPtr demand = nullptr);
+  void HandleDemandUpdate(
+      fuchsia::media::MediaPacketDemandPtr demand = nullptr);
 
   // Updates demand_ and calls demand_update_callback_ if it's set and demand
   // has changed.
-  void UpdateDemand(const MediaPacketDemand& demand);
+  void UpdateDemand(const fuchsia::media::MediaPacketDemand& demand);
 
   SharedBufferSetAllocator allocator_;
-  MediaPacketConsumerPtr consumer_;
+  fuchsia::media::MediaPacketConsumerPtr consumer_;
   bool flush_in_progress_ = false;
 
   mutable std::mutex mutex_;
-  MediaPacketDemand demand_ FXL_GUARDED_BY(mutex_);
+  fuchsia::media::MediaPacketDemand demand_ FXL_GUARDED_BY(mutex_);
   uint32_t packets_outstanding_ FXL_GUARDED_BY(mutex_);
   int64_t pts_last_produced_ FXL_GUARDED_BY(mutex_) =
       std::numeric_limits<int64_t>::min();
diff --git a/public/lib/media/transport/shared_buffer_set.h b/public/lib/media/transport/shared_buffer_set.h
index e81abe4..93e5ad3 100644
--- a/public/lib/media/transport/shared_buffer_set.h
+++ b/public/lib/media/transport/shared_buffer_set.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TRANSPORT_SHARED_BUFFER_SET_H_
+#define LIB_MEDIA_TRANSPORT_SHARED_BUFFER_SET_H_
 
 #include <limits>
 #include <map>
@@ -68,10 +69,8 @@
   // buffer id assigned to the buffer and a vmo to the buffer via
   // |buffer_id_out| and |out_vmo|. |vmo_rights| specifies the rights for
   // |out_vmo|.
-  zx_status_t CreateNewBuffer(uint64_t size,
-                              uint32_t* buffer_id_out,
-                              zx_rights_t vmo_rights,
-                              zx::vmo* out_vmo);
+  zx_status_t CreateNewBuffer(uint64_t size, uint32_t* buffer_id_out,
+                              zx_rights_t vmo_rights, zx::vmo* out_vmo);
 
   // Removes a buffer.
   void RemoveBuffer(uint32_t buffer_id);
@@ -103,3 +102,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TRANSPORT_SHARED_BUFFER_SET_H_
diff --git a/public/lib/media/transport/shared_buffer_set_allocator.h b/public/lib/media/transport/shared_buffer_set_allocator.h
index a717fdc..e5d22e1 100644
--- a/public/lib/media/transport/shared_buffer_set_allocator.h
+++ b/public/lib/media/transport/shared_buffer_set_allocator.h
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#pragma once
+#ifndef LIB_MEDIA_TRANSPORT_SHARED_BUFFER_SET_ALLOCATOR_H_
+#define LIB_MEDIA_TRANSPORT_SHARED_BUFFER_SET_ALLOCATOR_H_
 
 #include <map>
 #include <memory>
@@ -199,3 +200,5 @@
 };
 
 }  // namespace media
+
+#endif  // LIB_MEDIA_TRANSPORT_SHARED_BUFFER_SET_ALLOCATOR_H_
diff --git a/public/lib/media/transport/test/shared_buffer_set_allocator_test.cc b/public/lib/media/transport/test/shared_buffer_set_allocator_test.cc
index fab32ae..8663a7d 100644
--- a/public/lib/media/transport/test/shared_buffer_set_allocator_test.cc
+++ b/public/lib/media/transport/test/shared_buffer_set_allocator_test.cc
@@ -28,8 +28,7 @@
   EXPECT_FALSE(under_test->PollForBufferUpdate(&buffer_id, &vmo));
 }
 
-void* AllocateRegion(SharedBufferSetAllocator* under_test,
-                     uint64_t size,
+void* AllocateRegion(SharedBufferSetAllocator* under_test, uint64_t size,
                      uint32_t* new_buffer_id_out) {
   // Do an allocation.
   void* region = under_test->AllocateRegion(size);
@@ -46,8 +45,7 @@
   return region;
 }
 
-void* AllocateRegion(SharedBufferSetAllocator* under_test,
-                     uint64_t size,
+void* AllocateRegion(SharedBufferSetAllocator* under_test, uint64_t size,
                      uint32_t expected_existing_buffer) {
   // Do an allocation.
   void* region = under_test->AllocateRegion(size);
diff --git a/public/lib/media/transport/test/shared_buffer_set_test.cc b/public/lib/media/transport/test/shared_buffer_set_test.cc
index 9d80a27..297faeb 100644
--- a/public/lib/media/transport/test/shared_buffer_set_test.cc
+++ b/public/lib/media/transport/test/shared_buffer_set_test.cc
@@ -15,8 +15,7 @@
   uint32_t buffer_id;
   zx::vmo vmo;
   zx_status_t status = under_test->CreateNewBuffer(
-      size, &buffer_id, ZX_RIGHTS_BASIC | ZX_RIGHTS_IO | ZX_RIGHT_MAP,
-      &vmo);
+      size, &buffer_id, ZX_RIGHTS_BASIC | ZX_RIGHTS_IO | ZX_RIGHT_MAP, &vmo);
   EXPECT_EQ(ZX_OK, status);
   return buffer_id;
 }
@@ -29,8 +28,7 @@
   EXPECT_EQ(ZX_OK, status);
 }
 
-void VerifyBuffer(const SharedBufferSet& under_test,
-                  uint32_t buffer_id,
+void VerifyBuffer(const SharedBufferSet& under_test, uint32_t buffer_id,
                   uint64_t size) {
   uint8_t* base = reinterpret_cast<uint8_t*>(
       under_test.PtrFromLocator(SharedBufferSet::Locator(buffer_id, 0)));
diff --git a/public/lib/mem/fidl/BUILD.gn b/public/lib/mem/fidl/BUILD.gn
index 8d49548..0e4c34f 100644
--- a/public/lib/mem/fidl/BUILD.gn
+++ b/public/lib/mem/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.mem"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/http/fidl/BUILD.gn b/public/lib/net/http/fidl/BUILD.gn
similarity index 85%
rename from public/lib/http/fidl/BUILD.gn
rename to public/lib/net/http/fidl/BUILD.gn
index 1220e61..9ec3acc 100644
--- a/public/lib/http/fidl/BUILD.gn
+++ b/public/lib/net/http/fidl/BUILD.gn
@@ -5,7 +5,8 @@
 import("//garnet/public/lib/fidl/build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "network"
+  name = "fuchsia.net.http"
+  cpp_legacy_callbacks = true
 
   sources = [
     "client.fidl",
diff --git a/public/lib/http/fidl/client.fidl b/public/lib/net/http/fidl/client.fidl
similarity index 99%
rename from public/lib/http/fidl/client.fidl
rename to public/lib/net/http/fidl/client.fidl
index 443ec13..429a4d2 100644
--- a/public/lib/http/fidl/client.fidl
+++ b/public/lib/net/http/fidl/client.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library http;
+library fuchsia.net.http;
 
 using fuchsia.mem;
 
diff --git a/public/lib/network/fidl/BUILD.gn b/public/lib/net/oldhttp/fidl/BUILD.gn
similarity index 80%
rename from public/lib/network/fidl/BUILD.gn
rename to public/lib/net/oldhttp/fidl/BUILD.gn
index 66b025b..9f96bf9 100644
--- a/public/lib/network/fidl/BUILD.gn
+++ b/public/lib/net/oldhttp/fidl/BUILD.gn
@@ -5,12 +5,13 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "network"
+  name = "fuchsia.net.oldhttp"
+  cpp_legacy_callbacks = true
 
   sources = [
+    "http_error.fidl",
     "http_header.fidl",
-    "network_error.fidl",
-    "network_service.fidl",
+    "http_service.fidl",
     "url_body.fidl",
     "url_loader.fidl",
     "url_request.fidl",
diff --git a/public/lib/network/fidl/network_error.fidl b/public/lib/net/oldhttp/fidl/http_error.fidl
similarity index 80%
rename from public/lib/network/fidl/network_error.fidl
rename to public/lib/net/oldhttp/fidl/http_error.fidl
index 414d227..db39ed6 100644
--- a/public/lib/network/fidl/network_error.fidl
+++ b/public/lib/net/oldhttp/fidl/http_error.fidl
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library network;
+library fuchsia.net.oldhttp;
 
-struct NetworkError {
+struct HttpError {
   int32 code;
   string? description;
 };
diff --git a/public/lib/network/fidl/http_header.fidl b/public/lib/net/oldhttp/fidl/http_header.fidl
similarity index 88%
rename from public/lib/network/fidl/http_header.fidl
rename to public/lib/net/oldhttp/fidl/http_header.fidl
index b1b949a..5e5f48f 100644
--- a/public/lib/network/fidl/http_header.fidl
+++ b/public/lib/net/oldhttp/fidl/http_header.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library network;
+library fuchsia.net.oldhttp;
 
 struct HttpHeader {
   string name;
diff --git a/public/lib/net/oldhttp/fidl/http_service.fidl b/public/lib/net/oldhttp/fidl/http_service.fidl
new file mode 100644
index 0000000..8e960a7
--- /dev/null
+++ b/public/lib/net/oldhttp/fidl/http_service.fidl
@@ -0,0 +1,10 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library fuchsia.net.oldhttp;
+
+[Discoverable]
+interface HttpService {
+  1: CreateURLLoader(request<URLLoader> loader);
+};
diff --git a/public/lib/network/fidl/url_body.fidl b/public/lib/net/oldhttp/fidl/url_body.fidl
similarity index 94%
rename from public/lib/network/fidl/url_body.fidl
rename to public/lib/net/oldhttp/fidl/url_body.fidl
index edd01e9..07bb672 100644
--- a/public/lib/network/fidl/url_body.fidl
+++ b/public/lib/net/oldhttp/fidl/url_body.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library network;
+library fuchsia.net.oldhttp;
 
 using fuchsia.mem;
 
diff --git a/public/lib/network/fidl/url_loader.fidl b/public/lib/net/oldhttp/fidl/url_loader.fidl
similarity index 96%
rename from public/lib/network/fidl/url_loader.fidl
rename to public/lib/net/oldhttp/fidl/url_loader.fidl
index 819f3d9..9d5ac09 100644
--- a/public/lib/network/fidl/url_loader.fidl
+++ b/public/lib/net/oldhttp/fidl/url_loader.fidl
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library network;
+library fuchsia.net.oldhttp;
 
 struct URLLoaderStatus {
   // If the loader has failed due to a network level error, this field will be
   // set.
-  NetworkError? error;
+  HttpError? error;
 
   // Set to true if the URLLoader is still working. Set to false once an error
   // is encountered or the response body is completely copied to the response
diff --git a/public/lib/network/fidl/url_request.fidl b/public/lib/net/oldhttp/fidl/url_request.fidl
similarity index 98%
rename from public/lib/network/fidl/url_request.fidl
rename to public/lib/net/oldhttp/fidl/url_request.fidl
index 1311443..8071f98 100644
--- a/public/lib/network/fidl/url_request.fidl
+++ b/public/lib/net/oldhttp/fidl/url_request.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library network;
+library fuchsia.net.oldhttp;
 
 // Specify the cache behavior of the request.
 enum CacheMode {
diff --git a/public/lib/network/fidl/url_response.fidl b/public/lib/net/oldhttp/fidl/url_response.fidl
similarity index 94%
rename from public/lib/network/fidl/url_response.fidl
rename to public/lib/net/oldhttp/fidl/url_response.fidl
index 9a5c5eb..e8667ca 100644
--- a/public/lib/network/fidl/url_response.fidl
+++ b/public/lib/net/oldhttp/fidl/url_response.fidl
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library network;
+library fuchsia.net.oldhttp;
 
 struct URLResponse {
   // If the response resulted in a network level error, this field will be set.
-  NetworkError? error;
+  HttpError? error;
 
   // The response body.
   URLBody? body;
diff --git a/public/lib/netconnector/cpp/BUILD.gn b/public/lib/netconnector/cpp/BUILD.gn
index befabf7..84dd308 100644
--- a/public/lib/netconnector/cpp/BUILD.gn
+++ b/public/lib/netconnector/cpp/BUILD.gn
@@ -9,12 +9,13 @@
     "net_stub_responder.h",
   ]
 
-  deps = [
+  public_deps = [
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/netconnector/fidl",
     "//garnet/public/lib/svc/cpp",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/zx",
   ]
 
diff --git a/public/lib/netconnector/cpp/message_relay.cc b/public/lib/netconnector/cpp/message_relay.cc
index ff19026..c751474 100644
--- a/public/lib/netconnector/cpp/message_relay.cc
+++ b/public/lib/netconnector/cpp/message_relay.cc
@@ -52,11 +52,10 @@
   OnChannelClosed();
 }
 
-void MessageRelayBase::ReadChannelMessages(
-    async_t* async,
-    async::WaitBase* wait,
-    zx_status_t status,
-    const zx_packet_signal_t* signal) {
+void MessageRelayBase::ReadChannelMessages(async_t* async,
+                                           async::WaitBase* wait,
+                                           zx_status_t status,
+                                           const zx_packet_signal_t* signal) {
   while (channel_) {
     uint32_t actual_byte_count;
     uint32_t actual_handle_count;
@@ -108,11 +107,10 @@
   }
 }
 
-void MessageRelayBase::WriteChannelMessages(
-    async_t* async,
-    async::WaitBase* wait,
-    zx_status_t status,
-    const zx_packet_signal_t* signal) {
+void MessageRelayBase::WriteChannelMessages(async_t* async,
+                                            async::WaitBase* wait,
+                                            zx_status_t status,
+                                            const zx_packet_signal_t* signal) {
   if (!channel_) {
     return;
   }
@@ -153,12 +151,12 @@
 MessageRelay::~MessageRelay() {}
 
 void MessageRelay::SetMessageReceivedCallback(
-    std::function<void(std::vector<uint8_t>)> callback) {
-  message_received_callback_ = callback;
+    fit::function<void(std::vector<uint8_t>)> callback) {
+  message_received_callback_ = std::move(callback);
 }
 
-void MessageRelay::SetChannelClosedCallback(std::function<void()> callback) {
-  channel_closed_callback_ = callback;
+void MessageRelay::SetChannelClosedCallback(fit::closure callback) {
+  channel_closed_callback_ = std::move(callback);
 }
 
 void MessageRelay::OnMessageReceived(std::vector<uint8_t> message) {
diff --git a/public/lib/netconnector/cpp/message_relay.h b/public/lib/netconnector/cpp/message_relay.h
index 436f4a5..94fac3a 100644
--- a/public/lib/netconnector/cpp/message_relay.h
+++ b/public/lib/netconnector/cpp/message_relay.h
@@ -6,6 +6,7 @@
 #define LIB_NETCONNECTOR_CPP_MESSAGE_RELAY_H_
 
 #include <lib/async/cpp/wait.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
 #include <queue>
@@ -44,22 +45,20 @@
 
  private:
   // Tries to read messages from channel_ and waits for more.
-  void ReadChannelMessages(async_t* async,
-                           async::WaitBase* wait,
+  void ReadChannelMessages(async_t* async, async::WaitBase* wait,
                            zx_status_t status,
                            const zx_packet_signal_t* signal);
 
   // Writes all the messages in messages_to_write_.
-  void WriteChannelMessages(async_t* async,
-                            async::WaitBase* wait,
+  void WriteChannelMessages(async_t* async, async::WaitBase* wait,
                             zx_status_t status,
                             const zx_packet_signal_t* signal);
 
   zx::channel channel_;
-  async::WaitMethod<MessageRelayBase,
-                    &MessageRelayBase::ReadChannelMessages> read_wait_{this};
-  async::WaitMethod<MessageRelayBase,
-                    &MessageRelayBase::WriteChannelMessages> write_wait_{this};
+  async::WaitMethod<MessageRelayBase, &MessageRelayBase::ReadChannelMessages>
+      read_wait_{this};
+  async::WaitMethod<MessageRelayBase, &MessageRelayBase::WriteChannelMessages>
+      write_wait_{this};
   std::queue<std::vector<uint8_t>> messages_to_write_;
 };
 
@@ -73,9 +72,9 @@
   ~MessageRelay() override;
 
   void SetMessageReceivedCallback(
-      std::function<void(std::vector<uint8_t>)> callback);
+      fit::function<void(std::vector<uint8_t>)> callback);
 
-  void SetChannelClosedCallback(std::function<void()> callback);
+  void SetChannelClosedCallback(fit::closure callback);
 
  protected:
   void OnMessageReceived(std::vector<uint8_t> message) override;
@@ -83,8 +82,8 @@
   void OnChannelClosed() override;
 
  private:
-  std::function<void(std::vector<uint8_t>)> message_received_callback_;
-  std::function<void()> channel_closed_callback_;
+  fit::function<void(std::vector<uint8_t>)> message_received_callback_;
+  fit::closure channel_closed_callback_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(MessageRelay);
 };
diff --git a/public/lib/netconnector/fidl/BUILD.gn b/public/lib/netconnector/fidl/BUILD.gn
index de19825..41a1078 100644
--- a/public/lib/netconnector/fidl/BUILD.gn
+++ b/public/lib/netconnector/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "netconnector"
+  cpp_legacy_callbacks = true
 
   sources = [
     "netconnector.fidl",
diff --git a/public/lib/netstack/fidl/BUILD.gn b/public/lib/netstack/fidl/BUILD.gn
index 7e8690c..0a3ae35 100644
--- a/public/lib/netstack/fidl/BUILD.gn
+++ b/public/lib/netstack/fidl/BUILD.gn
@@ -5,7 +5,8 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "netstack"
+  name = "fuchsia.netstack"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/netstack/fidl/net_address.fidl b/public/lib/netstack/fidl/net_address.fidl
index 0f9b0ad..8e7a64b 100644
--- a/public/lib/netstack/fidl/net_address.fidl
+++ b/public/lib/netstack/fidl/net_address.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library netstack;
+library fuchsia.netstack;
 
 enum NetAddressFamily {
   UNSPECIFIED = 0;
diff --git a/public/lib/netstack/fidl/netstack.fidl b/public/lib/netstack/fidl/netstack.fidl
index a2f712e..3e8f933 100644
--- a/public/lib/netstack/fidl/netstack.fidl
+++ b/public/lib/netstack/fidl/netstack.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library netstack;
+library fuchsia.netstack;
 
 enum Protocol {
   UNSPECIFIED = 0;
@@ -142,7 +142,7 @@
   // Returns the list of registered network interfaces.
   4: GetInterfaces() -> (vector<NetInterface> interfaces);
 
-  // DEPRECATED: see device_settings.fidl
+  // DEPRECATED: see devicesettings.fidl
   // Returns the netstack's node name.
   // 5: GetNodeName() -> (string node_name);
 
diff --git a/public/lib/network/fidl/network_service.fidl b/public/lib/network/fidl/network_service.fidl
deleted file mode 100644
index 1845003..0000000
--- a/public/lib/network/fidl/network_service.fidl
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library network;
-
-[Discoverable]
-interface NetworkService {
-  1: CreateURLLoader(request<URLLoader> loader);
-
-  // This is not implemented
-  2: GetCookieStore(handle<channel> cookie_store);
-
-  // This is not implemented
-  3: CreateWebSocket(handle<channel> socket);
-};
diff --git a/public/lib/network_wrapper/BUILD.gn b/public/lib/network_wrapper/BUILD.gn
index d78b727..bd8e6b5 100644
--- a/public/lib/network_wrapper/BUILD.gn
+++ b/public/lib/network_wrapper/BUILD.gn
@@ -13,7 +13,7 @@
     "//garnet/public/lib/backoff",
     "//garnet/public/lib/callback",
     "//garnet/public/lib/fxl",
-    "//garnet/public/lib/network/fidl",
+    "//garnet/public/lib/net/oldhttp/fidl",
     "//zircon/public/lib/zx",
   ]
 }
diff --git a/public/lib/network_wrapper/fake_network_wrapper.cc b/public/lib/network_wrapper/fake_network_wrapper.cc
index c8707de..e09bc53 100644
--- a/public/lib/network_wrapper/fake_network_wrapper.cc
+++ b/public/lib/network_wrapper/fake_network_wrapper.cc
@@ -15,24 +15,26 @@
 
 namespace network_wrapper {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 FakeNetworkWrapper::FakeNetworkWrapper(async_t* async) : async_(async) {}
 
 FakeNetworkWrapper::~FakeNetworkWrapper() {}
 
-network::URLRequest* FakeNetworkWrapper::GetRequest() {
+http::URLRequest* FakeNetworkWrapper::GetRequest() {
   return request_received_.get();
 }
 
 void FakeNetworkWrapper::ResetRequest() { request_received_.reset(); }
 
-void FakeNetworkWrapper::SetResponse(network::URLResponse response) {
+void FakeNetworkWrapper::SetResponse(http::URLResponse response) {
   response_to_return_ = fidl::MakeOptional(std::move(response));
 }
 
 void FakeNetworkWrapper::SetSocketResponse(zx::socket body,
                                            uint32_t status_code) {
-  network::URLResponse server_response;
-  server_response.body = network::URLBody::New();
+  http::URLResponse server_response;
+  server_response.body = http::URLBody::New();
   server_response.body->set_stream(std::move(body));
   server_response.status_code = status_code;
   SetResponse(std::move(server_response));
@@ -44,8 +46,8 @@
 }
 
 fxl::RefPtr<callback::Cancellable> FakeNetworkWrapper::Request(
-    std::function<network::URLRequest()> request_factory,
-    std::function<void(network::URLResponse)> callback) {
+    std::function<http::URLRequest()> request_factory,
+    std::function<void(http::URLResponse)> callback) {
   std::unique_ptr<bool> cancelled = std::make_unique<bool>(false);
 
   bool* cancelled_ptr = cancelled.get();
diff --git a/public/lib/network_wrapper/fake_network_wrapper.h b/public/lib/network_wrapper/fake_network_wrapper.h
index 6eeca20..e89307a 100644
--- a/public/lib/network_wrapper/fake_network_wrapper.h
+++ b/public/lib/network_wrapper/fake_network_wrapper.h
@@ -5,7 +5,7 @@
 #ifndef LIB_NETWORK_WRAPPER_FAKE_NETWORK_WRAPPER_H_
 #define LIB_NETWORK_WRAPPER_FAKE_NETWORK_WRAPPER_H_
 
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 #include <lib/async/dispatcher.h>
 
 #include "lib/fxl/macros.h"
@@ -18,10 +18,10 @@
   explicit FakeNetworkWrapper(async_t* async);
   ~FakeNetworkWrapper() override;
 
-  network::URLRequest* GetRequest();
+  ::fuchsia::net::oldhttp::URLRequest* GetRequest();
   void ResetRequest();
 
-  void SetResponse(network::URLResponse response);
+  void SetResponse(::fuchsia::net::oldhttp::URLResponse response);
 
   void SetSocketResponse(zx::socket body, uint32_t status_code);
 
@@ -30,11 +30,11 @@
  private:
   // NetworkWrapper
   fxl::RefPtr<callback::Cancellable> Request(
-      std::function<network::URLRequest()> request_factory,
-      std::function<void(network::URLResponse)> callback) override;
+      std::function<::fuchsia::net::oldhttp::URLRequest()> request_factory,
+      std::function<void(::fuchsia::net::oldhttp::URLResponse)> callback) override;
 
-  std::unique_ptr<network::URLRequest> request_received_;
-  std::unique_ptr<network::URLResponse> response_to_return_;
+  std::unique_ptr<::fuchsia::net::oldhttp::URLRequest> request_received_;
+  std::unique_ptr<::fuchsia::net::oldhttp::URLResponse> response_to_return_;
   async_t* const async_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(FakeNetworkWrapper);
diff --git a/public/lib/network_wrapper/network_wrapper.h b/public/lib/network_wrapper/network_wrapper.h
index 6732ab7..c33373b 100644
--- a/public/lib/network_wrapper/network_wrapper.h
+++ b/public/lib/network_wrapper/network_wrapper.h
@@ -5,7 +5,7 @@
 #ifndef LIB_NETWORK_WRAPPER_NETWORK_WRAPPER_H_
 #define LIB_NETWORK_WRAPPER_NETWORK_WRAPPER_H_
 
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 #include "lib/callback/cancellable.h"
 #include "lib/fxl/macros.h"
 #include "lib/fxl/memory/ref_ptr.h"
@@ -22,8 +22,8 @@
 
   // Starts a url network request.
   virtual fxl::RefPtr<callback::Cancellable> Request(
-      std::function<network::URLRequest()> request_factory,
-      std::function<void(network::URLResponse)> callback) = 0;
+      std::function<::fuchsia::net::oldhttp::URLRequest()> request_factory,
+      std::function<void(::fuchsia::net::oldhttp::URLResponse)> callback) = 0;
 
  private:
   FXL_DISALLOW_COPY_AND_ASSIGN(NetworkWrapper);
diff --git a/public/lib/network_wrapper/network_wrapper_impl.cc b/public/lib/network_wrapper/network_wrapper_impl.cc
index e98113f..f0453eb 100644
--- a/public/lib/network_wrapper/network_wrapper_impl.cc
+++ b/public/lib/network_wrapper/network_wrapper_impl.cc
@@ -14,13 +14,15 @@
 
 namespace network_wrapper {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 const uint32_t kMaxRedirectCount = 32;
 const int32_t kTooManyRedirectErrorCode = -310;
 const int32_t kInvalidResponseErrorCode = -320;
 
 class NetworkWrapperImpl::RunningRequest {
  public:
-  explicit RunningRequest(std::function<network::URLRequest()> request_factory)
+  explicit RunningRequest(std::function<http::URLRequest()> request_factory)
       : request_factory_(std::move(request_factory)), redirect_count_(0u) {}
 
   void Cancel() {
@@ -29,18 +31,18 @@
   }
 
   // Set the network service to use. This will start (or restart) the request.
-  void SetNetworkService(network::NetworkService* network_service) {
-    network_service_ = network_service;
-    if (network_service) {
+  void SetHttpService(http::HttpService* http_service) {
+    http_service_ = http_service;
+    if (http_service) {
       // Restart the request, as any fidl callback is now pending forever.
       Start();
     }
   }
 
-  void set_callback(std::function<void(network::URLResponse)> callback) {
+  void set_callback(std::function<void(http::URLResponse)> callback) {
     // Once this class calls its callback, it must notify its container.
     callback_ = [this, callback = std::move(callback)](
-                    network::URLResponse response) mutable {
+                    http::URLResponse response) mutable {
       FXL_DCHECK(on_empty_callback_);
       if (destruction_sentinel_.DestructedWhile(
               [callback = std::move(callback), &response] {
@@ -62,7 +64,7 @@
     url_loader_.Unbind();
 
     // If no network service has been set, bail out and wait to be called again.
-    if (!network_service_)
+    if (!http_service_)
       return;
 
     auto request = request_factory_();
@@ -71,14 +73,14 @@
     if (!next_url_.empty())
       request.url = next_url_;
 
-    network_service_->CreateURLLoader(url_loader_.NewRequest());
+    http_service_->CreateURLLoader(url_loader_.NewRequest());
 
     const std::string& url = request.url;
     const std::string& method = request.method;
     url_loader_->Start(
         std::move(request),
         TRACE_CALLBACK(
-            callback::ToStdFunction([this](network::URLResponse response) {
+            callback::ToStdFunction([this](http::URLResponse response) {
               url_loader_.Unbind();
 
               if (response.error) {
@@ -108,7 +110,7 @@
     });
   }
 
-  void HandleRedirect(network::URLResponse response) {
+  void HandleRedirect(http::URLResponse response) {
     // Follow the redirect if a Location header is found.
     for (const auto& header : *response.headers) {
       if (fxl::EqualsCaseInsensitiveASCII(header.name.get(), "location")) {
@@ -132,36 +134,36 @@
     // variables afterwards.
   }
 
-  network::URLResponse NewErrorResponse(int32_t code, std::string reason) {
-    network::URLResponse response;
-    response.error = network::NetworkError::New();
+  http::URLResponse NewErrorResponse(int32_t code, std::string reason) {
+    http::URLResponse response;
+    response.error = http::HttpError::New();
     response.error->code = code;
     response.error->description = reason;
     return response;
   }
 
-  std::function<network::URLRequest()> request_factory_;
-  std::function<void(network::URLResponse)> callback_;
+  std::function<http::URLRequest()> request_factory_;
+  std::function<void(http::URLResponse)> callback_;
   fxl::Closure on_empty_callback_;
   std::string next_url_;
   uint32_t redirect_count_;
-  network::NetworkService* network_service_;
-  network::URLLoaderPtr url_loader_;
+  http::HttpService* http_service_;
+  http::URLLoaderPtr url_loader_;
   callback::DestructionSentinel destruction_sentinel_;
 };
 
 NetworkWrapperImpl::NetworkWrapperImpl(
     async_t* async, std::unique_ptr<backoff::Backoff> backoff,
-    std::function<network::NetworkServicePtr()> network_service_factory)
+    std::function<http::HttpServicePtr()> http_service_factory)
     : backoff_(std::move(backoff)),
-      network_service_factory_(std::move(network_service_factory)),
+      http_service_factory_(std::move(http_service_factory)),
       task_runner_(async) {}
 
 NetworkWrapperImpl::~NetworkWrapperImpl() {}
 
 fxl::RefPtr<callback::Cancellable> NetworkWrapperImpl::Request(
-    std::function<network::URLRequest()> request_factory,
-    std::function<void(network::URLResponse)> callback) {
+    std::function<http::URLRequest()> request_factory,
+    std::function<void(http::URLResponse)> callback) {
   RunningRequest& request =
       running_requests_.emplace(std::move(request_factory));
 
@@ -171,40 +173,40 @@
   request.set_callback(cancellable->WrapCallback(TRACE_CALLBACK(
       std::move(callback), "network_wrapper", "network_request")));
   if (!in_backoff_) {
-    request.SetNetworkService(GetNetworkService());
+    request.SetHttpService(GetHttpService());
   }
 
   return cancellable;
 }
 
-network::NetworkService* NetworkWrapperImpl::GetNetworkService() {
-  if (!network_service_) {
-    network_service_ = network_service_factory_();
-    network_service_.set_error_handler([this]() {
+http::HttpService* NetworkWrapperImpl::GetHttpService() {
+  if (!http_service_) {
+    http_service_ = http_service_factory_();
+    http_service_.set_error_handler([this]() {
       FXL_LOG(WARNING) << "Network service crashed or not configured "
                        << "in environment, trying to reconnect.";
       FXL_DCHECK(!in_backoff_);
       in_backoff_ = true;
       for (auto& request : running_requests_) {
-        request.SetNetworkService(nullptr);
+        request.SetHttpService(nullptr);
       }
-      network_service_.Unbind();
-      task_runner_.PostDelayedTask([this] { RetryGetNetworkService(); },
+      http_service_.Unbind();
+      task_runner_.PostDelayedTask([this] { RetryGetHttpService(); },
                                    backoff_->GetNext());
     });
   }
 
-  return network_service_.get();
+  return http_service_.get();
 }
 
-void NetworkWrapperImpl::RetryGetNetworkService() {
+void NetworkWrapperImpl::RetryGetHttpService() {
   in_backoff_ = false;
   if (running_requests_.empty()) {
     return;
   }
-  network::NetworkService* network_service = GetNetworkService();
+  http::HttpService* http_service = GetHttpService();
   for (auto& request : running_requests_) {
-    request.SetNetworkService(network_service);
+    request.SetHttpService(http_service);
   }
 }
 
diff --git a/public/lib/network_wrapper/network_wrapper_impl.h b/public/lib/network_wrapper/network_wrapper_impl.h
index d6f7eb6..6682274 100644
--- a/public/lib/network_wrapper/network_wrapper_impl.h
+++ b/public/lib/network_wrapper/network_wrapper_impl.h
@@ -5,7 +5,7 @@
 #ifndef LIB_NETWORK_WRAPPER_NETWORK_WRAPPER_IMPL_H_
 #define LIB_NETWORK_WRAPPER_NETWORK_WRAPPER_IMPL_H_
 
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
 
 #include "lib/backoff/backoff.h"
 #include "lib/callback/auto_cleanable.h"
@@ -18,24 +18,24 @@
  public:
   NetworkWrapperImpl(
       async_t* async, std::unique_ptr<backoff::Backoff> backoff,
-      std::function<network::NetworkServicePtr()> network_service_factory);
+      std::function<::fuchsia::net::oldhttp::HttpServicePtr()> http_service_factory);
   ~NetworkWrapperImpl() override;
 
   fxl::RefPtr<callback::Cancellable> Request(
-      std::function<network::URLRequest()> request_factory,
-      std::function<void(network::URLResponse)> callback) override;
+      std::function<::fuchsia::net::oldhttp::URLRequest()> request_factory,
+      std::function<void(::fuchsia::net::oldhttp::URLResponse)> callback) override;
 
  private:
   class RunningRequest;
 
-  network::NetworkService* GetNetworkService();
+  ::fuchsia::net::oldhttp::HttpService* GetHttpService();
 
-  void RetryGetNetworkService();
+  void RetryGetHttpService();
 
   std::unique_ptr<backoff::Backoff> backoff_;
   bool in_backoff_ = false;
-  std::function<network::NetworkServicePtr()> network_service_factory_;
-  network::NetworkServicePtr network_service_;
+  std::function<::fuchsia::net::oldhttp::HttpServicePtr()> http_service_factory_;
+  ::fuchsia::net::oldhttp::HttpServicePtr http_service_;
   callback::AutoCleanableSet<RunningRequest> running_requests_;
 
   // Must be the last member field.
diff --git a/public/lib/network_wrapper/network_wrapper_impl_unittest.cc b/public/lib/network_wrapper/network_wrapper_impl_unittest.cc
index f1c460f..baeed0e 100644
--- a/public/lib/network_wrapper/network_wrapper_impl_unittest.cc
+++ b/public/lib/network_wrapper/network_wrapper_impl_unittest.cc
@@ -8,8 +8,8 @@
 #include <utility>
 #include <vector>
 
-#include <netstack/cpp/fidl.h>
-#include <network/cpp/fidl.h>
+#include <fuchsia/net/oldhttp/cpp/fidl.h>
+#include <fuchsia/netstack/cpp/fidl.h>
 #include <lib/async/cpp/task.h>
 #include <lib/zx/socket.h>
 
@@ -25,23 +25,25 @@
 namespace network_wrapper {
 namespace {
 
+namespace http = ::fuchsia::net::oldhttp;
+
 const char kRedirectUrl[] = "http://example.com/redirect";
 
 // Url loader that stores the url request for inspection in |request_received|,
 // and returns response indicated in |response_to_return|. |response_to_return|
 // is moved out in ::Start().
-class FakeURLLoader : public network::URLLoader {
+class FakeURLLoader : public http::URLLoader {
  public:
-  FakeURLLoader(fidl::InterfaceRequest<network::URLLoader> request,
-                network::URLResponse response_to_return,
-                network::URLRequest* request_received)
+  FakeURLLoader(fidl::InterfaceRequest<http::URLLoader> request,
+                http::URLResponse response_to_return,
+                http::URLRequest* request_received)
       : binding_(this, std::move(request)),
         response_to_return_(std::move(response_to_return)),
         request_received_(request_received) {}
   ~FakeURLLoader() override {}
 
   // URLLoader:
-  void Start(network::URLRequest request, StartCallback callback) override {
+  void Start(http::URLRequest request, StartCallback callback) override {
     *request_received_ = std::move(request);
     callback(std::move(response_to_return_));
   }
@@ -49,9 +51,9 @@
   void QueryStatus(QueryStatusCallback) override {}
 
  private:
-  fidl::Binding<network::URLLoader> binding_;
-  network::URLResponse response_to_return_;
-  network::URLRequest* request_received_;
+  fidl::Binding<http::URLLoader> binding_;
+  http::URLResponse response_to_return_;
+  http::URLRequest* request_received_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(FakeURLLoader);
 };
@@ -60,34 +62,30 @@
 // passed to any url loader and set the response that url loaders need to
 // return. Response is moved out when url request starts, and needs to be set
 // each time.
-class FakeNetworkWrapper : public network::NetworkService {
+class FakeNetworkWrapper : public http::HttpService {
  public:
-  explicit FakeNetworkWrapper(fidl::InterfaceRequest<NetworkService> request)
+  explicit FakeNetworkWrapper(fidl::InterfaceRequest<http::HttpService> request)
       : binding_(this, std::move(request)) {}
   ~FakeNetworkWrapper() override {}
 
-  network::URLRequest* GetRequest() { return &request_received_; }
+  http::URLRequest* GetRequest() { return &request_received_; }
 
-  void SetResponse(network::URLResponse response) {
+  void SetResponse(http::URLResponse response) {
     response_to_return_ = std::move(response);
   }
 
   // NetworkService:
   void CreateURLLoader(
-      fidl::InterfaceRequest<network::URLLoader> loader) override {
+      fidl::InterfaceRequest<http::URLLoader> loader) override {
     loaders_.push_back(std::make_unique<FakeURLLoader>(
         std::move(loader), std::move(response_to_return_), &request_received_));
   }
-  void GetCookieStore(zx::channel /*cookie_store*/) override {
-    FXL_DCHECK(false);
-  }
-  void CreateWebSocket(zx::channel /*socket*/) override { FXL_DCHECK(false); }
 
  private:
-  fidl::Binding<NetworkService> binding_;
+  fidl::Binding<http::HttpService> binding_;
   std::vector<std::unique_ptr<FakeURLLoader>> loaders_;
-  network::URLRequest request_received_;
-  network::URLResponse response_to_return_;
+  http::URLRequest request_received_;
+  http::URLResponse response_to_return_;
 
   FXL_DISALLOW_COPY_AND_ASSIGN(FakeNetworkWrapper);
 };
@@ -113,14 +111,14 @@
   NetworkWrapperImplTest()
       : network_service_(message_loop_.async(),
                          std::make_unique<backoff::TestBackoff>(),
-                         [this] { return NewNetworkService(); }) {}
+                         [this] { return NewHttpService(); }) {}
 
   void SetSocketResponse(zx::socket body, uint32_t status_code) {
-    network::URLResponse server_response;
-    server_response.body = network::URLBody::New();
+    http::URLResponse server_response;
+    server_response.body = http::URLBody::New();
     server_response.body->set_stream(std::move(body));
     server_response.status_code = status_code;
-    network::HttpHeader header;
+    http::HttpHeader header;
     header.name = "Location";
     header.value = kRedirectUrl;
     server_response.headers.push_back(std::move(header));
@@ -135,17 +133,17 @@
     SetSocketResponse(fsl::WriteStringToSocket(body), status_code);
   }
 
-  network::URLRequest NewRequest(const std::string& method,
+  http::URLRequest NewRequest(const std::string& method,
                                  const std::string& url) {
-    network::URLRequest request;
+    http::URLRequest request;
     request.method = method;
     request.url = url;
     return request;
   }
 
  private:
-  network::NetworkServicePtr NewNetworkService() {
-    network::NetworkServicePtr result;
+  http::HttpServicePtr NewHttpService() {
+    http::HttpServicePtr result;
     fake_network_service_ =
         std::make_unique<FakeNetworkWrapper>(result.NewRequest());
     if (response_) {
@@ -157,12 +155,12 @@
  protected:
   NetworkWrapperImpl network_service_;
   std::unique_ptr<FakeNetworkWrapper> fake_network_service_;
-  network::URLResponsePtr response_;
+  http::URLResponsePtr response_;
 };
 
 TEST_F(NetworkWrapperImplTest, SimpleRequest) {
   bool callback_destroyed = false;
-  network::URLResponse response;
+  http::URLResponse response;
   network_service_.Request(
       [this]() {
         SetStringResponse("Hello", 200);
@@ -171,7 +169,7 @@
       [this, destroy_watcher = DestroyWatcher::Create([&callback_destroyed] {
                callback_destroyed = true;
              }),
-       &response](network::URLResponse received_response) {
+       &response](http::URLResponse received_response) {
         response = std::move(received_response);
       });
   EXPECT_FALSE(callback_destroyed);
@@ -192,7 +190,7 @@
       [this, &received_response,
        destroy_watcher = DestroyWatcher::Create([this, &callback_destroyed] {
          callback_destroyed = true;
-       })](network::URLResponse) { received_response = true; });
+       })](http::URLResponse) { received_response = true; });
 
   async::PostTask(message_loop_.async(), [cancel] { cancel->Cancel(); });
   cancel = nullptr;
@@ -203,7 +201,7 @@
 
 TEST_F(NetworkWrapperImplTest, NetworkDeleted) {
   int request_count = 0;
-  network::URLResponse response;
+  http::URLResponse response;
   network_service_.Request(
       [this, &request_count]() {
         if (request_count == 0) {
@@ -213,7 +211,7 @@
         SetStringResponse("Hello", 200);
         return NewRequest("GET", "http://example.com");
       },
-      [this, &response](network::URLResponse received_response) {
+      [this, &response](http::URLResponse received_response) {
         response = std::move(received_response);
       });
   RunLoopUntilIdle();
@@ -224,7 +222,7 @@
 
 TEST_F(NetworkWrapperImplTest, Redirection) {
   int request_count = 0;
-  network::URLResponse response;
+  http::URLResponse response;
   network_service_.Request(
       [this, &request_count]() {
         if (request_count == 0) {
@@ -235,7 +233,7 @@
         ++request_count;
         return NewRequest("GET", "http://example.com");
       },
-      [this, &response](network::URLResponse received_response) {
+      [this, &response](http::URLResponse received_response) {
         response = std::move(received_response);
       });
   RunLoopUntilIdle();
@@ -247,14 +245,14 @@
 
 TEST_F(NetworkWrapperImplTest, CancelOnCallback) {
   fxl::RefPtr<callback::Cancellable> request;
-  network::URLResponsePtr response;
+  http::URLResponsePtr response;
   request = network_service_.Request(
       [this] {
         SetStringResponse("Hello", 200);
         return NewRequest("GET", "http://example.com");
       },
       [this, &request,
-       &response](network::URLResponse received_response) mutable {
+       &response](http::URLResponse received_response) mutable {
         response = fidl::MakeOptional(std::move(received_response));
         request->Cancel();
         request = nullptr;
diff --git a/public/lib/power_manager/fidl/BUILD.gn b/public/lib/power_manager/fidl/BUILD.gn
index fa1cb3f..a5c68dd 100644
--- a/public/lib/power_manager/fidl/BUILD.gn
+++ b/public/lib/power_manager/fidl/BUILD.gn
@@ -5,9 +5,10 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "power_manager"
+  name = "fuchsia.power"
+  cpp_legacy_callbacks = true
 
   sources = [
-    "power_manager.fidl",
+    "power.fidl",
   ]
 }
diff --git a/public/lib/power_manager/fidl/power_manager.fidl b/public/lib/power_manager/fidl/power.fidl
similarity index 97%
rename from public/lib/power_manager/fidl/power_manager.fidl
rename to public/lib/power_manager/fidl/power.fidl
index 8f8242b..c8f8147 100644
--- a/public/lib/power_manager/fidl/power_manager.fidl
+++ b/public/lib/power_manager/fidl/power.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library power_manager;
+library fuchsia.power;
 
 enum Status {
   OK = 0;
diff --git a/public/lib/svc/cpp/BUILD.gn b/public/lib/svc/cpp/BUILD.gn
index de7481b..d5c6d83 100644
--- a/public/lib/svc/cpp/BUILD.gn
+++ b/public/lib/svc/cpp/BUILD.gn
@@ -18,6 +18,7 @@
     "//garnet/public/lib/fxl",
     "//zircon/public/lib/fbl",
     "//zircon/public/lib/fdio",
+    "//zircon/public/lib/fit",
     "//zircon/public/lib/fs",
     "//zircon/public/lib/zx",
   ]
diff --git a/public/lib/svc/cpp/service_namespace.cc b/public/lib/svc/cpp/service_namespace.cc
index 2300711..c08903b 100644
--- a/public/lib/svc/cpp/service_namespace.cc
+++ b/public/lib/svc/cpp/service_namespace.cc
@@ -5,7 +5,7 @@
 #include "lib/svc/cpp/service_namespace.h"
 
 #include <fcntl.h>
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <fs/service.h>
 #include <lib/async/default.h>
 #include <zircon/device/vfs.h>
diff --git a/public/lib/svc/cpp/service_namespace.h b/public/lib/svc/cpp/service_namespace.h
index cf05759..4d1b638 100644
--- a/public/lib/svc/cpp/service_namespace.h
+++ b/public/lib/svc/cpp/service_namespace.h
@@ -8,9 +8,9 @@
 #include <fbl/ref_ptr.h>
 #include <fs/synchronous-vfs.h>
 #include <fs/pseudo-dir.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
-#include <functional>
 #include <string>
 #include <unordered_map>
 #include <utility>
@@ -32,7 +32,7 @@
   // |ServiceConnector| is the generic, type-unsafe interface for objects used
   // by |ServiceNamespace| to connect generic "interface requests" (i.e.,
   // just channels) specified by service name to service implementations.
-  using ServiceConnector = std::function<void(zx::channel)>;
+  using ServiceConnector = fit::function<void(zx::channel)>;
 
   // A |InterfaceRequestHandler<Interface>| is simply a function that
   // handles an interface request for |Interface|. If it determines that the
@@ -41,7 +41,7 @@
   // by the interface).
   template <typename Interface>
   using InterfaceRequestHandler =
-      std::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
+      fit::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
 
   // Constructs this service namespace implementation in an unbound state.
   ServiceNamespace();
@@ -89,7 +89,7 @@
   void AddService(InterfaceRequestHandler<Interface> handler,
                   const std::string& service_name = Interface::Name_) {
     AddServiceForName(
-        [handler](zx::channel channel) {
+        [handler = std::move(handler)](zx::channel channel) {
           handler(fidl::InterfaceRequest<Interface>(std::move(channel)));
         },
         service_name);
diff --git a/public/lib/svc/cpp/service_provider_bridge.cc b/public/lib/svc/cpp/service_provider_bridge.cc
index 7acc9b1..0a6ddd8 100644
--- a/public/lib/svc/cpp/service_provider_bridge.cc
+++ b/public/lib/svc/cpp/service_provider_bridge.cc
@@ -5,7 +5,7 @@
 #include "lib/svc/cpp/service_provider_bridge.h"
 
 #include <fcntl.h>
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 #include <fs/service.h>
 #include <lib/async/default.h>
 #include <zircon/device/vfs.h>
diff --git a/public/lib/svc/cpp/service_provider_bridge.h b/public/lib/svc/cpp/service_provider_bridge.h
index 4432b89..39daa46 100644
--- a/public/lib/svc/cpp/service_provider_bridge.h
+++ b/public/lib/svc/cpp/service_provider_bridge.h
@@ -7,9 +7,9 @@
 
 #include <fbl/ref_ptr.h>
 #include <fs/synchronous-vfs.h>
+#include <lib/fit/function.h>
 #include <lib/zx/channel.h>
 
-#include <functional>
 #include <string>
 #include <unordered_map>
 #include <utility>
@@ -33,11 +33,11 @@
   ServiceProviderBridge();
   ~ServiceProviderBridge() override;
 
-  using ServiceConnector = std::function<void(zx::channel)>;
+  using ServiceConnector = fit::function<void(zx::channel)>;
 
   template <typename Interface>
   using InterfaceRequestHandler =
-      std::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
+      fit::function<void(fidl::InterfaceRequest<Interface> interface_request)>;
 
   void AddServiceForName(ServiceConnector connector,
                          const std::string& service_name);
@@ -46,7 +46,7 @@
   void AddService(InterfaceRequestHandler<Interface> handler,
                   const std::string& service_name = Interface::Name_) {
     AddServiceForName(
-        [handler](zx::channel channel) {
+        [handler = std::move(handler)](zx::channel channel) {
           handler(fidl::InterfaceRequest<Interface>(std::move(channel)));
         },
         service_name);
diff --git a/public/lib/svc/cpp/services.cc b/public/lib/svc/cpp/services.cc
index 91d9576..9c232d7 100644
--- a/public/lib/svc/cpp/services.cc
+++ b/public/lib/svc/cpp/services.cc
@@ -4,7 +4,7 @@
 
 #include "lib/svc/cpp/services.h"
 
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 
 #include "lib/fxl/logging.h"
 
diff --git a/public/lib/svc/dir_unittest.cc b/public/lib/svc/dir_unittest.cc
index 77be210..b52ab5a 100644
--- a/public/lib/svc/dir_unittest.cc
+++ b/public/lib/svc/dir_unittest.cc
@@ -7,7 +7,7 @@
 #include <lib/async-loop/cpp/loop.h>
 #include <lib/async-loop/loop.h>
 #include <lib/zx/channel.h>
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
 
 #include <thread>
 
diff --git a/public/lib/syslog/go/src/syslog/logger/logger.go b/public/lib/syslog/go/src/syslog/logger/logger.go
index 1c14d5e..9cbc6cb 100644
--- a/public/lib/syslog/go/src/syslog/logger/logger.go
+++ b/public/lib/syslog/go/src/syslog/logger/logger.go
@@ -18,7 +18,7 @@
 
 	"app/context"
 
-	logger_fidl "fidl/logger"
+	logger_fidl "fidl/fuchsia/logger"
 )
 
 var (
diff --git a/public/lib/test_runner/cpp/scope.h b/public/lib/test_runner/cpp/scope.h
index afc2161..8d464c4 100644
--- a/public/lib/test_runner/cpp/scope.h
+++ b/public/lib/test_runner/cpp/scope.h
@@ -29,7 +29,7 @@
       fuchsia::sys::ServiceProviderImpl::InterfaceRequestHandler<Interface>
           handler,
       const std::string& service_name = Interface::Name_) {
-    service_provider_bridge_.AddService(handler, service_name);
+    service_provider_bridge_.AddService(std::move(handler), service_name);
   }
 
   fuchsia::sys::Launcher* GetLauncher();
diff --git a/public/lib/test_runner/fidl/BUILD.gn b/public/lib/test_runner/fidl/BUILD.gn
index 25e840d..f6d4aba 100644
--- a/public/lib/test_runner/fidl/BUILD.gn
+++ b/public/lib/test_runner/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "test_runner"
+  cpp_legacy_callbacks = true
 
   sources = [
     "test_runner.fidl",
diff --git a/public/lib/time_zone/fidl/BUILD.gn b/public/lib/time_zone/fidl/BUILD.gn
index 833e21b..2fa5442 100644
--- a/public/lib/time_zone/fidl/BUILD.gn
+++ b/public/lib/time_zone/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "time_zone"
+  cpp_legacy_callbacks = true
 
   sources = [
     "time_zone.fidl"
diff --git a/public/lib/tracing/fidl/BUILD.gn b/public/lib/tracing/fidl/BUILD.gn
index 8ba8289..12c9d4a 100644
--- a/public/lib/tracing/fidl/BUILD.gn
+++ b/public/lib/tracing/fidl/BUILD.gn
@@ -6,6 +6,8 @@
 
 fidl("fidl") {
   name = "tracing"
+  cpp_legacy_callbacks = true
+
   sources = [
     "trace_controller.fidl",
   ]
diff --git a/public/lib/tts/fidl/BUILD.gn b/public/lib/tts/fidl/BUILD.gn
index 4210a10..b635d65 100644
--- a/public/lib/tts/fidl/BUILD.gn
+++ b/public/lib/tts/fidl/BUILD.gn
@@ -5,7 +5,8 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "tts"
+  name = "fuchsia.tts"
+  cpp_legacy_callbacks = true
 
   sources = [
     "tts.fidl",
diff --git a/public/lib/tts/fidl/tts.fidl b/public/lib/tts/fidl/tts.fidl
index d4fe38c..e8546b1 100644
--- a/public/lib/tts/fidl/tts.fidl
+++ b/public/lib/tts/fidl/tts.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library tts;
+library fuchsia.tts;
 
 [Discoverable]
 interface TtsService {
diff --git a/public/lib/ui/a11y/fidl/BUILD.gn b/public/lib/ui/a11y/fidl/BUILD.gn
new file mode 100644
index 0000000..ffdff5a
--- /dev/null
+++ b/public/lib/ui/a11y/fidl/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/fidl/fidl.gni")
+
+fidl("fidl") {
+  name = "fuchsia.ui.a11y"
+  cpp_legacy_callbacks = true
+
+  sdk_category = "partner"
+
+  sources = [
+    "a11y_client.fidl"
+  ]
+
+  public_deps = [
+    "//garnet/public/lib/app/fidl",
+  ]
+}
diff --git a/public/lib/ui/a11y/fidl/a11y_client.fidl b/public/lib/ui/a11y/fidl/a11y_client.fidl
new file mode 100644
index 0000000..ce8bf84
--- /dev/null
+++ b/public/lib/ui/a11y/fidl/a11y_client.fidl
@@ -0,0 +1,11 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library fuchsia.ui.a11y;
+
+// This is a stub implementation and is currently a work in progress.
+[Discoverable]
+interface A11yClient {
+  1: NotifyViewSelected();
+};
\ No newline at end of file
diff --git a/public/lib/ui/geometry/fidl/BUILD.gn b/public/lib/ui/geometry/fidl/BUILD.gn
index 999966d..14085c9 100644
--- a/public/lib/ui/geometry/fidl/BUILD.gn
+++ b/public/lib/ui/geometry/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.math"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/gfx/fidl/BUILD.gn b/public/lib/ui/gfx/fidl/BUILD.gn
index 3d5faac..4a72783 100644
--- a/public/lib/ui/gfx/fidl/BUILD.gn
+++ b/public/lib/ui/gfx/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.ui.gfx"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/gfx/fidl/commands.fidl b/public/lib/ui/gfx/fidl/commands.fidl
index 1a9cea7..0849b55 100644
--- a/public/lib/ui/gfx/fidl/commands.fidl
+++ b/public/lib/ui/gfx/fidl/commands.fidl
@@ -7,74 +7,74 @@
 // Commands that are used to modify the state of a |Session|.
 // TODO(SCN-237): reorder Command definitions to match the order in this union.
 union Command {
-  CreateResourceCommand create_resource;
-  ReleaseResourceCommand release_resource;
-  ExportResourceCommand export_resource;
-  ImportResourceCommand import_resource;
+  CreateResourceCmd create_resource;
+  ReleaseResourceCmd release_resource;
+  ExportResourceCmd export_resource;
+  ImportResourceCmd import_resource;
 
   // Tagging commands.
-  SetTagCommand set_tag;
+  SetTagCmd set_tag;
 
   // Grouping commands.
-  DetachCommand detach;
+  DetachCmd detach;
 
   // Spatial commands.
-  SetTranslationCommand set_translation;
-  SetScaleCommand set_scale;
-  SetRotationCommand set_rotation;
-  SetAnchorCommand set_anchor;
-  SetSizeCommand set_size;
+  SetTranslationCmd set_translation;
+  SetScaleCmd set_scale;
+  SetRotationCmd set_rotation;
+  SetAnchorCmd set_anchor;
+  SetSizeCmd set_size;
 
   // Node-specific commands.
-  AddChildCommand add_child;  // TODO: Should we require a DetachCommand before
+  AddChildCmd add_child;  // TODO: Should we require a DetachCmd before
                               // re-parenting?
-  AddPartCommand add_part;
-  DetachChildrenCommand detach_children;
-  SetShapeCommand set_shape;
-  SetMaterialCommand set_material;
-  SetClipCommand set_clip;
-  SetHitTestBehaviorCommand set_hit_test_behavior;
-  SetSpacePropertiesCommand set_space_properties;
+  AddPartCmd add_part;
+  DetachChildrenCmd detach_children;
+  SetShapeCmd set_shape;
+  SetMaterialCmd set_material;
+  SetClipCmd set_clip;
+  SetHitTestBehaviorCmd set_hit_test_behavior;
+  SetSpacePropertiesCmd set_space_properties;
 
   // Camera and lighting commands.
-  SetCameraCommand set_camera;
-  SetCameraTransformCommand set_camera_transform;
-  SetCameraProjectionCommand set_camera_projection;
-  SetStereoCameraProjectionCommand set_stereo_camera_projection;
-  SetCameraPoseBufferCommand set_camera_pose_buffer;
-  SetLightColorCommand set_light_color;
-  SetLightDirectionCommand set_light_direction;
-  AddLightCommand add_light;
-  DetachLightCommand detach_light;
-  DetachLightsCommand detach_lights;
+  SetCameraCmd set_camera;
+  SetCameraTransformCmd set_camera_transform;
+  SetCameraProjectionCmd set_camera_projection;
+  SetStereoCameraProjectionCmd set_stereo_camera_projection;
+  SetCameraPoseBufferCmd set_camera_pose_buffer;
+  SetLightColorCmd set_light_color;
+  SetLightDirectionCmd set_light_direction;
+  AddLightCmd add_light;
+  DetachLightCmd detach_light;
+  DetachLightsCmd detach_lights;
 
-  SetTextureCommand set_texture;
-  SetColorCommand set_color;
+  SetTextureCmd set_texture;
+  SetColorCmd set_color;
 
   // Mesh commands.
-  BindMeshBuffersCommand bind_mesh_buffers;
+  BindMeshBuffersCmd bind_mesh_buffers;
 
   // Layer and renderer commands.
-  AddLayerCommand add_layer;
-  RemoveLayerCommand remove_layer;
-  RemoveAllLayersCommand remove_all_layers;
-  SetLayerStackCommand set_layer_stack;
-  SetRendererCommand set_renderer;
-  SetRendererParamCommand set_renderer_param;
+  AddLayerCmd add_layer;
+  RemoveLayerCmd remove_layer;
+  RemoveAllLayersCmd remove_all_layers;
+  SetLayerStackCmd set_layer_stack;
+  SetRendererCmd set_renderer;
+  SetRendererParamCmd set_renderer_param;
 
   // Events.
-  SetEventMaskCommand set_event_mask;
+  SetEventMaskCmd set_event_mask;
 
   // Diagnostic commands.
-  SetLabelCommand set_label;
+  SetLabelCmd set_label;
 
   // Debugging commands.
-  SetDisableClippingCommand set_disable_clipping;
+  SetDisableClippingCmd set_disable_clipping;
 };
 
 // Instructs the compositor to create the specified |Resource|, and to register
 // it in a table so that it can be referenced by subsequent commands.
-struct CreateResourceCommand {
+struct CreateResourceCmd {
   // An ID that is currently not used within the session.
   uint32 id;
   ResourceArgs resource;
@@ -87,38 +87,38 @@
 // resource may be required to render an in-progress frame, or it may be
 // referred to by another resource).  However, the ID will be immediately
 // unregistered, and may be reused to create a new resource.
-struct ReleaseResourceCommand {
+struct ReleaseResourceCmd {
   // ID of the resource to be dereferenced.
   uint32 id;
 };
 
 // Create an external reference to the specified resource, which can then be
 // imported into another Session by passing a handle to |token|'s peer to
-// ImportResourceCommand; see that comment for more details.
+// ImportResourceCmd; see that comment for more details.
 //
 // The importing client is typically in a different process than the exporter.
 // No specific mechanism is provided for transferring a token from an exporter
 // to an importer; collaborators may choose any out-of-band API they wish to do
 // so.
-struct ExportResourceCommand {
+struct ExportResourceCmd {
   uint32 id;
   handle<eventpair> token;
 };
 
-// Import a resource that was exported via ExportResourceCommand().  |token| is
+// Import a resource that was exported via ExportResourceCmd().  |token| is
 // a handle to the eventpair peer that was used to export the resource, and
 // |spec| describes the type of the imported resource, and the commands which
 // can legally be applied to it.  Afterward, |id| can be used to refer to the
 // resource in an Command, similarly (but not identically: see below) to a
 // resource that was created in the session.  For example, you can add children
-// to an imported EntityNode via AddChildCommand.
+// to an imported EntityNode via AddChildCmd.
 //
 // However, note that the importer does not gain full access to the imported
 // resource, but rather to an attenuated subset of its capabilities.  For
-// example, you cannot use a DetachCommand to detach an imported EntityNode from
+// example, you cannot use a DetachCmd to detach an imported EntityNode from
 // its parent.
 //
-// Unlike ExportResourceCommand, there is no configurable timeout.  There is an
+// Unlike ExportResourceCmd, there is no configurable timeout.  There is an
 // expectation that the exported resource will become available in a short
 // amount of time.  TODO: this needs elaboration... e.g. we might notify via the
 // SessionListener when we know that the link will never be made (e.g. if the
@@ -127,7 +127,7 @@
 // TODO: describe how the imported resource behaves if the exported resource
 // isn't yet available, or becomes unavailable (e.g. an imported Material might
 // act as a plain white texture).
-struct ImportResourceCommand {
+struct ImportResourceCmd {
   uint32 id;
   handle<eventpair> token;
   ImportSpec spec;
@@ -146,7 +146,7 @@
 // Constraints:
 // - The label's maximum length is |kLabelMaxLength| characters.
 // - Setting the label to an empty string clears it.
-struct SetLabelCommand {
+struct SetLabelCmd {
   uint32 id;
   string label;
 };
@@ -158,9 +158,9 @@
 // - |child_id| refs any Node.
 //
 // Discussion:
-// The child node is first removed from its existing parent, as if DetachCommand
+// The child node is first removed from its existing parent, as if DetachCmd
 // was applied first.
-struct AddChildCommand {
+struct AddChildCmd {
   uint32 node_id;
   uint32 child_id;
 };
@@ -168,7 +168,7 @@
 // Add a node as a part of another node.  The implications of being a part
 // rather than a child differ based on the type of the part.  However, one
 // implication is constant: removing all of a node's children (e.g. via
-// DetachChildrenCommand) does not affect its parts.  This is similar to the
+// DetachChildrenCmd) does not affect its parts.  This is similar to the
 // "shadow DOM" in a web browser: the controls of a <video> element are
 // implemented as using the shadow DOM, and do no show up amongst the children
 // of that element.
@@ -178,9 +178,9 @@
 // - |part_id| refs any Node.
 //
 // Discussion:
-// The part node is first removed from its existing parent, as if DetachCommand
+// The part node is first removed from its existing parent, as if DetachCmd
 // was applied first.
-struct AddPartCommand {
+struct AddPartCmd {
   uint32 node_id;
   uint32 part_id;
 };
@@ -195,12 +195,12 @@
 // Discussion:
 // For nodes, this command will detach a node from its parent, regardless of
 // whether it is a part or a child of its parent.
-struct DetachCommand {
+struct DetachCmd {
   uint32 id;
 };
 
 // Detaches all of a node's children (but not its parts).
-struct DetachChildrenCommand {
+struct DetachChildrenCmd {
   uint32 node_id;
 };
 
@@ -218,7 +218,7 @@
 // Constraints:
 // - |node_id| refs a |Node|.
 // - |tag_value| is the tag value to assign, or 0 to remove the tag.
-struct SetTagCommand {
+struct SetTagCmd {
   uint32 node_id;
   uint32 tag_value;
 };
@@ -227,7 +227,7 @@
 //
 // Constraints:
 // - |id| refs a Resource with the has_transform characteristic.
-struct SetTranslationCommand {
+struct SetTranslationCmd {
   uint32 id;
   Vector3Value value;
 };
@@ -236,7 +236,7 @@
 //
 // Constraints:
 // - |id| refs a Resource with the has_transform characteristic.
-struct SetScaleCommand {
+struct SetScaleCmd {
   uint32 id;
   Vector3Value value;
 };
@@ -245,7 +245,7 @@
 //
 // Constraints:
 // - |id| refs a Resource with the has_transform characteristic.
-struct SetRotationCommand {
+struct SetRotationCmd {
   uint32 id;
   QuaternionValue value;
 };
@@ -254,7 +254,7 @@
 //
 // Constraints:
 // - |id| refs a Resource with the has_transform characteristic.
-struct SetAnchorCommand {
+struct SetAnchorCmd {
   uint32 id;
   Vector3Value value;
 };
@@ -265,7 +265,7 @@
 // - |id| refs a resizeable object.
 // - some objects that support this command may have additional constraints
 //   (e.g. in some cases |depth| must be zero).
-struct SetSizeCommand {
+struct SetSizeCmd {
   uint32 id;
   Vector2Value value;
 };
@@ -284,7 +284,7 @@
 // In order to be painted, a node requires both a |Shape| and a |Material|.
 // Without a material, a node can still participate in hit-testing and clipping.
 // Without a shape, a node cannot do any of the above.
-struct SetShapeCommand {
+struct SetShapeCmd {
   uint32 node_id;
   uint32 shape_id;
 };
@@ -303,7 +303,7 @@
 // In order to be painted, a node requires both a |Shape| and a |Material|.
 // Without a material, a node can still participate in hit-testing and clipping.
 // Without a shape, a node cannot do any of the above.
-struct SetMaterialCommand {
+struct SetMaterialCmd {
   uint32 node_id;
   uint32 material_id;
 };
@@ -328,7 +328,7 @@
 // For example, consider a 3D space that looks through a portal into a 2D space
 // that uses a clip for a circular reveal.  It would not be meaningful to clip
 // objects on the outside (i.e. in the 3D space).
-struct SetClipCommand {
+struct SetClipCmd {
   uint32 node_id;
   uint32 clip_id;
   bool clip_to_self;
@@ -339,7 +339,7 @@
 // Discussion:
 // By default, hit testing is performed on the node's content, its parts,
 // and its children.
-struct SetHitTestBehaviorCommand {
+struct SetHitTestBehaviorCmd {
   uint32 node_id;
   HitTestBehavior hit_test_behavior;
 };
@@ -348,7 +348,7 @@
 //
 // Constraints:
 // - |space_holder_id| refs a |SpaceHolder|.
-struct SetSpacePropertiesCommand {
+struct SetSpacePropertiesCmd {
   uint32 space_holder_id;
   SpaceProperties properties;
 };
@@ -359,7 +359,7 @@
 // - |renderer_id| refs a |Renderer|.
 // - |camera_id| refs a |Camera|, or stops rendering by passing zero.
 // - |matrix| is a value or variable of type kMatrix4x4.
-struct SetCameraCommand {
+struct SetCameraCmd {
   uint32 renderer_id;
   uint32 camera_id;
 };
@@ -372,7 +372,7 @@
 // - |eye_position| is the position of the eye.
 // - |eye_look_at| is the point is the scene the that eye is pointed at.
 // - |eye_up| defines the camera's "up" vector.
-struct SetCameraTransformCommand {
+struct SetCameraTransformCmd {
   uint32 camera_id;
   Vector3Value eye_position;
   Vector3Value eye_look_at;
@@ -388,7 +388,7 @@
 //
 // NOTE: A default orthographic projection is specified by setting |fovy| to
 // zero.  In this case, the camera transform is ignored.
-struct SetCameraProjectionCommand {
+struct SetCameraProjectionCmd {
   uint32 camera_id;
   FloatValue fovy;  // Y-axis field of view, in radians.
 };
@@ -403,7 +403,7 @@
 //
 // These projection matrices may also contain a transform in camera space for
 // their eye if needed.
-struct SetStereoCameraProjectionCommand {
+struct SetStereoCameraProjectionCmd {
   uint32 camera_id;
   Matrix4Value left_projection;
   Matrix4Value right_projection;
@@ -481,7 +481,7 @@
 //
 // This commanderation is intended for late latching camera pose to support
 // low-latency motion-tracked rendering.
-struct SetCameraPoseBufferCommand {
+struct SetCameraPoseBufferCmd {
   uint32 camera_id;
   uint32 buffer_id;
   uint32 num_entries;
@@ -490,32 +490,32 @@
 };
 
 // Sets the color of the Light identified by |light_id|.
-struct SetLightColorCommand {
+struct SetLightColorCmd {
   uint32 light_id;
   ColorRgbValue color;
 };
 
 // Sets the direction of the DirectionalLight identified by |light_id|.
-struct SetLightDirectionCommand {
+struct SetLightDirectionCmd {
   uint32 light_id;
   Vector3Value direction;
 };
 
 // Adds the light specified by |light_id| specified by |light_id| to the scene
 // identified by |scene_id|.
-struct AddLightCommand {
+struct AddLightCmd {
   uint32 scene_id;
   uint32 light_id;
 };
 
 // Detach the light specified by |light_id| from the scene that it is attached
 // to, if any.
-struct DetachLightCommand {
+struct DetachLightCmd {
   uint32 light_id;
 };
 
 // Detach all lights from the scene specified by |scene_id|.
-struct DetachLightsCommand {
+struct DetachLightsCmd {
   uint32 scene_id;
 };
 
@@ -528,7 +528,7 @@
 // If no texture is provided (i.e. |texture_id| is zero), a solid color is used.
 // If a texture is provided, then the value sampled from the texture is
 // multiplied by the color.
-struct SetTextureCommand {
+struct SetTextureCmd {
   uint32 material_id;
   uint32 texture_id;  // Refers to an Image resource.  May be zero (no texture).
 };
@@ -540,7 +540,7 @@
 //
 // If a texture is set on the material, then the value sampled from the texture
 // is multiplied by the color.
-struct SetColorCommand {
+struct SetColorCmd {
   uint32 material_id;
   ColorRgbaValue color;
 };
@@ -581,7 +581,7 @@
   ValueType tex_coord_type;
 };
 
-struct BindMeshBuffersCommand {
+struct BindMeshBuffersCmd {
   uint32 mesh_id;
   uint32 index_buffer_id;
   MeshIndexFormat index_format;
@@ -600,7 +600,7 @@
 // - |layer_id| refs a |Layer|.
 // - The layer must not already belong to a different stack; it must first be
 //   detached.
-struct AddLayerCommand {
+struct AddLayerCmd {
   uint32 layer_stack_id;
   uint32 layer_id;
 };
@@ -610,7 +610,7 @@
 // - |layer_stack_id| refs a |LayerStack|.
 // - |layer_id| refs a |Layer|.
 // - The layer must belong to this stack.
-struct RemoveLayerCommand {
+struct RemoveLayerCmd {
   uint32 layer_stack_id;
   uint32 layer_id;
 };
@@ -618,7 +618,7 @@
 // Remove all layers from a layer stack.
 // Constraints
 // - |layer_stack_id| refs a |LayerStack|.
-struct RemoveAllLayersCommand {
+struct RemoveAllLayersCmd {
   uint32 layer_stack_id;
 };
 
@@ -626,7 +626,7 @@
 // Constraints:
 // - |compositor_id| refs a |DisplayCompositor| or |ImagePipeCompositor|.
 // - |layer_stack_id| refs a |LayerStack|.
-struct SetLayerStackCommand {
+struct SetLayerStackCmd {
   uint32 compositor_id;
   uint32 layer_stack_id;
 };
@@ -635,7 +635,7 @@
 // Constraints:
 // - |layer_id| refs a |Layer|.
 // - |renderer_id| refs a |Renderer|.
-struct SetRendererCommand {
+struct SetRendererCmd {
   uint32 layer_id;
   uint32 renderer_id;
 };
@@ -644,7 +644,7 @@
 //
 // |renderer_id| refs the Renderer that is being modified.
 // |param| describes the parameter that should be set, and to what.
-struct SetRendererParamCommand {
+struct SetRendererParamCmd {
   uint32 renderer_id;
   RendererParam param;
 };
@@ -658,7 +658,7 @@
 // Constraints:
 // - |resource_id| is a valid resource id
 // - |event_mask| is zero or a combination of |k*EventMask| bits OR'ed together.
-struct SetEventMaskCommand {
+struct SetEventMaskCmd {
   uint32 id;
   uint32 event_mask;
 };
@@ -672,7 +672,7 @@
 //
 // |renderer_id| refs the target renderer.
 // |disable_clipping| specifies whether the clipping should be disabled.
-struct SetDisableClippingCommand {
+struct SetDisableClippingCmd {
   uint32 renderer_id;
   bool disable_clipping;
 };
diff --git a/public/lib/ui/gfx/fidl/events.fidl b/public/lib/ui/gfx/fidl/events.fidl
index f5259cc..0071267 100644
--- a/public/lib/ui/gfx/fidl/events.fidl
+++ b/public/lib/ui/gfx/fidl/events.fidl
@@ -9,7 +9,7 @@
 const uint32 kMetricsEventMask = 1;
 
 // These are all of the types of events which can be reported by a |Session|.
-// Use |SetEventMaskCommand| to enable event delivery for a resource.
+// Use |SetEventMaskCmd| to enable event delivery for a resource.
 union Event {
   // Events which are controlled by a mask.
   MetricsEvent metrics;
diff --git a/public/lib/ui/gfx/fidl/resources.fidl b/public/lib/ui/gfx/fidl/resources.fidl
index a113ce0..5b2afcd 100644
--- a/public/lib/ui/gfx/fidl/resources.fidl
+++ b/public/lib/ui/gfx/fidl/resources.fidl
@@ -195,10 +195,10 @@
 // Simple texture-mapped material.
 //
 // Commands that can be performed later:
-// SetTextureCommand will set the texture, or it can be left as zero (no
+// SetTextureCmd will set the texture, or it can be left as zero (no
 // texture).
 //   The texture can be an Image or ImagePipe.
-// SetColorCommand will set the color.
+// SetColorCmd will set the color.
 struct MaterialArgs {
   // TODO(SCN-694): Clean up dummy args.
   uint32 dummy = 0;
@@ -210,7 +210,7 @@
 };
 
 // Describes an exported resource that is to be imported by an
-// ImportResourceCommand.
+// ImportResourceCmd.
 //
 // NOTE: Currently just an enum of importable resource types, but may later be
 // expanded to express concepts like "meshes with a particular vertex format".
diff --git a/public/lib/ui/gfx/fidl/shapes.fidl b/public/lib/ui/gfx/fidl/shapes.fidl
index cc25ad0..5734af1 100644
--- a/public/lib/ui/gfx/fidl/shapes.fidl
+++ b/public/lib/ui/gfx/fidl/shapes.fidl
@@ -34,7 +34,7 @@
 };
 
 // A Mesh cannot be rendered until it has been bound to vertex/index buffers;
-// see BindMeshBuffersCommand.
+// see BindMeshBuffersCmd.
 struct MeshArgs {
     uint8 dummy;
 };
diff --git a/public/lib/ui/input/BUILD.gn b/public/lib/ui/input/BUILD.gn
index f65f838..0aeeac5 100644
--- a/public/lib/ui/input/BUILD.gn
+++ b/public/lib/ui/input/BUILD.gn
@@ -10,10 +10,11 @@
     "input_device_impl.h",
   ]
 
-  deps = [
+  public_deps = [
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/fxl",
     "//garnet/public/lib/ui/input/fidl",
     "//zircon/public/lib/hid",
+    "//zircon/public/lib/fit",
   ]
 }
diff --git a/public/lib/ui/input/device_state.cc b/public/lib/ui/input/device_state.cc
index 13017a7..dd08a25 100644
--- a/public/lib/ui/input/device_state.cc
+++ b/public/lib/ui/input/device_state.cc
@@ -443,7 +443,7 @@
       mouse_(this),
       stylus_(this),
       touchscreen_(this),
-      callback_(callback),
+      callback_(std::move(callback)),
       sensor_(this),
       sensor_callback_(nullptr) {}
 
@@ -458,7 +458,7 @@
       touchscreen_(this),
       callback_(nullptr),
       sensor_(this),
-      sensor_callback_(callback) {}
+      sensor_callback_(std::move(callback)) {}
 
 DeviceState::~DeviceState() {}
 
diff --git a/public/lib/ui/input/device_state.h b/public/lib/ui/input/device_state.h
index 90bd4f3..afbaf1b 100644
--- a/public/lib/ui/input/device_state.h
+++ b/public/lib/ui/input/device_state.h
@@ -14,18 +14,21 @@
 
 #include <fuchsia/math/cpp/fidl.h>
 #include <fuchsia/ui/input/cpp/fidl.h>
+#include <lib/fit/function.h>
+
 #include "lib/fxl/memory/ref_counted.h"
 #include "lib/fxl/memory/weak_ptr.h"
 
 namespace mozart {
 
 using OnEventCallback =
-    std::function<void(fuchsia::ui::input::InputEvent event)>;
+    fit::function<void(fuchsia::ui::input::InputEvent event)>;
+
 // In contrast to keyboard and mouse devices, which require extra state to
 // correctly interpret their data, sensor devices are simpler, so we just pass
 // through the raw InputReport. We do need a device_id to understand which
 // sensor the report came from.
-using OnSensorEventCallback = std::function<void(
+using OnSensorEventCallback = fit::function<void(
     uint32_t device_id, fuchsia::ui::input::InputReport event)>;
 
 class DeviceState;
@@ -131,8 +134,8 @@
               fuchsia::math::Size display_size);
 
   uint32_t device_id() { return device_id_; }
-  OnEventCallback callback() { return callback_; }
-  OnSensorEventCallback sensor_callback() { return sensor_callback_; }
+  const OnEventCallback& callback() { return callback_; }
+  const OnSensorEventCallback& sensor_callback() { return sensor_callback_; }
 
   fuchsia::ui::input::KeyboardDescriptor* keyboard_descriptor() {
     return descriptor_->keyboard.get();
diff --git a/public/lib/ui/input/fidl/BUILD.gn b/public/lib/ui/input/fidl/BUILD.gn
index 5f1397f..52f40b1 100644
--- a/public/lib/ui/input/fidl/BUILD.gn
+++ b/public/lib/ui/input/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.ui.input"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/presentation/fidl/BUILD.gn b/public/lib/ui/policy/fidl/BUILD.gn
similarity index 86%
rename from public/lib/ui/presentation/fidl/BUILD.gn
rename to public/lib/ui/policy/fidl/BUILD.gn
index 8543ab1..92c94a5 100644
--- a/public/lib/ui/presentation/fidl/BUILD.gn
+++ b/public/lib/ui/policy/fidl/BUILD.gn
@@ -5,7 +5,8 @@
 import("//build/fidl/fidl.gni")
 
 fidl("fidl") {
-  name = "presentation"
+  name = "fuchsia.ui.policy"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/presentation/fidl/display_usage.fidl b/public/lib/ui/policy/fidl/display_usage.fidl
similarity index 94%
rename from public/lib/ui/presentation/fidl/display_usage.fidl
rename to public/lib/ui/policy/fidl/display_usage.fidl
index 7e008b6..79f820f 100644
--- a/public/lib/ui/presentation/fidl/display_usage.fidl
+++ b/public/lib/ui/policy/fidl/display_usage.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library presentation;
+library fuchsia.ui.policy;
 
 // Describes the intended usage of the display.
 enum DisplayUsage {
diff --git a/public/lib/ui/presentation/fidl/presentation.fidl b/public/lib/ui/policy/fidl/presentation.fidl
similarity index 98%
rename from public/lib/ui/presentation/fidl/presentation.fidl
rename to public/lib/ui/policy/fidl/presentation.fidl
index b078afc..09dc2a6 100644
--- a/public/lib/ui/presentation/fidl/presentation.fidl
+++ b/public/lib/ui/policy/fidl/presentation.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library presentation;
+library fuchsia.ui.policy;
 
 using fuchsia.ui.gfx;
 using fuchsia.ui.input;
diff --git a/public/lib/ui/presentation/fidl/presenter.fidl b/public/lib/ui/policy/fidl/presenter.fidl
similarity index 96%
rename from public/lib/ui/presentation/fidl/presenter.fidl
rename to public/lib/ui/policy/fidl/presenter.fidl
index fe5800b..ecc4fe0 100644
--- a/public/lib/ui/presentation/fidl/presenter.fidl
+++ b/public/lib/ui/policy/fidl/presenter.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library presentation;
+library fuchsia.ui.policy;
 
 using fuchsia.ui.gfx;
 
diff --git a/public/lib/ui/scenic/BUILD.gn b/public/lib/ui/scenic/BUILD.gn
index 88d2983..53e0938 100644
--- a/public/lib/ui/scenic/BUILD.gn
+++ b/public/lib/ui/scenic/BUILD.gn
@@ -39,6 +39,7 @@
 
   public_deps = [
     ":fidl_helpers",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/public/lib/ui/scenic/client/host_image_cycler.cc b/public/lib/ui/scenic/client/host_image_cycler.cc
index 163f982..06013bb 100644
--- a/public/lib/ui/scenic/client/host_image_cycler.cc
+++ b/public/lib/ui/scenic/client/host_image_cycler.cc
@@ -57,7 +57,7 @@
     reconfigured_ = false;
   }
 
-  // TODO(MZ-145): Define an |InvalidateCommand| on |Image| instead.
+  // TODO(MZ-145): Define an |InvalidateCmd| on |Image| instead.
   image_pool_.DiscardImage(image_index_);
   image_index_ = (image_index_ + 1) % kNumBuffers;
 }
diff --git a/public/lib/ui/scenic/client/resources.cc b/public/lib/ui/scenic/client/resources.cc
index 66b2916..490b446 100644
--- a/public/lib/ui/scenic/client/resources.cc
+++ b/public/lib/ui/scenic/client/resources.cc
@@ -27,19 +27,19 @@
 }
 
 void Resource::Export(zx::eventpair export_token) {
-  session_->Enqueue(NewExportResourceCommand(id(), std::move(export_token)));
+  session_->Enqueue(NewExportResourceCmd(id(), std::move(export_token)));
 }
 
 void Resource::ExportAsRequest(zx::eventpair* out_import_token) {
-  session_->Enqueue(NewExportResourceCommandAsRequest(id(), out_import_token));
+  session_->Enqueue(NewExportResourceCmdAsRequest(id(), out_import_token));
 }
 
 void Resource::SetEventMask(uint32_t event_mask) {
-  session_->Enqueue(NewSetEventMaskCommand(id(), event_mask));
+  session_->Enqueue(NewSetEventMaskCmd(id(), event_mask));
 }
 
 void Resource::SetLabel(const std::string& label) {
-  session_->Enqueue(NewSetLabelCommand(id(), label));
+  session_->Enqueue(NewSetLabelCmd(id(), label));
 }
 
 Shape::Shape(Session* session) : Resource(session) {}
@@ -49,7 +49,7 @@
 Shape::~Shape() = default;
 
 Circle::Circle(Session* session, float radius) : Shape(session) {
-  session->Enqueue(NewCreateCircleCommand(id(), radius));
+  session->Enqueue(NewCreateCircleCmd(id(), radius));
 }
 
 Circle::Circle(Circle&& moved) : Shape(std::move(moved)) {}
@@ -58,7 +58,7 @@
 
 Rectangle::Rectangle(Session* session, float width, float height)
     : Shape(session) {
-  session->Enqueue(NewCreateRectangleCommand(id(), width, height));
+  session->Enqueue(NewCreateRectangleCmd(id(), width, height));
 }
 
 Rectangle::Rectangle(Rectangle&& moved) : Shape(std::move(moved)) {}
@@ -71,7 +71,7 @@
                                    float bottom_right_radius,
                                    float bottom_left_radius)
     : Shape(session) {
-  session->Enqueue(NewCreateRoundedRectangleCommand(
+  session->Enqueue(NewCreateRoundedRectangleCmd(
       id(), width, height, top_left_radius, top_right_radius,
       bottom_right_radius, bottom_left_radius));
 }
@@ -89,7 +89,7 @@
              fuchsia::images::ImageInfo info)
     : Resource(session), memory_offset_(memory_offset), info_(info) {
   session->Enqueue(
-      NewCreateImageCommand(id(), memory_id, memory_offset_, std::move(info)));
+      NewCreateImageCmd(id(), memory_id, memory_offset_, std::move(info)));
 }
 
 Image::Image(Image&& moved)
@@ -119,7 +119,7 @@
                size_t num_bytes)
     : Resource(session) {
   session->Enqueue(
-      NewCreateBufferCommand(id(), memory_id, memory_offset, num_bytes));
+      NewCreateBufferCmd(id(), memory_id, memory_offset, num_bytes));
 }
 
 Buffer::Buffer(Buffer&& moved) : Resource(std::move(moved)) {}
@@ -129,7 +129,7 @@
 Memory::Memory(Session* session, zx::vmo vmo,
                fuchsia::images::MemoryType memory_type)
     : Resource(session), memory_type_(memory_type) {
-  session->Enqueue(NewCreateMemoryCommand(id(), std::move(vmo), memory_type));
+  session->Enqueue(NewCreateMemoryCmd(id(), std::move(vmo), memory_type));
 }
 
 Memory::Memory(Memory&& moved)
@@ -138,7 +138,7 @@
 Memory::~Memory() = default;
 
 Mesh::Mesh(Session* session) : Shape(session) {
-  session->Enqueue(NewCreateMeshCommand(id()));
+  session->Enqueue(NewCreateMeshCmd(id()));
 }
 
 Mesh::Mesh(Mesh&& moved) : Shape(std::move(moved)) {}
@@ -155,14 +155,14 @@
                        const float bounding_box_max[3]) {
   FXL_DCHECK(session() == index_buffer.session() &&
              session() == vertex_buffer.session());
-  session()->Enqueue(NewBindMeshBuffersCommand(
+  session()->Enqueue(NewBindMeshBuffersCmd(
       id(), index_buffer.id(), index_format, index_offset, index_count,
       vertex_buffer.id(), std::move(vertex_format), vertex_offset, vertex_count,
       bounding_box_min, bounding_box_max));
 }
 
 Material::Material(Session* session) : Resource(session) {
-  session->Enqueue(NewCreateMaterialCommand(id()));
+  session->Enqueue(NewCreateMaterialCmd(id()));
 }
 
 Material::Material(Material&& moved) : Resource(std::move(moved)) {}
@@ -170,12 +170,12 @@
 Material::~Material() = default;
 
 void Material::SetTexture(uint32_t image_id) {
-  session()->Enqueue(NewSetTextureCommand(id(), image_id));
+  session()->Enqueue(NewSetTextureCmd(id(), image_id));
 }
 
 void Material::SetColor(uint8_t red, uint8_t green, uint8_t blue,
                         uint8_t alpha) {
-  session()->Enqueue(NewSetColorCommand(id(), red, green, blue, alpha));
+  session()->Enqueue(NewSetColorCmd(id(), red, green, blue, alpha));
 }
 
 Node::Node(Session* session) : Resource(session) {}
@@ -185,50 +185,50 @@
 Node::~Node() = default;
 
 void Node::SetTranslation(const float translation[3]) {
-  session()->Enqueue(NewSetTranslationCommand(id(), translation));
+  session()->Enqueue(NewSetTranslationCmd(id(), translation));
 }
 
 void Node::SetTranslation(uint32_t variable_id) {
-  session()->Enqueue(NewSetTranslationCommand(id(), variable_id));
+  session()->Enqueue(NewSetTranslationCmd(id(), variable_id));
 }
 
 void Node::SetScale(const float scale[3]) {
-  session()->Enqueue(NewSetScaleCommand(id(), scale));
+  session()->Enqueue(NewSetScaleCmd(id(), scale));
 }
 
 void Node::SetScale(uint32_t variable_id) {
-  session()->Enqueue(NewSetScaleCommand(id(), variable_id));
+  session()->Enqueue(NewSetScaleCmd(id(), variable_id));
 }
 
 void Node::SetRotation(const float quaternion[4]) {
-  session()->Enqueue(NewSetRotationCommand(id(), quaternion));
+  session()->Enqueue(NewSetRotationCmd(id(), quaternion));
 }
 
 void Node::SetRotation(uint32_t variable_id) {
-  session()->Enqueue(NewSetRotationCommand(id(), variable_id));
+  session()->Enqueue(NewSetRotationCmd(id(), variable_id));
 }
 
 void Node::SetAnchor(const float anchor[3]) {
-  session()->Enqueue(NewSetAnchorCommand(id(), anchor));
+  session()->Enqueue(NewSetAnchorCmd(id(), anchor));
 }
 
 void Node::SetAnchor(uint32_t variable_id) {
-  session()->Enqueue(NewSetAnchorCommand(id(), variable_id));
+  session()->Enqueue(NewSetAnchorCmd(id(), variable_id));
 }
 
 void Node::SetTag(uint32_t tag_value) {
-  session()->Enqueue(NewSetTagCommand(id(), tag_value));
+  session()->Enqueue(NewSetTagCmd(id(), tag_value));
 }
 
 void Node::SetHitTestBehavior(
     fuchsia::ui::gfx::HitTestBehavior hit_test_behavior) {
-  session()->Enqueue(NewSetHitTestBehaviorCommand(id(), hit_test_behavior));
+  session()->Enqueue(NewSetHitTestBehaviorCmd(id(), hit_test_behavior));
 }
 
-void Node::Detach() { session()->Enqueue(NewDetachCommand(id())); }
+void Node::Detach() { session()->Enqueue(NewDetachCmd(id())); }
 
 ShapeNode::ShapeNode(Session* session) : Node(session) {
-  session->Enqueue(NewCreateShapeNodeCommand(id()));
+  session->Enqueue(NewCreateShapeNodeCmd(id()));
 }
 
 ShapeNode::ShapeNode(ShapeNode&& moved) : Node(std::move(moved)) {}
@@ -236,11 +236,11 @@
 ShapeNode::~ShapeNode() = default;
 
 void ShapeNode::SetShape(uint32_t shape_id) {
-  session()->Enqueue(NewSetShapeCommand(id(), shape_id));
+  session()->Enqueue(NewSetShapeCmd(id(), shape_id));
 }
 
 void ShapeNode::SetMaterial(uint32_t material_id) {
-  session()->Enqueue(NewSetMaterialCommand(id(), material_id));
+  session()->Enqueue(NewSetMaterialCmd(id(), material_id));
 }
 
 ContainerNode::ContainerNode(Session* session) : Node(session) {}
@@ -250,25 +250,25 @@
 ContainerNode::~ContainerNode() = default;
 
 void ContainerNode::AddChild(uint32_t child_node_id) {
-  session()->Enqueue(NewAddChildCommand(id(), child_node_id));
+  session()->Enqueue(NewAddChildCmd(id(), child_node_id));
 }
 
 void ContainerNode::AddPart(uint32_t part_node_id) {
-  session()->Enqueue(NewAddPartCommand(id(), part_node_id));
+  session()->Enqueue(NewAddPartCmd(id(), part_node_id));
 }
 
 void ContainerNode::DetachChildren() {
-  session()->Enqueue(NewDetachChildrenCommand(id()));
+  session()->Enqueue(NewDetachChildrenCmd(id()));
 }
 
 EntityNode::EntityNode(Session* session) : ContainerNode(session) {
-  session->Enqueue(NewCreateEntityNodeCommand(id()));
+  session->Enqueue(NewCreateEntityNodeCmd(id()));
 }
 
 EntityNode::~EntityNode() = default;
 
 void EntityNode::SetClip(uint32_t clip_id, bool clip_to_self) {
-  session()->Enqueue(NewSetClipCommand(id(), clip_id, clip_to_self));
+  session()->Enqueue(NewSetClipCmd(id(), clip_id, clip_to_self));
 }
 
 ImportNode::ImportNode(Session* session) : ContainerNode(session) {}
@@ -281,20 +281,20 @@
 
 void ImportNode::Bind(zx::eventpair import_token) {
   FXL_DCHECK(!is_bound_);
-  session()->Enqueue(NewImportResourceCommand(
+  session()->Enqueue(NewImportResourceCmd(
       id(), fuchsia::ui::gfx::ImportSpec::NODE, std::move(import_token)));
   is_bound_ = true;
 }
 
 void ImportNode::BindAsRequest(zx::eventpair* out_export_token) {
   FXL_DCHECK(!is_bound_);
-  session()->Enqueue(NewImportResourceCommandAsRequest(
+  session()->Enqueue(NewImportResourceCmdAsRequest(
       id(), fuchsia::ui::gfx::ImportSpec::NODE, out_export_token));
   is_bound_ = true;
 }
 
 ClipNode::ClipNode(Session* session) : ContainerNode(session) {
-  session->Enqueue(NewCreateClipNodeCommand(id()));
+  session->Enqueue(NewCreateClipNodeCmd(id()));
 }
 
 ClipNode::ClipNode(ClipNode&& moved) : ContainerNode(std::move(moved)) {}
@@ -304,7 +304,7 @@
 OpacityNode::OpacityNode(Session* session) : ContainerNode(session) {
   // TODO(MZ-139): Opacities are not currently implemented. Create an
   // entity node for now.
-  session->Enqueue(NewCreateEntityNodeCommand(id()));
+  session->Enqueue(NewCreateEntityNodeCmd(id()));
 }
 
 OpacityNode::OpacityNode(OpacityNode&& moved)
@@ -323,7 +323,7 @@
 
 Variable::Variable(Session* session, fuchsia::ui::gfx::Value initial_value)
     : Resource(session) {
-  session->Enqueue(NewCreateVariableCommand(id(), std::move(initial_value)));
+  session->Enqueue(NewCreateVariableCmd(id(), std::move(initial_value)));
 }
 
 Variable::Variable(Variable&& moved) : Resource(std::move(moved)) {}
@@ -331,7 +331,7 @@
 Variable::~Variable() = default;
 
 Scene::Scene(Session* session) : ContainerNode(session) {
-  session->Enqueue(NewCreateSceneCommand(id()));
+  session->Enqueue(NewCreateSceneCmd(id()));
 }
 
 Scene::Scene(Scene&& moved) : ContainerNode(std::move(moved)) {}
@@ -339,28 +339,28 @@
 Scene::~Scene() = default;
 
 void Scene::AddLight(uint32_t light_id) {
-  session()->Enqueue(NewAddLightCommand(id(), light_id));
+  session()->Enqueue(NewAddLightCmd(id(), light_id));
 }
 
-void Scene::DetachLights() { session()->Enqueue(NewDetachLightsCommand(id())); }
+void Scene::DetachLights() { session()->Enqueue(NewDetachLightsCmd(id())); }
 
 void CameraBase::SetTransform(const float eye_position[3],
                               const float eye_look_at[3],
                               const float eye_up[3]) {
   session()->Enqueue(
-      NewSetCameraTransformCommand(id(), eye_position, eye_look_at, eye_up));
+      NewSetCameraTransformCmd(id(), eye_position, eye_look_at, eye_up));
 }
 
 void CameraBase::SetPoseBuffer(const Buffer& buffer, uint32_t num_entries,
                                uint64_t base_time, uint64_t time_interval) {
-  session()->Enqueue(scenic_lib::NewSetCameraPoseBufferCommand(
+  session()->Enqueue(scenic_lib::NewSetCameraPoseBufferCmd(
       id(), buffer.id(), num_entries, base_time, time_interval));
 }
 
 Camera::Camera(const Scene& scene) : Camera(scene.session(), scene.id()) {}
 
 Camera::Camera(Session* session, uint32_t scene_id) : CameraBase(session) {
-  session->Enqueue(NewCreateCameraCommand(id(), scene_id));
+  session->Enqueue(NewCreateCameraCmd(id(), scene_id));
 }
 
 Camera::Camera(Camera&& moved) : CameraBase(std::move(moved)) {}
@@ -368,7 +368,7 @@
 Camera::~Camera() = default;
 
 void Camera::SetProjection(const float fovy) {
-  session()->Enqueue(NewSetCameraProjectionCommand(id(), fovy));
+  session()->Enqueue(NewSetCameraProjectionCmd(id(), fovy));
 }
 
 StereoCamera::StereoCamera(const Scene& scene)
@@ -376,7 +376,7 @@
 
 StereoCamera::StereoCamera(Session* session, uint32_t scene_id)
     : CameraBase(session) {
-  session->Enqueue(NewCreateStereoCameraCommand(id(), scene_id));
+  session->Enqueue(NewCreateStereoCameraCmd(id(), scene_id));
 }
 
 StereoCamera::StereoCamera(StereoCamera&& moved)
@@ -386,12 +386,12 @@
 
 void StereoCamera::SetStereoProjection(const float left_projection[16],
                                        const float right_projection[16]) {
-  session()->Enqueue(NewSetStereoCameraProjectionCommand(id(), left_projection,
+  session()->Enqueue(NewSetStereoCameraProjectionCmd(id(), left_projection,
                                                          right_projection));
 }
 
 Renderer::Renderer(Session* session) : Resource(session) {
-  session->Enqueue(NewCreateRendererCommand(id()));
+  session->Enqueue(NewCreateRendererCmd(id()));
 }
 
 Renderer::Renderer(Renderer&& moved) : Resource(std::move(moved)) {}
@@ -399,11 +399,11 @@
 Renderer::~Renderer() = default;
 
 void Renderer::SetCamera(uint32_t camera_id) {
-  session()->Enqueue(NewSetCameraCommand(id(), camera_id));
+  session()->Enqueue(NewSetCameraCmd(id(), camera_id));
 }
 
 void Renderer::SetParam(fuchsia::ui::gfx::RendererParam param) {
-  session()->Enqueue(NewSetRendererParamCommand(id(), std::move(param)));
+  session()->Enqueue(NewSetRendererParamCmd(id(), std::move(param)));
 }
 
 void Renderer::SetShadowTechnique(fuchsia::ui::gfx::ShadowTechnique technique) {
@@ -413,11 +413,11 @@
 }
 
 void Renderer::SetDisableClipping(bool disable_clipping) {
-  session()->Enqueue(NewSetDisableClippingCommand(id(), disable_clipping));
+  session()->Enqueue(NewSetDisableClippingCmd(id(), disable_clipping));
 }
 
 Layer::Layer(Session* session) : Resource(session) {
-  session->Enqueue(NewCreateLayerCommand(id()));
+  session->Enqueue(NewCreateLayerCmd(id()));
 }
 
 Layer::Layer(Layer&& moved) : Resource(std::move(moved)) {}
@@ -425,15 +425,15 @@
 Layer::~Layer() = default;
 
 void Layer::SetRenderer(uint32_t renderer_id) {
-  session()->Enqueue(NewSetRendererCommand(id(), renderer_id));
+  session()->Enqueue(NewSetRendererCmd(id(), renderer_id));
 }
 
 void Layer::SetSize(const float size[2]) {
-  session()->Enqueue(NewSetSizeCommand(id(), size));
+  session()->Enqueue(NewSetSizeCmd(id(), size));
 }
 
 LayerStack::LayerStack(Session* session) : Resource(session) {
-  session->Enqueue(NewCreateLayerStackCommand(id()));
+  session->Enqueue(NewCreateLayerStackCmd(id()));
 }
 
 LayerStack::LayerStack(LayerStack&& moved) : Resource(std::move(moved)) {}
@@ -441,19 +441,19 @@
 LayerStack::~LayerStack() = default;
 
 void LayerStack::AddLayer(uint32_t layer_id) {
-  session()->Enqueue(NewAddLayerCommand(id(), layer_id));
+  session()->Enqueue(NewAddLayerCmd(id(), layer_id));
 }
 
 void LayerStack::RemoveLayer(uint32_t layer_id) {
-  session()->Enqueue(NewRemoveLayerCommand(id(), layer_id));
+  session()->Enqueue(NewRemoveLayerCmd(id(), layer_id));
 }
 
 void LayerStack::RemoveAllLayers() {
-  session()->Enqueue(NewRemoveAllLayersCommand(id()));
+  session()->Enqueue(NewRemoveAllLayersCmd(id()));
 }
 
 DisplayCompositor::DisplayCompositor(Session* session) : Resource(session) {
-  session->Enqueue(NewCreateDisplayCompositorCommand(id()));
+  session->Enqueue(NewCreateDisplayCompositorCmd(id()));
 }
 
 DisplayCompositor::DisplayCompositor(DisplayCompositor&& moved)
@@ -462,7 +462,7 @@
 DisplayCompositor::~DisplayCompositor() = default;
 
 void DisplayCompositor::SetLayerStack(uint32_t layer_stack_id) {
-  session()->Enqueue(NewSetLayerStackCommand(id(), layer_stack_id));
+  session()->Enqueue(NewSetLayerStackCmd(id(), layer_stack_id));
 }
 
 Light::Light(Session* session) : Resource(session) {}
@@ -472,17 +472,17 @@
 Light::~Light() = default;
 
 void Light::SetColor(const float rgb[3]) {
-  session()->Enqueue(NewSetLightColorCommand(id(), rgb));
+  session()->Enqueue(NewSetLightColorCmd(id(), rgb));
 }
 
 void Light::SetColor(uint32_t variable_id) {
-  session()->Enqueue(NewSetLightColorCommand(id(), variable_id));
+  session()->Enqueue(NewSetLightColorCmd(id(), variable_id));
 }
 
-void Light::Detach() { session()->Enqueue(NewDetachLightCommand(id())); }
+void Light::Detach() { session()->Enqueue(NewDetachLightCmd(id())); }
 
 AmbientLight::AmbientLight(Session* session) : Light(session) {
-  session->Enqueue(NewCreateAmbientLightCommand(id()));
+  session->Enqueue(NewCreateAmbientLightCmd(id()));
 }
 
 AmbientLight::AmbientLight(AmbientLight&& moved) : Light(std::move(moved)) {}
@@ -490,7 +490,7 @@
 AmbientLight::~AmbientLight() = default;
 
 DirectionalLight::DirectionalLight(Session* session) : Light(session) {
-  session->Enqueue(NewCreateDirectionalLightCommand(id()));
+  session->Enqueue(NewCreateDirectionalLightCmd(id()));
 }
 
 DirectionalLight::DirectionalLight(DirectionalLight&& moved)
@@ -499,11 +499,11 @@
 DirectionalLight::~DirectionalLight() = default;
 
 void DirectionalLight::SetDirection(const float direction[3]) {
-  session()->Enqueue(NewSetLightDirectionCommand(id(), direction));
+  session()->Enqueue(NewSetLightDirectionCmd(id(), direction));
 }
 
 void DirectionalLight::SetDirection(uint32_t variable_id) {
-  session()->Enqueue(NewSetLightDirectionCommand(id(), variable_id));
+  session()->Enqueue(NewSetLightDirectionCmd(id(), variable_id));
 }
 
 }  // namespace scenic_lib
diff --git a/public/lib/ui/scenic/client/resources.h b/public/lib/ui/scenic/client/resources.h
index ddfedf2..83e044c 100644
--- a/public/lib/ui/scenic/client/resources.h
+++ b/public/lib/ui/scenic/client/resources.h
@@ -176,7 +176,7 @@
   ~Mesh();
 
   // These arguments are documented in commands.fidl; see
-  // BindMeshBuffersCommand.
+  // BindMeshBuffersCmd.
   void BindBuffers(const Buffer& index_buffer,
                    fuchsia::ui::gfx::MeshIndexFormat index_format,
                    uint64_t index_offset, uint32_t index_count,
diff --git a/public/lib/ui/scenic/client/session.cc b/public/lib/ui/scenic/client/session.cc
index ab15371..d9d48e2 100644
--- a/public/lib/ui/scenic/client/session.cc
+++ b/public/lib/ui/scenic/client/session.cc
@@ -4,6 +4,7 @@
 
 #include "lib/ui/scenic/client/session.h"
 
+#include "lib/fxl/functional/make_copyable.h"
 #include "lib/fxl/logging.h"
 #include "lib/ui/scenic/fidl_helpers.h"
 
@@ -44,7 +45,7 @@
 
 void Session::ReleaseResource(uint32_t resource_id) {
   resource_count_--;
-  Enqueue(NewReleaseResourceCommand(resource_id));
+  Enqueue(NewReleaseResourceCmd(resource_id));
 }
 
 void Session::Enqueue(fuchsia::ui::gfx::Command command) {
@@ -83,7 +84,8 @@
   if (release_fences_.is_null())
     release_fences_.resize(0u);
   session_->Present(presentation_time, std::move(acquire_fences_),
-                    std::move(release_fences_), std::move(callback));
+                    std::move(release_fences_),
+                    fxl::MakeCopyable(std::move(callback)));
 }
 
 void Session::HitTest(uint32_t node_id, const float ray_origin[3],
@@ -99,7 +101,8 @@
   ray_direction_vec.z = ray_direction[2];
 
   session_->HitTest(node_id, std::move(ray_origin_vec),
-                    std::move(ray_direction_vec), std::move(callback));
+                    std::move(ray_direction_vec),
+                    fxl::MakeCopyable(std::move(callback)));
 }
 
 void Session::HitTestDeviceRay(
@@ -116,7 +119,8 @@
   ray_direction_vec.z = ray_direction[2];
 
   session_->HitTestDeviceRay(std::move(ray_origin_vec),
-                             std::move(ray_direction_vec), callback);
+                             std::move(ray_direction_vec),
+                             fxl::MakeCopyable(callback));
 }
 
 void Session::OnError(fidl::StringPtr error) {
diff --git a/public/lib/ui/scenic/client/session.h b/public/lib/ui/scenic/client/session.h
index 9f2657f..b2b5b89 100644
--- a/public/lib/ui/scenic/client/session.h
+++ b/public/lib/ui/scenic/client/session.h
@@ -5,8 +5,7 @@
 #ifndef LIB_UI_SCENIC_CLIENT_SESSION_H_
 #define LIB_UI_SCENIC_CLIENT_SESSION_H_
 
-#include <functional>
-
+#include <lib/fit/function.h>
 #include <lib/zx/event.h>
 
 #include <fuchsia/images/cpp/fidl.h>
@@ -14,7 +13,6 @@
 #include <fuchsia/ui/scenic/cpp/fidl.h>
 
 #include "lib/fidl/cpp/binding.h"
-#include "lib/fxl/functional/closure.h"
 #include "lib/fxl/macros.h"
 
 namespace scenic_lib {
@@ -27,15 +25,15 @@
   // Provides timing information about a presentation request which has
   // been applied by the scene manager.
   using PresentCallback =
-      std::function<void(fuchsia::images::PresentationInfo info)>;
+      fit::function<void(fuchsia::images::PresentationInfo info)>;
 
   // Provide information about hits.
   using HitTestCallback =
-      std::function<void(fidl::VectorPtr<fuchsia::ui::gfx::Hit> hits)>;
+      fit::function<void(fidl::VectorPtr<fuchsia::ui::gfx::Hit> hits)>;
 
   // Called when session events are received.
   using EventHandler =
-      std::function<void(fidl::VectorPtr<fuchsia::ui::scenic::Event>)>;
+      fit::function<void(fidl::VectorPtr<fuchsia::ui::scenic::Event>)>;
 
   // Wraps the provided session and session listener.
   // The listener is optional.
@@ -53,7 +51,7 @@
   ~Session();
 
   // Sets a callback which is invoked if the session dies.
-  void set_error_handler(fxl::Closure closure) {
+  void set_error_handler(fit::closure closure) {
     session_.set_error_handler(std::move(closure));
   }
 
diff --git a/public/lib/ui/scenic/fidl/BUILD.gn b/public/lib/ui/scenic/fidl/BUILD.gn
index 84007a2..d57bd9b 100644
--- a/public/lib/ui/scenic/fidl/BUILD.gn
+++ b/public/lib/ui/scenic/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.ui.scenic"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/scenic/fidl/session.fidl b/public/lib/ui/scenic/fidl/session.fidl
index be29edd..1eebd9d 100644
--- a/public/lib/ui/scenic/fidl/session.fidl
+++ b/public/lib/ui/scenic/fidl/session.fidl
@@ -140,6 +140,6 @@
   1: OnError(string error);
 
   // Called to deliver a batch of one or more events to the listener.
-  // Use |SetEventMaskCommand| to enable event delivery for a resource.
+  // Use |SetEventMaskCmd| to enable event delivery for a resource.
   2: OnEvent(vector<Event> events);
 };
diff --git a/public/lib/ui/scenic/fidl_helpers.cc b/public/lib/ui/scenic/fidl_helpers.cc
index feaa83f..18ca9eb 100644
--- a/public/lib/ui/scenic/fidl_helpers.cc
+++ b/public/lib/ui/scenic/fidl_helpers.cc
@@ -26,9 +26,9 @@
 }
 
 // Helper function for all resource creation functions.
-static fuchsia::ui::gfx::Command NewCreateResourceCommand(
+static fuchsia::ui::gfx::Command NewCreateResourceCmd(
     uint32_t id, fuchsia::ui::gfx::ResourceArgs resource) {
-  fuchsia::ui::gfx::CreateResourceCommand create_resource;
+  fuchsia::ui::gfx::CreateResourceCmd create_resource;
   create_resource.id = id;
   create_resource.resource = std::move(resource);
 
@@ -38,7 +38,7 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewCreateMemoryCommand(
+fuchsia::ui::gfx::Command NewCreateMemoryCmd(
     uint32_t id, zx::vmo vmo, fuchsia::images::MemoryType memory_type) {
   fuchsia::ui::gfx::MemoryArgs memory;
   memory.vmo = std::move(vmo);
@@ -47,10 +47,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_memory(std::move(memory));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateImageCommand(
+fuchsia::ui::gfx::Command NewCreateImageCmd(
     uint32_t id, uint32_t memory_id, uint32_t memory_offset,
     fuchsia::images::ImageInfo info) {
   fuchsia::ui::gfx::ImageArgs image;
@@ -61,20 +61,20 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_image(std::move(image));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateImagePipeCommand(
+fuchsia::ui::gfx::Command NewCreateImagePipeCmd(
     uint32_t id, ::fidl::InterfaceRequest<fuchsia::images::ImagePipe> request) {
   fuchsia::ui::gfx::ImagePipeArgs image_pipe;
   image_pipe.image_pipe_request = std::move(request);
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_image_pipe(std::move(image_pipe));
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateImageCommand(
+fuchsia::ui::gfx::Command NewCreateImageCmd(
     uint32_t id, uint32_t memory_id, uint32_t memory_offset,
     fuchsia::images::PixelFormat format,
     fuchsia::images::ColorSpace color_space, fuchsia::images::Tiling tiling,
@@ -86,10 +86,10 @@
   info.width = width;
   info.height = height;
   info.stride = stride;
-  return NewCreateImageCommand(id, memory_id, memory_offset, std::move(info));
+  return NewCreateImageCmd(id, memory_id, memory_offset, std::move(info));
 }
 
-fuchsia::ui::gfx::Command NewCreateBufferCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateBufferCmd(uint32_t id,
                                                  uint32_t memory_id,
                                                  uint32_t memory_offset,
                                                  uint32_t num_bytes) {
@@ -101,46 +101,46 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_buffer(std::move(buffer));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateDisplayCompositorCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateDisplayCompositorCmd(uint32_t id) {
   fuchsia::ui::gfx::DisplayCompositorArgs display_compositor;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_display_compositor(std::move(display_compositor));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateLayerStackCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateLayerStackCmd(uint32_t id) {
   fuchsia::ui::gfx::LayerStackArgs layer_stack;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_layer_stack(std::move(layer_stack));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateLayerCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateLayerCmd(uint32_t id) {
   fuchsia::ui::gfx::LayerArgs layer;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_layer(std::move(layer));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateSceneCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateSceneCmd(uint32_t id) {
   fuchsia::ui::gfx::SceneArgs scene;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_scene(std::move(scene));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateCameraCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateCameraCmd(uint32_t id,
                                                  uint32_t scene_id) {
   fuchsia::ui::gfx::CameraArgs camera;
   camera.scene_id = scene_id;
@@ -148,10 +148,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_camera(std::move(camera));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateStereoCameraCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateStereoCameraCmd(uint32_t id,
                                                        uint32_t scene_id) {
   fuchsia::ui::gfx::StereoCameraArgs stereo_camera;
   stereo_camera.scene_id = scene_id;
@@ -159,36 +159,36 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_stereo_camera(std::move(stereo_camera));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateRendererCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateRendererCmd(uint32_t id) {
   fuchsia::ui::gfx::RendererArgs renderer;
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_renderer(std::move(renderer));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateAmbientLightCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateAmbientLightCmd(uint32_t id) {
   fuchsia::ui::gfx::AmbientLightArgs ambient_light;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_ambient_light(std::move(ambient_light));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateDirectionalLightCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateDirectionalLightCmd(uint32_t id) {
   fuchsia::ui::gfx::DirectionalLightArgs directional_light;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_directional_light(std::move(directional_light));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateCircleCommand(uint32_t id, float radius) {
+fuchsia::ui::gfx::Command NewCreateCircleCmd(uint32_t id, float radius) {
   fuchsia::ui::gfx::Value radius_value;
   radius_value.set_vector1(radius);
 
@@ -198,10 +198,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_circle(std::move(circle));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateRectangleCommand(uint32_t id, float width,
+fuchsia::ui::gfx::Command NewCreateRectangleCmd(uint32_t id, float width,
                                                     float height) {
   fuchsia::ui::gfx::Value width_value;
   width_value.set_vector1(width);
@@ -216,10 +216,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_rectangle(std::move(rectangle));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateRoundedRectangleCommand(
+fuchsia::ui::gfx::Command NewCreateRoundedRectangleCmd(
     uint32_t id, float width, float height, float top_left_radius,
     float top_right_radius, float bottom_right_radius,
     float bottom_left_radius) {
@@ -252,10 +252,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_rounded_rectangle(std::move(rectangle));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateVarCircleCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateVarCircleCmd(uint32_t id,
                                                     uint32_t radius_var_id,
                                                     uint32_t height_var_id) {
   fuchsia::ui::gfx::Value radius_value;
@@ -267,10 +267,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_circle(std::move(circle));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateVarRectangleCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateVarRectangleCmd(uint32_t id,
                                                        uint32_t width_var_id,
                                                        uint32_t height_var_id) {
   fuchsia::ui::gfx::Value width_value;
@@ -286,10 +286,10 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_rectangle(std::move(rectangle));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateVarRoundedRectangleCommand(
+fuchsia::ui::gfx::Command NewCreateVarRoundedRectangleCmd(
     uint32_t id, uint32_t width_var_id, uint32_t height_var_id,
     uint32_t top_left_radius_var_id, uint32_t top_right_radius_var_id,
     uint32_t bottom_left_radius_var_id, uint32_t bottom_right_radius_var_id) {
@@ -322,55 +322,55 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_rounded_rectangle(std::move(rectangle));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateMeshCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateMeshCmd(uint32_t id) {
   fuchsia::ui::gfx::MeshArgs mesh;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_mesh(std::move(mesh));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateMaterialCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateMaterialCmd(uint32_t id) {
   fuchsia::ui::gfx::MaterialArgs material;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_material(std::move(material));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateClipNodeCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateClipNodeCmd(uint32_t id) {
   fuchsia::ui::gfx::ClipNodeArgs node;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_clip_node(std::move(node));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateEntityNodeCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateEntityNodeCmd(uint32_t id) {
   fuchsia::ui::gfx::EntityNodeArgs node;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_entity_node(std::move(node));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateShapeNodeCommand(uint32_t id) {
+fuchsia::ui::gfx::Command NewCreateShapeNodeCmd(uint32_t id) {
   fuchsia::ui::gfx::ShapeNodeArgs node;
 
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_shape_node(std::move(node));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewCreateVariableCommand(
+fuchsia::ui::gfx::Command NewCreateVariableCmd(
     uint32_t id, fuchsia::ui::gfx::Value value) {
   fuchsia::ui::gfx::VariableArgs variable;
   switch (value.Which()) {
@@ -415,11 +415,11 @@
   fuchsia::ui::gfx::ResourceArgs resource;
   resource.set_variable(std::move(variable));
 
-  return NewCreateResourceCommand(id, std::move(resource));
+  return NewCreateResourceCmd(id, std::move(resource));
 }
 
-fuchsia::ui::gfx::Command NewReleaseResourceCommand(uint32_t id) {
-  fuchsia::ui::gfx::ReleaseResourceCommand release_resource;
+fuchsia::ui::gfx::Command NewReleaseResourceCmd(uint32_t id) {
+  fuchsia::ui::gfx::ReleaseResourceCmd release_resource;
   release_resource.id = id;
 
   fuchsia::ui::gfx::Command command;
@@ -428,11 +428,11 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewExportResourceCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewExportResourceCmd(uint32_t resource_id,
                                                    zx::eventpair export_token) {
   FXL_DCHECK(export_token);
 
-  fuchsia::ui::gfx::ExportResourceCommand export_resource;
+  fuchsia::ui::gfx::ExportResourceCmd export_resource;
   export_resource.id = resource_id;
   export_resource.token = std::move(export_token);
 
@@ -442,12 +442,12 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewImportResourceCommand(
+fuchsia::ui::gfx::Command NewImportResourceCmd(
     uint32_t resource_id, fuchsia::ui::gfx::ImportSpec spec,
     zx::eventpair import_token) {
   FXL_DCHECK(import_token);
 
-  fuchsia::ui::gfx::ImportResourceCommand import_resource;
+  fuchsia::ui::gfx::ImportResourceCmd import_resource;
   import_resource.id = resource_id;
   import_resource.token = std::move(import_token);
   import_resource.spec = spec;
@@ -458,7 +458,7 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewExportResourceCommandAsRequest(
+fuchsia::ui::gfx::Command NewExportResourceCmdAsRequest(
     uint32_t resource_id, zx::eventpair* out_import_token) {
   FXL_DCHECK(out_import_token);
   FXL_DCHECK(!*out_import_token);
@@ -467,10 +467,10 @@
   zx_status_t status =
       zx::eventpair::create(0u, &export_token, out_import_token);
   FXL_CHECK(status == ZX_OK) << "event pair create failed: status=" << status;
-  return NewExportResourceCommand(resource_id, std::move(export_token));
+  return NewExportResourceCmd(resource_id, std::move(export_token));
 }
 
-fuchsia::ui::gfx::Command NewImportResourceCommandAsRequest(
+fuchsia::ui::gfx::Command NewImportResourceCmdAsRequest(
     uint32_t resource_id, fuchsia::ui::gfx::ImportSpec import_spec,
     zx::eventpair* out_export_token) {
   FXL_DCHECK(out_export_token);
@@ -480,13 +480,13 @@
   zx_status_t status =
       zx::eventpair::create(0u, &import_token, out_export_token);
   FXL_CHECK(status == ZX_OK) << "event pair create failed: status=" << status;
-  return NewImportResourceCommand(resource_id, import_spec,
+  return NewImportResourceCmd(resource_id, import_spec,
                                   std::move(import_token));
 }
 
-fuchsia::ui::gfx::Command NewAddChildCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewAddChildCmd(uint32_t node_id,
                                              uint32_t child_id) {
-  fuchsia::ui::gfx::AddChildCommand add_child;
+  fuchsia::ui::gfx::AddChildCmd add_child;
   add_child.node_id = node_id;
   add_child.child_id = child_id;
 
@@ -496,9 +496,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewAddPartCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewAddPartCmd(uint32_t node_id,
                                             uint32_t part_id) {
-  fuchsia::ui::gfx::AddPartCommand add_part;
+  fuchsia::ui::gfx::AddPartCmd add_part;
   add_part.node_id = node_id;
   add_part.part_id = part_id;
 
@@ -508,8 +508,8 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewDetachCommand(uint32_t id) {
-  fuchsia::ui::gfx::DetachCommand detach;
+fuchsia::ui::gfx::Command NewDetachCmd(uint32_t id) {
+  fuchsia::ui::gfx::DetachCmd detach;
   detach.id = id;
 
   fuchsia::ui::gfx::Command command;
@@ -518,8 +518,8 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewDetachChildrenCommand(uint32_t node_id) {
-  fuchsia::ui::gfx::DetachChildrenCommand detach_children;
+fuchsia::ui::gfx::Command NewDetachChildrenCmd(uint32_t node_id) {
+  fuchsia::ui::gfx::DetachChildrenCmd detach_children;
   detach_children.node_id = node_id;
 
   fuchsia::ui::gfx::Command command;
@@ -528,9 +528,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetTranslationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetTranslationCmd(uint32_t node_id,
                                                    const float translation[3]) {
-  fuchsia::ui::gfx::SetTranslationCommand set_translation;
+  fuchsia::ui::gfx::SetTranslationCmd set_translation;
   set_translation.id = node_id;
   set_translation.value = NewVector3Value(translation);
 
@@ -540,9 +540,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetTranslationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetTranslationCmd(uint32_t node_id,
                                                    uint32_t variable_id) {
-  fuchsia::ui::gfx::SetTranslationCommand set_translation;
+  fuchsia::ui::gfx::SetTranslationCmd set_translation;
   set_translation.id = node_id;
   set_translation.value = NewVector3Value(variable_id);
 
@@ -552,9 +552,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetScaleCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetScaleCmd(uint32_t node_id,
                                              const float scale[3]) {
-  fuchsia::ui::gfx::SetScaleCommand set_scale;
+  fuchsia::ui::gfx::SetScaleCmd set_scale;
   set_scale.id = node_id;
   set_scale.value = NewVector3Value(scale);
 
@@ -564,9 +564,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetScaleCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetScaleCmd(uint32_t node_id,
                                              uint32_t variable_id) {
-  fuchsia::ui::gfx::SetScaleCommand set_scale;
+  fuchsia::ui::gfx::SetScaleCmd set_scale;
   set_scale.id = node_id;
   set_scale.value = NewVector3Value(variable_id);
 
@@ -576,9 +576,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetRotationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetRotationCmd(uint32_t node_id,
                                                 const float quaternion[4]) {
-  fuchsia::ui::gfx::SetRotationCommand set_rotation;
+  fuchsia::ui::gfx::SetRotationCmd set_rotation;
   set_rotation.id = node_id;
   set_rotation.value = NewQuaternionValue(quaternion);
 
@@ -588,9 +588,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetRotationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetRotationCmd(uint32_t node_id,
                                                 uint32_t variable_id) {
-  fuchsia::ui::gfx::SetRotationCommand set_rotation;
+  fuchsia::ui::gfx::SetRotationCmd set_rotation;
   set_rotation.id = node_id;
   set_rotation.value = NewQuaternionValue(variable_id);
 
@@ -600,9 +600,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetAnchorCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetAnchorCmd(uint32_t node_id,
                                               const float anchor[3]) {
-  fuchsia::ui::gfx::SetAnchorCommand set_anchor;
+  fuchsia::ui::gfx::SetAnchorCmd set_anchor;
   set_anchor.id = node_id;
   set_anchor.value = NewVector3Value(anchor);
 
@@ -612,9 +612,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetAnchorCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetAnchorCmd(uint32_t node_id,
                                               uint32_t variable_id) {
-  fuchsia::ui::gfx::SetAnchorCommand set_anchor;
+  fuchsia::ui::gfx::SetAnchorCmd set_anchor;
   set_anchor.id = node_id;
   set_anchor.value = NewVector3Value(variable_id);
 
@@ -624,9 +624,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetShapeCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetShapeCmd(uint32_t node_id,
                                              uint32_t shape_id) {
-  fuchsia::ui::gfx::SetShapeCommand set_shape;
+  fuchsia::ui::gfx::SetShapeCmd set_shape;
   set_shape.node_id = node_id;
   set_shape.shape_id = shape_id;
 
@@ -636,9 +636,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetMaterialCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetMaterialCmd(uint32_t node_id,
                                                 uint32_t material_id) {
-  fuchsia::ui::gfx::SetMaterialCommand set_material;
+  fuchsia::ui::gfx::SetMaterialCmd set_material;
   set_material.node_id = node_id;
   set_material.material_id = material_id;
 
@@ -648,9 +648,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetClipCommand(uint32_t node_id, uint32_t clip_id,
+fuchsia::ui::gfx::Command NewSetClipCmd(uint32_t node_id, uint32_t clip_id,
                                             bool clip_to_self) {
-  fuchsia::ui::gfx::SetClipCommand set_clip;
+  fuchsia::ui::gfx::SetClipCmd set_clip;
   set_clip.node_id = node_id;
   set_clip.clip_id = clip_id;
   set_clip.clip_to_self = clip_to_self;
@@ -661,9 +661,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetTagCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetTagCmd(uint32_t node_id,
                                            uint32_t tag_value) {
-  fuchsia::ui::gfx::SetTagCommand set_tag;
+  fuchsia::ui::gfx::SetTagCmd set_tag;
   set_tag.node_id = node_id;
   set_tag.tag_value = tag_value;
 
@@ -673,9 +673,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetHitTestBehaviorCommand(
+fuchsia::ui::gfx::Command NewSetHitTestBehaviorCmd(
     uint32_t node_id, fuchsia::ui::gfx::HitTestBehavior hit_test_behavior) {
-  fuchsia::ui::gfx::SetHitTestBehaviorCommand set_hit_test_behavior;
+  fuchsia::ui::gfx::SetHitTestBehaviorCmd set_hit_test_behavior;
   set_hit_test_behavior.node_id = node_id;
   set_hit_test_behavior.hit_test_behavior = hit_test_behavior;
 
@@ -685,9 +685,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetCameraCommand(uint32_t renderer_id,
+fuchsia::ui::gfx::Command NewSetCameraCmd(uint32_t renderer_id,
                                               uint32_t camera_id) {
-  fuchsia::ui::gfx::SetCameraCommand set_camera;
+  fuchsia::ui::gfx::SetCameraCmd set_camera;
   set_camera.renderer_id = renderer_id;
   set_camera.camera_id = camera_id;
 
@@ -696,9 +696,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetTextureCommand(uint32_t material_id,
+fuchsia::ui::gfx::Command NewSetTextureCmd(uint32_t material_id,
                                                uint32_t texture_id) {
-  fuchsia::ui::gfx::SetTextureCommand set_texture;
+  fuchsia::ui::gfx::SetTextureCmd set_texture;
   set_texture.material_id = material_id;
   set_texture.texture_id = texture_id;
 
@@ -707,7 +707,7 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetColorCommand(uint32_t material_id, uint8_t red,
+fuchsia::ui::gfx::Command NewSetColorCmd(uint32_t material_id, uint8_t red,
                                              uint8_t green, uint8_t blue,
                                              uint8_t alpha) {
   fuchsia::ui::gfx::ColorRgbaValue color;
@@ -716,7 +716,7 @@
   color.value.blue = blue;
   color.value.alpha = alpha;
   color.variable_id = 0;
-  fuchsia::ui::gfx::SetColorCommand set_color;
+  fuchsia::ui::gfx::SetColorCmd set_color;
   set_color.material_id = material_id;
   set_color.color = std::move(color);
 
@@ -737,14 +737,14 @@
   return vertex_format;
 }
 
-fuchsia::ui::gfx::Command NewBindMeshBuffersCommand(
+fuchsia::ui::gfx::Command NewBindMeshBuffersCmd(
     uint32_t mesh_id, uint32_t index_buffer_id,
     fuchsia::ui::gfx::MeshIndexFormat index_format, uint64_t index_offset,
     uint32_t index_count, uint32_t vertex_buffer_id,
     fuchsia::ui::gfx::MeshVertexFormat vertex_format, uint64_t vertex_offset,
     uint32_t vertex_count, const float bounding_box_min[3],
     const float bounding_box_max[3]) {
-  fuchsia::ui::gfx::BindMeshBuffersCommand bind_mesh_buffers;
+  fuchsia::ui::gfx::BindMeshBuffersCmd bind_mesh_buffers;
   bind_mesh_buffers.mesh_id = mesh_id;
   bind_mesh_buffers.index_buffer_id = index_buffer_id;
   bind_mesh_buffers.index_format = index_format;
@@ -768,9 +768,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewAddLayerCommand(uint32_t layer_stack_id,
+fuchsia::ui::gfx::Command NewAddLayerCmd(uint32_t layer_stack_id,
                                              uint32_t layer_id) {
-  fuchsia::ui::gfx::AddLayerCommand add_layer;
+  fuchsia::ui::gfx::AddLayerCmd add_layer;
   add_layer.layer_stack_id = layer_stack_id;
   add_layer.layer_id = layer_id;
 
@@ -779,9 +779,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewRemoveLayerCommand(uint32_t layer_stack_id,
+fuchsia::ui::gfx::Command NewRemoveLayerCmd(uint32_t layer_stack_id,
                                                 uint32_t layer_id) {
-  fuchsia::ui::gfx::RemoveLayerCommand remove_layer;
+  fuchsia::ui::gfx::RemoveLayerCmd remove_layer;
   remove_layer.layer_stack_id = layer_stack_id;
   remove_layer.layer_id = layer_id;
 
@@ -790,8 +790,8 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewRemoveAllLayersCommand(uint32_t layer_stack_id) {
-  fuchsia::ui::gfx::RemoveAllLayersCommand remove_all_layers;
+fuchsia::ui::gfx::Command NewRemoveAllLayersCmd(uint32_t layer_stack_id) {
+  fuchsia::ui::gfx::RemoveAllLayersCmd remove_all_layers;
   remove_all_layers.layer_stack_id = layer_stack_id;
 
   fuchsia::ui::gfx::Command command;
@@ -799,9 +799,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetLayerStackCommand(uint32_t compositor_id,
+fuchsia::ui::gfx::Command NewSetLayerStackCmd(uint32_t compositor_id,
                                                   uint32_t layer_stack_id) {
-  fuchsia::ui::gfx::SetLayerStackCommand set_layer_stack;
+  fuchsia::ui::gfx::SetLayerStackCmd set_layer_stack;
   set_layer_stack.compositor_id = compositor_id;
   set_layer_stack.layer_stack_id = layer_stack_id;
 
@@ -810,9 +810,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetRendererCommand(uint32_t layer_id,
+fuchsia::ui::gfx::Command NewSetRendererCmd(uint32_t layer_id,
                                                 uint32_t renderer_id) {
-  fuchsia::ui::gfx::SetRendererCommand set_renderer;
+  fuchsia::ui::gfx::SetRendererCmd set_renderer;
   set_renderer.layer_id = layer_id;
   set_renderer.renderer_id = renderer_id;
 
@@ -821,9 +821,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetRendererParamCommand(
+fuchsia::ui::gfx::Command NewSetRendererParamCmd(
     uint32_t renderer_id, fuchsia::ui::gfx::RendererParam param) {
-  fuchsia::ui::gfx::SetRendererParamCommand param_command;
+  fuchsia::ui::gfx::SetRendererParamCmd param_command;
   param_command.renderer_id = renderer_id;
   param_command.param = std::move(param);
 
@@ -832,9 +832,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetSizeCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetSizeCmd(uint32_t node_id,
                                             const float size[2]) {
-  fuchsia::ui::gfx::SetSizeCommand set_size;
+  fuchsia::ui::gfx::SetSizeCmd set_size;
   set_size.id = node_id;
   auto& value = set_size.value.value;
   value.x = size[0];
@@ -847,10 +847,10 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetCameraTransformCommand(
+fuchsia::ui::gfx::Command NewSetCameraTransformCmd(
     uint32_t camera_id, const float eye_position[3], const float eye_look_at[3],
     const float eye_up[3]) {
-  fuchsia::ui::gfx::SetCameraTransformCommand set_command;
+  fuchsia::ui::gfx::SetCameraTransformCmd set_command;
   set_command.camera_id = camera_id;
   set_command.eye_position = NewVector3Value(eye_position);
   set_command.eye_look_at = NewVector3Value(eye_look_at);
@@ -862,9 +862,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetCameraProjectionCommand(uint32_t camera_id,
+fuchsia::ui::gfx::Command NewSetCameraProjectionCmd(uint32_t camera_id,
                                                         const float fovy) {
-  fuchsia::ui::gfx::SetCameraProjectionCommand set_command;
+  fuchsia::ui::gfx::SetCameraProjectionCmd set_command;
   set_command.camera_id = camera_id;
   set_command.fovy = NewFloatValue(fovy);
 
@@ -874,10 +874,10 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetStereoCameraProjectionCommand(
+fuchsia::ui::gfx::Command NewSetStereoCameraProjectionCmd(
     uint32_t camera_id, const float left_projection[16],
     const float right_projection[16]) {
-  fuchsia::ui::gfx::SetStereoCameraProjectionCommand set_command;
+  fuchsia::ui::gfx::SetStereoCameraProjectionCmd set_command;
   set_command.camera_id = camera_id;
   set_command.left_projection = NewMatrix4Value(left_projection);
   set_command.right_projection = NewMatrix4Value(right_projection);
@@ -888,10 +888,10 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetCameraPoseBufferCommand(
+fuchsia::ui::gfx::Command NewSetCameraPoseBufferCmd(
     uint32_t camera_id, uint32_t buffer_id, uint32_t num_entries,
     uint64_t base_time, uint64_t time_interval) {
-  fuchsia::ui::gfx::SetCameraPoseBufferCommand set_command;
+  fuchsia::ui::gfx::SetCameraPoseBufferCmd set_command;
   set_command.camera_id = camera_id;
   set_command.buffer_id = buffer_id;
   set_command.num_entries = num_entries;
@@ -904,9 +904,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetLightColorCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightColorCmd(uint32_t light_id,
                                                   const float rgb[3]) {
-  fuchsia::ui::gfx::SetLightColorCommand set_command;
+  fuchsia::ui::gfx::SetLightColorCmd set_command;
   set_command.light_id = light_id;
   set_command.color = NewColorRgbValue(rgb[0], rgb[1], rgb[2]);
 
@@ -916,9 +916,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetLightColorCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightColorCmd(uint32_t light_id,
                                                   uint32_t variable_id) {
-  fuchsia::ui::gfx::SetLightColorCommand set_command;
+  fuchsia::ui::gfx::SetLightColorCmd set_command;
   set_command.light_id = light_id;
   set_command.color = NewColorRgbValue(variable_id);
 
@@ -928,9 +928,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetLightDirectionCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightDirectionCmd(uint32_t light_id,
                                                       const float dir[3]) {
-  fuchsia::ui::gfx::SetLightDirectionCommand set_command;
+  fuchsia::ui::gfx::SetLightDirectionCmd set_command;
   set_command.light_id = light_id;
   set_command.direction = NewVector3Value(dir);
 
@@ -940,9 +940,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetLightDirectionCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightDirectionCmd(uint32_t light_id,
                                                       uint32_t variable_id) {
-  fuchsia::ui::gfx::SetLightDirectionCommand set_command;
+  fuchsia::ui::gfx::SetLightDirectionCmd set_command;
   set_command.light_id = light_id;
   set_command.direction = NewVector3Value(variable_id);
 
@@ -952,9 +952,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewAddLightCommand(uint32_t scene_id,
+fuchsia::ui::gfx::Command NewAddLightCmd(uint32_t scene_id,
                                              uint32_t light_id) {
-  fuchsia::ui::gfx::AddLightCommand add_light_command;
+  fuchsia::ui::gfx::AddLightCmd add_light_command;
   add_light_command.scene_id = scene_id;
   add_light_command.light_id = light_id;
 
@@ -964,8 +964,8 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewDetachLightCommand(uint32_t light_id) {
-  fuchsia::ui::gfx::DetachLightCommand detach_light_command;
+fuchsia::ui::gfx::Command NewDetachLightCmd(uint32_t light_id) {
+  fuchsia::ui::gfx::DetachLightCmd detach_light_command;
   detach_light_command.light_id = light_id;
 
   fuchsia::ui::gfx::Command command;
@@ -974,8 +974,8 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewDetachLightsCommand(uint32_t scene_id) {
-  fuchsia::ui::gfx::DetachLightsCommand detach_lights_command;
+fuchsia::ui::gfx::Command NewDetachLightsCmd(uint32_t scene_id) {
+  fuchsia::ui::gfx::DetachLightsCmd detach_lights_command;
   detach_lights_command.scene_id = scene_id;
 
   fuchsia::ui::gfx::Command command;
@@ -984,9 +984,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetEventMaskCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewSetEventMaskCmd(uint32_t resource_id,
                                                  uint32_t event_mask) {
-  fuchsia::ui::gfx::SetEventMaskCommand set_event_mask_command;
+  fuchsia::ui::gfx::SetEventMaskCmd set_event_mask_command;
   set_event_mask_command.id = resource_id;
   set_event_mask_command.event_mask = event_mask;
 
@@ -996,9 +996,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetLabelCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewSetLabelCmd(uint32_t resource_id,
                                              const std::string& label) {
-  fuchsia::ui::gfx::SetLabelCommand set_label_command;
+  fuchsia::ui::gfx::SetLabelCmd set_label_command;
   set_label_command.id = resource_id;
   set_label_command.label = label.substr(0, fuchsia::ui::gfx::kLabelMaxLength);
 
@@ -1008,9 +1008,9 @@
   return command;
 }
 
-fuchsia::ui::gfx::Command NewSetDisableClippingCommand(uint32_t renderer_id,
+fuchsia::ui::gfx::Command NewSetDisableClippingCmd(uint32_t renderer_id,
                                                        bool disable_clipping) {
-  fuchsia::ui::gfx::SetDisableClippingCommand set_disable_clipping_command;
+  fuchsia::ui::gfx::SetDisableClippingCmd set_disable_clipping_command;
   set_disable_clipping_command.renderer_id = renderer_id;
   set_disable_clipping_command.disable_clipping = disable_clipping;
 
diff --git a/public/lib/ui/scenic/fidl_helpers.h b/public/lib/ui/scenic/fidl_helpers.h
index 0817d69..bbfdc79 100644
--- a/public/lib/ui/scenic/fidl_helpers.h
+++ b/public/lib/ui/scenic/fidl_helpers.h
@@ -25,159 +25,159 @@
 fuchsia::ui::scenic::Command NewCommand(fuchsia::ui::gfx::Command command);
 
 // Resource creation.
-fuchsia::ui::gfx::Command NewCreateMemoryCommand(
+fuchsia::ui::gfx::Command NewCreateMemoryCmd(
     uint32_t id, zx::vmo vmo, fuchsia::images::MemoryType memory_type);
-fuchsia::ui::gfx::Command NewCreateImageCommand(
+fuchsia::ui::gfx::Command NewCreateImageCmd(
     uint32_t id, uint32_t memory_id, uint32_t memory_offset,
     fuchsia::images::ImageInfo info);
-fuchsia::ui::gfx::Command NewCreateImageCommand(
+fuchsia::ui::gfx::Command NewCreateImageCmd(
     uint32_t id, uint32_t memory_id, uint32_t memory_offset,
     fuchsia::images::PixelFormat format,
     fuchsia::images::ColorSpace color_space, fuchsia::images::Tiling tiling,
     uint32_t width, uint32_t height, uint32_t stride);
-fuchsia::ui::gfx::Command NewCreateImagePipeCommand(
+fuchsia::ui::gfx::Command NewCreateImagePipeCmd(
     uint32_t id, ::fidl::InterfaceRequest<fuchsia::images::ImagePipe> request);
-fuchsia::ui::gfx::Command NewCreateBufferCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateBufferCmd(uint32_t id,
                                                  uint32_t memory_id,
                                                  uint32_t memory_offset,
                                                  uint32_t num_bytes);
 
-fuchsia::ui::gfx::Command NewCreateDisplayCompositorCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateLayerStackCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateLayerCommand(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateDisplayCompositorCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateLayerStackCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateLayerCmd(uint32_t id);
 
-fuchsia::ui::gfx::Command NewCreateSceneCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateCameraCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateSceneCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateCameraCmd(uint32_t id,
                                                  uint32_t scene_id);
-fuchsia::ui::gfx::Command NewCreateStereoCameraCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateStereoCameraCmd(uint32_t id,
                                                        uint32_t scene_id);
-fuchsia::ui::gfx::Command NewCreateRendererCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateAmbientLightCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateDirectionalLightCommand(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateRendererCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateAmbientLightCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateDirectionalLightCmd(uint32_t id);
 
-fuchsia::ui::gfx::Command NewCreateCircleCommand(uint32_t id, float radius);
-fuchsia::ui::gfx::Command NewCreateRectangleCommand(uint32_t id, float width,
+fuchsia::ui::gfx::Command NewCreateCircleCmd(uint32_t id, float radius);
+fuchsia::ui::gfx::Command NewCreateRectangleCmd(uint32_t id, float width,
                                                     float height);
-fuchsia::ui::gfx::Command NewCreateRoundedRectangleCommand(
+fuchsia::ui::gfx::Command NewCreateRoundedRectangleCmd(
     uint32_t id, float width, float height, float top_left_radius,
     float top_right_radius, float bottom_right_radius,
     float bottom_left_radius);
 
-// Variant of NewCreateCircleCommand that uses a variable radius instead of a
+// Variant of NewCreateCircleCmd that uses a variable radius instead of a
 // constant one set at construction time.
-fuchsia::ui::gfx::Command NewCreateVarCircleCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateVarCircleCmd(uint32_t id,
                                                     uint32_t radius_var_id);
-// Variant of NewCreateRectangleCommand that uses a variable width/height
+// Variant of NewCreateRectangleCmd that uses a variable width/height
 // instead of constant ones set at construction time.
-fuchsia::ui::gfx::Command NewCreateVarRectangleCommand(uint32_t id,
+fuchsia::ui::gfx::Command NewCreateVarRectangleCmd(uint32_t id,
                                                        uint32_t width_var_id,
                                                        uint32_t height_var_id);
-// Variant of NewCreateRoundedRectangleCommand that uses a variable
+// Variant of NewCreateRoundedRectangleCmd that uses a variable
 // width/height/etc. instead of constant ones set at construction time.
-fuchsia::ui::gfx::Command NewCreateVarRoundedRectangleCommand(
+fuchsia::ui::gfx::Command NewCreateVarRoundedRectangleCmd(
     uint32_t id, uint32_t width_var_id, uint32_t height_var_id,
     uint32_t top_left_radius_var_id, uint32_t top_right_radius_var_id,
     uint32_t bottom_left_radius_var_id, uint32_t bottom_right_radius_var_id);
 
-fuchsia::ui::gfx::Command NewCreateMeshCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateMaterialCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateClipNodeCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateEntityNodeCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateShapeNodeCommand(uint32_t id);
-fuchsia::ui::gfx::Command NewCreateVariableCommand(
+fuchsia::ui::gfx::Command NewCreateMeshCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateMaterialCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateClipNodeCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateEntityNodeCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateShapeNodeCmd(uint32_t id);
+fuchsia::ui::gfx::Command NewCreateVariableCmd(
     uint32_t id, fuchsia::ui::gfx::Value value);
 
-fuchsia::ui::gfx::Command NewReleaseResourceCommand(uint32_t id);
+fuchsia::ui::gfx::Command NewReleaseResourceCmd(uint32_t id);
 
 // Export & Import operations.
-fuchsia::ui::gfx::Command NewExportResourceCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewExportResourceCmd(uint32_t resource_id,
                                                    zx::eventpair export_token);
-fuchsia::ui::gfx::Command NewImportResourceCommand(
+fuchsia::ui::gfx::Command NewImportResourceCmd(
     uint32_t resource_id, fuchsia::ui::gfx::ImportSpec spec,
     zx::eventpair import_token);
 
 // Exports the resource and returns an import token in |out_import_token|
 // which allows it to be imported into other sessions.
-fuchsia::ui::gfx::Command NewExportResourceCommandAsRequest(
+fuchsia::ui::gfx::Command NewExportResourceCmdAsRequest(
     uint32_t resource_id, zx::eventpair* out_import_token);
 
 // Imports the resource and returns an export token in |out_export_token|
 // by which another session can export a resource to associate with this import.
-fuchsia::ui::gfx::Command NewImportResourceCommandAsRequest(
+fuchsia::ui::gfx::Command NewImportResourceCmdAsRequest(
     uint32_t resource_id, fuchsia::ui::gfx::ImportSpec import_spec,
     zx::eventpair* out_export_token);
 
 // Node operations.
-fuchsia::ui::gfx::Command NewAddChildCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewAddChildCmd(uint32_t node_id,
                                              uint32_t child_id);
-fuchsia::ui::gfx::Command NewAddPartCommand(uint32_t node_id, uint32_t part_id);
-fuchsia::ui::gfx::Command NewDetachCommand(uint32_t node_id);
-fuchsia::ui::gfx::Command NewDetachChildrenCommand(uint32_t node_id);
-fuchsia::ui::gfx::Command NewSetTranslationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewAddPartCmd(uint32_t node_id, uint32_t part_id);
+fuchsia::ui::gfx::Command NewDetachCmd(uint32_t node_id);
+fuchsia::ui::gfx::Command NewDetachChildrenCmd(uint32_t node_id);
+fuchsia::ui::gfx::Command NewSetTranslationCmd(uint32_t node_id,
                                                    const float translation[3]);
-fuchsia::ui::gfx::Command NewSetTranslationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetTranslationCmd(uint32_t node_id,
                                                    uint32_t variable_id);
-fuchsia::ui::gfx::Command NewSetScaleCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetScaleCmd(uint32_t node_id,
                                              const float scale[3]);
-fuchsia::ui::gfx::Command NewSetScaleCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetScaleCmd(uint32_t node_id,
                                              uint32_t variable_id);
-fuchsia::ui::gfx::Command NewSetRotationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetRotationCmd(uint32_t node_id,
                                                 const float quaternion[4]);
-fuchsia::ui::gfx::Command NewSetRotationCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetRotationCmd(uint32_t node_id,
                                                 uint32_t variable_id);
-fuchsia::ui::gfx::Command NewSetAnchorCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetAnchorCmd(uint32_t node_id,
                                               const float anchor[3]);
-fuchsia::ui::gfx::Command NewSetAnchorCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetAnchorCmd(uint32_t node_id,
                                               uint32_t variable_id);
 
-fuchsia::ui::gfx::Command NewSetShapeCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetShapeCmd(uint32_t node_id,
                                              uint32_t shape_id);
-fuchsia::ui::gfx::Command NewSetMaterialCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetMaterialCmd(uint32_t node_id,
                                                 uint32_t material_id);
-fuchsia::ui::gfx::Command NewSetClipCommand(uint32_t node_id, uint32_t clip_id,
+fuchsia::ui::gfx::Command NewSetClipCmd(uint32_t node_id, uint32_t clip_id,
                                             bool clip_to_self);
-fuchsia::ui::gfx::Command NewSetTagCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetTagCmd(uint32_t node_id,
                                            uint32_t tag_value);
-fuchsia::ui::gfx::Command NewSetHitTestBehaviorCommand(
+fuchsia::ui::gfx::Command NewSetHitTestBehaviorCmd(
     uint32_t node_id, fuchsia::ui::gfx::HitTestBehavior hit_test_behavior);
 
 // Camera and lighting operations.
 
-fuchsia::ui::gfx::Command NewSetCameraCommand(uint32_t renderer_id,
+fuchsia::ui::gfx::Command NewSetCameraCmd(uint32_t renderer_id,
                                               uint32_t camera_id);
-fuchsia::ui::gfx::Command NewSetCameraTransformCommand(
+fuchsia::ui::gfx::Command NewSetCameraTransformCmd(
     uint32_t camera_id, const float eye_position[3], const float eye_look_at[3],
     const float eye_up[3]);
-fuchsia::ui::gfx::Command NewSetCameraProjectionCommand(uint32_t camera_id,
+fuchsia::ui::gfx::Command NewSetCameraProjectionCmd(uint32_t camera_id,
                                                         const float fovy);
 
-fuchsia::ui::gfx::Command NewSetCameraPoseBufferCommand(uint32_t camera_id,
+fuchsia::ui::gfx::Command NewSetCameraPoseBufferCmd(uint32_t camera_id,
                                                         uint32_t buffer_id,
                                                         uint32_t num_entries,
                                                         uint64_t base_time,
                                                         uint64_t time_interval);
 
-fuchsia::ui::gfx::Command NewSetStereoCameraProjectionCommand(
+fuchsia::ui::gfx::Command NewSetStereoCameraProjectionCmd(
     uint32_t camera_id, const float left_projection[16],
     const float right_projection[16]);
 
-fuchsia::ui::gfx::Command NewSetLightColorCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightColorCmd(uint32_t light_id,
                                                   const float rgb[3]);
-fuchsia::ui::gfx::Command NewSetLightColorCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightColorCmd(uint32_t light_id,
                                                   uint32_t variable_id);
-fuchsia::ui::gfx::Command NewSetLightDirectionCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightDirectionCmd(uint32_t light_id,
                                                       const float direction[3]);
-fuchsia::ui::gfx::Command NewSetLightDirectionCommand(uint32_t light_id,
+fuchsia::ui::gfx::Command NewSetLightDirectionCmd(uint32_t light_id,
                                                       uint32_t variable_id);
-fuchsia::ui::gfx::Command NewAddLightCommand(uint32_t scene_id,
+fuchsia::ui::gfx::Command NewAddLightCmd(uint32_t scene_id,
                                              uint32_t light_id);
-fuchsia::ui::gfx::Command NewDetachLightCommand(uint32_t light_id);
-fuchsia::ui::gfx::Command NewDetachLightsCommand(uint32_t scene_id);
+fuchsia::ui::gfx::Command NewDetachLightCmd(uint32_t light_id);
+fuchsia::ui::gfx::Command NewDetachLightsCmd(uint32_t scene_id);
 
 // Material operations.
-fuchsia::ui::gfx::Command NewSetTextureCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetTextureCmd(uint32_t node_id,
                                                uint32_t image_id);
-fuchsia::ui::gfx::Command NewSetColorCommand(uint32_t node_id, uint8_t red,
+fuchsia::ui::gfx::Command NewSetColorCmd(uint32_t node_id, uint8_t red,
                                              uint8_t green, uint8_t blue,
                                              uint8_t alpha);
 
@@ -186,8 +186,8 @@
     fuchsia::ui::gfx::ValueType position_type,
     fuchsia::ui::gfx::ValueType normal_type,
     fuchsia::ui::gfx::ValueType tex_coord_type);
-// These arguments are documented in commands.fidl; see BindMeshBuffersCommand.
-fuchsia::ui::gfx::Command NewBindMeshBuffersCommand(
+// These arguments are documented in commands.fidl; see BindMeshBuffersCmd.
+fuchsia::ui::gfx::Command NewBindMeshBuffersCmd(
     uint32_t mesh_id, uint32_t index_buffer_id,
     fuchsia::ui::gfx::MeshIndexFormat index_format, uint64_t index_offset,
     uint32_t index_count, uint32_t vertex_buffer_id,
@@ -196,30 +196,30 @@
     const float bounding_box_max[3]);
 
 // Layer / LayerStack / Compositor operations.
-fuchsia::ui::gfx::Command NewAddLayerCommand(uint32_t layer_stack_id,
+fuchsia::ui::gfx::Command NewAddLayerCmd(uint32_t layer_stack_id,
                                              uint32_t layer_id);
-fuchsia::ui::gfx::Command NewRemoveLayerCommand(uint32_t layer_stack_id,
+fuchsia::ui::gfx::Command NewRemoveLayerCmd(uint32_t layer_stack_id,
                                                 uint32_t layer_id);
-fuchsia::ui::gfx::Command NewRemoveAllLayersCommand(uint32_t layer_stack_id);
-fuchsia::ui::gfx::Command NewSetLayerStackCommand(uint32_t compositor_id,
+fuchsia::ui::gfx::Command NewRemoveAllLayersCmd(uint32_t layer_stack_id);
+fuchsia::ui::gfx::Command NewSetLayerStackCmd(uint32_t compositor_id,
                                                   uint32_t layer_stack_id);
-fuchsia::ui::gfx::Command NewSetRendererCommand(uint32_t layer_id,
+fuchsia::ui::gfx::Command NewSetRendererCmd(uint32_t layer_id,
                                                 uint32_t renderer_id);
-fuchsia::ui::gfx::Command NewSetRendererParamCommand(
+fuchsia::ui::gfx::Command NewSetRendererParamCmd(
     uint32_t renderer_id, fuchsia::ui::gfx::RendererParam param);
-fuchsia::ui::gfx::Command NewSetSizeCommand(uint32_t node_id,
+fuchsia::ui::gfx::Command NewSetSizeCmd(uint32_t node_id,
                                             const float size[2]);
 
 // Event operations.
-fuchsia::ui::gfx::Command NewSetEventMaskCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewSetEventMaskCmd(uint32_t resource_id,
                                                  uint32_t event_mask);
 
 // Diagnostic operations.
-fuchsia::ui::gfx::Command NewSetLabelCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewSetLabelCmd(uint32_t resource_id,
                                              const std::string& label);
 
 // Debugging operations.
-fuchsia::ui::gfx::Command NewSetDisableClippingCommand(uint32_t resource_id,
+fuchsia::ui::gfx::Command NewSetDisableClippingCmd(uint32_t resource_id,
                                                        bool disable_clipping);
 
 // Basic types.
diff --git a/public/lib/ui/sketchy/client/BUILD.gn b/public/lib/ui/sketchy/client/BUILD.gn
index a2bc79c..f9671bc 100644
--- a/public/lib/ui/sketchy/client/BUILD.gn
+++ b/public/lib/ui/sketchy/client/BUILD.gn
@@ -12,11 +12,12 @@
     "types.h",
   ]
 
-  deps = [
+  public_deps = [
     "//garnet/public/lib/app/cpp",
     "//garnet/public/lib/fsl",
     "//garnet/public/lib/ui/scenic:client",
     "//garnet/public/lib/ui/sketchy/fidl",
+    "//zircon/public/lib/fit",
   ]
 
   include_dirs = [ "//third_party/glm" ]
diff --git a/public/lib/ui/sketchy/client/canvas.cc b/public/lib/ui/sketchy/client/canvas.cc
index 4067b8d..00de16a 100644
--- a/public/lib/ui/sketchy/client/canvas.cc
+++ b/public/lib/ui/sketchy/client/canvas.cc
@@ -4,6 +4,8 @@
 
 #include "lib/ui/sketchy/client/canvas.h"
 
+#include "lib/fxl/functional/make_copyable.h"
+
 namespace sketchy_lib {
 
 Canvas::Canvas(fuchsia::sys::StartupContext* context, async::Loop* loop)
@@ -34,7 +36,7 @@
     // it safe to continue using.
     commands_.reset();
   }
-  canvas_->Present(time, std::move(callback));
+  canvas_->Present(time, fxl::MakeCopyable(std::move(callback)));
 }
 
 }  // namespace sketchy_lib
diff --git a/public/lib/ui/sketchy/client/resources.cc b/public/lib/ui/sketchy/client/resources.cc
index fed6204..b52bd85 100644
--- a/public/lib/ui/sketchy/client/resources.cc
+++ b/public/lib/ui/sketchy/client/resources.cc
@@ -10,57 +10,57 @@
     : canvas_(canvas), id_(canvas_->AllocateResourceId()) {}
 
 Resource::~Resource() {
-  ::fuchsia::ui::sketchy::ReleaseResourceCommand release_resource;
+  ::fuchsia::ui::sketchy::ReleaseResourceCmd release_resource;
   release_resource.id = id_;
   ::fuchsia::ui::sketchy::Command command;
   command.set_release_resource(std::move(release_resource));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
-void Resource::EnqueueCommand(::fuchsia::ui::sketchy::Command command) const {
+void Resource::EnqueueCmd(::fuchsia::ui::sketchy::Command command) const {
   canvas_->commands_.push_back(std::move(command));
 }
 
-void Resource::EnqueueCreateResourceCommand(ResourceId resource_id,
+void Resource::EnqueueCreateResourceCmd(ResourceId resource_id,
                                             ::fuchsia::ui::sketchy::ResourceArgs args) const {
-  ::fuchsia::ui::sketchy::CreateResourceCommand create_resource;
+  ::fuchsia::ui::sketchy::CreateResourceCmd create_resource;
   create_resource.id = resource_id;
   create_resource.args = std::move(args);
   ::fuchsia::ui::sketchy::Command command;
   command.set_create_resource(std::move(create_resource));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
-void Resource::EnqueueImportResourceCommand(
+void Resource::EnqueueImportResourceCmd(
     ResourceId resource_id, zx::eventpair token,
     fuchsia::ui::gfx::ImportSpec spec) const {
-  fuchsia::ui::gfx::ImportResourceCommand import_resource;
+  fuchsia::ui::gfx::ImportResourceCmd import_resource;
   import_resource.id = resource_id;
   import_resource.token = std::move(token);
   import_resource.spec = spec;
   ::fuchsia::ui::sketchy::Command command;
   command.set_scenic_import_resource(std::move(import_resource));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 Stroke::Stroke(Canvas* canvas) : Resource(canvas) {
   ::fuchsia::ui::sketchy::Stroke stroke;
   ::fuchsia::ui::sketchy::ResourceArgs resource_args;
   resource_args.set_stroke(std::move(stroke));
-  EnqueueCreateResourceCommand(id(), std::move(resource_args));
+  EnqueueCreateResourceCmd(id(), std::move(resource_args));
 }
 
 void Stroke::SetPath(const StrokePath& path) const {
-  ::fuchsia::ui::sketchy::SetStrokePathCommand set_stroke_path;
+  ::fuchsia::ui::sketchy::SetStrokePathCmd set_stroke_path;
   set_stroke_path.stroke_id = id();
   set_stroke_path.path = path.NewSketchyStrokePath();
   ::fuchsia::ui::sketchy::Command command;
   command.set_set_path(std::move(set_stroke_path));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 void Stroke::Begin(glm::vec2 pt) const {
-  ::fuchsia::ui::sketchy::BeginStrokeCommand begin_stroke;
+  ::fuchsia::ui::sketchy::BeginStrokeCmd begin_stroke;
   begin_stroke.stroke_id = id();
   ::fuchsia::ui::sketchy::Touch touch;
   touch.position.x = pt.x;
@@ -68,13 +68,13 @@
   begin_stroke.touch = std::move(touch);
   ::fuchsia::ui::sketchy::Command command;
   command.set_begin_stroke(std::move(begin_stroke));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 void Stroke::Extend(std::vector<glm::vec2> pts) const {
   FXL_DCHECK(!pts.empty());
 
-  ::fuchsia::ui::sketchy::ExtendStrokeCommand extend_stroke;
+  ::fuchsia::ui::sketchy::ExtendStrokeCmd extend_stroke;
   extend_stroke.stroke_id = id();
   fidl::VectorPtr<::fuchsia::ui::sketchy::Touch> touches;
   for (size_t i = 0; i < pts.size(); i++) {
@@ -89,65 +89,65 @@
   // TODO(MZ-269): Populate predicted touches.
   ::fuchsia::ui::sketchy::Command command;
   command.set_extend_stroke(std::move(extend_stroke));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 void Stroke::Finish() const {
-  ::fuchsia::ui::sketchy::FinishStrokeCommand finish_stroke;
+  ::fuchsia::ui::sketchy::FinishStrokeCmd finish_stroke;
   finish_stroke.stroke_id = id();
   ::fuchsia::ui::sketchy::Command command;
   command.set_finish_stroke(std::move(finish_stroke));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 StrokeGroup::StrokeGroup(Canvas* canvas) : Resource(canvas) {
   ::fuchsia::ui::sketchy::StrokeGroup stroke_group;
   ::fuchsia::ui::sketchy::ResourceArgs resource_args;
   resource_args.set_stroke_group(std::move(stroke_group));
-  EnqueueCreateResourceCommand(id(), std::move(resource_args));
+  EnqueueCreateResourceCmd(id(), std::move(resource_args));
 }
 
 void StrokeGroup::AddStroke(const Stroke& stroke) const {
-  ::fuchsia::ui::sketchy::AddStrokeCommand add_stroke;
+  ::fuchsia::ui::sketchy::AddStrokeCmd add_stroke;
   add_stroke.stroke_id = stroke.id();
   add_stroke.group_id = id();
   ::fuchsia::ui::sketchy::Command command;
   command.set_add_stroke(std::move(add_stroke));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 void StrokeGroup::RemoveStroke(const Stroke& stroke) const {
-  ::fuchsia::ui::sketchy::RemoveStrokeCommand remove_stroke;
+  ::fuchsia::ui::sketchy::RemoveStrokeCmd remove_stroke;
   remove_stroke.stroke_id = stroke.id();
   remove_stroke.group_id = id();
   ::fuchsia::ui::sketchy::Command command;
   command.set_remove_stroke(std::move(remove_stroke));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 void StrokeGroup::Clear() const {
-  ::fuchsia::ui::sketchy::ClearGroupCommand clear_group;
+  ::fuchsia::ui::sketchy::ClearGroupCmd clear_group;
   clear_group.group_id = id();
   ::fuchsia::ui::sketchy::Command command;
   command.set_clear_group(std::move(clear_group));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 ImportNode::ImportNode(Canvas* canvas, scenic_lib::EntityNode& export_node)
     : Resource(canvas) {
   zx::eventpair token;
   export_node.ExportAsRequest(&token);
-  EnqueueImportResourceCommand(id(), std::move(token),
+  EnqueueImportResourceCmd(id(), std::move(token),
                                fuchsia::ui::gfx::ImportSpec::NODE);
 }
 
 void ImportNode::AddChild(const Resource& child) const {
-  fuchsia::ui::gfx::AddChildCommand add_child;
+  fuchsia::ui::gfx::AddChildCmd add_child;
   add_child.child_id = child.id();
   add_child.node_id = id();
   ::fuchsia::ui::sketchy::Command command;
   command.set_scenic_add_child(std::move(add_child));
-  EnqueueCommand(std::move(command));
+  EnqueueCmd(std::move(command));
 }
 
 }  // namespace sketchy_lib
diff --git a/public/lib/ui/sketchy/client/resources.h b/public/lib/ui/sketchy/client/resources.h
index 22f16ae..01f264d 100644
--- a/public/lib/ui/sketchy/client/resources.h
+++ b/public/lib/ui/sketchy/client/resources.h
@@ -23,7 +23,7 @@
 //
 // Resource is the base class for these other classes.
 // provides lifecycle management; the constructor enqueues a
-// CreateResourceCommand and the destructor enqueues a ReleaseResourceCommand.
+// CreateResourceCmd and the destructor enqueues a ReleaseResourceCmd.
 class Resource {
  public:
   Canvas* canvas() const { return canvas_; }
@@ -39,7 +39,7 @@
 
   // Enqueue an op in canvas to create a resource. Called in the constructor of
   // concrete resources to be created.
-  void EnqueueCreateResourceCommand(
+  void EnqueueCreateResourceCmd(
       ResourceId resource_id, ::fuchsia::ui::sketchy::ResourceArgs args) const;
 
   // Enqueue an op in canvas to import the resource. Called in the constructor
@@ -48,11 +48,11 @@
   // |token| Token that is exported by the local resource, with which the remote
   //     canvas can import.
   // |spec| Type of the resource.
-  void EnqueueImportResourceCommand(ResourceId resource_id, zx::eventpair token,
+  void EnqueueImportResourceCmd(ResourceId resource_id, zx::eventpair token,
                                     fuchsia::ui::gfx::ImportSpec spec) const;
 
   // Enqueue an op in canvas.
-  void EnqueueCommand(::fuchsia::ui::sketchy::Command command) const;
+  void EnqueueCmd(::fuchsia::ui::sketchy::Command command) const;
 
  private:
   Canvas* const canvas_;
diff --git a/public/lib/ui/sketchy/fidl/BUILD.gn b/public/lib/ui/sketchy/fidl/BUILD.gn
index 896e32d..0dc6ed3 100644
--- a/public/lib/ui/sketchy/fidl/BUILD.gn
+++ b/public/lib/ui/sketchy/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.ui.sketchy"
+  cpp_legacy_callbacks = true
 
   sources = [
     "canvas.fidl",
diff --git a/public/lib/ui/sketchy/fidl/commands.fidl b/public/lib/ui/sketchy/fidl/commands.fidl
index 46f3d2c..1708835 100644
--- a/public/lib/ui/sketchy/fidl/commands.fidl
+++ b/public/lib/ui/sketchy/fidl/commands.fidl
@@ -8,47 +8,47 @@
 
 union Command {
   // Resource creation and lifecycle.
-  CreateResourceCommand create_resource;
-  ReleaseResourceCommand release_resource;
+  CreateResourceCmd create_resource;
+  ReleaseResourceCmd release_resource;
 
   // Stroke commands.
-  ClearStrokeCommand clear_stroke;
-  BeginStrokeCommand begin_stroke;
-  ExtendStrokeCommand extend_stroke;
-  FinishStrokeCommand finish_stroke;
-  SetStrokeStyleCommand set_style;
-  SetStrokePathCommand set_path;
+  ClearStrokeCmd clear_stroke;
+  BeginStrokeCmd begin_stroke;
+  ExtendStrokeCmd extend_stroke;
+  FinishStrokeCmd finish_stroke;
+  SetStrokeStyleCmd set_style;
+  SetStrokePathCmd set_path;
 
   // StrokeGroup commands.
-  AddStrokeCommand add_stroke;
-  RemoveStrokeCommand remove_stroke;
-  ClearGroupCommand clear_group;
+  AddStrokeCmd add_stroke;
+  RemoveStrokeCmd remove_stroke;
+  ClearGroupCmd clear_group;
 
   // Pen commands.
-  SetPenStyleCommand set_pen_style;
+  SetPenStyleCmd set_pen_style;
 
   // Interaction with Scenic scene-graph:
 
   // Import the specified Scenic resource.  Currently only the following
   // resource types are supported:
-  // - NODE: imported nodes enable the use of ui.fuchsia.ui.gfx.AddChildCommand to insert
+  // - NODE: imported nodes enable the use of ui.fuchsia.ui.gfx.AddChildCmd to insert
   //         stroke-groups into a Scenic scene-graph.
   // - MATERIAL: imported materials can be applied to a stroke-style.
-  fuchsia.ui.gfx.ImportResourceCommand scenic_import_resource;
+  fuchsia.ui.gfx.ImportResourceCmd scenic_import_resource;
 
   // Attach a stroke-group as a child of the specified imported Scenic node.
-  fuchsia.ui.gfx.AddChildCommand scenic_add_child;
+  fuchsia.ui.gfx.AddChildCmd scenic_add_child;
 
   // Detach a stroke-group from the Scenic node that it is attached to, if any.
-  fuchsia.ui.gfx.DetachCommand scenic_detach;
+  fuchsia.ui.gfx.DetachCmd scenic_detach;
 
   // Set the material of a stroke-style.  This material will be applied to any
   // strokes/stroke-groups that use this style.
-  fuchsia.ui.gfx.SetMaterialCommand scenic_set_material;
+  fuchsia.ui.gfx.SetMaterialCmd scenic_set_material;
 };
 
 // Instantiates a new resource.
-struct CreateResourceCommand {
+struct CreateResourceCmd {
   // The ID of the resource to create; this ID must not currently be used within
   // the session.  The client may use this ID to refer to the resource in
   // subsequent commands.
@@ -66,24 +66,24 @@
 // after the client releases the stroke.
 //
 // TODO: edge cases.  What about releasing a stroke that is currently being
-// drawn by Begin/Extend/FinishStrokeCommand?
-struct ReleaseResourceCommand {
+// drawn by Begin/Extend/FinishStrokeCmd?
+struct ReleaseResourceCmd {
   // The ID of the resource to be dereferenced.  The ID must currently reference
-  // a resource (i.e. it must match one from a previous CreateResourceCommand, and
-  // must not have match one from a subsequent ReleaseResourceCommand).
+  // a resource (i.e. it must match one from a previous CreateResourceCmd, and
+  // must not have match one from a subsequent ReleaseResourceCmd).
   uint32 id;
 };
 
 // Clear the path of the specified stroke.  Must not be called in the middle of
 // Begin/Extend/FinishStroke.
-struct ClearStrokeCommand {
+struct ClearStrokeCmd {
   uint32 stroke_id;
 };
 
 // Start drawing a stroke with a pen.
-struct BeginStrokeCommand {
+struct BeginStrokeCmd {
   // ID of the stroke to draw with the pen.  This must be a new stroke, or one
-  // which has been cleared via ClearStrokeCommand.
+  // which has been cleared via ClearStrokeCmd.
   uint32 stroke_id;
   // ID of the pen to draw the stroke with.
   uint32 pen_id;
@@ -92,15 +92,15 @@
 };
 
 // Continue drawing a stroke with a pen.  The stroke must have previously been
-// started (via BeginStrokeCommand), but not finished.
-struct ExtendStrokeCommand {
+// started (via BeginStrokeCmd), but not finished.
+struct ExtendStrokeCmd {
   // ID of the stroke that is being drawn.
   uint32 stroke_id;
   // ID of the pen that is drawing the stroke.  Must match the ID provided
-  // to BeginStrokeCommand.
+  // to BeginStrokeCmd.
   uint32 pen_id;
   // Touch events that describe the trajectory of the stroke since the previous
-  // BeginStrokeCommand or ExtendStrokeCommand.
+  // BeginStrokeCmd or ExtendStrokeCmd.
   vector<Touch> touches;
   // Procedurally-generated touch events that describe the predicted future
   // trajectory of the stroke.  Sketchy uses these to improve perceived latency
@@ -111,23 +111,23 @@
 };
 
 // Finish drawing a stroke with a pen.
-struct FinishStrokeCommand {
+struct FinishStrokeCmd {
   // ID of the stroke that is being drawn.
   uint32 stroke_id;
   // ID of the pen that is drawing the stroke.  Must match the ID provided
-  // to BeginStrokeCommand.
+  // to BeginStrokeCmd.
   uint32 pen_id;
 };
 
 // Set the style of the specified stroke.
-struct SetStrokeStyleCommand {
+struct SetStrokeStyleCmd {
   uint32 stroke_id;
   uint32 style_id;
 };
 
 // Set the path of a stroke.  This cannot be applied to a stroke that is in the
 // middle of Begin/Extend/FinishStroke.
-struct SetStrokePathCommand {
+struct SetStrokePathCmd {
   // ID of the stroke whose path is to be set.
   uint32 stroke_id;
   // Describes the stroke's new path.
@@ -136,27 +136,27 @@
 
 // Add a stroke to a stroke-group.  The stroke must not currently be a member of
 // any group, including the specified group.
-struct AddStrokeCommand {
+struct AddStrokeCmd {
   uint32 group_id;
   uint32 stroke_id;
 };
 
 // Remove a stroke from a stroke-group.  The stroke must currently be a member
 // of that group.
-struct RemoveStrokeCommand {
+struct RemoveStrokeCmd {
   uint32 group_id;
   uint32 stroke_id;
 };
 
 // Remove all strokes from the specified stroke-group.  These strokes may be
 // re-added later to the same group, or a different one.
-struct ClearGroupCommand {
+struct ClearGroupCmd {
   uint32 group_id;
 };
 
 // Set the style that is applied to strokes that are subsequently drawn by the
 // specified pen.
-struct SetPenStyleCommand {
+struct SetPenStyleCmd {
   uint32 pen_id;
   uint32 style_id;
 };
diff --git a/public/lib/ui/sketchy/fidl/resources.fidl b/public/lib/ui/sketchy/fidl/resources.fidl
index f903a72..0a8176c 100644
--- a/public/lib/ui/sketchy/fidl/resources.fidl
+++ b/public/lib/ui/sketchy/fidl/resources.fidl
@@ -4,7 +4,7 @@
 
 library fuchsia.ui.sketchy;
 
-// Specifies the type of a resource created via CreateResourceCommand, along with
+// Specifies the type of a resource created via CreateResourceCmd, along with
 // any other required data.
 union ResourceArgs {
   Stroke stroke;
diff --git a/public/lib/ui/spaces/fidl/BUILD.gn b/public/lib/ui/spaces/fidl/BUILD.gn
index 3213b42..8847cfa 100644
--- a/public/lib/ui/spaces/fidl/BUILD.gn
+++ b/public/lib/ui/spaces/fidl/BUILD.gn
@@ -8,6 +8,7 @@
 # reorganized.
 fidl("fidl") {
   name = "fuchsia.ui.app"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/view_framework/BUILD.gn b/public/lib/ui/view_framework/BUILD.gn
index c03cae0..a22a817 100644
--- a/public/lib/ui/view_framework/BUILD.gn
+++ b/public/lib/ui/view_framework/BUILD.gn
@@ -19,6 +19,7 @@
     "//garnet/public/lib/ui/scenic:client",
     "//garnet/public/lib/ui/scenic:fidl_helpers",
     "//garnet/public/lib/ui/views/fidl:v1",
+    "//zircon/public/lib/fit",
   ]
 
   deps = [
diff --git a/public/lib/ui/view_framework/base_view.cc b/public/lib/ui/view_framework/base_view.cc
index 47d5426..a7f571f 100644
--- a/public/lib/ui/view_framework/base_view.cc
+++ b/public/lib/ui/view_framework/base_view.cc
@@ -66,8 +66,8 @@
   return view_container_.get();
 }
 
-void BaseView::SetReleaseHandler(fxl::Closure callback) {
-  view_listener_binding_.set_error_handler(callback);
+void BaseView::SetReleaseHandler(fit::closure callback) {
+  view_listener_binding_.set_error_handler(std::move(callback));
 }
 
 void BaseView::InvalidateScene() {
diff --git a/public/lib/ui/view_framework/base_view.h b/public/lib/ui/view_framework/base_view.h
index 62383fc..a7798bc 100644
--- a/public/lib/ui/view_framework/base_view.h
+++ b/public/lib/ui/view_framework/base_view.h
@@ -8,6 +8,7 @@
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/ui/input/cpp/fidl.h>
 #include <fuchsia/ui/views_v1/cpp/fidl.h>
+#include <lib/fit/function.h>
 
 #include <memory>
 #include <string>
@@ -110,7 +111,7 @@
   //
   // This should be used to implement cleanup policies to release resources
   // associated with the view (including the object itself).
-  void SetReleaseHandler(fxl::Closure callback);
+  void SetReleaseHandler(fit::closure callback);
 
   // Invalidates the scene, causing |OnSceneInvalidated()| to be invoked
   // during the next frame.
diff --git a/public/lib/ui/views/cpp/formatting.cc b/public/lib/ui/views/cpp/formatting.cc
index bcc4450..9ee0286 100644
--- a/public/lib/ui/views/cpp/formatting.cc
+++ b/public/lib/ui/views/cpp/formatting.cc
@@ -22,13 +22,7 @@
 
 std::ostream& operator<<(std::ostream& os,
                          const ::fuchsia::ui::views_v1::ViewProperties& value) {
-  return os << "{display_metrics=" << *value.display_metrics
-            << ", view_layout=" << *value.view_layout << "}";
-}
-
-std::ostream& operator<<(std::ostream& os,
-                         const ::fuchsia::ui::views_v1::DisplayMetrics& value) {
-  return os << "{device_pixel_ratio=" << value.device_pixel_ratio << "}";
+  return os << "{view_layout=" << *value.view_layout << "}";
 }
 
 std::ostream& operator<<(std::ostream& os,
diff --git a/public/lib/ui/views/cpp/formatting.h b/public/lib/ui/views/cpp/formatting.h
index 4162d22..82524c5 100644
--- a/public/lib/ui/views/cpp/formatting.h
+++ b/public/lib/ui/views/cpp/formatting.h
@@ -23,8 +23,6 @@
 std::ostream& operator<<(std::ostream& os,
                          const ::fuchsia::ui::views_v1::ViewProperties& value);
 std::ostream& operator<<(std::ostream& os,
-                         const ::fuchsia::ui::views_v1::DisplayMetrics& value);
-std::ostream& operator<<(std::ostream& os,
                          const ::fuchsia::ui::views_v1::ViewLayout& value);
 
 }  // namespace views_v1
diff --git a/public/lib/ui/views/fidl/BUILD.gn b/public/lib/ui/views/fidl/BUILD.gn
index 63c9724..0d8688a 100644
--- a/public/lib/ui/views/fidl/BUILD.gn
+++ b/public/lib/ui/views/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("v1") {
   name = "fuchsia.ui.views_v1"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
@@ -33,6 +34,7 @@
 # ":fidl" after ViewManager is re-implemented in Mozart.
 fidl("v2") {
   name = "fuchsia.ui.views"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
@@ -51,6 +53,7 @@
 
 fidl("view_token") {
   name = "fuchsia.ui.views_v1_token"
+  cpp_legacy_callbacks = true
 
   sdk_category = "partner"
 
diff --git a/public/lib/ui/views/fidl/events.fidl b/public/lib/ui/views/fidl/events.fidl
index 3d7b9ac..f737e57 100644
--- a/public/lib/ui/views/fidl/events.fidl
+++ b/public/lib/ui/views/fidl/events.fidl
@@ -7,33 +7,10 @@
 using fuchsia.ui.gfx;
 
 union Event {
-  ViewPropertiesChangedEvent view_properties_changed;
   ChildViewAttachedEvent child_view_attached;
   ChildViewUnavailableEvent child_view_unavailable;
 };
 
-// |id| identifies the View whose properties have changed.
-//
-// TODO: this corresponds to ViewListener.OnPropertiesChanged(), which has a
-// void return value to notify when the listener has responded to the event.
-// Is this still necessary?
-struct ViewPropertiesChangedEvent {
-  uint32 id;
-
-  // The ratio of the size of a logical pixel to a physical pixel assuming
-  // pixels are square.  This value changes in relation to display
-  // resolution and density.  Must be > 0.
-  float32 device_pixel_ratio = 1.0;
-
-  // The size of the view in logical pixels.
-  // Must be non-negative.
-  fuchsia.ui.gfx.BoundingBox size;
-
-  // The inset of the view in logical pixels.
-  // Must be non-negative.
-  fuchsia.ui.gfx.vec3 inset;
-};
-
 // Called when a child view is attached.
 struct ChildViewAttachedEvent {
   uint32 view_holder_id;
diff --git a/public/lib/ui/views/fidl/view_properties.fidl b/public/lib/ui/views/fidl/view_properties.fidl
index 7b158b6..5bbc6d6 100644
--- a/public/lib/ui/views/fidl/view_properties.fidl
+++ b/public/lib/ui/views/fidl/view_properties.fidl
@@ -11,18 +11,9 @@
 // When a container sets properties for its children, any properties which
 // are set to null are inherited from the container's own ancestors.
 struct ViewProperties {
-  DisplayMetrics? display_metrics;
   ViewLayout? view_layout;
 };
 
-// Provides information about the physical characteristics of the display.
-struct DisplayMetrics {
-  // The ratio of the size of a logical pixel to a physical pixel assuming
-  // pixels are square.  This value changes in relation to display
-  // resolution and density.  Must be > 0.
-  float32 device_pixel_ratio = 1.0;
-};
-
 // Provides layout constraints for a view.
 //
 // TODO(jeffbrown): Decide how measurement should be performed.  Perhaps
diff --git a/public/lib/wlan/fidl/BUILD.gn b/public/lib/wlan/fidl/BUILD.gn
index fe2348a..b9085f1 100644
--- a/public/lib/wlan/fidl/BUILD.gn
+++ b/public/lib/wlan/fidl/BUILD.gn
@@ -5,15 +5,20 @@
 import("//build/fidl/fidl.gni")
 
 fidl("mlme") {
-  name = "wlan_mlme"
+  name = "fuchsia.wlan.mlme"
+  cpp_legacy_callbacks = true
   sources = [
     "wlan_mlme.fidl",
     "wlan_mlme_ext.fidl",
   ]
+  deps = [
+    ":stats",
+  ]
 }
 
 fidl("service") {
-  name = "wlan_service"
+  name = "fuchsia.wlan.service"
+  cpp_legacy_callbacks = true
   sources = [
     "wlan_service.fidl",
   ]
@@ -24,7 +29,8 @@
 
 
 fidl("stats") {
-  name = "wlan_stats"
+  name = "fuchsia.wlan.stats"
+  cpp_legacy_callbacks = true
   sources = [
     "wlan_stats.fidl"
   ]
diff --git a/public/lib/wlan/fidl/wlan_mlme.fidl b/public/lib/wlan/fidl/wlan_mlme.fidl
index b0c8dcf..ac19f10 100644
--- a/public/lib/wlan/fidl/wlan_mlme.fidl
+++ b/public/lib/wlan/fidl/wlan_mlme.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_mlme;
+library fuchsia.wlan.mlme;
 
 // Stub types for communicating between the wlan service and the MLME drivers. Based on the 802.11
 // MLME SAP interface (IEEE Std 802.11-2016 section 6.3).
@@ -513,4 +513,7 @@
 
     0x1003: DeviceQueryReq(DeviceQueryRequest req);
     0x1004: -> DeviceQueryConf(DeviceQueryConfirm resp);
+
+    0x1005: StatsQueryReq();
+    0x1006: -> StatsQueryResp(StatsQueryResponse resp);
 };
diff --git a/public/lib/wlan/fidl/wlan_mlme_ext.fidl b/public/lib/wlan/fidl/wlan_mlme_ext.fidl
index f09050c..e69760e 100644
--- a/public/lib/wlan/fidl/wlan_mlme_ext.fidl
+++ b/public/lib/wlan/fidl/wlan_mlme_ext.fidl
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_mlme;
+library fuchsia.wlan.mlme;
+using fuchsia.wlan.stats;
 
 // Custom primitives for communicating between the wlan service and the MLME drivers.
 // The primitives defined here are not part of the official 802.11 MLME SAP interface specification,
@@ -50,5 +51,17 @@
     vector<BandCapabilities> bands;
 };
 
+// STATS_QUERY.response
+
+union MlmeStats {
+  fuchsia.wlan.stats.ClientMlmeStats client_mlme_stats;
+  fuchsia.wlan.stats.ApMlmeStats ap_mlme_stats;
+};
+
+struct StatsQueryResponse {
+    fuchsia.wlan.stats.DispatcherStats dispatcher_stats;
+    MlmeStats mlme_stats;
+};
+
 // Method ordinals are defined in wlan_mlme.fidl to prevent error prone overlaps with official
 // MLME primitives.
diff --git a/public/lib/wlan/fidl/wlan_service.fidl b/public/lib/wlan/fidl/wlan_service.fidl
index fb53feb..ece244a 100644
--- a/public/lib/wlan/fidl/wlan_service.fidl
+++ b/public/lib/wlan/fidl/wlan_service.fidl
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_service;
-using wlan_mlme;
+library fuchsia.wlan.service;
+
+using fuchsia.wlan.mlme;
 
 enum ErrCode {
   OK = 0;
@@ -24,7 +25,7 @@
   int8         rssi_dbm;
   bool         is_secure;
   bool         is_compatible; // with respect to Fuchsia
-  wlan_mlme.WlanChan chan;
+  fuchsia.wlan.mlme.WlanChan chan;
 };
 
 struct ScanRequest {
diff --git a/public/lib/wlan/fidl/wlan_stats.fidl b/public/lib/wlan/fidl/wlan_stats.fidl
index 54392a1..948270a 100644
--- a/public/lib/wlan/fidl/wlan_stats.fidl
+++ b/public/lib/wlan/fidl/wlan_stats.fidl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-library wlan_stats;
+library fuchsia.wlan.stats;
 
 struct Counter {
   uint64 count;
@@ -30,4 +30,8 @@
   PacketCounter mgmt_frame;
 };
 
-// LINT.ThenChange(//garnet/lib/wlan/common/include/wlan/common/stats.h)
\ No newline at end of file
+struct ApMlmeStats {
+  PacketCounter not_used;
+};
+
+// LINT.ThenChange(//garnet/lib/wlan/common/include/wlan/common/stats.h)
diff --git a/public/lib/xi/fidl/BUILD.gn b/public/lib/xi/fidl/BUILD.gn
index 6fa7b1b..73fde95 100644
--- a/public/lib/xi/fidl/BUILD.gn
+++ b/public/lib/xi/fidl/BUILD.gn
@@ -6,6 +6,7 @@
 
 fidl("fidl") {
   name = "fuchsia.xi"
+  cpp_legacy_callbacks = true
   sources = [
     "xi.fidl",
   ]
diff --git a/public/rust/crates/fuchsia-async/src/lib.rs b/public/rust/crates/fuchsia-async/src/lib.rs
index 3b12853..7e9270c 100644
--- a/public/rust/crates/fuchsia-async/src/lib.rs
+++ b/public/rust/crates/fuchsia-async/src/lib.rs
@@ -10,7 +10,7 @@
 extern crate bytes;
 extern crate crossbeam;
 #[macro_use]
-extern crate futures;
+pub extern crate futures;
 extern crate fuchsia_zircon as zx;
 extern crate libc;
 extern crate net2;
@@ -47,20 +47,20 @@
             )*
         }
 
-        impl<$first, $($subfuture,)*> Future for $future<$first, $($subfuture,)*>
+        impl<$first, $($subfuture,)*> $crate::futures::Future for $future<$first, $($subfuture,)*>
         where
-            $first: Future,
+            $first: $crate::futures::Future,
             $(
-                $subfuture: Future<Item = $first::Item, Error = $first::Error>,
+                $subfuture: $crate::futures::Future<Item = $first::Item, Error = $first::Error>,
             )*
         {
             type Item = $first::Item;
             type Error = $first::Error;
-            fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
+            fn poll(&mut self, cx: &mut $crate::futures::task::Context) -> $crate::futures::Poll<Self::Item, Self::Error> {
                 match self {
-                    $future::$first(x) => x.poll(cx),
+                    $future::$first(x) => $crate::futures::Future::poll(x, cx),
                     $(
-                        $future::$subfuture(x) => x.poll(cx),
+                        $future::$subfuture(x) => $crate::futures::Future::poll(x, cx),
                     )*
                 }
             }
diff --git a/public/rust/crates/fuchsia-zircon/BUILD.gn b/public/rust/crates/fuchsia-zircon/BUILD.gn
index 680bb50..4d9ba3e 100644
--- a/public/rust/crates/fuchsia-zircon/BUILD.gn
+++ b/public/rust/crates/fuchsia-zircon/BUILD.gn
@@ -5,8 +5,7 @@
 import("//build/rust/rustc_library.gni")
 
 rustc_library("fuchsia-zircon") {
-  name = "fuchsia_zircon"
-  version = "0.3.4"
+  version = "0.3.3"
   with_unit_tests = true
   deps = [
     "fuchsia-zircon-sys",
diff --git a/public/rust/crates/fuchsia-zircon/Cargo.toml b/public/rust/crates/fuchsia-zircon/Cargo.toml
new file mode 100644
index 0000000..6aae732
--- /dev/null
+++ b/public/rust/crates/fuchsia-zircon/Cargo.toml
@@ -0,0 +1,18 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+[package]
+name = "fuchsia-zircon"
+version = "0.3.3"
+license = "BSD-3-Clause"
+authors = ["rust-fuchsia@fuchsia.com"]
+description = "Rust crate for Fuchsia OS"
+repository = "https://fuchsia.googlesource.com"
+
+[dependencies]
+failure = "0.1.1"
+bitflags = "1"
+
+[dependencies.fuchsia-zircon-sys]
+path = "fuchsia-zircon-sys"
+version = "0.3.3"
diff --git a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/BUILD.gn b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/BUILD.gn
index 679fef3..01af75e 100644
--- a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/BUILD.gn
+++ b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/BUILD.gn
@@ -5,6 +5,5 @@
 import("//build/rust/rustc_library.gni")
 
 rustc_library("fuchsia-zircon-sys") {
-  name = "fuchsia_zircon_sys"
-  version = "0.3.4"
+  version = "0.3.3"
 }
diff --git a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/Cargo.toml b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/Cargo.toml
new file mode 100644
index 0000000..b8924d8
--- /dev/null
+++ b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/Cargo.toml
@@ -0,0 +1,10 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+[package]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+license = "BSD-3-Clause"
+authors = ["rust-fuchsia@fuchsia.com"]
+description = "Rust crate for Fuchsia OS"
+repository = "https://fuchsia.googlesource.com"
diff --git a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/definitions.rs b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/definitions.rs
index 29b7ec9..8d12404 100644
--- a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/definitions.rs
+++ b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/definitions.rs
@@ -823,12 +823,6 @@
         cmdline_len: u32
         ) -> zx_status_t;
 
-    pub fn zx_job_set_relative_importance(
-        root_resource: zx_handle_t,
-        job: zx_handle_t,
-        less_important_job: zx_handle_t
-        ) -> zx_status_t;
-
     pub fn zx_syscall_test_0(
         ) -> zx_status_t;
 
diff --git a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs
index e8a3c81..59d8e09 100644
--- a/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs
+++ b/public/rust/crates/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs
@@ -267,6 +267,13 @@
     ZX_CACHE_POLICY_WRITE_COMBINING = 3,
 }
 
+// Flag bits for zx_cache_flush.
+multiconst!(u32, [
+    ZX_CACHE_FLUSH_INSN         = 1 << 0;
+    ZX_CACHE_FLUSH_DATA         = 1 << 1;
+    ZX_CACHE_FLUSH_INVALIDATE   = 1 << 2;
+]);
+
 #[repr(C)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
 pub struct zx_wait_item_t {
diff --git a/public/rust/crates/zerocopy/src/lib.rs b/public/rust/crates/zerocopy/src/lib.rs
index 9cdd5a7..0d503b3 100644
--- a/public/rust/crates/zerocopy/src/lib.rs
+++ b/public/rust/crates/zerocopy/src/lib.rs
@@ -2,8 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#![no_std]
+#![cfg_attr(not(test), no_std)]
 
+#[cfg(test)]
+extern crate core;
+
+use core::fmt::{self, Debug, Display, Formatter};
 use core::marker::PhantomData;
 use core::mem;
 use core::ops::{Deref, DerefMut};
@@ -174,6 +178,27 @@
         Some((LayoutVerified(bytes, PhantomData), rest))
     }
 
+    /// Construct a new `LayoutVerified` from the suffix of a byte slice.
+    ///
+    /// `new_from_suffix` verifies that `bytes.len() >= size_of::<T>()` and that
+    /// the last `size_of::<T>()` bytes of `bytes` are aligned to
+    /// `align_of::<T>()`. It consumes the last `size_of::<T>()` bytes from
+    /// `bytes` to construct a `LayoutVerified`, and returns the preceding bytes
+    /// to the caller. If either the length or alignment checks fail, it returns
+    /// `None`.
+    #[inline]
+    pub fn new_from_suffix(bytes: B) -> Option<(LayoutVerified<B, T>, B)> {
+        let bytes_len = bytes.len();
+        if bytes_len < mem::size_of::<T>() {
+            return None;
+        }
+        let (prefix, bytes) = bytes.split_at(bytes_len - mem::size_of::<T>());
+        if !aligned_to(bytes.deref(), mem::align_of::<T>()) {
+            return None;
+        }
+        Some((LayoutVerified(bytes, PhantomData), prefix))
+    }
+
     #[inline]
     pub fn bytes(&self) -> &[u8] {
         &self.0
@@ -214,6 +239,23 @@
         let (bytes, rest) = bytes.split_at(mem::size_of::<T>());
         Some((LayoutVerified(bytes, PhantomData), rest))
     }
+
+    /// Construct a new `LayoutVerified` from the suffix of a byte slice for a
+    /// type with no alignment requirement.
+    ///
+    /// `new_unaligned_from_suffix` verifies that `bytes.len() >=
+    /// size_of::<T>()`. It consumes the last `size_of::<T>()` bytes from
+    /// `bytes` to construct a `LayoutVerified`, and returns the preceding bytes
+    /// to the caller. If the length check fails, it returns `None`.
+    #[inline]
+    pub fn new_unaligned_from_suffix(bytes: B) -> Option<(LayoutVerified<B, T>, B)> {
+        let bytes_len = bytes.len();
+        if bytes_len < mem::size_of::<T>() {
+            return None;
+        }
+        let (prefix, bytes) = bytes.split_at(bytes_len - mem::size_of::<T>());
+        Some((LayoutVerified(bytes, PhantomData), prefix))
+    }
 }
 
 fn aligned_to(bytes: &[u8], align: usize) -> bool {
@@ -249,8 +291,32 @@
     }
 }
 
+impl<T, B> Display for LayoutVerified<B, T>
+where
+    B: ByteSlice,
+    T: FromBytes + Display,
+{
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        let inner: &T = self;
+        inner.fmt(fmt)
+    }
+}
+
+impl<T, B> Debug for LayoutVerified<B, T>
+where
+    B: ByteSlice,
+    T: FromBytes + Debug,
+{
+    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
+        let inner: &T = self;
+        fmt.debug_tuple("LayoutVerified").field(&inner).finish()
+    }
+}
+
 mod sealed {
     pub trait Sealed {}
+    impl<'a> Sealed for &'a [u8] {}
+    impl<'a> Sealed for &'a mut [u8] {}
 }
 
 // ByteSlice abstract over &[u8] and &mut [u8]. We rely on various behaviors of
@@ -270,8 +336,6 @@
     fn split_at(self, mid: usize) -> (Self, Self);
 }
 
-impl<'a> self::sealed::Sealed for &'a [u8] {}
-impl<'a> self::sealed::Sealed for &'a mut [u8] {}
 unsafe impl<'a> ByteSlice for &'a [u8] {
     fn as_ptr(&self) -> *const u8 {
         <[u8]>::as_ptr(&self)
@@ -367,49 +431,83 @@
 
     #[test]
     fn test_new() {
-        // test that a properly-aligned, properly-sized buffer works for new and
-        // new_from_preifx, and that new_prefix returns an empty slice
+        // test that a properly-aligned, properly-sized buffer works for new,
+        // new_from_preifx, and new_from_suffix, and that new_from_prefix and
+        // new_from_suffix return empty slices
 
         // a buffer with an alignment of 8
         let mut buf = AlignedBuffer::<u64, [u8; 8]>::default();
         // buf.buf should be aligned to 8, so this should always succeed
         test_new_helper(LayoutVerified::<_, u64>::new(&mut buf.buf[..]).unwrap());
         buf.clear_buf();
-        let (lv, rest) = LayoutVerified::<_, u64>::new_from_prefix(&mut buf.buf[..]).unwrap();
-        assert!(rest.is_empty());
+        {
+            // in a block so that lv and rest don't live too long
+            let (lv, rest) = LayoutVerified::<_, u64>::new_from_prefix(&mut buf.buf[..]).unwrap();
+            assert!(rest.is_empty());
+            test_new_helper(lv);
+        }
+        buf.clear_buf();
+        let (lv, prefix) = LayoutVerified::<_, u64>::new_from_suffix(&mut buf.buf[..]).unwrap();
+        assert!(prefix.is_empty());
         test_new_helper(lv);
 
-        // test that an unaligned, properly-sized buffer works for new_unaligned
-        // and new_unaligned_from_prefix, and that new_unaligned_from_prefix
-        // returns an empty slice
+        // test that an unaligned, properly-sized buffer works for
+        // new_unaligned, new_unaligned_from_prefix, and
+        // new_unaligned_from_suffix, and that new_unaligned_from_prefix
+        // new_unaligned_from_suffix return empty slices
 
         let mut buf = [0u8; 8];
         test_new_helper_unaligned(
             LayoutVerified::<_, [u8; 8]>::new_unaligned(&mut buf[..]).unwrap(),
         );
         buf = [0u8; 8];
-        let (lv, rest) =
-            LayoutVerified::<_, [u8; 8]>::new_unaligned_from_prefix(&mut buf[..]).unwrap();
-        assert!(rest.is_empty());
+        {
+            // in a block so that lv and rest don't live too long
+            let (lv, rest) =
+                LayoutVerified::<_, [u8; 8]>::new_unaligned_from_prefix(&mut buf[..]).unwrap();
+            assert!(rest.is_empty());
+            test_new_helper_unaligned(lv);
+        }
+        buf = [0u8; 8];
+        let (lv, prefix) =
+            LayoutVerified::<_, [u8; 8]>::new_unaligned_from_suffix(&mut buf[..]).unwrap();
+        assert!(prefix.is_empty());
         test_new_helper_unaligned(lv);
 
         // test that a properly-aligned, overly-sized buffer works for
-        // new_from_prefix, and that it returns the remainder of the slice
+        // new_from_prefix and new_from_suffix, and that they return the
+        // remainder and prefix of the slice respectively
 
         let mut buf = AlignedBuffer::<u64, [u8; 16]>::default();
+        {
+            // in a block so that lv and rest don't live too long
+            // buf.buf should be aligned to 8, so this should always succeed
+            let (lv, rest) = LayoutVerified::<_, u64>::new_from_prefix(&mut buf.buf[..]).unwrap();
+            assert_eq!(rest.len(), 8);
+            test_new_helper(lv);
+        }
+        buf.clear_buf();
         // buf.buf should be aligned to 8, so this should always succeed
-        let (lv, rest) = LayoutVerified::<_, u64>::new_from_prefix(&mut buf.buf[..]).unwrap();
-        assert_eq!(rest.len(), 8);
+        let (lv, prefix) = LayoutVerified::<_, u64>::new_from_suffix(&mut buf.buf[..]).unwrap();
+        assert_eq!(prefix.len(), 8);
         test_new_helper(lv);
 
         // test than an unaligned, overly-sized buffer works for
-        // new_unaligned_from_prefix, and that it returns the remainder of the
-        // slice
+        // new_unaligned_from_prefix and new_unaligned_from_suffix, and that
+        // they return the remainder and prefix of the slice respectively
 
         let mut buf = [0u8; 16];
-        let (lv, rest) =
-            LayoutVerified::<_, [u8; 8]>::new_unaligned_from_prefix(&mut buf[..]).unwrap();
-        assert_eq!(rest.len(), 8);
+        {
+            // in a block so that lv and rest don't live too long
+            let (lv, rest) =
+                LayoutVerified::<_, [u8; 8]>::new_unaligned_from_prefix(&mut buf[..]).unwrap();
+            assert_eq!(rest.len(), 8);
+            test_new_helper_unaligned(lv);
+        }
+        buf = [0u8; 16];
+        let (lv, prefix) =
+            LayoutVerified::<_, [u8; 8]>::new_unaligned_from_suffix(&mut buf[..]).unwrap();
+        assert_eq!(prefix.len(), 8);
         test_new_helper_unaligned(lv);
     }
 
@@ -431,7 +529,9 @@
         assert!(LayoutVerified::<_, u64>::new(&buf.buf[..]).is_none());
         assert!(LayoutVerified::<_, [u8; 8]>::new_unaligned(&buf.buf[..]).is_none());
         assert!(LayoutVerified::<_, u64>::new_from_prefix(&buf.buf[..]).is_none());
+        assert!(LayoutVerified::<_, u64>::new_from_suffix(&buf.buf[..]).is_none());
         assert!(LayoutVerified::<_, [u8; 8]>::new_unaligned_from_prefix(&buf.buf[..]).is_none());
+        assert!(LayoutVerified::<_, [u8; 8]>::new_unaligned_from_suffix(&buf.buf[..]).is_none());
 
         // fail because the alignment is insufficient
 
@@ -441,5 +541,16 @@
         // should succeed) but an alignment of only 4, which is insufficient
         assert!(LayoutVerified::<_, u64>::new(&buf.buf[4..]).is_none());
         assert!(LayoutVerified::<_, u64>::new_from_prefix(&buf.buf[4..]).is_none());
+        // slicing from 4 should be unnecessary because new_from_suffix uses the
+        // suffix of the slice
+        assert!(LayoutVerified::<_, u64>::new_from_suffix(&buf.buf[..]).is_none());
+    }
+
+    #[test]
+    fn test_display_debug() {
+        let buf = AlignedBuffer::<u64, [u8; 8]>::default();
+        let lv = LayoutVerified::<_, u64>::new(&buf.buf[..]).unwrap();
+        assert_eq!(format!("{}", lv), "0");
+        assert_eq!(format!("{:?}", lv), "LayoutVerified(0)");
     }
 }
diff --git a/public/sdk/BUILD.gn b/public/sdk/BUILD.gn
index c24a531..42ca594 100644
--- a/public/sdk/BUILD.gn
+++ b/public/sdk/BUILD.gn
@@ -61,7 +61,7 @@
     "//garnet/public/lib/ui/geometry/fidl:fidl_sdk($fidl_toolchain)",
     "//garnet/public/lib/ui/gfx/fidl:fidl_sdk($fidl_toolchain)",
     "//garnet/public/lib/ui/input/fidl:fidl_sdk($fidl_toolchain)",
-    "//garnet/public/lib/ui/presentation/fidl:fidl_sdk($fidl_toolchain)",
+    "//garnet/public/lib/ui/policy/fidl:fidl_sdk($fidl_toolchain)",
     "//garnet/public/lib/ui/scenic/fidl:fidl_sdk($fidl_toolchain)",
     "//garnet/public/lib/ui/views/fidl:v1_sdk($fidl_toolchain)",
     "//garnet/public/lib/ui/views/fidl:v2_sdk($fidl_toolchain)",