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
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk
index b242cfc..95414bc 100644
--- a/wifi/1.2/default/Android.mk
+++ b/wifi/1.2/default/Android.mk
@@ -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 @@
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)
diff --git a/wifi/1.2/default/service.cpp b/wifi/1.2/default/service.cpp
index 6297cf2..01d22bd 100644
--- a/wifi/1.2/default/service.cpp
+++ b/wifi/1.2/default/service.cpp
@@ -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 @@
// 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";
diff --git a/wifi/1.2/default/tests/main.cpp b/wifi/1.2/default/tests/main.cpp
new file mode 100644
index 0000000..9aac837
--- /dev/null
+++ b/wifi/1.2/default/tests/main.cpp
@@ -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();
+}
diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
new file mode 100644
index 0000000..8d0b192
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
@@ -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
diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.h b/wifi/1.2/default/tests/mock_wifi_feature_flags.h
new file mode 100644
index 0000000..8cf1d4b
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_feature_flags.h
@@ -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_
diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
new file mode 100644
index 0000000..8381dde
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
@@ -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
diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.h b/wifi/1.2/default/tests/mock_wifi_legacy_hal.h
new file mode 100644
index 0000000..8e1696e
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_legacy_hal.h
@@ -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_
diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
new file mode 100644
index 0000000..461a581
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
@@ -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
diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.h b/wifi/1.2/default/tests/mock_wifi_mode_controller.h
new file mode 100644
index 0000000..50c3e35
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_mode_controller.h
@@ -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_
diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.2/default/tests/runtests.sh
new file mode 100755
index 0000000..966a6a7
--- /dev/null
+++ b/wifi/1.2/default/tests/runtests.sh
@@ -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
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
new file mode 100644
index 0000000..f73869b
--- /dev/null
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -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
diff --git a/wifi/1.2/default/wifi.cpp b/wifi/1.2/default/wifi.cpp
index a2d8f9f..06f5058 100644
--- a/wifi/1.2/default/wifi.cpp
+++ b/wifi/1.2/default/wifi.cpp
@@ -33,9 +33,13 @@
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 @@
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 @@
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: "
diff --git a/wifi/1.2/default/wifi.h b/wifi/1.2/default/wifi.h
index 114d774..440c3c7 100644
--- a/wifi/1.2/default/wifi.h
+++ b/wifi/1.2/default/wifi.h
@@ -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 @@
*/
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 @@
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 @@
// 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>
diff --git a/wifi/1.2/default/wifi_ap_iface.cpp b/wifi/1.2/default/wifi_ap_iface.cpp
index 284f9b9..92b7b48 100644
--- a/wifi/1.2/default/wifi_ap_iface.cpp
+++ b/wifi/1.2/default/wifi_ap_iface.cpp
@@ -40,6 +40,8 @@
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);
diff --git a/wifi/1.2/default/wifi_ap_iface.h b/wifi/1.2/default/wifi_ap_iface.h
index 6375121..5363ec2 100644
--- a/wifi/1.2/default/wifi_ap_iface.h
+++ b/wifi/1.2/default/wifi_ap_iface.h
@@ -39,6 +39,7 @@
// Refer to |WifiChip::invalidate()|.
void invalidate();
bool isValid();
+ std::string getName();
// HIDL methods exposed.
Return<void> getName(getName_cb hidl_status_cb) override;
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index 4e2191d..adba054 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -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 @@
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 @@
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 @@
}
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, 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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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
diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.2/default/wifi_chip.h
index ac59d59..97c434e 100644
--- a/wifi/1.2/default/wifi_chip.h
+++ b/wifi/1.2/default/wifi_chip.h
@@ -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 @@
*/
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 @@
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.
diff --git a/wifi/1.2/default/wifi_feature_flags.cpp b/wifi/1.2/default/wifi_feature_flags.cpp
new file mode 100644
index 0000000..554d4d5
--- /dev/null
+++ b/wifi/1.2/default/wifi_feature_flags.cpp
@@ -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
diff --git a/wifi/1.2/default/wifi_feature_flags.h b/wifi/1.2/default/wifi_feature_flags.h
index da4ca37..dc0c1ff 100644
--- a/wifi/1.2/default/wifi_feature_flags.h
+++ b/wifi/1.2/default/wifi_feature_flags.h
@@ -22,16 +22,18 @@
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
diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp
index 24b80d5..9abe514 100644
--- a/wifi/1.2/default/wifi_legacy_hal.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal.cpp
@@ -455,7 +455,7 @@
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 @@
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(
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
index 05f700e..da88f6b 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -142,15 +142,16 @@
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 @@
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 @@
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 @@
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);
diff --git a/wifi/1.2/default/wifi_mode_controller.cpp b/wifi/1.2/default/wifi_mode_controller.cpp
index 8a89e81..c286d24 100644
--- a/wifi/1.2/default/wifi_mode_controller.cpp
+++ b/wifi/1.2/default/wifi_mode_controller.cpp
@@ -59,11 +59,15 @@
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";
diff --git a/wifi/1.2/default/wifi_mode_controller.h b/wifi/1.2/default/wifi_mode_controller.h
index 839bf9e..395aa5d 100644
--- a/wifi/1.2/default/wifi_mode_controller.h
+++ b/wifi/1.2/default/wifi_mode_controller.h
@@ -37,15 +37,17 @@
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_;
diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.2/default/wifi_nan_iface.cpp
index e7bbfaa..12e4d7b 100644
--- a/wifi/1.2/default/wifi_nan_iface.cpp
+++ b/wifi/1.2/default/wifi_nan_iface.cpp
@@ -494,6 +494,8 @@
bool WifiNanIface::isValid() { return is_valid_; }
+std::string WifiNanIface::getName() { return ifname_; }
+
std::set<sp<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
return event_cb_handler_.getCallbacks();
}
diff --git a/wifi/1.2/default/wifi_nan_iface.h b/wifi/1.2/default/wifi_nan_iface.h
index 2ca2e45..6fa7b0c 100644
--- a/wifi/1.2/default/wifi_nan_iface.h
+++ b/wifi/1.2/default/wifi_nan_iface.h
@@ -41,6 +41,7 @@
// Refer to |WifiChip::invalidate()|.
void invalidate();
bool isValid();
+ std::string getName();
// HIDL methods exposed.
Return<void> getName(getName_cb hidl_status_cb) override;
diff --git a/wifi/1.2/default/wifi_p2p_iface.cpp b/wifi/1.2/default/wifi_p2p_iface.cpp
index f1fbf2c..92bbaee 100644
--- a/wifi/1.2/default/wifi_p2p_iface.cpp
+++ b/wifi/1.2/default/wifi_p2p_iface.cpp
@@ -39,6 +39,8 @@
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);
diff --git a/wifi/1.2/default/wifi_p2p_iface.h b/wifi/1.2/default/wifi_p2p_iface.h
index 839d3c3..76120b1 100644
--- a/wifi/1.2/default/wifi_p2p_iface.h
+++ b/wifi/1.2/default/wifi_p2p_iface.h
@@ -39,6 +39,7 @@
// Refer to |WifiChip::invalidate()|.
void invalidate();
bool isValid();
+ std::string getName();
// HIDL methods exposed.
Return<void> getName(getName_cb hidl_status_cb) override;
diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.2/default/wifi_sta_iface.cpp
index c8605ee..6faf009 100644
--- a/wifi/1.2/default/wifi_sta_iface.cpp
+++ b/wifi/1.2/default/wifi_sta_iface.cpp
@@ -49,6 +49,8 @@
bool WifiStaIface::isValid() { return is_valid_; }
+std::string WifiStaIface::getName() { return ifname_; }
+
std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
return event_cb_handler_.getCallbacks();
}
diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.2/default/wifi_sta_iface.h
index 6731864..423365c 100644
--- a/wifi/1.2/default/wifi_sta_iface.h
+++ b/wifi/1.2/default/wifi_sta_iface.h
@@ -42,6 +42,7 @@
void invalidate();
bool isValid();
std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
+ std::string getName();
// HIDL methods exposed.
Return<void> getName(getName_cb hidl_status_cb) override;