1 /*
2  * Copyright 2018 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 #pragma once
18 
19 #include <chrono>      // for milliseconds
20 #include <cstddef>     // for size_t
21 #include <functional>  // for function
22 #include <map>
23 #include <memory>  // for shared_ptr
24 #include <optional>
25 #include <string>  // for string
26 #include <vector>  // for vector
27 
28 #include "hci/address.h"                // for Address
29 #include "model/devices/hci_device.h"   // for HciDevice
30 #include "model/setup/async_manager.h"  // for AsyncUserId, AsyncTaskId
31 #include "phy.h"                        // for Phy, Phy::Type
32 #include "phy_layer.h"
33 #include "rootcanal/configuration.pb.h"
34 
35 namespace rootcanal {
36 class Device;
37 
38 using ::bluetooth::hci::Address;
39 
40 class TestModel {
41 public:
42   TestModel(std::function<AsyncUserId()> get_user_id,
43             std::function<AsyncTaskId(AsyncUserId, std::chrono::milliseconds, const TaskCallback&)>
44                     event_scheduler,
45             std::function<AsyncTaskId(AsyncUserId, std::chrono::milliseconds,
46                                       std::chrono::milliseconds, const TaskCallback&)>
47                     periodic_event_scheduler,
48             std::function<void(AsyncUserId)> cancel_tasks_from_user,
49             std::function<void(AsyncTaskId)> cancel,
50             std::function<std::shared_ptr<Device>(const std::string&, int, Phy::Type)>
51                     connect_to_remote,
52             std::array<uint8_t, 5> bluetooth_address_prefix = {0xda, 0x4c, 0x10, 0xde, 0x17});
53   virtual ~TestModel();
54 
55   TestModel(TestModel& model) = delete;
56   TestModel& operator=(const TestModel& model) = delete;
57 
SetReuseDeviceAddresses(bool reuse_device_addresses)58   void SetReuseDeviceAddresses(bool reuse_device_addresses) {
59     reuse_device_addresses_ = reuse_device_addresses;
60   }
61 
62   // Allow derived classes to use custom phy layer.
63   virtual std::unique_ptr<PhyLayer> CreatePhyLayer(PhyLayer::Identifier id, Phy::Type type);
64 
65   // Allow derived classes to use custom phy devices.
66   virtual std::shared_ptr<PhyDevice> CreatePhyDevice(std::string type,
67                                                      std::shared_ptr<Device> device);
68 
69   // Test model commands
70 
71   PhyDevice::Identifier AddDevice(std::shared_ptr<Device> device);
72   void RemoveDevice(PhyDevice::Identifier id);
73   PhyLayer::Identifier AddPhy(Phy::Type type);
74   void RemovePhy(PhyLayer::Identifier id);
75   void AddDeviceToPhy(PhyDevice::Identifier device_id, PhyLayer::Identifier phy_id);
76   void RemoveDeviceFromPhy(PhyDevice::Identifier device_id, PhyLayer::Identifier phy_id);
77 
78   // Runtime implementation.
79 
80   // Handle incoming remote connections
81   void AddLinkLayerConnection(std::shared_ptr<Device> dev, Phy::Type phy_type);
82   // Add an HCI device, return its index
83   PhyDevice::Identifier AddHciConnection(std::shared_ptr<HciDevice> dev,
84                                          std::optional<Address> address = {});
85   // Handle closed remote connections (both hci & link layer)
86   void OnConnectionClosed(PhyDevice::Identifier device_id, AsyncUserId user_id);
87 
88   // Connect to a remote device
89   void AddRemote(const std::string& server, int port, Phy::Type phy_type);
90 
91   // Set the device's Bluetooth address
92   void SetDeviceAddress(PhyDevice::Identifier device_id, Address device_address);
93 
94   void SetDeviceConfiguration(PhyDevice::Identifier device_id,
95                               rootcanal::configuration::Controller const& configuration);
96 
97   // Let devices know about the passage of time
98   void Tick();
99   void StartTimer();
100   void StopTimer();
101   void SetTimerPeriod(std::chrono::milliseconds new_period);
102 
103   // List the devices that the test knows about
104   const std::string& List();
105 
106   // Clear all devices and phys.
107   void Reset();
108 
109 private:
110   Address GenerateBluetoothAddress(uint32_t device_id) const;
111 
112   std::map<PhyLayer::Identifier, std::shared_ptr<PhyLayer>> phy_layers_;
113   std::map<PhyDevice::Identifier, std::shared_ptr<PhyDevice>> phy_devices_;
114   std::string list_string_;
115 
116   // Generator for device identifiers.
117   bool reuse_device_addresses_{true};
118 
119   // Prefix used to generate public device addresses for hosts
120   // connecting over TCP.
121   std::array<uint8_t, 5> bluetooth_address_prefix_;
122 
123   // Callbacks to schedule tasks.
124   std::function<AsyncUserId()> get_user_id_;
125   std::function<AsyncTaskId(AsyncUserId, std::chrono::milliseconds, const TaskCallback&)>
126           schedule_task_;
127   std::function<AsyncTaskId(AsyncUserId, std::chrono::milliseconds, std::chrono::milliseconds,
128                             const TaskCallback&)>
129           schedule_periodic_task_;
130   std::function<void(AsyncTaskId)> cancel_task_;
131   std::function<void(AsyncUserId)> cancel_tasks_from_user_;
132   std::function<std::shared_ptr<Device>(const std::string&, int, Phy::Type)> connect_to_remote_;
133 
134   AsyncUserId model_user_id_;
135   AsyncTaskId timer_tick_task_{kInvalidTaskId};
136   std::chrono::milliseconds timer_period_{};
137 };
138 
139 }  // namespace rootcanal
140