blob: c136708ff0cb0ec6c36faf16ba7331763eaf48d7 [file] [log] [blame]
Ana Krulec13be8ad2018-08-21 02:43:56 +00001#include <gtest/gtest.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +00002#include <gui/ISurfaceComposer.h>
3#include <gui/LayerDebugInfo.h>
4#include <gui/Surface.h>
5#include <gui/SurfaceComposerClient.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +00006#include <private/android_filesystem_config.h>
7#include <private/gui/ComposerService.h>
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -08008#include <ui/DisplayConfig.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +00009#include <utils/String8.h>
10
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080011#include <functional>
12
Ana Krulec13be8ad2018-08-21 02:43:56 +000013namespace android {
14
15using Transaction = SurfaceComposerClient::Transaction;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -080016using ui::ColorMode;
Ana Krulec13be8ad2018-08-21 02:43:56 +000017
18namespace {
19const String8 DISPLAY_NAME("Credentials Display Test");
20const String8 SURFACE_NAME("Test Surface Name");
Ana Krulec13be8ad2018-08-21 02:43:56 +000021const float FRAME_SCALE = 1.0f;
22} // namespace
23
24/**
25 * This class tests the CheckCredentials method in SurfaceFlinger.
26 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
27 * return anything meaningful.
28 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080029
30// TODO(b/129481165): remove the #pragma below and fix conversion issues
31#pragma clang diagnostic push
32#pragma clang diagnostic ignored "-Wconversion"
Ana Krulec13be8ad2018-08-21 02:43:56 +000033class CredentialsTest : public ::testing::Test {
34protected:
35 void SetUp() override {
36 // Start the tests as root.
37 seteuid(AID_ROOT);
38
39 ASSERT_NO_FATAL_FAILURE(initClient());
40 }
41
42 void TearDown() override {
43 mComposerClient->dispose();
44 mBGSurfaceControl.clear();
45 mComposerClient.clear();
46 // Finish the tests as root.
47 seteuid(AID_ROOT);
48 }
49
50 sp<IBinder> mDisplay;
51 sp<IBinder> mVirtualDisplay;
52 sp<SurfaceComposerClient> mComposerClient;
53 sp<SurfaceControl> mBGSurfaceControl;
54 sp<SurfaceControl> mVirtualSurfaceControl;
55
56 void initClient() {
57 mComposerClient = new SurfaceComposerClient;
58 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
59 }
60
61 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080062 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
63 ASSERT_FALSE(mDisplay == nullptr);
64
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080065 DisplayConfig config;
66 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config));
Ana Krulec13be8ad2018-08-21 02:43:56 +000067
68 // Background surface
69 mBGSurfaceControl =
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080070 mComposerClient->createSurface(SURFACE_NAME, config.resolution.getWidth(),
71 config.resolution.getHeight(),
Ana Krulec13be8ad2018-08-21 02:43:56 +000072 PIXEL_FORMAT_RGBA_8888, 0);
73 ASSERT_TRUE(mBGSurfaceControl != nullptr);
74 ASSERT_TRUE(mBGSurfaceControl->isValid());
75
76 Transaction t;
77 t.setDisplayLayerStack(mDisplay, 0);
78 ASSERT_EQ(NO_ERROR,
79 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
80 }
81
82 void setupVirtualDisplay() {
83 mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
84 const ssize_t displayWidth = 100;
85 const ssize_t displayHeight = 100;
86
87 // Background surface
88 mVirtualSurfaceControl =
89 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
90 PIXEL_FORMAT_RGBA_8888, 0);
91 ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
92 ASSERT_TRUE(mVirtualSurfaceControl->isValid());
93
94 Transaction t;
95 t.setDisplayLayerStack(mVirtualDisplay, 0);
96 ASSERT_EQ(NO_ERROR,
97 t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
98 .show(mVirtualSurfaceControl)
99 .apply());
100 }
101
102 /**
103 * Sets UID to imitate Graphic's process.
104 */
105 void setGraphicsUID() {
106 seteuid(AID_ROOT);
107 seteuid(AID_GRAPHICS);
108 }
109
110 /**
111 * Sets UID to imitate System's process.
112 */
113 void setSystemUID() {
114 seteuid(AID_ROOT);
115 seteuid(AID_SYSTEM);
116 }
117
118 /**
119 * Sets UID to imitate a process that doesn't have any special privileges in
120 * our code.
121 */
122 void setBinUID() {
123 seteuid(AID_ROOT);
124 seteuid(AID_BIN);
125 }
126
127 /**
128 * Template function the check a condition for different types of users: root
129 * graphics, system, and non-supported user. Root, graphics, and system should
130 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
131 */
132 template <typename T>
133 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
134 // Check with root.
135 seteuid(AID_ROOT);
136 ASSERT_EQ(privilegedValue, condition());
137
138 // Check as a Graphics user.
139 setGraphicsUID();
140 ASSERT_EQ(privilegedValue, condition());
141
142 // Check as a system user.
143 setSystemUID();
144 ASSERT_EQ(privilegedValue, condition());
145
146 // Check as a non-supported user.
147 setBinUID();
148 ASSERT_EQ(unprivilegedValue, condition());
149 }
150};
151
152TEST_F(CredentialsTest, ClientInitTest) {
153 // Root can init can init the client.
154 ASSERT_NO_FATAL_FAILURE(initClient());
155
156 // Graphics can init the client.
157 setGraphicsUID();
158 ASSERT_NO_FATAL_FAILURE(initClient());
159
160 // System can init the client.
161 setSystemUID();
162 ASSERT_NO_FATAL_FAILURE(initClient());
163
Robert Carrb89ea9d2018-12-10 13:01:14 -0800164 // Anyone else can init the client.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000165 setBinUID();
166 mComposerClient = new SurfaceComposerClient;
Robert Carrb89ea9d2018-12-10 13:01:14 -0800167 ASSERT_NO_FATAL_FAILURE(initClient());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000168}
169
170TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800171 std::function<bool()> condition = [] {
172 return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000173 };
174 // Anyone can access display information.
175 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
176}
177
178TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
179 // The following methods are tested with a UID that is not root, graphics,
180 // or system, to show that anyone can access them.
181 setBinUID();
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800182 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000183 ASSERT_TRUE(display != nullptr);
184
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800185 DisplayConfig config;
186 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000187
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800188 Vector<DisplayConfig> configs;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000189 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
190
191 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
192
193 ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
194 SurfaceComposerClient::getActiveColorMode(display));
195}
196
197TEST_F(CredentialsTest, GetDisplayColorModesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800198 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000199 std::function<status_t()> condition = [=]() {
200 Vector<ui::ColorMode> outColorModes;
201 return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
202 };
203 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
204}
205
Daniel Solomon42d04562019-01-20 21:03:19 -0800206TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800207 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Daniel Solomon42d04562019-01-20 21:03:19 -0800208 std::function<status_t()> condition = [=]() {
209 ui::DisplayPrimaries primaries;
210 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
211 };
212 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
213}
214
Steven Thomasa87ed452020-01-03 16:10:05 -0800215TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800216 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Steven Thomasa87ed452020-01-03 16:10:05 -0800217 int32_t defaultConfig;
Steven Thomasf734df42020-04-13 21:09:28 -0700218 float primaryFpsMin;
219 float primaryFpsMax;
220 float appRequestFpsMin;
221 float appRequestFpsMax;
222 status_t res =
223 SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
224 &primaryFpsMin, &primaryFpsMax,
225 &appRequestFpsMin,
226 &appRequestFpsMax);
Steven Thomasa87ed452020-01-03 16:10:05 -0800227 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000228 std::function<status_t()> condition = [=]() {
Steven Thomasf734df42020-04-13 21:09:28 -0700229 return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig,
230 primaryFpsMin, primaryFpsMax,
231 appRequestFpsMin,
232 appRequestFpsMax);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000233 };
234 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
235}
236
237TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800238 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000239 std::function<status_t()> condition = [=]() {
240 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
241 };
242 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
243}
244
Ana Krulec13be8ad2018-08-21 02:43:56 +0000245TEST_F(CredentialsTest, CreateDisplayTest) {
246 std::function<bool()> condition = [=]() {
247 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
248 return testDisplay.get() != nullptr;
249 };
250 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
251
252 condition = [=]() {
253 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
254 return testDisplay.get() != nullptr;
255 };
256 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
257}
258
Ana Krulec13be8ad2018-08-21 02:43:56 +0000259TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800260 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000261 std::function<status_t()> condition = [=]() {
262 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700263 return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
264 ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
Dominik Laskowski718f9602019-11-09 20:01:35 -0800265 0 /*reqHeight*/, false, ui::ROTATION_0, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000266 };
267 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
268}
269
270TEST_F(CredentialsTest, CaptureLayersTest) {
271 setupBackgroundSurface();
272 sp<GraphicBuffer> outBuffer;
273 std::function<status_t()> condition = [=]() {
274 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700275 return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
276 ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
Vishnu Nairefc42e22019-12-03 17:36:12 -0800277 Rect(0, 0, 1, 1), FRAME_SCALE, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000278 };
279 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
280}
281
282/**
283 * The following tests are for methods accessible directly through SurfaceFlinger.
284 */
285
286/**
287 * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
288 * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
289 * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
290 * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
291 * the consumer of a buffer queue is SurfaceFlinger.
292 */
293TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
294 setupBackgroundSurface();
295 sp<IGraphicBufferProducer> producer =
296 mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
297 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
298
299 std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
300 // Anyone should be able to check if the consumer of the buffer queue is SF.
301 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
302}
303
304TEST_F(CredentialsTest, GetLayerDebugInfo) {
305 setupBackgroundSurface();
306 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
307
308 // Historically, only root and shell can access the getLayerDebugInfo which
309 // is called when we call dumpsys. I don't see a reason why we should change this.
310 std::vector<LayerDebugInfo> outLayers;
311 // Check with root.
312 seteuid(AID_ROOT);
313 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
314
315 // Check as a shell.
316 seteuid(AID_SHELL);
317 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
318
319 // Check as anyone else.
320 seteuid(AID_ROOT);
321 seteuid(AID_BIN);
322 ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
323}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800324
325TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800326 const auto display = SurfaceComposerClient::getInternalDisplayToken();
327 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800328 bool result = false;
329 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
330 ASSERT_EQ(NO_ERROR, error);
331 bool hasWideColorMode = false;
332 Vector<ColorMode> colorModes;
333 SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
334 for (ColorMode colorMode : colorModes) {
335 switch (colorMode) {
336 case ColorMode::DISPLAY_P3:
337 case ColorMode::ADOBE_RGB:
338 case ColorMode::DCI_P3:
339 hasWideColorMode = true;
340 break;
341 default:
342 break;
343 }
344 }
345 ASSERT_EQ(hasWideColorMode, result);
346}
347
348TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800349 const auto display = SurfaceComposerClient::getInternalDisplayToken();
350 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800351 std::function<status_t()> condition = [=]() {
352 bool result = false;
353 return SurfaceComposerClient::isWideColorDisplay(display, &result);
354 };
355 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
356}
357
Peiyong Lind1fedb42019-03-11 17:48:41 -0700358TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
359 const auto display = SurfaceComposerClient::getInternalDisplayToken();
360 ASSERT_FALSE(display == nullptr);
361 ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
362 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
363}
364
Ana Krulec13be8ad2018-08-21 02:43:56 +0000365} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800366
367// TODO(b/129481165): remove the #pragma below and fix conversion issues
368#pragma clang diagnostic pop // ignored "-Wconversion"