Merge "Remove/rename IRadio version-specific commands"
diff --git a/guest/commands/Android.bp b/guest/commands/Android.bp
index df15067..088948b 100644
--- a/guest/commands/Android.bp
+++ b/guest/commands/Android.bp
@@ -16,7 +16,6 @@
 subdirs = [
   "vsock_logcat",
   "ip_link_add",
-  "usbforward",
   "vport_trigger",
   "vsoc_input_service",
 ]
diff --git a/guest/commands/usbforward/Android.bp b/guest/commands/usbforward/Android.bp
deleted file mode 100644
index fe390e6..0000000
--- a/guest/commands/usbforward/Android.bp
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-
-cc_binary {
-    name: "usbforward",
-    srcs: [
-        "main.cpp",
-        "usb_server.cpp",
-        "transport_request.cpp",
-    ],
-    shared_libs: [
-        "libcuttlefish_fs",
-        "libusb",
-        "libbase",
-        "liblog",
-    ],
-    cflags: [
-        "-DLOG_TAG=\"UsbForward\"",
-    ],
-    defaults: ["cuttlefish_guest_only"]
-}
diff --git a/guest/commands/usbforward/main.cpp b/guest/commands/usbforward/main.cpp
deleted file mode 100644
index 3edd78f..0000000
--- a/guest/commands/usbforward/main.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <log/log.h>
-#include <stdio.h>
-#include <libusb/libusb.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "guest/commands/usbforward/usb_server.h"
-
-int main(int argc, char* argv[]) {
-  if (argc == 1) {
-    printf("Usage: %s <virtio_channel>\n", argv[0]);
-    return 1;
-  }
-
-  cvd::SharedFD fd = cvd::SharedFD::Open(argv[1], O_RDWR | O_NOCTTY);
-  if (!fd->IsOpen()) {
-    ALOGE("Could not open %s: %s", argv[1], fd->StrError());
-    return 1;
-  }
-
-  usb_forward::USBServer server(fd);
-  server.Serve();
-  ALOGE("Terminated.");
-
-  libusb_exit(nullptr);
-  return 1;
-}
diff --git a/guest/commands/usbforward/transport_request.cpp b/guest/commands/usbforward/transport_request.cpp
deleted file mode 100644
index fa68ace..0000000
--- a/guest/commands/usbforward/transport_request.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "guest/commands/usbforward/transport_request.h"
-
-#include <log/log.h>
-
-namespace usb_forward {
-
-TransportRequest::TransportRequest(std::shared_ptr<libusb_device_handle> handle,
-                                   CallbackType callback,
-                                   const ControlTransfer& transfer)
-    : handle_{std::move(handle)},
-      callback_{std::move(callback)},
-      is_control_{true},
-      transfer_{libusb_alloc_transfer(0), libusb_free_transfer} {
-  // NOTE: libusb places setup structure as part of user data!
-  buffer_.reset(new uint8_t[transfer.length + LIBUSB_CONTROL_SETUP_SIZE]);
-
-  // NOTE: libusb places a structure of size LIBUSB_CONTROL_SETUP_SIZE directly
-  // in the data buffer.
-  libusb_fill_control_setup(buffer_.get(), transfer.type, transfer.cmd,
-                            transfer.value, transfer.index, transfer.length);
-
-  // NOTE: despite libusb requires user to allocate buffer large enough to
-  // accommodate SETUP structure and actual data, it requires user to provide
-  // only data length here, while setup length is added internally.
-  libusb_fill_control_transfer(transfer_.get(), handle_.get(), buffer_.get(),
-                               OnTransferComplete, this, transfer.timeout);
-}
-
-TransportRequest::TransportRequest(std::shared_ptr<libusb_device_handle> handle,
-                                   CallbackType callback,
-                                   const DataTransfer& transfer)
-    : handle_{std::move(handle)},
-      callback_{std::move(callback)},
-      is_control_{false},
-      transfer_{libusb_alloc_transfer(0), libusb_free_transfer} {
-  buffer_.reset(new uint8_t[transfer.length]);
-  libusb_fill_bulk_transfer(
-      transfer_.get(), handle_.get(),
-      transfer.endpoint_id | (transfer.is_host_to_device ? LIBUSB_ENDPOINT_OUT
-                                                         : LIBUSB_ENDPOINT_IN),
-      buffer_.get(), transfer.length, OnTransferComplete, this,
-      transfer.timeout);
-}
-
-uint8_t* TransportRequest::Buffer() {
-  if (is_control_) {
-    return &buffer_[LIBUSB_CONTROL_SETUP_SIZE];
-  } else {
-    return buffer_.get();
-  }
-}
-
-bool TransportRequest::Submit() {
-  if (handle_) {
-    auto err = libusb_submit_transfer(transfer_.get());
-    if (err != 0) {
-      ALOGE("libusb transfer failed: %d", err);
-    }
-    return err == 0;
-  } else {
-    ALOGE("Initiated transfer, but device not opened.");
-    return false;
-  }
-}
-
-void TransportRequest::OnTransferComplete(libusb_transfer* req) {
-  auto treq = static_cast<TransportRequest*>(req->user_data);
-  treq->callback_(req->status == 0, treq->Buffer(), req->actual_length);
-}
-
-}  // namespace usb_forward
diff --git a/guest/commands/usbforward/transport_request.h b/guest/commands/usbforward/transport_request.h
deleted file mode 100644
index 1f76bbe..0000000
--- a/guest/commands/usbforward/transport_request.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <functional>
-#include <memory>
-
-#include <stdint.h>
-#include <libusb/libusb.h>
-#include "common/libs/usbforward/protocol.h"
-
-namespace usb_forward {
-
-// TransportRequest represents a libusb asynchronous transport request.
-// This class encapsulates everything that is necessary to complete
-// transfer.
-class TransportRequest final {
- public:
-  // CallbackType describes what kind of function can receive call when this
-  // asynchronous call is complete.
-  // Parameters passed to callback, in order:
-  // - success indicator (true = success),
-  // - buffer with data (in or out),
-  // - actual length transferred.
-  using CallbackType = std::function<void(bool, const uint8_t*, int32_t)>;
-
-  TransportRequest(std::shared_ptr<libusb_device_handle> device,
-                   CallbackType callback, const ControlTransfer& transfer);
-  TransportRequest(std::shared_ptr<libusb_device_handle> device,
-                   CallbackType callback, const DataTransfer& transfer);
-  ~TransportRequest() = default;
-
-  uint8_t* Buffer();
-
-  // Submit sends an asynchronous data exchange requests.
-  // Returns true only if operation was successful. At this point
-  // ownership of this structure is passed to libusb and user
-  // must not release the underlying structure.
-  bool Submit();
-
-  // Executes corresponding callback with execution results.
-  // This is a static call to ensure that the callback being invoked
-  // can dispose of this instance.
-  static void OnTransferComplete(libusb_transfer* req);
-
- private:
-  std::shared_ptr<libusb_device_handle> handle_;
-  CallbackType callback_;
-  bool is_control_;
-  std::unique_ptr<libusb_transfer, void (*)(libusb_transfer*)> transfer_;
-  std::unique_ptr<uint8_t[]> buffer_;
-
-  TransportRequest(const TransportRequest& other) = delete;
-  TransportRequest& operator=(const TransportRequest& other) = delete;
-};
-
-}  // namespace usb_forward
diff --git a/guest/commands/usbforward/usb_server.cpp b/guest/commands/usbforward/usb_server.cpp
deleted file mode 100644
index e8f5525..0000000
--- a/guest/commands/usbforward/usb_server.cpp
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// #undef NDEBUG
-
-#include "guest/commands/usbforward/usb_server.h"
-
-#include <string>
-#include <vector>
-#include <strings.h>
-#include <log/log.h>
-#include <libusb/libusb.h>
-#include "common/libs/fs/shared_select.h"
-#include "common/libs/usbforward/protocol.h"
-#include "guest/commands/usbforward/transport_request.h"
-
-namespace usb_forward {
-namespace {
-// USBServer exports device kExportedVendorID:kExportedProductID to the server.
-// We will not support exporting multiple USB devices as there's no practical
-// need for this.
-constexpr uint16_t kExportedVendorID = 0x18d1;
-constexpr uint16_t kExportedProductID = 0x4ee7;
-
-// Use default BUS and DEVICE IDs so that it's easier to attach over USB/IP.
-constexpr uint8_t kDefaultBusID = 1;
-constexpr uint8_t kDefaultDevID = 1;
-
-std::shared_ptr<libusb_device_handle> GetDevice() {
-  std::shared_ptr<libusb_device_handle> res(
-      libusb_open_device_with_vid_pid(nullptr, kExportedVendorID,
-                                      kExportedProductID),
-      [](libusb_device_handle* h) {
-        // Apparently, deleter is called even on an uninitialized shared_ptr.
-        if (h != nullptr) {
-          libusb_release_interface(h, 0);
-          libusb_close(h);
-        }
-      });
-
-  if (res) libusb_claim_interface(res.get(), 0);
-
-  return res;
-}
-
-}  // anonymous namespace
-
-bool USBServer::GetDeviceInfo(
-    DeviceInfo* info, std::vector<InterfaceInfo>* ifaces) {
-  if (!handle_) return false;
-
-  // This function does not modify the reference count of the returned device,
-  // so do not feel compelled to unreference it when you are done.
-  libusb_device* dev = libusb_get_device(handle_.get());
-
-  libusb_device_descriptor desc;
-  libusb_config_descriptor* conf;
-  memset(info, 0, sizeof(*info));
-
-  int res = libusb_get_device_descriptor(dev, &desc);
-  if (res < 0) {
-    // This shouldn't really happen.
-    ALOGE("libusb_get_device_descriptor failed %d", res);
-    return false;
-  }
-
-  res = libusb_get_active_config_descriptor(dev, &conf);
-  if (res < 0) {
-    // This shouldn't really happen.
-    ALOGE("libusb_get_active_config_descriptor failed %d", res);
-    libusb_free_config_descriptor(conf);
-    return false;
-  }
-
-  info->vendor_id = desc.idVendor;
-  info->product_id = desc.idProduct;
-  info->dev_version = desc.bcdDevice;
-  info->dev_class = desc.bDeviceClass;
-  info->dev_subclass = desc.bDeviceSubClass;
-  info->dev_protocol = desc.bDeviceProtocol;
-  info->speed = libusb_get_device_speed(dev);
-  info->num_configurations = desc.bNumConfigurations;
-  info->num_interfaces = conf->bNumInterfaces;
-  info->cur_configuration = conf->bConfigurationValue;
-  info->bus_id = kDefaultBusID;
-  info->dev_id = kDefaultDevID;
-
-  if (ifaces != nullptr) {
-    for (int ifidx = 0; ifidx < conf->bNumInterfaces; ++ifidx) {
-      const libusb_interface& iface = conf->interface[ifidx];
-      for (int altidx = 0; altidx < iface.num_altsetting; ++altidx) {
-        const libusb_interface_descriptor& alt = iface.altsetting[altidx];
-        ifaces->push_back(InterfaceInfo{alt.bInterfaceClass,
-                                        alt.bInterfaceSubClass,
-                                        alt.bInterfaceProtocol, 0});
-      }
-    }
-  }
-  libusb_free_config_descriptor(conf);
-  return true;
-}
-
-USBServer::USBServer(const cvd::SharedFD& fd)
-    : fd_{fd},
-      device_event_fd_{cvd::SharedFD::Event(0, 0)},
-      thread_event_fd_{cvd::SharedFD::Event(0, 0)} {}
-
-void USBServer::HandleDeviceList(uint32_t tag) {
-  // Iterate all devices and send structure for every found device.
-  // Write header: number of devices.
-  DeviceInfo info;
-  std::vector<InterfaceInfo> ifaces;
-  bool found = GetDeviceInfo(&info, &ifaces);
-
-  cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
-  ResponseHeader rsp{StatusSuccess, tag};
-  fd_->Write(&rsp, sizeof(rsp));
-  if (found) {
-    uint32_t cnt = 1;
-    fd_->Write(&cnt, sizeof(cnt));
-    fd_->Write(&info, sizeof(info));
-    fd_->Write(ifaces.data(), ifaces.size() * sizeof(InterfaceInfo));
-  } else {
-    // No devices.
-    uint32_t cnt = 0;
-    fd_->Write(&cnt, sizeof(cnt));
-  }
-}
-
-void USBServer::HandleAttach(uint32_t tag) {
-  // We read the request, but it no longer plays any significant role here.
-  AttachRequest req;
-  if (fd_->Read(&req, sizeof(req)) != sizeof(req)) return;
-
-  cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
-  ResponseHeader rsp{handle_ ? StatusSuccess : StatusFailure, tag};
-  fd_->Write(&rsp, sizeof(rsp));
-}
-
-void USBServer::HandleHeartbeat(uint32_t tag) {
-  cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
-  ResponseHeader rsp{handle_ ? StatusSuccess : StatusFailure, tag};
-  fd_->Write(&rsp, sizeof(rsp));
-}
-
-void USBServer::HandleControlTransfer(uint32_t tag) {
-  ControlTransfer req;
-  // If disconnected prematurely, don't send response.
-  if (fd_->Read(&req, sizeof(req)) != sizeof(req)) return;
-
-  // Technically speaking this isn't endpoint, but names, masks, values and
-  // meaning here is exactly same.
-  bool is_data_in =
-      ((req.type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN);
-
-  std::unique_ptr<TransportRequest> treq(new TransportRequest(
-      handle_,
-      [this, is_data_in, tag](bool is_success, const uint8_t* data,
-                              int32_t length) {
-        OnTransferComplete(tag, is_data_in, is_success, data, length);
-      },
-      req));
-
-  if (!is_data_in && req.length) {
-    // If disconnected prematurely, don't send response.
-    int32_t got = 0;
-    while (got < req.length) {
-      auto read = fd_->Read(&treq->Buffer()[got], req.length - got);
-      if (fd_->GetErrno() != 0) {
-        ALOGE("Failed to read from client: %s", fd_->StrError());
-        return;
-      } else if (read == 0) {
-        ALOGE("Failed to read from client: short read");
-        return;
-      }
-      got += read;
-    }
-  }
-
-  // At this point we store transport request internally until it completes.
-  TransportRequest* treq_ptr = treq.get();
-  {
-    cvd::LockGuard<cvd::Mutex> lock(requests_mutex_);
-    requests_in_flight_[tag] = std::move(treq);
-  }
-
-  if (!treq_ptr->Submit()) {
-    OnTransferComplete(tag, is_data_in, false, nullptr, 0);
-  }
-}
-
-void USBServer::HandleDataTransfer(uint32_t tag) {
-  DataTransfer req;
-  // If disconnected prematurely, don't send response.
-  if (fd_->Read(&req, sizeof(req)) != sizeof(req)) return;
-
-  bool is_data_in = !req.is_host_to_device;
-
-  std::unique_ptr<TransportRequest> treq(new TransportRequest(
-      handle_,
-      [this, is_data_in, tag](bool is_success, const uint8_t* data,
-                              int32_t length) {
-        OnTransferComplete(tag, is_data_in, is_success, data, length);
-      },
-      req));
-
-  if (!is_data_in && req.length) {
-    // If disconnected prematurely, don't send response.
-    int32_t got = 0;
-    while (got < req.length) {
-      auto read = fd_->Read(&treq->Buffer()[got], req.length - got);
-      if (fd_->GetErrno() != 0) {
-        ALOGE("Failed to read from client: %s", fd_->StrError());
-        return;
-      } else if (read == 0) {
-        ALOGE("Failed to read from client: short read");
-        return;
-      }
-      got += read;
-    }
-  }
-
-  // At this point we store transport request internally until it completes.
-  TransportRequest* treq_ptr = treq.get();
-  {
-    cvd::LockGuard<cvd::Mutex> lock(requests_mutex_);
-    requests_in_flight_[tag] = std::move(treq);
-  }
-
-  if (!treq_ptr->Submit()) {
-    OnTransferComplete(tag, is_data_in, false, nullptr, 0);
-  }
-}
-
-void USBServer::OnTransferComplete(uint32_t tag, bool is_data_in,
-                                   bool is_success, const uint8_t* buffer,
-                                   int32_t actual_length) {
-  ResponseHeader rsp{is_success ? StatusSuccess : StatusFailure, tag};
-
-  cvd::LockGuard<cvd::Mutex> lock(write_mutex_);
-  fd_->Write(&rsp, sizeof(rsp));
-  if (is_success && is_data_in) {
-    fd_->Write(&actual_length, sizeof(actual_length));
-    if (actual_length > 0) {
-      // NOTE: don't use buffer_ here directly, as libusb uses first few bytes
-      // to store control data there.
-      int32_t sent = 0;
-      while (sent < actual_length) {
-        int packet_size = fd_->Write(&buffer[sent], actual_length - sent);
-        sent += packet_size;
-        ALOGV("Sending response, %d / %d bytes sent", sent, actual_length);
-        if (fd_->GetErrno() != 0) {
-          ALOGE("Send failed: %s", fd_->StrError());
-          return;
-        }
-      }
-    }
-  }
-
-  {
-    cvd::LockGuard<cvd::Mutex> lock(requests_mutex_);
-    requests_in_flight_.erase(tag);
-  }
-}
-
-int USBServer::HandleDeviceEvent(libusb_context*, libusb_device*,
-                                 libusb_hotplug_event, void* self_raw) {
-  auto self = reinterpret_cast<USBServer*>(self_raw);
-  int64_t dummy = 1;
-  self->device_event_fd_->Write(&dummy, sizeof(dummy));
-  return 0;
-}
-
-void* USBServer::ProcessLibUSBRequests(void* self_raw) {
-  USBServer* self = reinterpret_cast<USBServer*>(self_raw);
-  ALOGI("Starting hotplug thread.");
-
-  cvd::SharedFDSet rset;
-  while (true) {
-    // Do not wait if there's no event.
-    timeval select_timeout{0, 0};
-    rset.Zero();
-    rset.Set(self->thread_event_fd_);
-    int ret = cvd::Select(&rset, nullptr, nullptr, &select_timeout);
-    if (ret > 0) break;
-
-    timeval libusb_timeout{1, 0};
-    libusb_handle_events_timeout_completed(nullptr, &libusb_timeout, nullptr);
-  }
-
-  int64_t dummy;
-  self->thread_event_fd_->Read(&dummy, sizeof(dummy));
-  ALOGI("Shutting down hotplug thread.");
-  return nullptr;
-}
-
-void USBServer::InitLibUSB() {
-  if (libusb_init(nullptr) != 0) return;
-  libusb_hotplug_register_callback(
-      nullptr,
-      libusb_hotplug_event(LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
-      libusb_hotplug_flag(0), kExportedVendorID, kExportedProductID,
-      LIBUSB_HOTPLUG_MATCH_ANY, &USBServer::HandleDeviceEvent, this,
-      &hotplug_handle_);
-  handle_ = GetDevice();
-  libusb_thread_.reset(new cvd::ScopedThread(&ProcessLibUSBRequests, this));
-}
-
-void USBServer::ExitLibUSB() {
-  if (!libusb_thread_) return;
-  libusb_hotplug_deregister_callback(nullptr, hotplug_handle_);
-  int64_t dummy = 1;
-  thread_event_fd_->Write(&dummy, sizeof(dummy));
-  libusb_thread_.reset();
-  handle_.reset();
-  libusb_exit(nullptr);
-}
-
-void USBServer::Serve() {
-  cvd::SharedFDSet rset;
-  while (true) {
-    timeval retry_timeout{1, 0};
-    timeval* select_timeout = nullptr;
-    if (!handle_) {
-      select_timeout = &retry_timeout;
-    }
-
-    rset.Zero();
-    rset.Set(fd_);
-    rset.Set(device_event_fd_);
-    int ret = cvd::Select(&rset, nullptr, nullptr, select_timeout);
-
-    // device_event_fd_ is reset each time libusb notices device has re-appeared
-    // or is gone. In both cases, the existing handle is no longer valid.
-    if (rset.IsSet(device_event_fd_)) {
-      int64_t dummy;
-      device_event_fd_->Read(&dummy, sizeof(dummy));
-      handle_.reset();
-    }
-
-    if (!handle_) {
-      ExitLibUSB();
-      InitLibUSB();
-      if (handle_) {
-        ALOGI("Device present.");
-      }
-    }
-
-    if (ret < 0) continue;
-
-    if (rset.IsSet(fd_)) {
-      RequestHeader req;
-      if (fd_->Read(&req, sizeof(req)) != sizeof(req)) {
-        // There's nobody on the other side.
-        sleep(3);
-        continue;
-      }
-
-      switch (req.command) {
-        case CmdDeviceList:
-          ALOGV("Processing DeviceList command, tag=%d", req.tag);
-          HandleDeviceList(req.tag);
-          break;
-
-        case CmdAttach:
-          ALOGV("Processing Attach command, tag=%d", req.tag);
-          HandleAttach(req.tag);
-          break;
-
-        case CmdControlTransfer:
-          ALOGV("Processing ControlTransfer command, tag=%d", req.tag);
-          HandleControlTransfer(req.tag);
-          break;
-
-        case CmdDataTransfer:
-          ALOGV("Processing DataTransfer command, tag=%d", req.tag);
-          HandleDataTransfer(req.tag);
-          break;
-
-        case CmdHeartbeat:
-          ALOGV("Processing Heartbeat command, tag=%d", req.tag);
-          HandleHeartbeat(req.tag);
-          break;
-
-        default:
-          ALOGE("Discarding unknown command %08x, tag=%d", req.command,
-                req.tag);
-      }
-    }
-  }
-}
-
-}  // namespace usb_forward
diff --git a/guest/commands/usbforward/usb_server.h b/guest/commands/usbforward/usb_server.h
deleted file mode 100644
index 77449b9..0000000
--- a/guest/commands/usbforward/usb_server.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#pragma once
-
-#include <map>
-#include <memory>
-#include <string>
-#include <libusb/libusb.h>
-
-#include "common/libs/fs/shared_fd.h"
-#include "common/libs/threads/cuttlefish_thread.h"
-#include "guest/commands/usbforward/transport_request.h"
-
-namespace usb_forward {
-
-// USBServer exposes access to USB devices over pipe (virtio channel etc).
-// Usage:
-//
-//     cvd::SharedFD pipe = cvd::SharedFD::Open(pipe_path, O_RDWR);
-//     USBServer server(pipe);
-//     CHECK(server.Init());
-//     server.Serve();
-class USBServer final {
- public:
-  USBServer(const cvd::SharedFD& fd);
-  ~USBServer() = default;
-
-  // Serve incoming USB requests.
-  void Serve();
-
- private:
-  // HandleDeviceEvent opens and closes Android Gadget device, whenever it
-  // appears / disappears.
-  static int HandleDeviceEvent(libusb_context*, libusb_device*,
-                                libusb_hotplug_event event, void* self_raw);
-
-  // Handle CmdDeviceList request.
-  void HandleDeviceList(uint32_t tag);
-
-  // Handle CmdAttach request.
-  void HandleAttach(uint32_t tag);
-
-  // Handle CmdControlTransfer request.
-  void HandleControlTransfer(uint32_t tag);
-
-  // Handle CmdDataTransfer request.
-  void HandleDataTransfer(uint32_t tag);
-
-  // Handle CmdHeartbeat request.
-  void HandleHeartbeat(uint32_t tag);
-
-  // OnAsyncDataTransferComplete handles end of asynchronous data transfer cycle
-  // and sends response back to caller.
-  void OnTransferComplete(uint32_t tag, bool is_data_in, bool is_success,
-                          const uint8_t* buffer, int32_t actual_length);
-
-  // Initialize, Configure and start libusb.
-  void InitLibUSB();
-
-  // Stop, Deconfigure and Clean up libusb.
-  void ExitLibUSB();
-
-  // Extract device info, if device is available.
-  bool GetDeviceInfo(DeviceInfo* info, std::vector<InterfaceInfo>* ifaces);
-
-  // Handle asynchronous libusb events.
-  static void* ProcessLibUSBRequests(void* self_ptr);
-
-  std::shared_ptr<libusb_device_handle> handle_;
-  libusb_hotplug_callback_handle hotplug_handle_;
-
-  std::unique_ptr<cvd::ScopedThread> libusb_thread_;
-  cvd::Mutex write_mutex_;
-  cvd::SharedFD fd_;
-  cvd::SharedFD device_event_fd_;
-  cvd::SharedFD thread_event_fd_;
-
-  cvd::Mutex requests_mutex_;
-  std::map<uint32_t, std::unique_ptr<TransportRequest>> requests_in_flight_;
-
-  USBServer(const USBServer& other) = delete;
-  USBServer& operator=(const USBServer& other) = delete;
-};
-
-}  // namespace usb_forward
diff --git a/guest/hals/camera/EmulatedCameraFactory.cpp b/guest/hals/camera/EmulatedCameraFactory.cpp
index 857f2ed..009e194 100644
--- a/guest/hals/camera/EmulatedCameraFactory.cpp
+++ b/guest/hals/camera/EmulatedCameraFactory.cpp
@@ -63,7 +63,7 @@
 
 EmulatedBaseCamera* EmulatedCameraFactory::getOrCreateFakeCamera(
     size_t cameraId) {
-  ::cvd::LockGuard< ::cvd::Mutex> lock(mEmulatedCamerasMutex);
+  std::lock_guard lock(mEmulatedCamerasMutex);
 
   if (cameraId >= getEmulatedCameraNum()) {
     ALOGE("%s: Invalid camera ID: %zu", __FUNCTION__, cameraId);
diff --git a/guest/hals/camera/EmulatedCameraFactory.h b/guest/hals/camera/EmulatedCameraFactory.h
index 1c5b9cd..f86ae1c 100644
--- a/guest/hals/camera/EmulatedCameraFactory.h
+++ b/guest/hals/camera/EmulatedCameraFactory.h
@@ -17,12 +17,14 @@
 #ifndef HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H
 #define HW_EMULATOR_CAMERA_EMULATED_CAMERA_FACTORY_H
 
+#include <mutex>
+
 #include <utils/RefBase.h>
 
 #include <utils/Vector.h>
 #include "CameraConfiguration.h"
 #include "EmulatedBaseCamera.h"
-#include "common/libs/threads/cuttlefish_thread.h"
+#include "common/libs/threads/thread_annotations.h"
 
 namespace android {
 
@@ -167,7 +169,7 @@
   Vector<EmulatedBaseCamera*> mEmulatedCameras;
 
   /* Guards access to mEmulatedCameras. */
-  cvd::Mutex mEmulatedCamerasMutex;
+  std::mutex mEmulatedCamerasMutex;
 
   /* Camera callbacks (for status changing) */
   const camera_module_callbacks_t* mCallbacks;
diff --git a/guest/hals/hwcomposer/common/stats_keeper.cpp b/guest/hals/hwcomposer/common/stats_keeper.cpp
index efff1d8..9e0d0d2 100644
--- a/guest/hals/hwcomposer/common/stats_keeper.cpp
+++ b/guest/hals/hwcomposer/common/stats_keeper.cpp
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 
 #include <algorithm>
+#include <mutex>
 #include <utility>
 #include <vector>
 
@@ -29,8 +30,6 @@
 
 #include "guest/hals/hwcomposer/common/geometry_utils.h"
 
-using cvd::LockGuard;
-using cvd::Mutex;
 using cvd::time::Microseconds;
 using cvd::time::MonotonicTimePoint;
 using cvd::time::Nanoseconds;
@@ -126,7 +125,7 @@
 
 void StatsKeeper::RecordSetEnd() {
   last_composition_stats_.set_end = MonotonicTimePoint::Now();
-  LockGuard<Mutex> lock(mutex_);
+  std::lock_guard lock(mutex_);
   num_set_calls_++;
   while (!raw_composition_data_.empty() &&
          period_length_ < last_composition_stats_.set_end -
@@ -189,7 +188,7 @@
 }
 
 void StatsKeeper::SynchronizedDump(char* buffer, int buffer_size) const {
-  LockGuard<Mutex> lock(mutex_);
+  std::lock_guard lock(mutex_);
   int chars_written = 0;
 // Make sure there is enough space to write the next line
 #define bprintf(...)                                                           \
diff --git a/guest/hals/hwcomposer/common/stats_keeper.h b/guest/hals/hwcomposer/common/stats_keeper.h
index 732bf58..116339d 100644
--- a/guest/hals/hwcomposer/common/stats_keeper.h
+++ b/guest/hals/hwcomposer/common/stats_keeper.h
@@ -16,11 +16,11 @@
  */
 
 #include <deque>
+#include <mutex>
 #include <set>
 
 #include <android-base/thread_annotations.h>
 
-#include "common/libs/threads/cuttlefish_thread.h"
 #include "common/libs/time/monotonic_time.h"
 
 #include "guest/hals/hwcomposer/common/base_composer.h"
@@ -143,7 +143,7 @@
   int64_t total_invisible_area GUARDED_BY(mutex_);
 
   // Controls access to data from past compositions.
-  mutable cvd::Mutex mutex_;
+  mutable std::mutex mutex_;
 };
 
 class WrappedScreenView : public ScreenView {
diff --git a/guest/monitoring/dumpstate_ext/Android.bp b/guest/monitoring/dumpstate_ext/Android.bp
index ba3320c..e679dc4 100644
--- a/guest/monitoring/dumpstate_ext/Android.bp
+++ b/guest/monitoring/dumpstate_ext/Android.bp
@@ -14,13 +14,14 @@
 // limitations under the License.
 
 cc_binary {
-    name: "android.hardware.dumpstate@1.0-service.cuttlefish",
+    name: "android.hardware.dumpstate@1.1-service.cuttlefish",
     srcs: [
         "dumpstate_device.cpp",
         "service.cpp",
     ],
     shared_libs: [
         "android.hardware.dumpstate@1.0",
+        "android.hardware.dumpstate@1.1",
         "libbase",
         "libcutils",
         "libdumpstateutil",
@@ -33,7 +34,7 @@
     ],
     relative_install_path: "hw",
     init_rc: [
-        "android.hardware.dumpstate@1.0-service.cuttlefish.rc",
+        "android.hardware.dumpstate@1.1-service.cuttlefish.rc",
     ],
     defaults: ["cuttlefish_guest_only"]
 }
diff --git a/guest/monitoring/dumpstate_ext/android.hardware.dumpstate@1.0-service.cuttlefish.rc b/guest/monitoring/dumpstate_ext/android.hardware.dumpstate@1.0-service.cuttlefish.rc
deleted file mode 100644
index ad68f35..0000000
--- a/guest/monitoring/dumpstate_ext/android.hardware.dumpstate@1.0-service.cuttlefish.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service.cuttlefish
-    class hal
-    user system
-    group system
diff --git a/guest/monitoring/dumpstate_ext/android.hardware.dumpstate@1.1-service.cuttlefish.rc b/guest/monitoring/dumpstate_ext/android.hardware.dumpstate@1.1-service.cuttlefish.rc
new file mode 100644
index 0000000..3fb31e3
--- /dev/null
+++ b/guest/monitoring/dumpstate_ext/android.hardware.dumpstate@1.1-service.cuttlefish.rc
@@ -0,0 +1,4 @@
+service dumpstate-1-1 /vendor/bin/hw/android.hardware.dumpstate@1.1-service.cuttlefish
+    class hal
+    user system
+    group system
diff --git a/guest/monitoring/dumpstate_ext/dumpstate_device.cpp b/guest/monitoring/dumpstate_ext/dumpstate_device.cpp
index d8481c7..48bc9d2 100644
--- a/guest/monitoring/dumpstate_ext/dumpstate_device.cpp
+++ b/guest/monitoring/dumpstate_ext/dumpstate_device.cpp
@@ -15,19 +15,26 @@
  */
 #include "guest/monitoring/dumpstate_ext/dumpstate_device.h"
 
-#include <log/log.h>
 #include <DumpstateUtil.h>
+#include <log/log.h>
 
 using android::os::dumpstate::DumpFileToFd;
 
 namespace android {
 namespace hardware {
 namespace dumpstate {
-namespace V1_0 {
+namespace V1_1 {
 namespace implementation {
 
 // Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
 Return<void> DumpstateDevice::dumpstateBoard(const hidl_handle& handle) {
+  return dumpstateBoard_1_1(handle, DumpstateMode::DEFAULT, 30 * 1000 /* timeoutMillis */);
+}
+
+// Methods from ::android::hardware::dumpstate::V1_1::IDumpstateDevice follow.
+Return<void> DumpstateDevice::dumpstateBoard_1_1(const hidl_handle& handle,
+                                                 DumpstateMode mode,
+                                                 uint64_t /* timeoutMillis */) {
   if (handle == nullptr || handle->numFds < 1) {
     ALOGE("no FDs\n");
     return Void();
@@ -39,13 +46,23 @@
     return Void();
   }
 
+  if (mode < DumpstateMode::FULL || mode > DumpstateMode::DEFAULT) {
+    ALOGE("Invalid mode: %d\n", mode);
+    return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+  }
+
   DumpFileToFd(fd, "GCE INITIAL METADATA", "/initial.metadata");
 
   return Void();
 }
 
+Return<bool> DumpstateDevice::setDeviceLoggingEnabled(bool /* enable */) {
+  // Unsupported operation.
+  return false;
+}
+
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace dumpstate
 }  // namespace hardware
 }  // namespace android
diff --git a/guest/monitoring/dumpstate_ext/dumpstate_device.h b/guest/monitoring/dumpstate_ext/dumpstate_device.h
index 581a96b..2f6990d 100644
--- a/guest/monitoring/dumpstate_ext/dumpstate_device.h
+++ b/guest/monitoring/dumpstate_ext/dumpstate_device.h
@@ -15,19 +15,21 @@
  */
 #pragma once
 
-#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
+#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
+#include <android/hardware/dumpstate/1.1/types.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
 namespace android {
 namespace hardware {
 namespace dumpstate {
-namespace V1_0 {
+namespace V1_1 {
 namespace implementation {
 
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_1::DumpstateMode;
+using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
@@ -37,10 +39,15 @@
 struct DumpstateDevice : public IDumpstateDevice {
   // Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
   Return<void> dumpstateBoard(const hidl_handle& h) override;
+
+  // Methods from ::android::hardware::dumpstate::V1_1::IDumpstateDevice follow.
+  Return<void> dumpstateBoard_1_1(const hidl_handle& h, DumpstateMode mode,
+                                  uint64_t timeoutMillis) override;
+  Return<bool> setDeviceLoggingEnabled(bool enable) override;
 };
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace dumpstate
 }  // namespace hardware
 }  // namespace android
diff --git a/guest/monitoring/dumpstate_ext/service.cpp b/guest/monitoring/dumpstate_ext/service.cpp
index 67eebe5..d8f339c 100644
--- a/guest/monitoring/dumpstate_ext/service.cpp
+++ b/guest/monitoring/dumpstate_ext/service.cpp
@@ -20,8 +20,8 @@
 
 using ::android::OK;
 using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
-using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
+using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_1::implementation::DumpstateDevice;
 using ::android::hardware::joinRpcThreadpool;
 using ::android::sp;
 
diff --git a/host/commands/assemble_cvd/Android.bp b/host/commands/assemble_cvd/Android.bp
index 18b846f..fcfa903 100644
--- a/host/commands/assemble_cvd/Android.bp
+++ b/host/commands/assemble_cvd/Android.bp
@@ -62,7 +62,8 @@
     defaults: ["cuttlefish_host_only", "cuttlefish_libicuuc"],
 }
 
-sh_binary_host {
+python_binary_host {
     name: "cf_bpttool",
-    src: "cf_bpttool",
+    srcs: [ "cf_bpttool.py" ],
+    defaults: ["py2_only"],
 }
diff --git a/host/commands/assemble_cvd/cf_bpttool b/host/commands/assemble_cvd/cf_bpttool.py
similarity index 100%
rename from host/commands/assemble_cvd/cf_bpttool
rename to host/commands/assemble_cvd/cf_bpttool.py
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index b30cedc..0ec8ea2 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -466,9 +466,9 @@
   // The global link to the config file
   prior_files += " " + vsoc::GetGlobalConfigFileLink();
   LOG(INFO) << "Assuming prior files of " << prior_files;
-  std::string fuser_cmd = "fuser " + prior_files + " 2> /dev/null";
-  int rval = std::system(fuser_cmd.c_str());
-  // fuser returns 0 if any of the files are open
+  std::string lsof_cmd = "lsof -t " + prior_files + " >/dev/null 2>&1";
+  int rval = std::system(lsof_cmd.c_str());
+  // lsof returns 0 if any of the files are open
   if (WEXITSTATUS(rval) == 0) {
     LOG(ERROR) << "Clean aborted: files are in use";
     return false;
diff --git a/host/commands/assemble_cvd/super_image_mixer.cc b/host/commands/assemble_cvd/super_image_mixer.cc
index fcc0dc1..78d2750 100644
--- a/host/commands/assemble_cvd/super_image_mixer.cc
+++ b/host/commands/assemble_cvd/super_image_mixer.cc
@@ -46,9 +46,8 @@
     }
     std::string expected_filename = "target_files-" + file_iter.second.build_id;
     if (file_path.find(expected_filename) != std::string::npos) {
-      continue;
+      return file_path;
     }
-    return file_path;;
   }
   return "";
 }
diff --git a/host/commands/stop_cvd/main.cc b/host/commands/stop_cvd/main.cc
index a598f3d..7d425a0 100644
--- a/host/commands/stop_cvd/main.cc
+++ b/host/commands/stop_cvd/main.cc
@@ -52,7 +52,7 @@
 namespace {
 // Gets a set of the possible process groups of a previous launch
 std::set<pid_t> GetCandidateProcessGroups() {
-  std::string cmd = "fuser";
+  std::string cmd = "lsof -t 2>/dev/null";
   // Add the instance directory
   auto instance_dir = cvd::StringFromEnv("HOME", ".") + "/cuttlefish_runtime";
   cmd += " " + instance_dir;
diff --git a/host/frontend/adb_connector/Android.bp b/host/frontend/adb_connector/Android.bp
index 41fa1f6..c0f04cd 100644
--- a/host/frontend/adb_connector/Android.bp
+++ b/host/frontend/adb_connector/Android.bp
@@ -16,13 +16,13 @@
 cc_binary_host {
     name: "adb_connector",
     srcs: [
+        "adb_connection_maintainer.cpp",
         "main.cpp"
     ],
     header_libs: [
         "cuttlefish_glog",
     ],
     static_libs: [
-        "libadb_connection_maintainer",
         "libgflags",
     ],
     shared_libs: [
diff --git a/host/libs/adb_connection_maintainer/adb_connection_maintainer.cpp b/host/frontend/adb_connector/adb_connection_maintainer.cpp
similarity index 98%
rename from host/libs/adb_connection_maintainer/adb_connection_maintainer.cpp
rename to host/frontend/adb_connector/adb_connection_maintainer.cpp
index 1336951..6b60e34 100644
--- a/host/libs/adb_connection_maintainer/adb_connection_maintainer.cpp
+++ b/host/frontend/adb_connector/adb_connection_maintainer.cpp
@@ -25,7 +25,7 @@
 #include <unistd.h>
 
 #include "common/libs/fs/shared_fd.h"
-#include "host/libs/adb_connection_maintainer/adb_connection_maintainer.h"
+#include "host/frontend/adb_connector/adb_connection_maintainer.h"
 
 namespace {
 
diff --git a/host/libs/adb_connection_maintainer/adb_connection_maintainer.h b/host/frontend/adb_connector/adb_connection_maintainer.h
similarity index 100%
rename from host/libs/adb_connection_maintainer/adb_connection_maintainer.h
rename to host/frontend/adb_connector/adb_connection_maintainer.h
diff --git a/host/frontend/adb_connector/main.cpp b/host/frontend/adb_connector/main.cpp
index 3d3d824..a6f8ebe 100644
--- a/host/frontend/adb_connector/main.cpp
+++ b/host/frontend/adb_connector/main.cpp
@@ -28,8 +28,8 @@
 #include <host/commands/kernel_log_monitor/kernel_log_server.h>
 
 #include "common/libs/fs/shared_fd.h"
+#include "host/frontend/adb_connector/adb_connection_maintainer.h"
 #include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/adb_connection_maintainer/adb_connection_maintainer.h"
 
 DEFINE_string(addresses, "", "Comma-separated list of addresses to "
                              "'adb connect' to");
diff --git a/host/libs/adb_connection_maintainer/Android.bp b/host/libs/adb_connection_maintainer/Android.bp
deleted file mode 100644
index 4a89da3..0000000
--- a/host/libs/adb_connection_maintainer/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_library_host_static {
-    name: "libadb_connection_maintainer",
-    srcs: [
-        "adb_connection_maintainer.cpp",
-    ],
-    header_libs: [
-        "cuttlefish_glog",
-    ],
-    shared_libs: [
-        "libbase",
-    ],
-    defaults: ["cuttlefish_host_only"],
-}
diff --git a/host/libs/vm_manager/vm_manager.cpp b/host/libs/vm_manager/vm_manager.cpp
index 40fa828..d2810da 100644
--- a/host/libs/vm_manager/vm_manager.cpp
+++ b/host/libs/vm_manager/vm_manager.cpp
@@ -117,7 +117,7 @@
   return true;
 }
 
-bool VmManager::LinuxVersionAtLeast4_8(std::vector<std::string>* config_commands) {
+std::pair<int,int> VmManager::GetLinuxVersion() {
   struct utsname info;
   if (!uname(&info)) {
     char* digit = strtok(info.release, "+.-");
@@ -125,24 +125,57 @@
     if (digit) {
       digit = strtok(NULL, "+.-");
       int minor = atoi(digit);
-      if (major > 4 || (major == 4 && minor >= 8)) {
-        return true;
-      }
+      return std::pair<int,int>{major, minor};
     }
   }
-  LOG(ERROR) << "Kernel version must be >=4.8";
-  config_commands->push_back("# Please upgrade your kernel to >=4.8");
+  LOG(ERROR) << "Failed to detect Linux kernel version";
+  return invalid_linux_version;
+}
+
+bool VmManager::LinuxVersionAtLeast(std::vector<std::string>* config_commands,
+                                    const std::pair<int,int>& version,
+                                    int major, int minor) {
+  if (version.first > major ||
+      (version.first == major && version.second >= minor)) {
+    return true;
+  }
+
+  LOG(ERROR) << "Kernel version must be >=" << major << "." << minor
+             << ", have " << version.first << "." << version.second;
+  config_commands->push_back("# Please upgrade your kernel to >=" +
+                             std::to_string(major) + "." +
+                             std::to_string(minor));
   return false;
 }
 
 bool VmManager::ValidateHostConfiguration(
     std::vector<std::string>* config_commands) const {
+  // if we can't detect the kernel version, just fail
+  auto version = VmManager::GetLinuxVersion();
+  if (version == invalid_linux_version) {
+    return false;
+  }
+
   // the check for cvdnetwork needs to happen even if the user is not in kvm, so
   // we can't just say UserInGroup("kvm") && UserInGroup("cvdnetwork")
-  auto in_kvm = VmManager::UserInGroup("kvm", config_commands);
   auto in_cvdnetwork = VmManager::UserInGroup("cvdnetwork", config_commands);
-  auto linux_ver_4_8 = VmManager::LinuxVersionAtLeast4_8(config_commands);
-  return in_kvm && in_cvdnetwork && linux_ver_4_8;
+
+  // if we're in the virtaccess group this is likely to be a CrOS environment.
+  auto is_cros = cvd::InGroup("virtaccess");
+  if (is_cros) {
+    // relax the minimum kernel requirement slightly, as chromeos-4.4 has the
+    // needed backports to enable vhost_vsock
+    auto linux_ver_4_4 =
+      VmManager::LinuxVersionAtLeast(config_commands, version, 4, 4);
+    return in_cvdnetwork && linux_ver_4_4;
+  } else {
+    // this is regular Linux, so use the Debian group name and be more
+    // conservative with the kernel version check.
+    auto in_kvm = VmManager::UserInGroup("kvm", config_commands);
+    auto linux_ver_4_8 =
+      VmManager::LinuxVersionAtLeast(config_commands, version, 4, 8);
+    return in_cvdnetwork && in_kvm && linux_ver_4_8;
+  }
 }
 
 void VmManager::WithFrontend(bool enabled) {
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index a14ad05..a86218c 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -60,7 +60,12 @@
  protected:
   static bool UserInGroup(const std::string& group,
                           std::vector<std::string>* config_commands);
-  static bool LinuxVersionAtLeast4_8(std::vector<std::string>* config_commands);
+  static constexpr std::pair<int,int> invalid_linux_version =
+    std::pair<int,int>();
+  static std::pair<int,int> GetLinuxVersion();
+  static bool LinuxVersionAtLeast(std::vector<std::string>* config_commands,
+                                  const std::pair<int,int>& version,
+                                  int major, int minor);
 
   const vsoc::CuttlefishConfig* config_;
   VmManager(const vsoc::CuttlefishConfig* config);
diff --git a/shared/auto/OWNERS b/shared/auto/OWNERS
new file mode 100644
index 0000000..53bbd52
--- /dev/null
+++ b/shared/auto/OWNERS
@@ -0,0 +1,3 @@
+# Android Auto leads
+ankitarora@google.com
+egranata@google.com
diff --git a/shared/auto/device.mk b/shared/auto/device.mk
index 30ff594..e0693e5 100644
--- a/shared/auto/device.mk
+++ b/shared/auto/device.mk
@@ -57,7 +57,10 @@
     vendor.rild.libpath=libcuttlefish-ril.so \
 
 # vehicle HAL
-PRODUCT_PACKAGES += android.hardware.automotive.vehicle@2.0-service
+ifeq ($(LOCAL_VHAL_PRODUCT_PACKAGE),)
+    LOCAL_VHAL_PRODUCT_PACKAGE := android.hardware.automotive.vehicle@2.0-service
+endif
+PRODUCT_PACKAGES += $(LOCAL_VHAL_PRODUCT_PACKAGE)
 
 # Broadcast Radio
 PRODUCT_PACKAGES += android.hardware.broadcastradio@2.0-service
diff --git a/shared/config/fstab.composite b/shared/config/fstab.composite
deleted file mode 100644
index afacfe4..0000000
--- a/shared/config/fstab.composite
+++ /dev/null
@@ -1,13 +0,0 @@
-boot /boot emmc defaults recoveryonly
-system /system ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect
-# Add all non-dynamic partitions except system, after this comment
-/dev/block/by-name/userdata /data ext4 nodev,noatime,nosuid,errors=panic wait,fileencryption=aes-256-xts:aes-256-cts,fsverity
-/dev/block/by-name/cache /cache ext4 nodev,noatime,nosuid,errors=panic wait
-/dev/block/by-name/metadata /metadata ext4 nodev,noatime,nosuid,errors=panic wait,formattable,first_stage_mount
-/dev/block/by-name/misc /misc emmc defaults defaults
-# Add all dynamic partitions except system, after this comment
-vendor /vendor ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect
-product /product ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect
-system_ext /system_ext ext4 noatime,ro,errors=panic wait,logical,first_stage_mount,slotselect
-/dev/block/zram0 none swap defaults zramsize=75%
-/tmp /sdcard none defaults,bind recoveryonly
diff --git a/shared/config/manifest.xml b/shared/config/manifest.xml
index 6783068..2d728e9 100644
--- a/shared/config/manifest.xml
+++ b/shared/config/manifest.xml
@@ -137,7 +137,7 @@
     <hal format="hidl">
         <name>android.hardware.dumpstate</name>
         <transport>hwbinder</transport>
-        <version>1.0</version>
+        <version>1.1</version>
         <interface>
             <name>IDumpstateDevice</name>
             <instance>default</instance>
diff --git a/shared/device.mk b/shared/device.mk
index 491d8e5..327e9fb 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -17,6 +17,9 @@
 # Enable updating of APEXes
 $(call inherit-product, $(SRC_TARGET_DIR)/product/updatable_apex.mk)
 
+# Enable userspace reboot
+$(call inherit-product, $(SRC_TARGET_DIR)/product/userspace_reboot.mk)
+
 PRODUCT_SHIPPING_API_LEVEL := 29
 PRODUCT_BUILD_BOOT_IMAGE := true
 PRODUCT_USE_DYNAMIC_PARTITIONS := true
@@ -66,7 +69,6 @@
 #
 PRODUCT_PACKAGES += \
     socket_vsock_proxy \
-    usbforward \
     CuttlefishService \
     wpa_supplicant.vsoc.conf \
     vsoc_input_service \
@@ -110,6 +112,12 @@
 PRODUCT_PACKAGES += \
     vulkan.pastel
 
+#
+# Packages for testing
+#
+PRODUCT_PACKAGES += \
+    aidl_lazy_test_server
+
 DEVICE_PACKAGE_OVERLAYS := device/google/cuttlefish/shared/overlay
 # PRODUCT_AAPT_CONFIG and PRODUCT_AAPT_PREF_CONFIG are intentionally not set to
 # pick up every density resources.
@@ -228,7 +236,7 @@
 # Dumpstate HAL
 #
 PRODUCT_PACKAGES += \
-    android.hardware.dumpstate@1.0-service.cuttlefish
+    android.hardware.dumpstate@1.1-service.cuttlefish
 
 #
 # Camera
diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts
index ac4cf3d..bc9ab47 100644
--- a/shared/sepolicy/vendor/file_contexts
+++ b/shared/sepolicy/vendor/file_contexts
@@ -48,7 +48,6 @@
 #############################
 # Vendor files
 #
-/vendor/bin/usbforward  u:object_r:usbforward_exec:s0
 /vendor/bin/socket_vsock_proxy  u:object_r:socket_vsock_proxy_exec:s0
 /vendor/bin/vsock_logcat  u:object_r:vsock_logcat_exec:s0
 /vendor/bin/vsoc_input_service  u:object_r:vsoc_input_service_exec:s0
@@ -61,7 +60,7 @@
 /vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service-lazy\.clearkey  u:object_r:hal_drm_clearkey_exec:s0
 /vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service\.widevine  u:object_r:hal_drm_widevine_exec:s0
 /vendor/bin/hw/android\.hardware\.drm@[0-9]+\.[0-9]+-service-lazy\.widevine  u:object_r:hal_drm_widevine_exec:s0
-/vendor/bin/hw/android\.hardware\.dumpstate@1\.0-service\.cuttlefish  u:object_r:hal_dumpstate_impl_exec:s0
+/vendor/bin/hw/android\.hardware\.dumpstate@1\.1-service\.cuttlefish  u:object_r:hal_dumpstate_impl_exec:s0
 /vendor/bin/hw/android\.hardware\.gatekeeper@1\.0-service\.software  u:object_r:hal_gatekeeper_default_exec:s0
 /vendor/bin/hw/android\.hardware\.health\.storage@1\.0-service\.cuttlefish u:object_r:hal_health_storage_default_exec:s0
 /vendor/bin/hw/android\.hardware\.neuralnetworks@1\.3-service-sample-.*   u:object_r:hal_neuralnetworks_sample_exec:s0
diff --git a/vsoc_arm64/auto/OWNERS b/vsoc_arm64/auto/OWNERS
new file mode 100644
index 0000000..53bbd52
--- /dev/null
+++ b/vsoc_arm64/auto/OWNERS
@@ -0,0 +1,3 @@
+# Android Auto leads
+ankitarora@google.com
+egranata@google.com
diff --git a/vsoc_x86/auto/OWNERS b/vsoc_x86/auto/OWNERS
new file mode 100644
index 0000000..53bbd52
--- /dev/null
+++ b/vsoc_x86/auto/OWNERS
@@ -0,0 +1,3 @@
+# Android Auto leads
+ankitarora@google.com
+egranata@google.com