1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/bluetooth/test/fake_gatt_device_service_winrt.h"
6
7 #include <wrl/client.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/strings/string16.h"
13 #include "base/strings/string_piece.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "base/win/async_operation.h"
17 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
18 #include "device/bluetooth/test/fake_bluetooth_le_device_winrt.h"
19 #include "device/bluetooth/test/fake_gatt_characteristic_winrt.h"
20 #include "device/bluetooth/test/fake_gatt_characteristics_result_winrt.h"
21
22 namespace device {
23
24 namespace {
25
26 using ABI::Windows::Devices::Bluetooth::BluetoothCacheMode;
27 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
28 GattCharacteristic;
29 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
30 GattCharacteristicsResult;
31 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
32 GattDeviceService;
33 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
34 GattDeviceServicesResult;
35 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattOpenStatus;
36 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
37 GattOpenStatus_AccessDenied;
38 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
39 GattOpenStatus_AlreadyOpened;
40 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
41 GattOpenStatus_Success;
42 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
43 GattSharingMode;
44 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
45 GattSharingMode_SharedReadAndWrite;
46 using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession;
47 using ABI::Windows::Devices::Enumeration::DeviceAccessStatus;
48 using ABI::Windows::Devices::Enumeration::IDeviceAccessInformation;
49 using ABI::Windows::Foundation::IAsyncOperation;
50 using ABI::Windows::Foundation::Collections::IVectorView;
51 using Microsoft::WRL::ComPtr;
52 using Microsoft::WRL::Make;
53
54 } // namespace
55
FakeGattDeviceServiceWinrt(BluetoothTestWinrt * bluetooth_test_winrt,ComPtr<FakeBluetoothLEDeviceWinrt> fake_device,base::StringPiece uuid,uint16_t attribute_handle,bool allowed)56 FakeGattDeviceServiceWinrt::FakeGattDeviceServiceWinrt(
57 BluetoothTestWinrt* bluetooth_test_winrt,
58 ComPtr<FakeBluetoothLEDeviceWinrt> fake_device,
59 base::StringPiece uuid,
60 uint16_t attribute_handle,
61 bool allowed)
62 : bluetooth_test_winrt_(bluetooth_test_winrt),
63 fake_device_(std::move(fake_device)),
64 uuid_(BluetoothUUID::GetCanonicalValueAsGUID(uuid)),
65 attribute_handle_(attribute_handle),
66 allowed_(allowed),
67 characteristic_attribute_handle_(attribute_handle_) {
68 fake_device_->AddReference();
69 }
70
~FakeGattDeviceServiceWinrt()71 FakeGattDeviceServiceWinrt::~FakeGattDeviceServiceWinrt() {
72 fake_device_->RemoveReference();
73 }
74
GetCharacteristics(GUID characteristic_uuid,IVectorView<GattCharacteristic * > ** value)75 HRESULT FakeGattDeviceServiceWinrt::GetCharacteristics(
76 GUID characteristic_uuid,
77 IVectorView<GattCharacteristic*>** value) {
78 return E_NOTIMPL;
79 }
80
GetIncludedServices(GUID service_uuid,IVectorView<GattDeviceService * > ** value)81 HRESULT FakeGattDeviceServiceWinrt::GetIncludedServices(
82 GUID service_uuid,
83 IVectorView<GattDeviceService*>** value) {
84 return E_NOTIMPL;
85 }
86
get_DeviceId(HSTRING * value)87 HRESULT FakeGattDeviceServiceWinrt::get_DeviceId(HSTRING* value) {
88 return E_NOTIMPL;
89 }
90
get_Uuid(GUID * value)91 HRESULT FakeGattDeviceServiceWinrt::get_Uuid(GUID* value) {
92 *value = uuid_;
93 return S_OK;
94 }
95
get_AttributeHandle(uint16_t * value)96 HRESULT FakeGattDeviceServiceWinrt::get_AttributeHandle(uint16_t* value) {
97 *value = attribute_handle_;
98 return S_OK;
99 }
100
get_DeviceAccessInformation(IDeviceAccessInformation ** value)101 HRESULT FakeGattDeviceServiceWinrt::get_DeviceAccessInformation(
102 IDeviceAccessInformation** value) {
103 return E_NOTIMPL;
104 }
105
get_Session(IGattSession ** value)106 HRESULT FakeGattDeviceServiceWinrt::get_Session(IGattSession** value) {
107 return E_NOTIMPL;
108 }
109
get_SharingMode(GattSharingMode * value)110 HRESULT FakeGattDeviceServiceWinrt::get_SharingMode(GattSharingMode* value) {
111 return E_NOTIMPL;
112 }
113
RequestAccessAsync(IAsyncOperation<DeviceAccessStatus> ** value)114 HRESULT FakeGattDeviceServiceWinrt::RequestAccessAsync(
115 IAsyncOperation<DeviceAccessStatus>** value) {
116 return E_NOTIMPL;
117 }
118
OpenAsync(GattSharingMode sharing_mode,IAsyncOperation<GattOpenStatus> ** operation)119 HRESULT FakeGattDeviceServiceWinrt::OpenAsync(
120 GattSharingMode sharing_mode,
121 IAsyncOperation<GattOpenStatus>** operation) {
122 if (sharing_mode != GattSharingMode_SharedReadAndWrite)
123 return E_NOTIMPL;
124
125 GattOpenStatus status;
126 if (allowed_) {
127 status = opened_ ? GattOpenStatus_AlreadyOpened : GattOpenStatus_Success;
128 opened_ = true;
129 } else {
130 status = GattOpenStatus_AccessDenied;
131 }
132
133 auto async_op = Make<base::win::AsyncOperation<GattOpenStatus>>();
134 base::ThreadTaskRunnerHandle::Get()->PostTask(
135 FROM_HERE, base::BindOnce(async_op->callback(), status));
136 *operation = async_op.Detach();
137 return S_OK;
138 }
139
GetCharacteristicsAsync(IAsyncOperation<GattCharacteristicsResult * > ** operation)140 HRESULT FakeGattDeviceServiceWinrt::GetCharacteristicsAsync(
141 IAsyncOperation<GattCharacteristicsResult*>** operation) {
142 // It has been observed that this method will implicitly call
143 // OpenAsync(Exclusive) if the service has not been opened already. Catch
144 // calls to an unopened service as we do not want to take an exclusive lock
145 // on a service.
146 if (!opened_)
147 return E_NOTIMPL;
148
149 auto async_op = Make<base::win::AsyncOperation<GattCharacteristicsResult*>>();
150 base::ThreadTaskRunnerHandle::Get()->PostTask(
151 FROM_HERE, base::BindOnce(async_op->callback(),
152 Make<FakeGattCharacteristicsResultWinrt>(
153 fake_characteristics_)));
154 *operation = async_op.Detach();
155 return S_OK;
156 }
157
GetCharacteristicsWithCacheModeAsync(BluetoothCacheMode cache_mode,IAsyncOperation<GattCharacteristicsResult * > ** operation)158 HRESULT FakeGattDeviceServiceWinrt::GetCharacteristicsWithCacheModeAsync(
159 BluetoothCacheMode cache_mode,
160 IAsyncOperation<GattCharacteristicsResult*>** operation) {
161 return E_NOTIMPL;
162 }
163
GetCharacteristicsForUuidAsync(GUID characteristic_uuid,IAsyncOperation<GattCharacteristicsResult * > ** operation)164 HRESULT FakeGattDeviceServiceWinrt::GetCharacteristicsForUuidAsync(
165 GUID characteristic_uuid,
166 IAsyncOperation<GattCharacteristicsResult*>** operation) {
167 return E_NOTIMPL;
168 }
169
GetCharacteristicsForUuidWithCacheModeAsync(GUID characteristic_uuid,BluetoothCacheMode cache_mode,IAsyncOperation<GattCharacteristicsResult * > ** operation)170 HRESULT FakeGattDeviceServiceWinrt::GetCharacteristicsForUuidWithCacheModeAsync(
171 GUID characteristic_uuid,
172 BluetoothCacheMode cache_mode,
173 IAsyncOperation<GattCharacteristicsResult*>** operation) {
174 return E_NOTIMPL;
175 }
176
GetIncludedServicesAsync(IAsyncOperation<GattDeviceServicesResult * > ** operation)177 HRESULT FakeGattDeviceServiceWinrt::GetIncludedServicesAsync(
178 IAsyncOperation<GattDeviceServicesResult*>** operation) {
179 return E_NOTIMPL;
180 }
181
GetIncludedServicesWithCacheModeAsync(BluetoothCacheMode cache_mode,IAsyncOperation<GattDeviceServicesResult * > ** operation)182 HRESULT FakeGattDeviceServiceWinrt::GetIncludedServicesWithCacheModeAsync(
183 BluetoothCacheMode cache_mode,
184 IAsyncOperation<GattDeviceServicesResult*>** operation) {
185 return E_NOTIMPL;
186 }
187
GetIncludedServicesForUuidAsync(GUID service_uuid,IAsyncOperation<GattDeviceServicesResult * > ** operation)188 HRESULT FakeGattDeviceServiceWinrt::GetIncludedServicesForUuidAsync(
189 GUID service_uuid,
190 IAsyncOperation<GattDeviceServicesResult*>** operation) {
191 return E_NOTIMPL;
192 }
193
194 HRESULT
GetIncludedServicesForUuidWithCacheModeAsync(GUID service_uuid,BluetoothCacheMode cache_mode,IAsyncOperation<GattDeviceServicesResult * > ** operation)195 FakeGattDeviceServiceWinrt::GetIncludedServicesForUuidWithCacheModeAsync(
196 GUID service_uuid,
197 BluetoothCacheMode cache_mode,
198 IAsyncOperation<GattDeviceServicesResult*>** operation) {
199 return E_NOTIMPL;
200 }
201
SimulateGattCharacteristic(base::StringPiece uuid,int properties)202 void FakeGattDeviceServiceWinrt::SimulateGattCharacteristic(
203 base::StringPiece uuid,
204 int properties) {
205 // In order to ensure attribute handles are unique across the Gatt Server
206 // we reserve sufficient address space for descriptors for each
207 // characteristic. We allocate space for 32 descriptors, which should be
208 // enough for tests.
209 fake_characteristics_.push_back(Make<FakeGattCharacteristicWinrt>(
210 bluetooth_test_winrt_, properties, uuid,
211 characteristic_attribute_handle_ += 0x20));
212 }
213
214 } // namespace device
215