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