2016-10-06 22:16:23 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <android-base/logging.h>
|
|
|
|
|
2016-10-27 21:48:12 +02:00
|
|
|
#include "hidl_return_util.h"
|
2016-12-06 00:25:51 +01:00
|
|
|
#include "hidl_struct_util.h"
|
2016-10-27 21:48:12 +02:00
|
|
|
#include "wifi_sta_iface.h"
|
2016-10-11 17:30:28 +02:00
|
|
|
#include "wifi_status_util.h"
|
2016-10-06 22:16:23 +02:00
|
|
|
|
|
|
|
namespace android {
|
|
|
|
namespace hardware {
|
|
|
|
namespace wifi {
|
2019-07-24 00:02:22 +02:00
|
|
|
namespace V1_4 {
|
2016-10-06 22:16:23 +02:00
|
|
|
namespace implementation {
|
2016-10-27 21:48:12 +02:00
|
|
|
using hidl_return_util::validateAndCall;
|
2016-10-06 22:16:23 +02:00
|
|
|
|
2016-10-28 19:11:17 +02:00
|
|
|
WifiStaIface::WifiStaIface(
|
|
|
|
const std::string& ifname,
|
2019-02-14 16:57:10 +01:00
|
|
|
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
|
|
|
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
|
|
|
|
: ifname_(ifname),
|
|
|
|
legacy_hal_(legacy_hal),
|
|
|
|
iface_util_(iface_util),
|
|
|
|
is_valid_(true) {
|
2017-10-07 01:30:38 +02:00
|
|
|
// Turn on DFS channel usage for STA iface.
|
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->setDfsFlag(ifname_, true);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
LOG(ERROR)
|
|
|
|
<< "Failed to set DFS flag; DFS channels may be unavailable.";
|
|
|
|
}
|
2017-04-20 08:11:07 +02:00
|
|
|
}
|
2016-10-06 22:16:23 +02:00
|
|
|
|
|
|
|
void WifiStaIface::invalidate() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal_.reset();
|
|
|
|
event_cb_handler_.invalidate();
|
|
|
|
is_valid_ = false;
|
2016-10-06 22:16:23 +02:00
|
|
|
}
|
|
|
|
|
2017-10-07 01:30:38 +02:00
|
|
|
bool WifiStaIface::isValid() { return is_valid_; }
|
2016-10-27 21:48:12 +02:00
|
|
|
|
2017-10-31 22:24:58 +01:00
|
|
|
std::string WifiStaIface::getName() { return ifname_; }
|
|
|
|
|
2017-01-31 22:13:28 +01:00
|
|
|
std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
|
2017-10-07 01:30:38 +02:00
|
|
|
return event_cb_handler_.getCallbacks();
|
2016-12-06 00:25:51 +01:00
|
|
|
}
|
|
|
|
|
2016-10-11 17:30:28 +02:00
|
|
|
Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getNameInternal, hidl_status_cb);
|
2016-10-06 22:16:23 +02:00
|
|
|
}
|
|
|
|
|
2016-10-11 17:30:28 +02:00
|
|
|
Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getTypeInternal, hidl_status_cb);
|
2016-10-27 21:48:12 +02:00
|
|
|
}
|
|
|
|
|
2016-10-27 23:36:26 +02:00
|
|
|
Return<void> WifiStaIface::registerEventCallback(
|
|
|
|
const sp<IWifiStaIfaceEventCallback>& callback,
|
|
|
|
registerEventCallback_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::registerEventCallbackInternal,
|
|
|
|
hidl_status_cb, callback);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getCapabilitiesInternal,
|
|
|
|
hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::getApfPacketFilterCapabilities(
|
|
|
|
getApfPacketFilterCapabilities_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(
|
|
|
|
this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::installApfPacketFilter(
|
2017-10-07 01:30:38 +02:00
|
|
|
uint32_t cmd_id, const hidl_vec<uint8_t>& program,
|
2016-10-27 23:36:26 +02:00
|
|
|
installApfPacketFilter_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::installApfPacketFilterInternal,
|
|
|
|
hidl_status_cb, cmd_id, program);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2018-03-06 16:17:50 +01:00
|
|
|
Return<void> WifiStaIface::readApfPacketFilterData(
|
|
|
|
readApfPacketFilterData_cb hidl_status_cb) {
|
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::readApfPacketFilterDataInternal,
|
|
|
|
hidl_status_cb);
|
|
|
|
}
|
|
|
|
|
2016-10-27 23:36:26 +02:00
|
|
|
Return<void> WifiStaIface::getBackgroundScanCapabilities(
|
|
|
|
getBackgroundScanCapabilities_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getBackgroundScanCapabilitiesInternal,
|
|
|
|
hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2017-02-22 18:48:03 +01:00
|
|
|
Return<void> WifiStaIface::getValidFrequenciesForBand(
|
2019-11-16 03:19:15 +01:00
|
|
|
V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getValidFrequenciesForBandInternal,
|
|
|
|
hidl_status_cb, band);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::startBackgroundScan(
|
2017-10-07 01:30:38 +02:00
|
|
|
uint32_t cmd_id, const StaBackgroundScanParameters& params,
|
2016-10-27 23:36:26 +02:00
|
|
|
startBackgroundScan_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::startBackgroundScanInternal,
|
|
|
|
hidl_status_cb, cmd_id, params);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::stopBackgroundScan(
|
|
|
|
uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::stopBackgroundScanInternal,
|
|
|
|
hidl_status_cb, cmd_id);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::enableLinkLayerStatsCollection(
|
|
|
|
bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(
|
|
|
|
this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb,
|
|
|
|
debug);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::disableLinkLayerStatsCollection(
|
|
|
|
disableLinkLayerStatsCollection_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(
|
|
|
|
this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::getLinkLayerStats(
|
|
|
|
getLinkLayerStats_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getLinkLayerStatsInternal,
|
|
|
|
hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2018-08-07 20:04:34 +02:00
|
|
|
Return<void> WifiStaIface::getLinkLayerStats_1_3(
|
|
|
|
getLinkLayerStats_1_3_cb hidl_status_cb) {
|
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getLinkLayerStatsInternal_1_3,
|
|
|
|
hidl_status_cb);
|
|
|
|
}
|
|
|
|
|
2016-12-06 19:04:05 +01:00
|
|
|
Return<void> WifiStaIface::startRssiMonitoring(
|
2017-10-07 01:30:38 +02:00
|
|
|
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
|
2016-12-06 19:04:05 +01:00
|
|
|
startRssiMonitoring_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::startRssiMonitoringInternal,
|
|
|
|
hidl_status_cb, cmd_id, max_rssi, min_rssi);
|
2016-12-06 19:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::stopRssiMonitoring(
|
|
|
|
uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::stopRssiMonitoringInternal,
|
|
|
|
hidl_status_cb, cmd_id);
|
2016-12-06 19:04:05 +01:00
|
|
|
}
|
|
|
|
|
2016-12-13 23:25:45 +01:00
|
|
|
Return<void> WifiStaIface::getRoamingCapabilities(
|
|
|
|
getRoamingCapabilities_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getRoamingCapabilitiesInternal,
|
|
|
|
hidl_status_cb);
|
2016-12-13 23:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::configureRoaming(
|
|
|
|
const StaRoamingConfig& config, configureRoaming_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::configureRoamingInternal,
|
|
|
|
hidl_status_cb, config);
|
2016-12-13 23:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::setRoamingState(StaRoamingState state,
|
|
|
|
setRoamingState_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::setRoamingStateInternal,
|
|
|
|
hidl_status_cb, state);
|
2016-12-13 23:25:45 +01:00
|
|
|
}
|
|
|
|
|
2017-01-12 00:37:25 +01:00
|
|
|
Return<void> WifiStaIface::enableNdOffload(bool enable,
|
|
|
|
enableNdOffload_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::enableNdOffloadInternal,
|
|
|
|
hidl_status_cb, enable);
|
2017-01-12 00:37:25 +01:00
|
|
|
}
|
|
|
|
|
2017-01-12 01:42:16 +01:00
|
|
|
Return<void> WifiStaIface::startSendingKeepAlivePackets(
|
2017-10-07 01:30:38 +02:00
|
|
|
uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data,
|
|
|
|
uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address,
|
|
|
|
const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms,
|
2017-01-12 01:42:16 +01:00
|
|
|
startSendingKeepAlivePackets_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::startSendingKeepAlivePacketsInternal,
|
|
|
|
hidl_status_cb, cmd_id, ip_packet_data, ether_type,
|
|
|
|
src_address, dst_address, period_in_ms);
|
2017-01-12 01:42:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::stopSendingKeepAlivePackets(
|
|
|
|
uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::stopSendingKeepAlivePacketsInternal,
|
|
|
|
hidl_status_cb, cmd_id);
|
2017-01-12 01:42:16 +01:00
|
|
|
}
|
|
|
|
|
2017-02-01 22:09:08 +01:00
|
|
|
Return<void> WifiStaIface::setScanningMacOui(
|
|
|
|
const hidl_array<uint8_t, 3>& oui, setScanningMacOui_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::setScanningMacOuiInternal,
|
|
|
|
hidl_status_cb, oui);
|
2017-02-01 22:09:08 +01:00
|
|
|
}
|
|
|
|
|
2016-10-27 23:36:26 +02:00
|
|
|
Return<void> WifiStaIface::startDebugPacketFateMonitoring(
|
|
|
|
startDebugPacketFateMonitoring_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(
|
|
|
|
this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::getDebugTxPacketFates(
|
|
|
|
getDebugTxPacketFates_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getDebugTxPacketFatesInternal,
|
|
|
|
hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Return<void> WifiStaIface::getDebugRxPacketFates(
|
|
|
|
getDebugRxPacketFates_cb hidl_status_cb) {
|
2017-10-07 01:30:38 +02:00
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getDebugRxPacketFatesInternal,
|
|
|
|
hidl_status_cb);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2018-03-17 00:21:49 +01:00
|
|
|
Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
|
|
|
|
setMacAddress_cb hidl_status_cb) {
|
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::setMacAddressInternal, hidl_status_cb,
|
|
|
|
mac);
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:57:26 +02:00
|
|
|
Return<void> WifiStaIface::getFactoryMacAddress(
|
|
|
|
getFactoryMacAddress_cb hidl_status_cb) {
|
|
|
|
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
|
|
|
&WifiStaIface::getFactoryMacAddressInternal,
|
|
|
|
hidl_status_cb);
|
|
|
|
}
|
|
|
|
|
2016-10-27 21:48:12 +02:00
|
|
|
std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
|
2016-10-27 21:48:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA};
|
2016-10-06 22:16:23 +02:00
|
|
|
}
|
|
|
|
|
2016-10-27 23:36:26 +02:00
|
|
|
WifiStatus WifiStaIface::registerEventCallbackInternal(
|
|
|
|
const sp<IWifiStaIfaceEventCallback>& callback) {
|
2017-10-07 01:30:38 +02:00
|
|
|
if (!event_cb_handler_.addCallback(callback)) {
|
|
|
|
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
|
|
|
|
}
|
|
|
|
return createWifiStatus(WifiStatusCode::SUCCESS);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
|
2019-12-10 00:24:16 +01:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
uint64_t legacy_feature_set;
|
|
|
|
std::tie(legacy_status, legacy_feature_set) =
|
|
|
|
legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), 0};
|
|
|
|
}
|
|
|
|
uint32_t legacy_logger_feature_set;
|
|
|
|
std::tie(legacy_status, legacy_logger_feature_set) =
|
|
|
|
legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
// some devices don't support querying logger feature set
|
|
|
|
legacy_logger_feature_set = 0;
|
|
|
|
}
|
|
|
|
uint32_t hidl_caps;
|
|
|
|
if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
|
|
|
|
legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, StaApfPacketFilterCapabilities>
|
|
|
|
WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
legacy_hal::PacketFilterCapabilities legacy_caps;
|
|
|
|
std::tie(legacy_status, legacy_caps) =
|
|
|
|
legacy_hal_.lock()->getPacketFilterCapabilities(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), {}};
|
|
|
|
}
|
|
|
|
StaApfPacketFilterCapabilities hidl_caps;
|
|
|
|
if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps,
|
|
|
|
&hidl_caps)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::installApfPacketFilterInternal(
|
2016-12-06 00:25:51 +01:00
|
|
|
uint32_t /* cmd_id */, const std::vector<uint8_t>& program) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->setPacketFilter(ifname_, program);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2018-03-06 16:17:50 +01:00
|
|
|
std::pair<WifiStatus, std::vector<uint8_t>>
|
|
|
|
WifiStaIface::readApfPacketFilterDataInternal() {
|
|
|
|
const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>>
|
|
|
|
legacy_status_and_data =
|
|
|
|
legacy_hal_.lock()->readApfPacketFilterData(ifname_);
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status_and_data.first),
|
|
|
|
std::move(legacy_status_and_data.second)};
|
|
|
|
}
|
|
|
|
|
2016-10-27 23:36:26 +02:00
|
|
|
std::pair<WifiStatus, StaBackgroundScanCapabilities>
|
|
|
|
WifiStaIface::getBackgroundScanCapabilitiesInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
legacy_hal::wifi_gscan_capabilities legacy_caps;
|
|
|
|
std::tie(legacy_status, legacy_caps) =
|
|
|
|
legacy_hal_.lock()->getGscanCapabilities(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), {}};
|
|
|
|
}
|
|
|
|
StaBackgroundScanCapabilities hidl_caps;
|
|
|
|
if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps,
|
|
|
|
&hidl_caps)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
|
2019-11-16 03:19:15 +01:00
|
|
|
WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
|
2017-10-07 01:30:38 +02:00
|
|
|
static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
|
|
|
|
"Size mismatch");
|
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
std::vector<uint32_t> valid_frequencies;
|
|
|
|
std::tie(legacy_status, valid_frequencies) =
|
|
|
|
legacy_hal_.lock()->getValidFrequenciesForBand(
|
|
|
|
ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::startBackgroundScanInternal(
|
2016-12-06 00:25:51 +01:00
|
|
|
uint32_t cmd_id, const StaBackgroundScanParameters& params) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_scan_cmd_params legacy_params;
|
|
|
|
if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params,
|
|
|
|
&legacy_params)) {
|
|
|
|
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
|
|
|
}
|
|
|
|
android::wp<WifiStaIface> weak_ptr_this(this);
|
|
|
|
const auto& on_failure_callback =
|
|
|
|
[weak_ptr_this](legacy_hal::wifi_request_id id) {
|
|
|
|
const auto shared_ptr_this = weak_ptr_this.promote();
|
|
|
|
if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
|
|
|
|
LOG(ERROR) << "Callback invoked on an invalid object";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
|
|
|
|
if (!callback->onBackgroundScanFailure(id).isOk()) {
|
|
|
|
LOG(ERROR)
|
|
|
|
<< "Failed to invoke onBackgroundScanFailure callback";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const auto& on_results_callback =
|
|
|
|
[weak_ptr_this](
|
|
|
|
legacy_hal::wifi_request_id id,
|
|
|
|
const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
|
|
|
|
const auto shared_ptr_this = weak_ptr_this.promote();
|
|
|
|
if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
|
|
|
|
LOG(ERROR) << "Callback invoked on an invalid object";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
std::vector<StaScanData> hidl_scan_datas;
|
|
|
|
if (!hidl_struct_util::
|
|
|
|
convertLegacyVectorOfCachedGscanResultsToHidl(
|
|
|
|
results, &hidl_scan_datas)) {
|
|
|
|
LOG(ERROR) << "Failed to convert scan results to HIDL structs";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
|
|
|
|
if (!callback->onBackgroundScanResults(id, hidl_scan_datas)
|
|
|
|
.isOk()) {
|
|
|
|
LOG(ERROR)
|
|
|
|
<< "Failed to invoke onBackgroundScanResults callback";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const auto& on_full_result_callback = [weak_ptr_this](
|
|
|
|
legacy_hal::wifi_request_id id,
|
|
|
|
const legacy_hal::
|
|
|
|
wifi_scan_result* result,
|
|
|
|
uint32_t buckets_scanned) {
|
2016-12-06 00:25:51 +01:00
|
|
|
const auto shared_ptr_this = weak_ptr_this.promote();
|
|
|
|
if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
|
2017-10-07 01:30:38 +02:00
|
|
|
LOG(ERROR) << "Callback invoked on an invalid object";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
StaScanResult hidl_scan_result;
|
|
|
|
if (!hidl_struct_util::convertLegacyGscanResultToHidl(
|
|
|
|
*result, true, &hidl_scan_result)) {
|
|
|
|
LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
|
|
|
|
return;
|
2016-12-06 00:25:51 +01:00
|
|
|
}
|
|
|
|
for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
|
2017-10-07 01:30:38 +02:00
|
|
|
if (!callback
|
|
|
|
->onBackgroundFullScanResult(id, buckets_scanned,
|
|
|
|
hidl_scan_result)
|
|
|
|
.isOk()) {
|
|
|
|
LOG(ERROR)
|
|
|
|
<< "Failed to invoke onBackgroundFullScanResult callback";
|
|
|
|
}
|
2016-12-06 00:25:51 +01:00
|
|
|
}
|
2017-10-07 01:30:38 +02:00
|
|
|
};
|
|
|
|
legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startGscan(
|
|
|
|
ifname_, cmd_id, legacy_params, on_failure_callback,
|
|
|
|
on_results_callback, on_full_result_callback);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-12-06 00:25:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->stopGscan(ifname_, cmd_id);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-12-06 00:25:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->disableLinkLayerStats(ifname_);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2018-08-07 20:04:34 +02:00
|
|
|
std::pair<WifiStatus, V1_0::StaLinkLayerStats>
|
2016-10-27 23:36:26 +02:00
|
|
|
WifiStaIface::getLinkLayerStatsInternal() {
|
2018-08-07 20:04:34 +02:00
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, V1_3::StaLinkLayerStats>
|
|
|
|
WifiStaIface::getLinkLayerStatsInternal_1_3() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
legacy_hal::LinkLayerStats legacy_stats;
|
|
|
|
std::tie(legacy_status, legacy_stats) =
|
|
|
|
legacy_hal_.lock()->getLinkLayerStats(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), {}};
|
|
|
|
}
|
2018-08-07 20:04:34 +02:00
|
|
|
V1_3::StaLinkLayerStats hidl_stats;
|
2017-10-07 01:30:38 +02:00
|
|
|
if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
|
|
|
|
&hidl_stats)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2016-12-06 19:04:05 +01:00
|
|
|
WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id,
|
|
|
|
int32_t max_rssi,
|
|
|
|
int32_t min_rssi) {
|
2017-10-07 01:30:38 +02:00
|
|
|
android::wp<WifiStaIface> weak_ptr_this(this);
|
|
|
|
const auto& on_threshold_breached_callback =
|
|
|
|
[weak_ptr_this](legacy_hal::wifi_request_id id,
|
|
|
|
std::array<uint8_t, 6> bssid, int8_t rssi) {
|
|
|
|
const auto shared_ptr_this = weak_ptr_this.promote();
|
|
|
|
if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
|
|
|
|
LOG(ERROR) << "Callback invoked on an invalid object";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
|
|
|
|
if (!callback->onRssiThresholdBreached(id, bssid, rssi)
|
|
|
|
.isOk()) {
|
|
|
|
LOG(ERROR)
|
|
|
|
<< "Failed to invoke onRssiThresholdBreached callback";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->startRssiMonitoring(ifname_, cmd_id, max_rssi,
|
|
|
|
min_rssi,
|
|
|
|
on_threshold_breached_callback);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-12-06 19:04:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-12-06 19:04:05 +01:00
|
|
|
}
|
|
|
|
|
2016-12-13 23:25:45 +01:00
|
|
|
std::pair<WifiStatus, StaRoamingCapabilities>
|
|
|
|
WifiStaIface::getRoamingCapabilitiesInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
legacy_hal::wifi_roaming_capabilities legacy_caps;
|
|
|
|
std::tie(legacy_status, legacy_caps) =
|
|
|
|
legacy_hal_.lock()->getRoamingCapabilities(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), {}};
|
|
|
|
}
|
|
|
|
StaRoamingCapabilities hidl_caps;
|
|
|
|
if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps,
|
|
|
|
&hidl_caps)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
|
2016-12-13 23:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::configureRoamingInternal(
|
|
|
|
const StaRoamingConfig& config) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_roaming_config legacy_config;
|
|
|
|
if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config,
|
|
|
|
&legacy_config)) {
|
|
|
|
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
|
|
|
}
|
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->configureRoaming(ifname_, legacy_config);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-12-13 23:25:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->enableFirmwareRoaming(
|
|
|
|
ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state));
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-12-13 23:25:45 +01:00
|
|
|
}
|
|
|
|
|
2017-01-12 00:37:25 +01:00
|
|
|
WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->configureNdOffload(ifname_, enable);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2017-01-12 00:37:25 +01:00
|
|
|
}
|
|
|
|
|
2017-01-12 01:42:16 +01:00
|
|
|
WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
|
2017-10-07 01:30:38 +02:00
|
|
|
uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data,
|
2019-03-06 02:38:06 +01:00
|
|
|
uint16_t ether_type, const std::array<uint8_t, 6>& src_address,
|
2017-10-07 01:30:38 +02:00
|
|
|
const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
|
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->startSendingOffloadedPacket(
|
2019-03-06 02:38:06 +01:00
|
|
|
ifname_, cmd_id, ether_type, ip_packet_data, src_address,
|
|
|
|
dst_address, period_in_ms);
|
2017-10-07 01:30:38 +02:00
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2017-01-12 01:42:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2017-01-12 01:42:16 +01:00
|
|
|
}
|
|
|
|
|
2017-01-31 22:13:28 +01:00
|
|
|
WifiStatus WifiStaIface::setScanningMacOuiInternal(
|
2020-04-17 01:18:23 +02:00
|
|
|
const std::array<uint8_t, 3>& /* oui */) {
|
|
|
|
// deprecated.
|
|
|
|
return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
|
2017-02-01 22:09:08 +01:00
|
|
|
}
|
|
|
|
|
2016-10-27 23:36:26 +02:00
|
|
|
WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status =
|
|
|
|
legacy_hal_.lock()->startPktFateMonitoring(ifname_);
|
|
|
|
return createWifiStatusFromLegacyError(legacy_status);
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
|
|
|
|
WifiStaIface::getDebugTxPacketFatesInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
std::vector<legacy_hal::wifi_tx_report> legacy_fates;
|
|
|
|
std::tie(legacy_status, legacy_fates) =
|
|
|
|
legacy_hal_.lock()->getTxPktFates(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), {}};
|
|
|
|
}
|
|
|
|
std::vector<WifiDebugTxPacketFateReport> hidl_fates;
|
|
|
|
if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(
|
|
|
|
legacy_fates, &hidl_fates)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
|
|
|
|
WifiStaIface::getDebugRxPacketFatesInternal() {
|
2017-10-07 01:30:38 +02:00
|
|
|
legacy_hal::wifi_error legacy_status;
|
|
|
|
std::vector<legacy_hal::wifi_rx_report> legacy_fates;
|
|
|
|
std::tie(legacy_status, legacy_fates) =
|
|
|
|
legacy_hal_.lock()->getRxPktFates(ifname_);
|
|
|
|
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
|
|
|
return {createWifiStatusFromLegacyError(legacy_status), {}};
|
|
|
|
}
|
|
|
|
std::vector<WifiDebugRxPacketFateReport> hidl_fates;
|
|
|
|
if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(
|
|
|
|
legacy_fates, &hidl_fates)) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
|
|
|
|
}
|
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
|
2016-10-27 23:36:26 +02:00
|
|
|
}
|
|
|
|
|
2018-03-17 00:21:49 +01:00
|
|
|
WifiStatus WifiStaIface::setMacAddressInternal(
|
|
|
|
const std::array<uint8_t, 6>& mac) {
|
2019-02-14 16:57:10 +01:00
|
|
|
bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
|
|
|
|
if (!status) {
|
2018-03-17 00:21:49 +01:00
|
|
|
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
|
|
|
|
}
|
|
|
|
return createWifiStatus(WifiStatusCode::SUCCESS);
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:57:26 +02:00
|
|
|
std::pair<WifiStatus, std::array<uint8_t, 6>>
|
|
|
|
WifiStaIface::getFactoryMacAddressInternal() {
|
|
|
|
std::array<uint8_t, 6> mac =
|
2019-02-14 16:57:10 +01:00
|
|
|
iface_util_.lock()->getFactoryMacAddress(ifname_);
|
2020-11-11 18:41:30 +01:00
|
|
|
if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 &&
|
|
|
|
mac[4] == 0 && mac[5] == 0) {
|
|
|
|
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
|
|
|
|
}
|
2018-08-09 03:57:26 +02:00
|
|
|
return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
|
|
|
|
}
|
|
|
|
|
2016-10-06 22:16:23 +02:00
|
|
|
} // namespace implementation
|
2019-07-24 00:02:22 +02:00
|
|
|
} // namespace V1_4
|
2016-10-06 22:16:23 +02:00
|
|
|
} // namespace wifi
|
|
|
|
} // namespace hardware
|
|
|
|
} // namespace android
|