mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Added minimal implementation of platform.cc using shared posix implementations.
This commit is contained in:
@@ -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_;
|
||||
|
||||
Reference in New Issue
Block a user