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