blob: adba054e2d74ebe1b372eb6ef369dac45c12fee0 [file] [log] [blame]
Roshan Pius3c4e8a32016-10-03 14:53:58 -07001/*
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
Roshan Pius3c4e8a32016-10-03 14:53:58 -070017#include <android-base/logging.h>
Roshan Pius9377a0d2017-10-06 13:18:54 -070018#include <cutils/properties.h>
Roshan Pius3c4e8a32016-10-03 14:53:58 -070019
Roshan Pius3c868522016-10-27 12:43:49 -070020#include "hidl_return_util.h"
Roshan Piuse2d0ab52016-12-05 15:24:20 -080021#include "hidl_struct_util.h"
Roshan Pius3c868522016-10-27 12:43:49 -070022#include "wifi_chip.h"
Roshan Pius5c055462016-10-11 08:27:27 -070023#include "wifi_status_util.h"
Roshan Pius3c4e8a32016-10-03 14:53:58 -070024
Roshan Pius35d958c2016-10-06 16:47:38 -070025namespace {
Roshan Pius35d958c2016-10-06 16:47:38 -070026using android::hardware::hidl_string;
Roshan Piusabcf78f2017-10-06 16:30:38 -070027using android::hardware::hidl_vec;
Roshan Pius2c06a3f2016-12-15 17:51:40 -080028using android::hardware::wifi::V1_0::ChipModeId;
Roshan Pius52947fb2016-11-18 11:38:07 -080029using android::hardware::wifi::V1_0::IfaceType;
Roshan Pius675609b2017-10-31 14:24:58 -070030using android::hardware::wifi::V1_0::IWifiChip;
Roshan Piusabcf78f2017-10-06 16:30:38 -070031using android::sp;
Roshan Pius52947fb2016-11-18 11:38:07 -080032
Roshan Pius2c06a3f2016-12-15 17:51:40 -080033constexpr ChipModeId kInvalidModeId = UINT32_MAX;
Roshan Piuscc338202017-11-02 13:54:09 -070034// These mode ID's should be unique (even across combo versions). Refer to
35// handleChipConfiguration() for it's usage.
36// Mode ID's for V1
37constexpr ChipModeId kV1StaChipModeId = 0;
38constexpr ChipModeId kV1ApChipModeId = 1;
39// Mode ID for V2
40constexpr ChipModeId kV2ChipModeId = 2;
Roshan Pius35d958c2016-10-06 16:47:38 -070041
Roshan Pius35d958c2016-10-06 16:47:38 -070042template <typename Iface>
Roshan Pius675609b2017-10-31 14:24:58 -070043void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
44 iface->invalidate();
45 ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface),
46 ifaces.end());
47}
48
49template <typename Iface>
50void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) {
51 for (const auto& iface : ifaces) {
Roshan Piusabcf78f2017-10-06 16:30:38 -070052 iface->invalidate();
Roshan Piusabcf78f2017-10-06 16:30:38 -070053 }
Roshan Pius675609b2017-10-31 14:24:58 -070054 ifaces.clear();
55}
56
57template <typename Iface>
58std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) {
59 std::vector<hidl_string> names;
60 for (const auto& iface : ifaces) {
61 names.emplace_back(iface->getName());
62 }
63 return names;
64}
65
66template <typename Iface>
67sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces,
68 const std::string& name) {
69 std::vector<hidl_string> names;
70 for (const auto& iface : ifaces) {
71 if (name == iface->getName()) {
72 return iface;
73 }
74 }
75 return nullptr;
Roshan Pius35d958c2016-10-06 16:47:38 -070076}
Roshan Pius9377a0d2017-10-06 13:18:54 -070077
78std::string getWlan0IfaceName() {
Roshan Piusabcf78f2017-10-06 16:30:38 -070079 std::array<char, PROPERTY_VALUE_MAX> buffer;
80 property_get("wifi.interface", buffer.data(), "wlan0");
81 return buffer.data();
Roshan Pius9377a0d2017-10-06 13:18:54 -070082}
83
Roshan Pius9377a0d2017-10-06 13:18:54 -070084std::string getWlan1IfaceName() {
Roshan Pius8e3c7ef2017-11-03 09:43:08 -070085 std::array<char, PROPERTY_VALUE_MAX> buffer;
86 property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
87 return buffer.data();
Roshan Pius9377a0d2017-10-06 13:18:54 -070088}
Roshan Pius9377a0d2017-10-06 13:18:54 -070089
90std::string getP2pIfaceName() {
Roshan Piusabcf78f2017-10-06 16:30:38 -070091 std::array<char, PROPERTY_VALUE_MAX> buffer;
92 property_get("wifi.direct.interface", buffer.data(), "p2p0");
93 return buffer.data();
Roshan Pius9377a0d2017-10-06 13:18:54 -070094}
95
Roshan Piusabcf78f2017-10-06 16:30:38 -070096} // namespace
Roshan Pius35d958c2016-10-06 16:47:38 -070097
Roshan Pius3c4e8a32016-10-03 14:53:58 -070098namespace android {
99namespace hardware {
100namespace wifi {
Etan Cohen6ce50902017-09-14 07:30:57 -0700101namespace V1_2 {
Roshan Pius79a99752016-10-04 13:03:58 -0700102namespace implementation {
Roshan Pius3c868522016-10-27 12:43:49 -0700103using hidl_return_util::validateAndCall;
Roshan Piusba38d9c2017-12-08 07:32:08 -0800104using hidl_return_util::validateAndCallWithLock;
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700105
Roshan Pius52947fb2016-11-18 11:38:07 -0800106WifiChip::WifiChip(
Roshan Piusabcf78f2017-10-06 16:30:38 -0700107 ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
Roshan Pius200a17d2017-11-01 13:03:35 -0700108 const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
109 const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
Roshan Pius52947fb2016-11-18 11:38:07 -0800110 : chip_id_(chip_id),
111 legacy_hal_(legacy_hal),
112 mode_controller_(mode_controller),
Roshan Pius200a17d2017-11-01 13:03:35 -0700113 feature_flags_(feature_flags),
Roshan Pius52947fb2016-11-18 11:38:07 -0800114 is_valid_(true),
Roshan Pius48185b22016-12-15 19:10:30 -0800115 current_mode_id_(kInvalidModeId),
Roshan Piuscc338202017-11-02 13:54:09 -0700116 debug_ring_buffer_cb_registered_(false) {
117 populateModes();
118}
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700119
Roshan Piusaabe5752016-09-29 09:03:59 -0700120void WifiChip::invalidate() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700121 invalidateAndRemoveAllIfaces();
122 legacy_hal_.reset();
123 event_cb_handler_.invalidate();
124 is_valid_ = false;
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700125}
126
Roshan Piusabcf78f2017-10-06 16:30:38 -0700127bool WifiChip::isValid() { return is_valid_; }
Roshan Pius3c868522016-10-27 12:43:49 -0700128
Roshan Piusd37341f2017-01-31 13:13:28 -0800129std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700130 return event_cb_handler_.getCallbacks();
Roshan Pius203cb032016-12-14 17:41:20 -0800131}
132
Roshan Pius5c055462016-10-11 08:27:27 -0700133Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700134 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
135 &WifiChip::getIdInternal, hidl_status_cb);
Roshan Piuscd566bd2016-10-10 08:03:42 -0700136}
137
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700138Return<void> WifiChip::registerEventCallback(
Roshan Pius5c055462016-10-11 08:27:27 -0700139 const sp<IWifiChipEventCallback>& event_callback,
140 registerEventCallback_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700141 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
142 &WifiChip::registerEventCallbackInternal,
143 hidl_status_cb, event_callback);
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700144}
145
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700146Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700147 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
148 &WifiChip::getCapabilitiesInternal, hidl_status_cb);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700149}
150
Roshan Pius5c055462016-10-11 08:27:27 -0700151Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700152 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
153 &WifiChip::getAvailableModesInternal,
154 hidl_status_cb);
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700155}
156
Roshan Pius2c06a3f2016-12-15 17:51:40 -0800157Return<void> WifiChip::configureChip(ChipModeId mode_id,
Roshan Pius5c055462016-10-11 08:27:27 -0700158 configureChip_cb hidl_status_cb) {
Roshan Piusba38d9c2017-12-08 07:32:08 -0800159 return validateAndCallWithLock(
160 this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
161 &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700162}
163
Roshan Pius5c055462016-10-11 08:27:27 -0700164Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700165 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
166 &WifiChip::getModeInternal, hidl_status_cb);
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700167}
168
Roshan Pius5c055462016-10-11 08:27:27 -0700169Return<void> WifiChip::requestChipDebugInfo(
170 requestChipDebugInfo_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700171 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
172 &WifiChip::requestChipDebugInfoInternal,
173 hidl_status_cb);
Roshan Pius5c055462016-10-11 08:27:27 -0700174}
175
176Return<void> WifiChip::requestDriverDebugDump(
177 requestDriverDebugDump_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700178 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
179 &WifiChip::requestDriverDebugDumpInternal,
180 hidl_status_cb);
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700181}
182
Roshan Pius5c055462016-10-11 08:27:27 -0700183Return<void> WifiChip::requestFirmwareDebugDump(
184 requestFirmwareDebugDump_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700185 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
186 &WifiChip::requestFirmwareDebugDumpInternal,
187 hidl_status_cb);
Roshan Pius3c4e8a32016-10-03 14:53:58 -0700188}
189
Roshan Pius5c055462016-10-11 08:27:27 -0700190Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700191 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
192 &WifiChip::createApIfaceInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700193}
194
Roshan Pius5c055462016-10-11 08:27:27 -0700195Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700196 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
197 &WifiChip::getApIfaceNamesInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700198}
199
Roshan Pius5c055462016-10-11 08:27:27 -0700200Return<void> WifiChip::getApIface(const hidl_string& ifname,
201 getApIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700202 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
203 &WifiChip::getApIfaceInternal, hidl_status_cb,
204 ifname);
Roshan Pius35d958c2016-10-06 16:47:38 -0700205}
206
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800207Return<void> WifiChip::removeApIface(const hidl_string& ifname,
208 removeApIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700209 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
210 &WifiChip::removeApIfaceInternal, hidl_status_cb,
211 ifname);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800212}
213
Roshan Pius5c055462016-10-11 08:27:27 -0700214Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700215 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
216 &WifiChip::createNanIfaceInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700217}
218
Roshan Pius5c055462016-10-11 08:27:27 -0700219Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700220 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
221 &WifiChip::getNanIfaceNamesInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700222}
223
224Return<void> WifiChip::getNanIface(const hidl_string& ifname,
Roshan Pius5c055462016-10-11 08:27:27 -0700225 getNanIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700226 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
227 &WifiChip::getNanIfaceInternal, hidl_status_cb,
228 ifname);
Roshan Pius35d958c2016-10-06 16:47:38 -0700229}
230
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800231Return<void> WifiChip::removeNanIface(const hidl_string& ifname,
232 removeNanIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700233 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
234 &WifiChip::removeNanIfaceInternal, hidl_status_cb,
235 ifname);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800236}
237
Roshan Pius5c055462016-10-11 08:27:27 -0700238Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700239 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
240 &WifiChip::createP2pIfaceInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700241}
242
Roshan Pius5c055462016-10-11 08:27:27 -0700243Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700244 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
245 &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700246}
247
248Return<void> WifiChip::getP2pIface(const hidl_string& ifname,
Roshan Pius5c055462016-10-11 08:27:27 -0700249 getP2pIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700250 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
251 &WifiChip::getP2pIfaceInternal, hidl_status_cb,
252 ifname);
Roshan Pius35d958c2016-10-06 16:47:38 -0700253}
254
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800255Return<void> WifiChip::removeP2pIface(const hidl_string& ifname,
256 removeP2pIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700257 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
258 &WifiChip::removeP2pIfaceInternal, hidl_status_cb,
259 ifname);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800260}
261
Roshan Pius5c055462016-10-11 08:27:27 -0700262Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700263 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
264 &WifiChip::createStaIfaceInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700265}
266
Roshan Pius5c055462016-10-11 08:27:27 -0700267Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700268 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
269 &WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
Roshan Pius35d958c2016-10-06 16:47:38 -0700270}
271
272Return<void> WifiChip::getStaIface(const hidl_string& ifname,
Roshan Pius5c055462016-10-11 08:27:27 -0700273 getStaIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700274 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
275 &WifiChip::getStaIfaceInternal, hidl_status_cb,
276 ifname);
Roshan Pius35d958c2016-10-06 16:47:38 -0700277}
278
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800279Return<void> WifiChip::removeStaIface(const hidl_string& ifname,
280 removeStaIface_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700281 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
282 &WifiChip::removeStaIfaceInternal, hidl_status_cb,
283 ifname);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800284}
285
Roshan Pius5c055462016-10-11 08:27:27 -0700286Return<void> WifiChip::createRttController(
287 const sp<IWifiIface>& bound_iface, createRttController_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700288 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
289 &WifiChip::createRttControllerInternal,
290 hidl_status_cb, bound_iface);
Roshan Pius59268282016-10-06 20:23:47 -0700291}
292
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700293Return<void> WifiChip::getDebugRingBuffersStatus(
294 getDebugRingBuffersStatus_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700295 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
296 &WifiChip::getDebugRingBuffersStatusInternal,
297 hidl_status_cb);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700298}
299
300Return<void> WifiChip::startLoggingToDebugRingBuffer(
Roshan Piusabcf78f2017-10-06 16:30:38 -0700301 const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
302 uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700303 startLoggingToDebugRingBuffer_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700304 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
305 &WifiChip::startLoggingToDebugRingBufferInternal,
306 hidl_status_cb, ring_name, verbose_level,
307 max_interval_in_sec, min_data_size_in_bytes);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700308}
309
310Return<void> WifiChip::forceDumpToDebugRingBuffer(
311 const hidl_string& ring_name,
312 forceDumpToDebugRingBuffer_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700313 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
314 &WifiChip::forceDumpToDebugRingBufferInternal,
315 hidl_status_cb, ring_name);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700316}
317
Roshan Pius8c0c8e92017-02-24 08:07:42 -0800318Return<void> WifiChip::stopLoggingToDebugRingBuffer(
319 stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700320 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
321 &WifiChip::stopLoggingToDebugRingBufferInternal,
322 hidl_status_cb);
Roshan Pius8c0c8e92017-02-24 08:07:42 -0800323}
324
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700325Return<void> WifiChip::getDebugHostWakeReasonStats(
326 getDebugHostWakeReasonStats_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700327 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
328 &WifiChip::getDebugHostWakeReasonStatsInternal,
329 hidl_status_cb);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700330}
331
Roshan Pius203cb032016-12-14 17:41:20 -0800332Return<void> WifiChip::enableDebugErrorAlerts(
333 bool enable, enableDebugErrorAlerts_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700334 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
335 &WifiChip::enableDebugErrorAlertsInternal,
336 hidl_status_cb, enable);
Roshan Pius203cb032016-12-14 17:41:20 -0800337}
338
Roshan Pius735ff432017-07-25 08:48:08 -0700339Return<void> WifiChip::selectTxPowerScenario(
340 TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700341 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
342 &WifiChip::selectTxPowerScenarioInternal,
343 hidl_status_cb, scenario);
Roshan Piusdbd83ef2017-06-20 12:05:40 -0700344}
345
Roshan Pius735ff432017-07-25 08:48:08 -0700346Return<void> WifiChip::resetTxPowerScenario(
347 resetTxPowerScenario_cb hidl_status_cb) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700348 return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
349 &WifiChip::resetTxPowerScenarioInternal,
350 hidl_status_cb);
Roshan Piusdbd83ef2017-06-20 12:05:40 -0700351}
352
Roshan Pius35d958c2016-10-06 16:47:38 -0700353void WifiChip::invalidateAndRemoveAllIfaces() {
Roshan Pius675609b2017-10-31 14:24:58 -0700354 invalidateAndClearAll(ap_ifaces_);
355 invalidateAndClearAll(nan_ifaces_);
356 invalidateAndClearAll(p2p_ifaces_);
357 invalidateAndClearAll(sta_ifaces_);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700358 // Since all the ifaces are invalid now, all RTT controller objects
359 // using those ifaces also need to be invalidated.
360 for (const auto& rtt : rtt_controllers_) {
361 rtt->invalidate();
362 }
363 rtt_controllers_.clear();
Roshan Pius35d958c2016-10-06 16:47:38 -0700364}
365
Roshan Pius3c868522016-10-27 12:43:49 -0700366std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700367 return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
Roshan Pius3c868522016-10-27 12:43:49 -0700368}
369
370WifiStatus WifiChip::registerEventCallbackInternal(
371 const sp<IWifiChipEventCallback>& event_callback) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700372 if (!event_cb_handler_.addCallback(event_callback)) {
373 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
374 }
375 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius3c868522016-10-27 12:43:49 -0700376}
377
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700378std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700379 legacy_hal::wifi_error legacy_status;
380 uint32_t legacy_feature_set;
381 uint32_t legacy_logger_feature_set;
382 std::tie(legacy_status, legacy_feature_set) =
383 legacy_hal_.lock()->getSupportedFeatureSet(getWlan0IfaceName());
384 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
385 return {createWifiStatusFromLegacyError(legacy_status), 0};
386 }
387 std::tie(legacy_status, legacy_logger_feature_set) =
388 legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
389 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
390 return {createWifiStatusFromLegacyError(legacy_status), 0};
391 }
392 uint32_t hidl_caps;
393 if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
394 legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
395 return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
396 }
397 return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700398}
399
Roshan Pius3c868522016-10-27 12:43:49 -0700400std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
401WifiChip::getAvailableModesInternal() {
Roshan Piuscc338202017-11-02 13:54:09 -0700402 return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
Roshan Pius3c868522016-10-27 12:43:49 -0700403}
404
Roshan Piusba38d9c2017-12-08 07:32:08 -0800405WifiStatus WifiChip::configureChipInternal(
406 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
407 ChipModeId mode_id) {
Roshan Piuscc338202017-11-02 13:54:09 -0700408 if (!isValidModeId(mode_id)) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700409 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
410 }
411 if (mode_id == current_mode_id_) {
412 LOG(DEBUG) << "Already in the specified mode " << mode_id;
413 return createWifiStatus(WifiStatusCode::SUCCESS);
414 }
Roshan Piusba38d9c2017-12-08 07:32:08 -0800415 WifiStatus status = handleChipConfiguration(lock, mode_id);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700416 if (status.code != WifiStatusCode::SUCCESS) {
417 for (const auto& callback : event_cb_handler_.getCallbacks()) {
418 if (!callback->onChipReconfigureFailure(status).isOk()) {
419 LOG(ERROR)
420 << "Failed to invoke onChipReconfigureFailure callback";
421 }
422 }
423 return status;
424 }
Roshan Piusd37341f2017-01-31 13:13:28 -0800425 for (const auto& callback : event_cb_handler_.getCallbacks()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700426 if (!callback->onChipReconfigured(mode_id).isOk()) {
427 LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
428 }
Roshan Pius52947fb2016-11-18 11:38:07 -0800429 }
Roshan Piusabcf78f2017-10-06 16:30:38 -0700430 current_mode_id_ = mode_id;
Roshan Piusba38d9c2017-12-08 07:32:08 -0800431 LOG(INFO) << "Configured chip in mode " << mode_id;
Roshan Pius2c06a3f2016-12-15 17:51:40 -0800432 return status;
Roshan Pius3c868522016-10-27 12:43:49 -0700433}
434
435std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
Roshan Piuscc338202017-11-02 13:54:09 -0700436 if (!isValidModeId(current_mode_id_)) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700437 return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
438 current_mode_id_};
439 }
440 return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
Roshan Pius3c868522016-10-27 12:43:49 -0700441}
442
443std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
444WifiChip::requestChipDebugInfoInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700445 IWifiChip::ChipDebugInfo result;
446 legacy_hal::wifi_error legacy_status;
447 std::string driver_desc;
448 std::tie(legacy_status, driver_desc) =
449 legacy_hal_.lock()->getDriverVersion(getWlan0IfaceName());
450 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
451 LOG(ERROR) << "Failed to get driver version: "
452 << legacyErrorToString(legacy_status);
453 WifiStatus status = createWifiStatusFromLegacyError(
454 legacy_status, "failed to get driver version");
455 return {status, result};
456 }
457 result.driverDescription = driver_desc.c_str();
Roshan Pius3c868522016-10-27 12:43:49 -0700458
Roshan Piusabcf78f2017-10-06 16:30:38 -0700459 std::string firmware_desc;
460 std::tie(legacy_status, firmware_desc) =
461 legacy_hal_.lock()->getFirmwareVersion(getWlan0IfaceName());
462 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
463 LOG(ERROR) << "Failed to get firmware version: "
464 << legacyErrorToString(legacy_status);
465 WifiStatus status = createWifiStatusFromLegacyError(
466 legacy_status, "failed to get firmware version");
467 return {status, result};
468 }
469 result.firmwareDescription = firmware_desc.c_str();
Roshan Pius3c868522016-10-27 12:43:49 -0700470
Roshan Piusabcf78f2017-10-06 16:30:38 -0700471 return {createWifiStatus(WifiStatusCode::SUCCESS), result};
Roshan Pius3c868522016-10-27 12:43:49 -0700472}
473
474std::pair<WifiStatus, std::vector<uint8_t>>
475WifiChip::requestDriverDebugDumpInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700476 legacy_hal::wifi_error legacy_status;
477 std::vector<uint8_t> driver_dump;
478 std::tie(legacy_status, driver_dump) =
479 legacy_hal_.lock()->requestDriverMemoryDump(getWlan0IfaceName());
480 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
481 LOG(ERROR) << "Failed to get driver debug dump: "
482 << legacyErrorToString(legacy_status);
483 return {createWifiStatusFromLegacyError(legacy_status),
484 std::vector<uint8_t>()};
485 }
486 return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump};
Roshan Pius3c868522016-10-27 12:43:49 -0700487}
488
489std::pair<WifiStatus, std::vector<uint8_t>>
490WifiChip::requestFirmwareDebugDumpInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700491 legacy_hal::wifi_error legacy_status;
492 std::vector<uint8_t> firmware_dump;
493 std::tie(legacy_status, firmware_dump) =
494 legacy_hal_.lock()->requestFirmwareMemoryDump(getWlan0IfaceName());
495 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
496 LOG(ERROR) << "Failed to get firmware debug dump: "
497 << legacyErrorToString(legacy_status);
498 return {createWifiStatusFromLegacyError(legacy_status), {}};
499 }
500 return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
Roshan Pius3c868522016-10-27 12:43:49 -0700501}
502
503std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
Roshan Piuscc338202017-11-02 13:54:09 -0700504 if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700505 return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
Roshan Piusbc662202017-01-30 17:07:42 -0800506 }
Roshan Pius8e3c7ef2017-11-03 09:43:08 -0700507 std::string ifname = allocateApOrStaIfaceName();
Roshan Pius675609b2017-10-31 14:24:58 -0700508 sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_);
509 ap_ifaces_.push_back(iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700510 for (const auto& callback : event_cb_handler_.getCallbacks()) {
511 if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
512 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
513 }
514 }
Roshan Pius675609b2017-10-31 14:24:58 -0700515 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700516}
517
518std::pair<WifiStatus, std::vector<hidl_string>>
519WifiChip::getApIfaceNamesInternal() {
Roshan Pius675609b2017-10-31 14:24:58 -0700520 if (ap_ifaces_.empty()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700521 return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
522 }
Roshan Pius675609b2017-10-31 14:24:58 -0700523 return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)};
Roshan Pius3c868522016-10-27 12:43:49 -0700524}
525
526std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal(
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800527 const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700528 const auto iface = findUsingName(ap_ifaces_, ifname);
529 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700530 return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
531 }
Roshan Pius675609b2017-10-31 14:24:58 -0700532 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700533}
534
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800535WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700536 const auto iface = findUsingName(ap_ifaces_, ifname);
537 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700538 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
Roshan Piusbc662202017-01-30 17:07:42 -0800539 }
Roshan Pius675609b2017-10-31 14:24:58 -0700540 invalidateAndClear(ap_ifaces_, iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700541 for (const auto& callback : event_cb_handler_.getCallbacks()) {
542 if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
543 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
544 }
545 }
546 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800547}
548
Roshan Pius3c868522016-10-27 12:43:49 -0700549std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
Roshan Piuscc338202017-11-02 13:54:09 -0700550 if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700551 return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
Etan Cohenc5700402017-03-08 16:43:38 -0800552 }
Roshan Pius8e3c7ef2017-11-03 09:43:08 -0700553 // These are still assumed to be based on wlan0.
Roshan Piuscc338202017-11-02 13:54:09 -0700554 std::string ifname = getWlan0IfaceName();
555 sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
556 nan_ifaces_.push_back(iface);
557 for (const auto& callback : event_cb_handler_.getCallbacks()) {
558 if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
559 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
560 }
561 }
562 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700563}
564
565std::pair<WifiStatus, std::vector<hidl_string>>
566WifiChip::getNanIfaceNamesInternal() {
Roshan Pius675609b2017-10-31 14:24:58 -0700567 if (nan_ifaces_.empty()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700568 return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
569 }
Roshan Pius675609b2017-10-31 14:24:58 -0700570 return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)};
Roshan Pius3c868522016-10-27 12:43:49 -0700571}
572
573std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal(
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800574 const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700575 const auto iface = findUsingName(nan_ifaces_, ifname);
576 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700577 return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
578 }
Roshan Pius675609b2017-10-31 14:24:58 -0700579 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700580}
581
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800582WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700583 const auto iface = findUsingName(nan_ifaces_, ifname);
584 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700585 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
Roshan Piusbc662202017-01-30 17:07:42 -0800586 }
Roshan Pius675609b2017-10-31 14:24:58 -0700587 invalidateAndClear(nan_ifaces_, iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700588 for (const auto& callback : event_cb_handler_.getCallbacks()) {
589 if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
590 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
591 }
592 }
593 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800594}
595
Roshan Pius3c868522016-10-27 12:43:49 -0700596std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
Roshan Piuscc338202017-11-02 13:54:09 -0700597 if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700598 return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
Roshan Piusbc662202017-01-30 17:07:42 -0800599 }
Roshan Piusabcf78f2017-10-06 16:30:38 -0700600 std::string ifname = getP2pIfaceName();
Roshan Pius675609b2017-10-31 14:24:58 -0700601 sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
602 p2p_ifaces_.push_back(iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700603 for (const auto& callback : event_cb_handler_.getCallbacks()) {
604 if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
605 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
606 }
607 }
Roshan Pius675609b2017-10-31 14:24:58 -0700608 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700609}
610
611std::pair<WifiStatus, std::vector<hidl_string>>
612WifiChip::getP2pIfaceNamesInternal() {
Roshan Pius675609b2017-10-31 14:24:58 -0700613 if (p2p_ifaces_.empty()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700614 return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
615 }
Roshan Pius675609b2017-10-31 14:24:58 -0700616 return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)};
Roshan Pius3c868522016-10-27 12:43:49 -0700617}
618
619std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800620 const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700621 const auto iface = findUsingName(p2p_ifaces_, ifname);
622 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700623 return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
624 }
Roshan Pius675609b2017-10-31 14:24:58 -0700625 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700626}
627
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800628WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700629 const auto iface = findUsingName(p2p_ifaces_, ifname);
630 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700631 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
Roshan Piusbc662202017-01-30 17:07:42 -0800632 }
Roshan Pius675609b2017-10-31 14:24:58 -0700633 invalidateAndClear(p2p_ifaces_, iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700634 for (const auto& callback : event_cb_handler_.getCallbacks()) {
635 if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
636 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
637 }
638 }
639 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800640}
641
Roshan Pius3c868522016-10-27 12:43:49 -0700642std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
Roshan Piuscc338202017-11-02 13:54:09 -0700643 if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700644 return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
Roshan Piusbc662202017-01-30 17:07:42 -0800645 }
Roshan Pius8e3c7ef2017-11-03 09:43:08 -0700646 std::string ifname = allocateApOrStaIfaceName();
Roshan Pius675609b2017-10-31 14:24:58 -0700647 sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);
648 sta_ifaces_.push_back(iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700649 for (const auto& callback : event_cb_handler_.getCallbacks()) {
650 if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
651 LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
652 }
653 }
Roshan Pius675609b2017-10-31 14:24:58 -0700654 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700655}
656
657std::pair<WifiStatus, std::vector<hidl_string>>
658WifiChip::getStaIfaceNamesInternal() {
Roshan Pius675609b2017-10-31 14:24:58 -0700659 if (sta_ifaces_.empty()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700660 return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
661 }
Roshan Pius675609b2017-10-31 14:24:58 -0700662 return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
Roshan Pius3c868522016-10-27 12:43:49 -0700663}
664
665std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800666 const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700667 const auto iface = findUsingName(sta_ifaces_, ifname);
668 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700669 return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
670 }
Roshan Pius675609b2017-10-31 14:24:58 -0700671 return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
Roshan Pius3c868522016-10-27 12:43:49 -0700672}
673
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800674WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
Roshan Pius675609b2017-10-31 14:24:58 -0700675 const auto iface = findUsingName(sta_ifaces_, ifname);
676 if (!iface.get()) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700677 return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
Roshan Piusbc662202017-01-30 17:07:42 -0800678 }
Roshan Pius675609b2017-10-31 14:24:58 -0700679 invalidateAndClear(sta_ifaces_, iface);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700680 for (const auto& callback : event_cb_handler_.getCallbacks()) {
681 if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
682 LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
683 }
684 }
685 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius8b55e6f2016-12-09 12:05:12 -0800686}
687
Roshan Pius3c868522016-10-27 12:43:49 -0700688std::pair<WifiStatus, sp<IWifiRttController>>
689WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700690 sp<WifiRttController> rtt =
691 new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
692 rtt_controllers_.emplace_back(rtt);
693 return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
Roshan Pius3c868522016-10-27 12:43:49 -0700694}
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700695
696std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
697WifiChip::getDebugRingBuffersStatusInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700698 legacy_hal::wifi_error legacy_status;
699 std::vector<legacy_hal::wifi_ring_buffer_status>
700 legacy_ring_buffer_status_vec;
701 std::tie(legacy_status, legacy_ring_buffer_status_vec) =
702 legacy_hal_.lock()->getRingBuffersStatus(getWlan0IfaceName());
703 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
704 return {createWifiStatusFromLegacyError(legacy_status), {}};
705 }
706 std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
707 if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
708 legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
709 return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
710 }
711 return {createWifiStatus(WifiStatusCode::SUCCESS),
712 hidl_ring_buffer_status_vec};
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700713}
714
715WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
Roshan Piusabcf78f2017-10-06 16:30:38 -0700716 const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
717 uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
718 WifiStatus status = registerDebugRingBufferCallback();
719 if (status.code != WifiStatusCode::SUCCESS) {
720 return status;
721 }
722 legacy_hal::wifi_error legacy_status =
723 legacy_hal_.lock()->startRingBufferLogging(
724 getWlan0IfaceName(), ring_name,
725 static_cast<
726 std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
727 verbose_level),
728 max_interval_in_sec, min_data_size_in_bytes);
729 return createWifiStatusFromLegacyError(legacy_status);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700730}
731
732WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
Roshan Piuse2d0ab52016-12-05 15:24:20 -0800733 const hidl_string& ring_name) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700734 WifiStatus status = registerDebugRingBufferCallback();
735 if (status.code != WifiStatusCode::SUCCESS) {
736 return status;
737 }
738 legacy_hal::wifi_error legacy_status =
739 legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
740 return createWifiStatusFromLegacyError(legacy_status);
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700741}
742
Roshan Pius8c0c8e92017-02-24 08:07:42 -0800743WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700744 legacy_hal::wifi_error legacy_status =
745 legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
746 getWlan0IfaceName());
747 return createWifiStatusFromLegacyError(legacy_status);
Roshan Pius8c0c8e92017-02-24 08:07:42 -0800748}
749
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700750std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
751WifiChip::getDebugHostWakeReasonStatsInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700752 legacy_hal::wifi_error legacy_status;
753 legacy_hal::WakeReasonStats legacy_stats;
754 std::tie(legacy_status, legacy_stats) =
755 legacy_hal_.lock()->getWakeReasonStats(getWlan0IfaceName());
756 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
757 return {createWifiStatusFromLegacyError(legacy_status), {}};
758 }
759 WifiDebugHostWakeReasonStats hidl_stats;
760 if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats,
761 &hidl_stats)) {
762 return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
763 }
764 return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
Roshan Pius7d08d7a2016-10-27 14:35:05 -0700765}
766
Roshan Pius203cb032016-12-14 17:41:20 -0800767WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700768 legacy_hal::wifi_error legacy_status;
769 if (enable) {
770 android::wp<WifiChip> weak_ptr_this(this);
771 const auto& on_alert_callback = [weak_ptr_this](
772 int32_t error_code,
773 std::vector<uint8_t> debug_data) {
774 const auto shared_ptr_this = weak_ptr_this.promote();
775 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
776 LOG(ERROR) << "Callback invoked on an invalid object";
777 return;
778 }
779 for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
780 if (!callback->onDebugErrorAlert(error_code, debug_data)
781 .isOk()) {
782 LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
783 }
784 }
785 };
786 legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
Roshan Piusacededb2017-10-06 14:59:26 -0700787 getWlan0IfaceName(), on_alert_callback);
Roshan Piusabcf78f2017-10-06 16:30:38 -0700788 } else {
789 legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
Roshan Piusacededb2017-10-06 14:59:26 -0700790 getWlan0IfaceName());
Roshan Piusabcf78f2017-10-06 16:30:38 -0700791 }
792 return createWifiStatusFromLegacyError(legacy_status);
Roshan Pius203cb032016-12-14 17:41:20 -0800793}
Roshan Pius2c06a3f2016-12-15 17:51:40 -0800794
Roshan Pius735ff432017-07-25 08:48:08 -0700795WifiStatus WifiChip::selectTxPowerScenarioInternal(TxPowerScenario scenario) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700796 auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
797 getWlan0IfaceName(),
798 hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
799 return createWifiStatusFromLegacyError(legacy_status);
Roshan Piusdbd83ef2017-06-20 12:05:40 -0700800}
801
Roshan Pius735ff432017-07-25 08:48:08 -0700802WifiStatus WifiChip::resetTxPowerScenarioInternal() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700803 auto legacy_status =
804 legacy_hal_.lock()->resetTxPowerScenario(getWlan0IfaceName());
805 return createWifiStatusFromLegacyError(legacy_status);
Roshan Piusdbd83ef2017-06-20 12:05:40 -0700806}
807
Roshan Piusba38d9c2017-12-08 07:32:08 -0800808WifiStatus WifiChip::handleChipConfiguration(
809 /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
810 ChipModeId mode_id) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700811 // If the chip is already configured in a different mode, stop
812 // the legacy HAL and then start it after firmware mode change.
Roshan Piuscc338202017-11-02 13:54:09 -0700813 if (isValidModeId(current_mode_id_)) {
Roshan Piusba38d9c2017-12-08 07:32:08 -0800814 LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
815 << " to mode " << mode_id;
816 invalidateAndRemoveAllIfaces();
817 legacy_hal::wifi_error legacy_status =
818 legacy_hal_.lock()->stop(lock, []() {});
819 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
820 LOG(ERROR) << "Failed to stop legacy HAL: "
821 << legacyErrorToString(legacy_status);
822 return createWifiStatusFromLegacyError(legacy_status);
823 }
Roshan Piusabcf78f2017-10-06 16:30:38 -0700824 }
Roshan Piuscc338202017-11-02 13:54:09 -0700825 // Firmware mode change not needed for V2 devices.
826 bool success = true;
827 if (mode_id == kV1StaChipModeId) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700828 success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
Roshan Piuscc338202017-11-02 13:54:09 -0700829 } else if (mode_id == kV1ApChipModeId) {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700830 success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
831 }
832 if (!success) {
833 return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
834 }
835 legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
836 if (legacy_status != legacy_hal::WIFI_SUCCESS) {
837 LOG(ERROR) << "Failed to start legacy HAL: "
838 << legacyErrorToString(legacy_status);
839 return createWifiStatusFromLegacyError(legacy_status);
840 }
841 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius2c06a3f2016-12-15 17:51:40 -0800842}
Roshan Pius48185b22016-12-15 19:10:30 -0800843
844WifiStatus WifiChip::registerDebugRingBufferCallback() {
Roshan Piusabcf78f2017-10-06 16:30:38 -0700845 if (debug_ring_buffer_cb_registered_) {
846 return createWifiStatus(WifiStatusCode::SUCCESS);
Roshan Pius48185b22016-12-15 19:10:30 -0800847 }
Roshan Pius3797e182017-03-30 18:01:54 -0700848
Roshan Piusabcf78f2017-10-06 16:30:38 -0700849 android::wp<WifiChip> weak_ptr_this(this);
850 const auto& on_ring_buffer_data_callback =
851 [weak_ptr_this](const std::string& /* name */,
852 const std::vector<uint8_t>& data,
853 const legacy_hal::wifi_ring_buffer_status& status) {
854 const auto shared_ptr_this = weak_ptr_this.promote();
855 if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
856 LOG(ERROR) << "Callback invoked on an invalid object";
857 return;
858 }
859 WifiDebugRingBufferStatus hidl_status;
860 if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(
861 status, &hidl_status)) {
862 LOG(ERROR) << "Error converting ring buffer status";
863 return;
864 }
865 for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
866 if (!callback->onDebugRingBufferDataAvailable(hidl_status, data)
867 .isOk()) {
868 LOG(ERROR)
869 << "Failed to invoke onDebugRingBufferDataAvailable"
870 << " callback on: " << toString(callback);
871 }
872 }
873 };
874 legacy_hal::wifi_error legacy_status =
875 legacy_hal_.lock()->registerRingBufferCallbackHandler(
876 getWlan0IfaceName(), on_ring_buffer_data_callback);
Roshan Pius48185b22016-12-15 19:10:30 -0800877
Roshan Piusabcf78f2017-10-06 16:30:38 -0700878 if (legacy_status == legacy_hal::WIFI_SUCCESS) {
879 debug_ring_buffer_cb_registered_ = true;
880 }
881 return createWifiStatusFromLegacyError(legacy_status);
Roshan Pius48185b22016-12-15 19:10:30 -0800882}
883
Roshan Piuscc338202017-11-02 13:54:09 -0700884void WifiChip::populateModes() {
885 // The chip combination supported for current devices is fixed.
886 // They can be one of the following based on device features:
887 // a) 2 separate modes of operation with 1 interface combination each:
888 // Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN(optional)
889 // concurrent iface operations.
890 // Mode 2 (AP mode): Will support 1 AP iface operation.
891 //
892 // b) 1 mode of operation with 2 interface combinations
893 // (conditional on isDualInterfaceSupported()):
894 // Interface Combination 1: Will support 1 STA and 1 P2P or NAN(optional)
895 // concurrent iface operations.
896 // Interface Combination 2: Will support 1 STA and 1 STA or AP concurrent
897 // iface operations.
898 // If Aware is enabled (conditional on isAwareSupported()), the iface
899 // combination will be modified to support either P2P or NAN in place of
900 // just P2P.
901 if (feature_flags_.lock()->isDualInterfaceSupported()) {
902 // V2 Iface combinations for Mode Id = 2.
903 const IWifiChip::ChipIfaceCombinationLimit
904 chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
905 const IWifiChip::ChipIfaceCombinationLimit
906 chip_iface_combination_limit_2 = {{IfaceType::STA, IfaceType::AP},
907 1};
908 IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;
909 if (feature_flags_.lock()->isAwareSupported()) {
910 chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},
911 1};
912 } else {
913 chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};
914 }
915 const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
916 {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
917 const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
918 {chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
919 const IWifiChip::ChipMode chip_mode = {
920 kV2ChipModeId,
921 {chip_iface_combination_1, chip_iface_combination_2}};
922 modes_ = {chip_mode};
923 } else {
924 // V1 Iface combinations for Mode Id = 0. (STA Mode)
925 const IWifiChip::ChipIfaceCombinationLimit
926 sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
927 IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
928 if (feature_flags_.lock()->isAwareSupported()) {
929 sta_chip_iface_combination_limit_2 = {
930 {IfaceType::P2P, IfaceType::NAN}, 1};
931 } else {
932 sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
933 }
934 const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
935 {sta_chip_iface_combination_limit_1,
936 sta_chip_iface_combination_limit_2}};
937 const IWifiChip::ChipMode sta_chip_mode = {
938 kV1StaChipModeId, {sta_chip_iface_combination}};
939 // Iface combinations for Mode Id = 1. (AP Mode)
940 const IWifiChip::ChipIfaceCombinationLimit
941 ap_chip_iface_combination_limit = {{IfaceType::AP}, 1};
942 const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
943 {ap_chip_iface_combination_limit}};
944 const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
945 {ap_chip_iface_combination}};
946 modes_ = {sta_chip_mode, ap_chip_mode};
947 }
948}
949
950std::vector<IWifiChip::ChipIfaceCombination>
951WifiChip::getCurrentModeIfaceCombinations() {
952 if (!isValidModeId(current_mode_id_)) {
953 LOG(ERROR) << "Chip not configured in a mode yet";
954 return {};
955 }
956 for (const auto& mode : modes_) {
957 if (mode.id == current_mode_id_) {
958 return mode.availableCombinations;
959 }
960 }
961 CHECK(0) << "Expected to find iface combinations for current mode!";
962 return {};
963}
964
965// Returns a map indexed by IfaceType with the number of ifaces currently
966// created of the corresponding type.
967std::map<IfaceType, size_t> WifiChip::getCurrentIfaceCombination() {
968 std::map<IfaceType, size_t> iface_counts;
969 iface_counts[IfaceType::AP] = ap_ifaces_.size();
970 iface_counts[IfaceType::NAN] = nan_ifaces_.size();
971 iface_counts[IfaceType::P2P] = p2p_ifaces_.size();
972 iface_counts[IfaceType::STA] = sta_ifaces_.size();
973 return iface_counts;
974}
975
976// This expands the provided iface combinations to a more parseable
977// form. Returns a vector of available combinations possible with the number
978// of ifaces of each type in the combination.
979// This method is a port of HalDeviceManager.expandIfaceCombos() from framework.
980std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations(
981 const IWifiChip::ChipIfaceCombination& combination) {
982 uint32_t num_expanded_combos = 1;
983 for (const auto& limit : combination.limits) {
984 for (uint32_t i = 0; i < limit.maxIfaces; i++) {
985 num_expanded_combos *= limit.types.size();
986 }
987 }
988
989 // Allocate the vector of expanded combos and reset all iface counts to 0
990 // in each combo.
991 std::vector<std::map<IfaceType, size_t>> expanded_combos;
992 expanded_combos.resize(num_expanded_combos);
993 for (auto& expanded_combo : expanded_combos) {
994 for (const auto type :
995 {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
996 expanded_combo[type] = 0;
997 }
998 }
999 uint32_t span = num_expanded_combos;
1000 for (const auto& limit : combination.limits) {
1001 for (uint32_t i = 0; i < limit.maxIfaces; i++) {
1002 span /= limit.types.size();
1003 for (uint32_t k = 0; k < num_expanded_combos; ++k) {
1004 const auto iface_type =
1005 limit.types[(k / span) % limit.types.size()];
1006 expanded_combos[k][iface_type]++;
1007 }
1008 }
1009 }
1010 return expanded_combos;
1011}
1012
1013bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType(
1014 const std::map<IfaceType, size_t>& combo, IfaceType requested_type) {
1015 const auto current_combo = getCurrentIfaceCombination();
1016
1017 // Check if we have space for 1 more iface of |type| in this combo
1018 for (const auto type :
1019 {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
1020 size_t num_ifaces_needed = current_combo.at(type);
1021 if (type == requested_type) {
1022 num_ifaces_needed++;
1023 }
1024 size_t num_ifaces_allowed = combo.at(type);
1025 if (num_ifaces_needed > num_ifaces_allowed) {
1026 return false;
1027 }
1028 }
1029 return true;
1030}
1031
1032// This method does the following:
1033// a) Enumerate all possible iface combos by expanding the current
1034// ChipIfaceCombination.
1035// b) Check if the requested iface type can be added to the current mode.
1036bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) {
1037 if (!isValidModeId(current_mode_id_)) {
1038 LOG(ERROR) << "Chip not configured in a mode yet";
1039 return false;
1040 }
1041 const auto combinations = getCurrentModeIfaceCombinations();
1042 for (const auto& combination : combinations) {
1043 const auto expanded_combos = expandIfaceCombinations(combination);
1044 for (const auto& expanded_combo : expanded_combos) {
1045 if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo,
1046 type)) {
1047 return true;
1048 }
1049 }
1050 }
1051 return false;
1052}
1053
1054bool WifiChip::isValidModeId(ChipModeId mode_id) {
1055 for (const auto& mode : modes_) {
1056 if (mode.id == mode_id) {
1057 return true;
1058 }
1059 }
1060 return false;
1061}
1062
Roshan Pius8e3c7ef2017-11-03 09:43:08 -07001063// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
1064// This is based on the assumption that we'll have a max of 2 concurrent
1065// AP/STA ifaces.
1066std::string WifiChip::allocateApOrStaIfaceName() {
1067 auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
1068 auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
1069 if (!ap_iface.get() && !sta_iface.get()) {
1070 return getWlan0IfaceName();
1071 }
1072 ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
1073 sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
1074 if (!ap_iface.get() && !sta_iface.get()) {
1075 return getWlan1IfaceName();
1076 }
1077 // This should never happen. We screwed up somewhere if it did.
1078 CHECK(0) << "wlan0 and wlan1 in use already!";
1079 return {};
1080}
1081
Roshan Pius79a99752016-10-04 13:03:58 -07001082} // namespace implementation
Etan Cohen6ce50902017-09-14 07:30:57 -07001083} // namespace V1_2
Roshan Pius3c4e8a32016-10-03 14:53:58 -07001084} // namespace wifi
1085} // namespace hardware
1086} // namespace android