blob: 27dc2d105d6876dc79d9ffd92bf876f2c2b52684 [file] [log] [blame]
/*
* Copyright 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "broken_adv.h"
#include "model/setup/device_boutique.h"
using std::vector;
namespace test_vendor_lib {
bool BrokenAdv::registered_ = DeviceBoutique::Register("broken_adv", &BrokenAdv::Create);
BrokenAdv::BrokenAdv() {
advertising_interval_ms_ = std::chrono::milliseconds(1280);
properties_.SetLeAdvertisementType(0x03 /* NON_CONNECT */);
constant_adv_data_ = {
0x02, // Length
0x01, // TYPE_FLAG
0x4 | 0x2, // BREDR_NOT_SPT | GEN_DISC_FLAG
0x13, // Length
0x09, // TYPE_NAME_CMPL
'g', 'D', 'e', 'v', 'i', 'c', 'e', '-', 'b', 'r', 'o', 'k', 'e', 'n', '_', 'a', 'd', 'v',
};
properties_.SetLeAdvertisement(constant_adv_data_);
properties_.SetLeScanResponse({0x0b, // Length
0x08, // TYPE_NAME_SHORT
'b', 'r', 'o', 'k', 'e', 'n', 'n', 'e', 's', 's'});
properties_.SetExtendedInquiryData({0x07, // Length
0x09, // TYPE_NAME_COMPLETE
'B', 'R', '0', 'K', '3', 'N'});
properties_.SetPageScanRepetitionMode(0);
page_scan_delay_ms_ = std::chrono::milliseconds(600);
}
void BrokenAdv::Initialize(const vector<std::string>& args) {
if (args.size() < 2) return;
Address addr{};
if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
if (args.size() < 3) return;
SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
}
// Mostly return the correct length
static uint8_t random_length(size_t bytes_remaining) {
uint32_t randomness = rand();
switch ((randomness & 0xf000000) >> 24) {
case (0):
return bytes_remaining + (randomness & 0xff);
case (1):
return bytes_remaining - (randomness & 0xff);
case (2):
return bytes_remaining + (randomness & 0xf);
case (3):
return bytes_remaining - (randomness & 0xf);
case (5):
case (6):
return bytes_remaining + (randomness & 0x3);
case (7):
case (8):
return bytes_remaining - (randomness & 0x3);
default:
return bytes_remaining;
}
}
static size_t random_adv_type() {
uint32_t randomness = rand();
switch ((randomness & 0xf000000) >> 24) {
case (0):
return 0xff; // TYPE_MANUFACTURER_SPECIFIC
case (1):
return (randomness & 0xff);
default:
return (randomness & 0x1f);
}
}
static size_t random_data_length(size_t length, size_t bytes_remaining) {
uint32_t randomness = rand();
switch ((randomness & 0xf000000) >> 24) {
case (0):
return bytes_remaining;
case (1):
return (length + (randomness & 0xff)) % bytes_remaining;
default:
return (length <= bytes_remaining ? length : bytes_remaining);
}
}
static void RandomizeAdvertisement(vector<uint8_t>& ad, size_t max) {
uint8_t length = random_length(max);
uint8_t data_length = random_data_length(length, max);
ad.push_back(random_adv_type());
ad.push_back(length);
for (size_t i = 0; i < data_length; i++) ad.push_back(rand() & 0xff);
}
void BrokenAdv::UpdateAdvertisement() {
std::vector<uint8_t> adv_data;
for (size_t i = 0; i < constant_adv_data_.size(); i++) adv_data.push_back(constant_adv_data_[i]);
RandomizeAdvertisement(adv_data, 31 - adv_data.size());
properties_.SetLeAdvertisement(adv_data);
adv_data.clear();
RandomizeAdvertisement(adv_data, 31);
properties_.SetLeScanResponse(adv_data);
Address le_addr = properties_.GetLeAddress();
uint8_t* low_order_byte = (uint8_t*)(&le_addr);
*low_order_byte += 1;
properties_.SetLeAddress(le_addr);
}
std::string BrokenAdv::ToString() const {
std::string str =
Device::ToString() + std::string(": Interval = ") + std::to_string(advertising_interval_ms_.count());
return str;
}
void BrokenAdv::UpdatePageScan() {
RandomizeAdvertisement(constant_scan_data_, 31);
Address page_addr = properties_.GetAddress();
uint8_t* low_order_byte = (uint8_t*)(&page_addr);
*low_order_byte += 1;
properties_.SetAddress(page_addr);
}
void BrokenAdv::TimerTick() {
UpdatePageScan();
UpdateAdvertisement();
}
} // namespace test_vendor_lib