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 #include <base/bind.h> 17 #include <base/location.h> 18 #include <base/logging.h> 19 #include <base/rand_util.h> 20 21 #include <android/bluetooth/BnBluetoothLeAdvertiserCallback.h> 22 #include <android/bluetooth/IBluetoothLeAdvertiser.h> 23 #include <bluetooth/low_energy_constants.h> 24 25 #include "constants.h" 26 #include "heart_rate_server.h" 27 28 using android::binder::Status; 29 using android::String8; 30 using android::String16; 31 32 using android::bluetooth::IBluetoothLeAdvertiser; 33 using android::bluetooth::BluetoothGattService; 34 35 namespace heart_rate { 36 37 class CLIBluetoothLeAdvertiserCallback 38 : public android::bluetooth::BnBluetoothLeAdvertiserCallback { 39 public: 40 explicit CLIBluetoothLeAdvertiserCallback( 41 android::sp<android::bluetooth::IBluetooth> bt) 42 : bt_(bt) {} 43 44 // IBluetoothLeAdvertiserCallback overrides: 45 Status OnAdvertiserRegistered(int status, int advertiser_id) { 46 if (status != bluetooth::BLE_STATUS_SUCCESS) { 47 LOG(ERROR) 48 << "Failed to register BLE advertiser, will not start advertising"; 49 return Status::ok(); 50 } 51 52 LOG(INFO) << "Registered BLE advertiser with ID: " << advertiser_id; 53 54 String16 name_param; 55 bt_->GetName(&name_param); 56 std::string name(String8(name_param).string()); 57 58 /* Advertising data: 16-bit Service UUID: Heart Rate Service, Tx power*/ 59 std::vector<uint8_t> data{0x03, bluetooth::kEIRTypeComplete16BitUUIDs, 60 0x0D, 0x18, 61 0x02, bluetooth::kEIRTypeTxPower, 62 0x00}; 63 data.push_back(name.length() + 1); 64 data.push_back(bluetooth::kEIRTypeCompleteLocalName); 65 data.insert(data.end(), name.c_str(), name.c_str() + name.length()); 66 67 base::TimeDelta timeout; 68 69 bluetooth::AdvertiseSettings settings( 70 bluetooth::AdvertiseSettings::MODE_LOW_POWER, timeout, 71 bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM, true); 72 73 bluetooth::AdvertiseData adv_data(data); 74 bluetooth::AdvertiseData scan_rsp; 75 76 android::sp<IBluetoothLeAdvertiser> ble; 77 bt_->GetLeAdvertiserInterface(&ble); 78 bool start_status; 79 ble->StartMultiAdvertising(advertiser_id, adv_data, scan_rsp, settings, 80 &start_status); 81 return Status::ok(); 82 } 83 84 Status OnMultiAdvertiseCallback( 85 int status, bool is_start, 86 const android::bluetooth::AdvertiseSettings& /* settings */) { 87 LOG(INFO) << "Advertising" << (is_start ? " started" : " stopped"); 88 return Status::ok(); 89 }; 90 91 private: 92 android::sp<android::bluetooth::IBluetooth> bt_; 93 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback); 94 }; 95 96 HeartRateServer::HeartRateServer( 97 android::sp<android::bluetooth::IBluetooth> bluetooth, 98 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 99 bool advertise) 100 : simulation_started_(false), 101 bluetooth_(bluetooth), 102 server_if_(-1), 103 hr_notification_count_(0), 104 energy_expended_(0), 105 advertise_(advertise), 106 main_task_runner_(main_task_runner), 107 weak_ptr_factory_(this) { 108 CHECK(bluetooth_.get()); 109 } 110 111 HeartRateServer::~HeartRateServer() { 112 std::lock_guard<std::mutex> lock(mutex_); 113 if (!gatt_.get() || server_if_ == -1) return; 114 115 if (!android::IInterface::asBinder(gatt_.get())->isBinderAlive()) return; 116 117 // Manually unregister ourselves from the daemon. It's good practice to do 118 // this, even though the daemon will automatically unregister us if this 119 // process exits. 120 gatt_->UnregisterServer(server_if_); 121 } 122 123 bool HeartRateServer::Run(const RunCallback& callback) { 124 std::lock_guard<std::mutex> lock(mutex_); 125 126 if (pending_run_cb_) { 127 LOG(ERROR) << "Already started"; 128 return false; 129 } 130 131 // Grab the IBluetoothGattServer binder from the Bluetooth daemon. 132 bluetooth_->GetGattServerInterface(&gatt_); 133 if (!gatt_.get()) { 134 LOG(ERROR) << "Failed to obtain handle to IBluetoothGattServer interface"; 135 return false; 136 } 137 138 // Register this instance as a GATT server. If this call succeeds, we will 139 // asynchronously receive a server ID via the OnServerRegistered callback. 140 bool status; 141 gatt_->RegisterServer(this, &status); 142 if (!status) { 143 LOG(ERROR) << "Failed to register with the server interface"; 144 return false; 145 } 146 147 pending_run_cb_ = callback; 148 149 return true; 150 } 151 152 void HeartRateServer::ScheduleNextMeasurement() { 153 main_task_runner_->PostDelayedTask( 154 FROM_HERE, base::Bind(&HeartRateServer::SendHeartRateMeasurement, 155 weak_ptr_factory_.GetWeakPtr()), 156 base::TimeDelta::FromSeconds(1)); 157 } 158 159 void HeartRateServer::SendHeartRateMeasurement() { 160 std::lock_guard<std::mutex> lock(mutex_); 161 162 // Send a notification or indication to all enabled devices. 163 bool found = false; 164 for (const auto& iter : device_ccc_map_) { 165 uint8_t ccc_val = iter.second; 166 167 if (!ccc_val) continue; 168 169 found = true; 170 171 // Don't send a notification if one is already pending for this device. 172 if (pending_notification_map_[iter.first]) continue; 173 174 std::vector<uint8_t> value; 175 BuildHeartRateMeasurementValue(&value); 176 177 bool status; 178 gatt_->SendNotification(server_if_, String16(String8(iter.first.c_str())), 179 hr_measurement_handle_, false, value, &status); 180 if (status) pending_notification_map_[iter.first] = true; 181 } 182 183 // Still enabled! 184 if (found) { 185 ScheduleNextMeasurement(); 186 return; 187 } 188 189 // All clients disabled notifications. 190 simulation_started_ = false; 191 192 // TODO(armansito): We should keep track of closed connections here so that we 193 // don't send notifications to uninterested clients. 194 } 195 196 void HeartRateServer::BuildHeartRateMeasurementValue( 197 std::vector<uint8_t>* out_value) { 198 CHECK(out_value); // Assert that |out_value| is not nullptr. 199 200 // Default flags field. Here is what we put in there: 201 // Bit 0: 0 - 8-bit Heart Rate value 202 // Bits 1 & 2: 11 - Sensor contact feature supported and contact detected. 203 uint8_t flags = kHRValueFormat8Bit | kHRSensorContactDetected; 204 205 // Our demo's heart rate. Pick a value between 90 and 130. 206 uint8_t heart_rate = base::RandInt(90, 130); 207 208 // On every tenth beat we include the Energy Expended value. 209 bool include_ee = false; 210 if (!(hr_notification_count_ % 10)) { 211 include_ee = true; 212 flags |= kHREnergyExpendedPresent; 213 } 214 215 hr_notification_count_++; 216 energy_expended_ = std::min(UINT16_MAX, (int)energy_expended_ + 1); 217 218 // Add all the value bytes. 219 out_value->push_back(flags); 220 out_value->push_back(heart_rate); 221 if (include_ee) { 222 out_value->push_back(energy_expended_); 223 out_value->push_back(energy_expended_ >> 8); 224 } 225 } 226 227 Status HeartRateServer::OnServerRegistered(int status, int server_if) { 228 std::lock_guard<std::mutex> lock(mutex_); 229 230 if (status != bluetooth::BLE_STATUS_SUCCESS) { 231 LOG(ERROR) << "Failed to register GATT server"; 232 pending_run_cb_(false); 233 return Status::ok(); 234 } 235 236 // Registration succeeded. Store our ID, as we need it for GATT server 237 // operations. 238 server_if_ = server_if; 239 240 LOG(INFO) << "Heart Rate server registered - server_if: " << server_if_; 241 242 bluetooth::Service hrService( 243 0, true, kHRServiceUUID, 244 {{0, 245 kHRMeasurementUUID, 246 bluetooth::kCharacteristicPropertyNotify, 247 0, 248 {{0, kCCCDescriptorUUID, (bluetooth::kAttributePermissionRead | 249 bluetooth::kAttributePermissionWrite)}}}, 250 {0, 251 kBodySensorLocationUUID, 252 bluetooth::kCharacteristicPropertyRead, 253 bluetooth::kAttributePermissionRead, 254 {}}, 255 {0, 256 kHRControlPointUUID, 257 bluetooth::kCharacteristicPropertyWrite, 258 bluetooth::kAttributePermissionWrite, 259 {}}}, 260 {}); 261 262 bool op_status = true; 263 264 Status stat = gatt_->AddService(server_if_, (BluetoothGattService)hrService, 265 &op_status); 266 if (!stat.isOk()) { 267 LOG(ERROR) << "Failed to add service, status is: " /*<< stat*/; 268 pending_run_cb_(false); 269 return Status::ok(); 270 } 271 272 if (!op_status) { 273 LOG(ERROR) << "Failed to add service"; 274 pending_run_cb_(false); 275 return Status::ok(); 276 } 277 278 LOG(INFO) << "Initiated AddService request"; 279 return Status::ok(); 280 } 281 282 Status HeartRateServer::OnServiceAdded( 283 int status, const android::bluetooth::BluetoothGattService& service) { 284 std::lock_guard<std::mutex> lock(mutex_); 285 286 if (status != bluetooth::BLE_STATUS_SUCCESS) { 287 LOG(ERROR) << "Failed to add Heart Rate service"; 288 pending_run_cb_(false); 289 return Status::ok(); 290 } 291 292 hr_service_handle_ = service.handle(); 293 hr_measurement_handle_ = service.characteristics()[0].handle(); 294 hr_measurement_cccd_handle_ = 295 service.characteristics()[0].descriptors()[0].handle(); 296 body_sensor_loc_handle_ = service.characteristics()[1].handle(); 297 hr_control_point_handle_ = service.characteristics()[2].handle(); 298 299 LOG(INFO) << "Heart Rate service added"; 300 pending_run_cb_(true); 301 302 if (advertise_) { 303 android::sp<IBluetoothLeAdvertiser> ble; 304 bluetooth_->GetLeAdvertiserInterface(&ble); 305 bool status; 306 ble->RegisterAdvertiser(new CLIBluetoothLeAdvertiserCallback(bluetooth_), 307 &status); 308 } 309 310 return Status::ok(); 311 } 312 313 Status HeartRateServer::OnCharacteristicReadRequest( 314 const String16& device_address, int request_id, int offset, 315 bool /* is_long */, int handle) { 316 std::lock_guard<std::mutex> lock(mutex_); 317 318 // This is where we handle an incoming characteristic read. Only the body 319 // sensor location characteristic is readable. 320 CHECK(handle == body_sensor_loc_handle_); 321 322 std::vector<uint8_t> value; 323 bluetooth::GATTError error = bluetooth::GATT_ERROR_NONE; 324 if (offset > 1) 325 error = bluetooth::GATT_ERROR_INVALID_OFFSET; 326 else if (offset == 0) 327 value.push_back(kHRBodyLocationFoot); 328 329 bool status; 330 gatt_->SendResponse(server_if_, device_address, request_id, error, offset, 331 value, &status); 332 return Status::ok(); 333 } 334 335 Status HeartRateServer::OnDescriptorReadRequest(const String16& device_address, 336 int request_id, int offset, 337 bool /* is_long */, 338 int handle) { 339 std::lock_guard<std::mutex> lock(mutex_); 340 341 // This is where we handle an incoming characteristic descriptor read. There 342 // is only one descriptor. 343 if (handle != hr_measurement_cccd_handle_) { 344 std::vector<uint8_t> value; 345 bool status; 346 gatt_->SendResponse(server_if_, device_address, request_id, 347 bluetooth::GATT_ERROR_ATTRIBUTE_NOT_FOUND, offset, 348 value, &status); 349 return Status::ok(); 350 } 351 352 // 16-bit value encoded as little-endian. 353 const uint8_t value_bytes[] = { 354 device_ccc_map_[std::string(String8(device_address).string())], 0x00}; 355 356 std::vector<uint8_t> value; 357 bluetooth::GATTError error = bluetooth::GATT_ERROR_NONE; 358 if (offset > 2) 359 error = bluetooth::GATT_ERROR_INVALID_OFFSET; 360 else 361 value.insert(value.begin(), value_bytes + offset, value_bytes + 2 - offset); 362 363 bool status; 364 gatt_->SendResponse(server_if_, device_address, request_id, error, offset, 365 value, &status); 366 return Status::ok(); 367 } 368 369 Status HeartRateServer::OnCharacteristicWriteRequest( 370 const String16& device_address, int request_id, int offset, 371 bool is_prepare_write, bool need_response, 372 const std::vector<uint8_t>& value, int handle) { 373 std::lock_guard<std::mutex> lock(mutex_); 374 375 std::vector<uint8_t> dummy; 376 377 // This is where we handle an incoming characteristic write. The Heart Rate 378 // service doesn't really support prepared writes, so we just reject them to 379 // keep things simple. 380 if (is_prepare_write) { 381 bool status; 382 gatt_->SendResponse(server_if_, device_address, request_id, 383 bluetooth::GATT_ERROR_REQUEST_NOT_SUPPORTED, offset, 384 dummy, &status); 385 return Status::ok(); 386 } 387 388 // Heart Rate Control point is the only writable characteristic. 389 CHECK(handle == hr_control_point_handle_); 390 391 // Writes to the Heart Rate Control Point characteristic must contain a single 392 // byte with the value 0x01. 393 if (value.size() != 1 || value[0] != 0x01) { 394 bool status; 395 gatt_->SendResponse(server_if_, device_address, request_id, 396 bluetooth::GATT_ERROR_OUT_OF_RANGE, offset, dummy, 397 &status); 398 return Status::ok(); 399 } 400 401 LOG(INFO) << "Heart Rate Control Point written; Enery Expended reset!"; 402 energy_expended_ = 0; 403 404 if (!need_response) return Status::ok(); 405 406 bool status; 407 gatt_->SendResponse(server_if_, device_address, request_id, 408 bluetooth::GATT_ERROR_NONE, offset, dummy, &status); 409 return Status::ok(); 410 } 411 412 Status HeartRateServer::OnDescriptorWriteRequest( 413 const String16& device_address, int request_id, int offset, 414 bool is_prepare_write, bool need_response, 415 const std::vector<uint8_t>& value, int handle) { 416 std::lock_guard<std::mutex> lock(mutex_); 417 418 std::vector<uint8_t> dummy; 419 420 // This is where we handle an incoming characteristic write. The Heart Rate 421 // service doesn't really support prepared writes, so we just reject them to 422 // keep things simple. 423 if (is_prepare_write) { 424 bool status; 425 gatt_->SendResponse(server_if_, device_address, request_id, 426 bluetooth::GATT_ERROR_REQUEST_NOT_SUPPORTED, offset, 427 dummy, &status); 428 return Status::ok(); 429 } 430 431 // CCC is the only descriptor we have. 432 CHECK(handle == hr_measurement_cccd_handle_); 433 434 // CCC must contain 2 bytes for a 16-bit value in little-endian. The only 435 // allowed values here are 0x0000 and 0x0001. 436 if (value.size() != 2 || value[1] != 0x00 || value[0] > 0x01) { 437 bool status; 438 gatt_->SendResponse(server_if_, device_address, request_id, 439 bluetooth::GATT_ERROR_CCCD_IMPROPERLY_CONFIGURED, 440 offset, dummy, &status); 441 return Status::ok(); 442 } 443 444 device_ccc_map_[std::string(String8(device_address).string())] = value[0]; 445 446 LOG(INFO) << "Heart Rate Measurement CCC written - device: " << device_address 447 << " value: " << (int)value[0]; 448 449 // Start the simulation. 450 if (!simulation_started_ && value[0]) { 451 simulation_started_ = true; 452 ScheduleNextMeasurement(); 453 } 454 455 if (!need_response) return Status::ok(); 456 457 bool status; 458 gatt_->SendResponse(server_if_, device_address, request_id, 459 bluetooth::GATT_ERROR_NONE, offset, dummy, &status); 460 return Status::ok(); 461 } 462 463 Status HeartRateServer::OnExecuteWriteRequest(const String16& device_address, 464 int request_id, 465 bool /* is_execute */) { 466 // We don't support Prepared Writes so, simply return Not Supported error. 467 std::vector<uint8_t> dummy; 468 bool status; 469 gatt_->SendResponse(server_if_, device_address, request_id, 470 bluetooth::GATT_ERROR_REQUEST_NOT_SUPPORTED, 0, dummy, 471 &status); 472 473 return Status::ok(); 474 } 475 476 Status HeartRateServer::OnNotificationSent(const String16& device_address, 477 int status) { 478 LOG(INFO) << "Notification was sent - device: " << device_address 479 << " status: " << status; 480 std::lock_guard<std::mutex> lock(mutex_); 481 pending_notification_map_[std::string(String8(device_address).string())] = 482 false; 483 484 return Status::ok(); 485 } 486 487 Status HeartRateServer::OnConnectionStateChanged(const String16& device_address, 488 bool connected) { 489 LOG(INFO) << "Connection state changed - device: " << device_address 490 << " connected: " << (connected ? "true" : "false"); 491 return Status::ok(); 492 } 493 } // namespace heart_rate 494