blob: 02466521dd14cd7ba7f8f8a11a427e8bb76a07db [file] [log] [blame]
Arman Uguraye0fe3872015-09-25 20:29:17 -07001//
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07002// Copyright 2015 Google, Inc.
Arman Uguraye0fe3872015-09-25 20:29:17 -07003//
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 Forrest878c50b2017-02-09 17:26:28 -080019#include <mutex>
Arman Uguray1c162dc2015-09-29 22:30:53 -070020#include <unordered_map>
21
Arman Uguraye0fe3872015-09-25 20:29:17 -070022#include <base/macros.h>
Arman Uguray1c162dc2015-09-29 22:30:53 -070023#include <base/memory/ref_counted.h>
24#include <base/memory/weak_ptr.h>
25#include <base/single_thread_task_runner.h>
Arman Uguraye0fe3872015-09-25 20:29:17 -070026
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080027#include <android/bluetooth/BnBluetoothGattServerCallback.h>
28#include <android/bluetooth/IBluetooth.h>
Arman Uguraye0fe3872015-09-25 20:29:17 -070029
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080030using android::binder::Status;
31using android::String16;
32
Arman Uguraye0fe3872015-09-25 20:29:17 -070033namespace 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 Pawlowskia4bd0d22016-02-16 11:53:14 -080037class HeartRateServer
38 : public android::bluetooth::BnBluetoothGattServerCallback {
Arman Uguraye0fe3872015-09-25 20:29:17 -070039 public:
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080040 HeartRateServer(android::sp<android::bluetooth::IBluetooth> bluetooth,
41 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
42 bool advertise);
Arman Uguraye0fe3872015-09-25 20:29:17 -070043 ~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 Uguray1c162dc2015-09-29 22:30:53 -070052 // Helpers for posting heart rate measurement notifications.
53 void ScheduleNextMeasurement();
54 void SendHeartRateMeasurement();
55 void BuildHeartRateMeasurementValue(std::vector<uint8_t>* out_value);
56
Arman Uguraye0fe3872015-09-25 20:29:17 -070057 // ipc::binder::IBluetoothGattServerCallback override:
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080058 Status OnServerRegistered(int status, int server_id) override;
59 Status OnServiceAdded(
Myles Watson911d1ae2016-11-28 16:44:40 -080060 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 Pawlowskia4bd0d22016-02-16 11:53:14 -080077 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 Pawlowski79327272016-07-07 16:40:11 -070081 Status OnConnectionStateChanged(const String16& device_address,
82 bool connected) override;
Arman Uguraye0fe3872015-09-25 20:29:17 -070083
Arman Uguray1c162dc2015-09-29 22:30:53 -070084 // Single mutex to protect all variables below.
Arman Uguraye0fe3872015-09-25 20:29:17 -070085 std::mutex mutex_;
86
Arman Uguray1c162dc2015-09-29 22:30:53 -070087 // 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 Pawlowskia4bd0d22016-02-16 11:53:14 -080093 android::sp<android::bluetooth::IBluetooth> bluetooth_;
94 android::sp<android::bluetooth::IBluetoothGattServer> gatt_;
Arman Uguray1c162dc2015-09-29 22:30:53 -070095
96 // ID assigned to us by the daemon to operate on our dedicated GATT server
97 // instance.
Arman Uguraye0fe3872015-09-25 20:29:17 -070098 int server_if_;
Arman Uguray1c162dc2015-09-29 22:30:53 -070099
100 // Callback passed to Run(). We use this to tell main that all attributes have
101 // been registered with the daemon.
Arman Uguraye0fe3872015-09-25 20:29:17 -0700102 RunCallback pending_run_cb_;
103
Arman Uguray1c162dc2015-09-29 22:30:53 -0700104 // 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 Pawlowskia641b6f2016-03-26 00:47:23 -0700115 // Handles that refer to Heart Rate Service GATT objects.
Arman Uguray1c162dc2015-09-29 22:30:53 -0700116 // These returned to us from the Bluetooth daemon as we populate the database.
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700117 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 Uguraye0fe3872015-09-25 20:29:17 -0700122
Arman Uguray1c162dc2015-09-29 22:30:53 -0700123 // 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 Pawlowski032169c2016-01-22 15:07:07 -0800127 // Wether we should also start advertising
128 bool advertise_;
129
Arman Uguray1c162dc2015-09-29 22:30:53 -0700130 // 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 Uguraye0fe3872015-09-25 20:29:17 -0700141 DISALLOW_COPY_AND_ASSIGN(HeartRateServer);
142};
143
144} // namespace heart_rate