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 
30 namespace 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.
34 class 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