diff options
-rw-r--r-- | host/commands/assemble_cvd/disk/disk.h | 10 | ||||
-rw-r--r-- | host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp | 157 | ||||
-rw-r--r-- | host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp | 6 | ||||
-rw-r--r-- | host/commands/assemble_cvd/disk_flags.cc | 2 | ||||
-rw-r--r-- | host/libs/audio_connector/buffers.cpp | 24 | ||||
-rw-r--r-- | host/libs/audio_connector/buffers.h | 39 | ||||
-rw-r--r-- | host/libs/audio_connector/server.cpp | 41 | ||||
-rw-r--r-- | host/libs/audio_connector/server.h | 4 | ||||
-rw-r--r-- | shared/bluetooth/device_vendor.mk | 6 | ||||
-rw-r--r-- | shared/device.mk | 2 |
10 files changed, 133 insertions, 158 deletions
diff --git a/host/commands/assemble_cvd/disk/disk.h b/host/commands/assemble_cvd/disk/disk.h index a32ab0377..548ab71b2 100644 --- a/host/commands/assemble_cvd/disk/disk.h +++ b/host/commands/assemble_cvd/disk/disk.h @@ -33,12 +33,8 @@ fruit::Component<fruit::Required<const CuttlefishConfig, KernelRamdiskRepacker> KernelRamdiskRepackerComponent(); -class GeneratePersistentBootconfig : public SetupFeature {}; - -fruit::Component<fruit::Required<const CuttlefishConfig, - const CuttlefishConfig::InstanceSpecific>, - GeneratePersistentBootconfig> -GeneratePersistentBootconfigComponent(); +Result<void> GeneratePersistentBootconfig( + const CuttlefishConfig&, const CuttlefishConfig::InstanceSpecific&); fruit::Component<fruit::Required<const CuttlefishConfig, KernelRamdiskRepacker>> Gem5ImageUnpackerComponent(); @@ -47,7 +43,7 @@ class GeneratePersistentVbmeta : public SetupFeature {}; fruit::Component<fruit::Required<const CuttlefishConfig::InstanceSpecific, AutoSetup<InitBootloaderEnvPartition>::Type, - GeneratePersistentBootconfig>, + AutoSetup<GeneratePersistentBootconfig>::Type>, GeneratePersistentVbmeta> GeneratePersistentVbmetaComponent(); diff --git a/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp b/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp index 568220594..d0a841fec 100644 --- a/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp +++ b/host/commands/assemble_cvd/disk/generate_persistent_bootconfig.cpp @@ -37,98 +37,77 @@ namespace cuttlefish { -class GeneratePersistentBootconfigImpl : public GeneratePersistentBootconfig { - public: - INJECT(GeneratePersistentBootconfigImpl( - const CuttlefishConfig& config, - const CuttlefishConfig::InstanceSpecific& instance)) - : config_(config), instance_(instance) {} - - // SetupFeature - std::string Name() const override { return "GeneratePersistentBootconfig"; } - bool Enabled() const override { return (!instance_.protected_vm()); } - - private: - std::unordered_set<SetupFeature*> Dependencies() const override { return {}; } - Result<void> ResultSetup() override { - // Cuttlefish for the time being won't be able to support OTA from a - // non-bootconfig kernel to a bootconfig-kernel (or vice versa) IF the - // device is stopped (via stop_cvd). This is rarely an issue since OTA - // testing run on cuttlefish is done within one launch cycle of the device. - // If this ever becomes an issue, this code will have to be rewritten. - if (!instance_.bootconfig_supported()) { - return {}; - } - const auto bootconfig_path = instance_.persistent_bootconfig_path(); - if (!FileExists(bootconfig_path)) { - CF_EXPECT(CreateBlankImage(bootconfig_path, 1 /* mb */, "none"), - "Failed to create image at " << bootconfig_path); - } - - auto bootconfig_fd = SharedFD::Open(bootconfig_path, O_RDWR); - CF_EXPECT(bootconfig_fd->IsOpen(), - "Unable to open bootconfig file: " << bootconfig_fd->StrError()); - - const auto bootconfig_args = - CF_EXPECT(BootconfigArgsFromConfig(config_, instance_)); - const auto bootconfig = - CF_EXPECT(BootconfigArgsString(bootconfig_args, "\n")) + "\n"; - - LOG(DEBUG) << "bootconfig size is " << bootconfig.size(); - ssize_t bytesWritten = WriteAll(bootconfig_fd, bootconfig); - CF_EXPECT(WriteAll(bootconfig_fd, bootconfig) == bootconfig.size(), - "Failed to write bootconfig to \"" << bootconfig_path << "\""); - LOG(DEBUG) << "Bootconfig parameters from vendor boot image and config are " - << ReadFile(bootconfig_path); - - CF_EXPECT(bootconfig_fd->Truncate(bootconfig.size()) == 0, - "`truncate --size=" << bootconfig.size() << " bytes " - << bootconfig_path - << "` failed:" << bootconfig_fd->StrError()); - - if (config_.vm_manager() == vm_manager::Gem5Manager::name()) { - const off_t bootconfig_size_bytes_gem5 = - AlignToPowerOf2(bytesWritten, PARTITION_SIZE_SHIFT); - CF_EXPECT(bootconfig_fd->Truncate(bootconfig_size_bytes_gem5) == 0); - bootconfig_fd->Close(); - } else { - bootconfig_fd->Close(); - const off_t bootconfig_size_bytes = AlignToPowerOf2( - MAX_AVB_METADATA_SIZE + bootconfig.size(), PARTITION_SIZE_SHIFT); - - auto avbtool_path = HostBinaryPath("avbtool"); - Command bootconfig_hash_footer_cmd(avbtool_path); - bootconfig_hash_footer_cmd.AddParameter("add_hash_footer"); - bootconfig_hash_footer_cmd.AddParameter("--image"); - bootconfig_hash_footer_cmd.AddParameter(bootconfig_path); - bootconfig_hash_footer_cmd.AddParameter("--partition_size"); - bootconfig_hash_footer_cmd.AddParameter(bootconfig_size_bytes); - bootconfig_hash_footer_cmd.AddParameter("--partition_name"); - bootconfig_hash_footer_cmd.AddParameter("bootconfig"); - bootconfig_hash_footer_cmd.AddParameter("--key"); - bootconfig_hash_footer_cmd.AddParameter( - DefaultHostArtifactsPath("etc/cvd_avb_testkey.pem")); - bootconfig_hash_footer_cmd.AddParameter("--algorithm"); - bootconfig_hash_footer_cmd.AddParameter("SHA256_RSA4096"); - int success = bootconfig_hash_footer_cmd.Start().Wait(); - CF_EXPECT( - success == 0, - "Unable to run append hash footer. Exited with status " << success); - } +Result<void> GeneratePersistentBootconfig( + const CuttlefishConfig& config, + const CuttlefishConfig::InstanceSpecific& instance) { + if (instance.protected_vm()) { return {}; } + // Cuttlefish for the time being won't be able to support OTA from a + // non-bootconfig kernel to a bootconfig-kernel (or vice versa) IF the + // device is stopped (via stop_cvd). This is rarely an issue since OTA + // testing run on cuttlefish is done within one launch cycle of the device. + // If this ever becomes an issue, this code will have to be rewritten. + if (!instance.bootconfig_supported()) { + return {}; + } + const auto bootconfig_path = instance.persistent_bootconfig_path(); + if (!FileExists(bootconfig_path)) { + CF_EXPECT(CreateBlankImage(bootconfig_path, 1 /* mb */, "none"), + "Failed to create image at " << bootconfig_path); + } - const CuttlefishConfig& config_; - const CuttlefishConfig::InstanceSpecific& instance_; -}; - -fruit::Component<fruit::Required<const CuttlefishConfig, - const CuttlefishConfig::InstanceSpecific>, - GeneratePersistentBootconfig> -GeneratePersistentBootconfigComponent() { - return fruit::createComponent() - .addMultibinding<SetupFeature, GeneratePersistentBootconfigImpl>() - .bind<GeneratePersistentBootconfig, GeneratePersistentBootconfigImpl>(); + auto bootconfig_fd = SharedFD::Open(bootconfig_path, O_RDWR); + CF_EXPECT(bootconfig_fd->IsOpen(), + "Unable to open bootconfig file: " << bootconfig_fd->StrError()); + + const auto bootconfig_args = + CF_EXPECT(BootconfigArgsFromConfig(config, instance)); + const auto bootconfig = + CF_EXPECT(BootconfigArgsString(bootconfig_args, "\n")) + "\n"; + + LOG(DEBUG) << "bootconfig size is " << bootconfig.size(); + ssize_t bytesWritten = WriteAll(bootconfig_fd, bootconfig); + CF_EXPECT(WriteAll(bootconfig_fd, bootconfig) == bootconfig.size(), + "Failed to write bootconfig to \"" << bootconfig_path << "\""); + LOG(DEBUG) << "Bootconfig parameters from vendor boot image and config are " + << ReadFile(bootconfig_path); + + CF_EXPECT(bootconfig_fd->Truncate(bootconfig.size()) == 0, + "`truncate --size=" << bootconfig.size() << " bytes " + << bootconfig_path + << "` failed:" << bootconfig_fd->StrError()); + + if (config.vm_manager() == vm_manager::Gem5Manager::name()) { + const off_t bootconfig_size_bytes_gem5 = + AlignToPowerOf2(bytesWritten, PARTITION_SIZE_SHIFT); + CF_EXPECT(bootconfig_fd->Truncate(bootconfig_size_bytes_gem5) == 0); + bootconfig_fd->Close(); + } else { + bootconfig_fd->Close(); + const off_t bootconfig_size_bytes = AlignToPowerOf2( + MAX_AVB_METADATA_SIZE + bootconfig.size(), PARTITION_SIZE_SHIFT); + + auto avbtool_path = HostBinaryPath("avbtool"); + Command bootconfig_hash_footer_cmd(avbtool_path); + bootconfig_hash_footer_cmd.AddParameter("add_hash_footer"); + bootconfig_hash_footer_cmd.AddParameter("--image"); + bootconfig_hash_footer_cmd.AddParameter(bootconfig_path); + bootconfig_hash_footer_cmd.AddParameter("--partition_size"); + bootconfig_hash_footer_cmd.AddParameter(bootconfig_size_bytes); + bootconfig_hash_footer_cmd.AddParameter("--partition_name"); + bootconfig_hash_footer_cmd.AddParameter("bootconfig"); + bootconfig_hash_footer_cmd.AddParameter("--key"); + bootconfig_hash_footer_cmd.AddParameter( + DefaultHostArtifactsPath("etc/cvd_avb_testkey.pem")); + bootconfig_hash_footer_cmd.AddParameter("--algorithm"); + bootconfig_hash_footer_cmd.AddParameter("SHA256_RSA4096"); + int success = bootconfig_hash_footer_cmd.Start().Wait(); + CF_EXPECT( + success == 0, + "Unable to run append hash footer. Exited with status " << success); + } + return {}; } } // namespace cuttlefish diff --git a/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp b/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp index a1c4cf2b3..6c3560c00 100644 --- a/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp +++ b/host/commands/assemble_cvd/disk/generate_persistent_vbmeta.cpp @@ -35,7 +35,7 @@ class GeneratePersistentVbmetaImpl : public GeneratePersistentVbmeta { INJECT(GeneratePersistentVbmetaImpl( const CuttlefishConfig::InstanceSpecific& instance, AutoSetup<InitBootloaderEnvPartition>::Type& bootloader_env, - GeneratePersistentBootconfig& bootconfig)) + AutoSetup<GeneratePersistentBootconfig>::Type& bootconfig)) : instance_(instance), bootloader_env_(bootloader_env), bootconfig_(bootconfig) {} @@ -112,12 +112,12 @@ class GeneratePersistentVbmetaImpl : public GeneratePersistentVbmeta { const CuttlefishConfig::InstanceSpecific& instance_; AutoSetup<InitBootloaderEnvPartition>::Type& bootloader_env_; - GeneratePersistentBootconfig& bootconfig_; + AutoSetup<GeneratePersistentBootconfig>::Type& bootconfig_; }; fruit::Component<fruit::Required<const CuttlefishConfig::InstanceSpecific, AutoSetup<InitBootloaderEnvPartition>::Type, - GeneratePersistentBootconfig>, + AutoSetup<GeneratePersistentBootconfig>::Type>, GeneratePersistentVbmeta> GeneratePersistentVbmetaComponent() { return fruit::createComponent() diff --git a/host/commands/assemble_cvd/disk_flags.cc b/host/commands/assemble_cvd/disk_flags.cc index 57bfa555d..07b17be2e 100644 --- a/host/commands/assemble_cvd/disk_flags.cc +++ b/host/commands/assemble_cvd/disk_flags.cc @@ -689,7 +689,7 @@ static fruit::Component<> DiskChangesPerInstanceComponent( .install(AutoSetup<InitializeHwcomposerPmemImage>::Component) .install(AutoSetup<InitializePstore>::Component) .install(AutoSetup<InitializeSdCard>::Component) - .install(GeneratePersistentBootconfigComponent) + .install(AutoSetup<GeneratePersistentBootconfig>::Component) .install(GeneratePersistentVbmetaComponent) .install(AutoSetup<InitializeInstanceCompositeDisk>::Component) .install(InitializeDataImageComponent); diff --git a/host/libs/audio_connector/buffers.cpp b/host/libs/audio_connector/buffers.cpp index 29804cadf..100599acd 100644 --- a/host/libs/audio_connector/buffers.cpp +++ b/host/libs/audio_connector/buffers.cpp @@ -19,11 +19,23 @@ namespace cuttlefish { +ShmBuffer::ShmBuffer(const virtio_snd_pcm_xfer& header, + volatile uint8_t* buffer, uint32_t len, + OnConsumedCb on_consumed) + : header_(header), + len_(len), + on_consumed_(on_consumed), + // Cast away the volatile qualifier: No one else will touch this buffer + // until SendStatus is called, at which point a memory fence will be used + // to ensure reads and writes are completed before the status is sent. + buffer_(const_cast<uint8_t*>(buffer)) {} + ShmBuffer::ShmBuffer(ShmBuffer&& other) : header_(std::move(other.header_)), len_(std::move(other.len_)), on_consumed_(std::move(other.on_consumed_)), - status_sent_(other.status_sent_) { + status_sent_(other.status_sent_.load()), + buffer_(other.buffer_) { // It's now this buffer's responsibility to send the status. other.status_sent_ = true; } @@ -32,12 +44,16 @@ ShmBuffer::~ShmBuffer() { CHECK(status_sent_) << "Disposing of ShmBuffer before setting status"; } -uint32_t ShmBuffer::stream_id() const { return header_.stream_id.as_uint32_t(); } +uint32_t ShmBuffer::stream_id() const { + return header_.stream_id.as_uint32_t(); +} void ShmBuffer::SendStatus(AudioStatus status, uint32_t latency_bytes, - uint32_t consumed_len) { + uint32_t consumed_len) { + // Memory order is seq_cst to provide memory fence. It ensures all accesses + // are completed before the status is sent and the buffer is released. + CHECK(!status_sent_.exchange(true)) << "Status should only be sent once"; on_consumed_(status, latency_bytes, consumed_len); - status_sent_ = true; } } // namespace cuttlefish diff --git a/host/libs/audio_connector/buffers.h b/host/libs/audio_connector/buffers.h index a92fd83f9..5dd589e2c 100644 --- a/host/libs/audio_connector/buffers.h +++ b/host/libs/audio_connector/buffers.h @@ -14,6 +14,7 @@ // limitations under the License. #pragma once +#include <atomic> #include <cinttypes> #include <functional> @@ -35,11 +36,11 @@ using OnConsumedCb = std::function<void(AudioStatus, uint32_t /*latency*/, // Objects of this class can only be moved, not copied. Destroying a buffer // without sending the status to the client is a bug so the program aborts in // those cases. +// This class is NOT thread safe despite its use of atomic variables. class ShmBuffer { public: - ShmBuffer(const virtio_snd_pcm_xfer& header, uint32_t len, - OnConsumedCb on_consumed) - : header_(header), len_(len), on_consumed_(on_consumed) {} + ShmBuffer(const virtio_snd_pcm_xfer& header, volatile uint8_t* buffer, + uint32_t len, OnConsumedCb on_consumed); ShmBuffer(const ShmBuffer& other) = delete; ShmBuffer(ShmBuffer&& other); ShmBuffer& operator=(const ShmBuffer& other) = delete; @@ -52,41 +53,27 @@ class ShmBuffer { void SendStatus(AudioStatus status, uint32_t latency_bytes, uint32_t consumed_len); + const uint8_t* get() const { return buffer_; } + private: const virtio_snd_pcm_xfer header_; const uint32_t len_; OnConsumedCb on_consumed_; - bool status_sent_ = false; -}; - -class TxBuffer : public ShmBuffer { - public: - TxBuffer(const virtio_snd_pcm_xfer& header, const volatile uint8_t* buffer, - uint32_t len, OnConsumedCb on_consumed) - : ShmBuffer(header, len, on_consumed), buffer_(buffer) {} - TxBuffer(const TxBuffer& other) = delete; - TxBuffer(TxBuffer&& other) = default; - TxBuffer& operator=(const TxBuffer& other) = delete; + std::atomic<bool> status_sent_ = false; - const volatile uint8_t* get() const { return buffer_; } - - private: - const volatile uint8_t* const buffer_; + protected: + uint8_t* buffer_; }; +using TxBuffer = ShmBuffer; +// Only RxBuffer can be written to class RxBuffer : public ShmBuffer { public: RxBuffer(const virtio_snd_pcm_xfer& header, volatile uint8_t* buffer, uint32_t len, OnConsumedCb on_consumed) - : ShmBuffer(header, len, on_consumed), buffer_(buffer) {} - RxBuffer(const RxBuffer& other) = delete; - RxBuffer(RxBuffer&& other) = default; - RxBuffer& operator=(const RxBuffer& other) = delete; + : ShmBuffer(header, buffer, len, on_consumed) {} - volatile uint8_t* get() const { return buffer_; } - - private: - volatile uint8_t* const buffer_; + uint8_t* get() { return buffer_; } }; } // namespace cuttlefish diff --git a/host/libs/audio_connector/server.cpp b/host/libs/audio_connector/server.cpp index ab74daa02..f98621c3b 100644 --- a/host/libs/audio_connector/server.cpp +++ b/host/libs/audio_connector/server.cpp @@ -55,6 +55,13 @@ ScopedMMap AllocateShm(size_t size, const std::string& name, SharedFD* shm_fd) { return mmap_res; } +volatile uint8_t* BufferAt(ScopedMMap& shm, size_t offset, size_t len) { + CHECK(shm.WithinBounds(offset, len)) + << "Tx buffer bounds outside the buffer area: " << offset << " " << len; + void* ptr = shm.get(); + return &reinterpret_cast<volatile uint8_t*>(ptr)[offset]; +} + bool CreateSocketPair(SharedFD* local, SharedFD* remote) { auto ret = SharedFD::SocketPair(AF_UNIX, SOCK_SEQPACKET, 0, local, remote); if (!ret) { @@ -301,10 +308,11 @@ bool AudioClientConnection::ReceivePlayback(AudioServerExecutor& executor) { LOG(ERROR) << "Received PCM_XFER message is too small: " << recv_size; return false; } - TxBuffer buffer(msg_hdr->io_xfer, - TxBufferAt(msg_hdr->buffer_offset, msg_hdr->buffer_len), - msg_hdr->buffer_len, - SendStatusCallback(msg_hdr->buffer_offset, tx_socket_)); + TxBuffer buffer( + msg_hdr->io_xfer, + BufferAt(tx_shm_, msg_hdr->buffer_offset, msg_hdr->buffer_len), + msg_hdr->buffer_len, + SendStatusCallback(msg_hdr->buffer_offset, tx_socket_)); executor.OnPlaybackBuffer(std::move(buffer)); return true; } @@ -320,10 +328,11 @@ bool AudioClientConnection::ReceiveCapture(AudioServerExecutor& executor) { LOG(ERROR) << "Received PCM_XFER message is too small: " << recv_size; return false; } - RxBuffer buffer(msg_hdr->io_xfer, - RxBufferAt(msg_hdr->buffer_offset, msg_hdr->buffer_len), - msg_hdr->buffer_len, - SendStatusCallback(msg_hdr->buffer_offset, rx_socket_)); + RxBuffer buffer( + msg_hdr->io_xfer, + BufferAt(rx_shm_, msg_hdr->buffer_offset, msg_hdr->buffer_len), + msg_hdr->buffer_len, + SendStatusCallback(msg_hdr->buffer_offset, rx_socket_)); executor.OnCaptureBuffer(std::move(buffer)); return true; } @@ -347,22 +356,6 @@ bool AudioClientConnection::CmdReply(AudioStatus status, const void* data, return true; } -const volatile uint8_t* AudioClientConnection::TxBufferAt(size_t offset, - size_t len) const { - CHECK(tx_shm_.WithinBounds(offset, len)) - << "Tx buffer bounds outside the buffer area: " << offset << " " << len; - const void* ptr = tx_shm_.get(); - return &reinterpret_cast<const volatile uint8_t*>(ptr)[offset]; -} - -volatile uint8_t* AudioClientConnection::RxBufferAt(size_t offset, - size_t len) { - CHECK(rx_shm_.WithinBounds(offset, len)) - << "Rx buffer bounds outside the buffer area: " << offset << " " << len; - void* ptr = rx_shm_.get(); - return &reinterpret_cast<volatile uint8_t*>(ptr)[offset]; -} - bool AudioClientConnection::SendEvent(/*TODO*/) { return false; } ssize_t AudioClientConnection::ReceiveMsg(SharedFD socket, void* buffer, diff --git a/host/libs/audio_connector/server.h b/host/libs/audio_connector/server.h index 6fa14d936..fec36dcb2 100644 --- a/host/libs/audio_connector/server.h +++ b/host/libs/audio_connector/server.h @@ -87,10 +87,8 @@ class AudioClientConnection { AudioServerExecutor& executor); ssize_t ReceiveMsg(SharedFD socket, void* buffer, size_t size); - const volatile uint8_t* TxBufferAt(size_t offset, size_t len) const; - volatile uint8_t* RxBufferAt(size_t offset, size_t len); - const ScopedMMap tx_shm_; + ScopedMMap tx_shm_; ScopedMMap rx_shm_; SharedFD control_socket_; SharedFD event_socket_; diff --git a/shared/bluetooth/device_vendor.mk b/shared/bluetooth/device_vendor.mk index 60c090adb..451f30063 100644 --- a/shared/bluetooth/device_vendor.mk +++ b/shared/bluetooth/device_vendor.mk @@ -32,6 +32,12 @@ PRODUCT_COPY_FILES += \ PRODUCT_PACKAGES += com.google.cf.bt +# +# Bluetooth Audio AIDL HAL +# +PRODUCT_PACKAGES += \ + android.hardware.bluetooth.audio-impl \ + else # BOARD_HAVE_BLUETOOTH == true PRODUCT_COPY_FILES += \ diff --git a/shared/device.mk b/shared/device.mk index 4dd1de652..4e9ea97ac 100644 --- a/shared/device.mk +++ b/shared/device.mk @@ -55,7 +55,7 @@ TARGET_USERDATAIMAGE_PARTITION_SIZE ?= 8589934592 TARGET_VULKAN_SUPPORT ?= true # Enable Virtual A/B -$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/android_t_baseline.mk) +$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/vabc_features.mk) PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD := lz4 PRODUCT_VIRTUAL_AB_COW_VERSION := 3 |