mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Define BluetoothPairing API for Nearby Platform Library and add implementation on Windows platform
PiperOrigin-RevId: 528510444
This commit is contained in:
committed by
Copybara-Service
parent
46e4b3eca7
commit
e46bfb52d0
@@ -16,7 +16,9 @@
|
||||
#define PLATFORM_PUBLIC_BLUETOOTH_CLASSIC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
@@ -126,6 +128,36 @@ class BluetoothServerSocket final {
|
||||
std::shared_ptr<api::BluetoothServerSocket> impl_;
|
||||
};
|
||||
|
||||
// Opaque wrapper for a BluetoothPairing.
|
||||
class BluetoothPairing final {
|
||||
public:
|
||||
explicit BluetoothPairing(
|
||||
std::unique_ptr<api::BluetoothPairing> bluetooth_pairing)
|
||||
: impl_(std::move(bluetooth_pairing)) {}
|
||||
|
||||
bool InitiatePairing(api::BluetoothPairingCallback pairing_cb) {
|
||||
return impl_->InitiatePairing(std::move(pairing_cb));
|
||||
}
|
||||
|
||||
bool FinishPairing(std::optional<absl::string_view> pin_code) {
|
||||
return impl_->FinishPairing(pin_code);
|
||||
}
|
||||
|
||||
bool CancelPairing() { return impl_->CancelPairing(); }
|
||||
|
||||
bool Unpair() { return impl_->Unpair(); }
|
||||
|
||||
bool IsPaired() { return impl_->IsPaired(); }
|
||||
|
||||
// Returns reference to platform implementation.
|
||||
// This is used to communicate with platform code, and for debugging
|
||||
// purposes.
|
||||
api::BluetoothPairing* GetImpl() { return impl_.get(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<api::BluetoothPairing> impl_;
|
||||
};
|
||||
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium final
|
||||
@@ -147,6 +179,7 @@ class BluetoothClassicMedium final
|
||||
absl::AnyInvocable<void(BluetoothDevice& device)> device_lost_cb =
|
||||
DefaultCallback<BluetoothDevice&>();
|
||||
};
|
||||
|
||||
struct DeviceDiscoveryInfo {
|
||||
BluetoothDevice device;
|
||||
};
|
||||
@@ -239,6 +272,15 @@ class BluetoothClassicMedium final
|
||||
impl_->ListenForService(service_name, service_uuid));
|
||||
}
|
||||
|
||||
// Return a Bluetooth pairing instance to handle the pairing process with the
|
||||
// remote device.
|
||||
std::unique_ptr<BluetoothPairing> CreatePairing(
|
||||
BluetoothDevice& remote_device) {
|
||||
std::unique_ptr<api::BluetoothPairing> bluetooth_pairing =
|
||||
impl_->CreatePairing(remote_device.GetImpl());
|
||||
return std::make_unique<BluetoothPairing>(std::move(bluetooth_pairing));
|
||||
}
|
||||
|
||||
bool IsValid() const { return impl_ != nullptr; }
|
||||
|
||||
api::BluetoothClassicMedium& GetImpl() { return *impl_; }
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#define PLATFORM_API_BLUETOOTH_CLASSIC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/exception.h"
|
||||
@@ -89,6 +92,105 @@ class BluetoothServerSocket {
|
||||
virtual Exception Close() = 0;
|
||||
};
|
||||
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/PairingParams
|
||||
//
|
||||
// Encapsulates the data for a particular pairing attempt.
|
||||
// The caller can use it to determine the pairing approach and choose a suitable
|
||||
// way to obtain user consent to conclude the pairing process.
|
||||
struct PairingParams {
|
||||
// Pairing type for this pairing attempt.
|
||||
// The Pairing type is based on the User Interface capabilities of both
|
||||
// the pairing devices, and determines the process of pairing.
|
||||
// `kConstent`: the user is expected to consent to the pairing process.
|
||||
// `kDisplayPasskey`: the user is notified of a pairing passkey.
|
||||
// `kDisplayPin`: same as kDisplayPasskey, but different pairing key format.
|
||||
// `kConfirmPasskey`: the user must confirm pairing after verifying a passkey.
|
||||
// `kRequestPin`: the user is supposed to enter a pin to confirm pairing.
|
||||
enum class PairingType {
|
||||
kUnknown = 0,
|
||||
kConsent = 1,
|
||||
kDisplayPasskey = 2,
|
||||
kDisplayPin = 3,
|
||||
kConfirmPasskey = 4,
|
||||
kRequestPin = 5,
|
||||
kLast,
|
||||
};
|
||||
PairingType pairing_type;
|
||||
|
||||
// Pairing pin to notify the user for the pairing process.
|
||||
// If not relevant to the current pairing process, it's empty.
|
||||
std::string passkey;
|
||||
};
|
||||
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothPairingCallback
|
||||
//
|
||||
// This callback is invoked during the Bluetooth pairing process and
|
||||
// contains all the relevant pairing information required for pairing.
|
||||
struct BluetoothPairingCallback {
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothPairingCallback.PairingError
|
||||
enum class PairingError {
|
||||
kUnknown = 0,
|
||||
kAuthCanceled = 1, /* failed because we canceled the pairing process. */
|
||||
kAuthFailed = 2, /* failed with pins did not match, or no response. */
|
||||
kAuthRejected = 3, /* failed with the remote device rejected pairing. */
|
||||
kAuthTimeout = 4, /* failed with authentication timeout. */
|
||||
kFailed = 5, /* failed with no explicit reason. */
|
||||
kRepeatedAttempts = 6, /* failed with many repeated attempts. */
|
||||
kLast,
|
||||
};
|
||||
|
||||
// Invoked when successfully paired with a device.
|
||||
absl::AnyInvocable<void()> on_paired_cb = DefaultCallback<>();
|
||||
|
||||
// Invoked when pairing with a device is canceled or fails.
|
||||
absl::AnyInvocable<void(BluetoothPairingCallback::PairingError error)>
|
||||
on_pairing_error_cb =
|
||||
DefaultCallback<BluetoothPairingCallback::PairingError>();
|
||||
|
||||
// Invoked when the pairing process has been initiated with a remote
|
||||
// Bluetooth device.
|
||||
absl::AnyInvocable<void(PairingParams pairingParams)>
|
||||
on_pairing_initiated_cb = DefaultCallback<PairingParams>();
|
||||
};
|
||||
|
||||
// This class is responsible for handling Bluetooth pairing with a remote
|
||||
// BluetoothDevice.
|
||||
// DCHECK_CALLED_ON_VALID_SEQUENCE
|
||||
class BluetoothPairing {
|
||||
public:
|
||||
virtual ~BluetoothPairing() = default;
|
||||
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothConnectionManager#initiatepairing
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothConnectionManager#registerpairingcallback
|
||||
//
|
||||
// Initiate Bluetooth pairing process with a remote device.
|
||||
// Register a BluetoothPairingCallback to listen for Bluetooth pairing events
|
||||
// Such as incoming pairing request, devices paired etc.
|
||||
virtual bool InitiatePairing(BluetoothPairingCallback pairing_cb) = 0;
|
||||
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothConnectionManager#finishpairing
|
||||
//
|
||||
// Invoke this function to finish the pairing process with the remote device.
|
||||
// Should be called only after receiving a callback from onPairingInitiated.
|
||||
// Pin is needed for PairingType::kRequestPin
|
||||
virtual bool FinishPairing(std::optional<absl::string_view> pin_code) = 0;
|
||||
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothConnectionManager#cancelpairing
|
||||
//
|
||||
// Cancel an ongoing pairing process with a remote device.
|
||||
virtual bool CancelPairing() = 0;
|
||||
|
||||
// https://developer.android.com/reference/com/google/android/things/bluetooth/BluetoothConnectionManager#unpair
|
||||
//
|
||||
// Destroys the existing pairing/bond with the remote device.
|
||||
virtual bool Unpair() = 0;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getBondState()
|
||||
//
|
||||
// Get the pairing state of the remote device.
|
||||
virtual bool IsPaired() = 0;
|
||||
};
|
||||
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium {
|
||||
@@ -174,6 +276,14 @@ class BluetoothClassicMedium {
|
||||
virtual std::unique_ptr<BluetoothServerSocket> ListenForService(
|
||||
const std::string& service_name, const std::string& service_uuid) = 0;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createBond()
|
||||
//
|
||||
// Start the bonding (pairing) process with the remote device.
|
||||
// Return a Bluetooth pairing instance to handle the pairing process with the
|
||||
// remote device.
|
||||
virtual std::unique_ptr<BluetoothPairing> CreatePairing(
|
||||
BluetoothDevice& remote_device) = 0;
|
||||
|
||||
virtual BluetoothDevice* GetRemoteDevice(const std::string& mac_address) = 0;
|
||||
|
||||
virtual void AddObserver(Observer* observer) = 0;
|
||||
|
||||
@@ -271,6 +271,12 @@ BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
return socket;
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
|
||||
api::BluetoothDevice& remote_device) {
|
||||
// TODO(b/279964840): Add g3 implementation for BluetoothPairing.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string& mac_address) {
|
||||
auto& env = MediumEnvironment::Instance();
|
||||
|
||||
@@ -233,6 +233,11 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
const std::string& service_name, const std::string& service_uuid) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Return a Bluetooth pairing instance to handle the pairing process with the
|
||||
// remote device.
|
||||
std::unique_ptr<api::BluetoothPairing> CreatePairing(
|
||||
api::BluetoothDevice& remote_device) override;
|
||||
|
||||
api::BluetoothDevice* GetRemoteDevice(
|
||||
const std::string& mac_address) override;
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <codecvt>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -29,10 +30,12 @@
|
||||
#include "internal/platform/cancellation_flag.h"
|
||||
#include "internal/platform/cancellation_flag_listener.h"
|
||||
#include "internal/platform/exception.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_device.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_server_socket.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_socket.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_pairing.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
@@ -45,7 +48,6 @@
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
|
||||
using winrt::Windows::Foundation::IInspectable;
|
||||
using winrt::Windows::Foundation::Collections::IMapView;
|
||||
|
||||
@@ -336,6 +338,37 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothPairing> BluetoothClassicMedium::CreatePairing(
|
||||
api::BluetoothDevice& remote_device) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to createPairing with device: "
|
||||
<< remote_device.GetMacAddress();
|
||||
try {
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice bluetooth_device =
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::
|
||||
FromBluetoothAddressAsync(
|
||||
mac_address_string_to_uint64(remote_device.GetMacAddress()))
|
||||
.get();
|
||||
winrt::Windows::Devices::Enumeration::DeviceInformationCustomPairing
|
||||
custom_pairing =
|
||||
bluetooth_device.DeviceInformation().Pairing().Custom();
|
||||
if (custom_pairing) {
|
||||
return std::make_unique<BluetoothPairing>(bluetooth_device,
|
||||
custom_pairing);
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Failed to get DeviceInformationCustomPairing.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << " : Failed to create pairing. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to create pairing. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::HaveAccess(winrt::hstring device_id) {
|
||||
if (device_id.empty()) {
|
||||
return false;
|
||||
|
||||
@@ -146,6 +146,11 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
api::BluetoothDevice* GetRemoteDevice(
|
||||
const std::string& mac_address) override;
|
||||
|
||||
// Return a Bluetooth pairing instance to handle the pairing process with the
|
||||
// remote device.
|
||||
std::unique_ptr<api::BluetoothPairing> CreatePairing(
|
||||
api::BluetoothDevice& remote_device) override;
|
||||
|
||||
void AddObserver(Observer* observer) override {
|
||||
// TODO(b/269521993): Implement.
|
||||
}
|
||||
|
||||
@@ -14,7 +14,20 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/bluetooth_pairing.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <exception>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/log/check.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/impl/Windows.Devices.Enumeration.0.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "winrt/Windows.Devices.Enumeration.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/base.h"
|
||||
@@ -23,93 +36,294 @@ namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
namespace {
|
||||
using ::winrt::Windows::Devices::Bluetooth::BluetoothDevice;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceInformationCustomPairing;
|
||||
using ::winrt::Windows::Devices::Enumeration::DevicePairingKinds;
|
||||
using ::winrt::Windows::Devices::Enumeration::DevicePairingProtectionLevel;
|
||||
using ::winrt::Windows::Devices::Enumeration::DevicePairingRequestedEventArgs;
|
||||
using ::winrt::Windows::Devices::Enumeration::DevicePairingResult;
|
||||
using ::winrt::Windows::Devices::Enumeration::DevicePairingResultStatus;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceUnpairingResult;
|
||||
using ::winrt::Windows::Devices::Enumeration::DeviceUnpairingResultStatus;
|
||||
using ::winrt::Windows::Foundation::IAsyncOperation;
|
||||
using PairingError = ::nearby::api::BluetoothPairingCallback::PairingError;
|
||||
using PairingType = ::nearby::api::PairingParams::PairingType;
|
||||
} // namespace
|
||||
|
||||
BluetoothPairing::BluetoothPairing(
|
||||
DeviceInformationCustomPairing& custom_pairing)
|
||||
: custom_pairing_(custom_pairing) {}
|
||||
BluetoothDevice bluetooth_device,
|
||||
DeviceInformationCustomPairing custom_pairing)
|
||||
: bluetooth_device_(bluetooth_device), custom_pairing_(custom_pairing) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": BluetoothPairing is created for device.";
|
||||
}
|
||||
|
||||
BluetoothPairing::~BluetoothPairing() = default;
|
||||
|
||||
void BluetoothPairing::StartPairing() {
|
||||
NEARBY_LOGS(VERBOSE) << "Bluetooth_pairing start pairing";
|
||||
pairing_requested_token_ = custom_pairing_.PairingRequested(
|
||||
{this, &BluetoothPairing::OnPairingRequested});
|
||||
IAsyncOperation<DevicePairingResult> pairing_operation =
|
||||
custom_pairing_.PairAsync(DevicePairingKinds::ConfirmOnly |
|
||||
DevicePairingKinds::ProvidePin |
|
||||
DevicePairingKinds::ConfirmPinMatch,
|
||||
DevicePairingProtectionLevel::None);
|
||||
DevicePairingResult pairing_result = pairing_operation.get();
|
||||
if (pairing_result != nullptr) {
|
||||
OnPair(pairing_result);
|
||||
BluetoothPairing::~BluetoothPairing() {
|
||||
if (pairing_requested_token_) {
|
||||
custom_pairing_.PairingRequested(
|
||||
std::exchange(pairing_requested_token_, {}));
|
||||
}
|
||||
CancelPairing();
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": BluetoothPairing is destroyed for device.";
|
||||
}
|
||||
|
||||
bool BluetoothPairing::InitiatePairing(
|
||||
api::BluetoothPairingCallback pairing_cb) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to initiate pairing process.";
|
||||
try {
|
||||
pairing_requested_token_ = custom_pairing_.PairingRequested(
|
||||
{this, &BluetoothPairing::OnPairingRequested});
|
||||
if (!pairing_requested_token_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< " Failed to registered pairing callback.";
|
||||
return false;
|
||||
}
|
||||
pairing_callback_ = std::move(pairing_cb);
|
||||
DevicePairingResult pairing_result =
|
||||
custom_pairing_
|
||||
.PairAsync(DevicePairingKinds::ConfirmOnly |
|
||||
DevicePairingKinds::ProvidePin |
|
||||
DevicePairingKinds::ConfirmPinMatch |
|
||||
DevicePairingKinds::DisplayPin,
|
||||
DevicePairingProtectionLevel::None)
|
||||
.get();
|
||||
OnPair(pairing_result);
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to initiate pairing. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to initiate pairing. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::FinishPairing(
|
||||
std::optional<absl::string_view> pin_code) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Start to finish pairing.";
|
||||
try {
|
||||
if (!pairing_requested_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "No pairing requested.";
|
||||
return false;
|
||||
}
|
||||
if (!pairing_deferral_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "No ongoing pairing process.";
|
||||
return false;
|
||||
}
|
||||
if (expecting_pin_code_) {
|
||||
if (!pin_code.has_value()) {
|
||||
NEARBY_LOGS(INFO) << __func__ << " Failed to get pin code";
|
||||
return false;
|
||||
}
|
||||
expecting_pin_code_ = false;
|
||||
auto pin_hstring = winrt::to_hstring(std::string(pin_code.value()));
|
||||
pairing_requested_.Accept(pin_hstring);
|
||||
} else {
|
||||
pairing_requested_.Accept();
|
||||
}
|
||||
pairing_deferral_.Complete();
|
||||
NEARBY_LOGS(VERBOSE) << "Successfully finished pairing.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to finish pairing. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to finish pairing. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::CancelPairing() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< "Start to cancel ongoing pairing process.";
|
||||
try {
|
||||
if (!pairing_deferral_) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "No ongoing pairing process.";
|
||||
return true;
|
||||
}
|
||||
// There is no way to explicitly cancel an in-progress pairing on Windows as
|
||||
// DevicePairingRequestedEventArgs has no Cancel() method.
|
||||
// Our approach is to complete the deferral, without accepting,
|
||||
// which results in a RejectedByHandler result status.
|
||||
// |was_cancelled_| is set so that OnPair(), which is called when the
|
||||
// deferral is completed, will know that cancellation was the actual result.
|
||||
was_cancelled_ = true;
|
||||
pairing_deferral_.Complete();
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Canceled ongoing pairing process.";
|
||||
return true;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to cancel ongoing pairing "
|
||||
<< "process. exception: " << exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to cancel ongoing pairing process. "
|
||||
<< "WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::Unpair() {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Start to unpair with remote device.";
|
||||
try {
|
||||
if (!IsPaired()) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << " : Remote device Was not paired.";
|
||||
return true;
|
||||
}
|
||||
DeviceUnpairingResult unpairing_result =
|
||||
bluetooth_device_.DeviceInformation().Pairing().UnpairAsync().get();
|
||||
if (unpairing_result.Status() == DeviceUnpairingResultStatus::Unpaired) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << ": Unpaired with remote device.";
|
||||
return true;
|
||||
}
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< ": Failed to unpaired with remote device.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to unpaired with device. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to unpaired with device. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothPairing::IsPaired() {
|
||||
try {
|
||||
bool is_paired = bluetooth_device_.DeviceInformation().Pairing().IsPaired();
|
||||
NEARBY_LOGS(INFO) << __func__ << (is_paired ? "True" : "False");
|
||||
return is_paired;
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get IsPaired. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get IsPaired. WinRT exception: "
|
||||
<< error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BluetoothPairing::OnPairingRequested(
|
||||
DeviceInformationCustomPairing custom_pairing,
|
||||
DevicePairingRequestedEventArgs pairing_requested) {
|
||||
NEARBY_LOGS(INFO) << "BluetoothPairing::OnPairingRequested()";
|
||||
DevicePairingKinds pairing_kind = pairing_requested.PairingKind();
|
||||
switch (pairing_kind) {
|
||||
case DevicePairingKinds::ProvidePin:
|
||||
NEARBY_LOGS(INFO) << "DevicePairingKind: RequestPinCode.";
|
||||
pairing_requested.Accept();
|
||||
return;
|
||||
case DevicePairingKinds::ConfirmOnly:
|
||||
NEARBY_LOGS(INFO) << "DevicePairingKind: ConfirmOnly.";
|
||||
pairing_requested.Accept();
|
||||
break;
|
||||
case DevicePairingKinds::ConfirmPinMatch:
|
||||
NEARBY_LOGS(INFO) << "DevicePairingKind: Confirm Pin Match: "
|
||||
<< pairing_requested.Pin().c_str();
|
||||
pairing_requested.Accept();
|
||||
break;
|
||||
default:
|
||||
NEARBY_LOGS(INFO) << "Unsupported DevicePairingKind = "
|
||||
<< static_cast<int>(pairing_kind);
|
||||
break;
|
||||
NEARBY_LOGS(VERBOSE) << __func__ << "Requested to pair.";
|
||||
try {
|
||||
DevicePairingKinds pairing_kind = pairing_requested.PairingKind();
|
||||
pairing_requested_ = pairing_requested;
|
||||
pairing_deferral_ = pairing_requested.GetDeferral();
|
||||
api::PairingParams params;
|
||||
switch (pairing_kind) {
|
||||
case DevicePairingKinds::ProvidePin:
|
||||
NEARBY_LOGS(INFO) << __func__ << "DevicePairingKind: RequestPinCode.";
|
||||
expecting_pin_code_ = true;
|
||||
params.pairing_type = PairingType::kRequestPin;
|
||||
pairing_callback_.on_pairing_initiated_cb(params);
|
||||
return;
|
||||
case DevicePairingKinds::ConfirmOnly:
|
||||
NEARBY_LOGS(INFO) << __func__ << "DevicePairingKind: ConfirmOnly.";
|
||||
params.pairing_type = PairingType::kConsent;
|
||||
pairing_callback_.on_pairing_initiated_cb(params);
|
||||
return;
|
||||
case DevicePairingKinds::ConfirmPinMatch:
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< "DevicePairingKind: Confirm Pin Match.";
|
||||
params.pairing_type = PairingType::kConfirmPasskey;
|
||||
params.passkey = winrt::to_string(pairing_requested.Pin());
|
||||
pairing_callback_.on_pairing_initiated_cb(params);
|
||||
return;
|
||||
default:
|
||||
params.pairing_type = PairingType::kUnknown;
|
||||
NEARBY_LOGS(INFO) << __func__ << "Unsupported DevicePairingKind:"
|
||||
<< static_cast<int>(pairing_kind);
|
||||
break;
|
||||
}
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to request to pair with device. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to request to pair with device. WinRT exception: "
|
||||
<< error.code() << ": " << winrt::to_string(error.message());
|
||||
}
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kFailed);
|
||||
}
|
||||
|
||||
void BluetoothPairing::OnPair(DevicePairingResult& pairing_result) {
|
||||
DevicePairingResultStatus status = pairing_result.Status();
|
||||
|
||||
switch (status) {
|
||||
case DevicePairingResultStatus::AlreadyPaired:
|
||||
case DevicePairingResultStatus::Paired:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Paired.";
|
||||
return;
|
||||
case DevicePairingResultStatus::PairingCanceled:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Pairing Canceled.";
|
||||
return;
|
||||
case DevicePairingResultStatus::AuthenticationFailure:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Authentication Failure.";
|
||||
return;
|
||||
case DevicePairingResultStatus::ConnectionRejected:
|
||||
case DevicePairingResultStatus::RejectedByHandler:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Authentication Rejected.";
|
||||
return;
|
||||
case DevicePairingResultStatus::AuthenticationTimeout:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Authentication Timeout.";
|
||||
return;
|
||||
case DevicePairingResultStatus::Failed:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Failed.";
|
||||
return;
|
||||
case DevicePairingResultStatus::OperationAlreadyInProgress:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Operatio In Progress.";
|
||||
return;
|
||||
default:
|
||||
NEARBY_LOGS(ERROR) << "Pairing Result Status: Failed.";
|
||||
return;
|
||||
try {
|
||||
DevicePairingResultStatus status = pairing_result.Status();
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< "Pairing Result Status: " << static_cast<int>(status);
|
||||
if (was_cancelled_ &&
|
||||
status == DevicePairingResultStatus::RejectedByHandler) {
|
||||
// See comment in CancelPairing() for explanation of why was_cancelled_
|
||||
// is used.
|
||||
status = DevicePairingResultStatus::PairingCanceled;
|
||||
}
|
||||
switch (status) {
|
||||
case DevicePairingResultStatus::AlreadyPaired:
|
||||
case DevicePairingResultStatus::Paired:
|
||||
NEARBY_LOGS(ERROR) << __func__ << "Pairing Result Status: Paired.";
|
||||
pairing_callback_.on_paired_cb();
|
||||
return;
|
||||
case DevicePairingResultStatus::PairingCanceled:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Pairing Canceled.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthCanceled);
|
||||
return;
|
||||
case DevicePairingResultStatus::AuthenticationFailure:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Failure.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthFailed);
|
||||
return;
|
||||
case DevicePairingResultStatus::ConnectionRejected:
|
||||
case DevicePairingResultStatus::RejectedByHandler:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Rejected.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthRejected);
|
||||
return;
|
||||
case DevicePairingResultStatus::AuthenticationTimeout:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Authentication Timeout.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kAuthTimeout);
|
||||
return;
|
||||
case DevicePairingResultStatus::Failed:
|
||||
NEARBY_LOGS(ERROR) << __func__ << "Pairing Result Status: Failed.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kFailed);
|
||||
return;
|
||||
case DevicePairingResultStatus::OperationAlreadyInProgress:
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< "Pairing Result Status: Operation In Progress.";
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kRepeatedAttempts);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
NEARBY_LOGS(ERROR) << __func__ << "Pairing Result Status: Failed.";
|
||||
} catch (std::exception exception) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get Pairing Result Status. exception: "
|
||||
<< exception.what();
|
||||
} catch (const winrt::hresult_error& error) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get Pairing Result Status."
|
||||
<< " WinRT exception: " << error.code() << ": "
|
||||
<< winrt::to_string(error.message());
|
||||
}
|
||||
pairing_callback_.on_pairing_error_cb(PairingError::kFailed);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -15,27 +15,35 @@
|
||||
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLUETOOTH_PAIRING_H_
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_BLUETOOTH_PAIRING_H_
|
||||
|
||||
#include <guiddef.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "winrt/Windows.Devices.Enumeration.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/base.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
class BluetoothPairing {
|
||||
class BluetoothPairing : public api::BluetoothPairing {
|
||||
public:
|
||||
explicit BluetoothPairing(
|
||||
::winrt::Windows::Devices::Enumeration::DeviceInformationCustomPairing&
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice bluetooth_device,
|
||||
::winrt::Windows::Devices::Enumeration::DeviceInformationCustomPairing
|
||||
custom_pairing);
|
||||
BluetoothPairing(const BluetoothPairing&) = default;
|
||||
BluetoothPairing& operator=(const BluetoothPairing&) = default;
|
||||
~BluetoothPairing() override;
|
||||
|
||||
~BluetoothPairing();
|
||||
|
||||
// Initiates the pairing procedure.
|
||||
void StartPairing();
|
||||
bool InitiatePairing(api::BluetoothPairingCallback pairing_cb) override;
|
||||
bool FinishPairing(std::optional<absl::string_view> pin_code) override;
|
||||
bool CancelPairing() override;
|
||||
bool Unpair() override;
|
||||
bool IsPaired() override;
|
||||
|
||||
private:
|
||||
void OnPairingRequested(
|
||||
@@ -48,9 +56,20 @@ class BluetoothPairing {
|
||||
pairing_result);
|
||||
|
||||
// WinRT objects
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothDevice bluetooth_device_;
|
||||
::winrt::Windows::Devices::Enumeration::DeviceInformationCustomPairing
|
||||
custom_pairing_;
|
||||
|
||||
::winrt::event_token pairing_requested_token_;
|
||||
::winrt::Windows::Devices::Enumeration::DevicePairingRequestedEventArgs
|
||||
pairing_requested_ = nullptr;
|
||||
::winrt::Windows::Foundation::Deferral pairing_deferral_ = nullptr;
|
||||
api::BluetoothPairingCallback pairing_callback_;
|
||||
|
||||
// Boolean indicating whether the device is currently pairing and expecting a
|
||||
// PIN Code to be returned.
|
||||
bool expecting_pin_code_ = false;
|
||||
bool was_cancelled_ = false;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
Reference in New Issue
Block a user