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