Skip to content

Commit 47c58ae

Browse files
Merge branch 'main' into feature/split_AttMtuExchange_interface
2 parents 15787f3 + f38e0ac commit 47c58ae

File tree

15 files changed

+764
-6
lines changed

15 files changed

+764
-6
lines changed

.clusterfuzzlite/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM gcr.io/oss-fuzz-base/base-builder@sha256:81c0c136cda1ba3f85fd41f65851f7feb942a5fc0aeca4c4f02fb53fa5e835d8
1+
FROM gcr.io/oss-fuzz-base/base-builder@sha256:0c430433cb437e80f8091fc163aac707d35e987ce3b3dc3b64eaf4823a0e74b2
22

33
HEALTHCHECK NONE
44

.devcontainer/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
FROM ghcr.io/philips-software/amp-devcontainer-cpp:6.6.3@sha256:0af2cde9ba1c07bb615c6737b522a29a63f417a0d38f0057a54edf24c75f479e
1+
FROM ghcr.io/philips-software/amp-devcontainer-cpp:6.6.4@sha256:0d6b572f5c589def3efb245844528ef44903c9927149da9bcec21feab36388b9
22

33
HEALTHCHECK NONE

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
host_build_test_container:
5252
name: Host Build & Test (amp-devcontainer-cpp)
5353
runs-on: ubuntu-latest
54-
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.1@sha256:9ba2d20db24a646edd6ea7a8a075e76239ce63d1542cc823242e680901e792f9 # v6.6.1
54+
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.4@sha256:0d6b572f5c589def3efb245844528ef44903c9927149da9bcec21feab36388b9 # v6.6.4
5555
steps:
5656
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
5757
with:
@@ -74,7 +74,7 @@ jobs:
7474
host_build_test_clang_msvc:
7575
name: Host Build & Test (clang-msvc)
7676
runs-on: ubuntu-latest
77-
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.1@sha256:9ba2d20db24a646edd6ea7a8a075e76239ce63d1542cc823242e680901e792f9 # v6.6.1
77+
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.4@sha256:0d6b572f5c589def3efb245844528ef44903c9927149da9bcec21feab36388b9 # v6.6.4
7878
steps:
7979
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
8080
with:

.github/workflows/static-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
sonar:
1919
name: SonarCloud
2020
runs-on: ubuntu-latest
21-
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.1@sha256:9ba2d20db24a646edd6ea7a8a075e76239ce63d1542cc823242e680901e792f9 # v6.6.1
21+
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.4@sha256:0d6b572f5c589def3efb245844528ef44903c9927149da9bcec21feab36388b9 # v6.6.4
2222
steps:
2323
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2424
with:
@@ -63,7 +63,7 @@ jobs:
6363
codeql:
6464
name: CodeQL
6565
runs-on: ubuntu-latest
66-
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.1@sha256:9ba2d20db24a646edd6ea7a8a075e76239ce63d1542cc823242e680901e792f9 # v6.6.1
66+
container: ghcr.io/philips-software/amp-devcontainer-cpp:v6.6.4@sha256:0d6b572f5c589def3efb245844528ef44903c9927149da9bcec21feab36388b9 # v6.6.4
6767
permissions:
6868
security-events: write
6969
steps:

services/ble/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ target_sources(services.ble PRIVATE
2626
BondStorageSynchronizer.hpp
2727
Gap.cpp
2828
Gap.hpp
29+
GapPeripheralIntervalDecorator.cpp
30+
GapPeripheralIntervalDecorator.hpp
2931
Gatt.cpp
3032
Gatt.hpp
3133
GattClient.cpp
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#include "services/ble/GapPeripheralIntervalDecorator.hpp"
2+
#include <cassert>
3+
4+
namespace services
5+
{
6+
const services::GapConnectionParameters GapPeripheralIntervalDecorator::defaultConnParam{
7+
6,
8+
6,
9+
0,
10+
500,
11+
};
12+
13+
const services::GapConnectionParameters GapPeripheralIntervalDecorator::longConnParam{
14+
50,
15+
50,
16+
0,
17+
500,
18+
};
19+
20+
GapPeripheralIntervalDecorator::GapPeripheralIntervalDecorator(GapPeripheral& subject)
21+
: GapPeripheralDecorator(subject)
22+
{}
23+
24+
void GapPeripheralIntervalDecorator::SwitchToLongInterval()
25+
{
26+
useLongInterval = true;
27+
SwitchInterval();
28+
}
29+
30+
void GapPeripheralIntervalDecorator::SwitchToUserInterval()
31+
{
32+
useLongInterval = false;
33+
SwitchInterval();
34+
}
35+
36+
void GapPeripheralIntervalDecorator::Advertise(services::GapAdvertisementType type, AdvertisementIntervalMultiplier multiplier)
37+
{
38+
userAdvparam.emplace(type, multiplier);
39+
GapPeripheralDecorator::Advertise(type, useLongInterval ? longAdvMutiplier : multiplier);
40+
}
41+
42+
void GapPeripheralIntervalDecorator::Standby()
43+
{
44+
pendingAdv = false;
45+
GapPeripheralDecorator::Standby();
46+
}
47+
48+
void GapPeripheralIntervalDecorator::StateChanged(services::GapState state)
49+
{
50+
this->state = state;
51+
GapPeripheralDecorator::StateChanged(state);
52+
if (state == services::GapState::connected)
53+
UpdateConnectionParameters();
54+
else if (state == services::GapState::standby)
55+
HandlePendingAdvertise();
56+
}
57+
58+
void GapPeripheralIntervalDecorator::SetConnectionParameters(const services::GapConnectionParameters& connParam)
59+
{
60+
userConnParam = connParam;
61+
if (state == services::GapState::connected)
62+
UpdateConnectionParameters();
63+
}
64+
65+
void GapPeripheralIntervalDecorator::SwitchInterval()
66+
{
67+
if (state == services::GapState::advertising)
68+
{
69+
assert(userAdvparam.has_value());
70+
Standby();
71+
pendingAdv = true;
72+
}
73+
else if (state == services::GapState::connected)
74+
UpdateConnectionParameters();
75+
}
76+
77+
void GapPeripheralIntervalDecorator::UpdateConnectionParameters()
78+
{
79+
if (useLongInterval)
80+
GapPeripheralDecorator::SetConnectionParameters(longConnParam);
81+
else
82+
GapPeripheralDecorator::SetConnectionParameters(userConnParam.has_value() ? userConnParam.value() : defaultConnParam);
83+
}
84+
85+
void GapPeripheralIntervalDecorator::HandlePendingAdvertise()
86+
{
87+
if (pendingAdv)
88+
{
89+
pendingAdv = false;
90+
auto [userAdvType, userAdvMultiplier] = userAdvparam.value();
91+
GapPeripheralDecorator::Advertise(userAdvType, useLongInterval ? longAdvMutiplier : userAdvMultiplier);
92+
}
93+
}
94+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#ifndef SERVICES_GAP_PERIPHERAL_INTERVAL_DECORATOR_HPP
2+
#define SERVICES_GAP_PERIPHERAL_INTERVAL_DECORATOR_HPP
3+
4+
#include "services/ble/Gap.hpp"
5+
#include <optional>
6+
7+
namespace services
8+
{
9+
class GapPeripheralIntervalController
10+
{
11+
public:
12+
virtual void SwitchToLongInterval() = 0;
13+
virtual void SwitchToUserInterval() = 0;
14+
};
15+
16+
class GapPeripheralIntervalDecorator
17+
: public services::GapPeripheralDecorator
18+
, public GapPeripheralIntervalController
19+
{
20+
public:
21+
explicit GapPeripheralIntervalDecorator(GapPeripheral& subject);
22+
23+
// Implementation of GapPeripheralIntervalController
24+
void SwitchToLongInterval() override;
25+
void SwitchToUserInterval() override;
26+
27+
// Implementation of GapPeripheralDecorator
28+
void Advertise(services::GapAdvertisementType type, AdvertisementIntervalMultiplier multiplier) override;
29+
void Standby() override;
30+
void StateChanged(services::GapState state) override;
31+
void SetConnectionParameters(const services::GapConnectionParameters& connParam) override;
32+
33+
private:
34+
void SwitchInterval();
35+
void UpdateConnectionParameters();
36+
void HandlePendingAdvertise();
37+
38+
static constexpr AdvertisementIntervalMultiplier longAdvMutiplier = 50;
39+
static const services::GapConnectionParameters defaultConnParam;
40+
static const services::GapConnectionParameters longConnParam;
41+
bool useLongInterval = false;
42+
services::GapState state = services::GapState::standby;
43+
std::optional<std::pair<services::GapAdvertisementType, AdvertisementIntervalMultiplier>> userAdvparam;
44+
bool pendingAdv = false;
45+
std::optional<services::GapConnectionParameters> userConnParam;
46+
};
47+
}
48+
49+
#endif

services/ble/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ target_sources(services.ble_test PRIVATE
1515
TestGapCentral.cpp
1616
TestGapPairing.cpp
1717
TestGapPeripheral.cpp
18+
TestGapPeripheralIntervalDecorator.cpp
1819
TestGatt.cpp
1920
TestGattClient.cpp
2021
TestClaimingGattClientAdapter.cpp
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include "services/ble/GapPeripheralIntervalDecorator.hpp"
2+
#include "services/ble/test_doubles/GapPeripheralMock.hpp"
3+
#include "services/ble/test_doubles/GapPeripheralObserverMock.hpp"
4+
#include "gmock/gmock.h"
5+
6+
class GapPeripheralIntervalDecoratorTest
7+
: public testing::Test
8+
{
9+
public:
10+
testing::StrictMock<services::GapPeripheralMock> gap;
11+
services::GapPeripheralIntervalDecorator gapPeripheralIntervalDecorator{ gap };
12+
testing::StrictMock<services::GapPeripheralObserverMock> gapObserver{ gapPeripheralIntervalDecorator };
13+
};
14+
15+
TEST_F(GapPeripheralIntervalDecoratorTest, use_user_adv_interval)
16+
{
17+
EXPECT_CALL(gap, Advertise(services::GapAdvertisementType::advInd, 10));
18+
gapPeripheralIntervalDecorator.Advertise(services::GapAdvertisementType::advInd, 10);
19+
}
20+
21+
TEST_F(GapPeripheralIntervalDecoratorTest, use_long_adv_interval)
22+
{
23+
gapPeripheralIntervalDecorator.SwitchToLongInterval();
24+
EXPECT_CALL(gap, Advertise(services::GapAdvertisementType::advInd, 50));
25+
gapPeripheralIntervalDecorator.Advertise(services::GapAdvertisementType::advInd, 10);
26+
}
27+
28+
TEST_F(GapPeripheralIntervalDecoratorTest, switch_to_long_and_back_interval_while_advertise)
29+
{
30+
EXPECT_CALL(gap, Advertise(services::GapAdvertisementType::advInd, 10));
31+
gapPeripheralIntervalDecorator.Advertise(services::GapAdvertisementType::advInd, 10);
32+
33+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::advertising));
34+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::advertising);
35+
36+
EXPECT_CALL(gap, Standby());
37+
gapPeripheralIntervalDecorator.SwitchToLongInterval();
38+
39+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::standby));
40+
EXPECT_CALL(gap, Advertise(services::GapAdvertisementType::advInd, 50));
41+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::standby);
42+
43+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::advertising));
44+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::advertising);
45+
46+
EXPECT_CALL(gap, Standby());
47+
gapPeripheralIntervalDecorator.SwitchToUserInterval();
48+
49+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::standby));
50+
EXPECT_CALL(gap, Advertise(services::GapAdvertisementType::advInd, 10));
51+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::standby);
52+
}
53+
54+
TEST_F(GapPeripheralIntervalDecoratorTest, requested_standby_will_overwrite_pending_adv)
55+
{
56+
EXPECT_CALL(gap, Advertise(services::GapAdvertisementType::advInd, 10));
57+
gapPeripheralIntervalDecorator.Advertise(services::GapAdvertisementType::advInd, 10);
58+
59+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::advertising));
60+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::advertising);
61+
62+
EXPECT_CALL(gap, Standby());
63+
gapPeripheralIntervalDecorator.Standby();
64+
65+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::standby));
66+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::standby);
67+
}
68+
69+
TEST_F(GapPeripheralIntervalDecoratorTest, use_default_connection_parameter_when_connect)
70+
{
71+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::connected));
72+
EXPECT_CALL(gap, SetConnectionParameters(testing::_)).WillOnce(testing::Invoke([](const services::GapConnectionParameters& connParam)
73+
{
74+
EXPECT_EQ(connParam.minConnIntMultiplier, 6);
75+
EXPECT_EQ(connParam.maxConnIntMultiplier, 6);
76+
EXPECT_EQ(connParam.slaveLatency, 0);
77+
EXPECT_EQ(connParam.supervisorTimeoutMs, 500);
78+
}));
79+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::connected);
80+
}
81+
82+
TEST_F(GapPeripheralIntervalDecoratorTest, use_user_connection_parameter_when_connect)
83+
{
84+
services::GapConnectionParameters connParam{ 10, 10, 0, 500 };
85+
gapPeripheralIntervalDecorator.SetConnectionParameters(connParam);
86+
87+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::connected));
88+
EXPECT_CALL(gap, SetConnectionParameters(testing::_)).WillOnce(testing::Invoke([](const services::GapConnectionParameters& connParam)
89+
{
90+
EXPECT_EQ(connParam.minConnIntMultiplier, 10);
91+
EXPECT_EQ(connParam.maxConnIntMultiplier, 10);
92+
EXPECT_EQ(connParam.slaveLatency, 0);
93+
EXPECT_EQ(connParam.supervisorTimeoutMs, 500);
94+
}));
95+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::connected);
96+
}
97+
98+
TEST_F(GapPeripheralIntervalDecoratorTest, use_long_connection_parameter_when_connect)
99+
{
100+
gapPeripheralIntervalDecorator.SwitchToLongInterval();
101+
102+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::connected));
103+
EXPECT_CALL(gap, SetConnectionParameters(testing::_)).WillOnce(testing::Invoke([](const services::GapConnectionParameters& connParam)
104+
{
105+
EXPECT_EQ(connParam.minConnIntMultiplier, 50);
106+
EXPECT_EQ(connParam.maxConnIntMultiplier, 50);
107+
EXPECT_EQ(connParam.slaveLatency, 0);
108+
EXPECT_EQ(connParam.supervisorTimeoutMs, 500);
109+
}));
110+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::connected);
111+
}
112+
113+
TEST_F(GapPeripheralIntervalDecoratorTest, switch_to_long_connection_interval_and_back)
114+
{
115+
EXPECT_CALL(gapObserver, StateChanged(services::GapState::connected));
116+
EXPECT_CALL(gap, SetConnectionParameters(testing::_)).WillOnce(testing::Invoke([](const services::GapConnectionParameters& connParam)
117+
{
118+
EXPECT_EQ(connParam.minConnIntMultiplier, 6);
119+
EXPECT_EQ(connParam.maxConnIntMultiplier, 6);
120+
EXPECT_EQ(connParam.slaveLatency, 0);
121+
EXPECT_EQ(connParam.supervisorTimeoutMs, 500);
122+
}));
123+
gapPeripheralIntervalDecorator.StateChanged(services::GapState::connected);
124+
125+
EXPECT_CALL(gap, SetConnectionParameters(testing::_)).WillOnce(testing::Invoke([](const services::GapConnectionParameters& connParam)
126+
{
127+
EXPECT_EQ(connParam.minConnIntMultiplier, 50);
128+
EXPECT_EQ(connParam.maxConnIntMultiplier, 50);
129+
EXPECT_EQ(connParam.slaveLatency, 0);
130+
EXPECT_EQ(connParam.supervisorTimeoutMs, 500);
131+
}));
132+
gapPeripheralIntervalDecorator.SwitchToLongInterval();
133+
134+
EXPECT_CALL(gap, SetConnectionParameters(testing::_)).WillOnce(testing::Invoke([](const services::GapConnectionParameters& connParam)
135+
{
136+
EXPECT_EQ(connParam.minConnIntMultiplier, 6);
137+
EXPECT_EQ(connParam.maxConnIntMultiplier, 6);
138+
EXPECT_EQ(connParam.slaveLatency, 0);
139+
EXPECT_EQ(connParam.supervisorTimeoutMs, 500);
140+
}));
141+
gapPeripheralIntervalDecorator.SwitchToUserInterval();
142+
}

services/util/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_library(services.util ${EMIL_EXCLUDE_FROM_ALL} STATIC)
22

3+
protocol_buffer_echo_cpp(services.util Flash.proto)
34
protocol_buffer_echo_cpp(services.util SesameSecurity.proto)
45

56
target_link_libraries(services.util PUBLIC
@@ -33,6 +34,8 @@ target_sources(services.util PRIVATE
3334
FlashAlign.cpp
3435
FlashAlign.hpp
3536
FlashDelegate.hpp
37+
FlashEcho.cpp
38+
FlashEcho.hpp
3639
FlashMultipleAccess.cpp
3740
FlashMultipleAccess.hpp
3841
FlashQuadSpi.cpp

0 commit comments

Comments
 (0)