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