OSDN Git Service

service: add SetMtu and OnMtuChanged
[android-x86/system-bt.git] / service / example / heart_rate / heart_rate_server.cpp
1 //
2 //  Copyright (C) 2015 Google, Inc.
3 //
4 //  Licensed under the Apache License, Version 2.0 (the "License");
5 //  you may not use this file except in compliance with the License.
6 //  You may obtain a copy of the License at:
7 //
8 //  http://www.apache.org/licenses/LICENSE-2.0
9 //
10 //  Unless required by applicable law or agreed to in writing, software
11 //  distributed under the License is distributed on an "AS IS" BASIS,
12 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 //  See the License for the specific language governing permissions and
14 //  limitations under the License.
15 //
16
17 #include "service/example/heart_rate/heart_rate_server.h"
18
19 #include <base/bind.h>
20 #include <base/location.h>
21 #include <base/logging.h>
22 #include <base/rand_util.h>
23
24 #include <bluetooth/low_energy_constants.h>
25
26 #include "service/example/heart_rate/constants.h"
27
28 namespace heart_rate {
29
30 class CLIBluetoothLowEnergyCallback
31     : public ipc::binder::BnBluetoothLowEnergyCallback {
32  public:
33   CLIBluetoothLowEnergyCallback(android::sp<ipc::binder::IBluetooth> bt)
34       : bt_(bt) {}
35
36   // IBluetoothLowEnergyCallback overrides:
37   void OnConnectionState(int status, int client_id, const char* address,
38                          bool connected) override {}
39   void OnMtuChanged(int status, const char *address, int mtu) override {}
40
41   void OnScanResult(const bluetooth::ScanResult& scan_result) override {}
42
43   void OnClientRegistered(int status, int client_id){
44     if (status != bluetooth::BLE_STATUS_SUCCESS) {
45       LOG(ERROR) << "Failed to register BLE client, will not start advertising";
46       return;
47     }
48
49     LOG(INFO) << "Registered BLE client with ID: " << client_id;
50
51     /* Advertising data: 16-bit Service UUID: Heart Rate Service */
52     std::vector<uint8_t> data{0x03, 0x03, 0x0D, 0x18};
53     base::TimeDelta timeout;
54
55     bluetooth::AdvertiseSettings settings(
56         bluetooth::AdvertiseSettings::MODE_LOW_POWER,
57         timeout,
58         bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM,
59         true);
60
61     bluetooth::AdvertiseData adv_data(data);
62     adv_data.set_include_device_name(true);
63     adv_data.set_include_tx_power_level(true);
64
65     bluetooth::AdvertiseData scan_rsp;
66
67     bt_->GetLowEnergyInterface()->
68         StartMultiAdvertising(client_id, adv_data, scan_rsp, settings);
69   }
70
71   void OnMultiAdvertiseCallback(int status, bool is_start,
72       const bluetooth::AdvertiseSettings& /* settings */) {
73     LOG(INFO) << "Advertising" << (is_start?" started":" stopped");
74   };
75
76  private:
77   android::sp<ipc::binder::IBluetooth> bt_;
78   DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback);
79 };
80
81
82 HeartRateServer::HeartRateServer(
83     android::sp<ipc::binder::IBluetooth> bluetooth,
84     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
85     bool advertise)
86     : simulation_started_(false),
87       bluetooth_(bluetooth),
88       server_if_(-1),
89       hr_notification_count_(0),
90       energy_expended_(0),
91       advertise_(advertise),
92       main_task_runner_(main_task_runner),
93       weak_ptr_factory_(this) {
94   CHECK(bluetooth_.get());
95 }
96
97 HeartRateServer::~HeartRateServer() {
98   std::lock_guard<std::mutex> lock(mutex_);
99   if (!gatt_.get() || server_if_ == -1)
100     return;
101
102   if (!android::IInterface::asBinder(gatt_.get())->isBinderAlive())
103     return;
104
105   // Manually unregister ourselves from the daemon. It's good practice to do
106   // this, even though the daemon will automatically unregister us if this
107   // process exits.
108   gatt_->UnregisterServer(server_if_);
109 }
110
111 bool HeartRateServer::Run(const RunCallback& callback) {
112   std::lock_guard<std::mutex> lock(mutex_);
113
114   if (pending_run_cb_) {
115     LOG(ERROR) << "Already started";
116     return false;
117   }
118
119   // Grab the IBluetoothGattServer binder from the Bluetooth daemon.
120   gatt_ = bluetooth_->GetGattServerInterface();
121   if (!gatt_.get()) {
122     LOG(ERROR) << "Failed to obtain handle to IBluetoothGattServer interface";
123     return false;
124   }
125
126   // Register this instance as a GATT server. If this call succeeds, we will
127   // asynchronously receive a server ID via the OnServerRegistered callback.
128   if (!gatt_->RegisterServer(this)) {
129     LOG(ERROR) << "Failed to register with the server interface";
130     return false;
131   }
132
133   pending_run_cb_ = callback;
134
135   return true;
136 }
137
138 void HeartRateServer::ScheduleNextMeasurement() {
139   main_task_runner_->PostDelayedTask(
140       FROM_HERE,
141       base::Bind(&HeartRateServer::SendHeartRateMeasurement,
142                  weak_ptr_factory_.GetWeakPtr()),
143       base::TimeDelta::FromSeconds(1));
144 }
145
146 void HeartRateServer::SendHeartRateMeasurement() {
147   std::lock_guard<std::mutex> lock(mutex_);
148
149   // Send a notification or indication to all enabled devices.
150   bool found = false;
151   for (const auto& iter : device_ccc_map_) {
152     uint8_t ccc_val = iter.second;
153
154     if (!ccc_val)
155       continue;
156
157     found = true;
158
159     // Don't send a notification if one is already pending for this device.
160     if (pending_notification_map_[iter.first])
161       continue;
162
163     std::vector<uint8_t> value;
164     BuildHeartRateMeasurementValue(&value);
165
166     if (gatt_->SendNotification(server_if_, iter.first, hr_measurement_id_,
167                                 false, value))
168       pending_notification_map_[iter.first] = true;
169   }
170
171   // Still enabled!
172   if (found) {
173     ScheduleNextMeasurement();
174     return;
175   }
176
177   // All clients disabled notifications.
178   simulation_started_ = false;
179
180   // TODO(armansito): We should keep track of closed connections here so that we
181   // don't send notifications to uninterested clients.
182 }
183
184 void HeartRateServer::BuildHeartRateMeasurementValue(
185     std::vector<uint8_t>* out_value) {
186   CHECK(out_value);  // Assert that |out_value| is not nullptr.
187
188   // Default flags field. Here is what we put in there:
189   //   Bit 0: 0 - 8-bit Heart Rate value
190   //   Bits 1 & 2: 11 - Sensor contact feature supported and contact detected.
191   uint8_t flags = kHRValueFormat8Bit | kHRSensorContactDetected;
192
193   // Our demo's heart rate. Pick a value between 90 and 130.
194   uint8_t heart_rate = base::RandInt(90, 130);
195
196   // On every tenth beat we include the Energy Expended value.
197   bool include_ee = false;
198   if (!(hr_notification_count_ % 10)) {
199     include_ee = true;
200     flags |= kHREnergyExpendedPresent;
201   }
202
203   hr_notification_count_++;
204   energy_expended_ = std::min(UINT16_MAX, (int)energy_expended_ + 1);
205
206   // Add all the value bytes.
207   out_value->push_back(flags);
208   out_value->push_back(heart_rate);
209   if (include_ee) {
210     out_value->push_back(energy_expended_);
211     out_value->push_back(energy_expended_ >> 8);
212   }
213 }
214
215 void HeartRateServer::OnServerRegistered(int status, int server_if) {
216   std::lock_guard<std::mutex> lock(mutex_);
217
218   if (status != bluetooth::BLE_STATUS_SUCCESS) {
219     LOG(ERROR) << "Failed to register GATT server";
220     pending_run_cb_(false);
221     return;
222   }
223
224   // Registration succeeded. Store our ID, as we need it for GATT server
225   // operations.
226   server_if_ = server_if;
227
228   LOG(INFO) << "Heart Rate server registered - server_if: " << server_if_;
229   LOG(INFO) << "Populating attributes";
230
231   // Start service declaration.
232   std::unique_ptr<bluetooth::GattIdentifier> gatt_id;
233   if (!gatt_->BeginServiceDeclaration(server_if_, true,
234                                       kHRServiceUUID,
235                                       &gatt_id)) {
236     LOG(ERROR) << "Failed to begin service declaration";
237     pending_run_cb_(false);
238     return;
239   }
240
241   hr_service_id_ = *gatt_id;
242
243   // Add Heart Rate Measurement characteristic.
244   if (!gatt_->AddCharacteristic(
245       server_if_, kHRMeasurementUUID,
246       bluetooth::kCharacteristicPropertyNotify,
247       0, &gatt_id)) {
248     LOG(ERROR) << "Failed to add heart rate measurement characteristic";
249     pending_run_cb_(false);
250     return;
251   }
252
253   hr_measurement_id_ = *gatt_id;
254
255   // Add Client Characteristic Configuration descriptor for the Heart Rate
256   // Measurement characteristic.
257   if (!gatt_->AddDescriptor(
258       server_if_, kCCCDescriptorUUID,
259       bluetooth::kAttributePermissionRead|bluetooth::kAttributePermissionWrite,
260       &gatt_id)) {
261     LOG(ERROR) << "Failed to add CCC descriptor";
262     pending_run_cb_(false);
263     return;
264   }
265
266   hr_measurement_cccd_id_ = *gatt_id;
267
268   // Add Body Sensor Location characteristic.
269   if (!gatt_->AddCharacteristic(
270       server_if_, kBodySensorLocationUUID,
271       bluetooth::kCharacteristicPropertyRead,
272       bluetooth::kAttributePermissionRead,
273       &gatt_id)) {
274     LOG(ERROR) << "Failed to add body sensor location characteristic";
275     pending_run_cb_(false);
276     return;
277   }
278
279   body_sensor_loc_id_ = *gatt_id;
280
281   // Add Heart Rate Control Point characteristic.
282   if (!gatt_->AddCharacteristic(
283       server_if_, kHRControlPointUUID,
284       bluetooth::kCharacteristicPropertyWrite,
285       bluetooth::kAttributePermissionWrite,
286       &gatt_id)) {
287     LOG(ERROR) << "Failed to add heart rate control point characteristic";
288     pending_run_cb_(false);
289     return;
290   }
291
292   hr_control_point_id_ = *gatt_id;
293
294   // End service declaration. We will be notified whether or not this succeeded
295   // via the OnServiceAdded callback.
296   if (!gatt_->EndServiceDeclaration(server_if_)) {
297     LOG(ERROR) << "Failed to end service declaration";
298     pending_run_cb_(false);
299     return;
300   }
301
302   LOG(INFO) << "Initiated EndServiceDeclaration request";
303 }
304
305 void HeartRateServer::OnServiceAdded(
306     int status,
307     const bluetooth::GattIdentifier& service_id) {
308   std::lock_guard<std::mutex> lock(mutex_);
309
310   if (status != bluetooth::BLE_STATUS_SUCCESS) {
311     LOG(ERROR) << "Failed to add Heart Rate service";
312     pending_run_cb_(false);
313     return;
314   }
315
316   if (service_id != hr_service_id_) {
317     LOG(ERROR) << "Received callback for the wrong service ID";
318     pending_run_cb_(false);
319     return;
320   }
321
322   // EndServiceDeclaration succeeded! Our Heart Rate service is now discoverable
323   // over GATT connections.
324
325   LOG(INFO) << "Heart Rate service added";
326   pending_run_cb_(true);
327
328   if (advertise_) {
329     auto ble = bluetooth_->GetLowEnergyInterface();
330     if (!ble.get()) {
331       LOG(ERROR) << "Failed to obtain handle to IBluetoothLowEnergy interface";
332       return;
333     }
334     ble->RegisterClient(new CLIBluetoothLowEnergyCallback(bluetooth_));
335   }
336
337 }
338
339 void HeartRateServer::OnCharacteristicReadRequest(
340     const std::string& device_address,
341     int request_id, int offset, bool /* is_long */,
342     const bluetooth::GattIdentifier& characteristic_id) {
343   std::lock_guard<std::mutex> lock(mutex_);
344
345   // This is where we handle an incoming characteristic read. Only the body
346   // sensor location characteristic is readable.
347   CHECK(characteristic_id == body_sensor_loc_id_);
348
349   std::vector<uint8_t> value;
350   bluetooth::GATTError error = bluetooth::GATT_ERROR_NONE;
351   if (offset > 1)
352     error = bluetooth::GATT_ERROR_INVALID_OFFSET;
353   else if (offset == 0)
354     value.push_back(kHRBodyLocationFoot);
355
356   gatt_->SendResponse(server_if_, device_address, request_id, error,
357                       offset, value);
358 }
359
360 void HeartRateServer::OnDescriptorReadRequest(
361     const std::string& device_address,
362     int request_id, int offset, bool /* is_long */,
363     const bluetooth::GattIdentifier& descriptor_id) {
364   std::lock_guard<std::mutex> lock(mutex_);
365
366   // This is where we handle an incoming characteristic descriptor read. There
367   // is only one descriptor.
368   if (descriptor_id != hr_measurement_cccd_id_) {
369     std::vector<uint8_t> value;
370     gatt_->SendResponse(server_if_, device_address, request_id,
371                         bluetooth::GATT_ERROR_ATTRIBUTE_NOT_FOUND,
372                         offset, value);
373     return;
374   }
375
376   // 16-bit value encoded as little-endian.
377   const uint8_t value_bytes[] = { device_ccc_map_[device_address], 0x00 };
378
379   std::vector<uint8_t> value;
380   bluetooth::GATTError error = bluetooth::GATT_ERROR_NONE;
381   if (offset > 2)
382     error = bluetooth::GATT_ERROR_INVALID_OFFSET;
383   else
384     value.insert(value.begin(), value_bytes + offset, value_bytes + 2 - offset);
385
386   gatt_->SendResponse(server_if_, device_address, request_id, error,
387                       offset, value);
388 }
389
390 void HeartRateServer::OnCharacteristicWriteRequest(
391     const std::string& device_address,
392     int request_id, int offset, bool is_prepare_write, bool need_response,
393     const std::vector<uint8_t>& value,
394     const bluetooth::GattIdentifier& characteristic_id) {
395   std::lock_guard<std::mutex> lock(mutex_);
396
397   std::vector<uint8_t> dummy;
398
399   // This is where we handle an incoming characteristic write. The Heart Rate
400   // service doesn't really support prepared writes, so we just reject them to
401   // keep things simple.
402   if (is_prepare_write) {
403     gatt_->SendResponse(server_if_, device_address, request_id,
404                         bluetooth::GATT_ERROR_REQUEST_NOT_SUPPORTED,
405                         offset, dummy);
406     return;
407   }
408
409   // Heart Rate Control point is the only writable characteristic.
410   CHECK(characteristic_id == hr_control_point_id_);
411
412   // Writes to the Heart Rate Control Point characteristic must contain a single
413   // byte with the value 0x01.
414   if (value.size() != 1 || value[0] != 0x01) {
415     gatt_->SendResponse(server_if_, device_address, request_id,
416                         bluetooth::GATT_ERROR_OUT_OF_RANGE,
417                         offset, dummy);
418     return;
419   }
420
421   LOG(INFO) << "Heart Rate Control Point written; Enery Expended reset!";
422   energy_expended_ = 0;
423
424   if (!need_response)
425     return;
426
427   gatt_->SendResponse(server_if_, device_address, request_id,
428                       bluetooth::GATT_ERROR_NONE, offset, dummy);
429 }
430
431 void HeartRateServer::OnDescriptorWriteRequest(
432     const std::string& device_address,
433     int request_id, int offset, bool is_prepare_write, bool need_response,
434     const std::vector<uint8_t>& value,
435     const bluetooth::GattIdentifier& descriptor_id) {
436   std::lock_guard<std::mutex> lock(mutex_);
437
438   std::vector<uint8_t> dummy;
439
440   // This is where we handle an incoming characteristic write. The Heart Rate
441   // service doesn't really support prepared writes, so we just reject them to
442   // keep things simple.
443   if (is_prepare_write) {
444     gatt_->SendResponse(server_if_, device_address, request_id,
445                         bluetooth::GATT_ERROR_REQUEST_NOT_SUPPORTED,
446                         offset, dummy);
447     return;
448   }
449
450   // CCC is the only descriptor we have.
451   CHECK(descriptor_id == hr_measurement_cccd_id_);
452
453   // CCC must contain 2 bytes for a 16-bit value in little-endian. The only
454   // allowed values here are 0x0000 and 0x0001.
455   if (value.size() != 2 || value[1] != 0x00 || value[0] > 0x01) {
456     gatt_->SendResponse(server_if_, device_address, request_id,
457                         bluetooth::GATT_ERROR_CCCD_IMPROPERLY_CONFIGURED,
458                         offset, dummy);
459     return;
460   }
461
462   device_ccc_map_[device_address] = value[0];
463
464   LOG(INFO) << "Heart Rate Measurement CCC written - device: "
465             << device_address << " value: " << (int)value[0];
466
467   // Start the simulation.
468   if (!simulation_started_ && value[0]) {
469     simulation_started_ = true;
470     ScheduleNextMeasurement();
471   }
472
473   if (!need_response)
474     return;
475
476   gatt_->SendResponse(server_if_, device_address, request_id,
477                       bluetooth::GATT_ERROR_NONE, offset, dummy);
478 }
479
480 void HeartRateServer::OnExecuteWriteRequest(
481     const std::string& device_address,
482     int request_id,
483     bool /* is_execute */) {
484   // We don't support Prepared Writes so, simply return Not Supported error.
485   std::vector<uint8_t> dummy;
486   gatt_->SendResponse(server_if_, device_address, request_id,
487                       bluetooth::GATT_ERROR_REQUEST_NOT_SUPPORTED, 0, dummy);
488 }
489
490 void HeartRateServer::OnNotificationSent(
491     const std::string& device_address, int status) {
492   LOG(INFO) << "Notification was sent - device: " << device_address
493             << " status: " << status;
494   std::lock_guard<std::mutex> lock(mutex_);
495   pending_notification_map_[device_address] = false;
496 }
497
498 }  // namespace heart_rate