Allow RAMDISK_KERNEL_MODULES to be overriden. am: 823e746b0a
Original change: https://googleplex-android-review.googlesource.com/c/device/google/cuttlefish/+/26566541
Change-Id: I426000b75114683471876e9f01fc0cfba8ad66b9
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/TEST_MAPPING b/TEST_MAPPING
index f711b63..fadf79d 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -28,6 +28,15 @@
},
{
"name": "CtsScopedStorageDeviceOnlyTest"
+ },
+ {
+ "name": "CtsScopedStorageBypassDatabaseOperationsTest"
+ },
+ {
+ "name": "CtsScopedStorageGeneralTest"
+ },
+ {
+ "name": "CtsScopedStorageRedactUriTest"
}
],
"auto-presubmit": [
diff --git a/guest/commands/bt_vhci_forwarder/Android.bp b/guest/commands/bt_vhci_forwarder/Android.bp
index 03b7a05..45308ba 100644
--- a/guest/commands/bt_vhci_forwarder/Android.bp
+++ b/guest/commands/bt_vhci_forwarder/Android.bp
@@ -20,6 +20,8 @@
cc_binary {
name: "bt_vhci_forwarder",
srcs: [
+ "hci/h4_packetizer.cc",
+ "hci/h4_parser.cc",
"main.cpp",
],
shared_libs: [
@@ -28,7 +30,6 @@
"liblog",
],
static_libs: [
- "h4_packetizer_lib",
"libgflags",
],
defaults: ["cuttlefish_guest_only"]
diff --git a/guest/commands/bt_vhci_forwarder/hci/h4.h b/guest/commands/bt_vhci_forwarder/hci/h4.h
new file mode 100644
index 0000000..e05a129
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/hci/h4.h
@@ -0,0 +1,32 @@
+//
+// Copyright 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.
+//
+
+#pragma once
+
+#include <cstdint> // for uint8_t
+
+namespace rootcanal {
+
+enum class PacketType : uint8_t {
+ UNKNOWN = 0,
+ COMMAND = 1,
+ ACL = 2,
+ SCO = 3,
+ EVENT = 4,
+ ISO = 5,
+};
+
+} // namespace rootcanal
diff --git a/guest/commands/bt_vhci_forwarder/hci/h4_packetizer.cc b/guest/commands/bt_vhci_forwarder/hci/h4_packetizer.cc
new file mode 100644
index 0000000..9564669
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/hci/h4_packetizer.cc
@@ -0,0 +1,92 @@
+//
+// Copyright 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 "h4_packetizer.h"
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <cerrno>
+
+#include "log.h"
+
+namespace rootcanal {
+
+H4Packetizer::H4Packetizer(int fd, PacketReadCallback command_cb,
+ PacketReadCallback event_cb,
+ PacketReadCallback acl_cb, PacketReadCallback sco_cb,
+ PacketReadCallback iso_cb,
+ ClientDisconnectCallback disconnect_cb)
+ : uart_fd_(fd),
+ h4_parser_(command_cb, event_cb, acl_cb, sco_cb, iso_cb),
+ disconnect_cb_(std::move(disconnect_cb)) {}
+
+size_t H4Packetizer::Send(uint8_t type, const uint8_t* data, size_t length) {
+ struct iovec iov[] = {{&type, sizeof(type)},
+ {const_cast<uint8_t*>(data), length}};
+ ssize_t ret = 0;
+ do {
+ ret = writev(uart_fd_, iov, sizeof(iov) / sizeof(iov[0]));
+ } while (-1 == ret && (EINTR == errno || EAGAIN == errno));
+
+ if (ret == -1) {
+ LOG_ERROR("Error writing to UART (%s)", strerror(errno));
+ } else if (ret < static_cast<ssize_t>(length + 1)) {
+ LOG_ERROR("%d / %d bytes written - something went wrong...",
+ static_cast<int>(ret), static_cast<int>(length + 1));
+ }
+ return ret;
+}
+
+void H4Packetizer::OnDataReady(int fd) {
+ if (disconnected_) {
+ return;
+ }
+ ssize_t bytes_to_read = h4_parser_.BytesRequested();
+ std::vector<uint8_t> buffer(bytes_to_read);
+
+ ssize_t bytes_read;
+ do {
+ bytes_read = read(fd, buffer.data(), bytes_to_read);
+ } while (bytes_read == -1 && errno == EINTR);
+
+ if (bytes_read == 0) {
+ LOG_INFO("remote disconnected!");
+ disconnected_ = true;
+ disconnect_cb_();
+ return;
+ }
+ if (bytes_read < 0) {
+ if (errno == EAGAIN) {
+ // No data, try again later.
+ return;
+ }
+ if (errno == ECONNRESET) {
+ // They probably rejected our packet
+ disconnected_ = true;
+ disconnect_cb_();
+ return;
+ }
+
+ LOG_ALWAYS_FATAL("Read error in %d: %s", h4_parser_.CurrentState(),
+ strerror(errno));
+ }
+ h4_parser_.Consume(buffer.data(), bytes_read);
+}
+
+} // namespace rootcanal
diff --git a/guest/commands/bt_vhci_forwarder/hci/h4_packetizer.h b/guest/commands/bt_vhci_forwarder/hci/h4_packetizer.h
new file mode 100644
index 0000000..4feed95
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/hci/h4_packetizer.h
@@ -0,0 +1,49 @@
+//
+// Copyright 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 <vector>
+
+#include "h4_parser.h"
+
+namespace rootcanal {
+
+// A socket based H4Packetizer. Call OnDataReady whenever
+// data can be read from file descriptor fd.
+//
+// This is only supported on unix.
+class H4Packetizer {
+ public:
+ H4Packetizer(int fd, PacketReadCallback command_cb,
+ PacketReadCallback event_cb, PacketReadCallback acl_cb,
+ PacketReadCallback sco_cb, PacketReadCallback iso_cb,
+ ClientDisconnectCallback disconnect_cb);
+
+ size_t Send(uint8_t type, const uint8_t* data, size_t length);
+
+ void OnDataReady(int fd);
+
+ private:
+ int uart_fd_;
+ H4Parser h4_parser_;
+
+ ClientDisconnectCallback disconnect_cb_;
+ bool disconnected_{false};
+};
+
+} // namespace rootcanal
diff --git a/guest/commands/bt_vhci_forwarder/hci/h4_parser.cc b/guest/commands/bt_vhci_forwarder/hci/h4_parser.cc
new file mode 100644
index 0000000..f616340
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/hci/h4_parser.cc
@@ -0,0 +1,215 @@
+//
+// Copyright 20 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 "hci/h4_parser.h" // for H4Parser, PacketType, H4Pars...
+
+#include <array>
+#include <cstddef> // for size_t
+#include <cstdint> // for uint8_t, int32_t
+#include <functional> // for function
+#include <utility> // for move
+#include <vector> // for vector
+
+#include "log.h" // for LOG_ALWAYS_FATAL, LOG_INFO
+
+namespace rootcanal {
+
+void H4Parser::Reset() {
+ state_ = HCI_TYPE;
+ packet_.clear();
+ bytes_wanted_ = 0;
+ packet_type_ = 0;
+}
+
+size_t H4Parser::HciGetPacketLengthForType(PacketType type,
+ const uint8_t* preamble) {
+ static const size_t
+ packet_length_offset[static_cast<size_t>(PacketType::ISO) + 1] = {
+ 0,
+ H4Parser::COMMAND_LENGTH_OFFSET,
+ H4Parser::ACL_LENGTH_OFFSET,
+ H4Parser::SCO_LENGTH_OFFSET,
+ H4Parser::EVENT_LENGTH_OFFSET,
+ H4Parser::ISO_LENGTH_OFFSET,
+ };
+
+ size_t offset = packet_length_offset[static_cast<size_t>(type)];
+ size_t size = preamble[offset];
+ if (type == PacketType::ACL) {
+ size |= ((size_t)preamble[offset + 1]) << 8;
+ }
+ if (type == PacketType::ISO) {
+ size |= ((size_t)preamble[offset + 1] & 0x0fU) << 8;
+ }
+ return size;
+}
+
+H4Parser::H4Parser(PacketReadCallback command_cb, PacketReadCallback event_cb,
+ PacketReadCallback acl_cb, PacketReadCallback sco_cb,
+ PacketReadCallback iso_cb, bool enable_recovery_state)
+ : command_cb_(std::move(command_cb)),
+ event_cb_(std::move(event_cb)),
+ acl_cb_(std::move(acl_cb)),
+ sco_cb_(std::move(sco_cb)),
+ iso_cb_(std::move(iso_cb)),
+ enable_recovery_state_(enable_recovery_state) {}
+
+void H4Parser::OnPacketReady() {
+ switch (hci_packet_type_) {
+ case PacketType::COMMAND:
+ command_cb_(packet_);
+ break;
+ case PacketType::ACL:
+ acl_cb_(packet_);
+ break;
+ case PacketType::SCO:
+ sco_cb_(packet_);
+ break;
+ case PacketType::EVENT:
+ event_cb_(packet_);
+ break;
+ case PacketType::ISO:
+ iso_cb_(packet_);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unimplemented packet type %d",
+ static_cast<int>(hci_packet_type_));
+ }
+ // Get ready for the next type byte.
+ hci_packet_type_ = PacketType::UNKNOWN;
+}
+
+size_t H4Parser::BytesRequested() {
+ switch (state_) {
+ case HCI_TYPE:
+ case HCI_RECOVERY:
+ return 1;
+ case HCI_PREAMBLE:
+ case HCI_PAYLOAD:
+ return bytes_wanted_;
+ }
+}
+
+bool H4Parser::Consume(const uint8_t* buffer, int32_t bytes_read) {
+ size_t bytes_to_read = BytesRequested();
+ if (bytes_read <= 0) {
+ LOG_INFO("remote disconnected, or unhandled error?");
+ return false;
+ }
+ if ((uint32_t)bytes_read > BytesRequested()) {
+ LOG_ALWAYS_FATAL("More bytes read (%u) than expected (%u)!",
+ static_cast<int>(bytes_read),
+ static_cast<int>(bytes_to_read));
+ }
+
+ static const size_t preamble_size[static_cast<size_t>(PacketType::ISO) + 1] =
+ {
+ 0,
+ H4Parser::COMMAND_PREAMBLE_SIZE,
+ H4Parser::ACL_PREAMBLE_SIZE,
+ H4Parser::SCO_PREAMBLE_SIZE,
+ H4Parser::EVENT_PREAMBLE_SIZE,
+ H4Parser::ISO_PREAMBLE_SIZE,
+ };
+ switch (state_) {
+ case HCI_TYPE:
+ // bytes_read >= 1
+ packet_type_ = *buffer;
+ packet_.clear();
+ break;
+
+ case HCI_RECOVERY: {
+ // Skip all received bytes until the HCI Reset command is received.
+ // The parser can end up in a bad state when the host is restarted.
+ const std::array<uint8_t, 4> reset_command{0x01, 0x03, 0x0c, 0x00};
+ size_t offset = packet_.size();
+ LOG_WARN("Received byte in recovery state : 0x%x",
+ static_cast<unsigned>(*buffer));
+ packet_.push_back(*buffer);
+
+ // Last byte does not match expected byte in the sequence.
+ // Drop all the bytes and start over.
+ if (packet_[offset] != reset_command[offset]) {
+ packet_.clear();
+ // The mismatched byte can also be the first of the correct sequence.
+ if (*buffer == reset_command[0]) {
+ packet_.push_back(*buffer);
+ }
+ }
+
+ // Received full reset command.
+ if (packet_.size() == reset_command.size()) {
+ LOG_INFO("Received HCI Reset command, exiting recovery state");
+ // Pop the Idc from the received packet.
+ packet_.erase(packet_.begin());
+ bytes_wanted_ = 0;
+ }
+ break;
+ }
+
+ case HCI_PREAMBLE:
+ case HCI_PAYLOAD:
+ packet_.insert(packet_.end(), buffer, buffer + bytes_read);
+ bytes_wanted_ -= bytes_read;
+ break;
+ }
+
+ switch (state_) {
+ case HCI_TYPE:
+ hci_packet_type_ = static_cast<PacketType>(packet_type_);
+ if (hci_packet_type_ != PacketType::ACL &&
+ hci_packet_type_ != PacketType::SCO &&
+ hci_packet_type_ != PacketType::COMMAND &&
+ hci_packet_type_ != PacketType::EVENT &&
+ hci_packet_type_ != PacketType::ISO) {
+ if (!enable_recovery_state_) {
+ LOG_ALWAYS_FATAL("Received invalid packet type 0x%x",
+ static_cast<unsigned>(packet_type_));
+ }
+ LOG_ERROR("Received invalid packet type 0x%x, entering recovery state",
+ static_cast<unsigned>(packet_type_));
+ state_ = HCI_RECOVERY;
+ hci_packet_type_ = PacketType::COMMAND;
+ bytes_wanted_ = 1;
+ } else {
+ state_ = HCI_PREAMBLE;
+ bytes_wanted_ = preamble_size[static_cast<size_t>(hci_packet_type_)];
+ }
+ break;
+ case HCI_PREAMBLE:
+ if (bytes_wanted_ == 0) {
+ size_t payload_size =
+ HciGetPacketLengthForType(hci_packet_type_, packet_.data());
+ if (payload_size == 0) {
+ OnPacketReady();
+ state_ = HCI_TYPE;
+ } else {
+ bytes_wanted_ = payload_size;
+ state_ = HCI_PAYLOAD;
+ }
+ }
+ break;
+ case HCI_RECOVERY:
+ case HCI_PAYLOAD:
+ if (bytes_wanted_ == 0) {
+ OnPacketReady();
+ state_ = HCI_TYPE;
+ }
+ break;
+ }
+ return true;
+}
+} // namespace rootcanal
diff --git a/guest/commands/bt_vhci_forwarder/hci/h4_parser.h b/guest/commands/bt_vhci_forwarder/hci/h4_parser.h
new file mode 100644
index 0000000..825c41a
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/hci/h4_parser.h
@@ -0,0 +1,131 @@
+//
+// Copyright 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.
+//
+
+#pragma once
+
+#include <stddef.h> // for size_t
+
+#include <cstdint> // for uint8_t, int32_t
+#include <functional> // for function
+#include <ostream> // for operator<<, ostream
+#include <vector> // for vector
+
+#include "hci/h4.h" // for PacketType
+
+namespace rootcanal {
+
+using PacketReadCallback = std::function<void(const std::vector<uint8_t>&)>;
+using HciPacketReadyCallback = std::function<void(void)>;
+using ClientDisconnectCallback = std::function<void()>;
+
+// An H4 Parser can parse H4 Packets and will invoke the proper callback
+// once a packet has been parsed.
+//
+// You use it as follows:
+//
+// H4Parser h4(....);
+// size_t nr_bytes = h4.BytesRequested();
+// std::vector fill_this_vector_with_at_most_nr_bytes(nr_bytes);
+// h4.Consume(fill_this_vector_with_at_most_nr_bytes.data(), nr_bytes.size());
+//
+// The parser will invoke the proper callbacks once a packet has been parsed.
+// The parser keeps internal state and is not thread safe.
+class H4Parser {
+ public:
+ enum State { HCI_TYPE, HCI_PREAMBLE, HCI_PAYLOAD, HCI_RECOVERY };
+
+ H4Parser(PacketReadCallback command_cb, PacketReadCallback event_cb,
+ PacketReadCallback acl_cb, PacketReadCallback sco_cb,
+ PacketReadCallback iso_cb, bool enable_recovery_state = false);
+
+ // Consumes the given number of bytes, returns true on success.
+ bool Consume(const uint8_t* buffer, int32_t bytes);
+
+ // The maximum number of bytes the parser can consume in the current state.
+ size_t BytesRequested();
+
+ // Resets the parser to the empty, initial state.
+ void Reset();
+
+ State CurrentState() { return state_; };
+
+ void EnableRecovery() { enable_recovery_state_ = true; }
+ void DisableRecovery() { enable_recovery_state_ = false; }
+
+ private:
+ void OnPacketReady();
+
+ // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
+ static constexpr size_t COMMAND_PREAMBLE_SIZE = 3;
+ static constexpr size_t COMMAND_LENGTH_OFFSET = 2;
+ // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
+ static constexpr size_t ACL_PREAMBLE_SIZE = 4;
+ static constexpr size_t ACL_LENGTH_OFFSET = 2;
+
+ // 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
+ static constexpr size_t SCO_PREAMBLE_SIZE = 3;
+ static constexpr size_t SCO_LENGTH_OFFSET = 2;
+
+ // 1 byte for event code, 1 byte for parameter length (Volume 2, Part
+ // E, 5.4.4)
+ static constexpr size_t EVENT_PREAMBLE_SIZE = 2;
+ static constexpr size_t EVENT_LENGTH_OFFSET = 1;
+
+ // 2 bytes for handle and flags, 12 bits for length (Volume 2, Part E, 5.4.5)
+ static constexpr size_t ISO_PREAMBLE_SIZE = 4;
+ static constexpr size_t ISO_LENGTH_OFFSET = 2;
+
+ PacketReadCallback command_cb_;
+ PacketReadCallback event_cb_;
+ PacketReadCallback acl_cb_;
+ PacketReadCallback sco_cb_;
+ PacketReadCallback iso_cb_;
+
+ static size_t HciGetPacketLengthForType(PacketType type,
+ const uint8_t* preamble);
+
+ PacketType hci_packet_type_{PacketType::UNKNOWN};
+
+ State state_{HCI_TYPE};
+ uint8_t packet_type_{};
+ std::vector<uint8_t> packet_;
+ size_t bytes_wanted_{0};
+ bool enable_recovery_state_{false};
+};
+
+inline std::ostream& operator<<(std::ostream& os,
+ H4Parser::State const& state_) {
+ switch (state_) {
+ case H4Parser::State::HCI_TYPE:
+ os << "HCI_TYPE";
+ break;
+ case H4Parser::State::HCI_PREAMBLE:
+ os << "HCI_PREAMBLE";
+ break;
+ case H4Parser::State::HCI_PAYLOAD:
+ os << "HCI_PAYLOAD";
+ break;
+ case H4Parser::State::HCI_RECOVERY:
+ os << "HCI_RECOVERY";
+ break;
+ default:
+ os << "unknown state " << static_cast<int>(state_);
+ break;
+ }
+ return os;
+}
+
+} // namespace rootcanal
diff --git a/guest/commands/bt_vhci_forwarder/hci/log.h b/guest/commands/bt_vhci_forwarder/hci/log.h
new file mode 100644
index 0000000..f301a32
--- /dev/null
+++ b/guest/commands/bt_vhci_forwarder/hci/log.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2022 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 <android-base/format.h>
+#include <android-base/logging.h>
+
+// FIXME: remove those shims
+#define LOG_DEBUG(...) LOG(DEBUG) << fmt::sprintf(__VA_ARGS__)
+#define LOG_INFO(...) LOG(INFO) << fmt::sprintf(__VA_ARGS__)
+#define LOG_WARN(...) LOG(WARNING) << fmt::sprintf(__VA_ARGS__)
+#define LOG_ERROR(...) LOG(ERROR) << fmt::sprintf(__VA_ARGS__)
+#define LOG_ALWAYS_FATAL(...) LOG(FATAL) << fmt::sprintf(__VA_ARGS__)
+
+#define ASSERT(cond) CHECK(cond)
+#define ASSERT_LOG(cond, ...) CHECK(cond) << fmt::sprintf(__VA_ARGS__)
diff --git a/guest/commands/bt_vhci_forwarder/main.cpp b/guest/commands/bt_vhci_forwarder/main.cpp
index faf6b55..7c83a5b 100644
--- a/guest/commands/bt_vhci_forwarder/main.cpp
+++ b/guest/commands/bt_vhci_forwarder/main.cpp
@@ -26,7 +26,7 @@
#include "android-base/logging.h"
-#include "model/hci/h4_packetizer.h"
+#include "hci/h4_packetizer.h"
// Copied from net/bluetooth/hci.h
#define HCI_ACLDATA_PKT 0x02