blob: f339ab01d790c325c9d4cb7da0dfc10d32e250cc [file] [log] [blame]
Ana Krulec13be8ad2018-08-21 02:43:56 +00001#include <algorithm>
2#include <functional>
3#include <limits>
4#include <ostream>
5
6#include <gtest/gtest.h>
7
8#include <gui/ISurfaceComposer.h>
9#include <gui/LayerDebugInfo.h>
10#include <gui/Surface.h>
11#include <gui/SurfaceComposerClient.h>
12
13#include <private/android_filesystem_config.h>
14#include <private/gui/ComposerService.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000015#include <ui/DisplayInfo.h>
16#include <utils/String8.h>
17
18namespace android {
19
20using Transaction = SurfaceComposerClient::Transaction;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -080021using ui::ColorMode;
Ana Krulec13be8ad2018-08-21 02:43:56 +000022
23namespace {
24const String8 DISPLAY_NAME("Credentials Display Test");
25const String8 SURFACE_NAME("Test Surface Name");
Ana Krulec13be8ad2018-08-21 02:43:56 +000026const float FRAME_SCALE = 1.0f;
27} // namespace
28
29/**
30 * This class tests the CheckCredentials method in SurfaceFlinger.
31 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
32 * return anything meaningful.
33 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080034
35// TODO(b/129481165): remove the #pragma below and fix conversion issues
36#pragma clang diagnostic push
37#pragma clang diagnostic ignored "-Wconversion"
Ana Krulec13be8ad2018-08-21 02:43:56 +000038class CredentialsTest : public ::testing::Test {
39protected:
40 void SetUp() override {
41 // Start the tests as root.
42 seteuid(AID_ROOT);
43
44 ASSERT_NO_FATAL_FAILURE(initClient());
45 }
46
47 void TearDown() override {
48 mComposerClient->dispose();
49 mBGSurfaceControl.clear();
50 mComposerClient.clear();
51 // Finish the tests as root.
52 seteuid(AID_ROOT);
53 }
54
55 sp<IBinder> mDisplay;
56 sp<IBinder> mVirtualDisplay;
57 sp<SurfaceComposerClient> mComposerClient;
58 sp<SurfaceControl> mBGSurfaceControl;
59 sp<SurfaceControl> mVirtualSurfaceControl;
60
61 void initClient() {
62 mComposerClient = new SurfaceComposerClient;
63 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
64 }
65
66 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080067 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
68 ASSERT_FALSE(mDisplay == nullptr);
69
Ana Krulec13be8ad2018-08-21 02:43:56 +000070 DisplayInfo info;
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080071 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
Ana Krulec13be8ad2018-08-21 02:43:56 +000072 const ssize_t displayWidth = info.w;
73 const ssize_t displayHeight = info.h;
74
75 // Background surface
76 mBGSurfaceControl =
77 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
78 PIXEL_FORMAT_RGBA_8888, 0);
79 ASSERT_TRUE(mBGSurfaceControl != nullptr);
80 ASSERT_TRUE(mBGSurfaceControl->isValid());
81
82 Transaction t;
83 t.setDisplayLayerStack(mDisplay, 0);
84 ASSERT_EQ(NO_ERROR,
85 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
86 }
87
88 void setupVirtualDisplay() {
89 mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
90 const ssize_t displayWidth = 100;
91 const ssize_t displayHeight = 100;
92
93 // Background surface
94 mVirtualSurfaceControl =
95 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
96 PIXEL_FORMAT_RGBA_8888, 0);
97 ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
98 ASSERT_TRUE(mVirtualSurfaceControl->isValid());
99
100 Transaction t;
101 t.setDisplayLayerStack(mVirtualDisplay, 0);
102 ASSERT_EQ(NO_ERROR,
103 t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
104 .show(mVirtualSurfaceControl)
105 .apply());
106 }
107
108 /**
109 * Sets UID to imitate Graphic's process.
110 */
111 void setGraphicsUID() {
112 seteuid(AID_ROOT);
113 seteuid(AID_GRAPHICS);
114 }
115
116 /**
117 * Sets UID to imitate System's process.
118 */
119 void setSystemUID() {
120 seteuid(AID_ROOT);
121 seteuid(AID_SYSTEM);
122 }
123
124 /**
125 * Sets UID to imitate a process that doesn't have any special privileges in
126 * our code.
127 */
128 void setBinUID() {
129 seteuid(AID_ROOT);
130 seteuid(AID_BIN);
131 }
132
133 /**
134 * Template function the check a condition for different types of users: root
135 * graphics, system, and non-supported user. Root, graphics, and system should
136 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
137 */
138 template <typename T>
139 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
140 // Check with root.
141 seteuid(AID_ROOT);
142 ASSERT_EQ(privilegedValue, condition());
143
144 // Check as a Graphics user.
145 setGraphicsUID();
146 ASSERT_EQ(privilegedValue, condition());
147
148 // Check as a system user.
149 setSystemUID();
150 ASSERT_EQ(privilegedValue, condition());
151
152 // Check as a non-supported user.
153 setBinUID();
154 ASSERT_EQ(unprivilegedValue, condition());
155 }
156};
157
158TEST_F(CredentialsTest, ClientInitTest) {
159 // Root can init can init the client.
160 ASSERT_NO_FATAL_FAILURE(initClient());
161
162 // Graphics can init the client.
163 setGraphicsUID();
164 ASSERT_NO_FATAL_FAILURE(initClient());
165
166 // System can init the client.
167 setSystemUID();
168 ASSERT_NO_FATAL_FAILURE(initClient());
169
Robert Carrb89ea9d2018-12-10 13:01:14 -0800170 // Anyone else can init the client.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000171 setBinUID();
172 mComposerClient = new SurfaceComposerClient;
Robert Carrb89ea9d2018-12-10 13:01:14 -0800173 ASSERT_NO_FATAL_FAILURE(initClient());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000174}
175
176TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800177 std::function<bool()> condition = [] {
178 return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000179 };
180 // Anyone can access display information.
181 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
182}
183
184TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
185 // The following methods are tested with a UID that is not root, graphics,
186 // or system, to show that anyone can access them.
187 setBinUID();
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800188 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000189 ASSERT_TRUE(display != nullptr);
190
191 DisplayInfo info;
192 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
193
194 Vector<DisplayInfo> configs;
195 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
196
197 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
198
199 ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
200 SurfaceComposerClient::getActiveColorMode(display));
201}
202
203TEST_F(CredentialsTest, GetDisplayColorModesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800204 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000205 std::function<status_t()> condition = [=]() {
206 Vector<ui::ColorMode> outColorModes;
207 return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
208 };
209 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
210}
211
Daniel Solomon42d04562019-01-20 21:03:19 -0800212TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800213 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Daniel Solomon42d04562019-01-20 21:03:19 -0800214 std::function<status_t()> condition = [=]() {
215 ui::DisplayPrimaries primaries;
216 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
217 };
218 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
219}
220
Steven Thomasa87ed452020-01-03 16:10:05 -0800221TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800222 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Steven Thomasa87ed452020-01-03 16:10:05 -0800223 int32_t defaultConfig;
224 float minFps;
225 float maxFps;
226 status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
227 &minFps, &maxFps);
228 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000229 std::function<status_t()> condition = [=]() {
Steven Thomasa87ed452020-01-03 16:10:05 -0800230 return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, minFps,
231 maxFps);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000232 };
233 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
234}
235
236TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800237 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000238 std::function<status_t()> condition = [=]() {
239 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
240 };
241 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
242}
243
Ana Krulec13be8ad2018-08-21 02:43:56 +0000244TEST_F(CredentialsTest, CreateDisplayTest) {
245 std::function<bool()> condition = [=]() {
246 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
247 return testDisplay.get() != nullptr;
248 };
249 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
250
251 condition = [=]() {
252 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
253 return testDisplay.get() != nullptr;
254 };
255 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
256}
257
258TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
259 setupVirtualDisplay();
260
261 DisplayInfo info;
262 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
263 SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
264 // This test currently fails. TODO(b/112002626): Find a way to properly create
265 // a display in the test environment, so that destroy display can remove it.
266 ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
267}
268
269TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800270 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000271 std::function<status_t()> condition = [=]() {
272 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700273 return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
274 ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
Dominik Laskowski718f9602019-11-09 20:01:35 -0800275 0 /*reqHeight*/, false, ui::ROTATION_0, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000276 };
277 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
278}
279
280TEST_F(CredentialsTest, CaptureLayersTest) {
281 setupBackgroundSurface();
282 sp<GraphicBuffer> outBuffer;
283 std::function<status_t()> condition = [=]() {
284 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700285 return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
286 ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
Vishnu Nairefc42e22019-12-03 17:36:12 -0800287 Rect(0, 0, 1, 1), FRAME_SCALE, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000288 };
289 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
290}
291
292/**
293 * The following tests are for methods accessible directly through SurfaceFlinger.
294 */
295
296/**
297 * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
298 * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
299 * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
300 * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
301 * the consumer of a buffer queue is SurfaceFlinger.
302 */
303TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
304 setupBackgroundSurface();
305 sp<IGraphicBufferProducer> producer =
306 mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
307 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
308
309 std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
310 // Anyone should be able to check if the consumer of the buffer queue is SF.
311 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
312}
313
314TEST_F(CredentialsTest, GetLayerDebugInfo) {
315 setupBackgroundSurface();
316 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
317
318 // Historically, only root and shell can access the getLayerDebugInfo which
319 // is called when we call dumpsys. I don't see a reason why we should change this.
320 std::vector<LayerDebugInfo> outLayers;
321 // Check with root.
322 seteuid(AID_ROOT);
323 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
324
325 // Check as a shell.
326 seteuid(AID_SHELL);
327 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
328
329 // Check as anyone else.
330 seteuid(AID_ROOT);
331 seteuid(AID_BIN);
332 ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
333}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800334
335TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800336 const auto display = SurfaceComposerClient::getInternalDisplayToken();
337 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800338 bool result = false;
339 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
340 ASSERT_EQ(NO_ERROR, error);
341 bool hasWideColorMode = false;
342 Vector<ColorMode> colorModes;
343 SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
344 for (ColorMode colorMode : colorModes) {
345 switch (colorMode) {
346 case ColorMode::DISPLAY_P3:
347 case ColorMode::ADOBE_RGB:
348 case ColorMode::DCI_P3:
349 hasWideColorMode = true;
350 break;
351 default:
352 break;
353 }
354 }
355 ASSERT_EQ(hasWideColorMode, result);
356}
357
358TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800359 const auto display = SurfaceComposerClient::getInternalDisplayToken();
360 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800361 std::function<status_t()> condition = [=]() {
362 bool result = false;
363 return SurfaceComposerClient::isWideColorDisplay(display, &result);
364 };
365 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
366}
367
Peiyong Lind1fedb42019-03-11 17:48:41 -0700368TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
369 const auto display = SurfaceComposerClient::getInternalDisplayToken();
370 ASSERT_FALSE(display == nullptr);
371 ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
372 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
373}
374
Ana Krulec13be8ad2018-08-21 02:43:56 +0000375} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800376
377// TODO(b/129481165): remove the #pragma below and fix conversion issues
378#pragma clang diagnostic pop // ignored "-Wconversion"