1 /*
2  * Copyright 2020 The Android Open Source Project
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 #include "le_advertiser.h"
18 
19 using namespace bluetooth::hci;
20 
21 namespace test_vendor_lib {
Initialize(AddressWithType address,AddressWithType peer_address,LeScanningFilterPolicy filter_policy,model::packets::AdvertisementType type,const std::vector<uint8_t> & advertisement,const std::vector<uint8_t> & scan_response,std::chrono::steady_clock::duration interval)22 void LeAdvertiser::Initialize(AddressWithType address,
23                               AddressWithType peer_address,
24                               LeScanningFilterPolicy filter_policy,
25                               model::packets::AdvertisementType type,
26                               const std::vector<uint8_t>& advertisement,
27                               const std::vector<uint8_t>& scan_response,
28                               std::chrono::steady_clock::duration interval) {
29   address_ = address;
30   peer_address_ = peer_address;
31   filter_policy_ = filter_policy;
32   type_ = type;
33   advertisement_ = advertisement;
34   scan_response_ = scan_response;
35   interval_ = interval;
36 }
37 
InitializeExtended(AddressType address_type,AddressWithType peer_address,LeScanningFilterPolicy filter_policy,model::packets::AdvertisementType type,std::chrono::steady_clock::duration interval)38 void LeAdvertiser::InitializeExtended(
39     AddressType address_type, AddressWithType peer_address,
40     LeScanningFilterPolicy filter_policy,
41     model::packets::AdvertisementType type,
42     std::chrono::steady_clock::duration interval) {
43   address_ = AddressWithType(address_.GetAddress(), address_type);
44   peer_address_ = peer_address;
45   filter_policy_ = filter_policy;
46   type_ = type;
47   interval_ = interval;
48   LOG_INFO("%s -> %s type = %hhx interval = %d ms", address_.ToString().c_str(),
49            peer_address.ToString().c_str(), type_,
50            static_cast<int>(interval_.count()));
51 }
52 
Clear()53 void LeAdvertiser::Clear() {
54   address_ = AddressWithType{};
55   peer_address_ = AddressWithType{};
56   filter_policy_ = LeScanningFilterPolicy::ACCEPT_ALL;
57   type_ = model::packets::AdvertisementType::ADV_IND;
58   advertisement_.clear();
59   scan_response_.clear();
60   interval_ = std::chrono::milliseconds(0);
61   enabled_ = false;
62 }
63 
SetAddress(Address address)64 void LeAdvertiser::SetAddress(Address address) {
65   LOG_INFO("set address %s", address_.ToString().c_str());
66   address_ = AddressWithType(address, address_.GetAddressType());
67 }
68 
GetAddress() const69 AddressWithType LeAdvertiser::GetAddress() const { return address_; }
70 
SetData(const std::vector<uint8_t> & data)71 void LeAdvertiser::SetData(const std::vector<uint8_t>& data) {
72   advertisement_ = data;
73 }
74 
Enable()75 void LeAdvertiser::Enable() {
76   enabled_ = true;
77   last_le_advertisement_ = std::chrono::steady_clock::now() - interval_;
78   LOG_INFO("%s -> %s type = %hhx ad length %zu, scan length %zu",
79            address_.ToString().c_str(), peer_address_.ToString().c_str(), type_,
80            advertisement_.size(), scan_response_.size());
81 }
82 
EnableExtended(std::chrono::steady_clock::duration duration)83 void LeAdvertiser::EnableExtended(
84     std::chrono::steady_clock::duration duration) {
85   last_le_advertisement_ = std::chrono::steady_clock::now();
86   if (duration != std::chrono::milliseconds(0)) {
87     ending_time_ = std::chrono::steady_clock::now() + duration;
88   }
89   enabled_ = true;
90   LOG_INFO("%s -> %s type = %hhx ad length %zu, scan length %zu",
91            address_.ToString().c_str(), peer_address_.ToString().c_str(), type_,
92            advertisement_.size(), scan_response_.size());
93 }
94 
Disable()95 void LeAdvertiser::Disable() { enabled_ = false; }
96 
IsEnabled() const97 bool LeAdvertiser::IsEnabled() const { return enabled_; }
98 
99 std::unique_ptr<model::packets::LeAdvertisementBuilder>
GetAdvertisement(std::chrono::steady_clock::time_point now)100 LeAdvertiser::GetAdvertisement(std::chrono::steady_clock::time_point now) {
101   if (!enabled_) {
102     return nullptr;
103   }
104 
105   if (now - last_le_advertisement_ < interval_) {
106     return nullptr;
107   }
108 
109   if (last_le_advertisement_ < ending_time_ && ending_time_ < now) {
110     enabled_ = false;
111     return nullptr;
112   }
113 
114   last_le_advertisement_ = now;
115   return model::packets::LeAdvertisementBuilder::Create(
116       address_.GetAddress(), peer_address_.GetAddress(),
117       static_cast<model::packets::AddressType>(address_.GetAddressType()),
118       type_, advertisement_);
119 }
120 
121 std::unique_ptr<model::packets::LeScanResponseBuilder>
GetScanResponse(bluetooth::hci::Address scanned,bluetooth::hci::Address scanner)122 LeAdvertiser::GetScanResponse(bluetooth::hci::Address scanned,
123                               bluetooth::hci::Address scanner) {
124   if (scanned != address_.GetAddress() || !enabled_ || scan_response_.empty()) {
125     return nullptr;
126   }
127   switch (filter_policy_) {
128     case bluetooth::hci::LeScanningFilterPolicy::
129         CONNECT_LIST_AND_INITIATORS_IDENTITY:
130     case bluetooth::hci::LeScanningFilterPolicy::CONNECT_LIST_ONLY:
131       LOG_WARN("ScanResponses don't handle connect list filters");
132       return nullptr;
133     case bluetooth::hci::LeScanningFilterPolicy::CHECK_INITIATORS_IDENTITY:
134       if (scanner != peer_address_.GetAddress()) {
135         return nullptr;
136       }
137       break;
138     case bluetooth::hci::LeScanningFilterPolicy::ACCEPT_ALL:
139       break;
140   }
141   return model::packets::LeScanResponseBuilder::Create(
142       address_.GetAddress(), peer_address_.GetAddress(),
143       static_cast<model::packets::AddressType>(address_.GetAddressType()),
144       model::packets::AdvertisementType::SCAN_RESPONSE, scan_response_);
145 }
146 
147 }  // namespace test_vendor_lib
148