• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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