nearby: snapshot of cl/304428753

Signed-off-by: Alexey Polyudov <apolyudov@google.com>
Change-Id: I0023ac6e40456fc4a8169c3173bcbff3b5ccc476
This commit is contained in:
Alexey Polyudov
2020-04-04 12:54:05 -07:00
parent 204f76077d
commit d455926d89
87 changed files with 2869 additions and 631 deletions
+9 -5
View File
@@ -26,7 +26,6 @@ cc_library(
":types",
"//platform/api",
"//platform/port:string",
"//strings",
"//absl/strings",
"//absl/time",
],
@@ -34,15 +33,11 @@ cc_library(
cc_library(
name = "types",
srcs = [
"ptr.cc",
],
hdrs = [
"byte_array.h",
"callable.h",
"cancelable.h",
"container_of.h",
"exception.cc",
"exception.h",
"ptr.h",
"runnable.h",
@@ -113,6 +108,15 @@ cc_test(
],
)
cc_test(
name = "exception_test",
srcs = ["exception_test.cc"],
deps = [
":types",
"//testing/base/public:gunit_main",
],
)
cc_test(
name = "pipe_test",
timeout = "short",
+5
View File
@@ -20,23 +20,28 @@ cc_library(
"hash_utils.h",
"input_file.h",
"input_stream.h",
"listenable_future.h",
"lock.h",
"multi_thread_executor.h",
"output_file.h",
"output_stream.h",
"scheduled_executor.h",
"server_sync.h",
"settable_future.h",
"single_thread_executor.h",
"socket.h",
"submittable_executor.h",
"system_clock.h",
"thread_utils.h",
"webrtc.h",
"wifi.h",
"wifi_lan.h",
],
deps = [
"//platform:types",
"//platform/port:down_cast",
"//platform/port:string",
"//webrtc/files/stable/webrtc/api:libjingle_peerconnection_api",
],
)
+6 -3
View File
@@ -39,7 +39,7 @@ struct BLEAdvertisementData {
std::set<std::string> service_uuids;
// Maps service UUIDs to their service data.
// Ownership of the map values is tied to ownership of BLEAdvertisementData.
std::map<std::string, ConstPtr<ByteArray> > service_data;
std::map<std::string, ConstPtr<ByteArray>> service_data;
};
// Opaque wrapper over a BLE peripheral. Must be able to uniquely identify a
@@ -217,7 +217,8 @@ class GATTServer {
// about this descriptor, please go to:
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
virtual Ptr<GATTCharacteristic> createCharacteristic(
const std::string& service_uuid, const std::string& characteristic_uuid,
const std::string& service_uuid,
const std::string& characteristic_uuid,
const std::set<GATTCharacteristic::Permission::Value>& permissions,
const std::set<GATTCharacteristic::Property::Value>& properties) = 0;
@@ -384,7 +385,9 @@ class BLEMediumV2 {
// HIGH:
// - Connection interval = ~100ms - 125ms
virtual Ptr<ClientGATTConnection> connectToGATTServer(
Ptr<BLEPeripheralV2> peripheral, MTU mtu, PowerMode::Value power_mode,
Ptr<BLEPeripheralV2> peripheral,
MTU mtu,
PowerMode::Value power_mode,
Ptr<ClientGATTConnectionLifecycleCallback>
connection_lifecycle_callback) = 0;
+7 -5
View File
@@ -60,7 +60,7 @@ class BluetoothServerSocket {
//
// The returned Ptr will be owned (and destroyed) by the caller. Returns
// Exception::IO on error.
virtual ExceptionOr<Ptr<BluetoothSocket> > accept() = 0;
virtual ExceptionOr<Ptr<BluetoothSocket>> accept() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
//
@@ -116,8 +116,9 @@ class BluetoothClassicMedium {
//
// The returned Ptr will be owned (and destroyed) by the caller. Returns
// Exception::IO on error.
virtual ExceptionOr<Ptr<BluetoothSocket> > connectToService(
Ptr<BluetoothDevice> remote_device, const std::string& service_uuid) = 0;
virtual ExceptionOr<Ptr<BluetoothSocket>> connectToService(
Ptr<BluetoothDevice> remote_device,
const std::string& service_uuid) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
//
@@ -129,8 +130,9 @@ class BluetoothClassicMedium {
//
// The returned Ptr will be owned (and destroyed) by the caller. Returns
// Exception::IO on error.
virtual ExceptionOr<Ptr<BluetoothServerSocket> > listenForService(
const std::string& service_name, const std::string& service_uuid) = 0;
virtual ExceptionOr<Ptr<BluetoothServerSocket>> listenForService(
const std::string& service_name,
const std::string& service_uuid) = 0;
};
} // namespace nearby
+6
View File
@@ -1,6 +1,9 @@
#ifndef PLATFORM_API_EXECUTOR_H_
#define PLATFORM_API_EXECUTOR_H_
#include "platform/ptr.h"
#include "platform/runnable.h"
namespace location {
namespace nearby {
@@ -12,6 +15,9 @@ class Executor {
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--
virtual void shutdown() = 0;
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-
virtual void execute(Ptr<Runnable> runnable) = 0;
};
} // namespace nearby
+7
View File
@@ -1,6 +1,8 @@
#ifndef PLATFORM_API_FUTURE_H_
#define PLATFORM_API_FUTURE_H_
#include <cstdint>
#include "platform/exception.h"
namespace location {
@@ -16,6 +18,11 @@ class Future {
virtual ExceptionOr<T>
get() = 0; // throws Exception::INTERRUPTED, Exception::EXECUTION
// throws Exception::INTERRUPTED, Exception::EXECUTION
// throws Exception::TIMEOUT if |timeout_ms| is exceeded while waiting for
// result.
virtual ExceptionOr<T> get(std::int64_t timeout_ms) = 0;
};
} // namespace nearby
+1 -1
View File
@@ -16,7 +16,7 @@ class InputFile {
// The returned ConstPtr will be owned (and destroyed) by the caller.
// When we have exhausted reading the file and no bytes remain, read will
// always return an empty ConstPtr for which isNull() is true.
virtual ExceptionOr<ConstPtr<ByteArray> > read(
virtual ExceptionOr<ConstPtr<ByteArray>> read(
std::int64_t size) = 0; // throws Exception::IO when the file cannot be
// opened or read.
virtual std::string getFilePath() const = 0;
+2 -2
View File
@@ -18,9 +18,9 @@ class InputStream {
virtual ~InputStream() {}
// The returned ConstPtr will be owned (and destroyed) by the caller.
virtual ExceptionOr<ConstPtr<ByteArray> > read() = 0; // throws Exception::IO
virtual ExceptionOr<ConstPtr<ByteArray>> read() = 0; // throws Exception::IO
// The returned ConstPtr will be owned (and destroyed) by the caller.
virtual ExceptionOr<ConstPtr<ByteArray> > read(
virtual ExceptionOr<ConstPtr<ByteArray>> read(
std::int64_t size) = 0; // throws Exception::IO
virtual Exception::Value close() = 0; // throws Exception::IO
};
+28
View File
@@ -0,0 +1,28 @@
#ifndef PLATFORM_API_LISTENABLE_FUTURE_H_
#define PLATFORM_API_LISTENABLE_FUTURE_H_
#include "platform/api/executor.h"
#include "platform/api/future.h"
#include "platform/exception.h"
#include "platform/ptr.h"
#include "platform/runnable.h"
namespace location {
namespace nearby {
// A Future that accepts completion listeners.
//
// https://guava.dev/releases/20.0/api/docs/com/google/common/util/concurrent/ListenableFuture.html
template <typename T>
class ListenableFuture : public Future<T> {
public:
~ListenableFuture() override {}
// Executor is shared among multiple runnables. It is not owned by any future.
virtual void addListener(Ptr<Runnable> runnable, Executor* executor) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API_LISTENABLE_FUTURE_H_
+2 -2
View File
@@ -11,8 +11,8 @@ namespace nearby {
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int-
template <typename ConcreteSubmittableExecutor>
class MultiThreadExecutor :
public SubmittableExecutor<ConcreteSubmittableExecutor> {
class MultiThreadExecutor
: public SubmittableExecutor<ConcreteSubmittableExecutor> {
public:
~MultiThreadExecutor() override {}
};
+64
View File
@@ -0,0 +1,64 @@
#ifndef PLATFORM_API_SERVER_SYNC_H_
#define PLATFORM_API_SERVER_SYNC_H_
#include <string>
#include "platform/byte_array.h"
#include "platform/ptr.h"
namespace location {
namespace nearby {
// Abstraction that represents a Nearby endpoint exchanging data through
// ServerSync Medium.
class ServerSyncDevice {
public:
virtual ~ServerSyncDevice() {}
virtual std::string getName() = 0;
virtual std::string getGuid() = 0;
virtual std::string getOwnGuid() = 0;
};
// Container of operations that can be performed over the Chrome Sync medium.
class ServerSyncMedium {
public:
virtual ~ServerSyncMedium() {}
// Takes ownership of (and is responsible for destroying) the passed-in
// 'endpoint_info'.
virtual bool startAdvertising(const std::string& service_id,
const std::string& endpoint_id,
ConstPtr<ByteArray> endpoint_info) = 0;
virtual void stopAdvertising(const std::string& service_id) = 0;
class DiscoveredDeviceCallback {
public:
virtual ~DiscoveredDeviceCallback() {}
// Called on a new ServerSyncDevice discovery.
virtual void onDeviceDiscovered(Ptr<ServerSyncDevice> device,
const std::string& service_id,
const std::string& endpoint_id,
ConstPtr<ByteArray> endpoint_info) = 0;
// Called when ServerSyncDevice is no longer reachable.
virtual void onDeviceLost(Ptr<ServerSyncDevice> device,
const std::string& service_id) = 0;
};
// Returns true once the Chrome Sync scan has been initiated.
virtual bool startDiscovery(
const std::string& service_id,
Ptr<DiscoveredDeviceCallback> discovered_device_callback) = 0;
// Returns true once Chrome Sync scan for service_id is well and truly
// stopped; after this returns, there must be no more invocations of the
// DiscoveredDeviceCallback passed in to startScanning() for service_id.
virtual void stopDiscovery(const std::string& service_id) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API_SERVER_SYNC_H_
+4 -2
View File
@@ -1,7 +1,7 @@
#ifndef PLATFORM_API_SETTABLE_FUTURE_H_
#define PLATFORM_API_SETTABLE_FUTURE_H_
#include "platform/api/future.h"
#include "platform/api/listenable_future.h"
namespace location {
namespace nearby {
@@ -10,11 +10,13 @@ namespace nearby {
//
// https://google.github.io/guava/releases/20.0/api/docs/com/google/common/util/concurrent/SettableFuture.html
template <typename T>
class SettableFuture : public Future<T> {
class SettableFuture : public ListenableFuture<T> {
public:
~SettableFuture() override {}
virtual bool set(T value) = 0;
virtual bool setException(Exception exception) = 0;
};
} // namespace nearby
+2 -2
View File
@@ -11,8 +11,8 @@ namespace nearby {
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor--
template <typename ConcreteSubmittableExecutor>
class SingleThreadExecutor :
public SubmittableExecutor<ConcreteSubmittableExecutor> {
class SingleThreadExecutor
: public SubmittableExecutor<ConcreteSubmittableExecutor> {
public:
~SingleThreadExecutor() override {}
};
+1 -5
View File
@@ -6,7 +6,6 @@
#include "platform/callable.h"
#include "platform/port/down_cast.h"
#include "platform/ptr.h"
#include "platform/runnable.h"
namespace location {
namespace nearby {
@@ -29,12 +28,9 @@ class SubmittableExecutor : public Executor {
~SubmittableExecutor() override {}
template <typename T>
Ptr<Future<T> > submit(Ptr<Callable<T> > callable) {
Ptr<Future<T>> submit(Ptr<Callable<T>> callable) {
return DOWN_CAST<ConcreteSubmittableExecutor*>(this)->submit(callable);
}
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-
virtual void execute(Ptr<Runnable> runnable) = 0;
};
} // namespace nearby
+46
View File
@@ -0,0 +1,46 @@
#ifndef PLATFORM_API_WEBRTC_H_
#define PLATFORM_API_WEBRTC_H_
#include <vector>
#include "platform/byte_array.h"
#include "platform/ptr.h"
#include "webrtc/files/stable/webrtc/api/peer_connection_interface.h"
namespace location {
namespace nearby {
class WebRtcSignalingMessenger {
public:
virtual ~WebRtcSignalingMessenger() = default;
/** Called whenever we receive an inbox message from tachyon. */
class SignalingMessageListener {
public:
virtual ~SignalingMessageListener() = default;
virtual void onSignalingMessage(ConstPtr<ByteArray> message) = 0;
};
class IceServersListener {
public:
virtual ~IceServersListener() = default;
virtual void OnIceServersFetched(
std::vector<Ptr<webrtc::PeerConnectionInterface::IceServer>>
ice_servers) = 0;
};
virtual bool registerSignaling() = 0;
virtual bool unregisterSignaling() = 0;
virtual bool sendMessage(const string& peer_id,
ConstPtr<ByteArray> message) = 0;
virtual bool startReceivingMessages(
Ptr<SignalingMessageListener> listener) = 0;
virtual void getIceServers(Ptr<IceServersListener> ice_servers_listener) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API_WEBRTC_H_
+3 -2
View File
@@ -58,7 +58,7 @@ class WifiMedium {
// owned (and destroyed) by the recipient of the callback methods (i.e. the
// creator of the concrete ScanResultCallback object).
virtual void onScanResults(
const std::vector<ConstPtr<WifiScanResult> >& scan_results) = 0;
const std::vector<ConstPtr<WifiScanResult>>& scan_results) = 0;
};
// Does not take ownership of the passed-in scan_result_callback -- destroying
@@ -69,7 +69,8 @@ class WifiMedium {
// WifiConnectionStatus::CONNECTED on success, or the appropriate failure code
// otherwise.
virtual WifiConnectionStatus::Value connectToNetwork(
const std::string& ssid, const std::string& password,
const std::string& ssid,
const std::string& password,
WifiAuthType::Value auth_type) = 0;
// Blocks until it's certain of there being a connection to the internet, or
+94
View File
@@ -0,0 +1,94 @@
#ifndef PLATFORM_API_WIFI_LAN_H_
#define PLATFORM_API_WIFI_LAN_H_
#include "platform/api/input_stream.h"
#include "platform/api/output_stream.h"
#include "platform/byte_array.h"
#include "platform/exception.h"
#include "platform/port/string.h"
#include "platform/ptr.h"
namespace location {
namespace nearby {
// Opaque wrapper over a WifiLan service which contains encoded service name.
class WifiLanService {
public:
virtual ~WifiLanService() = default;
virtual std::string GetName() = 0;
};
class WifiLanSocket {
public:
virtual ~WifiLanSocket() = default;
// Returns the InputStream of the WifiLanSocket, or a null Ptr<InputStream>
// on error.
//
// The returned Ptr is not owned by the caller, and can be invalidated once
// the WifiLanSocket object is destroyed.
virtual Ptr<InputStream> GetInputStream() = 0;
// Returns the OutputStream of the WifiLanSocket, or a null
// Ptr<OutputStream> on error.
//
// The returned Ptr is not owned by the caller, and can be invalidated once
// the WifiLanSocket object is destroyed.
virtual Ptr<OutputStream> GetOutputStream() = 0;
// Returns Exception::IO on error, Exception::NONE otherwise.
virtual Exception::Value Close() = 0;
// The returned Ptr is not owned by the caller, and can be invalidated once
// the WifiLanSocket object is destroyed.
virtual Ptr<WifiLanService> GetRemoteWifiLanService() = 0;
};
// Container of operations that can be performed over the WifiLan medium.
class WifiLanMedium {
public:
virtual ~WifiLanMedium() = default;
virtual bool StartAdvertising(const std::string& service_id,
const string& wifi_lan_service_info_name) = 0;
virtual void StopAdvertising(const std::string& service_id) = 0;
// Callback for WifiLan discover results.
class DiscoveredServiceCallback {
public:
virtual ~DiscoveredServiceCallback() = default;
virtual void OnServiceDiscovered(Ptr<WifiLanService> wifi_lan_service) = 0;
virtual void OnServiceLost(Ptr<WifiLanService> wifi_lan_service) = 0;
};
virtual bool StartDiscovery(
const std::string& service_id,
Ptr<DiscoveredServiceCallback> discovered_service_callback) = 0;
virtual void StopDiscovery(const std::string& service_id) = 0;
class AcceptedConnectionCallback {
public:
virtual ~AcceptedConnectionCallback() = default;
// The Ptr provided in this callback method will be owned (and
// destroyed) by the recipient of the callback methods (i.e. the creator of
// the concrete AcceptedConnectionCallback object).
virtual void OnConnectionAccepted(Ptr<WifiLanSocket> socket,
const string& service_id) = 0;
};
virtual bool StartAcceptingConnections(
const std::string& service_id,
Ptr<AcceptedConnectionCallback> accepted_connection_callback) = 0;
virtual void StopAcceptingConnections(const std::string& service_id) = 0;
virtual Ptr<WifiLanSocket> Connect(Ptr<WifiLanService> wifi_lan_service,
const std::string& service_id) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API_WIFI_LAN_H_
+65
View File
@@ -0,0 +1,65 @@
package(default_visibility = [
"//core:__subpackages__",
"//platform:__subpackages__",
"//location/nearby/setup/core:__subpackages__",
])
cc_library(
name = "api2",
hdrs = [
"atomic_boolean.h",
"atomic_reference.h",
"ble.h",
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
"condition_variable.h",
"count_down_latch.h",
"executor.h",
"future.h",
"hash_utils.h",
"input_file.h",
"input_stream.h",
"listenable_future.h",
"multi_thread_executor.h",
"mutex.h",
"output_file.h",
"output_stream.h",
"scheduled_executor.h",
"server_sync.h",
"settable_future.h",
"single_thread_executor.h",
"socket.h",
"submittable_executor.h",
"system_clock.h",
"thread_utils.h",
"webrtc.h",
"wifi.h",
],
deps = [
"//platform:types",
"//absl/strings",
"//absl/time",
"//webrtc/files/stable/webrtc/api:libjingle_peerconnection_api",
],
)
cc_library(
name = "mutex",
hdrs = ["mutex.h"],
visibility = [
"//platform:__subpackages__",
],
)
cc_library(
name = "condition_variable",
hdrs = ["condition_variable.h"],
visibility = [
"//platform:__subpackages__",
],
deps = [
"//platform:types",
"//absl/time",
],
)
+21
View File
@@ -0,0 +1,21 @@
#ifndef PLATFORM_API2_ATOMIC_BOOLEAN_H_
#define PLATFORM_API2_ATOMIC_BOOLEAN_H_
namespace location {
namespace nearby {
// A boolean value that may be updated atomically.
//
// https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html
class AtomicBoolean {
public:
virtual ~AtomicBoolean() {}
virtual bool Get() = 0;
virtual void Set(bool value) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_ATOMIC_BOOLEAN_H_
+22
View File
@@ -0,0 +1,22 @@
#ifndef PLATFORM_API2_ATOMIC_REFERENCE_H_
#define PLATFORM_API2_ATOMIC_REFERENCE_H_
namespace location {
namespace nearby {
// An object reference that may be updated atomically.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
template <typename T>
class AtomicReference {
public:
virtual ~AtomicReference() {}
virtual T Get() = 0;
virtual void Set(const T& value) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_ATOMIC_REFERENCE_H_
+111
View File
@@ -0,0 +1,111 @@
#ifndef PLATFORM_API2_BLE_H_
#define PLATFORM_API2_BLE_H_
#include "platform/api2/bluetooth_classic.h"
#include "platform/api2/input_stream.h"
#include "platform/api2/output_stream.h"
#include "platform/byte_array.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
// Opaque wrapper over a BLE peripheral. Must contain enough data about a
// particular BLE device to connect to its GATT server.
class BlePeripheral {
public:
virtual ~BlePeripheral() {}
// The returned Ptr is not owned by the caller, and can be invalidated once
// the corresponding BLEPeripheral object is destroyed.
virtual BluetoothDevice& GetBluetoothDevice() = 0;
};
class BleSocket {
public:
virtual ~BleSocket() {}
// Returns the InputStream of the BleSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the BleSocket object is destroyed.
virtual InputStream& GetInputStream() = 0;
// Returns the OutputStream of the BleSocket.
// On error, returned stream will report Exception::kIo on any operation.
//
// The returned object is not owned by the caller, and can be invalidated once
// the BleSocket object is destroyed.
virtual OutputStream& GetOutputStream() = 0;
// Conforms to the same contract as
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#close().
//
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
// The returned object is not owned by the caller, and can be invalidated once
// the BleSocket object is destroyed.
virtual BlePeripheral& GetRemotePeripheral() = 0;
};
// Container of operations that can be performed over the BLE medium.
class BleMedium {
public:
virtual ~BleMedium() {}
virtual bool StartAdvertising(absl::string_view service_id,
const ByteArray& advertisement) = 0;
virtual void StopAdvertising(absl::string_view service_id) = 0;
class DiscoveredPeripheralCallback {
public:
virtual ~DiscoveredPeripheralCallback() {}
// The BlePeripheral* is not owned by callbacks.
// It is passed to give access to its non-const methods.
// It is guaranteed to be valid for the duration of call.
virtual void OnPeripheralDiscovered(BlePeripheral* ble_peripheral,
absl::string_view service_id,
const ByteArray& advertisement) = 0;
virtual void OnPeripheralLost(BlePeripheral* ble_peripheral,
absl::string_view service_id) = 0;
};
// Returns true once the BLE scan has been initiated.
virtual bool StartScanning(
absl::string_view service_id,
const DiscoveredPeripheralCallback& discovered_peripheral_callback) = 0;
// Returns true once BLE scanning for service_id is well and truly stopped;
// after this returns, there must be no more invocations of the
// DiscoveredPeripheralCallback passed in to StartScanning() for service_id.
virtual void StopScanning(absl::string_view service_id) = 0;
// Callback that is invoked when a new connection is accepted.
class AcceptedConnectionCallback {
public:
virtual ~AcceptedConnectionCallback() {}
virtual void OnConnectionAccepted(std::unique_ptr<BleSocket> socket,
absl::string_view service_id) = 0;
};
// Returns true once BLE socket connection requests to service_id can be
// accepted.
virtual bool StartAcceptingConnections(
absl::string_view service_id,
const AcceptedConnectionCallback& accepted_connection_callback) = 0;
virtual void StopAcceptingConnections(const std::string& service_id) = 0;
// BlePeripheral* is not owned by this call;
// it must remain valid for the duration of a call.
virtual std::unique_ptr<BleSocket> Connect(BlePeripheral* ble_peripheral,
absl::string_view service_id) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_BLE_H_
+390
View File
@@ -0,0 +1,390 @@
#ifndef PLATFORM_API2_BLE_V2_H_
#define PLATFORM_API2_BLE_V2_H_
#include <cstdint>
#include <limits>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include "platform/byte_array.h"
#include "platform/exception.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
namespace v2 {
// https://developer.android.com/reference/android/bluetooth/le/AdvertiseData
//
// Bundle of data found in a BLE advertisement.
//
// All service UUIDs will conform to the 16-bit Bluetooth base UUID,
// 0000xxxx-0000-1000-8000-00805F9B34FB. This makes it possible to store two
// byte service UUIDs in the advertisement.
struct BleAdvertisementData {
using TxPowerLevel = int8_t;
static const TxPowerLevel kUnspecifiedTxPowerLevel =
std::numeric_limits<TxPowerLevel>::min();
bool is_connectable;
// When set to kUnspecifiedTxPowerLevel, TX power should not be included in
// the advertisement data.
TxPowerLevel tx_power_level;
// When set to an empty string, local name should not be included in the
// advertisement data.
std::string local_name;
// When set to an empty vector, the set of 16-bit service class UUIDs should
// not be included in the advertisement data.
std::set<std::string> service_uuids;
// Maps service UUIDs to their service data.
std::map<std::string, ByteArray> service_data;
};
// Opaque wrapper over a BLE peripheral. Must be able to uniquely identify a
// peripheral so that we can connect to its GATT server.
class BlePeripheral {
public:
virtual ~BlePeripheral() {}
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice#getAddress()
//
// This should be the MAC address when possible. If the implementation is
// unable to retrieve that, any unique identifier should suffice.
virtual std::string GetId() const = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic
//
// Representation of a GATT characteristic.
class GattCharacteristic {
public:
virtual ~GattCharacteristic() {}
// Possible permissions of a GATT characteristic.
enum class Permission {
kUnknown = 0,
kRead = 1,
kWrite = 2,
kLast,
};
// Possible properties of a GATT characteristic.
enum class Property {
kUnknown = 0,
kRead = 1,
kWrite = 2,
kIndicate = 3,
kLast,
};
// Returns the UUID of this characteristic.
virtual std::string GetUuid() = 0;
// Returns the UUID of the containing GATT service.
virtual std::string GetServiceUuid() = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt
//
// Representation of a client GATT connection to a remote GATT server.
class ClientGattConnection {
public:
virtual ~ClientGattConnection() {}
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#getDevice()
//
// Retrieves the BLE peripheral that this connection is tied to.
virtual BlePeripheral& GetPeripheral() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#discoverServices()
//
// Discovers all available services and characteristics on this connection.
// Returns whether or not discovery finished successfully.
//
// This function should block until discovery has finished.
virtual bool DiscoverServices() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#getService(java.util.UUID)
// https://developer.android.com/reference/android/bluetooth/BluetoothGattService.html#getCharacteristic(java.util.UUID)
//
// Retrieves a GATT characteristic. On error, does not return a value.
//
// DiscoverServices() should be called before this method to fetch all
// available services and characteristics first.
//
// It is okay for duplicate services to exist, as long as the specified
// characteristic UUID is unique among all services of the same UUID.
virtual std::optional<GattCharacteristic> GetCharacteristic(
absl::string_view service_uuid,
absl::string_view characteristic_uuid) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#readCharacteristic(android.bluetooth.BluetoothGattCharacteristic)
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#getValue()
//
// Reads a GATT characteristic. No value is returned upon error.
virtual std::optional<ByteArray> ReadCharacteristic(
const GattCharacteristic& characteristic) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[])
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic)
//
// Sends a remote characteristic write request to the server and returns
// whether or not it was successful.
virtual bool WriteCharacteristic(const GattCharacteristic& characteristic,
const ByteArray& value) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#disconnect()
//
// Disconnects a GATT connection.
virtual void Disconnect() = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothGattServer
//
// Representation of a server GATT connection to a remote GATT client.
class ServerGattConnection {
public:
virtual ~ServerGattConnection() {}
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[])
// https://developer.android.com/reference/android/bluetooth/BluetoothGattServer.html#notifyCharacteristicChanged(android.bluetooth.BluetoothDevice,%20android.bluetooth.BluetoothGattCharacteristic,%20boolean)
//
// Sends a notification (via indication) to the client that a characteristic
// has changed with the given value. Returns whether or not it was successful.
//
// The value sent does not have to reflect the locally stored characteristic
// value. To update the local value, call GattServer::UpdateCharacteristic.
virtual bool SendCharacteristic(const GattCharacteristic& characteristic,
const ByteArray& value) = 0;
};
// Callback for asynchronous events on the client side of a GATT connection.
class ClientGattConnectionLifeCycleCallback {
public:
virtual ~ClientGattConnectionLifeCycleCallback() {}
// Called when the client is disconnected from the GATT server.
virtual void OnDisconnected(ClientGattConnection* connection) = 0;
};
// Callback for asynchronous events on the server side of a GATT connection.
class ServerGattConnectionLifeCycleCallback {
public:
virtual ~ServerGattConnectionLifeCycleCallback() {}
// Called when a remote peripheral connected to us and subscribed to one of
// our characteristics.
virtual void OnCharacteristicSubscription(
ServerGattConnection* connection,
const GattCharacteristic& characteristic) = 0;
// Called when a remote peripheral unsubscribed from one of our
// characteristics.
virtual void OnCharacteristicUnsubscription(
ServerGattConnection* connection,
const GattCharacteristic& characteristic) = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothGattServer
//
// Representation of a BLE GATT server.
class GattServer {
public:
virtual ~GattServer() {}
// Creates a characteristic and adds it to the GATT server under the given
// characteristic and service UUIDs. Returns no value upon error.
//
// Characteristics of the same service UUID should be put under one
// service rather than many services with the same UUID.
//
// If the INDICATE property is included, the characteristic should include the
// official Bluetooth Client Characteristic Configuration descriptor with UUID
// 0x2902 and a WRITE permission. This allows remote clients to write to this
// descriptor and subscribe for characteristic changes. For more information
// about this descriptor, please go to:
// https://www.bluetooth.com/specifications/Gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.Gatt.client_characteristic_configuration.xml
virtual std::optional<GattCharacteristic> CreateCharacteristic(
absl::string_view service_uuid, absl::string_view characteristic_uuid,
const std::set<GattCharacteristic::Permission>& permissions,
const std::set<GattCharacteristic::Property>& properties) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#setValue(byte[])
//
// Locally updates the value of a characteristic and returns whether or not it
// was successful.
// Takes ownership of (and is responsible for destroying) the passed-in
// 'value'.
virtual bool UpdateCharacteristic(const GattCharacteristic& characteristic,
const ByteArray& value) = 0;
// Stops a GATT server.
virtual void Stop() = 0;
};
// A BLE socket representation.
class BleSocket {
public:
virtual ~BleSocket() {}
// Returns the remote BLE peripheral tied to this socket.
virtual BlePeripheral& GetRemotePeripheral() = 0;
// Writes a message on the socket and blocks until finished. Returns
// Exception::kIo upon error, and Exception::kSuccess otherwise.
virtual Exception Write(const ByteArray& message) = 0;
// Closes the socket and blocks until finished. Returns Exception::kIo upon
// error, and Exception::kSuccess otherwise.
virtual Exception Close() = 0;
};
// Callback for asynchronous events on a BleSocket object.
class BleSocketLifeCycleCallback {
public:
virtual ~BleSocketLifeCycleCallback() {}
// Called when a message arrives on a socket.
virtual void OnMessageReceived(BleSocket* socket,
const ByteArray& message) = 0;
// Called when a socket gets disconnected.
virtual void OnDisconnected(BleSocket* socket) = 0;
};
// Callback for asynchronous events on the server side of a BleSocket object.
class ServerBleSocketLifeCycleCallback : public BleSocketLifeCycleCallback {
public:
~ServerBleSocketLifeCycleCallback() override {}
// Called when a new incoming socket has been established.
virtual void OnSocketEstablished(BleSocket* socket) = 0;
};
// The main BLE medium used inside of Nearby. This serves as the entry point for
// all BLE and GATT related operations.
class BleMedium {
public:
using Mtu = uint32_t;
virtual ~BleMedium() {}
// Coarse representation of power settings throughout all BLE operations.
enum class PowerMode {
kUnknown = 0,
kLow = 1,
kHigh = 2,
kLast,
};
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#startAdvertising(android.bluetooth.le.AdvertiseSettings,%20android.bluetooth.le.AdvertiseData,%20android.bluetooth.le.AdvertiseData,%20android.bluetooth.le.AdvertiseCallback)
//
// Starts BLE advertising and returns whether or not it was successful.
//
// Power mode should be interpreted in the following way:
// LOW:
// - Advertising interval = ~1000ms
// - TX power = low
// HIGH:
// - Advertising interval = ~100ms
// - TX power = high
virtual bool StartAdvertising(const BleAdvertisementData& advertisement_data,
const BleAdvertisementData& scan_response,
PowerMode power_mode) = 0;
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#stopAdvertising(android.bluetooth.le.AdvertiseCallback)
//
// Stops advertising.
virtual void StopAdvertising() = 0;
// https://developer.android.com/reference/android/bluetooth/le/ScanCallback
//
// Callback for BLE scan results.
class ScanCallback {
public:
virtual ~ScanCallback() {}
// https://developer.android.com/reference/android/bluetooth/le/ScanCallback.html#onScanResult(int,%20android.bluetooth.le.ScanResult)
//
// Called when a BLE advertisement is discovered.
//
// The passed in advertisement_data is the merged combination of both
// advertisement data and scan response.
//
// Every discovery of an advertisement should be reported, even if the
// advertisement was discovered before.
//
// Ownership of the BleAdvertisementData transfers to the caller at this
// point.
virtual void OnAdvertisementFound(
BlePeripheral* peripheral,
const BleAdvertisementData& advertisement_data) = 0;
};
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(java.util.List%3Candroid.bluetooth.le.ScanFilter%3E,%20android.bluetooth.le.ScanSettings,%20android.bluetooth.le.ScanCallback)
//
// Starts scanning and returns whether or not it was successful.
//
// Power mode should be interpreted in the following way:
// LOW:
// - Scan window = ~512ms
// - Scan interval = ~5120ms
// HIGH:
// - Scan window = ~4096ms
// - Scan interval = ~4096ms
virtual bool StartScanning(const std::set<std::string>& service_uuids,
PowerMode power_mode,
const ScanCallback& scan_callback) = 0;
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#stopScan(android.bluetooth.le.ScanCallback)
//
// Stops scanning.
virtual void StopScanning() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothManager#openGattServer(android.content.Context,%20android.bluetooth.BluetoothGattServerCallback)
//
// Starts a GATT server. Returns a nullptr upon error.
virtual std::unique_ptr<GattServer> StartGattServer(
const ServerGattConnectionLifeCycleCallback& callback) = 0;
// Starts listening for incoming BLE sockets and returns false upon error.
virtual bool StartListeningForIncomingBleSockets(
const ServerBleSocketLifeCycleCallback& callback) = 0;
// Stops listening for incoming BLE sockets.
virtual void StopListeningForIncomingBleSockets() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#connectGatt(android.content.Context,%20boolean,%20android.bluetooth.BluetoothGattCallback)
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#requestConnectionPriority(int)
// https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#requestMtu(int)
//
// Connects to a GATT server and negotiates the specified connection
// parameters. Returns nullptr upon error.
//
// Both connection interval and MTU can be negotiated on a best-effort basis.
//
// Power mode should be interpreted in the following way:
// LOW:
// - Connection interval = ~11.25ms - 15ms
// HIGH:
// - Connection interval = ~100ms - 125ms
virtual std::unique_ptr<ClientGattConnection> ConnectToGattServer(
BlePeripheral* peripheral, Mtu mtu, PowerMode power_mode,
const ClientGattConnectionLifeCycleCallback& callback) = 0;
// Establishes a BLE socket to the specified remote peripheral. Returns
// nullptr on error.
virtual std::unique_ptr<BleSocket> EstablishBleSocket(
BlePeripheral* peripheral,
const BleSocketLifeCycleCallback& callback) = 0;
};
} // namespace v2
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_BLE_V2_H_
+55
View File
@@ -0,0 +1,55 @@
#ifndef PLATFORM_API2_BLUETOOTH_ADAPTER_H_
#define PLATFORM_API2_BLUETOOTH_ADAPTER_H_
#include <cstdint>
#include <string>
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
class BluetoothAdapter {
public:
virtual ~BluetoothAdapter() {}
// Eligible statuses of the BluetoothAdapter.
enum class Status {
kDisabled,
kEnabled,
};
// Synchronously sets the status of the BluetoothAdapter to 'status', and
// returns true if the operation was a success.
virtual bool SetStatus(Status status) = 0;
// Returns true if the BluetoothAdapter's current status is
// Status::Value::kEnabled.
virtual bool IsEnabled() = 0;
// Scan modes of a BluetoothAdapter, as described at
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode().
enum class ScanMode {
kUnknown,
kConnectableDiscoverable,
};
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode()
//
// Returns ScanMode::kUnknown on error.
virtual ScanMode GetScanMode() = 0;
// Synchronously sets the scan mode of the adapter, and returns true if the
// operation was a success.
virtual bool SetScanMode(ScanMode scan_mode) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
// Returns an empty string on error
virtual std::string GetName() const = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
virtual bool SetName(absl::string_view name) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_BLUETOOTH_ADAPTER_H_
+124
View File
@@ -0,0 +1,124 @@
#ifndef PLATFORM_API2_BLUETOOTH_CLASSIC_H_
#define PLATFORM_API2_BLUETOOTH_CLASSIC_H_
#include <memory>
#include <string>
#include "platform/api2/input_stream.h"
#include "platform/api2/output_stream.h"
#include "platform/byte_array.h"
#include "platform/exception.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice {
public:
virtual ~BluetoothDevice() {}
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
virtual std::string GetName() = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html.
class BluetoothSocket {
public:
virtual ~BluetoothSocket() {}
// Returns the InputStream of the BluetoothSocket.
virtual InputStream& GetInputStream() = 0;
// Returns the OutputStream of the BluetoothSocket.
virtual OutputStream& GetOutputStream() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#close()
//
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice()
virtual BluetoothDevice& GetRemoteDevice() = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html.
class BluetoothServerSocket {
public:
virtual ~BluetoothServerSocket() {}
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
//
// returns Exception::kIo on error.
virtual ExceptionOr<std::unique_ptr<BluetoothSocket>> Accept() = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
//
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
virtual Exception Close() = 0;
};
// Container of operations that can be performed over the Bluetooth Classic
// medium.
class BluetoothClassicMedium {
public:
virtual ~BluetoothClassicMedium() {}
class DiscoveryCallback {
public:
virtual ~DiscoveryCallback() {}
// BluetoothDevice* is not owned by callbacks.
// Pointer is guaranteed to remain valid for the duration of a call.
virtual void OnDeviceDiscovered(BluetoothDevice* device) = 0;
virtual void OnDeviceNameChanged(BluetoothDevice* device) = 0;
virtual void OnDeviceLost(BluetoothDevice* device) = 0;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
//
// Returns true once the process of discovery has been initiated.
//
// Does not take ownership of the passed-in discovery_callback -- destroying
// that is up to the caller.
virtual bool StartDiscovery(const DiscoveryCallback& discovery_callback) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#cancelDiscovery()
//
// Returns true once discovery is well and truly stopped; after this returns,
// there must be no more invocations of the DiscoveryCallback passed in to
// startDiscovery().
virtual bool StopDiscovery() = 0;
// A combination of
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createInsecureRfcommSocketToServiceRecord
// followed by
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#connect().
//
// service_uuid is the canonical textual representation
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
// type 3 name-based
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
// UUID.
//
// On success, returns a new BluetoothSocket, wrapped in a ExceptionOr object.
// On error, returns Exception object.
virtual ExceptionOr<std::unique_ptr<BluetoothSocket>> ConnectToService(
BluetoothDevice* remote_device, absl::string_view service_uuid) = 0;
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
//
// service_uuid is the canonical textual representation
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
// type 3 name-based
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
// UUID.
//
// Returns Exception::kIo on error.
virtual ExceptionOr<std::unique_ptr<BluetoothServerSocket>> ListenForService(
absl::string_view service_name, absl::string_view service_uuid) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_BLUETOOTH_CLASSIC_H_
+26
View File
@@ -0,0 +1,26 @@
#ifndef PLATFORM_API2_CONDITION_VARIABLE_H_
#define PLATFORM_API2_CONDITION_VARIABLE_H_
#include "platform/exception.h"
namespace location {
namespace nearby {
// The ConditionVariable class is a synchronization primitive that can be used
// to block a thread, or multiple threads at the same time, until another thread
// both modifies a shared variable (the condition), and notifies the
// ConditionVariable.
class ConditionVariable {
public:
virtual ~ConditionVariable() {}
// https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#notify--
virtual void Notify() = 0;
// https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait--
virtual Exception Wait() = 0; // throws Exception::kInterrupted
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_CONDITION_VARIABLE_H_
+29
View File
@@ -0,0 +1,29 @@
#ifndef PLATFORM_API2_COUNT_DOWN_LATCH_H_
#define PLATFORM_API2_COUNT_DOWN_LATCH_H_
#include <cstdint>
#include "platform/exception.h"
#include "absl/time/time.h"
namespace location {
namespace nearby {
// A synchronization aid that allows one or more threads to wait until a set of
// operations being performed in other threads completes.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html
class CountDownLatch {
public:
virtual ~CountDownLatch() {}
virtual Exception Await() = 0; // throws Exception::kInterrupted
virtual ExceptionOr<bool> Await(
absl::Duration timeout) = 0; // throws Exception::kInterrupted
virtual void CountDown() = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_COUNT_DOWN_LATCH_H_
+26
View File
@@ -0,0 +1,26 @@
#ifndef PLATFORM_API2_EXECUTOR_H_
#define PLATFORM_API2_EXECUTOR_H_
#include <memory>
#include "platform/runnable.h"
namespace location {
namespace nearby {
// This abstract class is the superclass of all classes representing an
// Executor.
class Executor {
public:
virtual ~Executor() = default;
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-
virtual void Execute(std::unique_ptr<Runnable> runnable) = 0;
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--
virtual void Shutdown() = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_EXECUTOR_H_
+30
View File
@@ -0,0 +1,30 @@
#ifndef PLATFORM_API2_FUTURE_H_
#define PLATFORM_API2_FUTURE_H_
#include "platform/exception.h"
#include "absl/time/time.h"
namespace location {
namespace nearby {
// A Future represents the result of an asynchronous computation.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html
template <typename T>
class Future {
public:
virtual ~Future() = default;
// throws Exception::kInterrupted, Exception::kExecution
virtual ExceptionOr<T> Get() = 0;
// throws Exception::kInterrupted, Exception::kExecution
// throws Exception::kTimeout if timeout is exceeded while waiting for
// result.
virtual ExceptionOr<T> Get(absl::Duration timeout) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_FUTURE_H_
+20
View File
@@ -0,0 +1,20 @@
#ifndef PLATFORM_API2_HASH_UTILS_H_
#define PLATFORM_API2_HASH_UTILS_H_
#include "platform/byte_array.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
// A provider of standard hashing algorithms.
class HashUtils {
public:
static ByteArray Md5(absl::string_view input);
static ByteArray Sha256(absl::string_view input);
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_HASH_UTILS_H_
+24
View File
@@ -0,0 +1,24 @@
#ifndef PLATFORM_API2_INPUT_FILE_H_
#define PLATFORM_API2_INPUT_FILE_H_
#include <cstdint>
#include "platform/api2/input_stream.h"
#include "platform/byte_array.h"
#include "platform/exception.h"
namespace location {
namespace nearby {
// An InputFile represents a readable file on the system.
class InputFile : public InputStream {
public:
~InputFile() override = default;
virtual std::string GetFilePath() const = 0;
virtual size_t GetTotalSize() const = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_INPUT_FILE_H_
+27
View File
@@ -0,0 +1,27 @@
#ifndef PLATFORM_API2_INPUT_STREAM_H_
#define PLATFORM_API2_INPUT_STREAM_H_
#include <cstdint>
#include "platform/byte_array.h"
#include "platform/exception.h"
namespace location {
namespace nearby {
// An InputStream represents an input stream of bytes.
//
// https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html
class InputStream {
public:
virtual ~InputStream() {}
virtual ExceptionOr<ByteArray> Read(
size_t size) = 0; // throws Exception::kIo
virtual Exception Close() = 0; // throws Exception::kIo
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_INPUT_STREAM_H_
+29
View File
@@ -0,0 +1,29 @@
#ifndef PLATFORM_API2_LISTENABLE_FUTURE_H_
#define PLATFORM_API2_LISTENABLE_FUTURE_H_
#include <memory>
#include "platform/api2/executor.h"
#include "platform/api2/future.h"
#include "platform/exception.h"
#include "platform/runnable.h"
namespace location {
namespace nearby {
// A Future that accepts completion listeners.
//
// https://guava.dev/releases/20.0/api/docs/com/google/common/util/concurrent/ListenableFuture.html
template <typename T>
class ListenableFuture : public Future<T> {
public:
~ListenableFuture() override = default;
virtual void AddListener(std::unique_ptr<Runnable> runnable,
Executor* executor) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_LISTENABLE_FUTURE_H_
+23
View File
@@ -0,0 +1,23 @@
#ifndef PLATFORM_API2_MULTI_THREAD_EXECUTOR_H_
#define PLATFORM_API2_MULTI_THREAD_EXECUTOR_H_
#include "platform/api2/submittable_executor.h"
namespace location {
namespace nearby {
// An Executor that reuses a fixed number of threads operating off a shared
// unbounded queue.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool-int-
template <typename ConcreteSubmittableExecutor>
class MultiThreadExecutor
: public SubmittableExecutor<ConcreteSubmittableExecutor> {
public:
~MultiThreadExecutor() override {}
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_MULTI_THREAD_EXECUTOR_H_
+22
View File
@@ -0,0 +1,22 @@
#ifndef PLATFORM_API2_MUTEX_H_
#define PLATFORM_API2_MUTEX_H_
namespace location {
namespace nearby {
// A lock is a tool for controlling access to a shared resource by multiple
// threads.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Lock.html
class Mutex {
public:
virtual ~Mutex() {}
virtual void Lock() = 0;
virtual void Unlock() = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_MUTEX_H_
+20
View File
@@ -0,0 +1,20 @@
#ifndef PLATFORM_API2_OUTPUT_FILE_H_
#define PLATFORM_API2_OUTPUT_FILE_H_
#include "platform/api2/output_stream.h"
#include "platform/byte_array.h"
#include "platform/exception.h"
namespace location {
namespace nearby {
// An OutputFile represents a writable file on the system.
class OutputFile : public OutputStream {
public:
~OutputFile() override = default;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_OUTPUT_FILE_H_
+25
View File
@@ -0,0 +1,25 @@
#ifndef PLATFORM_API2_OUTPUT_STREAM_H_
#define PLATFORM_API2_OUTPUT_STREAM_H_
#include "platform/byte_array.h"
#include "platform/exception.h"
namespace location {
namespace nearby {
// An OutputStream represents an output stream of bytes.
//
// https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html
class OutputStream {
public:
virtual ~OutputStream() {}
virtual Exception Write(const ByteArray& data) = 0; // throws Exception::kIo
virtual Exception Flush() = 0; // throws Exception::kIo
virtual Exception Close() = 0; // throws Exception::kIo
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_OUTPUT_STREAM_H_
+29
View File
@@ -0,0 +1,29 @@
#ifndef PLATFORM_API2_SCHEDULED_EXECUTOR_H_
#define PLATFORM_API2_SCHEDULED_EXECUTOR_H_
#include <cstdint>
#include <memory>
#include "platform/api2/executor.h"
#include "platform/cancelable.h"
#include "platform/runnable.h"
#include "absl/time/time.h"
namespace location {
namespace nearby {
// An Executor that can schedule commands to run after a given delay, or to
// execute periodically.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html
class ScheduledExecutor : public Executor {
public:
~ScheduledExecutor() override = default;
virtual std::unique_ptr<Cancelable> Schedule(
std::unique_ptr<Runnable> runnable, absl::Duration duration) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SCHEDULED_EXECUTOR_H_
+60
View File
@@ -0,0 +1,60 @@
#ifndef PLATFORM_API2_SERVER_SYNC_H_
#define PLATFORM_API2_SERVER_SYNC_H_
#include <string>
#include "platform/byte_array.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
// Abstraction that represents a Nearby endpoint exchanging data through
// ServerSync Medium.
class ServerSyncDevice {
public:
virtual ~ServerSyncDevice() = default;
virtual std::string GetName() const = 0;
virtual std::string GetGuid() const = 0;
virtual std::string GetOwnGuid() const = 0;
};
// Container of operations that can be performed over the Chrome Sync medium.
class ServerSyncMedium {
public:
virtual ~ServerSyncMedium() = default;
virtual bool StartAdvertising(absl::string_view service_id,
absl::string_view endpoint_id,
const ByteArray& endpoint_info) = 0;
virtual void StopAdvertising(absl::string_view service_id) = 0;
class DiscoveredDeviceCallback {
public:
virtual ~DiscoveredDeviceCallback() = default;
// Called on a new ServerSyncDevice discovery.
virtual void OnDeviceDiscovered(ServerSyncDevice* device,
absl::string_view service_id,
absl::string_view endpoint_id,
const ByteArray& endpoint_info) = 0;
// Called when ServerSyncDevice is no longer reachable.
virtual void OnDeviceLost(ServerSyncDevice* device,
absl::string_view service_id) = 0;
};
// Returns true once the Chrome Sync scan has been initiated.
virtual bool StartDiscovery(
absl::string_view service_id,
const DiscoveredDeviceCallback& discovered_device_callback) = 0;
// Returns true once Chrome Sync scan for service_id is well and truly
// stopped; after this returns, there must be no more invocations of the
// DiscoveredDeviceCallback passed in to startScanning() for service_id.
virtual void StopDiscovery(absl::string_view service_id) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SERVER_SYNC_H_
+24
View File
@@ -0,0 +1,24 @@
#ifndef PLATFORM_API2_SETTABLE_FUTURE_H_
#define PLATFORM_API2_SETTABLE_FUTURE_H_
#include "platform/api2/listenable_future.h"
namespace location {
namespace nearby {
// A SettableFuture is a type of Future whose result can be set.
//
// https://google.github.io/guava/releases/20.0/api/docs/com/google/common/util/concurrent/SettableFuture.html
template <typename T>
class SettableFuture : public ListenableFuture<T> {
public:
~SettableFuture() override = default;
virtual bool Set(const T& value) = 0;
virtual bool SetException(Exception exception) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SETTABLE_FUTURE_H_
@@ -0,0 +1,23 @@
#ifndef PLATFORM_API2_SINGLE_THREAD_EXECUTOR_H_
#define PLATFORM_API2_SINGLE_THREAD_EXECUTOR_H_
#include "platform/api2/submittable_executor.h"
namespace location {
namespace nearby {
// An Executor that uses a single worker thread operating off an unbounded
// queue.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html#newSingleThreadExecutor--
template <typename ConcreteSubmittableExecutor>
class SingleThreadExecutor
: public SubmittableExecutor<ConcreteSubmittableExecutor> {
public:
~SingleThreadExecutor() override {}
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SINGLE_THREAD_EXECUTOR_H_
+25
View File
@@ -0,0 +1,25 @@
#ifndef PLATFORM_API2_SOCKET_H_
#define PLATFORM_API2_SOCKET_H_
#include "platform/api2/input_stream.h"
#include "platform/api2/output_stream.h"
namespace location {
namespace nearby {
// A socket is an endpoint for communication between two machines.
//
// https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html
class Socket {
public:
virtual ~Socket() {}
virtual InputStream& GetInputStream() = 0;
virtual OutputStream& GetOutputStream() = 0;
virtual void Close() = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SOCKET_H_
+42
View File
@@ -0,0 +1,42 @@
#ifndef PLATFORM_API2_SUBMITTABLE_EXECUTOR_H_
#define PLATFORM_API2_SUBMITTABLE_EXECUTOR_H_
#include <memory>
#include "platform/api2/executor.h"
#include "platform/api2/future.h"
#include "platform/callable.h"
namespace location {
namespace nearby {
// Each per-platform concrete implementation is expected to extend from
// SubmittableExecutor and provide an override of its submit() method.
//
// e.g.
// class XyzSubmittableExecutor
// : public SubmittableExecutor<XyzSubmittableExecutor> {
// public:
// template <typename T>
// std::unique_ptr<Future<T>> submit(std::unique_ptr<Callable<T>> callable) {
// ...
// }
// }
template <typename ConcreteSubmittableExecutor>
class SubmittableExecutor : public Executor {
public:
~SubmittableExecutor() override {}
template <typename T>
std::unique_ptr<Future<T>> Submit(std::unique_ptr<Callable<T>> callable) {
static_assert(
std::is_base_of_v<SubmittableExecutor, ConcreteSubmittableExecutor>,
"Class template type is not derived from SubmittableExecutor");
return static_cast<ConcreteSubmittableExecutor*>(this)->submit(callable);
}
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SUBMITTABLE_EXECUTOR_H_
+22
View File
@@ -0,0 +1,22 @@
#ifndef PLATFORM_API2_SYSTEM_CLOCK_H_
#define PLATFORM_API2_SYSTEM_CLOCK_H_
#include <cstdint>
#include "absl/time/time.h"
namespace location {
namespace nearby {
class SystemClock final {
public:
// Returns the time (in milliseconds) since the system was booted, and
// includes deep sleep. This clock should be guaranteed to be monotonic, and
// should continue to tick even when the CPU is in power saving modes.
static absl::Time ElapsedRealtime();
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_SYSTEM_CLOCK_H_
+22
View File
@@ -0,0 +1,22 @@
#ifndef PLATFORM_API2_THREAD_UTILS_H_
#define PLATFORM_API2_THREAD_UTILS_H_
#include <cstdint>
#include "platform/exception.h"
#include "absl/time/time.h"
namespace location {
namespace nearby {
class ThreadUtils final {
public:
// https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#sleep(long)
// throws Exception::kInterrupted
static Exception Sleep(absl::Duration timeout);
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_THREAD_UTILS_H_
+46
View File
@@ -0,0 +1,46 @@
#ifndef PLATFORM_API2_WEBRTC_H_
#define PLATFORM_API2_WEBRTC_H_
#include <vector>
#include "platform/byte_array.h"
#include "webrtc/files/stable/webrtc/api/peer_connection_interface.h"
namespace location {
namespace nearby {
class WebRtcSignalingMessenger {
public:
virtual ~WebRtcSignalingMessenger() = default;
/** Called whenever we receive an inbox message from tachyon. */
class SignalingMessageListener {
public:
virtual ~SignalingMessageListener() = default;
virtual void OnSignalingMessage(const ByteArray& message) = 0;
};
class IceServersListener {
public:
virtual ~IceServersListener() = default;
virtual void OnIceServersFetched(
std::vector<webrtc::PeerConnectionInterface::IceServer>
ice_servers) = 0;
};
virtual bool RegisterSignaling() = 0;
virtual bool UnregisterSignaling() = 0;
virtual bool SendMessage(std::string_view peer_id,
const ByteArray& message) = 0;
virtual bool StartReceivingMessages(
const SignalingMessageListener& listener) = 0;
virtual void GetIceServers(
const IceServersListener& ice_servers_listener) = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_WEBRTC_H_
+88
View File
@@ -0,0 +1,88 @@
#ifndef PLATFORM_API2_WIFI_H_
#define PLATFORM_API2_WIFI_H_
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
// Possible authentication types for a WiFi network.
enum class WifiAuthType {
// WiFi Authentication type; either none (non-secured a.k.a. open) link, or
// WPA PSK (WiFi Protected Access PreShared Key), or
// see https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access
// WEP (Wired Equivalent Privacy);
// see https://en.wikipedia.org/wiki/Wired_Equivalent_Privacy
kUnknown = 0,
kOpen = 1,
kWpaPsk = 2,
kWep = 3,
};
// Possible statuses of a device's connection to a WiFi network.
enum class WifiConnectionStatus {
kUnknown = 0,
kConnected = 1,
kConnectionFailure = 2,
kAuthFailure = 3,
};
// Represents a WiFi network found during a call to WifiMedium#scan().
class WifiScanResult {
public:
virtual ~WifiScanResult() {}
// Gets the SSID of this WiFi network.
virtual std::string GetSsid() const = 0;
// Gets the signal strength of this WiFi network in dBm.
virtual std::int32_t GetSignalStrengthDbm() const = 0;
// Gets the frequency band of this WiFi network in MHz.
virtual std::int32_t GetFrequencyMhz() const = 0;
// Gets the authentication type of this WiFi network.
virtual WifiAuthType GetAuthType() const = 0;
};
// Container of operations that can be performed over the WiFi medium.
class WifiMedium {
public:
virtual ~WifiMedium() {}
class ScanResultCallback {
public:
virtual ~ScanResultCallback() {}
virtual void OnScanResults(
const std::vector<WifiScanResult>& scan_results) = 0;
};
// Does not take ownership of the passed-in scan_result_callback -- destroying
// that is up to the caller.
virtual bool Scan(const ScanResultCallback& scan_result_callback) = 0;
// If 'password' is an empty string, none has been provided. Returns
// WifiConnectionStatus::CONNECTED on success, or the appropriate failure code
// otherwise.
virtual WifiConnectionStatus ConnectToNetwork(absl::string_view ssid,
absl::string_view password,
WifiAuthType auth_type) = 0;
// Blocks until it's certain of there being a connection to the internet, or
// returns false if it fails to do so.
//
// How this method wants to verify said connection is totally up to it (so it
// can feel free to ping whatever server, download whatever resource, etc.
// that it needs to gain confidence that the internet is reachable hereon in).
virtual bool VerifyInternetConnectivity() = 0;
// Returns the local device's IP address in the IPv4 dotted-quad format.
virtual std::string GetIpAddress() = 0;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_API2_WIFI_H_
+3 -4
View File
@@ -1,6 +1,5 @@
#include "platform/base64_utils.h"
#include "strings/escaping.h"
#include "absl/strings/escaping.h"
namespace location {
@@ -25,7 +24,7 @@ std::string Base64Utils::encode(const ByteArray& bytes) {
return base64_string;
}
std::string Base64Utils::encode(const std::string& input) {
std::string Base64Utils::encode(absl::string_view input) {
std::string base64_string;
absl::WebSafeBase64Escape(input, &base64_string);
@@ -33,7 +32,7 @@ std::string Base64Utils::encode(const std::string& input) {
}
template<>
Ptr<ByteArray> Base64Utils::decode(const std::string& base64_string) {
Ptr<ByteArray> Base64Utils::decode(absl::string_view base64_string) {
std::string decoded_string;
if (!absl::WebSafeBase64Unescape(base64_string, &decoded_string)) {
return Ptr<ByteArray>();
@@ -43,7 +42,7 @@ Ptr<ByteArray> Base64Utils::decode(const std::string& base64_string) {
}
template<>
ByteArray Base64Utils::decode(const std::string& base64_string) {
ByteArray Base64Utils::decode(absl::string_view base64_string) {
std::string decoded_string;
if (!absl::WebSafeBase64Unescape(base64_string, &decoded_string)) {
return ByteArray();
+6 -5
View File
@@ -4,23 +4,24 @@
#include "platform/byte_array.h"
#include "platform/port/string.h"
#include "platform/ptr.h"
#include "absl/strings/string_view.h"
namespace location {
namespace nearby {
class Base64Utils {
public:
static std::string encode(const std::string& input);
static std::string encode(absl::string_view input);
static std::string encode(const ByteArray& bytes);
static std::string encode(ConstPtr<ByteArray> bytes);
template <typename T>
static T decode(const std::string& base64_string);
static T decode(absl::string_view base64_string);
template <>
Ptr<ByteArray> decode(const std::string& base64_string);
Ptr<ByteArray> decode(absl::string_view base64_string);
template <>
ByteArray decode(const std::string& base64_string);
static Ptr<ByteArray> decode(const std::string& base64_string) {
ByteArray decode(absl::string_view base64_string);
static Ptr<ByteArray> decode(absl::string_view base64_string) {
return decode<Ptr<ByteArray>>(base64_string);
}
};
-30
View File
@@ -1,30 +0,0 @@
#include "platform/exception.h"
namespace location {
namespace nearby {
template <typename T>
ExceptionOr<T>::ExceptionOr(T result)
: result_(result), exception_(Exception::NONE) {}
template <typename T>
ExceptionOr<T>::ExceptionOr(Exception::Value exception)
: result_(), exception_(exception) {}
template <typename T>
bool ExceptionOr<T>::ok() const {
return Exception::NONE == exception_;
}
template <typename T>
T ExceptionOr<T>::result() const {
return result_;
}
template <typename T>
Exception::Value ExceptionOr<T>::exception() const {
return exception_;
}
} // namespace nearby
} // namespace location
+33 -11
View File
@@ -1,21 +1,34 @@
#ifndef PLATFORM_EXCEPTION_H_
#define PLATFORM_EXCEPTION_H_
#include <utility>
namespace location {
namespace nearby {
struct Exception {
enum Value {
enum Value : int {
NONE,
IO,
INTERRUPTED,
INVALID_PROTOCOL_BUFFER,
EXECUTION,
// New code should use the kConstants.
// Old CONSTANTS are deprecated, and should not be used.
kFailed = -1, // Initial value of Exception; any unknown error.
kSuccess = NONE, // No exception.
kIo = IO, // IO Error happened.
kInterrupted = INTERRUPTED, // Operation was interrupted.
kInvalidProtocolBuffer = INVALID_PROTOCOL_BUFFER, // Couldn't parse.
kExecution = EXECUTION, // Couldn't execute.
kTimeout, // Operarion did not finish within specified time.
};
Value value {kFailed};
};
// ExceptionOr models the concept of the return value of a function that might
// throw an exception.
// ExceptionOr provides experience similar to StatusOr<T> used in
// Google Cloud API, see:
// https://googleapis.github.io/google-cloud-cpp/0.7.0/common/status__or_8h_source.html
//
// If ok() returns true, result() is a usable return value. Otherwise,
// exception() explains why such a value is not present.
@@ -36,22 +49,31 @@ struct Exception {
template <typename T>
class ExceptionOr {
public:
explicit ExceptionOr(T result);
explicit ExceptionOr(Exception::Value exception);
ExceptionOr() = default;
ExceptionOr(T&& result) : result_{std::move(result)}, // NOLINT
exception_{Exception::kSuccess} {}
ExceptionOr(const T& result) : result_{result}, // NOLINT
exception_{Exception::kSuccess} {}
ExceptionOr(Exception::Value exception) : exception_{exception} {} // NOLINT
bool ok() const;
bool ok() const { return exception_.value == Exception::kSuccess; }
T result() const;
Exception::Value exception() const;
T& result() & { return result_; }
const T& result() const & { return result_; }
T&& result() && { return std::move(result_); }
const T&& result() const && { return std::move(result_); }
Exception::Value exception() const { return exception_.value; }
T GetResult() const;
Exception GetException() const;
private:
T result_;
Exception::Value exception_;
Exception exception_ {Exception::kFailed};
};
} // namespace nearby
} // namespace location
#include "platform/exception.cc"
#endif // PLATFORM_EXCEPTION_H_
+76
View File
@@ -0,0 +1,76 @@
#include "platform/exception.h"
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace location::nearby {
TEST(ExceptionOr, Result_Copy_NonConst) {
ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
EXPECT_FALSE(exception_or_vector.result().empty());
// Expect a copy when not explicitly moving the result.
std::vector<int> copy = exception_or_vector.result();
EXPECT_FALSE(copy.empty());
EXPECT_FALSE(exception_or_vector.result().empty());
// Modifying |exception_or_vector| should not affect the copy.
exception_or_vector.result().clear();
EXPECT_FALSE(copy.empty());
}
TEST(ExceptionOr, Result_Copy_Const) {
const ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
EXPECT_FALSE(exception_or_vector.result().empty());
// Expect a copy when not explicitly moving the result.
std::vector<int> copy = exception_or_vector.result();
EXPECT_FALSE(copy.empty());
EXPECT_FALSE(exception_or_vector.result().empty());
}
TEST(ExceptionOr, Result_Reference_NonConst) {
ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
EXPECT_FALSE(exception_or_vector.result().empty());
// Getting a reference should not modify the source.
std::vector<int>& reference = exception_or_vector.result();
EXPECT_FALSE(reference.empty());
EXPECT_FALSE(exception_or_vector.result().empty());
// Modifying |exception_or_vector| should reflect in the reference.
exception_or_vector.result().clear();
EXPECT_TRUE(reference.empty());
}
TEST(ExceptionOr, Result_Reference_Const) {
const ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
EXPECT_FALSE(exception_or_vector.result().empty());
// Getting a reference should not modify the source.
const std::vector<int>& reference = exception_or_vector.result();
EXPECT_FALSE(reference.empty());
EXPECT_FALSE(exception_or_vector.result().empty());
}
TEST(ExceptionOr, Result_Move_NonConst) {
ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
ASSERT_FALSE(exception_or_vector.result().empty());
// Moving the result should clear the source.
std::vector<int> moved = std::move(exception_or_vector).result();
ASSERT_FALSE(moved.empty());
}
TEST(ExceptionOr, Result_Move_Const) {
const ExceptionOr<std::vector<int>> exception_or_vector({1, 2, 3});
ASSERT_FALSE(exception_or_vector.result().empty());
// Moving const rvalue reference will result in a copy.
std::vector<int> moved = std::move(exception_or_vector).result();
ASSERT_FALSE(moved.empty());
}
} // namespace location::nearby
+3 -3
View File
@@ -1,8 +1,6 @@
cc_library(
name = "default",
srcs = [
"default_condition_variable.cc",
"default_lock.cc",
"default_platform.cc",
],
hdrs = [
@@ -15,6 +13,8 @@ cc_library(
"//core:__subpackages__",
],
deps = [
":condition_variable",
":lock",
"//platform:types",
"//platform/api",
],
@@ -38,7 +38,7 @@ cc_library(
"//platform:__subpackages__",
],
deps = [
":default",
":lock",
"//platform:types",
"//platform/api:condition_variable",
],
-13
View File
@@ -1,13 +0,0 @@
#include "platform/ptr.h"
namespace location {
namespace nearby {
namespace ptr_impl {
const std::int32_t RefCount::kInitialCount = 0;
} // namespace ptr_impl
} // namespace nearby
} // namespace location
+64 -194
View File
@@ -4,78 +4,15 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <type_traits>
#include "platform/impl/default/default_lock.h"
#include "platform/logging.h"
#include "platform/port/down_cast.h"
namespace location {
namespace nearby {
namespace ptr_impl {
class RefCount {
public:
RefCount() : lock_(), count_(kInitialCount) {}
// Returns false if this operation doesn't make conceptual sense any more
// (for example, if it leads to bringing count_ back from the dead).
bool increment() {
bool result;
lock_.lock();
{
// Avoid coming back from the dead.
if (count_ < kInitialCount) {
result = false;
} else {
count_++;
result = true;
}
}
lock_.unlock();
return result;
}
// Returns true if after this operation, count_ is 0.
bool decrement() {
bool result;
lock_.lock();
{
// It's alright for count_ to go negative because it will only be exactly
// 0 once (since increment() makes sure that once you go negative, you
// can't come back from the dead).
count_--;
result = (count_ == 0);
}
lock_.unlock();
return result;
}
private:
static const std::int32_t kInitialCount;
DefaultLock lock_;
std::int32_t count_;
};
} // namespace ptr_impl
template <typename T>
class ObjectDestroyer {
public:
static void destroy(T* t) { delete t; }
};
template <typename T>
class ArrayDestroyer {
public:
static void destroy(T* t) { delete[] t; }
};
// Forward declarations to make it possible for Ptr (a class template) to
// declare ConstifyPtr, DowncastPtr, and DowncastConstPtr (function templates)
// as friends.
@@ -85,7 +22,7 @@ class ArrayDestroyer {
// Ptr (which is what one might reasonably expect).
//
// See https://isocpp.org/wiki/faq/templates#template-friends for more.
template <typename T, template <typename> class Destroyer = ObjectDestroyer>
template <typename T>
class Ptr;
template <typename T>
class ConstPtr;
@@ -96,128 +33,74 @@ Ptr<ChildT> DowncastPtr(Ptr<BaseT> base_ptr);
template <typename ChildT, typename BaseT>
ConstPtr<ChildT> DowncastConstPtr(ConstPtr<BaseT> base_ptr);
// A layer of indirection over a raw pointer, to buy flexibility in the
// future to use, for instance:
//
// a) the in-built shared_ptr in modern implementations of C++,
// b) a custom reference-counting mechanism, etc.
//
// , all without having to touch every line of our codebase that uses
// pointers.
//
// Destroyer defines how the owned pointee should be destroyed, and is
// expected to be a class template that provides at least a destroy()
// method, like so:
//
// template <typename T>
// class MyDestroyer {
// public:
// static void destroy(T* t);
// };
//
// It defaults to ObjectDestroyer<T>.
template <typename T, template <typename> class Destroyer>
// A layer of indirection over a raw pointer.
// It is being deprecated in favor of standard c++ smart pointers.
// For transion period, Ptr<T> will behave similar to shared_ptr<T>.
// New code should use shrared_ptr<T> or unique_ptr<T> and not Ptr<T>.
template <typename T>
class Ptr {
public:
// Provide an alias for use as a dependent name.
typedef T PointeeType;
Ptr() : pointee_(nullptr), ref_count_(nullptr) {}
explicit Ptr(T* pointee, bool is_ref_counted = false,
ptr_impl::RefCount* ref_count = nullptr)
: pointee_(pointee),
ref_count_(
is_ref_counted
? (ref_count != nullptr ? ref_count : new ptr_impl::RefCount())
: nullptr) {
init();
}
Ptr(const Ptr& that) : pointee_(that.pointee_), ref_count_(that.ref_count_) {
init();
}
Ptr() = default;
explicit Ptr(T* pointee) : ptr_(pointee) {}
Ptr(const Ptr& that) = default;
Ptr& operator=(const Ptr& other) {
if (pointee_ != other.pointee_) {
// If we're not currently ref-counted, then an assignment shouldn't lead
// to any destruction of our past state -- that's the responsibility of
// whichever instance of Ptr believes it owns pointee_.
destroy(false);
Ptr(std::shared_ptr<T> ptr) : ptr_(ptr) {} // NOLINT
pointee_ = other.pointee_;
ref_count_ = other.ref_count_;
init();
}
template <typename T2>
Ptr<T>& operator=(T2* ptr) {
Ptr<T> tmp(ptr);
this->ptr_.swap(tmp);
return *this;
}
Ptr& operator=(const Ptr& other) = default;
// Conversion to Ptr<T2>, where T is trivially convertible to T2. E.g.
// conversion from derived to base class.
template <typename T2>
operator Ptr<T2>() {
return Ptr<T2>(pointee_, isRefCounted(), ref_count_);
operator Ptr<T2>() { // NOLINT
return Ptr<T2>(std::static_pointer_cast<T2>(this->ptr_));
}
operator Ptr() { // NOLINT
return Ptr(*this);
}
~Ptr() {
if (isRefCounted()) {
destroy();
} else {
// Left empty on purpose.
}
}
explicit operator std::shared_ptr<T>() { return this->ptr_; }
~Ptr() = default;
bool operator==(const Ptr& other) const {
assert(!(this->isNull()));
assert(!(other.isNull()));
return ((*(this->pointee_) == *(other.pointee_)) &&
(this->isRefCounted() == other.isRefCounted()));
return *(this->ptr_) == *(other.ptr_);
}
bool operator!=(const Ptr& other) const { return !(*this == other); }
bool operator<(const Ptr& other) const {
assert(!(this->isNull()));
assert(!(other.isNull()));
return *(this->pointee_) < *(other.pointee_);
return *(this->ptr_) < *(other.ptr_);
}
// Calls Destroyer::destroy() to perform deallocation of pointee_.
void destroy(bool should_destroy_if_not_ref_counted = true) {
bool need_to_destroy = isRefCounted() ? ref_count_->decrement()
: should_destroy_if_not_ref_counted;
if (need_to_destroy) {
delete ref_count_;
Destroyer<T>::destroy(pointee_);
}
// No-op: refcounted objects will be destroyed correctly
ABSL_DEPRECATED("Use c++ smart pointers directly instead of Ptr<T>")
void destroy(bool = true) {}
ref_count_ = NULL; // NOLINT
pointee_ = NULL; // NOLINT
}
// No-op: refcounted objects will be destroyed correctly
ABSL_DEPRECATED("Use c++ smart pointers directly instead of Ptr<T>")
void clear() {}
// Use this function only when the ownership is held by someone else, and this
// Ptr object has no responsibility to destroy it.
void clear() {
if (isRefCounted()) {
NEARBY_LOG(FATAL, "Attempting to invoke clear() on a RefCounted Ptr.");
}
T& operator*() const { return *ptr_; }
pointee_ = NULL; // NOLINT
}
T* operator->() const { return ptr_.get(); }
T* get() { return ptr_.get(); }
void reset() { return ptr_.reset(); }
T& operator*() const {
assert(pointee_ != NULL); // NOLINT
return *pointee_;
}
ABSL_DEPRECATED("Use c++ smart pointers directly instead of Ptr<T>")
bool isNull() const { return !this->ptr_; }
T* operator->() const {
assert(pointee_ != NULL); // NOLINT
return pointee_;
}
bool isNull() const { return pointee_ == nullptr; }
bool isRefCounted() const { return ref_count_ != nullptr; }
// used by pipe.cc; introduced by cr/295271652
ABSL_DEPRECATED("Use c++ smart pointers directly instead of Ptr<T>")
bool isRefCounted() const { return true; }
private:
template <typename PointeeT>
@@ -227,16 +110,7 @@ class Ptr {
template <typename ChildT, typename BaseT>
friend ConstPtr<ChildT> DowncastConstPtr(ConstPtr<BaseT> base_ptr);
void init() {
if (isRefCounted()) {
if (!ref_count_->increment()) {
NEARBY_LOG(FATAL, "Failed to increment RefCount.");
}
}
}
T* pointee_;
ptr_impl::RefCount* ref_count_;
std::shared_ptr<T> ptr_;
};
// Convenience wrapper for a read-only version of Ptr (in which the pointee
@@ -259,9 +133,9 @@ template <typename T>
class ConstPtr : public Ptr<T const> {
public:
ConstPtr() {}
explicit ConstPtr(T* pointee, bool is_ref_counted = false,
ptr_impl::RefCount* ref_count = nullptr)
: Ptr<T const>(pointee, is_ref_counted, ref_count) {}
explicit ConstPtr(const T* pointee) : Ptr<T const>(pointee) {}
explicit ConstPtr(T* pointee) : Ptr<T const>(pointee) {}
explicit ConstPtr(Ptr<T> ptr) : Ptr<T const>(ptr) {}
};
// RAII wrapper over Ptr and ConstPtr (hereon referred to by the PtrType
@@ -291,33 +165,29 @@ class ScopedPtr {
public:
explicit ScopedPtr(typename PtrType::PointeeType* pointee) : ptr_(pointee) {}
explicit ScopedPtr(PtrType ptr) : ptr_(ptr) {}
~ScopedPtr() { ptr_.destroy(); }
ScopedPtr(const ScopedPtr&) = delete;
~ScopedPtr() = default;
ScopedPtr& operator=(const ScopedPtr&) = delete;
// Shadow methods for the underlying Ptr.
typename PtrType::PointeeType& operator*() const { return ptr_.operator*(); }
typename PtrType::PointeeType& operator*() const { return *ptr_; }
typename PtrType::PointeeType* operator->() const {
return ptr_.operator->();
}
bool isNull() const { return ptr_.isNull(); }
// Accessor for the underlying Ptr.
PtrType get() const { return ptr_; }
PtrType get() const { return this->ptr_; }
// Releases the underlying Ptr from the clutches of this ScopedPtr,
// effectively resetting this ScopedPtr (and making its destructor be a no-op)
// -- useful for transfer of ownership from one ScopedPtr to another across
// scopes.
// Does nothing;
// this is to avoid unintended destruction of a managed pointer.
// TODO(b/149938110): remove this completely.
PtrType release() {
PtrType released = ptr_;
ptr_ = PtrType();
return released;
return ptr_;
}
private:
// Disallow copy and assignment.
ScopedPtr(const ScopedPtr&);
ScopedPtr& operator=(const ScopedPtr&);
PtrType ptr_;
};
@@ -358,19 +228,19 @@ ConstPtr<T> MakeConstPtr(T* raw_ptr) {
// reference).
template <typename T>
Ptr<T> MakeRefCountedPtr(T* raw_ptr) {
return Ptr<T>(raw_ptr, true);
return Ptr<T>(raw_ptr);
}
// ConstPtr counterpart to MakeRefCountedPtr().
template <typename T>
ConstPtr<T> MakeRefCountedConstPtr(T* raw_ptr) {
return ConstPtr<T>(raw_ptr, true);
return ConstPtr<T>(raw_ptr);
}
// Use this function to convert a Ptr object to a ConstPtr object.
template <typename T>
ConstPtr<T> ConstifyPtr(Ptr<T> ptr) {
return ConstPtr<T>(ptr.pointee_, ptr.isRefCounted(), ptr.ref_count_);
return ConstPtr<T>(ptr);
}
// Use this function to downcast from a Ptr<BaseT> to a Ptr<ChildT>.
@@ -382,16 +252,16 @@ ConstPtr<T> ConstifyPtr(Ptr<T> ptr) {
// Ptr<MyChild> my_child_ptr = DowncastPtr<MyChild>(my_base_ptr);
template <typename ChildT, typename BaseT>
Ptr<ChildT> DowncastPtr(Ptr<BaseT> base_ptr) {
return Ptr<ChildT>(DOWN_CAST<ChildT*>(base_ptr.pointee_),
base_ptr.isRefCounted(), base_ptr.ref_count_);
static_assert(std::is_base_of_v<BaseT, ChildT>);
return Ptr<ChildT>(std::static_pointer_cast<ChildT>(base_ptr.ptr_));
}
// ConstPtr counterpart to DowncastPtr().
template <typename ChildT, typename BaseT>
ConstPtr<ChildT> DowncastConstPtr(ConstPtr<BaseT> base_ptr) {
static_assert(std::is_base_of_v<BaseT, ChildT>);
return ConstPtr<ChildT>(
const_cast<ChildT*>(DOWN_CAST<const ChildT*>(base_ptr.pointee_)),
base_ptr.isRefCounted(), base_ptr.ref_count_);
std::static_pointer_cast<const ChildT>(base_ptr.ptr_));
}
} // namespace nearby
+19 -128
View File
@@ -22,15 +22,6 @@ TEST(PtrTest, RefCountedPtr_MultipleReferences) {
SUCCEED();
}
TEST(PtrTest, RefCountedPtr_IsRefCounted_Works) {
Ptr<int> ref_counted = MakeRefCountedPtr(new int(1234));
Ptr<int> manually_counted = MakePtr(new int(1234));
ScopedPtr<Ptr<int> > scoped_manually_counted(manually_counted);
ASSERT_TRUE(ref_counted.isRefCounted());
ASSERT_FALSE(manually_counted.isRefCounted());
}
TEST(PtrTest, RefCountedPtr_MultipleReferencesWithScoped) {
Ptr<int> ref_counted = MakeRefCountedPtr(new int(1234));
ScopedPtr<Ptr<int> > scoped_ref_counted_1(ref_counted);
@@ -51,60 +42,6 @@ TEST(PtrTest, AssignmentOperator_RefCountedToRefCounted) {
ASSERT_EQ(1234, *ref_counted_2);
}
TEST(PtrTest, AssignmentOperator_ManuallyCountedToManuallyCounted) {
Ptr<int> manually_counted_1 = MakePtr(new int(1234));
Ptr<int> manually_counted_2 = MakePtr(new int(5678));
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted_1(manually_counted_1);
ScopedPtr<Ptr<int> > scoped_manually_counted_2(manually_counted_2);
manually_counted_2 = manually_counted_1;
ASSERT_EQ(1234, *manually_counted_1);
ASSERT_EQ(1234, *manually_counted_2);
ASSERT_EQ(1234, *scoped_manually_counted_1);
ASSERT_EQ(5678, *scoped_manually_counted_2);
}
TEST(PtrTest, AssignmentOperator_RefCountedToManuallyCounted) {
Ptr<int> ref_counted = MakeRefCountedPtr(new int(1234));
Ptr<int> manually_counted = MakePtr(new int(5678));
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted(manually_counted);
manually_counted = ref_counted;
ASSERT_EQ(1234, *ref_counted);
ASSERT_EQ(1234, *manually_counted);
ASSERT_EQ(5678, *scoped_manually_counted);
}
TEST(PtrTest, AssignmentOperator_ManuallyCountedToRefCounted) {
Ptr<int> manually_counted = MakePtr(new int(1234));
Ptr<int> ref_counted = MakeRefCountedPtr(new int(5678));
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted(manually_counted);
ref_counted = manually_counted;
ASSERT_EQ(1234, *ref_counted);
ASSERT_EQ(1234, *manually_counted);
ASSERT_EQ(1234, *scoped_manually_counted);
}
TEST(PtrTest, AssignmentOperator_SelfAssignment_ManuallyCounted) {
Ptr<int> manually_counted_1 = MakePtr(new int(1234));
Ptr<int> manually_counted_2(manually_counted_1);
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted_1(manually_counted_1);
manually_counted_1 = manually_counted_2;
ASSERT_EQ(1234, *manually_counted_1);
ASSERT_EQ(1234, *manually_counted_2);
ASSERT_EQ(1234, *scoped_manually_counted_1);
}
TEST(PtrTest, AssignmentOperator_SelfAssignment_RefCounted) {
Ptr<int> ref_counted_1 = MakeRefCountedPtr(new int(1234));
Ptr<int> ref_counted_2(ref_counted_1);
@@ -115,19 +52,6 @@ TEST(PtrTest, AssignmentOperator_SelfAssignment_RefCounted) {
ASSERT_EQ(1234, *ref_counted_2);
}
TEST(PtrTest, EqualityOperator_ManuallyCounted) {
Ptr<int> manually_counted_1 = MakePtr(new int(1234));
Ptr<int> manually_counted_2(manually_counted_1);
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted_1(manually_counted_1);
ASSERT_TRUE(manually_counted_1 == manually_counted_2);
manually_counted_1 = manually_counted_2;
ASSERT_TRUE(manually_counted_1 == manually_counted_2);
}
TEST(PtrTest, EqualityOperator_RefCounted) {
Ptr<int> ref_counted_1 = MakeRefCountedPtr(new int(1234));
Ptr<int> ref_counted_2(ref_counted_1);
@@ -139,16 +63,6 @@ TEST(PtrTest, EqualityOperator_RefCounted) {
ASSERT_TRUE(ref_counted_1 == ref_counted_2);
}
TEST(PtrTest, EqualityOperator_ManuallyAndRefCounted) {
int* raw = new int(1234);
Ptr<int> manually_counted = MakePtr(raw);
Ptr<int> ref_counted = MakeRefCountedPtr(raw);
// No need for a ScopedPtr for manually_counted here because we know that
// ref_counted will take care of deallocating 'raw'.
ASSERT_FALSE(manually_counted == ref_counted);
}
namespace {
class Base {
@@ -171,17 +85,6 @@ class Derived : public Base {
} // namespace
TEST(PtrTest, DerivedToBaseConversion_ManuallyCounted) {
Ptr<Derived> derived = MakePtr(new Derived(1234));
Ptr<Base> base = derived;
// Avoid leaks.
ScopedPtr<Ptr<Derived> > scoped_derived(derived);
ASSERT_EQ(1234, base->getInt());
ASSERT_EQ(1234, derived->getInt());
ASSERT_EQ(1234, scoped_derived->getInt());
}
TEST(PtrTest, DerivedToBaseConversion_RefCounted) {
Ptr<Derived> derived = MakeRefCountedPtr(new Derived(1234));
Ptr<Base> base = derived;
@@ -193,17 +96,18 @@ TEST(PtrTest, DerivedToBaseConversion_RefCounted) {
ASSERT_EQ(1234, base->getInt());
}
TEST(PtrTest, ScopedPtr_Release_ManuallyCounted) {
Ptr<int> manually_counted_1 = MakePtr(new int(1234));
ScopedPtr<Ptr<int> > scoped_manually_counted_1(manually_counted_1);
TEST(PtrTest, DistinctValuesAreNotEqual) {
Ptr<int> value1 = MakePtr(new int(5));
Ptr<int> value2 = MakePtr(new int(6));
Ptr<int> manually_counted_2 = scoped_manually_counted_1.release();
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted_2(manually_counted_2);
ASSERT_NE(value1, value2);
}
ASSERT_TRUE(scoped_manually_counted_1.isNull());
ASSERT_EQ(1234, *manually_counted_2);
ASSERT_EQ(1234, *scoped_manually_counted_2);
TEST(PtrTest, SameValuesAreEqual) {
Ptr<int> value1 = MakePtr(new int(5));
Ptr<int> value2 = MakePtr(new int(5));
ASSERT_EQ(value1, value2);
}
TEST(PtrTest, ScopedPtr_Release_RefCounted) {
@@ -212,20 +116,20 @@ TEST(PtrTest, ScopedPtr_Release_RefCounted) {
Ptr<int> ref_counted_2 = scoped_ref_counted_1.release();
ASSERT_TRUE(scoped_ref_counted_1.isNull());
ASSERT_EQ(*scoped_ref_counted_1, *ref_counted_2);
ASSERT_EQ(1234, *ref_counted_2);
}
TEST(PtrTest, ConstifyPtr_ManuallyCounted) {
Ptr<int> manually_counted = MakePtr(new int(1234));
// Avoid leaks.
ScopedPtr<Ptr<int> > scoped_manually_counted(manually_counted);
TEST(PtrTest, ScopedPtr_Release_RefCounted_Stay_Valid) {
Ptr<int> ref_counted_1 = MakeRefCountedPtr(new int(1234));
Ptr<int> ref_counted_2 = ref_counted_1;
ScopedPtr<Ptr<int> > scoped_ref_counted_1(ref_counted_1);
ConstPtr<int> const_manually_counted = ConstifyPtr(manually_counted);
Ptr<int> ref_counted_3 = scoped_ref_counted_1.release();
ASSERT_EQ(1234, *const_manually_counted);
ASSERT_EQ(1234, *manually_counted);
ASSERT_EQ(1234, *scoped_manually_counted);
ASSERT_EQ(*scoped_ref_counted_1, *ref_counted_3);
ASSERT_EQ(1234, *ref_counted_2);
ASSERT_EQ(1234, *ref_counted_3);
}
TEST(PtrTest, ConstifyPtr_RefCounted) {
@@ -240,19 +144,6 @@ TEST(PtrTest, ConstifyPtr_RefCounted) {
ASSERT_EQ(1234, *const_ref_counted);
}
TEST(PtrTest, DowncastPtr_ManuallyCounted) {
Ptr<Derived> derived = MakePtr(new Derived(1234));
Ptr<Base> base = derived;
// Avoid leaks.
ScopedPtr<Ptr<Derived> > scoped_derived(derived);
Ptr<Derived> derived_from_downcast = DowncastPtr<Derived>(base);
ASSERT_EQ(1234, base->getInt());
ASSERT_EQ(1234, derived->getInt());
ASSERT_EQ(1234, derived_from_downcast->getInt());
}
TEST(PtrTest, DowncastPtr_RefCounted) {
Ptr<Derived> derived = MakeRefCountedPtr(new Derived(1234));
Ptr<Base> base = derived;