Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e599e5ee authored by Henri Chataing's avatar Henri Chataing Committed by Automerger Merge Worker
Browse files

Merge "RootCanal: Implement a timeout for receiving the response to a LE Scan...

Merge "RootCanal: Implement a timeout for receiving the response to a LE Scan request" into main am: 67f44019 am: ddd194a5

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2899068



Change-Id: Ice05bf597ddd5c07404172a8b60ba2ed1fd2f504
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1efbe2fa ddd194a5
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ using TaskId = rootcanal::LinkLayerController::TaskId;

namespace rootcanal {

constexpr milliseconds kScanRequestTimeout(200);
constexpr milliseconds kNoDelayMs(0);
constexpr milliseconds kPageInterval(1000);
constexpr milliseconds kInquiryInterval(500);
@@ -1293,6 +1294,7 @@ ErrorCode LinkLayerController::LeSetScanEnable(bool enable,
  if (!enable) {
    scanner_.scan_enable = false;
    scanner_.pending_scan_request = {};
    scanner_.pending_scan_request_timeout = {};
    scanner_.history.clear();
    return ErrorCode::SUCCESS;
  }
@@ -1322,6 +1324,7 @@ ErrorCode LinkLayerController::LeSetScanEnable(bool enable,
  scanner_.timeout = {};
  scanner_.periodical_timeout = {};
  scanner_.pending_scan_request = {};
  scanner_.pending_scan_request_timeout = {};
  scanner_.filter_duplicates = filter_duplicates
                                   ? bluetooth::hci::FilterDuplicates::ENABLED
                                   : bluetooth::hci::FilterDuplicates::DISABLED;
@@ -1453,6 +1456,7 @@ ErrorCode LinkLayerController::LeSetExtendedScanEnable(
  if (!enable) {
    scanner_.scan_enable = false;
    scanner_.pending_scan_request = {};
    scanner_.pending_scan_request_timeout = {};
    scanner_.history.clear();
    return ErrorCode::SUCCESS;
  }
@@ -1510,6 +1514,7 @@ ErrorCode LinkLayerController::LeSetExtendedScanEnable(
  scanner_.timeout = {};
  scanner_.periodical_timeout = {};
  scanner_.pending_scan_request = {};
  scanner_.pending_scan_request_timeout = {};
  scanner_.filter_duplicates = filter_duplicates;
  scanner_.duration = duration_ms;
  scanner_.period = period_ms;
@@ -3184,6 +3189,8 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu(
    // is connectable in the scan response report.
    scanner_.connectable_scan_response = connectable_advertising;
    scanner_.pending_scan_request = advertising_address;
    scanner_.pending_scan_request_timeout =
        std::chrono::steady_clock::now() + kScanRequestTimeout;

    INFO(id_,
         "Sending LE Scan request to advertising address {} with scanning "
@@ -5057,6 +5064,15 @@ void LinkLayerController::LeScanning() {
    scanner_.timeout = now + scanner_.duration;
    scanner_.periodical_timeout = now + scanner_.period;
  }

  // Pending scan timeout.
  // Cancel the pending scan request. This may condition may be triggered
  // when the advertiser is stopped before sending the scan request.
  if (scanner_.pending_scan_request_timeout.has_value() &&
      now >= scanner_.pending_scan_request_timeout.value()) {
    scanner_.pending_scan_request = {};
    scanner_.pending_scan_request_timeout = {};
  }
}

void LinkLayerController::LeSynchronization() {
+2 −0
Original line number Diff line number Diff line
@@ -1066,6 +1066,8 @@ class LinkLayerController {
    // Save information about the advertising PDU being scanned.
    bool connectable_scan_response;
    std::optional<AddressWithType> pending_scan_request{};
    std::optional<std::chrono::steady_clock::time_point>
        pending_scan_request_timeout{};

    // Time keeping
    std::optional<std::chrono::steady_clock::time_point> timeout;
+111 −0
Original line number Diff line number Diff line
# Copyright 2023 Google LLC
#
# 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
#
#     https://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.

import asyncio
import hci_packets as hci
import link_layer_packets as ll
import unittest
from hci_packets import ErrorCode
from py.bluetooth import Address
from py.controller import ControllerTest, generate_rpa


class Test(ControllerTest):

    # Verify that the scanner gracefully handles missing scan responses
    # after a timeout.
    async def test(self):
        # Test parameters.
        LL_scanner_scanInterval_MIN = 0x2000
        LL_scanner_scanInterval_MAX = 0x2000
        LL_scanner_scanWindow_MIN = 0x200
        LL_scanner_scanWindow_MAX = 0x200
        LL_scanner_Adv_Channel_Map = 0x7

        controller = self.controller
        peer_address = Address('aa:bb:cc:dd:ee:ff')

        controller.send_cmd(
            hci.LeSetScanParameters(le_scan_type=hci.LeScanType.ACTIVE,
                                    le_scan_interval=LL_scanner_scanInterval_MAX,
                                    le_scan_window=LL_scanner_scanWindow_MAX,
                                    own_address_type=hci.OwnAddressType.RESOLVABLE_OR_PUBLIC_ADDRESS,
                                    scanning_filter_policy=hci.LeScanningFilterPolicy.ACCEPT_ALL))

        await self.expect_evt(hci.LeSetScanParametersComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))

        controller.send_cmd(
            hci.LeSetScanEnable(le_scan_enable=hci.Enable.ENABLED, filter_duplicates=hci.Enable.DISABLED))

        await self.expect_evt(hci.LeSetScanEnableComplete(status=ErrorCode.SUCCESS, num_hci_command_packets=1))

        controller.send_ll(ll.LeLegacyAdvertisingPdu(source_address=peer_address,
                                                     advertising_address_type=ll.AddressType.RANDOM,
                                                     advertising_type=ll.LegacyAdvertisingType.ADV_SCAN_IND,
                                                     advertising_data=[]),
                           rssi=-16)

        await self.expect_evt(
            hci.LeAdvertisingReport(responses=[
                hci.LeAdvertisingResponse(event_type=hci.AdvertisingEventType.ADV_SCAN_IND,
                                          address_type=hci.AddressType.RANDOM_DEVICE_ADDRESS,
                                          address=peer_address,
                                          advertising_data=[],
                                          rssi=0xf0)
            ]))

        await self.expect_ll(
            ll.LeScan(source_address=controller.address,
                      destination_address=peer_address,
                      advertising_address_type=ll.AddressType.RANDOM,
                      scanning_address_type=ll.AddressType.PUBLIC))

        # No response is sent for the duration of the scan request timeout.
        # The next scan request must be correctly handled.
        await asyncio.sleep(1.0)

        controller.send_ll(ll.LeLegacyAdvertisingPdu(source_address=peer_address,
                                                     advertising_address_type=ll.AddressType.RANDOM,
                                                     advertising_type=ll.LegacyAdvertisingType.ADV_SCAN_IND,
                                                     advertising_data=[]),
                           rssi=-16)

        await self.expect_evt(
            hci.LeAdvertisingReport(responses=[
                hci.LeAdvertisingResponse(event_type=hci.AdvertisingEventType.ADV_SCAN_IND,
                                          address_type=hci.AddressType.RANDOM_DEVICE_ADDRESS,
                                          address=peer_address,
                                          advertising_data=[],
                                          rssi=0xf0)
            ]))

        await self.expect_ll(
            ll.LeScan(source_address=controller.address,
                      destination_address=peer_address,
                      advertising_address_type=ll.AddressType.RANDOM,
                      scanning_address_type=ll.AddressType.PUBLIC))

        controller.send_ll(ll.LeScanResponse(source_address=peer_address,
                                             advertising_address_type=ll.AddressType.RANDOM,
                                             scan_response_data=[]),
                           rssi=-16)

        await self.expect_evt(
            hci.LeAdvertisingReport(responses=[
                hci.LeAdvertisingResponse(event_type=hci.AdvertisingEventType.SCAN_RESPONSE,
                                          address_type=hci.AddressType.RANDOM_DEVICE_ADDRESS,
                                          address=peer_address,
                                          advertising_data=[],
                                          rssi=0xf0)
            ]))
+1 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ tests = [
    'LMP.LIH.BV_144_C',
    'LMP.LIH.BV_149_C',
    'LL.scan_collision',
    'LL.scan_timeout',
    'LMP.page_collision',
]