Merge "Adds host test to check that gfxstream enabled"
diff --git a/guest/commands/bt_vhci_forwarder/Android.bp b/guest/commands/bt_vhci_forwarder/Android.bp
new file mode 100644
index 0000000..6260b17
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/Android.bp
@@ -0,0 +1,15 @@
+cc_binary {
+    name: "bt_vhci_forwarder",
+    srcs: [
+        "main.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+    ],
+    static_libs: [
+        "libgflags",
+    ],
+    defaults: ["cuttlefish_guest_only"]
+}
diff --git a/guest/commands/bt_vhci_forwarder/main.cpp b/guest/commands/bt_vhci_forwarder/main.cpp
new file mode 100644
index 0000000..6920b62
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/main.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 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 <fcntl.h>
+#include <sys/poll.h>
+#include <termios.h>
+#include <unistd.h>
+#include <iomanip>
+#include <ios>
+#include <optional>
+
+#include <gflags/gflags.h>
+
+#include "android-base/logging.h"
+
+// Copied from net/bluetooth/hci.h
+#define HCI_VENDOR_PKT 0xff
+#define HCI_MAX_ACL_SIZE 1024
+#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
+
+// Include H4 header byte, and reserve more buffer size in the case of excess
+// packet.
+constexpr const size_t kBufferSize = (HCI_MAX_FRAME_SIZE + 1) * 2;
+
+constexpr const char* kVhciDev = "/dev/vhci";
+DEFINE_string(virtio_console_dev, "", "virtio-console device path");
+
+ssize_t forward(int from, int to, std::optional<unsigned char> filter_out,
+                unsigned char* buf) {
+  ssize_t count = TEMP_FAILURE_RETRY(read(from, buf, kBufferSize));
+  if (count < 0) {
+    PLOG(ERROR) << "read failed";
+    return count;
+  } else if (count == 0) {
+    return count;
+  }
+  if (filter_out && buf[0] == *filter_out) {
+    LOG(INFO) << "ignore 0x" << std::hex << std::setw(2) << std::setfill('0')
+              << (unsigned)buf[0] << " packet";
+    return 0;
+  }
+  count = TEMP_FAILURE_RETRY(write(to, buf, count));
+  if (count < 0) {
+    PLOG(ERROR) << "write failed, type: 0x" << std::hex << std::setw(2)
+               << std::setfill('0') << (unsigned)buf[0];
+  }
+  return count;
+}
+
+ssize_t forward(int from, int to, unsigned char* buf) {
+  return forward(from, to, std::nullopt, buf);
+}
+
+int setTerminalRaw(int fd_) {
+  termios terminal_settings;
+  int rval = tcgetattr(fd_, &terminal_settings);
+  if (rval < 0) {
+    return rval;
+  }
+  cfmakeraw(&terminal_settings);
+  rval = tcsetattr(fd_, TCSANOW, &terminal_settings);
+  return rval;
+}
+
+int main(int argc, char** argv) {
+  gflags::ParseCommandLineFlags(&argc, &argv, true);
+
+  int vhci_fd = open(kVhciDev, O_RDWR);
+  int virtio_fd = open(FLAGS_virtio_console_dev.c_str(), O_RDWR);
+  setTerminalRaw(virtio_fd);
+
+  struct pollfd fds[2];
+
+  fds[0].fd = vhci_fd;
+  fds[0].events = POLLIN;
+  fds[1].fd = virtio_fd;
+  fds[1].events = POLLIN;
+  unsigned char buf[kBufferSize];
+
+  while (true) {
+    int ret = TEMP_FAILURE_RETRY(poll(fds, 2, -1));
+    if (ret < 0) {
+      PLOG(ERROR) << "poll failed";
+      continue;
+    }
+    if (fds[0].revents & (POLLIN | POLLERR)) {
+      // TODO(b/182245475) Ignore HCI_VENDOR_PKT
+      // because root-canal cannot handle it.
+      ssize_t c = forward(vhci_fd, virtio_fd, HCI_VENDOR_PKT, buf);
+      if (c < 0) {
+        PLOG(ERROR) << "vhci to virtio-console failed";
+      }
+    }
+
+    if (fds[1].revents & (POLLIN | POLLERR)) {
+      ssize_t c = forward(virtio_fd, vhci_fd, buf);
+      if (c < 0) {
+        PLOG(ERROR) << "virtio-console to vhci failed";
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/host/commands/assemble_cvd/boot_image_utils.cc b/host/commands/assemble_cvd/boot_image_utils.cc
index 572fd41..285daa4 100644
--- a/host/commands/assemble_cvd/boot_image_utils.cc
+++ b/host/commands/assemble_cvd/boot_image_utils.cc
@@ -241,13 +241,19 @@
   bootconfig_fd->Write(bootconfig.c_str(), bootconfig.size());
   LOG(DEBUG) << "Bootconfig parameters from vendor boot image and config are "
              << ReadFile(instance_internal_dir + "/bootconfig");
-
   std::string vendor_boot_params = ReadFile(build_dir + "/vendor_boot_params");
   auto kernel_cmdline =
       ExtractValue(vendor_boot_params, "vendor command line args: ") +
       (bootconfig_supported
            ? ""
            : " " + android::base::StringReplace(bootconfig, "\n", " ", true));
+  if (!bootconfig_supported) {
+    // "androidboot.hardware" kernel parameter has changed to "hardware" in
+    // bootconfig and needs to be replaced before being used in the kernel
+    // cmdline.
+    kernel_cmdline = android::base::StringReplace(
+        kernel_cmdline, " hardware=", " androidboot.hardware=", true);
+  }
   LOG(DEBUG) << "Cmdline from vendor boot image is " << kernel_cmdline;
 
   auto tmp_vendor_boot_image_path = new_vendor_boot_image_path + TMP_EXTENSION;
diff --git a/host/commands/assemble_cvd/flags.cc b/host/commands/assemble_cvd/flags.cc
index de047ff..af84f33 100644
--- a/host/commands/assemble_cvd/flags.cc
+++ b/host/commands/assemble_cvd/flags.cc
@@ -731,7 +731,7 @@
 
   // If the user specifies a --config name, then use that config
   // preset option.
-  std::string android_info_path = DefaultGuestImagePath("/android-info.txt");
+  std::string android_info_path = FLAGS_system_image_dir + "/android-info.txt";
   if (IsFlagSet("config")) {
     if (!allowed_config_presets.count(config_preset)) {
       LOG(FATAL) << "Invalid --config option '" << config_preset
diff --git a/host/commands/bt_connector/main.cpp b/host/commands/bt_connector/main.cpp
index 1b8d291..fc17b31 100644
--- a/host/commands/bt_connector/main.cpp
+++ b/host/commands/bt_connector/main.cpp
@@ -28,6 +28,14 @@
 #include "host/libs/config/cuttlefish_config.h"
 #include "host/libs/config/logging.h"
 
+// Copied from net/bluetooth/hci.h
+#define HCI_MAX_ACL_SIZE 1024
+#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
+
+// Include H4 header byte, and reserve more buffer size in the case of excess
+// packet.
+constexpr const size_t kBufferSize = (HCI_MAX_FRAME_SIZE + 1) * 2;
+
 DEFINE_int32(bt_in, -1, "A pipe for bt communication");
 DEFINE_int32(bt_out, -1, "A pipe for bt communication");
 DEFINE_int32(hci_port, -1, "A port for bt hci command");
@@ -63,7 +71,7 @@
 
   auto guest_to_host = std::thread([&]() {
     while (true) {
-      char buf[1024];
+      char buf[kBufferSize];
       auto read = bt_in->Read(buf, sizeof(buf));
       while (cuttlefish::WriteAll(sock, buf, read) == -1) {
         LOG(ERROR) << "failed to write to socket, retry.";
@@ -76,7 +84,7 @@
 
   auto host_to_guest = std::thread([&]() {
     while (true) {
-      char buf[1024];
+      char buf[kBufferSize];
       auto read = sock->Read(buf, sizeof(buf));
       if (read == -1) {
         LOG(ERROR) << "failed to read from socket, retry.";
diff --git a/host/libs/config/bootconfig_args.cpp b/host/libs/config/bootconfig_args.cpp
index f48a96b..b7c7f7a 100644
--- a/host/libs/config/bootconfig_args.cpp
+++ b/host/libs/config/bootconfig_args.cpp
@@ -86,7 +86,7 @@
   auto vmm = vm_manager::GetVmManager(config.vm_manager());
   AppendVector(&bootconfig_args,
                vmm->ConfigureBootDevices(instance.virtual_disk_paths().size()));
-  // TODO(b/173815685): Resolve issue with androidboot.hardware and add GpuMode
+  AppendVector(&bootconfig_args, vmm->ConfigureGpuMode(config.gpu_mode()));
 
   bootconfig_args.push_back(
       concat("androidboot.serialno=", instance.serial_number()));
diff --git a/host/libs/config/kernel_args.cpp b/host/libs/config/kernel_args.cpp
index c4789dc..7a9a40e 100644
--- a/host/libs/config/kernel_args.cpp
+++ b/host/libs/config/kernel_args.cpp
@@ -24,13 +24,11 @@
 #include "common/libs/utils/environment.h"
 #include "common/libs/utils/files.h"
 #include "host/libs/config/cuttlefish_config.h"
-#include "host/libs/vm_manager/crosvm_manager.h"
 #include "host/libs/vm_manager/qemu_manager.h"
 #include "host/libs/vm_manager/vm_manager.h"
 
 namespace cuttlefish {
 
-using vm_manager::CrosvmManager;
 using vm_manager::QemuManager;
 
 namespace {
@@ -100,8 +98,6 @@
   std::vector<std::string> kernel_cmdline;
 
   AppendVector(&kernel_cmdline, VmManagerKernelCmdline(config));
-  auto vmm = vm_manager::GetVmManager(config.vm_manager());
-  AppendVector(&kernel_cmdline, vmm->ConfigureGpuMode(config.gpu_mode()));
 
   if (config.enable_gnss_grpc_proxy()) {
     kernel_cmdline.push_back("gnss_cmdline.serdev=serial8250/serial0/serial0-0");
diff --git a/shared/BoardConfig.mk b/shared/BoardConfig.mk
index c77440d..7be8375 100644
--- a/shared/BoardConfig.mk
+++ b/shared/BoardConfig.mk
@@ -158,6 +158,8 @@
 
 # vendor sepolicy
 BOARD_VENDOR_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/vendor
+
+BOARD_SEPOLICY_DIRS += system/bt/vendor_libs/linux/sepolicy
 BOARD_VENDOR_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/vendor/google
 # product sepolicy, allow other layers to append
 PRODUCT_PRIVATE_SEPOLICY_DIRS += device/google/cuttlefish/shared/sepolicy/product/private
@@ -202,7 +204,7 @@
 BOARD_KERNEL_CMDLINE += firmware_class.path=/vendor/etc/
 
 BOARD_KERNEL_CMDLINE += init=/init
-BOARD_BOOTCONFIG += androidboot.hardware=cutf_cvm
+BOARD_BOOTCONFIG += hardware=cutf_cvm
 
 # TODO(b/176860479): Remove once goldfish and cuttlefish share a wifi implementation
 BOARD_KERNEL_CMDLINE += mac80211_hwsim.radios=0
diff --git a/shared/config/init.vendor.rc b/shared/config/init.vendor.rc
index af05896..3cd5a02 100644
--- a/shared/config/init.vendor.rc
+++ b/shared/config/init.vendor.rc
@@ -49,6 +49,8 @@
     # works around framework netiface enumeration issue
     start rename_eth1
 
+    start bt_vhci_forwarder
+
     # So GceBootReporter can print to kmsg
     chmod 622 /dev/kmsg
 
@@ -76,6 +78,10 @@
     mkdir /data/vendor/wifi/wpa/sockets 0770 wifi wifi
     start socket_vsock_proxy
 
+service bt_vhci_forwarder /vendor/bin/bt_vhci_forwarder -virtio_console_dev=/dev/hvc5
+    user bluetooth
+    group bluetooth
+
 service setup_wifi /vendor/bin/setup_wifi
     oneshot
 
diff --git a/shared/config/ueventd.rc b/shared/config/ueventd.rc
index f214300..84d2806 100644
--- a/shared/config/ueventd.rc
+++ b/shared/config/ueventd.rc
@@ -24,6 +24,7 @@
 
 # bluetooth
 /dev/hvc5 0660 bluetooth bluetooth
+/dev/vhci 0660 bluetooth bluetooth
 
 /dev/gnss0 0666 system system
 
diff --git a/shared/device.mk b/shared/device.mk
index a9f1f9b..8f43661 100644
--- a/shared/device.mk
+++ b/shared/device.mk
@@ -43,6 +43,7 @@
 # Depends on TARGET_PRODUCT because TARGET_ARCH is not available here.
 ifneq ($(findstring x86,$(TARGET_PRODUCT)),)
 TARGET_ENABLE_HOST_BLUETOOTH_EMULATION ?= true
+TARGET_USE_BTLINUX_HAL_IMPL ?= true
 endif
 
 AB_OTA_UPDATER := true
@@ -149,6 +150,7 @@
     cuttlefish_rotate \
     rename_netiface \
     setup_wifi \
+    bt_vhci_forwarder \
     socket_vsock_proxy \
     tombstone_transmit \
     tombstone_producer \
@@ -372,9 +374,13 @@
 #
 
 ifeq ($(TARGET_ENABLE_HOST_BLUETOOTH_EMULATION),true)
-PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.remote
+ifeq ($(TARGET_USE_BTLINUX_HAL_IMPL),true)
+    PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.btlinux
 else
-PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.sim
+    PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.remote
+endif
+else
+    PRODUCT_PACKAGES += android.hardware.bluetooth@1.1-service.sim
 endif
 PRODUCT_PACKAGES += android.hardware.bluetooth.audio@2.1-impl
 
diff --git a/shared/sepolicy/system_ext/private/traceur_app.te b/shared/sepolicy/system_ext/private/traceur_app.te
new file mode 100644
index 0000000..ed1bead
--- /dev/null
+++ b/shared/sepolicy/system_ext/private/traceur_app.te
@@ -0,0 +1 @@
+gpu_access(traceur_app)
diff --git a/shared/sepolicy/vendor/bt_vhci_forwarder.te b/shared/sepolicy/vendor/bt_vhci_forwarder.te
new file mode 100644
index 0000000..2172696
--- /dev/null
+++ b/shared/sepolicy/vendor/bt_vhci_forwarder.te
@@ -0,0 +1,6 @@
+type bt_vhci_forwarder, domain;
+type bt_vhci_forwarder_exec, exec_type, vendor_file_type, file_type;
+
+init_daemon_domain(bt_vhci_forwarder)
+
+allow bt_vhci_forwarder bt_device:chr_file { open read write ioctl};
diff --git a/shared/sepolicy/vendor/file_contexts b/shared/sepolicy/vendor/file_contexts
index 6ff4871..8a5004a 100644
--- a/shared/sepolicy/vendor/file_contexts
+++ b/shared/sepolicy/vendor/file_contexts
@@ -24,6 +24,8 @@
 /dev/hvc4  u:object_r:gatekeeper_device:s0
 /dev/hvc5  u:object_r:bt_device:s0
 
+/dev/vhci  u:object_r:bt_device:s0
+
 # ARM serial console device
 /dev/ttyAMA[0-9]*  u:object_r:serial_device:s0
 
@@ -77,6 +79,8 @@
 /vendor/bin/hw/android\.hardware\.neuralnetworks-service-sample-.*   u:object_r:hal_neuralnetworks_sample_exec:s0
 /vendor/bin/hw/android\.hardware\.vibrator@1\.x-service\.example u:object_r:hal_vibrator_default_exec:s0
 /vendor/bin/setup_wifi  u:object_r:setup_wifi_exec:s0
+/vendor/bin/bt_vhci_forwarder  u:object_r:bt_vhci_forwarder_exec:s0
+
 /vendor/bin/hw/android\.hardware\.sensors@2\.1-service\.mock  u:object_r:hal_sensors_default_exec:s0
 /vendor/bin/hw/android\.hardware\.input\.classifier@1\.0-service.default  u:object_r:hal_input_classifier_default_exec:s0
 /vendor/bin/hw/android\.hardware\.thermal@2\.0-service\.mock  u:object_r:hal_thermal_default_exec:s0