mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Merge changes I017d3528,Ie5444041,Iff873784,I1049176a,I8575df02, ...
* changes: wifi(implementation): Load wifi driver on IWifi.start() wifi(implementation): Different names for concurrent ifaces wifi(implementation): Add iface combo for 2018 wifi(implementation): Unit tests for V1 & V2 iface combos wifi(implementation): Add unit test framework wifi(implementation): Support multiple ifaces of same type
This commit is contained in:
@@ -13,21 +13,27 @@
|
||||
# limitations under the License.
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
###
|
||||
### android.hardware.wifi static library
|
||||
###
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.wifi@1.0-service
|
||||
LOCAL_MODULE := android.hardware.wifi@1.0-service-lib
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
|
||||
ifdef WIFI_HIDL_FEATURE_AWARE
|
||||
LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_AWARE
|
||||
endif
|
||||
ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
|
||||
LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DUAL_INTERFACE
|
||||
endif
|
||||
LOCAL_SRC_FILES := \
|
||||
hidl_struct_util.cpp \
|
||||
hidl_sync_util.cpp \
|
||||
service.cpp \
|
||||
wifi.cpp \
|
||||
wifi_ap_iface.cpp \
|
||||
wifi_chip.cpp \
|
||||
wifi_feature_flags.cpp \
|
||||
wifi_legacy_hal.cpp \
|
||||
wifi_legacy_hal_stubs.cpp \
|
||||
wifi_mode_controller.cpp \
|
||||
@@ -49,5 +55,64 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
android.hardware.wifi@1.0 \
|
||||
android.hardware.wifi@1.1 \
|
||||
android.hardware.wifi@1.2
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
###
|
||||
### android.hardware.wifi daemon
|
||||
###
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.wifi@1.0-service
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
|
||||
LOCAL_SRC_FILES := \
|
||||
service.cpp
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libcutils \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libnl \
|
||||
libutils \
|
||||
libwifi-hal \
|
||||
libwifi-system-iface \
|
||||
android.hardware.wifi@1.0 \
|
||||
android.hardware.wifi@1.1 \
|
||||
android.hardware.wifi@1.2
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
android.hardware.wifi@1.0-service-lib
|
||||
LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
###
|
||||
### android.hardware.wifi unit tests.
|
||||
###
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.wifi@1.0-service-tests
|
||||
LOCAL_PROPRIETARY_MODULE := true
|
||||
LOCAL_SRC_FILES := \
|
||||
tests/main.cpp \
|
||||
tests/mock_wifi_feature_flags.cpp \
|
||||
tests/mock_wifi_legacy_hal.cpp \
|
||||
tests/mock_wifi_mode_controller.cpp \
|
||||
tests/wifi_chip_unit_tests.cpp
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libgmock \
|
||||
libgtest \
|
||||
android.hardware.wifi@1.0-service-lib
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbase \
|
||||
libcutils \
|
||||
libhidlbase \
|
||||
libhidltransport \
|
||||
liblog \
|
||||
libnl \
|
||||
libutils \
|
||||
libwifi-hal \
|
||||
libwifi-system-iface \
|
||||
android.hardware.wifi@1.0 \
|
||||
android.hardware.wifi@1.1 \
|
||||
android.hardware.wifi@1.2
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
||||
@@ -20,9 +20,17 @@
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include "wifi.h"
|
||||
#include "wifi_feature_flags.h"
|
||||
#include "wifi_legacy_hal.h"
|
||||
#include "wifi_mode_controller.h"
|
||||
|
||||
using android::hardware::configureRpcThreadpool;
|
||||
using android::hardware::joinRpcThreadpool;
|
||||
using android::hardware::wifi::V1_2::implementation::feature_flags::
|
||||
WifiFeatureFlags;
|
||||
using android::hardware::wifi::V1_2::implementation::legacy_hal::WifiLegacyHal;
|
||||
using android::hardware::wifi::V1_2::implementation::mode_controller::
|
||||
WifiModeController;
|
||||
|
||||
int main(int /*argc*/, char** argv) {
|
||||
android::base::InitLogging(
|
||||
@@ -33,7 +41,10 @@ int main(int /*argc*/, char** argv) {
|
||||
|
||||
// Setup hwbinder service
|
||||
android::sp<android::hardware::wifi::V1_2::IWifi> service =
|
||||
new android::hardware::wifi::V1_2::implementation::Wifi();
|
||||
new android::hardware::wifi::V1_2::implementation::Wifi(
|
||||
std::make_shared<WifiLegacyHal>(),
|
||||
std::make_shared<WifiModeController>(),
|
||||
std::make_shared<WifiFeatureFlags>());
|
||||
CHECK_EQ(service->registerAsService(), android::NO_ERROR)
|
||||
<< "Failed to register wifi HAL";
|
||||
|
||||
|
||||
28
wifi/1.2/default/tests/main.cpp
Normal file
28
wifi/1.2/default/tests/main.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
::testing::InitGoogleMock(&argc, argv);
|
||||
// Force ourselves to always log to stderr
|
||||
android::base::InitLogging(argv, android::base::StderrLogger);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
35
wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
Normal file
35
wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 <gmock/gmock.h>
|
||||
|
||||
#include "mock_wifi_feature_flags.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace feature_flags {
|
||||
|
||||
MockWifiFeatureFlags::MockWifiFeatureFlags() {}
|
||||
|
||||
} // namespace feature_flags
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
46
wifi/1.2/default/tests/mock_wifi_feature_flags.h
Normal file
46
wifi/1.2/default/tests/mock_wifi_feature_flags.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef MOCK_WIFI_FEATURE_FLAGS_H_
|
||||
#define MOCK_WIFI_FEATURE_FLAGS_H_
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "wifi_feature_flags.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace feature_flags {
|
||||
|
||||
class MockWifiFeatureFlags : public WifiFeatureFlags {
|
||||
public:
|
||||
MockWifiFeatureFlags();
|
||||
|
||||
MOCK_METHOD0(isAwareSupported, bool());
|
||||
MOCK_METHOD0(isDualInterfaceSupported, bool());
|
||||
};
|
||||
|
||||
} // namespace feature_flags
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // MOCK_WIFI_FEATURE_FLAGS_H_
|
||||
37
wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
Normal file
37
wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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>
|
||||
#include <android-base/macros.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
|
||||
#include "mock_wifi_legacy_hal.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace legacy_hal {
|
||||
|
||||
MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {}
|
||||
} // namespace legacy_hal
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
54
wifi/1.2/default/tests/mock_wifi_legacy_hal.h
Normal file
54
wifi/1.2/default/tests/mock_wifi_legacy_hal.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef MOCK_WIFI_LEGACY_HAL_H_
|
||||
#define MOCK_WIFI_LEGACY_HAL_H_
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "wifi_legacy_hal.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace legacy_hal {
|
||||
|
||||
class MockWifiLegacyHal : public WifiLegacyHal {
|
||||
public:
|
||||
MockWifiLegacyHal();
|
||||
MOCK_METHOD0(initialize, wifi_error());
|
||||
MOCK_METHOD0(start, wifi_error());
|
||||
MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*,
|
||||
const std::function<void()>&));
|
||||
MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool));
|
||||
MOCK_METHOD2(nanRegisterCallbackHandlers,
|
||||
wifi_error(const std::string&, const NanCallbackHandlers&));
|
||||
MOCK_METHOD2(nanDisableRequest,
|
||||
wifi_error(const std::string&, transaction_id));
|
||||
MOCK_METHOD3(nanDataInterfaceDelete,
|
||||
wifi_error(const std::string&, transaction_id,
|
||||
const std::string&));
|
||||
};
|
||||
} // namespace legacy_hal
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // MOCK_WIFI_LEGACY_HAL_H_
|
||||
37
wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
Normal file
37
wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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>
|
||||
#include <android-base/macros.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
|
||||
#include "mock_wifi_mode_controller.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace mode_controller {
|
||||
|
||||
MockWifiModeController::MockWifiModeController() : WifiModeController() {}
|
||||
} // namespace mode_controller
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
46
wifi/1.2/default/tests/mock_wifi_mode_controller.h
Normal file
46
wifi/1.2/default/tests/mock_wifi_mode_controller.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#ifndef MOCK_WIFI_MODE_CONTROLLER_H_
|
||||
#define MOCK_WIFI_MODE_CONTROLLER_H_
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "wifi_mode_controller.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace mode_controller {
|
||||
|
||||
class MockWifiModeController : public WifiModeController {
|
||||
public:
|
||||
MockWifiModeController();
|
||||
MOCK_METHOD0(initialize, bool());
|
||||
MOCK_METHOD1(changeFirmwareMode, bool(IfaceType));
|
||||
MOCK_METHOD1(isFirmwareModeChangeNeeded, bool(IfaceType));
|
||||
MOCK_METHOD0(deinitialize, bool());
|
||||
};
|
||||
} // namespace mode_controller
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // MOCK_WIFI_MODE_CONTROLLER_H_
|
||||
50
wifi/1.2/default/tests/runtests.sh
Executable file
50
wifi/1.2/default/tests/runtests.sh
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright(C) 2017 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.
|
||||
|
||||
if [ -z $ANDROID_BUILD_TOP ]; then
|
||||
echo "You need to source and lunch before you can use this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running tests"
|
||||
set -e # fail early
|
||||
|
||||
#NOTE We can't actually run these commands, since they rely on functions added by
|
||||
#build / envsetup.sh to the bash shell environment.
|
||||
echo "+ mmma -j32 $ANDROID_BUILD_TOP/"
|
||||
make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk \
|
||||
MODULES-IN-hardware-interfaces-wifi-1.2-default
|
||||
|
||||
set -x # print commands
|
||||
|
||||
adb wait-for-device
|
||||
adb root
|
||||
adb wait-for-device
|
||||
|
||||
#'disable-verity' will appear in 'adb remount' output if
|
||||
#dm - verity is enabled and needs to be disabled.
|
||||
if adb remount | grep 'disable-verity'; then
|
||||
adb disable-verity
|
||||
adb reboot
|
||||
adb wait-for-device
|
||||
adb root
|
||||
adb wait-for-device
|
||||
adb remount
|
||||
fi
|
||||
|
||||
adb sync
|
||||
|
||||
adb shell /data/nativetest/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests
|
||||
547
wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
Normal file
547
wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
/*
|
||||
* Copyright (C) 2017, 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>
|
||||
#include <android-base/macros.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
|
||||
#include "wifi_chip.h"
|
||||
|
||||
#include "mock_wifi_feature_flags.h"
|
||||
#include "mock_wifi_legacy_hal.h"
|
||||
#include "mock_wifi_mode_controller.h"
|
||||
|
||||
using testing::NiceMock;
|
||||
using testing::Return;
|
||||
using testing::Test;
|
||||
|
||||
namespace {
|
||||
using android::hardware::wifi::V1_0::ChipId;
|
||||
|
||||
constexpr ChipId kFakeChipId = 5;
|
||||
} // namespace
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
|
||||
class WifiChipTest : public Test {
|
||||
protected:
|
||||
void setupV1IfaceCombination() {
|
||||
EXPECT_CALL(*feature_flags_, isAwareSupported())
|
||||
.WillRepeatedly(testing::Return(false));
|
||||
EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
|
||||
.WillRepeatedly(testing::Return(false));
|
||||
}
|
||||
|
||||
void setupV1_AwareIfaceCombination() {
|
||||
EXPECT_CALL(*feature_flags_, isAwareSupported())
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
|
||||
.WillRepeatedly(testing::Return(false));
|
||||
}
|
||||
|
||||
void setupV2_AwareIfaceCombination() {
|
||||
EXPECT_CALL(*feature_flags_, isAwareSupported())
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
}
|
||||
|
||||
void assertNumberOfModes(uint32_t num_modes) {
|
||||
chip_->getAvailableModes(
|
||||
[num_modes](const WifiStatus& status,
|
||||
const std::vector<WifiChip::ChipMode>& modes) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
// V2_Aware has 1 mode of operation.
|
||||
ASSERT_EQ(num_modes, modes.size());
|
||||
});
|
||||
}
|
||||
|
||||
void findModeAndConfigureForIfaceType(const IfaceType& type) {
|
||||
// This should be aligned with kInvalidModeId in wifi_chip.cpp.
|
||||
ChipModeId mode_id = UINT32_MAX;
|
||||
chip_->getAvailableModes(
|
||||
[&mode_id, &type](const WifiStatus& status,
|
||||
const std::vector<WifiChip::ChipMode>& modes) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
for (const auto& mode : modes) {
|
||||
for (const auto& combination : mode.availableCombinations) {
|
||||
for (const auto& limit : combination.limits) {
|
||||
if (limit.types.end() !=
|
||||
std::find(limit.types.begin(),
|
||||
limit.types.end(), type)) {
|
||||
mode_id = mode.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ASSERT_NE(UINT32_MAX, mode_id);
|
||||
|
||||
chip_->configureChip(mode_id, [](const WifiStatus& status) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
});
|
||||
}
|
||||
|
||||
// Returns an empty string on error.
|
||||
std::string createIface(const IfaceType& type) {
|
||||
std::string iface_name;
|
||||
if (type == IfaceType::AP) {
|
||||
chip_->createApIface([&iface_name](const WifiStatus& status,
|
||||
const sp<IWifiApIface>& iface) {
|
||||
if (WifiStatusCode::SUCCESS == status.code) {
|
||||
ASSERT_NE(iface.get(), nullptr);
|
||||
iface->getName([&iface_name](const WifiStatus& status,
|
||||
const hidl_string& name) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
iface_name = name.c_str();
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (type == IfaceType::NAN) {
|
||||
chip_->createNanIface(
|
||||
[&iface_name](const WifiStatus& status,
|
||||
const sp<IWifiNanIface>& iface) {
|
||||
if (WifiStatusCode::SUCCESS == status.code) {
|
||||
ASSERT_NE(iface.get(), nullptr);
|
||||
iface->getName([&iface_name](const WifiStatus& status,
|
||||
const hidl_string& name) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
iface_name = name.c_str();
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (type == IfaceType::P2P) {
|
||||
chip_->createP2pIface(
|
||||
[&iface_name](const WifiStatus& status,
|
||||
const sp<IWifiP2pIface>& iface) {
|
||||
if (WifiStatusCode::SUCCESS == status.code) {
|
||||
ASSERT_NE(iface.get(), nullptr);
|
||||
iface->getName([&iface_name](const WifiStatus& status,
|
||||
const hidl_string& name) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
iface_name = name.c_str();
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (type == IfaceType::STA) {
|
||||
chip_->createStaIface(
|
||||
[&iface_name](const WifiStatus& status,
|
||||
const sp<IWifiStaIface>& iface) {
|
||||
if (WifiStatusCode::SUCCESS == status.code) {
|
||||
ASSERT_NE(iface.get(), nullptr);
|
||||
iface->getName([&iface_name](const WifiStatus& status,
|
||||
const hidl_string& name) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
iface_name = name.c_str();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return iface_name;
|
||||
}
|
||||
|
||||
void removeIface(const IfaceType& type, const std::string& iface_name) {
|
||||
if (type == IfaceType::AP) {
|
||||
chip_->removeApIface(iface_name, [](const WifiStatus& status) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
});
|
||||
} else if (type == IfaceType::NAN) {
|
||||
chip_->removeNanIface(iface_name, [](const WifiStatus& status) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
});
|
||||
} else if (type == IfaceType::P2P) {
|
||||
chip_->removeP2pIface(iface_name, [](const WifiStatus& status) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
});
|
||||
} else if (type == IfaceType::STA) {
|
||||
chip_->removeStaIface(iface_name, [](const WifiStatus& status) {
|
||||
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
|
||||
feature_flags_);
|
||||
|
||||
EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
EXPECT_CALL(*legacy_hal_, start())
|
||||
.WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
|
||||
}
|
||||
|
||||
private:
|
||||
sp<WifiChip> chip_;
|
||||
ChipId chip_id_ = kFakeChipId;
|
||||
std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
|
||||
new NiceMock<legacy_hal::MockWifiLegacyHal>};
|
||||
std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
|
||||
mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
|
||||
std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
|
||||
feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
|
||||
};
|
||||
|
||||
////////// V1 Iface Combinations ////////////
|
||||
// Mode 1 - STA + P2P
|
||||
// Mode 2 - AP
|
||||
class WifiChipV1IfaceCombinationTest : public WifiChipTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
setupV1IfaceCombination();
|
||||
WifiChipTest::SetUp();
|
||||
// V1 has 2 modes of operation.
|
||||
assertNumberOfModes(2u);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateNan_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_TRUE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_TRUE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_TRUE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
////////// V1 + Aware Iface Combinations ////////////
|
||||
// Mode 1 - STA + P2P/NAN
|
||||
// Mode 2 - AP
|
||||
class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
setupV1_AwareIfaceCombination();
|
||||
WifiChipTest::SetUp();
|
||||
// V1_Aware has 2 modes of operation.
|
||||
assertNumberOfModes(2u);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateNan_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_TRUE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaP2p_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaNan_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaP2PNan_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto p2p_iface_name = createIface(IfaceType::P2P);
|
||||
ASSERT_FALSE(p2p_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
|
||||
// After removing P2P iface, NAN iface creation should succeed.
|
||||
removeIface(IfaceType::P2P, p2p_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto nan_iface_name = createIface(IfaceType::NAN);
|
||||
ASSERT_FALSE(nan_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::P2P).empty());
|
||||
|
||||
// After removing NAN iface, P2P iface creation should succeed.
|
||||
removeIface(IfaceType::NAN, nan_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_TRUE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_TRUE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
////////// V2 + Aware Iface Combinations ////////////
|
||||
// Mode 1 - STA + STA/AP
|
||||
// - STA + P2P/NAN
|
||||
class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
setupV2_AwareIfaceCombination();
|
||||
WifiChipTest::SetUp();
|
||||
// V2_Aware has 1 mode of operation.
|
||||
assertNumberOfModes(1u);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNan_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaStaAp_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
CreateStaAp_AfterStaRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto sta_iface_name = createIface(IfaceType::STA);
|
||||
ASSERT_FALSE(sta_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::AP).empty());
|
||||
|
||||
// After removing STA iface, AP iface creation should succeed.
|
||||
removeIface(IfaceType::STA, sta_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
CreateStaSta_AfterApRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto ap_iface_name = createIface(IfaceType::AP);
|
||||
ASSERT_FALSE(ap_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::STA).empty());
|
||||
|
||||
// After removing AP iface, STA iface creation should succeed.
|
||||
removeIface(IfaceType::AP, ap_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2PNan_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
CreateStaNan_AfterP2pRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto p2p_iface_name = createIface(IfaceType::P2P);
|
||||
ASSERT_FALSE(p2p_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
|
||||
// After removing P2P iface, NAN iface creation should succeed.
|
||||
removeIface(IfaceType::P2P, p2p_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
CreateStaP2p_AfterNanRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto nan_iface_name = createIface(IfaceType::NAN);
|
||||
ASSERT_FALSE(nan_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::P2P).empty());
|
||||
|
||||
// After removing NAN iface, P2P iface creation should succeed.
|
||||
removeIface(IfaceType::NAN, nan_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApNan_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApP2p_ShouldFail) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
ASSERT_FALSE(createIface(IfaceType::AP).empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto p2p_iface_name = createIface(IfaceType::P2P);
|
||||
ASSERT_FALSE(p2p_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
|
||||
|
||||
// After removing P2P iface, NAN iface creation should succeed.
|
||||
removeIface(IfaceType::P2P, p2p_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::NAN).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::STA);
|
||||
ASSERT_FALSE(createIface(IfaceType::STA).empty());
|
||||
const auto nan_iface_name = createIface(IfaceType::NAN);
|
||||
ASSERT_FALSE(nan_iface_name.empty());
|
||||
ASSERT_TRUE(createIface(IfaceType::P2P).empty());
|
||||
|
||||
// After removing NAN iface, P2P iface creation should succeed.
|
||||
removeIface(IfaceType::NAN, nan_iface_name);
|
||||
ASSERT_FALSE(createIface(IfaceType::P2P).empty());
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
CreateStaSta_EnsureDifferentIfaceNames) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
const auto sta1_iface_name = createIface(IfaceType::STA);
|
||||
const auto sta2_iface_name = createIface(IfaceType::STA);
|
||||
ASSERT_FALSE(sta1_iface_name.empty());
|
||||
ASSERT_FALSE(sta2_iface_name.empty());
|
||||
ASSERT_NE(sta1_iface_name, sta2_iface_name);
|
||||
}
|
||||
|
||||
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
|
||||
CreateStaAp_EnsureDifferentIfaceNames) {
|
||||
findModeAndConfigureForIfaceType(IfaceType::AP);
|
||||
const auto sta_iface_name = createIface(IfaceType::STA);
|
||||
const auto ap_iface_name = createIface(IfaceType::AP);
|
||||
ASSERT_FALSE(sta_iface_name.empty());
|
||||
ASSERT_FALSE(ap_iface_name.empty());
|
||||
ASSERT_NE(sta_iface_name, ap_iface_name);
|
||||
}
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -33,9 +33,13 @@ namespace implementation {
|
||||
using hidl_return_util::validateAndCall;
|
||||
using hidl_return_util::validateAndCallWithLock;
|
||||
|
||||
Wifi::Wifi()
|
||||
: legacy_hal_(new legacy_hal::WifiLegacyHal()),
|
||||
mode_controller_(new mode_controller::WifiModeController()),
|
||||
Wifi::Wifi(
|
||||
const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
|
||||
const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
|
||||
: legacy_hal_(legacy_hal),
|
||||
mode_controller_(mode_controller),
|
||||
feature_flags_(feature_flags),
|
||||
run_state_(RunState::STOPPED) {}
|
||||
|
||||
bool Wifi::isValid() {
|
||||
@@ -88,10 +92,11 @@ WifiStatus Wifi::startInternal() {
|
||||
return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
|
||||
"HAL is stopping");
|
||||
}
|
||||
WifiStatus wifi_status = initializeLegacyHal();
|
||||
WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
|
||||
if (wifi_status.code == WifiStatusCode::SUCCESS) {
|
||||
// Create the chip instance once the HAL is started.
|
||||
chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
|
||||
chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
|
||||
feature_flags_);
|
||||
run_state_ = RunState::STARTED;
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onStart().isOk()) {
|
||||
@@ -161,7 +166,11 @@ std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
|
||||
}
|
||||
|
||||
WifiStatus Wifi::initializeLegacyHal() {
|
||||
WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
|
||||
if (!mode_controller_->initialize()) {
|
||||
LOG(ERROR) << "Failed to initialize firmware mode controller";
|
||||
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
|
||||
}
|
||||
legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
|
||||
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
|
||||
LOG(ERROR) << "Failed to initialize legacy HAL: "
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "hidl_callback_util.h"
|
||||
#include "wifi_chip.h"
|
||||
#include "wifi_feature_flags.h"
|
||||
#include "wifi_legacy_hal.h"
|
||||
#include "wifi_mode_controller.h"
|
||||
|
||||
@@ -39,7 +40,10 @@ namespace implementation {
|
||||
*/
|
||||
class Wifi : public V1_2::IWifi {
|
||||
public:
|
||||
Wifi();
|
||||
Wifi(const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::shared_ptr<mode_controller::WifiModeController>
|
||||
mode_controller,
|
||||
const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags);
|
||||
|
||||
bool isValid();
|
||||
|
||||
@@ -64,7 +68,7 @@ class Wifi : public V1_2::IWifi {
|
||||
std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
|
||||
std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
|
||||
|
||||
WifiStatus initializeLegacyHal();
|
||||
WifiStatus initializeModeControllerAndLegacyHal();
|
||||
WifiStatus stopLegacyHalAndDeinitializeModeController(
|
||||
std::unique_lock<std::recursive_mutex>* lock);
|
||||
|
||||
@@ -72,6 +76,7 @@ class Wifi : public V1_2::IWifi {
|
||||
// and shared with all the child HIDL interface objects.
|
||||
std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
|
||||
std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
|
||||
std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
|
||||
RunState run_state_;
|
||||
sp<WifiChip> chip_;
|
||||
hidl_callback_util::HidlCallbackHandler<IWifiEventCallback>
|
||||
|
||||
@@ -40,6 +40,8 @@ void WifiApIface::invalidate() {
|
||||
|
||||
bool WifiApIface::isValid() { return is_valid_; }
|
||||
|
||||
std::string WifiApIface::getName() { return ifname_; }
|
||||
|
||||
Return<void> WifiApIface::getName(getName_cb hidl_status_cb) {
|
||||
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
||||
&WifiApIface::getNameInternal, hidl_status_cb);
|
||||
|
||||
@@ -39,6 +39,7 @@ class WifiApIface : public V1_0::IWifiApIface {
|
||||
// Refer to |WifiChip::invalidate()|.
|
||||
void invalidate();
|
||||
bool isValid();
|
||||
std::string getName();
|
||||
|
||||
// HIDL methods exposed.
|
||||
Return<void> getName(getName_cb hidl_status_cb) override;
|
||||
|
||||
@@ -20,27 +20,59 @@
|
||||
#include "hidl_return_util.h"
|
||||
#include "hidl_struct_util.h"
|
||||
#include "wifi_chip.h"
|
||||
#include "wifi_feature_flags.h"
|
||||
#include "wifi_status_util.h"
|
||||
|
||||
namespace {
|
||||
using android::hardware::hidl_string;
|
||||
using android::hardware::hidl_vec;
|
||||
using android::hardware::wifi::V1_0::ChipModeId;
|
||||
using android::hardware::wifi::V1_0::IWifiChip;
|
||||
using android::hardware::wifi::V1_0::IfaceType;
|
||||
using android::hardware::wifi::V1_0::IWifiChip;
|
||||
using android::sp;
|
||||
|
||||
constexpr ChipModeId kStaChipModeId = 0;
|
||||
constexpr ChipModeId kApChipModeId = 1;
|
||||
constexpr ChipModeId kInvalidModeId = UINT32_MAX;
|
||||
// These mode ID's should be unique (even across combo versions). Refer to
|
||||
// handleChipConfiguration() for it's usage.
|
||||
// Mode ID's for V1
|
||||
constexpr ChipModeId kV1StaChipModeId = 0;
|
||||
constexpr ChipModeId kV1ApChipModeId = 1;
|
||||
// Mode ID for V2
|
||||
constexpr ChipModeId kV2ChipModeId = 2;
|
||||
|
||||
template <typename Iface>
|
||||
void invalidateAndClear(sp<Iface>& iface) {
|
||||
if (iface.get()) {
|
||||
void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
|
||||
iface->invalidate();
|
||||
ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface),
|
||||
ifaces.end());
|
||||
}
|
||||
|
||||
template <typename Iface>
|
||||
void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) {
|
||||
for (const auto& iface : ifaces) {
|
||||
iface->invalidate();
|
||||
iface.clear();
|
||||
}
|
||||
ifaces.clear();
|
||||
}
|
||||
|
||||
template <typename Iface>
|
||||
std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) {
|
||||
std::vector<hidl_string> names;
|
||||
for (const auto& iface : ifaces) {
|
||||
names.emplace_back(iface->getName());
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
template <typename Iface>
|
||||
sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces,
|
||||
const std::string& name) {
|
||||
std::vector<hidl_string> names;
|
||||
for (const auto& iface : ifaces) {
|
||||
if (name == iface->getName()) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string getWlan0IfaceName() {
|
||||
@@ -49,13 +81,11 @@ std::string getWlan0IfaceName() {
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
/** Not used yet.
|
||||
std::string getWlan1IfaceName() {
|
||||
std::array<char, PROPERTY_VALUE_MAX> buffer;
|
||||
property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
|
||||
return buffer.data();
|
||||
std::array<char, PROPERTY_VALUE_MAX> buffer;
|
||||
property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
|
||||
return buffer.data();
|
||||
}
|
||||
*/
|
||||
|
||||
std::string getP2pIfaceName() {
|
||||
std::array<char, PROPERTY_VALUE_MAX> buffer;
|
||||
@@ -75,13 +105,17 @@ using hidl_return_util::validateAndCallWithLock;
|
||||
|
||||
WifiChip::WifiChip(
|
||||
ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::weak_ptr<mode_controller::WifiModeController> mode_controller)
|
||||
const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
|
||||
const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
|
||||
: chip_id_(chip_id),
|
||||
legacy_hal_(legacy_hal),
|
||||
mode_controller_(mode_controller),
|
||||
feature_flags_(feature_flags),
|
||||
is_valid_(true),
|
||||
current_mode_id_(kInvalidModeId),
|
||||
debug_ring_buffer_cb_registered_(false) {}
|
||||
debug_ring_buffer_cb_registered_(false) {
|
||||
populateModes();
|
||||
}
|
||||
|
||||
void WifiChip::invalidate() {
|
||||
invalidateAndRemoveAllIfaces();
|
||||
@@ -317,10 +351,10 @@ Return<void> WifiChip::resetTxPowerScenario(
|
||||
}
|
||||
|
||||
void WifiChip::invalidateAndRemoveAllIfaces() {
|
||||
invalidateAndClear(ap_iface_);
|
||||
invalidateAndClear(nan_iface_);
|
||||
invalidateAndClear(p2p_iface_);
|
||||
invalidateAndClear(sta_iface_);
|
||||
invalidateAndClearAll(ap_ifaces_);
|
||||
invalidateAndClearAll(nan_ifaces_);
|
||||
invalidateAndClearAll(p2p_ifaces_);
|
||||
invalidateAndClearAll(sta_ifaces_);
|
||||
// Since all the ifaces are invalid now, all RTT controller objects
|
||||
// using those ifaces also need to be invalidated.
|
||||
for (const auto& rtt : rtt_controllers_) {
|
||||
@@ -365,43 +399,13 @@ std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
|
||||
|
||||
std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
|
||||
WifiChip::getAvailableModesInternal() {
|
||||
// The chip combination supported for current devices is fixed for now with
|
||||
// 2 separate modes of operation:
|
||||
// Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN iface operations
|
||||
// concurrently [NAN conditional on wifiHidlFeatureAware]
|
||||
// Mode 2 (AP mode): Will support 1 AP iface operations.
|
||||
// TODO (b/32997844): Read this from some device specific flags in the
|
||||
// makefile.
|
||||
// STA mode iface combinations.
|
||||
const IWifiChip::ChipIfaceCombinationLimit
|
||||
sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
|
||||
IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
|
||||
if (WifiFeatureFlags::wifiHidlFeatureAware) {
|
||||
sta_chip_iface_combination_limit_2 = {{IfaceType::P2P, IfaceType::NAN},
|
||||
1};
|
||||
} else {
|
||||
sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
|
||||
}
|
||||
const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
|
||||
{sta_chip_iface_combination_limit_1,
|
||||
sta_chip_iface_combination_limit_2}};
|
||||
const IWifiChip::ChipMode sta_chip_mode = {kStaChipModeId,
|
||||
{sta_chip_iface_combination}};
|
||||
// AP mode iface combinations.
|
||||
const IWifiChip::ChipIfaceCombinationLimit ap_chip_iface_combination_limit =
|
||||
{{IfaceType::AP}, 1};
|
||||
const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
|
||||
{ap_chip_iface_combination_limit}};
|
||||
const IWifiChip::ChipMode ap_chip_mode = {kApChipModeId,
|
||||
{ap_chip_iface_combination}};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS),
|
||||
{sta_chip_mode, ap_chip_mode}};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
|
||||
}
|
||||
|
||||
WifiStatus WifiChip::configureChipInternal(
|
||||
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
|
||||
ChipModeId mode_id) {
|
||||
if (mode_id != kStaChipModeId && mode_id != kApChipModeId) {
|
||||
if (!isValidModeId(mode_id)) {
|
||||
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
||||
}
|
||||
if (mode_id == current_mode_id_) {
|
||||
@@ -429,7 +433,7 @@ WifiStatus WifiChip::configureChipInternal(
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
|
||||
if (current_mode_id_ == kInvalidModeId) {
|
||||
if (!isValidModeId(current_mode_id_)) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
|
||||
current_mode_id_};
|
||||
}
|
||||
@@ -497,40 +501,43 @@ WifiChip::requestFirmwareDebugDumpInternal() {
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
|
||||
if (current_mode_id_ != kApChipModeId || ap_iface_.get()) {
|
||||
if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
|
||||
}
|
||||
std::string ifname = getWlan0IfaceName();
|
||||
ap_iface_ = new WifiApIface(ifname, legacy_hal_);
|
||||
std::string ifname = allocateApOrStaIfaceName();
|
||||
sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_);
|
||||
ap_ifaces_.push_back(iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
|
||||
}
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, std::vector<hidl_string>>
|
||||
WifiChip::getApIfaceNamesInternal() {
|
||||
if (!ap_iface_.get()) {
|
||||
if (ap_ifaces_.empty()) {
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {getWlan0IfaceName()}};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal(
|
||||
const std::string& ifname) {
|
||||
if (!ap_iface_.get() || (ifname != getWlan0IfaceName())) {
|
||||
const auto iface = findUsingName(ap_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
|
||||
if (!ap_iface_.get() || (ifname != getWlan0IfaceName())) {
|
||||
const auto iface = findUsingName(ap_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
||||
}
|
||||
invalidateAndClear(ap_iface_);
|
||||
invalidateAndClear(ap_ifaces_, iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
|
||||
@@ -540,46 +547,44 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
|
||||
// Only 1 of NAN or P2P iface can be active at a time.
|
||||
if (WifiFeatureFlags::wifiHidlFeatureAware) {
|
||||
if (current_mode_id_ != kStaChipModeId || nan_iface_.get() ||
|
||||
p2p_iface_.get()) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
|
||||
}
|
||||
std::string ifname = getWlan0IfaceName();
|
||||
nan_iface_ = new WifiNanIface(ifname, legacy_hal_);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
|
||||
}
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_};
|
||||
} else {
|
||||
if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
|
||||
}
|
||||
// These are still assumed to be based on wlan0.
|
||||
std::string ifname = getWlan0IfaceName();
|
||||
sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
|
||||
nan_ifaces_.push_back(iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
|
||||
}
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, std::vector<hidl_string>>
|
||||
WifiChip::getNanIfaceNamesInternal() {
|
||||
if (!nan_iface_.get()) {
|
||||
if (nan_ifaces_.empty()) {
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {getWlan0IfaceName()}};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal(
|
||||
const std::string& ifname) {
|
||||
if (!nan_iface_.get() || (ifname != getWlan0IfaceName())) {
|
||||
const auto iface = findUsingName(nan_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
|
||||
if (!nan_iface_.get() || (ifname != getWlan0IfaceName())) {
|
||||
const auto iface = findUsingName(nan_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
||||
}
|
||||
invalidateAndClear(nan_iface_);
|
||||
invalidateAndClear(nan_ifaces_, iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
|
||||
@@ -589,42 +594,43 @@ WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
|
||||
// Only 1 of NAN or P2P iface can be active at a time.
|
||||
if (current_mode_id_ != kStaChipModeId || p2p_iface_.get() ||
|
||||
nan_iface_.get()) {
|
||||
if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
|
||||
}
|
||||
std::string ifname = getP2pIfaceName();
|
||||
p2p_iface_ = new WifiP2pIface(ifname, legacy_hal_);
|
||||
sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
|
||||
p2p_ifaces_.push_back(iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
|
||||
}
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, std::vector<hidl_string>>
|
||||
WifiChip::getP2pIfaceNamesInternal() {
|
||||
if (!p2p_iface_.get()) {
|
||||
if (p2p_ifaces_.empty()) {
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {getP2pIfaceName()}};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(
|
||||
const std::string& ifname) {
|
||||
if (!p2p_iface_.get() || (ifname != getP2pIfaceName())) {
|
||||
const auto iface = findUsingName(p2p_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
|
||||
if (!p2p_iface_.get() || (ifname != getP2pIfaceName())) {
|
||||
const auto iface = findUsingName(p2p_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
||||
}
|
||||
invalidateAndClear(p2p_iface_);
|
||||
invalidateAndClear(p2p_ifaces_, iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
|
||||
@@ -634,40 +640,43 @@ WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
|
||||
if (current_mode_id_ != kStaChipModeId || sta_iface_.get()) {
|
||||
if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
|
||||
}
|
||||
std::string ifname = getWlan0IfaceName();
|
||||
sta_iface_ = new WifiStaIface(ifname, legacy_hal_);
|
||||
std::string ifname = allocateApOrStaIfaceName();
|
||||
sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);
|
||||
sta_ifaces_.push_back(iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
|
||||
}
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, std::vector<hidl_string>>
|
||||
WifiChip::getStaIfaceNamesInternal() {
|
||||
if (!sta_iface_.get()) {
|
||||
if (sta_ifaces_.empty()) {
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), {getWlan0IfaceName()}};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
|
||||
}
|
||||
|
||||
std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
|
||||
const std::string& ifname) {
|
||||
if (!sta_iface_.get() || (ifname != getWlan0IfaceName())) {
|
||||
const auto iface = findUsingName(sta_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
|
||||
}
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_};
|
||||
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
|
||||
}
|
||||
|
||||
WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
|
||||
if (!sta_iface_.get() || (ifname != getWlan0IfaceName())) {
|
||||
const auto iface = findUsingName(sta_ifaces_, ifname);
|
||||
if (!iface.get()) {
|
||||
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
|
||||
}
|
||||
invalidateAndClear(sta_iface_);
|
||||
invalidateAndClear(sta_ifaces_, iface);
|
||||
for (const auto& callback : event_cb_handler_.getCallbacks()) {
|
||||
if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
|
||||
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
|
||||
@@ -801,7 +810,7 @@ WifiStatus WifiChip::handleChipConfiguration(
|
||||
ChipModeId mode_id) {
|
||||
// If the chip is already configured in a different mode, stop
|
||||
// the legacy HAL and then start it after firmware mode change.
|
||||
if (current_mode_id_ != kInvalidModeId) {
|
||||
if (isValidModeId(current_mode_id_)) {
|
||||
LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
|
||||
<< " to mode " << mode_id;
|
||||
invalidateAndRemoveAllIfaces();
|
||||
@@ -813,10 +822,11 @@ WifiStatus WifiChip::handleChipConfiguration(
|
||||
return createWifiStatusFromLegacyError(legacy_status);
|
||||
}
|
||||
}
|
||||
bool success;
|
||||
if (mode_id == kStaChipModeId) {
|
||||
// Firmware mode change not needed for V2 devices.
|
||||
bool success = true;
|
||||
if (mode_id == kV1StaChipModeId) {
|
||||
success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
|
||||
} else {
|
||||
} else if (mode_id == kV1ApChipModeId) {
|
||||
success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
|
||||
}
|
||||
if (!success) {
|
||||
@@ -871,6 +881,204 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() {
|
||||
return createWifiStatusFromLegacyError(legacy_status);
|
||||
}
|
||||
|
||||
void WifiChip::populateModes() {
|
||||
// The chip combination supported for current devices is fixed.
|
||||
// They can be one of the following based on device features:
|
||||
// a) 2 separate modes of operation with 1 interface combination each:
|
||||
// Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN(optional)
|
||||
// concurrent iface operations.
|
||||
// Mode 2 (AP mode): Will support 1 AP iface operation.
|
||||
//
|
||||
// b) 1 mode of operation with 2 interface combinations
|
||||
// (conditional on isDualInterfaceSupported()):
|
||||
// Interface Combination 1: Will support 1 STA and 1 P2P or NAN(optional)
|
||||
// concurrent iface operations.
|
||||
// Interface Combination 2: Will support 1 STA and 1 STA or AP concurrent
|
||||
// iface operations.
|
||||
// If Aware is enabled (conditional on isAwareSupported()), the iface
|
||||
// combination will be modified to support either P2P or NAN in place of
|
||||
// just P2P.
|
||||
if (feature_flags_.lock()->isDualInterfaceSupported()) {
|
||||
// V2 Iface combinations for Mode Id = 2.
|
||||
const IWifiChip::ChipIfaceCombinationLimit
|
||||
chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
|
||||
const IWifiChip::ChipIfaceCombinationLimit
|
||||
chip_iface_combination_limit_2 = {{IfaceType::STA, IfaceType::AP},
|
||||
1};
|
||||
IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;
|
||||
if (feature_flags_.lock()->isAwareSupported()) {
|
||||
chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},
|
||||
1};
|
||||
} else {
|
||||
chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};
|
||||
}
|
||||
const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
|
||||
{chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
|
||||
const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
|
||||
{chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
|
||||
const IWifiChip::ChipMode chip_mode = {
|
||||
kV2ChipModeId,
|
||||
{chip_iface_combination_1, chip_iface_combination_2}};
|
||||
modes_ = {chip_mode};
|
||||
} else {
|
||||
// V1 Iface combinations for Mode Id = 0. (STA Mode)
|
||||
const IWifiChip::ChipIfaceCombinationLimit
|
||||
sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
|
||||
IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
|
||||
if (feature_flags_.lock()->isAwareSupported()) {
|
||||
sta_chip_iface_combination_limit_2 = {
|
||||
{IfaceType::P2P, IfaceType::NAN}, 1};
|
||||
} else {
|
||||
sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
|
||||
}
|
||||
const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
|
||||
{sta_chip_iface_combination_limit_1,
|
||||
sta_chip_iface_combination_limit_2}};
|
||||
const IWifiChip::ChipMode sta_chip_mode = {
|
||||
kV1StaChipModeId, {sta_chip_iface_combination}};
|
||||
// Iface combinations for Mode Id = 1. (AP Mode)
|
||||
const IWifiChip::ChipIfaceCombinationLimit
|
||||
ap_chip_iface_combination_limit = {{IfaceType::AP}, 1};
|
||||
const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
|
||||
{ap_chip_iface_combination_limit}};
|
||||
const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
|
||||
{ap_chip_iface_combination}};
|
||||
modes_ = {sta_chip_mode, ap_chip_mode};
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<IWifiChip::ChipIfaceCombination>
|
||||
WifiChip::getCurrentModeIfaceCombinations() {
|
||||
if (!isValidModeId(current_mode_id_)) {
|
||||
LOG(ERROR) << "Chip not configured in a mode yet";
|
||||
return {};
|
||||
}
|
||||
for (const auto& mode : modes_) {
|
||||
if (mode.id == current_mode_id_) {
|
||||
return mode.availableCombinations;
|
||||
}
|
||||
}
|
||||
CHECK(0) << "Expected to find iface combinations for current mode!";
|
||||
return {};
|
||||
}
|
||||
|
||||
// Returns a map indexed by IfaceType with the number of ifaces currently
|
||||
// created of the corresponding type.
|
||||
std::map<IfaceType, size_t> WifiChip::getCurrentIfaceCombination() {
|
||||
std::map<IfaceType, size_t> iface_counts;
|
||||
iface_counts[IfaceType::AP] = ap_ifaces_.size();
|
||||
iface_counts[IfaceType::NAN] = nan_ifaces_.size();
|
||||
iface_counts[IfaceType::P2P] = p2p_ifaces_.size();
|
||||
iface_counts[IfaceType::STA] = sta_ifaces_.size();
|
||||
return iface_counts;
|
||||
}
|
||||
|
||||
// This expands the provided iface combinations to a more parseable
|
||||
// form. Returns a vector of available combinations possible with the number
|
||||
// of ifaces of each type in the combination.
|
||||
// This method is a port of HalDeviceManager.expandIfaceCombos() from framework.
|
||||
std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations(
|
||||
const IWifiChip::ChipIfaceCombination& combination) {
|
||||
uint32_t num_expanded_combos = 1;
|
||||
for (const auto& limit : combination.limits) {
|
||||
for (uint32_t i = 0; i < limit.maxIfaces; i++) {
|
||||
num_expanded_combos *= limit.types.size();
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate the vector of expanded combos and reset all iface counts to 0
|
||||
// in each combo.
|
||||
std::vector<std::map<IfaceType, size_t>> expanded_combos;
|
||||
expanded_combos.resize(num_expanded_combos);
|
||||
for (auto& expanded_combo : expanded_combos) {
|
||||
for (const auto type :
|
||||
{IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
|
||||
expanded_combo[type] = 0;
|
||||
}
|
||||
}
|
||||
uint32_t span = num_expanded_combos;
|
||||
for (const auto& limit : combination.limits) {
|
||||
for (uint32_t i = 0; i < limit.maxIfaces; i++) {
|
||||
span /= limit.types.size();
|
||||
for (uint32_t k = 0; k < num_expanded_combos; ++k) {
|
||||
const auto iface_type =
|
||||
limit.types[(k / span) % limit.types.size()];
|
||||
expanded_combos[k][iface_type]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return expanded_combos;
|
||||
}
|
||||
|
||||
bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType(
|
||||
const std::map<IfaceType, size_t>& combo, IfaceType requested_type) {
|
||||
const auto current_combo = getCurrentIfaceCombination();
|
||||
|
||||
// Check if we have space for 1 more iface of |type| in this combo
|
||||
for (const auto type :
|
||||
{IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
|
||||
size_t num_ifaces_needed = current_combo.at(type);
|
||||
if (type == requested_type) {
|
||||
num_ifaces_needed++;
|
||||
}
|
||||
size_t num_ifaces_allowed = combo.at(type);
|
||||
if (num_ifaces_needed > num_ifaces_allowed) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This method does the following:
|
||||
// a) Enumerate all possible iface combos by expanding the current
|
||||
// ChipIfaceCombination.
|
||||
// b) Check if the requested iface type can be added to the current mode.
|
||||
bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) {
|
||||
if (!isValidModeId(current_mode_id_)) {
|
||||
LOG(ERROR) << "Chip not configured in a mode yet";
|
||||
return false;
|
||||
}
|
||||
const auto combinations = getCurrentModeIfaceCombinations();
|
||||
for (const auto& combination : combinations) {
|
||||
const auto expanded_combos = expandIfaceCombinations(combination);
|
||||
for (const auto& expanded_combo : expanded_combos) {
|
||||
if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo,
|
||||
type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WifiChip::isValidModeId(ChipModeId mode_id) {
|
||||
for (const auto& mode : modes_) {
|
||||
if (mode.id == mode_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
|
||||
// This is based on the assumption that we'll have a max of 2 concurrent
|
||||
// AP/STA ifaces.
|
||||
std::string WifiChip::allocateApOrStaIfaceName() {
|
||||
auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
|
||||
auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
|
||||
if (!ap_iface.get() && !sta_iface.get()) {
|
||||
return getWlan0IfaceName();
|
||||
}
|
||||
ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
|
||||
sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
|
||||
if (!ap_iface.get() && !sta_iface.get()) {
|
||||
return getWlan1IfaceName();
|
||||
}
|
||||
// This should never happen. We screwed up somewhere if it did.
|
||||
CHECK(0) << "wlan0 and wlan1 in use already!";
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "hidl_callback_util.h"
|
||||
#include "wifi_ap_iface.h"
|
||||
#include "wifi_feature_flags.h"
|
||||
#include "wifi_legacy_hal.h"
|
||||
#include "wifi_mode_controller.h"
|
||||
#include "wifi_nan_iface.h"
|
||||
@@ -45,10 +46,12 @@ using namespace android::hardware::wifi::V1_0;
|
||||
*/
|
||||
class WifiChip : public V1_1::IWifiChip {
|
||||
public:
|
||||
WifiChip(ChipId chip_id,
|
||||
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::weak_ptr<mode_controller::WifiModeController>
|
||||
mode_controller);
|
||||
WifiChip(
|
||||
ChipId chip_id,
|
||||
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
|
||||
const std::weak_ptr<mode_controller::WifiModeController>
|
||||
mode_controller,
|
||||
const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags);
|
||||
// HIDL does not provide a built-in mechanism to let the server invalidate
|
||||
// a HIDL interface object after creation. If any client process holds onto
|
||||
// a reference to the object in their context, any method calls on that
|
||||
@@ -190,16 +193,31 @@ class WifiChip : public V1_1::IWifiChip {
|
||||
std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
|
||||
WifiStatus registerDebugRingBufferCallback();
|
||||
|
||||
void populateModes();
|
||||
std::vector<IWifiChip::ChipIfaceCombination>
|
||||
getCurrentModeIfaceCombinations();
|
||||
std::map<IfaceType, size_t> getCurrentIfaceCombination();
|
||||
std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
|
||||
const IWifiChip::ChipIfaceCombination& combination);
|
||||
bool canExpandedIfaceCombinationSupportIfaceOfType(
|
||||
const std::map<IfaceType, size_t>& combo, IfaceType type);
|
||||
bool canCurrentModeSupportIfaceOfType(IfaceType type);
|
||||
bool isValidModeId(ChipModeId mode_id);
|
||||
std::string allocateApOrStaIfaceName();
|
||||
|
||||
ChipId chip_id_;
|
||||
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
|
||||
std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
|
||||
sp<WifiApIface> ap_iface_;
|
||||
sp<WifiNanIface> nan_iface_;
|
||||
sp<WifiP2pIface> p2p_iface_;
|
||||
sp<WifiStaIface> sta_iface_;
|
||||
std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
|
||||
std::vector<sp<WifiApIface>> ap_ifaces_;
|
||||
std::vector<sp<WifiNanIface>> nan_ifaces_;
|
||||
std::vector<sp<WifiP2pIface>> p2p_ifaces_;
|
||||
std::vector<sp<WifiStaIface>> sta_ifaces_;
|
||||
std::vector<sp<WifiRttController>> rtt_controllers_;
|
||||
bool is_valid_;
|
||||
// Members pertaining to chip configuration.
|
||||
uint32_t current_mode_id_;
|
||||
std::vector<IWifiChip::ChipMode> modes_;
|
||||
// The legacy ring buffer callback API has only a global callback
|
||||
// registration mechanism. Use this to check if we have already
|
||||
// registered a callback.
|
||||
|
||||
50
wifi/1.2/default/wifi_feature_flags.cpp
Normal file
50
wifi/1.2/default/wifi_feature_flags.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 "wifi_feature_flags.h"
|
||||
|
||||
namespace {
|
||||
#ifdef WIFI_HIDL_FEATURE_AWARE
|
||||
static const bool wifiHidlFeatureAware = true;
|
||||
#else
|
||||
static const bool wifiHidlFeatureAware = false;
|
||||
#endif // WIFI_HIDL_FEATURE_AWARE
|
||||
#ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
|
||||
static const bool wifiHidlFeatureDualInterface = true;
|
||||
#else
|
||||
static const bool wifiHidlFeatureDualInterface = false;
|
||||
#endif // WIFI_HIDL_FEATURE_DUAL_INTERFACE
|
||||
} // namespace
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace feature_flags {
|
||||
|
||||
WifiFeatureFlags::WifiFeatureFlags() {}
|
||||
bool WifiFeatureFlags::isAwareSupported() { return wifiHidlFeatureAware; }
|
||||
bool WifiFeatureFlags::isDualInterfaceSupported() {
|
||||
return wifiHidlFeatureDualInterface;
|
||||
}
|
||||
|
||||
} // namespace feature_flags
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
@@ -22,16 +22,18 @@ namespace hardware {
|
||||
namespace wifi {
|
||||
namespace V1_2 {
|
||||
namespace implementation {
|
||||
namespace feature_flags {
|
||||
|
||||
class WifiFeatureFlags {
|
||||
public:
|
||||
#ifdef WIFI_HIDL_FEATURE_AWARE
|
||||
static const bool wifiHidlFeatureAware = true;
|
||||
#else
|
||||
static const bool wifiHidlFeatureAware = false;
|
||||
#endif // WIFI_HIDL_FEATURE_AWARE
|
||||
WifiFeatureFlags();
|
||||
virtual ~WifiFeatureFlags() = default;
|
||||
|
||||
virtual bool isAwareSupported();
|
||||
virtual bool isDualInterfaceSupported();
|
||||
};
|
||||
|
||||
} // namespace feature_flags
|
||||
} // namespace implementation
|
||||
} // namespace V1_2
|
||||
} // namespace wifi
|
||||
|
||||
@@ -455,7 +455,7 @@ std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet(
|
||||
const std::string& iface_name) {
|
||||
feature_set set;
|
||||
static_assert(sizeof(set) == sizeof(uint32_t),
|
||||
"Some features can not be represented in output");
|
||||
"Some feature_flags can not be represented in output");
|
||||
wifi_error status = global_func_table_.wifi_get_supported_feature_set(
|
||||
getIfaceHandle(iface_name), &set);
|
||||
return {status, static_cast<uint32_t>(set)};
|
||||
@@ -759,11 +759,11 @@ wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
|
||||
|
||||
std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
|
||||
const std::string& iface_name) {
|
||||
uint32_t supported_features;
|
||||
uint32_t supported_feature_flags;
|
||||
wifi_error status =
|
||||
global_func_table_.wifi_get_logger_supported_feature_set(
|
||||
getIfaceHandle(iface_name), &supported_features);
|
||||
return {status, supported_features};
|
||||
getIfaceHandle(iface_name), &supported_feature_flags);
|
||||
return {status, supported_feature_flags};
|
||||
}
|
||||
|
||||
wifi_error WifiLegacyHal::startPktFateMonitoring(
|
||||
|
||||
@@ -142,15 +142,16 @@ using on_error_alert_callback =
|
||||
class WifiLegacyHal {
|
||||
public:
|
||||
WifiLegacyHal();
|
||||
virtual ~WifiLegacyHal() = default;
|
||||
|
||||
// Initialize the legacy HAL function table.
|
||||
wifi_error initialize();
|
||||
virtual wifi_error initialize();
|
||||
// Start the legacy HAL and the event looper thread.
|
||||
wifi_error start();
|
||||
virtual wifi_error start();
|
||||
// Deinitialize the legacy HAL and wait for the event loop thread to exit
|
||||
// using a predefined timeout.
|
||||
wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
|
||||
const std::function<void()>& on_complete_callback);
|
||||
virtual wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
|
||||
const std::function<void()>& on_complete_callback);
|
||||
// Wrappers for all the functions in the legacy HAL function table.
|
||||
std::pair<wifi_error, std::string> getDriverVersion(
|
||||
const std::string& iface_name);
|
||||
@@ -190,7 +191,7 @@ class WifiLegacyHal {
|
||||
wifi_error stopGscan(const std::string& iface_name, wifi_request_id id);
|
||||
std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand(
|
||||
const std::string& iface_name, wifi_band band);
|
||||
wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on);
|
||||
virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on);
|
||||
// Link layer stats functions.
|
||||
wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug);
|
||||
wifi_error disableLinkLayerStats(const std::string& iface_name);
|
||||
@@ -276,12 +277,12 @@ class WifiLegacyHal {
|
||||
wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id,
|
||||
const wifi_lcr_information& info);
|
||||
// NAN functions.
|
||||
wifi_error nanRegisterCallbackHandlers(
|
||||
virtual wifi_error nanRegisterCallbackHandlers(
|
||||
const std::string& iface_name, const NanCallbackHandlers& callbacks);
|
||||
wifi_error nanEnableRequest(const std::string& iface_name,
|
||||
transaction_id id, const NanEnableRequest& msg);
|
||||
wifi_error nanDisableRequest(const std::string& iface_name,
|
||||
transaction_id id);
|
||||
virtual wifi_error nanDisableRequest(const std::string& iface_name,
|
||||
transaction_id id);
|
||||
wifi_error nanPublishRequest(const std::string& iface_name,
|
||||
transaction_id id,
|
||||
const NanPublishRequest& msg);
|
||||
@@ -312,9 +313,9 @@ class WifiLegacyHal {
|
||||
wifi_error nanDataInterfaceCreate(const std::string& iface_name,
|
||||
transaction_id id,
|
||||
const std::string& data_iface_name);
|
||||
wifi_error nanDataInterfaceDelete(const std::string& iface_name,
|
||||
transaction_id id,
|
||||
const std::string& data_iface_name);
|
||||
virtual wifi_error nanDataInterfaceDelete(
|
||||
const std::string& iface_name, transaction_id id,
|
||||
const std::string& data_iface_name);
|
||||
wifi_error nanDataRequestInitiator(const std::string& iface_name,
|
||||
transaction_id id,
|
||||
const NanDataPathInitiatorRequest& msg);
|
||||
|
||||
@@ -59,11 +59,15 @@ bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
|
||||
convertIfaceTypeToFirmwareMode(type));
|
||||
}
|
||||
|
||||
bool WifiModeController::changeFirmwareMode(IfaceType type) {
|
||||
bool WifiModeController::initialize() {
|
||||
if (!driver_tool_->LoadDriver()) {
|
||||
LOG(ERROR) << "Failed to load WiFi driver";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WifiModeController::changeFirmwareMode(IfaceType type) {
|
||||
if (!driver_tool_->ChangeFirmwareMode(
|
||||
convertIfaceTypeToFirmwareMode(type))) {
|
||||
LOG(ERROR) << "Failed to change firmware mode";
|
||||
|
||||
@@ -37,15 +37,17 @@ using namespace android::hardware::wifi::V1_0;
|
||||
class WifiModeController {
|
||||
public:
|
||||
WifiModeController();
|
||||
virtual ~WifiModeController() = default;
|
||||
|
||||
// Checks if a firmware mode change is necessary to support the specified
|
||||
// iface type operations.
|
||||
bool isFirmwareModeChangeNeeded(IfaceType type);
|
||||
virtual bool isFirmwareModeChangeNeeded(IfaceType type);
|
||||
virtual bool initialize();
|
||||
// Change the firmware mode to support the specified iface type operations.
|
||||
bool changeFirmwareMode(IfaceType type);
|
||||
virtual bool changeFirmwareMode(IfaceType type);
|
||||
// Unload the driver. This should be invoked whenever |IWifi.stop()| is
|
||||
// invoked.
|
||||
bool deinitialize();
|
||||
virtual bool deinitialize();
|
||||
|
||||
private:
|
||||
std::unique_ptr<wifi_hal::DriverTool> driver_tool_;
|
||||
|
||||
@@ -494,6 +494,8 @@ void WifiNanIface::invalidate() {
|
||||
|
||||
bool WifiNanIface::isValid() { return is_valid_; }
|
||||
|
||||
std::string WifiNanIface::getName() { return ifname_; }
|
||||
|
||||
std::set<sp<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
|
||||
return event_cb_handler_.getCallbacks();
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ class WifiNanIface : public V1_0::IWifiNanIface {
|
||||
// Refer to |WifiChip::invalidate()|.
|
||||
void invalidate();
|
||||
bool isValid();
|
||||
std::string getName();
|
||||
|
||||
// HIDL methods exposed.
|
||||
Return<void> getName(getName_cb hidl_status_cb) override;
|
||||
|
||||
@@ -39,6 +39,8 @@ void WifiP2pIface::invalidate() {
|
||||
|
||||
bool WifiP2pIface::isValid() { return is_valid_; }
|
||||
|
||||
std::string WifiP2pIface::getName() { return ifname_; }
|
||||
|
||||
Return<void> WifiP2pIface::getName(getName_cb hidl_status_cb) {
|
||||
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
|
||||
&WifiP2pIface::getNameInternal, hidl_status_cb);
|
||||
|
||||
@@ -39,6 +39,7 @@ class WifiP2pIface : public V1_0::IWifiP2pIface {
|
||||
// Refer to |WifiChip::invalidate()|.
|
||||
void invalidate();
|
||||
bool isValid();
|
||||
std::string getName();
|
||||
|
||||
// HIDL methods exposed.
|
||||
Return<void> getName(getName_cb hidl_status_cb) override;
|
||||
|
||||
@@ -49,6 +49,8 @@ void WifiStaIface::invalidate() {
|
||||
|
||||
bool WifiStaIface::isValid() { return is_valid_; }
|
||||
|
||||
std::string WifiStaIface::getName() { return ifname_; }
|
||||
|
||||
std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
|
||||
return event_cb_handler_.getCallbacks();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ class WifiStaIface : public V1_0::IWifiStaIface {
|
||||
void invalidate();
|
||||
bool isValid();
|
||||
std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
|
||||
std::string getName();
|
||||
|
||||
// HIDL methods exposed.
|
||||
Return<void> getName(getName_cb hidl_status_cb) override;
|
||||
|
||||
Reference in New Issue
Block a user