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