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#pragma once
18
19#include <unordered_map>
20
21#include <base/macros.h>
22#include <base/memory/ref_counted.h>
23#include <base/memory/weak_ptr.h>
24#include <base/single_thread_task_runner.h>
25
26#include <bluetooth/binder/IBluetooth.h>
27#include <bluetooth/binder/IBluetoothGattServerCallback.h>
28#include <bluetooth/gatt_identifier.h>
29
30namespace heart_rate {
31
32// Implements an example GATT Heart Rate service. This class emulates the
33// behavior of a heart rate service by sending fake heart-rate pulses.
34class HeartRateServer : public ipc::binder::BnBluetoothGattServerCallback {
35 public:
36  HeartRateServer(
37      android::sp<ipc::binder::IBluetooth> bluetooth,
38      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
39      bool advertise);
40  ~HeartRateServer() override;
41
42  // Set up the server and register the GATT services with the stack. This
43  // initiates a set of asynchronous procedures. Invokes |callback|
44  // asynchronously with the result of the operation.
45  using RunCallback = std::function<void(bool success)>;
46  bool Run(const RunCallback& callback);
47
48 private:
49  // Helpers for posting heart rate measurement notifications.
50  void ScheduleNextMeasurement();
51  void SendHeartRateMeasurement();
52  void BuildHeartRateMeasurementValue(std::vector<uint8_t>* out_value);
53
54  // ipc::binder::IBluetoothGattServerCallback override:
55  void OnServerRegistered(int status, int server_if) override;
56  void OnServiceAdded(
57      int status,
58      const bluetooth::GattIdentifier& service_id) override;
59  void OnCharacteristicReadRequest(
60      const std::string& device_address,
61      int request_id, int offset, bool is_long,
62      const bluetooth::GattIdentifier& characteristic_id) override;
63  void OnDescriptorReadRequest(
64      const std::string& device_address,
65      int request_id, int offset, bool is_long,
66      const bluetooth::GattIdentifier& descriptor_id) override;
67  void OnCharacteristicWriteRequest(
68      const std::string& device_address,
69      int request_id, int offset, bool is_prepare_write, bool need_response,
70      const std::vector<uint8_t>& value,
71      const bluetooth::GattIdentifier& characteristic_id) override;
72  void OnDescriptorWriteRequest(
73      const std::string& device_address,
74      int request_id, int offset, bool is_prepare_write, bool need_response,
75      const std::vector<uint8_t>& value,
76      const bluetooth::GattIdentifier& descriptor_id) override;
77  void OnExecuteWriteRequest(
78      const std::string& device_address,
79      int request_id, bool is_execute) override;
80  void OnNotificationSent(const std::string& device_address,
81                          int status) override;
82
83  // Single mutex to protect all variables below.
84  std::mutex mutex_;
85
86  // This stores whether or not at least one remote device has written to the
87  // CCC descriptor.
88  bool simulation_started_;
89
90  // The IBluetooth and IBluetoothGattServer binders that we use to communicate
91  // with the Bluetooth daemon's GATT server features.
92  android::sp<ipc::binder::IBluetooth> bluetooth_;
93  android::sp<ipc::binder::IBluetoothGattServer> gatt_;
94
95  // ID assigned to us by the daemon to operate on our dedicated GATT server
96  // instance.
97  int server_if_;
98
99  // Callback passed to Run(). We use this to tell main that all attributes have
100  // been registered with the daemon.
101  RunCallback pending_run_cb_;
102
103  // Stores whether or not an outgoing notification is still pending. We use
104  // this to throttle notifications so that we don't accidentally congest the
105  // connection.
106  std::unordered_map<std::string, bool> pending_notification_map_;
107
108  // The current HR notification count.
109  int hr_notification_count_;
110
111  // The Energy Expended value we use in our notifications.
112  uint16_t energy_expended_;
113
114  // The unique IDs that refer to each of the Heart Rate Service GATT objects.
115  // These returned to us from the Bluetooth daemon as we populate the database.
116  bluetooth::GattIdentifier hr_service_id_;
117  bluetooth::GattIdentifier hr_measurement_id_;
118  bluetooth::GattIdentifier hr_measurement_cccd_id_;
119  bluetooth::GattIdentifier body_sensor_loc_id_;
120  bluetooth::GattIdentifier hr_control_point_id_;
121
122  // The daemon itself doesn't maintain a Client Characteristic Configuration
123  // mapping, so we do it ourselves here.
124  std::unordered_map<std::string, uint8_t> device_ccc_map_;
125
126  // Wether we should also start advertising
127  bool advertise_;
128
129  // libchrome task runner that we use to post heart rate measurement
130  // notifications on the main thread.
131  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
132
133  // We use this to pass weak_ptr's to base::Bind, which won't execute if the
134  // HeartRateServer object gets deleted. This is a convenience utility from
135  // libchrome and we use it here since base::TaskRunner uses base::Callback.
136  // Note: This should remain the last member so that it'll be destroyed and
137  // invalidate its weak pointers before any other members are destroyed.
138  base::WeakPtrFactory<HeartRateServer> weak_ptr_factory_;
139
140  DISALLOW_COPY_AND_ASSIGN(HeartRateServer);
141};
142
143}  // namespace heart_rate
144