302 lines
10 KiB
C++
302 lines
10 KiB
C++
/*
|
|
* Copyright (C) 2022 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 <cstdint>
|
|
|
|
#include "chre/core/event_loop_manager.h"
|
|
#include "chre/core/settings.h"
|
|
#include "chre/platform/linux/pal_nan.h"
|
|
#include "chre/platform/linux/pal_wifi.h"
|
|
#include "chre/platform/log.h"
|
|
#include "chre/util/system/napp_permissions.h"
|
|
#include "chre_api/chre/event.h"
|
|
#include "chre_api/chre/wifi.h"
|
|
#include "gtest/gtest.h"
|
|
#include "test_base.h"
|
|
#include "test_event.h"
|
|
#include "test_event_queue.h"
|
|
#include "test_util.h"
|
|
|
|
namespace chre {
|
|
namespace {
|
|
|
|
CREATE_CHRE_TEST_EVENT(SCAN_REQUEST, 20);
|
|
|
|
struct WifiAsyncData {
|
|
const uint32_t *cookie;
|
|
chreError errorCode;
|
|
};
|
|
|
|
class WifiScanRequestQueueTestBase : public TestBase {
|
|
public:
|
|
void SetUp() {
|
|
TestBase::SetUp();
|
|
// Add delay to make sure the requests are queued.
|
|
chrePalWifiDelayResponse(PalWifiAsyncRequestTypes::SCAN,
|
|
std::chrono::seconds(1));
|
|
}
|
|
|
|
void TearDown() {
|
|
TestBase::TearDown();
|
|
chrePalWifiDelayResponse(PalWifiAsyncRequestTypes::SCAN,
|
|
std::chrono::seconds(0));
|
|
}
|
|
};
|
|
|
|
struct WifiScanTestNanoapp : public TestNanoapp {
|
|
uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
|
|
|
|
decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
|
|
const void *eventData) {
|
|
constexpr uint8_t kMaxPendingCookie = 10;
|
|
static uint32_t cookies[kMaxPendingCookie];
|
|
static uint8_t nextFreeCookieIndex = 0;
|
|
|
|
switch (eventType) {
|
|
case CHRE_EVENT_WIFI_ASYNC_RESULT: {
|
|
auto *event = static_cast<const chreAsyncResult *>(eventData);
|
|
TestEventQueueSingleton::get()->pushEvent(
|
|
CHRE_EVENT_WIFI_ASYNC_RESULT,
|
|
WifiAsyncData{
|
|
.cookie = static_cast<const uint32_t *>(event->cookie),
|
|
.errorCode = static_cast<chreError>(event->errorCode)});
|
|
break;
|
|
}
|
|
|
|
case CHRE_EVENT_WIFI_SCAN_RESULT: {
|
|
TestEventQueueSingleton::get()->pushEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
|
|
break;
|
|
}
|
|
|
|
case CHRE_EVENT_TEST_EVENT: {
|
|
auto event = static_cast<const TestEvent *>(eventData);
|
|
switch (event->type) {
|
|
case SCAN_REQUEST:
|
|
bool success = false;
|
|
if (nextFreeCookieIndex < kMaxPendingCookie) {
|
|
cookies[nextFreeCookieIndex] =
|
|
*static_cast<uint32_t *>(event->data);
|
|
success = chreWifiRequestScanAsyncDefault(
|
|
&cookies[nextFreeCookieIndex]);
|
|
nextFreeCookieIndex++;
|
|
} else {
|
|
LOGE("Too many cookies passed from test body!");
|
|
}
|
|
TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
TEST_F(TestBase, WifiScanBasicSettingTest) {
|
|
auto app = loadNanoapp<WifiScanTestNanoapp>();
|
|
|
|
EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
|
|
Setting::WIFI_AVAILABLE, true /* enabled */);
|
|
|
|
constexpr uint32_t firstCookie = 0x1010;
|
|
bool success;
|
|
WifiAsyncData wifiAsyncData;
|
|
|
|
sendEventToNanoapp(app, SCAN_REQUEST, firstCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
|
|
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
|
|
EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
|
|
EXPECT_EQ(*wifiAsyncData.cookie, firstCookie);
|
|
waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
|
|
|
|
EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
|
|
Setting::WIFI_AVAILABLE, false /* enabled */);
|
|
|
|
constexpr uint32_t secondCookie = 0x2020;
|
|
sendEventToNanoapp(app, SCAN_REQUEST, secondCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
|
|
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
|
|
EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_FUNCTION_DISABLED);
|
|
EXPECT_EQ(*wifiAsyncData.cookie, secondCookie);
|
|
|
|
EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
|
|
Setting::WIFI_AVAILABLE, true /* enabled */);
|
|
unloadNanoapp(app);
|
|
}
|
|
|
|
TEST_F(WifiScanRequestQueueTestBase, WifiQueuedScanSettingChangeTest) {
|
|
struct WifiScanTestNanoappTwo : public WifiScanTestNanoapp {
|
|
uint64_t id = 0x1123456789abcdef;
|
|
};
|
|
|
|
auto firstApp = loadNanoapp<WifiScanTestNanoapp>();
|
|
auto secondApp = loadNanoapp<WifiScanTestNanoappTwo>();
|
|
|
|
constexpr uint32_t firstRequestCookie = 0x1010;
|
|
constexpr uint32_t secondRequestCookie = 0x2020;
|
|
bool success;
|
|
sendEventToNanoapp(firstApp, SCAN_REQUEST, firstRequestCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
sendEventToNanoapp(secondApp, SCAN_REQUEST, secondRequestCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
|
|
EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
|
|
Setting::WIFI_AVAILABLE, false /* enabled */);
|
|
|
|
WifiAsyncData wifiAsyncData;
|
|
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
|
|
EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
|
|
EXPECT_EQ(*wifiAsyncData.cookie, firstRequestCookie);
|
|
waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
|
|
|
|
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
|
|
EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_FUNCTION_DISABLED);
|
|
EXPECT_EQ(*wifiAsyncData.cookie, secondRequestCookie);
|
|
|
|
EventLoopManagerSingleton::get()->getSettingManager().postSettingChange(
|
|
Setting::WIFI_AVAILABLE, true /* enabled */);
|
|
|
|
unloadNanoapp(firstApp);
|
|
unloadNanoapp(secondApp);
|
|
}
|
|
|
|
TEST_F(WifiScanRequestQueueTestBase, WifiScanRejectRequestFromSameNanoapp) {
|
|
auto app = loadNanoapp<WifiScanTestNanoapp>();
|
|
|
|
constexpr uint32_t firstRequestCookie = 0x1010;
|
|
constexpr uint32_t secondRequestCookie = 0x2020;
|
|
bool success;
|
|
sendEventToNanoapp(app, SCAN_REQUEST, firstRequestCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
sendEventToNanoapp(app, SCAN_REQUEST, secondRequestCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_FALSE(success);
|
|
|
|
WifiAsyncData wifiAsyncData;
|
|
waitForEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, &wifiAsyncData);
|
|
EXPECT_EQ(wifiAsyncData.errorCode, CHRE_ERROR_NONE);
|
|
EXPECT_EQ(*wifiAsyncData.cookie, firstRequestCookie);
|
|
waitForEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
|
|
|
|
unloadNanoapp(app);
|
|
}
|
|
|
|
TEST_F(WifiScanRequestQueueTestBase, WifiScanActiveScanFromDistinctNanoapps) {
|
|
CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT,
|
|
1);
|
|
CREATE_CHRE_TEST_EVENT(CONCURRENT_NANOAPP_READ_COOKIE, 2);
|
|
|
|
struct AppCookies {
|
|
uint32_t sent = 0;
|
|
uint32_t received = 0;
|
|
};
|
|
|
|
constexpr uint64_t kAppOneId = 0x0123456789000001;
|
|
constexpr uint64_t kAppTwoId = 0x0123456789000002;
|
|
|
|
struct WifiScanTestConcurrentNanoappOne : public TestNanoapp {
|
|
uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
|
|
uint64_t id = kAppOneId;
|
|
|
|
decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
|
|
const void *eventData) {
|
|
constexpr uint8_t kExpectedReceiveAsyncResultCount = 2;
|
|
static uint8_t receivedCookieCount = 0;
|
|
static AppCookies appOneCookies;
|
|
static AppCookies appTwoCookies;
|
|
|
|
// Retrieve cookies from different apps that have the same access to
|
|
// static storage due to inheritance.
|
|
AppCookies *appCookies =
|
|
chreGetAppId() == kAppTwoId ? &appTwoCookies : &appOneCookies;
|
|
|
|
switch (eventType) {
|
|
case CHRE_EVENT_WIFI_ASYNC_RESULT: {
|
|
auto *event = static_cast<const chreAsyncResult *>(eventData);
|
|
if (event->errorCode == CHRE_ERROR_NONE) {
|
|
appCookies->received =
|
|
*static_cast<const uint32_t *>(event->cookie);
|
|
++receivedCookieCount;
|
|
} else {
|
|
LOGE("Received failed async result");
|
|
}
|
|
|
|
if (receivedCookieCount == kExpectedReceiveAsyncResultCount) {
|
|
TestEventQueueSingleton::get()->pushEvent(
|
|
CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case CHRE_EVENT_TEST_EVENT: {
|
|
auto event = static_cast<const TestEvent *>(eventData);
|
|
bool success = false;
|
|
uint32_t expectedCookie;
|
|
switch (event->type) {
|
|
case SCAN_REQUEST:
|
|
appCookies->sent = *static_cast<uint32_t *>(event->data);
|
|
success = chreWifiRequestScanAsyncDefault(&(appCookies->sent));
|
|
TestEventQueueSingleton::get()->pushEvent(SCAN_REQUEST, success);
|
|
break;
|
|
case CONCURRENT_NANOAPP_READ_COOKIE:
|
|
TestEventQueueSingleton::get()->pushEvent(
|
|
CONCURRENT_NANOAPP_READ_COOKIE, appCookies->received);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
};
|
|
};
|
|
|
|
struct WifiScanTestConcurrentNanoappTwo
|
|
: public WifiScanTestConcurrentNanoappOne {
|
|
uint64_t id = kAppTwoId;
|
|
};
|
|
|
|
auto appOne = loadNanoapp<WifiScanTestConcurrentNanoappOne>();
|
|
auto appTwo = loadNanoapp<WifiScanTestConcurrentNanoappTwo>();
|
|
|
|
constexpr uint32_t kAppOneRequestCookie = 0x1010;
|
|
constexpr uint32_t kAppTwoRequestCookie = 0x2020;
|
|
bool success;
|
|
sendEventToNanoapp(appOne, SCAN_REQUEST, kAppOneRequestCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
sendEventToNanoapp(appTwo, SCAN_REQUEST, kAppTwoRequestCookie);
|
|
waitForEvent(SCAN_REQUEST, &success);
|
|
EXPECT_TRUE(success);
|
|
|
|
waitForEvent(CONCURRENT_NANOAPP_RECEIVED_EXPECTED_ASYNC_EVENT_COUNT);
|
|
|
|
uint32_t receivedCookie;
|
|
sendEventToNanoapp(appOne, CONCURRENT_NANOAPP_READ_COOKIE);
|
|
waitForEvent(CONCURRENT_NANOAPP_READ_COOKIE, &receivedCookie);
|
|
EXPECT_EQ(kAppOneRequestCookie, receivedCookie);
|
|
|
|
sendEventToNanoapp(appTwo, CONCURRENT_NANOAPP_READ_COOKIE);
|
|
waitForEvent(CONCURRENT_NANOAPP_READ_COOKIE, &receivedCookie);
|
|
EXPECT_EQ(kAppTwoRequestCookie, receivedCookie);
|
|
|
|
unloadNanoapp(appOne);
|
|
unloadNanoapp(appTwo);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace chre
|