Snap for 10385628 from a8b6c4ca357727736da22378a26e2d5e15a19518 to udc-d1-release
Change-Id: Icbabbdfd121932e1aa53ac0edc9871b5c6e328b4
diff --git a/core/ble_request_manager.cc b/core/ble_request_manager.cc
index 811af1d..0c8605f 100644
--- a/core/ble_request_manager.cc
+++ b/core/ble_request_manager.cc
@@ -171,7 +171,7 @@
success = updateRequests(std::move(request), hasExistingRequest,
&requestChanged, &requestIndex);
if (success) {
- if (!asyncResponsePending()) {
+ if (!mPlatformRequestInProgress) {
if (!requestChanged) {
handleAsyncResult(instanceId, enabled, true /* success */,
CHRE_ERROR_NONE);
@@ -219,6 +219,7 @@
req.setRequestStatus(RequestStatus::PENDING_RESP);
}
}
+ mPlatformRequestInProgress = true;
}
return success;
@@ -266,27 +267,21 @@
success = false;
CHRE_ASSERT_LOG(false, "Unable to stop BLE scan");
}
- if (mInternalRequestPending) {
- mInternalRequestPending = false;
- if (!success) {
- LOGE("Failed to resync BLE platform");
- }
- } else {
- for (BleRequest &req : mRequests.getMutableRequests()) {
- if (req.getRequestStatus() == RequestStatus::PENDING_RESP) {
- handleAsyncResult(req.getInstanceId(), req.isEnabled(), success,
- errorCode);
- if (success) {
- req.setRequestStatus(RequestStatus::APPLIED);
- }
+
+ mPlatformRequestInProgress = false;
+ for (BleRequest &req : mRequests.getMutableRequests()) {
+ if (req.getRequestStatus() == RequestStatus::PENDING_RESP) {
+ handleAsyncResult(req.getInstanceId(), req.isEnabled(), success,
+ errorCode);
+ if (success) {
+ req.setRequestStatus(RequestStatus::APPLIED);
}
}
-
- if (!success) {
- mRequests.removeRequests(RequestStatus::PENDING_RESP);
- }
}
- if (success) {
+
+ if (!success) {
+ mRequests.removeRequests(RequestStatus::PENDING_RESP);
+ } else {
// No need to waste memory for requests that have no effect on the overall
// maximal request.
mRequests.removeDisabledRequests();
@@ -301,7 +296,7 @@
if (mResyncPending) {
if (success) {
mResyncPending = false;
- } else if (!success && !asyncResponsePending()) {
+ } else if (!success && !mPlatformRequestInProgress) {
mResyncPending = false;
updatePlatformRequest(true /* forceUpdate */);
}
@@ -311,7 +306,7 @@
// If both a resync and a setting change are pending, prioritize the resync.
// If the resync successfully completes, the PAL will be in the correct state
// and updatePlatformRequest will not begin a new request.
- if (mSettingChangePending && !asyncResponsePending()) {
+ if (mSettingChangePending && !mPlatformRequestInProgress) {
updatePlatformRequest();
mSettingChangePending = false;
}
@@ -374,7 +369,7 @@
}
void BleRequestManager::handleRequestStateResyncCallbackSync() {
- if (asyncResponsePending()) {
+ if (mPlatformRequestInProgress) {
mResyncPending = true;
} else {
updatePlatformRequest(true /* forceUpdate */);
@@ -476,7 +471,7 @@
void BleRequestManager::onSettingChanged(Setting setting, bool /* state */) {
if (setting == Setting::BLE_AVAILABLE) {
- if (asyncResponsePending()) {
+ if (mPlatformRequestInProgress) {
mSettingChangePending = true;
} else {
updatePlatformRequest();
@@ -492,7 +487,6 @@
if (updatePlatform) {
if (controlPlatform()) {
- mInternalRequestPending = true;
addBleRequestLog(CHRE_INSTANCE_ID, desiredPlatformState,
mRequests.getRequests().size(),
true /* compliesWithBleSetting */);
@@ -502,11 +496,6 @@
}
}
-bool BleRequestManager::asyncResponsePending() const {
- return (mInternalRequestPending ||
- mRequests.hasRequests(RequestStatus::PENDING_RESP));
-}
-
bool BleRequestManager::validateParams(const BleRequest &request) {
bool valid = true;
if (request.isEnabled()) {
@@ -557,7 +546,7 @@
debugDump.print(" Active Platform Request:\n");
mActivePlatformRequest.logStateToBuffer(debugDump,
true /* isPlatformRequest */);
- if (asyncResponsePending()) {
+ if (mPlatformRequestInProgress) {
debugDump.print(" Pending Platform Request:\n");
mPendingPlatformRequest.logStateToBuffer(debugDump,
true /* isPlatformRequest */);
diff --git a/core/include/chre/core/ble_request_manager.h b/core/include/chre/core/ble_request_manager.h
index adc9cd5..747b5a7 100644
--- a/core/include/chre/core/ble_request_manager.h
+++ b/core/include/chre/core/ble_request_manager.h
@@ -213,8 +213,8 @@
// Current state of the platform.
BleRequest mActivePlatformRequest;
- // True if a request from the PAL is currently pending.
- bool mInternalRequestPending;
+ // True if a platform request is in progress.
+ bool mPlatformRequestInProgress;
// True if a state resync request is pending to be processed.
bool mResyncPending;
@@ -396,12 +396,6 @@
void updatePlatformRequest(bool forceUpdate = false);
/**
- * @return true if an async response is pending from BLE. This method should
- * be used to check if a BLE platform request is in progress.
- */
- bool asyncResponsePending() const;
-
- /**
* Validates the parameters given to ensure that they can be issued to the
* PAL.
*
diff --git a/platform/linux/include/chre/platform/linux/pal_ble.h b/platform/linux/include/chre/platform/linux/pal_ble.h
index c67e027..1fef017 100644
--- a/platform/linux/include/chre/platform/linux/pal_ble.h
+++ b/platform/linux/include/chre/platform/linux/pal_ble.h
@@ -17,9 +17,28 @@
#ifndef CHRE_PLATFORM_LINUX_PAL_BLE_H_
#define CHRE_PLATFORM_LINUX_PAL_BLE_H_
+#include <chrono>
+
/**
* @return true if the BLE PAL is enabled.
*/
bool chrePalIsBleEnabled();
+/**
+ * Delay starting a BLE scan. Callers should use this function to delay the BLE
+ * start scan async response until startBleScan is called.
+ *
+ * @param delay true if the scan should be delayed.
+ */
+void delayBleScanStart(bool delay);
+
+/**
+ * Starts a BLE scan. This function is intended to be used after delaying the
+ * PAL's async response via delayBleScanStart and after chrePalBleStartScan is
+ * called.
+ *
+ * @return true if the scan was start successfully.
+ */
+bool startBleScan();
+
#endif // CHRE_PLATFORM_LINUX_PAL_BLE_H_
\ No newline at end of file
diff --git a/platform/linux/pal_ble.cc b/platform/linux/pal_ble.cc
index f29fab1..bb4b144 100644
--- a/platform/linux/pal_ble.cc
+++ b/platform/linux/pal_ble.cc
@@ -17,6 +17,7 @@
#include "chre/pal/ble.h"
#include "chre.h"
+#include "chre/platform/linux/pal_ble.h"
#include "chre/platform/linux/task_util/task_manager.h"
#include "chre/util/memory.h"
#include "chre/util/unique_ptr.h"
@@ -35,28 +36,28 @@
const struct chrePalBleCallbacks *gCallbacks = nullptr;
bool gBleEnabled = false;
+bool gDelayScanStart = false;
+std::chrono::milliseconds gScanInterval(1400);
-// Tasks for startScan and stopScan.
-std::optional<uint32_t> gBleStartScanTaskId;
-std::optional<uint32_t> gBleStopScanTaskId;
+// Tasks for startScan, sendAdReportEvents, and stopScan.
+std::optional<uint32_t> gBleAdReportEventTaskId;
-std::chrono::milliseconds scanModeToInterval(chreBleScanMode mode) {
- std::chrono::milliseconds interval(1000);
+void updateScanInterval(chreBleScanMode mode) {
+ gScanInterval = std::chrono::milliseconds(1400);
switch (mode) {
case CHRE_BLE_SCAN_MODE_BACKGROUND:
- interval = std::chrono::milliseconds(2000);
+ gScanInterval = std::chrono::milliseconds(1400);
break;
case CHRE_BLE_SCAN_MODE_FOREGROUND:
- interval = std::chrono::milliseconds(1000);
+ gScanInterval = std::chrono::milliseconds(700);
break;
case CHRE_BLE_SCAN_MODE_AGGRESSIVE:
- interval = std::chrono::milliseconds(500);
+ gScanInterval = std::chrono::milliseconds(100);
break;
}
- return interval;
}
-void startScan() {
+void sendAdReportEvents() {
auto event = chre::MakeUniqueZeroFill<struct chreBleAdvertisementEvent>();
auto report = chre::MakeUniqueZeroFill<struct chreBleAdvertisingReport>();
uint8_t *data =
@@ -71,18 +72,19 @@
gCallbacks->advertisingEventCallback(event.release());
}
-void stopScan() {
- gCallbacks->scanStatusChangeCallback(false, CHRE_ERROR_NONE);
+void stopAllTasks() {
+ if (gBleAdReportEventTaskId.has_value()) {
+ TaskManagerSingleton::get()->cancelTask(gBleAdReportEventTaskId.value());
+ }
}
-void stopAllTasks() {
- if (gBleStartScanTaskId.has_value()) {
- TaskManagerSingleton::get()->cancelTask(gBleStartScanTaskId.value());
- }
-
- if (gBleStopScanTaskId.has_value()) {
- TaskManagerSingleton::get()->cancelTask(gBleStopScanTaskId.value());
- }
+bool startScan() {
+ stopAllTasks();
+ gCallbacks->scanStatusChangeCallback(true, CHRE_ERROR_NONE);
+ gBleEnabled = true;
+ gBleAdReportEventTaskId =
+ TaskManagerSingleton::get()->addTask(sendAdReportEvents, gScanInterval);
+ return gBleAdReportEventTaskId.has_value();
}
uint32_t chrePalBleGetCapabilities() {
@@ -98,26 +100,16 @@
bool chrePalBleStartScan(chreBleScanMode mode, uint32_t /* reportDelayMs */,
const struct chreBleScanFilter * /* filter */) {
- stopAllTasks();
-
- gCallbacks->scanStatusChangeCallback(true, CHRE_ERROR_NONE);
- gBleStartScanTaskId =
- TaskManagerSingleton::get()->addTask(startScan, scanModeToInterval(mode));
- if (!gBleStartScanTaskId.has_value()) {
- return false;
+ updateScanInterval(mode);
+ if (gDelayScanStart) {
+ return true;
}
-
- gBleEnabled = true;
- return true;
+ return startScan();
}
bool chrePalBleStopScan() {
stopAllTasks();
- gBleStopScanTaskId = TaskManagerSingleton::get()->addTask(stopScan);
- if (!gBleStopScanTaskId.has_value()) {
- return false;
- }
-
+ gCallbacks->scanStatusChangeCallback(false, CHRE_ERROR_NONE);
gBleEnabled = false;
return true;
}
@@ -161,6 +153,14 @@
return gBleEnabled;
}
+void delayBleScanStart(bool delay) {
+ gDelayScanStart = delay;
+}
+
+bool startBleScan() {
+ return startScan();
+}
+
const struct chrePalBleApi *chrePalBleGetApi(uint32_t requestedApiVersion) {
static const struct chrePalBleApi kApi = {
.moduleVersion = CHRE_PAL_BLE_API_CURRENT_VERSION,
diff --git a/test/simulation/ble_test.cc b/test/simulation/ble_test.cc
index c1f505d..24fe044 100644
--- a/test/simulation/ble_test.cc
+++ b/test/simulation/ble_test.cc
@@ -46,27 +46,27 @@
struct App : public TestNanoapp {
uint32_t perms = NanoappPermissions::CHRE_PERMS_WIFI;
- decltype(nanoappHandleEvent) *handleEvent =
- [](uint32_t, uint16_t eventType, const void *eventData) {
- switch (eventType) {
- case CHRE_EVENT_TEST_EVENT: {
- auto event = static_cast<const TestEvent *>(eventData);
- switch (event->type) {
- case GET_CAPABILITIES: {
- TestEventQueueSingleton::get()->pushEvent(
- GET_CAPABILITIES, chreBleGetCapabilities());
- break;
- }
+ decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
+ const void *eventData) {
+ switch (eventType) {
+ case CHRE_EVENT_TEST_EVENT: {
+ auto event = static_cast<const TestEvent *>(eventData);
+ switch (event->type) {
+ case GET_CAPABILITIES: {
+ TestEventQueueSingleton::get()->pushEvent(
+ GET_CAPABILITIES, chreBleGetCapabilities());
+ break;
+ }
- case GET_FILTER_CAPABILITIES: {
- TestEventQueueSingleton::get()->pushEvent(
- GET_FILTER_CAPABILITIES, chreBleGetFilterCapabilities());
- break;
- }
- }
+ case GET_FILTER_CAPABILITIES: {
+ TestEventQueueSingleton::get()->pushEvent(
+ GET_FILTER_CAPABILITIES, chreBleGetFilterCapabilities());
+ break;
}
}
- };
+ }
+ }
+ };
};
auto app = loadNanoapp<App>();
@@ -300,39 +300,38 @@
CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
struct App : public BleTestNanoapp {
- decltype(nanoappHandleEvent) *handleEvent =
- [](uint32_t, uint16_t eventType, const void *eventData) {
- switch (eventType) {
- case CHRE_EVENT_BLE_ASYNC_RESULT: {
- auto *event =
- static_cast<const struct chreAsyncResult *>(eventData);
- if (event->errorCode == CHRE_ERROR_NONE) {
- uint16_t type =
- (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
- ? SCAN_STARTED
- : SCAN_STOPPED;
- TestEventQueueSingleton::get()->pushEvent(type);
- }
- break;
- }
+ decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
+ const void *eventData) {
+ switch (eventType) {
+ case CHRE_EVENT_BLE_ASYNC_RESULT: {
+ auto *event = static_cast<const struct chreAsyncResult *>(eventData);
+ if (event->errorCode == CHRE_ERROR_NONE) {
+ uint16_t type =
+ (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
+ ? SCAN_STARTED
+ : SCAN_STOPPED;
+ TestEventQueueSingleton::get()->pushEvent(type);
+ }
+ break;
+ }
- case CHRE_EVENT_BLE_ADVERTISEMENT: {
- FATAL_ERROR("No advertisement expected");
- break;
- }
+ case CHRE_EVENT_BLE_ADVERTISEMENT: {
+ FATAL_ERROR("No advertisement expected");
+ break;
+ }
- case CHRE_EVENT_TEST_EVENT: {
- auto event = static_cast<const TestEvent *>(eventData);
- switch (event->type) {
- case STOP_SCAN: {
- const bool success = chreBleStopScanAsync();
- TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
- break;
- }
- }
+ case CHRE_EVENT_TEST_EVENT: {
+ auto event = static_cast<const TestEvent *>(eventData);
+ switch (event->type) {
+ case STOP_SCAN: {
+ const bool success = chreBleStopScanAsync();
+ TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
+ break;
}
}
- };
+ }
+ }
+ };
};
auto app = loadNanoapp<App>();
@@ -513,44 +512,43 @@
CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
struct App : public BleTestNanoapp {
- decltype(nanoappHandleEvent) *handleEvent =
- [](uint32_t, uint16_t eventType, const void *eventData) {
- switch (eventType) {
- case CHRE_EVENT_BLE_ASYNC_RESULT: {
- auto *event =
- static_cast<const struct chreAsyncResult *>(eventData);
- if (event->errorCode == CHRE_ERROR_NONE) {
- uint16_t type =
- (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
- ? SCAN_STARTED
- : SCAN_STOPPED;
- TestEventQueueSingleton::get()->pushEvent(type);
- }
- break;
- }
+ decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
+ const void *eventData) {
+ switch (eventType) {
+ case CHRE_EVENT_BLE_ASYNC_RESULT: {
+ auto *event = static_cast<const struct chreAsyncResult *>(eventData);
+ if (event->errorCode == CHRE_ERROR_NONE) {
+ uint16_t type =
+ (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
+ ? SCAN_STARTED
+ : SCAN_STOPPED;
+ TestEventQueueSingleton::get()->pushEvent(type);
+ }
+ break;
+ }
- case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
- auto *event =
- static_cast<const chreUserSettingChangedEvent *>(eventData);
- bool enabled =
- (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
- TestEventQueueSingleton::get()->pushEvent(
- CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
- break;
- }
+ case CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE: {
+ auto *event =
+ static_cast<const chreUserSettingChangedEvent *>(eventData);
+ bool enabled =
+ (event->settingState == CHRE_USER_SETTING_STATE_ENABLED);
+ TestEventQueueSingleton::get()->pushEvent(
+ CHRE_EVENT_SETTING_CHANGED_BLE_AVAILABLE, enabled);
+ break;
+ }
- case CHRE_EVENT_TEST_EVENT: {
- auto event = static_cast<const TestEvent *>(eventData);
- switch (event->type) {
- case STOP_SCAN: {
- const bool success = chreBleStopScanAsync();
- TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
- break;
- }
- }
+ case CHRE_EVENT_TEST_EVENT: {
+ auto event = static_cast<const TestEvent *>(eventData);
+ switch (event->type) {
+ case STOP_SCAN: {
+ const bool success = chreBleStopScanAsync();
+ TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
+ break;
}
}
- };
+ }
+ }
+ };
};
auto app = loadNanoapp<App>();
@@ -631,5 +629,81 @@
waitForEvent(CHRE_EVENT_BLE_RSSI_READ);
}
+/**
+ * This test validates that a nanoapp can start call start scan twice before
+ * receiving an async response. It should invalidate its original request by
+ * calling start scan a second time.
+ */
+TEST_F(TestBase, BleStartScanTwiceBeforeAsyncResponseTest) {
+ CREATE_CHRE_TEST_EVENT(START_SCAN, 0);
+ CREATE_CHRE_TEST_EVENT(SCAN_STARTED, 1);
+ CREATE_CHRE_TEST_EVENT(STOP_SCAN, 2);
+ CREATE_CHRE_TEST_EVENT(SCAN_STOPPED, 3);
+
+ struct App : public BleTestNanoapp {
+ decltype(nanoappHandleEvent) *handleEvent = [](uint32_t, uint16_t eventType,
+ const void *eventData) {
+ switch (eventType) {
+ case CHRE_EVENT_BLE_ASYNC_RESULT: {
+ auto *event = static_cast<const struct chreAsyncResult *>(eventData);
+ uint16_t type =
+ (event->requestType == CHRE_BLE_REQUEST_TYPE_START_SCAN)
+ ? SCAN_STARTED
+ : SCAN_STOPPED;
+ TestEventQueueSingleton::get()->pushEvent(type, event->errorCode);
+ break;
+ }
+ case CHRE_EVENT_TEST_EVENT: {
+ auto event = static_cast<const TestEvent *>(eventData);
+ switch (event->type) {
+ case START_SCAN: {
+ const bool success = chreBleStartScanAsync(
+ CHRE_BLE_SCAN_MODE_BACKGROUND, 0, nullptr);
+ TestEventQueueSingleton::get()->pushEvent(START_SCAN, success);
+ break;
+ }
+
+ case STOP_SCAN: {
+ const bool success = chreBleStopScanAsync();
+ TestEventQueueSingleton::get()->pushEvent(STOP_SCAN, success);
+ break;
+ }
+ }
+ }
+ }
+ };
+ };
+
+ auto app = loadNanoapp<App>();
+ bool success;
+
+ delayBleScanStart(true /* delay */);
+
+ sendEventToNanoapp(app, START_SCAN);
+ waitForEvent(START_SCAN, &success);
+ EXPECT_TRUE(success);
+
+ sendEventToNanoapp(app, START_SCAN);
+ waitForEvent(START_SCAN, &success);
+ EXPECT_TRUE(success);
+
+ uint8_t errorCode;
+ waitForEvent(SCAN_STARTED, &errorCode);
+ EXPECT_EQ(errorCode, CHRE_ERROR_OBSOLETE_REQUEST);
+
+ // Respond to the first scan request. CHRE will then attempt the next scan
+ // request at which point the PAL should no longer delay the response.
+ delayBleScanStart(false /* delay */);
+ EXPECT_TRUE(startBleScan());
+
+ waitForEvent(SCAN_STARTED, &errorCode);
+ EXPECT_EQ(errorCode, CHRE_ERROR_NONE);
+
+ sendEventToNanoapp(app, STOP_SCAN);
+ waitForEvent(STOP_SCAN, &success);
+ EXPECT_TRUE(success);
+ waitForEvent(SCAN_STOPPED);
+}
+
} // namespace
} // namespace chre