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