1 #include <SurfaceFlingerProperties.h>
2 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
3 #include <android/hardware/configstore/1.1/types.h>
4 #include <android/hardware_buffer.h>
5 #include <binder/IServiceManager.h>
6 #include <binder/Parcel.h>
7 #include <binder/ProcessState.h>
8 #include <configstore/Utils.h>
9 #include <cutils/properties.h>
10 #include <gtest/gtest.h>
11 #include <gui/ISurfaceComposer.h>
12 #include <log/log.h>
13 #include <utils/StrongPointer.h>
14
15 #include <chrono>
16 #include <memory>
17 #include <mutex>
18 #include <optional>
19 #include <thread>
20
21 #include <private/dvr/display_client.h>
22
23 using namespace android::hardware::configstore;
24 using namespace android::hardware::configstore::V1_0;
25 using android::dvr::display::DisplayClient;
26 using android::dvr::display::Surface;
27 using android::dvr::display::SurfaceAttribute;
28 using android::dvr::display::SurfaceAttributeValue;
29
30 namespace android {
31 namespace dvr {
32
33 // The transaction code for asking surface flinger if vr flinger is active. This
34 // is done as a hidden api since it's only used for tests. See the "case 1028"
35 // block in SurfaceFlinger::onTransact() in SurfaceFlinger.cpp.
36 constexpr uint32_t kIsVrFlingerActiveTransactionCode = 1028;
37
38 // The maximum amount of time to give vr flinger to activate/deactivate. If the
39 // switch hasn't completed in this amount of time, the test will fail.
40 constexpr auto kVrFlingerSwitchMaxTime = std::chrono::seconds(1);
41
42 // How long to wait between each check to see if the vr flinger switch
43 // completed.
44 constexpr auto kVrFlingerSwitchPollInterval = std::chrono::milliseconds(50);
45
46 // A Binder connection to surface flinger.
47 class SurfaceFlingerConnection {
48 public:
Create()49 static std::unique_ptr<SurfaceFlingerConnection> Create() {
50 sp<ISurfaceComposer> surface_flinger = interface_cast<ISurfaceComposer>(
51 defaultServiceManager()->getService(String16("SurfaceFlinger")));
52 if (surface_flinger == nullptr) {
53 return nullptr;
54 }
55
56 return std::unique_ptr<SurfaceFlingerConnection>(
57 new SurfaceFlingerConnection(surface_flinger));
58 }
59
60 // Returns true if the surface flinger process is still running. We use this
61 // to detect if surface flinger has crashed.
IsAlive()62 bool IsAlive() {
63 IInterface::asBinder(surface_flinger_)->pingBinder();
64 return IInterface::asBinder(surface_flinger_)->isBinderAlive();
65 }
66
67 // Return true if vr flinger is currently active, false otherwise. If there's
68 // an error communicating with surface flinger, std::nullopt is returned.
IsVrFlingerActive()69 std::optional<bool> IsVrFlingerActive() {
70 Parcel data, reply;
71 status_t result =
72 data.writeInterfaceToken(surface_flinger_->getInterfaceDescriptor());
73 if (result != OK) {
74 return std::nullopt;
75 }
76 result = IInterface::asBinder(surface_flinger_)
77 ->transact(kIsVrFlingerActiveTransactionCode, data, &reply);
78 if (result != OK) {
79 return std::nullopt;
80 }
81 bool vr_flinger_active;
82 result = reply.readBool(&vr_flinger_active);
83 if (result != OK) {
84 return std::nullopt;
85 }
86 return vr_flinger_active;
87 }
88
89 enum class VrFlingerSwitchResult : int8_t {
90 kSuccess,
91 kTimedOut,
92 kCommunicationError,
93 kSurfaceFlingerDied
94 };
95
96 // Wait for vr flinger to become active or inactive.
WaitForVrFlinger(bool wait_active)97 VrFlingerSwitchResult WaitForVrFlinger(bool wait_active) {
98 return WaitForVrFlingerTimed(wait_active, kVrFlingerSwitchPollInterval,
99 kVrFlingerSwitchMaxTime);
100 }
101
102 // Wait for vr flinger to become active or inactive, specifying custom timeouts.
WaitForVrFlingerTimed(bool wait_active,std::chrono::milliseconds pollInterval,std::chrono::seconds timeout)103 VrFlingerSwitchResult WaitForVrFlingerTimed(bool wait_active,
104 std::chrono::milliseconds pollInterval, std::chrono::seconds timeout) {
105 auto start_time = std::chrono::steady_clock::now();
106 while (1) {
107 std::this_thread::sleep_for(pollInterval);
108 if (!IsAlive()) {
109 return VrFlingerSwitchResult::kSurfaceFlingerDied;
110 }
111 std::optional<bool> vr_flinger_active = IsVrFlingerActive();
112 if (!vr_flinger_active.has_value()) {
113 return VrFlingerSwitchResult::kCommunicationError;
114 }
115 if (vr_flinger_active.value() == wait_active) {
116 return VrFlingerSwitchResult::kSuccess;
117 } else if (std::chrono::steady_clock::now() - start_time > timeout) {
118 return VrFlingerSwitchResult::kTimedOut;
119 }
120 }
121 }
122
123 private:
SurfaceFlingerConnection(sp<ISurfaceComposer> surface_flinger)124 SurfaceFlingerConnection(sp<ISurfaceComposer> surface_flinger)
125 : surface_flinger_(surface_flinger) {}
126
127 sp<ISurfaceComposer> surface_flinger_ = nullptr;
128 };
129
130 // This test activates vr flinger by creating a vr flinger surface, then
131 // deactivates vr flinger by destroying the surface. We verify that vr flinger
132 // is activated and deactivated as expected, and that surface flinger doesn't
133 // crash.
134 //
135 // If the device doesn't support vr flinger (as repoted by ConfigStore), the
136 // test does nothing.
137 //
138 // If the device is a standalone vr device, the test also does nothing, since
139 // this test verifies the behavior of display handoff from surface flinger to vr
140 // flinger and back, and standalone devices never hand control of the display
141 // back to surface flinger.
TEST(VrFlingerTest,ActivateDeactivate)142 TEST(VrFlingerTest, ActivateDeactivate) {
143 android::ProcessState::self()->startThreadPool();
144
145 // Exit immediately if the device doesn't support vr flinger. This ConfigStore
146 // check is the same mechanism used by surface flinger to decide if it should
147 // initialize vr flinger.
148 bool vr_flinger_enabled = android::sysprop::use_vr_flinger(false);
149 if (!vr_flinger_enabled) {
150 return;
151 }
152
153 auto surface_flinger_connection = SurfaceFlingerConnection::Create();
154 ASSERT_NE(surface_flinger_connection, nullptr);
155
156 // Verify we start off with vr flinger disabled.
157 ASSERT_TRUE(surface_flinger_connection->IsAlive());
158 auto vr_flinger_active = surface_flinger_connection->IsVrFlingerActive();
159 ASSERT_TRUE(vr_flinger_active.has_value());
160 ASSERT_FALSE(vr_flinger_active.value());
161
162 // Create a vr flinger surface, and verify vr flinger becomes active.
163 // Introduce a scope so that, at the end of the scope, the vr flinger surface
164 // is destroyed, and vr flinger deactivates.
165 {
166 auto display_client = DisplayClient::Create();
167 ASSERT_NE(display_client, nullptr);
168 auto metrics = display_client->GetDisplayMetrics();
169 ASSERT_TRUE(metrics.ok());
170
171 auto surface = Surface::CreateSurface({
172 {SurfaceAttribute::Direct, SurfaceAttributeValue(true)},
173 {SurfaceAttribute::Visible, SurfaceAttributeValue(true)},
174 });
175 ASSERT_TRUE(surface.ok());
176 ASSERT_TRUE(surface.get() != nullptr);
177
178 auto queue = surface.get()->CreateQueue(
179 metrics.get().display_width, metrics.get().display_height,
180 /*layer_count=*/1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
181 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
182 AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
183 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
184 /*capacity=*/1,
185 /*metadata_size=*/0);
186 ASSERT_TRUE(queue.ok());
187 ASSERT_TRUE(queue.get() != nullptr);
188
189 size_t slot;
190 pdx::LocalHandle release_fence;
191 auto buffer = queue.get()->Dequeue(/*timeout=*/0, &slot, &release_fence);
192 ASSERT_TRUE(buffer.ok());
193 ASSERT_TRUE(buffer.get() != nullptr);
194
195 ASSERT_EQ(buffer.get()->width(), metrics.get().display_width);
196 ASSERT_EQ(buffer.get()->height(), metrics.get().display_height);
197
198 void* raw_buf = nullptr;
199 ASSERT_GE(buffer.get()->buffer()->Lock(
200 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, /*x=*/0, /*y=*/0,
201 buffer.get()->width(), buffer.get()->height(), &raw_buf),
202 0);
203 ASSERT_NE(raw_buf, nullptr);
204 uint32_t* pixels = static_cast<uint32_t*>(raw_buf);
205
206 for (int i = 0; i < buffer.get()->stride() * buffer.get()->height(); ++i) {
207 pixels[i] = 0x0000ff00;
208 }
209
210 ASSERT_GE(buffer.get()->buffer()->Unlock(), 0);
211
212 ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle()), 0);
213
214 ASSERT_EQ(
215 surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/true),
216 SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess);
217 }
218
219 // Now that the vr flinger surface is destroyed, vr flinger should deactivate.
220 ASSERT_EQ(
221 surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/false),
222 SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess);
223 }
224
225 } // namespace dvr
226 } // namespace android
227