blob: 507d28b14381ac72293c9ba1788512713526f36b [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;
218 float minFps;
219 float maxFps;
220 status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
221 &minFps, &maxFps);
222 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000223 std::function<status_t()> condition = [=]() {
Steven Thomasa87ed452020-01-03 16:10:05 -0800224 return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, minFps,
225 maxFps);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000226 };
227 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
228}
229
230TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800231 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000232 std::function<status_t()> condition = [=]() {
233 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
234 };
235 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
236}
237
Ana Krulec13be8ad2018-08-21 02:43:56 +0000238TEST_F(CredentialsTest, CreateDisplayTest) {
239 std::function<bool()> condition = [=]() {
240 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
241 return testDisplay.get() != nullptr;
242 };
243 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
244
245 condition = [=]() {
246 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
247 return testDisplay.get() != nullptr;
248 };
249 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
250}
251
Ana Krulec13be8ad2018-08-21 02:43:56 +0000252TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800253 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000254 std::function<status_t()> condition = [=]() {
255 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700256 return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
257 ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
Dominik Laskowski718f9602019-11-09 20:01:35 -0800258 0 /*reqHeight*/, false, ui::ROTATION_0, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000259 };
260 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
261}
262
263TEST_F(CredentialsTest, CaptureLayersTest) {
264 setupBackgroundSurface();
265 sp<GraphicBuffer> outBuffer;
266 std::function<status_t()> condition = [=]() {
267 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700268 return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
269 ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
Vishnu Nairefc42e22019-12-03 17:36:12 -0800270 Rect(0, 0, 1, 1), FRAME_SCALE, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000271 };
272 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
273}
274
275/**
276 * The following tests are for methods accessible directly through SurfaceFlinger.
277 */
278
279/**
280 * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
281 * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
282 * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
283 * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
284 * the consumer of a buffer queue is SurfaceFlinger.
285 */
286TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
287 setupBackgroundSurface();
288 sp<IGraphicBufferProducer> producer =
289 mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
290 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
291
292 std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
293 // Anyone should be able to check if the consumer of the buffer queue is SF.
294 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
295}
296
297TEST_F(CredentialsTest, GetLayerDebugInfo) {
298 setupBackgroundSurface();
299 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
300
301 // Historically, only root and shell can access the getLayerDebugInfo which
302 // is called when we call dumpsys. I don't see a reason why we should change this.
303 std::vector<LayerDebugInfo> outLayers;
304 // Check with root.
305 seteuid(AID_ROOT);
306 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
307
308 // Check as a shell.
309 seteuid(AID_SHELL);
310 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
311
312 // Check as anyone else.
313 seteuid(AID_ROOT);
314 seteuid(AID_BIN);
315 ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
316}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800317
318TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800319 const auto display = SurfaceComposerClient::getInternalDisplayToken();
320 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800321 bool result = false;
322 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
323 ASSERT_EQ(NO_ERROR, error);
324 bool hasWideColorMode = false;
325 Vector<ColorMode> colorModes;
326 SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
327 for (ColorMode colorMode : colorModes) {
328 switch (colorMode) {
329 case ColorMode::DISPLAY_P3:
330 case ColorMode::ADOBE_RGB:
331 case ColorMode::DCI_P3:
332 hasWideColorMode = true;
333 break;
334 default:
335 break;
336 }
337 }
338 ASSERT_EQ(hasWideColorMode, result);
339}
340
341TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800342 const auto display = SurfaceComposerClient::getInternalDisplayToken();
343 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800344 std::function<status_t()> condition = [=]() {
345 bool result = false;
346 return SurfaceComposerClient::isWideColorDisplay(display, &result);
347 };
348 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
349}
350
Peiyong Lind1fedb42019-03-11 17:48:41 -0700351TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
352 const auto display = SurfaceComposerClient::getInternalDisplayToken();
353 ASSERT_FALSE(display == nullptr);
354 ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
355 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
356}
357
Ana Krulec13be8ad2018-08-21 02:43:56 +0000358} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800359
360// TODO(b/129481165): remove the #pragma below and fix conversion issues
361#pragma clang diagnostic pop // ignored "-Wconversion"