Skip to content

Commit 585e3f8

Browse files
committed
end2end: Implement a fake IComposerClient [4/N]
Implements a minimal but function ComposerClient which responds to all the initial SurfaceFlinger queries needed to allow fake physical displays to be connected and used. The implementation code is split into two parts. First is a series of special delegating helper implementations, located under the hwc3/delegators directory. These implement the full interface by delegating to a templated handler function. This allows the default behavior for the full interface to be specified by just writing a single function, whether that behavior is to return an error for all calls, or to do something else. This is then used as a base class by the actual implementation which focuses on overriding only the interface functions which need special handling. The existing files are shuffled around a bit, as the delegators will be reused by a subsequent CL to define a intercepting/forwarding observer implementation, and this will be distinct from the "fake" implementation as it will eventually be used to observe the interactions between SF and the drm_hwcomposer real implementation for use by the test. This change also introduces a local SharedMutex helper, which wraps `std::shared_mutex` and enforces the correct locking for the two types of access (exclusive or shared). The shared mutex allows the display changes to be made by the test potentially at the same time as SF is making calls to query the display properties. With the fake implementation correctly configured for SurfaceFlinger to use, SF now boots and enters a usable state. The test can now control SF through the front-end interfaces, though there are other changes still needed to make presentation work. Flag: TEST_ONLY Bug: 372735083 Test: atest surfaceflinger_end2end_tests Change-Id: Ic67ed4ed0627649c70910cb20643bfa0c7b75208
1 parent f110207 commit 585e3f8

File tree

13 files changed

+1545
-166
lines changed

13 files changed

+1545
-166
lines changed

services/surfaceflinger/tests/end2end/Android.bp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ cc_test {
3232
],
3333
srcs: [
3434
"main.cpp",
35-
3635
"test_framework/core/EdidBuilder.cpp",
3736
"test_framework/core/TestService.cpp",
38-
"test_framework/fake_hwc3/Hwc3Composer.cpp",
39-
"test_framework/fake_hwc3/Hwc3Controller.cpp",
37+
"test_framework/hwc3/FakeComposer.cpp",
38+
"test_framework/hwc3/Hwc3Controller.cpp",
4039
"test_framework/surfaceflinger/SFController.cpp",
4140

4241
// Internal tests
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <functional>
20+
#include <mutex>
21+
#include <shared_mutex>
22+
#include <type_traits>
23+
24+
namespace android::surfaceflinger::tests::end2end::test_framework::core {
25+
26+
// Ensures all access to a state structure `SharedState` is done while holding an appropriate
27+
// `std::shared_mutex` lock.
28+
//
29+
// This works around limitations with Clang thread safety analysis when using `std::shared_lock`, as
30+
// there will be a compiler diagnostic despite acquiring the lock.
31+
template <typename SharedState>
32+
class GuardedSharedState final {
33+
public:
34+
// Allows shared read-only access to the state. The lambda is invoked with a `const
35+
// SharedState&` first argument referencing the state.
36+
template <typename F>
37+
auto withSharedLock(F&& continuation) const -> std::invoke_result_t<F, const SharedState&> {
38+
const std::shared_lock lock(mMutex);
39+
return std::invoke(std::forward<F>(continuation), mState);
40+
}
41+
42+
// Allows exclusive read/write access to the state. The lambda is invoked with a `SharedState&`
43+
// first argument referencing the state.
44+
template <typename F>
45+
auto withExclusiveLock(F&& continuation) -> std::invoke_result_t<F, SharedState&> {
46+
const std::lock_guard lock(mMutex);
47+
return std::invoke(std::forward<F>(continuation), mState);
48+
}
49+
50+
private:
51+
mutable std::shared_mutex mMutex;
52+
SharedState mState;
53+
};
54+
55+
} // namespace android::surfaceflinger::tests::end2end::test_framework::core

services/surfaceflinger/tests/end2end/test_framework/core/TestService.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#include "test_framework/core/DisplayConfiguration.h"
2727
#include "test_framework/core/TestService.h"
28-
#include "test_framework/fake_hwc3/Hwc3Controller.h"
28+
#include "test_framework/hwc3/Hwc3Controller.h"
2929
#include "test_framework/surfaceflinger/SFController.h"
3030

3131
namespace android::surfaceflinger::tests::end2end::test_framework::core {
@@ -56,7 +56,7 @@ auto TestService::init(std::span<const DisplayConfiguration> displays)
5656
-> base::expected<void, std::string> {
5757
using namespace std::string_literals;
5858

59-
auto hwcResult = fake_hwc3::Hwc3Controller::make(displays);
59+
auto hwcResult = hwc3::Hwc3Controller::make(displays);
6060
if (!hwcResult) {
6161
return base::unexpected(std::move(hwcResult).error());
6262
}
@@ -68,7 +68,7 @@ auto TestService::init(std::span<const DisplayConfiguration> displays)
6868
}
6969
auto flinger = *std::move(flingerResult);
7070

71-
surfaceflinger::SFController::useHwcService(fake_hwc3::Hwc3Controller::getServiceName());
71+
surfaceflinger::SFController::useHwcService(hwc3::Hwc3Controller::getServiceName());
7272

7373
if (auto result = flinger->startAndConnect(); !result) {
7474
return base::unexpected(std::move(result).error());

services/surfaceflinger/tests/end2end/test_framework/core/TestService.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ class SFController;
3434

3535
} // namespace surfaceflinger
3636

37-
namespace fake_hwc3 {
37+
namespace hwc3 {
3838

3939
class Hwc3Controller;
4040

41-
} // namespace fake_hwc3
41+
} // namespace hwc3
4242

4343
namespace core {
4444

@@ -53,7 +53,7 @@ class TestService final {
5353
explicit TestService(Passkey passkey);
5454

5555
// Obtains the HWC3 back-end controller
56-
[[nodiscard]] auto hwc() -> fake_hwc3::Hwc3Controller& {
56+
[[nodiscard]] auto hwc() -> hwc3::Hwc3Controller& {
5757
CHECK(mHwc);
5858
return *mHwc;
5959
}
@@ -68,7 +68,7 @@ class TestService final {
6868
[[nodiscard]] auto init(std::span<const DisplayConfiguration> displays)
6969
-> base::expected<void, std::string>;
7070

71-
std::shared_ptr<fake_hwc3::Hwc3Controller> mHwc;
71+
std::shared_ptr<hwc3::Hwc3Controller> mHwc;
7272
std::shared_ptr<surfaceflinger::SFController> mFlinger;
7373
};
7474

services/surfaceflinger/tests/end2end/test_framework/fake_hwc3/Hwc3Composer.cpp

Lines changed: 0 additions & 123 deletions
This file was deleted.

0 commit comments

Comments
 (0)