| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device/bluetooth/test/fake_gatt_session_winrt.h" |
| |
| #include <wrl/client.h> |
| |
| #include "base/test/bind.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/win/async_operation.h" |
| #include "device/bluetooth/test/bluetooth_test_win.h" |
| |
| namespace device { |
| |
| namespace { |
| |
| using ABI::Windows::Devices::Bluetooth::BluetoothError; |
| using ABI::Windows::Devices::Bluetooth::BluetoothError_OtherError; |
| using ABI::Windows::Devices::Bluetooth::BluetoothError_Success; |
| using ABI::Windows::Devices::Bluetooth::IBluetoothDeviceId; |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattSession; |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| GattSessionStatus; |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| GattSessionStatus_Active; |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| GattSessionStatus_Closed; |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| GattSessionStatusChangedEventArgs; |
| using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| IGattSessionStatusChangedEventArgs; |
| using ABI::Windows::Foundation::IAsyncOperation; |
| using ABI::Windows::Foundation::ITypedEventHandler; |
| using Microsoft::WRL::Make; |
| |
| class FakeGattSessionStatusChangedEventArgs |
| : public Microsoft::WRL::RuntimeClass< |
| Microsoft::WRL::RuntimeClassFlags< |
| Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>, |
| ABI::Windows::Devices::Bluetooth::GenericAttributeProfile:: |
| IGattSessionStatusChangedEventArgs> { |
| public: |
| FakeGattSessionStatusChangedEventArgs(GattSessionStatus status, |
| BluetoothError error) |
| : status_(status), error_(error) {} |
| FakeGattSessionStatusChangedEventArgs( |
| const FakeGattSessionStatusChangedEventArgs&) = delete; |
| FakeGattSessionStatusChangedEventArgs& operator=( |
| const FakeGattSessionStatusChangedEventArgs&) = delete; |
| ~FakeGattSessionStatusChangedEventArgs() override {} |
| |
| IFACEMETHODIMP get_Error(BluetoothError* value) override { |
| *value = error_; |
| return S_OK; |
| } |
| |
| IFACEMETHODIMP get_Status(GattSessionStatus* value) override { |
| *value = status_; |
| return S_OK; |
| } |
| |
| private: |
| GattSessionStatus status_; |
| BluetoothError error_; |
| }; |
| |
| } // namespace |
| |
| FakeGattSessionWinrt::FakeGattSessionWinrt( |
| BluetoothTestWinrt* bluetooth_test_winrt) |
| : bluetooth_test_winrt_(bluetooth_test_winrt) {} |
| |
| FakeGattSessionWinrt::~FakeGattSessionWinrt() = default; |
| |
| void FakeGattSessionWinrt::SimulateGattConnection() { |
| // Ensure the GattSession.MaintainConnection property has been set in order |
| // to force the OS to establish a GATT connection. |
| DCHECK(maintain_connection_); |
| status_ = GattSessionStatus_Active; |
| auto args = Make<FakeGattSessionStatusChangedEventArgs>( |
| GattSessionStatus_Active, BluetoothError_Success); |
| status_changed_handler_->Invoke(this, args.Get()); |
| } |
| |
| void FakeGattSessionWinrt::SimulateGattDisconnection() { |
| if (status_ == GattSessionStatus_Closed) { |
| SimulateGattConnectionError(); |
| return; |
| } |
| |
| status_ = GattSessionStatus_Closed; |
| auto args = Make<FakeGattSessionStatusChangedEventArgs>( |
| GattSessionStatus_Closed, BluetoothError_Success); |
| status_changed_handler_->Invoke(this, args.Get()); |
| } |
| |
| void FakeGattSessionWinrt::SimulateGattConnectionError() { |
| status_ = GattSessionStatus_Closed; |
| auto args = Make<FakeGattSessionStatusChangedEventArgs>( |
| GattSessionStatus_Closed, BluetoothError_OtherError); |
| status_changed_handler_->Invoke(this, args.Get()); |
| } |
| |
| HRESULT FakeGattSessionWinrt::get_DeviceId(IBluetoothDeviceId** value) { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT FakeGattSessionWinrt::get_CanMaintainConnection(::boolean* value) { |
| *value = true; |
| return S_OK; |
| } |
| |
| HRESULT FakeGattSessionWinrt::put_MaintainConnection(::boolean value) { |
| if (!maintain_connection_ && value) { |
| bluetooth_test_winrt_->OnFakeBluetoothDeviceConnectGattAttempt(); |
| } |
| |
| maintain_connection_ = value; |
| return S_OK; |
| } |
| |
| HRESULT FakeGattSessionWinrt::get_MaintainConnection(::boolean* value) { |
| *value = maintain_connection_; |
| return S_OK; |
| } |
| |
| HRESULT FakeGattSessionWinrt::get_MaxPduSize(UINT16* value) { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT FakeGattSessionWinrt::get_SessionStatus(GattSessionStatus* value) { |
| *value = status_; |
| return S_OK; |
| } |
| |
| HRESULT FakeGattSessionWinrt::add_MaxPduSizeChanged( |
| ITypedEventHandler<GattSession*, IInspectable*>* handler, |
| EventRegistrationToken* token) { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT |
| FakeGattSessionWinrt::remove_MaxPduSizeChanged(EventRegistrationToken token) { |
| return E_NOTIMPL; |
| } |
| |
| HRESULT FakeGattSessionWinrt::add_SessionStatusChanged( |
| ITypedEventHandler<GattSession*, GattSessionStatusChangedEventArgs*>* |
| handler, |
| EventRegistrationToken* token) { |
| status_changed_handler_ = handler; |
| return S_OK; |
| } |
| |
| HRESULT |
| FakeGattSessionWinrt::remove_SessionStatusChanged( |
| EventRegistrationToken token) { |
| status_changed_handler_ = nullptr; |
| return S_OK; |
| } |
| |
| HRESULT FakeGattSessionWinrt::Close() { |
| return S_OK; |
| } |
| |
| FakeGattSessionStaticsWinrt::FakeGattSessionStaticsWinrt( |
| BluetoothTestWinrt* bluetooth_test_winrt) |
| : bluetooth_test_winrt_(bluetooth_test_winrt) { |
| // BluetoothDeviceWinrt does not obtain a GattSession if |
| // |kNewBLEGattSessionHandling| is disabled. |
| DCHECK(bluetooth_test_winrt_->UsesNewGattSessionHandling()); |
| } |
| |
| FakeGattSessionStaticsWinrt::~FakeGattSessionStaticsWinrt() = default; |
| |
| HRESULT FakeGattSessionStaticsWinrt::FromDeviceIdAsync( |
| IBluetoothDeviceId* device_id, |
| IAsyncOperation<GattSession*>** operation) { |
| DCHECK(device_id); |
| auto async_op = Make<base::win::AsyncOperation<GattSession*>>(); |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::BindOnce(async_op->callback(), |
| Make<FakeGattSessionWinrt>(bluetooth_test_winrt_))); |
| *operation = async_op.Detach(); |
| return S_OK; |
| } |
| |
| } // namespace device |