diff --git a/uwb/aidl/default/Android.bp b/uwb/aidl/default/Android.bp index 9621f2cb10..8c2b60e37d 100644 --- a/uwb/aidl/default/Android.bp +++ b/uwb/aidl/default/Android.bp @@ -7,26 +7,29 @@ package { default_applicable_licenses: ["hardware_interfaces_license"], } -rust_binary { +cc_binary { name: "android.hardware.uwb-service", - crate_name: "uwb_default_hal", relative_install_path: "hw", + init_rc: ["uwb-service.rc"], vintf_fragments: ["uwb-service.xml"], vendor: true, - rustlibs: [ - "android.hardware.uwb-V1-rust", - "liblogger", - "liblog_rust", - "libbinder_rs", - "libbinder_tokio_rs", - "libtokio", - "libnix", - "libanyhow", + cflags: [ + "-Wall", + "-Wextra", + "-g", ], - proc_macros: [ - "libasync_trait", + shared_libs: [ + "liblog", + "libbinder_ndk", + ], + static_libs: [ + "libbase", + "libutils", + "android.hardware.uwb-V1-ndk", ], srcs: [ - "src/service.rs", + "service.cpp", + "uwb.cpp", + "uwb_chip.cpp", ], } diff --git a/uwb/aidl/default/service.cpp b/uwb/aidl/default/service.cpp new file mode 100644 index 0000000000..007637f5d1 --- /dev/null +++ b/uwb/aidl/default/service.cpp @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "uwb.h" + +using ::aidl::android::hardware::uwb::IUwb; +using ::android::sp; +using ::android::base::InitLogging; +using ::android::base::StderrLogger; +using ::android::hardware::uwb::impl::Uwb; + +int main(int /*argc*/, char* argv[]) { + InitLogging(argv, StderrLogger); + LOG(INFO) << "UWB HAL starting up"; + + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr uwb = ndk::SharedRefBase::make(); + const std::string instance = std::string() + IUwb::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(uwb->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +} diff --git a/uwb/aidl/default/src/service.rs b/uwb/aidl/default/src/service.rs deleted file mode 100644 index 7d5c07323f..0000000000 --- a/uwb/aidl/default/src/service.rs +++ /dev/null @@ -1,47 +0,0 @@ -use android_hardware_uwb::aidl::android::hardware::uwb::IUwb::{self, IUwb as _}; -use android_hardware_uwb::binder; - -use tokio::runtime::Runtime; - -use std::env; -use std::panic; - -use log::Level; - -mod uwb; -mod uwb_chip; - -fn main() -> anyhow::Result<()> { - logger::init( - logger::Config::default() - .with_min_level(Level::Debug) - .with_tag_on_device("android.hardware.uwb"), - ); - - // Redirect panic messages to logcat. - panic::set_hook(Box::new(|panic_info| { - log::error!("{}", panic_info); - })); - - log::info!("UWB HAL starting up"); - - // Create the tokio runtime - let rt = Runtime::new()?; - - let chips = env::args() - .skip(1) // Skip binary name - .enumerate() - .map(|(i, arg)| uwb_chip::UwbChip::new(i.to_string(), arg)); - - binder::add_service( - &format!("{}/default", IUwb::BpUwb::get_descriptor()), - IUwb::BnUwb::new_binder( - uwb::Uwb::from_chips(chips, rt.handle().clone()), - binder::BinderFeatures::default(), - ) - .as_binder(), - )?; - - binder::ProcessState::join_thread_pool(); - Ok(()) -} diff --git a/uwb/aidl/default/src/uwb.rs b/uwb/aidl/default/src/uwb.rs deleted file mode 100644 index 428f08fec0..0000000000 --- a/uwb/aidl/default/src/uwb.rs +++ /dev/null @@ -1,53 +0,0 @@ -use android_hardware_uwb::aidl::android::hardware::uwb::{IUwb, IUwbChip}; -use android_hardware_uwb::binder; -use binder::{Result, Strong}; -use binder_tokio::TokioRuntime; -use tokio::runtime::Handle as TokioHandle; - -use crate::uwb_chip; - -pub struct Uwb { - chips: Vec>, -} - -impl Uwb { - pub fn from_chips( - chips: impl IntoIterator, - handle: TokioHandle, - ) -> Self { - Self { - chips: chips - .into_iter() - .map(|chip| { - IUwbChip::BnUwbChip::new_async_binder( - chip, - TokioRuntime(handle.clone()), - binder::BinderFeatures::default(), - ) - }) - .collect(), - } - } -} - -impl binder::Interface for Uwb {} - -impl IUwb::IUwb for Uwb { - fn getChips(&self) -> Result> { - log::debug!("getChips"); - self.chips.iter().map(|chip| chip.getName()).collect() - } - - fn getChip(&self, name: &str) -> Result> { - log::debug!("getChip {}", name); - let chip = self - .chips - .iter() - .find(|chip| chip.getName().as_deref() == Ok(name)); - if let Some(chip) = chip { - Ok(chip.clone()) - } else { - Err(binder::ExceptionCode::ILLEGAL_ARGUMENT.into()) - } - } -} diff --git a/uwb/aidl/default/src/uwb_chip.rs b/uwb/aidl/default/src/uwb_chip.rs deleted file mode 100644 index 7c2c30056d..0000000000 --- a/uwb/aidl/default/src/uwb_chip.rs +++ /dev/null @@ -1,168 +0,0 @@ -use android_hardware_uwb::aidl::android::hardware::uwb::{ - IUwbChip::IUwbChipAsyncServer, IUwbClientCallback::IUwbClientCallback, UwbEvent::UwbEvent, - UwbStatus::UwbStatus, -}; -use android_hardware_uwb::binder; -use async_trait::async_trait; -use binder::{Result, Strong}; - -use tokio::fs::File; -use tokio::io::{AsyncReadExt, AsyncWriteExt}; -use tokio::sync::Mutex; - -use std::os::fd::AsRawFd; - -use std::io; - -use nix::sys::termios; - -enum State { - Closed, - Opened { - callbacks: Strong, - #[allow(dead_code)] - tasks: tokio::task::JoinSet<()>, - write: File, - }, -} - -pub struct UwbChip { - name: String, - path: String, - state: Mutex, -} - -impl UwbChip { - pub fn new(name: String, path: String) -> Self { - Self { - name, - path, - state: Mutex::new(State::Closed), - } - } -} - -pub fn makeraw(file: File) -> io::Result { - let fd = file.as_raw_fd(); - - let mut attrs = termios::tcgetattr(fd)?; - - termios::cfmakeraw(&mut attrs); - - termios::tcsetattr(fd, termios::SetArg::TCSANOW, &attrs)?; - - Ok(file) -} - -impl binder::Interface for UwbChip {} - -#[async_trait] -impl IUwbChipAsyncServer for UwbChip { - async fn getName(&self) -> Result { - Ok(self.name.clone()) - } - - async fn open(&self, callbacks: &Strong) -> Result<()> { - log::debug!("open: {:?}", &self.path); - - let serial = File::open(&self.path) - .await - .and_then(makeraw) - .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?; - - let mut read = serial - .try_clone() - .await - .map_err(|_| binder::StatusCode::UNKNOWN_ERROR)?; - let write = serial; - - let mut state = self.state.lock().await; - - if let State::Closed = *state { - let client_callbacks = callbacks.clone(); - - let mut tasks = tokio::task::JoinSet::new(); - - tasks.spawn(async move { - loop { - const UWB_HEADER_SIZE: usize = 4; - - let mut buffer = vec![0; UWB_HEADER_SIZE]; - read.read_exact(&mut buffer[0..UWB_HEADER_SIZE]) - .await - .unwrap(); - - let length = buffer[3] as usize + UWB_HEADER_SIZE; - - buffer.resize(length, 0); - read.read_exact(&mut buffer[UWB_HEADER_SIZE..length]) - .await - .unwrap(); - - client_callbacks.onUciMessage(&buffer[..]).unwrap(); - } - }); - - callbacks.onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK)?; - - *state = State::Opened { - callbacks: callbacks.clone(), - tasks, - write, - }; - - Ok(()) - } else { - Err(binder::ExceptionCode::ILLEGAL_STATE.into()) - } - } - - async fn close(&self) -> Result<()> { - log::debug!("close"); - - let mut state = self.state.lock().await; - - if let State::Opened { ref callbacks, .. } = *state { - callbacks.onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK)?; - *state = State::Closed; - Ok(()) - } else { - Err(binder::ExceptionCode::ILLEGAL_STATE.into()) - } - } - - async fn coreInit(&self) -> Result<()> { - log::debug!("coreInit"); - - if let State::Opened { ref callbacks, .. } = *self.state.lock().await { - callbacks.onHalEvent(UwbEvent::POST_INIT_CPLT, UwbStatus::OK)?; - Ok(()) - } else { - Err(binder::ExceptionCode::ILLEGAL_STATE.into()) - } - } - - async fn sessionInit(&self, _id: i32) -> Result<()> { - log::debug!("sessionInit"); - - Ok(()) - } - - async fn getSupportedAndroidUciVersion(&self) -> Result { - Ok(1) - } - - async fn sendUciMessage(&self, data: &[u8]) -> Result { - log::debug!("sendUciMessage"); - - if let State::Opened { write, .. } = &mut *self.state.lock().await { - write - .write(data) - .await - .map(|written| written as i32) - .map_err(|_| binder::StatusCode::UNKNOWN_ERROR.into()) - } else { - Err(binder::ExceptionCode::ILLEGAL_STATE.into()) - } - } -} diff --git a/uwb/aidl/default/uwb-service.rc b/uwb/aidl/default/uwb-service.rc new file mode 100644 index 0000000000..e2c3825d35 --- /dev/null +++ b/uwb/aidl/default/uwb-service.rc @@ -0,0 +1,3 @@ +service vendor.uwb_hal /vendor/bin/hw/android.hardware.uwb-service + class hal + user uwb diff --git a/uwb/aidl/default/uwb.cpp b/uwb/aidl/default/uwb.cpp new file mode 100644 index 0000000000..1e2ef4e0a4 --- /dev/null +++ b/uwb/aidl/default/uwb.cpp @@ -0,0 +1,55 @@ +/* + * 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. + */ +#include + +#include "uwb.h" + +namespace { +static constexpr char kDefaultChipName[] = "default"; + +} // namespace + +namespace android { +namespace hardware { +namespace uwb { +namespace impl { +using namespace ::aidl::android::hardware::uwb; + +// The default implementation of the HAL assumes 1 chip on the device. +Uwb::Uwb() : chips_({{kDefaultChipName, ndk::SharedRefBase::make(kDefaultChipName)}}) {} + +Uwb::~Uwb() {} + +::ndk::ScopedAStatus Uwb::getChips(std::vector* names) { + for (const auto& chip : chips_) { + names->push_back(chip.first); + } + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus Uwb::getChip(const std::string& name, std::shared_ptr* chip) { + const auto chip_found = chips_.find(name); + if (chip_found == chips_.end()) { + LOG(ERROR) << "Unknown chip name" << name; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + *chip = chip_found->second; + return ndk::ScopedAStatus::ok(); +} +} // namespace impl +} // namespace uwb +} // namespace hardware +} // namespace android diff --git a/uwb/aidl/default/uwb.h b/uwb/aidl/default/uwb.h new file mode 100644 index 0000000000..ec51fd8a5c --- /dev/null +++ b/uwb/aidl/default/uwb.h @@ -0,0 +1,49 @@ +/* + * 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. + */ +#ifndef ANDROID_HARDWARE_UWB_UWB +#define ANDROID_HARDWARE_UWB_UWB + +#include +#include + +#include +#include + +#include "uwb_chip.h" + +namespace android { +namespace hardware { +namespace uwb { +namespace impl { +using namespace ::aidl::android::hardware::uwb; +// Default implementation mean't to be used on simulator targets. +class Uwb : public BnUwb { + public: + Uwb(); + virtual ~Uwb(); + + ::ndk::ScopedAStatus getChips(std::vector* names) override; + ::ndk::ScopedAStatus getChip(const std::string& name, std::shared_ptr* chip) override; + + private: + std::map> chips_; +}; +} // namespace impl +} // namespace uwb +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_UWB_UWB \ No newline at end of file diff --git a/uwb/aidl/default/uwb_chip.cpp b/uwb/aidl/default/uwb_chip.cpp new file mode 100644 index 0000000000..41f14fd894 --- /dev/null +++ b/uwb/aidl/default/uwb_chip.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#include "uwb.h" + +namespace { +constexpr static int32_t kAndroidUciVersion = 1; +} + +namespace android { +namespace hardware { +namespace uwb { +namespace impl { +using namespace ::aidl::android::hardware::uwb; + +UwbChip::UwbChip(const std::string& name) : name_(name), mClientCallback(nullptr) {} +UwbChip::~UwbChip() {} + +::ndk::ScopedAStatus UwbChip::getName(std::string* name) { + *name = name_; + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus UwbChip::open(const std::shared_ptr& clientCallback) { + mClientCallback = clientCallback; + mClientCallback->onHalEvent(UwbEvent::OPEN_CPLT, UwbStatus::OK); + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus UwbChip::close() { + mClientCallback->onHalEvent(UwbEvent::CLOSE_CPLT, UwbStatus::OK); + mClientCallback = nullptr; + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus UwbChip::coreInit() { + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus UwbChip::sessionInit(int /* sessionId */) { + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus UwbChip::getSupportedAndroidUciVersion(int32_t* version) { + *version = kAndroidUciVersion; + return ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus UwbChip::sendUciMessage(const std::vector& /* data */, + int32_t* /* bytes_written */) { + // TODO(b/195992658): Need emulator support for UCI stack. + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); +} +} // namespace impl +} // namespace uwb +} // namespace hardware +} // namespace android diff --git a/uwb/aidl/default/uwb_chip.h b/uwb/aidl/default/uwb_chip.h new file mode 100644 index 0000000000..e900cbe123 --- /dev/null +++ b/uwb/aidl/default/uwb_chip.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef ANDROID_HARDWARE_UWB_UWBCHIP +#define ANDROID_HARDWARE_UWB_UWBCHIP + +#include + +#include +#include + +namespace android { +namespace hardware { +namespace uwb { +namespace impl { +using namespace ::aidl::android::hardware::uwb; +// Default implementation mean't to be used on simulator targets. +class UwbChip : public BnUwbChip { + public: + UwbChip(const std::string& name); + virtual ~UwbChip(); + + ::ndk::ScopedAStatus getName(std::string* name) override; + ::ndk::ScopedAStatus open(const std::shared_ptr& clientCallback) override; + ::ndk::ScopedAStatus close() override; + ::ndk::ScopedAStatus coreInit() override; + ::ndk::ScopedAStatus sessionInit(int sesionId) override; + ::ndk::ScopedAStatus getSupportedAndroidUciVersion(int32_t* version) override; + ::ndk::ScopedAStatus sendUciMessage(const std::vector& data, + int32_t* bytes_written) override; + + private: + std::string name_; + std::shared_ptr mClientCallback; +}; +} // namespace impl +} // namespace uwb +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_UWB_UWBCHIP