blob: 10a517e2e4cd7096eaf581878d492f7a895bb4ba [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 +000021} // namespace
22
23/**
24 * This class tests the CheckCredentials method in SurfaceFlinger.
25 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
26 * return anything meaningful.
27 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080028
29// TODO(b/129481165): remove the #pragma below and fix conversion issues
30#pragma clang diagnostic push
31#pragma clang diagnostic ignored "-Wconversion"
Ana Krulec13be8ad2018-08-21 02:43:56 +000032class CredentialsTest : public ::testing::Test {
33protected:
34 void SetUp() override {
35 // Start the tests as root.
36 seteuid(AID_ROOT);
37
38 ASSERT_NO_FATAL_FAILURE(initClient());
39 }
40
41 void TearDown() override {
42 mComposerClient->dispose();
43 mBGSurfaceControl.clear();
44 mComposerClient.clear();
45 // Finish the tests as root.
46 seteuid(AID_ROOT);
47 }
48
49 sp<IBinder> mDisplay;
50 sp<IBinder> mVirtualDisplay;
51 sp<SurfaceComposerClient> mComposerClient;
52 sp<SurfaceControl> mBGSurfaceControl;
53 sp<SurfaceControl> mVirtualSurfaceControl;
54
55 void initClient() {
56 mComposerClient = new SurfaceComposerClient;
57 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
58 }
59
60 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080061 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
62 ASSERT_FALSE(mDisplay == nullptr);
63
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080064 DisplayConfig config;
65 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config));
Ana Krulec13be8ad2018-08-21 02:43:56 +000066
67 // Background surface
68 mBGSurfaceControl =
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080069 mComposerClient->createSurface(SURFACE_NAME, config.resolution.getWidth(),
70 config.resolution.getHeight(),
Ana Krulec13be8ad2018-08-21 02:43:56 +000071 PIXEL_FORMAT_RGBA_8888, 0);
72 ASSERT_TRUE(mBGSurfaceControl != nullptr);
73 ASSERT_TRUE(mBGSurfaceControl->isValid());
74
75 Transaction t;
76 t.setDisplayLayerStack(mDisplay, 0);
77 ASSERT_EQ(NO_ERROR,
78 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
79 }
80
81 void setupVirtualDisplay() {
82 mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
83 const ssize_t displayWidth = 100;
84 const ssize_t displayHeight = 100;
85
86 // Background surface
87 mVirtualSurfaceControl =
88 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
89 PIXEL_FORMAT_RGBA_8888, 0);
90 ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
91 ASSERT_TRUE(mVirtualSurfaceControl->isValid());
92
93 Transaction t;
94 t.setDisplayLayerStack(mVirtualDisplay, 0);
95 ASSERT_EQ(NO_ERROR,
96 t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
97 .show(mVirtualSurfaceControl)
98 .apply());
99 }
100
101 /**
102 * Sets UID to imitate Graphic's process.
103 */
104 void setGraphicsUID() {
105 seteuid(AID_ROOT);
106 seteuid(AID_GRAPHICS);
107 }
108
109 /**
110 * Sets UID to imitate System's process.
111 */
112 void setSystemUID() {
113 seteuid(AID_ROOT);
114 seteuid(AID_SYSTEM);
115 }
116
117 /**
118 * Sets UID to imitate a process that doesn't have any special privileges in
119 * our code.
120 */
121 void setBinUID() {
122 seteuid(AID_ROOT);
123 seteuid(AID_BIN);
124 }
125
126 /**
127 * Template function the check a condition for different types of users: root
128 * graphics, system, and non-supported user. Root, graphics, and system should
129 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
130 */
131 template <typename T>
132 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
133 // Check with root.
134 seteuid(AID_ROOT);
135 ASSERT_EQ(privilegedValue, condition());
136
137 // Check as a Graphics user.
138 setGraphicsUID();
139 ASSERT_EQ(privilegedValue, condition());
140
141 // Check as a system user.
142 setSystemUID();
143 ASSERT_EQ(privilegedValue, condition());
144
145 // Check as a non-supported user.
146 setBinUID();
147 ASSERT_EQ(unprivilegedValue, condition());
148 }
149};
150
151TEST_F(CredentialsTest, ClientInitTest) {
152 // Root can init can init the client.
153 ASSERT_NO_FATAL_FAILURE(initClient());
154
155 // Graphics can init the client.
156 setGraphicsUID();
157 ASSERT_NO_FATAL_FAILURE(initClient());
158
159 // System can init the client.
160 setSystemUID();
161 ASSERT_NO_FATAL_FAILURE(initClient());
162
Robert Carrb89ea9d2018-12-10 13:01:14 -0800163 // Anyone else can init the client.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000164 setBinUID();
165 mComposerClient = new SurfaceComposerClient;
Robert Carrb89ea9d2018-12-10 13:01:14 -0800166 ASSERT_NO_FATAL_FAILURE(initClient());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000167}
168
169TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800170 std::function<bool()> condition = [] {
171 return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000172 };
173 // Anyone can access display information.
174 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
175}
176
177TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
178 // The following methods are tested with a UID that is not root, graphics,
179 // or system, to show that anyone can access them.
180 setBinUID();
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800181 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000182 ASSERT_TRUE(display != nullptr);
183
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800184 DisplayConfig config;
185 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000186
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800187 Vector<DisplayConfig> configs;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000188 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
189
190 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
191
192 ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
193 SurfaceComposerClient::getActiveColorMode(display));
194}
195
196TEST_F(CredentialsTest, GetDisplayColorModesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800197 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000198 std::function<status_t()> condition = [=]() {
199 Vector<ui::ColorMode> outColorModes;
200 return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
201 };
202 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
203}
204
Daniel Solomon42d04562019-01-20 21:03:19 -0800205TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800206 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Daniel Solomon42d04562019-01-20 21:03:19 -0800207 std::function<status_t()> condition = [=]() {
208 ui::DisplayPrimaries primaries;
209 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
210 };
211 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
212}
213
Steven Thomasa87ed452020-01-03 16:10:05 -0800214TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800215 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Steven Thomasa87ed452020-01-03 16:10:05 -0800216 int32_t defaultConfig;
Steven Thomasf734df42020-04-13 21:09:28 -0700217 float primaryFpsMin;
218 float primaryFpsMax;
219 float appRequestFpsMin;
220 float appRequestFpsMax;
221 status_t res =
222 SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
223 &primaryFpsMin, &primaryFpsMax,
224 &appRequestFpsMin,
225 &appRequestFpsMax);
Steven Thomasa87ed452020-01-03 16:10:05 -0800226 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000227 std::function<status_t()> condition = [=]() {
Steven Thomasf734df42020-04-13 21:09:28 -0700228 return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig,
229 primaryFpsMin, primaryFpsMax,
230 appRequestFpsMin,
231 appRequestFpsMax);
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
Ana Krulec13be8ad2018-08-21 02:43:56 +0000258TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800259 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000260 std::function<status_t()> condition = [=]() {
261 sp<GraphicBuffer> outBuffer;
chaviw690db382020-07-27 16:46:46 -0700262 DisplayCaptureArgs captureArgs;
263 captureArgs.displayToken = display;
264 ScreenCaptureResults captureResults;
265 return ScreenshotClient::captureDisplay(captureArgs, captureResults);
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 = [=]() {
chaviw26c52482020-07-28 16:25:52 -0700274 LayerCaptureArgs captureArgs;
275 captureArgs.layerHandle = mBGSurfaceControl->getHandle();
276 captureArgs.sourceCrop = {0, 0, 1, 1};
277
278 ScreenCaptureResults captureResults;
279 return ScreenshotClient::captureLayers(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000280 };
281 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
282}
283
284/**
285 * The following tests are for methods accessible directly through SurfaceFlinger.
286 */
287
288/**
289 * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
290 * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
291 * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
292 * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
293 * the consumer of a buffer queue is SurfaceFlinger.
294 */
295TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
296 setupBackgroundSurface();
297 sp<IGraphicBufferProducer> producer =
298 mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
299 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
300
301 std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
302 // Anyone should be able to check if the consumer of the buffer queue is SF.
303 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
304}
305
306TEST_F(CredentialsTest, GetLayerDebugInfo) {
307 setupBackgroundSurface();
308 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
309
310 // Historically, only root and shell can access the getLayerDebugInfo which
311 // is called when we call dumpsys. I don't see a reason why we should change this.
312 std::vector<LayerDebugInfo> outLayers;
313 // Check with root.
314 seteuid(AID_ROOT);
315 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
316
317 // Check as a shell.
318 seteuid(AID_SHELL);
319 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
320
321 // Check as anyone else.
322 seteuid(AID_ROOT);
323 seteuid(AID_BIN);
324 ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
325}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800326
327TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800328 const auto display = SurfaceComposerClient::getInternalDisplayToken();
329 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800330 bool result = false;
331 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
332 ASSERT_EQ(NO_ERROR, error);
333 bool hasWideColorMode = false;
334 Vector<ColorMode> colorModes;
335 SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
336 for (ColorMode colorMode : colorModes) {
337 switch (colorMode) {
338 case ColorMode::DISPLAY_P3:
339 case ColorMode::ADOBE_RGB:
340 case ColorMode::DCI_P3:
341 hasWideColorMode = true;
342 break;
343 default:
344 break;
345 }
346 }
347 ASSERT_EQ(hasWideColorMode, result);
348}
349
350TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800351 const auto display = SurfaceComposerClient::getInternalDisplayToken();
352 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800353 std::function<status_t()> condition = [=]() {
354 bool result = false;
355 return SurfaceComposerClient::isWideColorDisplay(display, &result);
356 };
357 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
358}
359
Peiyong Lind1fedb42019-03-11 17:48:41 -0700360TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
361 const auto display = SurfaceComposerClient::getInternalDisplayToken();
362 ASSERT_FALSE(display == nullptr);
363 ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
364 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
365}
366
Ana Krulec13be8ad2018-08-21 02:43:56 +0000367} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800368
369// TODO(b/129481165): remove the #pragma below and fix conversion issues
370#pragma clang diagnostic pop // ignored "-Wconversion"