1 /*
2  * Copyright (C) 2016 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 <android/log.h>
18 
19 #include <android/hardware/wifi/1.3/IWifiChip.h>
20 #include <android/hardware/wifi/1.5/IWifiChip.h>
21 #include <wifi_system/interface_tool.h>
22 
23 #include "wifi_hidl_call_util.h"
24 #include "wifi_hidl_test_utils.h"
25 
26 using ::android::hardware::wifi::V1_0::IWifi;
27 using ::android::hardware::wifi::V1_0::IWifiApIface;
28 using ::android::hardware::wifi::V1_0::IWifiChip;
29 using ::android::hardware::wifi::V1_0::IWifiIface;
30 using ::android::hardware::wifi::V1_0::IWifiNanIface;
31 using ::android::hardware::wifi::V1_0::IWifiP2pIface;
32 using ::android::hardware::wifi::V1_0::IWifiRttController;
33 using ::android::hardware::wifi::V1_0::IWifiStaIface;
34 using ::android::hardware::wifi::V1_0::ChipModeId;
35 using ::android::hardware::wifi::V1_0::ChipId;
36 using ::android::hardware::wifi::V1_0::IfaceType;
37 using ::android::hardware::wifi::V1_0::WifiStatus;
38 using ::android::hardware::wifi::V1_0::WifiStatusCode;
39 using ::android::sp;
40 using ::android::hardware::hidl_string;
41 using ::android::hardware::hidl_vec;
42 using ::android::wifi_system::InterfaceTool;
43 
44 namespace {
45 constexpr uint32_t kHalStartRetryMaxCount = 5;
46 constexpr uint32_t kHalStartRetryIntervalInMs = 2;
47 
findAnyModeSupportingIfaceType(IfaceType desired_type,const std::vector<IWifiChip::ChipMode> & modes,ChipModeId * mode_id)48 bool findAnyModeSupportingIfaceType(
49     IfaceType desired_type, const std::vector<IWifiChip::ChipMode>& modes,
50     ChipModeId* mode_id) {
51     for (const auto& mode : modes) {
52         for (const auto& combination : mode.availableCombinations) {
53             for (const auto& iface_limit : combination.limits) {
54                 const auto& iface_types = iface_limit.types;
55                 if (std::find(iface_types.begin(), iface_types.end(),
56                               desired_type) != iface_types.end()) {
57                     *mode_id = mode.id;
58                     return true;
59                 }
60             }
61         }
62     }
63     return false;
64 }
65 
configureChipToSupportIfaceTypeInternal(const sp<IWifiChip> & wifi_chip,IfaceType type,ChipModeId * configured_mode_id)66 bool configureChipToSupportIfaceTypeInternal(const sp<IWifiChip>& wifi_chip,
67                                              IfaceType type,
68                                              ChipModeId* configured_mode_id) {
69     if (!configured_mode_id || !wifi_chip.get()) {
70         return false;
71     }
72     const auto& status_and_modes = HIDL_INVOKE(wifi_chip, getAvailableModes);
73     if (status_and_modes.first.code != WifiStatusCode::SUCCESS) {
74         return false;
75     }
76     if (!findAnyModeSupportingIfaceType(type, status_and_modes.second,
77                                         configured_mode_id)) {
78         return false;
79     }
80     if (HIDL_INVOKE(wifi_chip, configureChip, *configured_mode_id).code !=
81         WifiStatusCode::SUCCESS) {
82         return false;
83     }
84     return true;
85 }
86 
configureChipToSupportIfaceTypeInternal(const sp<IWifiChip> & wifi_chip,IfaceType type)87 bool configureChipToSupportIfaceTypeInternal(const sp<IWifiChip>& wifi_chip,
88                                              IfaceType type) {
89     ChipModeId mode_id;
90     return configureChipToSupportIfaceTypeInternal(wifi_chip, type, &mode_id);
91 }
92 
doesChipSupportIfaceTypeInternal(const sp<IWifiChip> & wifi_chip,IfaceType type)93 bool doesChipSupportIfaceTypeInternal(const sp<IWifiChip>& wifi_chip,
94                                          IfaceType type) {
95     ChipModeId mode_id;
96     if (!wifi_chip.get()) {
97         return false;
98     }
99     const auto& status_and_modes = HIDL_INVOKE(wifi_chip, getAvailableModes);
100     if (status_and_modes.first.code != WifiStatusCode::SUCCESS) {
101         return false;
102     }
103     if (!findAnyModeSupportingIfaceType(type, status_and_modes.second,
104                                         &mode_id)) {
105         return false;
106     }
107 
108     return true;
109 }
110 }  // namespace
111 
getWifi(const std::string & instance_name)112 sp<IWifi> getWifi(const std::string& instance_name) {
113     return IWifi::getService(instance_name);
114 }
115 
getWifiChip(const std::string & instance_name)116 sp<IWifiChip> getWifiChip(const std::string& instance_name) {
117     sp<IWifi> wifi = getWifi(instance_name);
118     if (!wifi.get()) {
119         return nullptr;
120     }
121     uint32_t retry_count = 0;
122     auto status = HIDL_INVOKE(wifi, start);
123     while (retry_count < kHalStartRetryMaxCount &&
124            status.code == WifiStatusCode::ERROR_NOT_AVAILABLE) {
125         retry_count++;
126         usleep(kHalStartRetryIntervalInMs * 1000);
127         status = HIDL_INVOKE(wifi, start);
128     }
129     if (status.code != WifiStatusCode::SUCCESS) {
130         return nullptr;
131     }
132     const auto& status_and_chip_ids = HIDL_INVOKE(wifi, getChipIds);
133     const auto& chip_ids = status_and_chip_ids.second;
134     if (status_and_chip_ids.first.code != WifiStatusCode::SUCCESS ||
135         chip_ids.size() < 1) {
136         return nullptr;
137     }
138     const auto& status_and_chip = HIDL_INVOKE(wifi, getChip, chip_ids[0]);
139     if (status_and_chip.first.code != WifiStatusCode::SUCCESS) {
140         return nullptr;
141     }
142     return status_and_chip.second;
143 }
144 
setIfaceUp(const sp<IWifiIface> & iface)145 void setIfaceUp(const sp<IWifiIface>& iface) {
146     // Set the iface up before retrurning the object.
147     const auto& status_and_name = HIDL_INVOKE(iface, getName);
148     if (status_and_name.first.code == WifiStatusCode::SUCCESS) {
149         const auto& iface_name = status_and_name.second;
150         InterfaceTool iface_tool;
151         iface_tool.SetUpState(iface_name.c_str(), true);
152     }
153 }
154 
getWifiApIface(const std::string & instance_name)155 sp<IWifiApIface> getWifiApIface(const std::string& instance_name) {
156     sp<IWifiChip> wifi_chip = getWifiChip(instance_name);
157     if (!wifi_chip.get()) {
158         return nullptr;
159     }
160     if (!configureChipToSupportIfaceTypeInternal(wifi_chip, IfaceType::AP)) {
161         return nullptr;
162     }
163     const auto& status_and_iface = HIDL_INVOKE(wifi_chip, createApIface);
164     if (status_and_iface.first.code != WifiStatusCode::SUCCESS) {
165         return nullptr;
166     }
167     setIfaceUp(status_and_iface.second);
168     return status_and_iface.second;
169 }
170 
getWifiNanIface(const std::string & instance_name)171 sp<IWifiNanIface> getWifiNanIface(const std::string& instance_name) {
172     sp<IWifiChip> wifi_chip = getWifiChip(instance_name);
173     if (!wifi_chip.get()) {
174         return nullptr;
175     }
176     if (!configureChipToSupportIfaceTypeInternal(wifi_chip, IfaceType::NAN)) {
177         return nullptr;
178     }
179     const auto& status_and_iface = HIDL_INVOKE(wifi_chip, createNanIface);
180     if (status_and_iface.first.code != WifiStatusCode::SUCCESS) {
181         return nullptr;
182     }
183     setIfaceUp(status_and_iface.second);
184     return status_and_iface.second;
185 }
186 
getWifiP2pIface(const std::string & instance_name)187 sp<IWifiP2pIface> getWifiP2pIface(const std::string& instance_name) {
188     sp<IWifiChip> wifi_chip = getWifiChip(instance_name);
189     if (!wifi_chip.get()) {
190         return nullptr;
191     }
192     if (!configureChipToSupportIfaceTypeInternal(wifi_chip, IfaceType::P2P)) {
193         return nullptr;
194     }
195     const auto& status_and_iface = HIDL_INVOKE(wifi_chip, createP2pIface);
196     if (status_and_iface.first.code != WifiStatusCode::SUCCESS) {
197         return nullptr;
198     }
199     setIfaceUp(status_and_iface.second);
200     return status_and_iface.second;
201 }
202 
getWifiStaIface(const std::string & instance_name)203 sp<IWifiStaIface> getWifiStaIface(const std::string& instance_name) {
204     sp<IWifiChip> wifi_chip = getWifiChip(instance_name);
205     if (!wifi_chip.get()) {
206         return nullptr;
207     }
208     if (!configureChipToSupportIfaceTypeInternal(wifi_chip, IfaceType::STA)) {
209         return nullptr;
210     }
211     const auto& status_and_iface = HIDL_INVOKE(wifi_chip, createStaIface);
212     if (status_and_iface.first.code != WifiStatusCode::SUCCESS) {
213         return nullptr;
214     }
215     setIfaceUp(status_and_iface.second);
216     return status_and_iface.second;
217 }
218 
configureChipToSupportIfaceType(const sp<IWifiChip> & wifi_chip,IfaceType type,ChipModeId * configured_mode_id)219 bool configureChipToSupportIfaceType(const sp<IWifiChip>& wifi_chip,
220                                      IfaceType type,
221                                      ChipModeId* configured_mode_id) {
222     return configureChipToSupportIfaceTypeInternal(wifi_chip, type,
223                                                    configured_mode_id);
224 }
225 
doesChipSupportIfaceType(const sp<IWifiChip> & wifi_chip,IfaceType type)226 bool doesChipSupportIfaceType(const sp<IWifiChip>& wifi_chip,
227                                      IfaceType type) {
228     return doesChipSupportIfaceTypeInternal(wifi_chip, type);
229 }
230 
stopWifi(const std::string & instance_name)231 void stopWifi(const std::string& instance_name) {
232     sp<IWifi> wifi = IWifi::getService(instance_name);
233     ASSERT_NE(wifi, nullptr);
234     HIDL_INVOKE(wifi, stop);
235 }
236 
getChipCapabilitiesLatest(const sp<IWifiChip> & wifi_chip)237 uint32_t getChipCapabilitiesLatest(const sp<IWifiChip>& wifi_chip) {
238     sp<::android::hardware::wifi::V1_5::IWifiChip> chip_converted15 =
239         ::android::hardware::wifi::V1_5::IWifiChip::castFrom(wifi_chip);
240     sp<::android::hardware::wifi::V1_3::IWifiChip> chip_converted13 =
241         ::android::hardware::wifi::V1_3::IWifiChip::castFrom(wifi_chip);
242     std::pair<WifiStatus, uint32_t> status_and_caps;
243 
244     if (chip_converted15 != nullptr) {
245         // Call the newer HAL 1.5 version
246         status_and_caps = HIDL_INVOKE(chip_converted15, getCapabilities_1_5);
247     } else if (chip_converted13 != nullptr) {
248         // Call the newer HAL 1.3 version
249         status_and_caps = HIDL_INVOKE(chip_converted13, getCapabilities_1_3);
250     } else {
251         status_and_caps = HIDL_INVOKE(wifi_chip, getCapabilities);
252     }
253 
254     EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
255     return status_and_caps.second;
256 }
257