Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 1 | // |
Jakub Pawlowski | 5b790fe | 2017-09-18 09:00:20 -0700 | [diff] [blame] | 2 | // Copyright 2015 Google, Inc. |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 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 | |
Bailey Forrest | 878c50b | 2017-02-09 17:26:28 -0800 | [diff] [blame] | 19 | #include <mutex> |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 20 | #include <unordered_map> |
| 21 | |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 22 | #include <base/macros.h> |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 23 | #include <base/memory/ref_counted.h> |
| 24 | #include <base/memory/weak_ptr.h> |
| 25 | #include <base/single_thread_task_runner.h> |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 26 | |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 27 | #include <android/bluetooth/BnBluetoothGattServerCallback.h> |
| 28 | #include <android/bluetooth/IBluetooth.h> |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 29 | |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 30 | using android::binder::Status; |
| 31 | using android::String16; |
| 32 | |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 33 | namespace 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. |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 37 | class HeartRateServer |
| 38 | : public android::bluetooth::BnBluetoothGattServerCallback { |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 39 | public: |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 40 | HeartRateServer(android::sp<android::bluetooth::IBluetooth> bluetooth, |
| 41 | scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 42 | bool advertise); |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 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: |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 52 | // Helpers for posting heart rate measurement notifications. |
| 53 | void ScheduleNextMeasurement(); |
| 54 | void SendHeartRateMeasurement(); |
| 55 | void BuildHeartRateMeasurementValue(std::vector<uint8_t>* out_value); |
| 56 | |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 57 | // ipc::binder::IBluetoothGattServerCallback override: |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 58 | Status OnServerRegistered(int status, int server_id) override; |
| 59 | Status OnServiceAdded( |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 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; |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 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; |
Jakub Pawlowski | 7932727 | 2016-07-07 16:40:11 -0700 | [diff] [blame] | 81 | Status OnConnectionStateChanged(const String16& device_address, |
| 82 | bool connected) override; |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 83 | |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 84 | // Single mutex to protect all variables below. |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 85 | std::mutex mutex_; |
| 86 | |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 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. |
Jakub Pawlowski | a4bd0d2 | 2016-02-16 11:53:14 -0800 | [diff] [blame] | 93 | android::sp<android::bluetooth::IBluetooth> bluetooth_; |
| 94 | android::sp<android::bluetooth::IBluetoothGattServer> gatt_; |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 95 | |
| 96 | // ID assigned to us by the daemon to operate on our dedicated GATT server |
| 97 | // instance. |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 98 | int server_if_; |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 99 | |
| 100 | // Callback passed to Run(). We use this to tell main that all attributes have |
| 101 | // been registered with the daemon. |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 102 | RunCallback pending_run_cb_; |
| 103 | |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 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 | |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 115 | // Handles that refer to Heart Rate Service GATT objects. |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 116 | // These returned to us from the Bluetooth daemon as we populate the database. |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 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_; |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 122 | |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 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 | |
Jakub Pawlowski | 032169c | 2016-01-22 15:07:07 -0800 | [diff] [blame] | 127 | // Wether we should also start advertising |
| 128 | bool advertise_; |
| 129 | |
Arman Uguray | 1c162dc | 2015-09-29 22:30:53 -0700 | [diff] [blame] | 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 | |
Arman Uguray | e0fe387 | 2015-09-25 20:29:17 -0700 | [diff] [blame] | 141 | DISALLOW_COPY_AND_ASSIGN(HeartRateServer); |
| 142 | }; |
| 143 | |
| 144 | } // namespace heart_rate |