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:
Roshan Pius
2017-12-15 04:02:13 +00:00
committed by Android (Google) Code Review
29 changed files with 1417 additions and 150 deletions

View File

@@ -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)

View File

@@ -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";

View 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();
}

View 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

View 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_

View 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

View 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_

View 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

View 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_

View 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

View 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

View File

@@ -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: "

View File

@@ -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>

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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.

View 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

View File

@@ -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

View File

@@ -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(

View File

@@ -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);

View File

@@ -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";

View File

@@ -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_;

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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;