Added minimal implementation of platform.cc using shared posix implementations.

This commit is contained in:
kidfromjupiter
2025-12-26 15:49:38 +00:00
parent 922ff58a3b
commit 333688074a
11 changed files with 355 additions and 51 deletions
+77 -6
View File
@@ -1,17 +1,88 @@
cc_library(
name = "linux_platform_impl",
name = "types",
srcs = [
"device_info.cc"
"device_info.cc",
],
hdrs = [
"device_info.h"
"atomics.h",
"bluetooth_adapter.h",
"generated/bluez_adapter_client_glue.h",
"device_info.h",
"multi_thread_executor.h",
"scheduled_executor.h",
"platform.h",
],
visibility = ["//visibility:private"],
deps = [
"@sdbus_cpp//:sdbus_cpp",
"@sdbus_cpp//:libsystemd",
"//internal/base:file_path",
"//internal/platform:base",
"//internal/platform:logging",
"//internal/platform/implementation:types",
"@com_google_absl//absl/strings"
"@com_google_absl//absl/strings",
"@sdbus_cpp//:sdbus_cpp",
"@sdbus_cpp//:libsystemd",
],
)
cc_library(
name = "linux",
srcs = [
"bluetooth_adapter.cc",
"platform.cc",
"scheduled_executor.cc",
],
hdrs = [
"device_info.h",
"bluetooth_adapter.h",
],
visibility = ["//visibility:public"],
deps = [
":types",
"//connections/implementation/flags:connections_flags",
"//internal/base:file_path",
"//internal/base:files",
"//internal/flags:nearby_flags",
"//internal/platform:base",
"//internal/platform:cancellation_flag",
"//internal/platform:logging",
"//internal/platform:mac_address",
"//internal/platform:types",
"//internal/platform:uuid",
"//internal/platform/flags:platform_flags",
"//internal/platform/implementation:comm",
"//internal/platform/implementation:platform",
"//internal/platform/implementation:types",
"//internal/platform/implementation:wifi_utils",
"//internal/platform/implementation/shared:posix_condition_variable",
"//internal/platform/implementation/shared:posix_mutex",
"//internal/platform/implementation/shared:count_down_latch",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:span",
"@nlohmann_json//:json",
"@sdbus_cpp//:sdbus_cpp",
"@sdbus_cpp//:libsystemd",
],
)
# The existing target that other BUILD files select on; keep for compatibility.
cc_library(
name = "linux_platform_impl",
srcs = [],
hdrs = [],
deps = [
":linux",
":types",
],
visibility = ["//visibility:public"],
)
@@ -1,33 +0,0 @@
//
// Created by root on 10/2/25.
//
#ifndef LINUX_ATOMIC_BOOLEAN_H
#define LINUX_ATOMIC_BOOLEAN_H
#include <atomic>
#include "internal/platform/implementation/atomic_boolean.h"
namespace nearby {
namespace linux {
// A boolean value that may be updated atomically.
class AtomicBoolean : public api::AtomicBoolean {
public:
explicit AtomicBoolean(bool value = false) : atomic_boolean_(value) {}
~AtomicBoolean() override = default;
// Atomically read and return current value.
bool Get() const override { return atomic_boolean_; };
// Atomically exchange original value with a new one. Return previous value.
bool Set(bool value) override { return atomic_boolean_.exchange(value); };
private:
std::atomic_bool atomic_boolean_ = false;
};
} // namespace api
} // namespace nearby
#endif //LINUX_ATOMIC_BOOLEAN_H
@@ -18,8 +18,6 @@
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/linux/bluetooth_adapter.h"
#include "third_party/absl/absl/strings/str_format.h"
namespace nearby {
namespace linux {
bool BluetoothAdapter::SetStatus(Status status)
@@ -52,10 +52,10 @@ class BluetoothAdapter : public api::BluetoothAdapter, public sdbus::ProxyInterf
// Synchronously sets the status of the BluetoothAdapter to 'status', and
// returns true if the operation was a success.
bool SetStatus(Status status) = 0;
bool SetStatus(Status status) override;
// Returns true if the BluetoothAdapter's current status is
// Status::Value::kEnabled.
bool IsEnabled() const = 0;
[[nodiscard]] bool IsEnabled() const override;
// Scan modes of a BluetoothAdapter, as described at
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode().
@@ -69,28 +69,28 @@ class BluetoothAdapter : public api::BluetoothAdapter, public sdbus::ProxyInterf
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode()
//
// Returns ScanMode::kUnknown on error.
ScanMode GetScanMode() const = 0;
[[nodiscard]] ScanMode GetScanMode() const override;
// Synchronously sets the scan mode of the adapter, and returns true if the
// operation was a success.
bool SetScanMode(ScanMode scan_mode) = 0;
bool SetScanMode(ScanMode scan_mode) override;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
// Returns an empty string on error
std::string GetName() const = 0;
[[nodiscard]] std::string GetName() const override;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
bool SetName(absl::string_view name) = 0;
bool SetName(absl::string_view name, bool persist) = 0;
bool SetName(absl::string_view name) override;
bool SetName(absl::string_view name, bool persist) override;
// Returns BT MAC address assigned to this adapter.
ABSL_DEPRECATED("Use GetAddress() instead.")
std::string GetMacAddress() const = 0;
[[nodiscard]] std::string GetMacAddress() const override;
// Implementation for migration only. Once subclasses implement this, the
// above GetMacAddress() can be removed.
MacAddress GetAddress() const {
[[nodiscard]] MacAddress GetAddress() const override {
std::string mac_address = GetMacAddress();
if (mac_address.empty()) {
return MacAddress();
return {};
}
MacAddress address;
MacAddress::FromString(mac_address, address);
@@ -0,0 +1,149 @@
// filepath: /workspace/internal/platform/implementation/linux/platform.cc
// Minimal Linux implementation of ImplementationPlatform.
#include "internal/platform/implementation/platform.h"
#include <memory>
#include <string>
#include "bluetooth_adapter.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/count_down_latch.h"
#include "internal/platform/implementation/http_loader.h"
#include "internal/platform/implementation/shared/count_down_latch.h"
#include "internal/platform/implementation/linux/atomics.h"
#include "internal/platform/implementation/linux/multi_thread_executor.h"
#include "internal/platform/implementation/linux/scheduled_executor.h"
#include "internal/platform/implementation/linux/device_info.h"
#include "internal/platform/implementation/shared/posix_mutex.h"
#include "internal/platform/implementation/shared/posix_condition_variable.h"
#include <sdbus-c++/sdbus-c++.h>
namespace nearby {
namespace api {
std::string ImplementationPlatform::GetCustomSavePath(const std::string& parent_folder,
const std::string& file_name) {
return absl::StrCat(parent_folder, "/", file_name);
}
std::string ImplementationPlatform::GetDownloadPath(const std::string& parent_folder,
const std::string& file_name) {
return absl::StrCat("/tmp/", file_name);
}
std::string ImplementationPlatform::GetDownloadPath(const std::string& file_name) {
return absl::StrCat("/tmp/", file_name);
}
std::string ImplementationPlatform::GetAppDataPath(const std::string& file_name) {
return absl::StrCat("/tmp/", file_name);
}
OSName ImplementationPlatform::GetCurrentOS() { return OSName::kLinux; }
std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(bool initial_value) {
return std::make_unique<nearby::linux::AtomicBoolean>(initial_value);
}
std::unique_ptr<AtomicUint32> ImplementationPlatform::CreateAtomicUint32(std::uint32_t value) {
return std::make_unique<nearby::linux::AtomicUint32>(value);
}
std::unique_ptr<CountDownLatch> ImplementationPlatform::CreateCountDownLatch(std::int32_t count) {
return std::make_unique<shared::CountDownLatch>(count);
}
#pragma push_macro("CreateMutex")
#undef CreateMutex
std::unique_ptr<Mutex> ImplementationPlatform::CreateMutex(Mutex::Mode mode) {
// Use the shared POSIX mutex implementation. The posix::Mutex is recursive by
// design (uses PTHREAD_MUTEX_RECURSIVE), so return it for both regular and
// recursive modes to use a consistent POSIX implementation across Linux.
return std::make_unique<posix::Mutex>();
}
#pragma pop_macro("CreateMutex")
std::unique_ptr<ConditionVariable> ImplementationPlatform::CreateConditionVariable(Mutex* mutex) {
if (mutex == nullptr) return nullptr;
// Expect a posix::Mutex instance here; if it's not, return nullptr.
auto* derived = dynamic_cast<posix::Mutex*>(mutex);
if (!derived) return nullptr;
return std::make_unique<posix::ConditionVariable>(derived);
}
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(PayloadId, std::int64_t) {
return nullptr;
}
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(const std::string&, size_t) {
return nullptr;
}
std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(PayloadId) {
return nullptr;
}
std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(const std::string&) {
return nullptr;
}
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(const char* file, int line, LogMessage::Severity severity) {
return nullptr;
}
std::unique_ptr<SubmittableExecutor> ImplementationPlatform::CreateSingleThreadExecutor() {
return std::make_unique<linux::MultiThreadExecutor>(1);
}
std::unique_ptr<SubmittableExecutor> ImplementationPlatform::CreateMultiThreadExecutor(std::int32_t max_concurrency) {
return std::make_unique<linux::MultiThreadExecutor>(static_cast<int>(max_concurrency));
}
std::unique_ptr<ScheduledExecutor> ImplementationPlatform::CreateScheduledExecutor() {
return std::unique_ptr<api::ScheduledExecutor>(new linux::ScheduledExecutor());
}
std::unique_ptr<AwdlMedium> ImplementationPlatform::CreateAwdlMedium() { return nullptr; }
std::unique_ptr<BluetoothAdapter> ImplementationPlatform::CreateBluetoothAdapter()
{
static auto connection = sdbus::createConnection();
return std::make_unique<linux::BluetoothAdapter>(*connection, "/org/bluez/hci0");
}
std::unique_ptr<BluetoothClassicMedium> ImplementationPlatform::CreateBluetoothClassicMedium(BluetoothAdapter&) { return nullptr; }
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(BluetoothAdapter&) { return nullptr; }
std::unique_ptr<api::ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter&) { return nullptr; }
std::unique_ptr<api::CredentialStorage> ImplementationPlatform::CreateCredentialStorage() { return nullptr; }
std::unique_ptr<ServerSyncMedium> ImplementationPlatform::CreateServerSyncMedium() { return nullptr; }
std::unique_ptr<WifiMedium> ImplementationPlatform::CreateWifiMedium() { return nullptr; }
std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() { return nullptr; }
std::unique_ptr<WifiHotspotMedium> ImplementationPlatform::CreateWifiHotspotMedium() { return nullptr; }
std::unique_ptr<WifiDirectMedium> ImplementationPlatform::CreateWifiDirectMedium() { return nullptr; }
std::unique_ptr<Timer> ImplementationPlatform::CreateTimer() { return nullptr; }
std::unique_ptr<DeviceInfo> ImplementationPlatform::CreateDeviceInfo() {
return std::make_unique<linux::DeviceInfo>();
}
#ifndef NO_WEBRTC
std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() { return nullptr; }
#endif
absl::StatusOr<WebResponse> ImplementationPlatform::SendRequest(const WebRequest& request) {
return absl::UnimplementedError("HTTP loader not implemented on this minimal linux platform");
}
#ifndef NEARBY_CHROMIUM
std::unique_ptr<nearby::api::PreferencesManager> ImplementationPlatform::CreatePreferencesManager(absl::string_view path) {
return nullptr;
}
#endif
} // namespace api
} // namespace nearby
@@ -6,6 +6,9 @@ namespace nearby
{
namespace linux
{
class Platform: public api::ImplementationPlatform
{
};
}
@@ -0,0 +1,97 @@
//
// Created by root on 10/8/25.
//
#ifndef WORKSPACE_SCHEDULED_EXECUTOR_H
#define WORKSPACE_SCHEDULED_EXECUTOR_H
#include "internal/platform/implementation/scheduled_executor.h"
#include "internal/platform/runnable.h"
#include "internal/platform/implementation/cancelable.h"
#include "internal/platform/implementation/linux/multi_thread_executor.h"
#include <atomic>
#include <thread>
#include <utility>
#include "absl/time/time.h"
namespace nearby
{
namespace linux
{
// Minimal ScheduledExecutor implementation for linux.
class ScheduledExecutor : public api::ScheduledExecutor
{
public:
~ScheduledExecutor() override = default;
ScheduledExecutor() : shutdown_(false), executor_(1) {}
// Schedule a runnable to run after `duration`. Returns a Cancelable which
// can be used to cancel the scheduled task before it runs.
std::shared_ptr<api::Cancelable> Schedule(Runnable&& runnable,
absl::Duration duration) override
{
class ScheduledCancelable : public api::Cancelable {
public:
enum Status { kNotRun, kExecuted, kCanceled };
ScheduledCancelable() : status_(kNotRun) {}
bool Cancel() override {
Status expected = kNotRun;
return status_.compare_exchange_strong(expected, kCanceled);
}
[[nodiscard]] bool IsCanceled() const { return status_.load() == kCanceled; }
[[nodiscard]] bool MarkExecuted() {
Status expected = kNotRun;
return status_.compare_exchange_strong(expected, kExecuted);
}
private:
std::atomic<Status> status_;
};
auto cancelable = std::make_shared<ScheduledCancelable>();
if (shutdown_.load()) return cancelable;
// Move runnable into the thread task.
Runnable task = [this, cancelable, runnable = std::move(runnable)]() mutable {
if (shutdown_.load()) return;
if (cancelable->IsCanceled()) return;
if (!cancelable->MarkExecuted()) return;
// Use executor_ to run the actual runnable.
executor_.Execute(std::move(runnable));
};
// Spawn a detached thread that sleeps for the duration then runs the task
// through executor_. Using a detached thread is simple and sufficient for
// a minimal implementation.
std::thread([d = duration, t = std::move(task), cancelable, this]() mutable {
if (absl::ToInt64Nanoseconds(d) > 0) {
std::this_thread::sleep_for(std::chrono::nanoseconds(
absl::ToInt64Nanoseconds(d)));
}
if (shutdown_.load()) return;
if (cancelable->IsCanceled()) return;
if (t) t();
}).detach();
return cancelable;
};
void Execute(Runnable&& runnable) override {
if (shutdown_.load()) return;
executor_.Execute(std::move(runnable));
}
void Shutdown() override {
if (!shutdown_.exchange(true)) {
executor_.Shutdown();
}
}
private:
std::atomic<bool> shutdown_;
// Reuse the multi-thread executor implementation for running tasks.
linux::MultiThreadExecutor executor_;
};
}
}
#endif //WORKSPACE_SCHEDULED_EXECUTOR_H
@@ -50,6 +50,7 @@ cc_library(
hdrs = [
"posix_condition_variable.h",
],
visibility = ["//internal/platform/implementation:__subpackages__"],
deps = [
":posix_mutex",
"//internal/platform/implementation:types",
@@ -13,6 +13,8 @@
// limitations under the License.
#include "internal/platform/implementation/shared/posix_condition_variable.h"
#include "absl/time/time.h"
#include <cerrno>
namespace nearby {
namespace posix {
@@ -38,5 +40,20 @@ Exception ConditionVariable::Wait() {
return {Exception::kSuccess};
}
Exception ConditionVariable::Wait(absl::Duration timeout) {
// Calculate absolute deadline as timespec for pthread_cond_timedwait.
absl::Time deadline = absl::Now() + timeout;
int64_t nanos = absl::ToUnixNanos(deadline);
timespec ts{}; // zero-initialize to satisfy static analyzers
ts.tv_sec = static_cast<time_t>(nanos / 1000000000LL);
ts.tv_nsec = static_cast<long>(nanos % 1000000000LL);
int rc = pthread_cond_timedwait(&cond_, &(mutex_->mutex_), &ts);
if (rc == 0) return {Exception::kSuccess};
if (rc == ETIMEDOUT) return {Exception::kTimeout};
if (rc == EINTR) return {Exception::kInterrupted};
return {Exception::kFailed};
}
} // namespace posix
} // namespace nearby
@@ -30,6 +30,7 @@ class ConditionVariable : public api::ConditionVariable {
void Notify() override;
Exception Wait() override;
Exception Wait(absl::Duration timeout) override;
private:
Mutex* mutex_;