blob: 61d09daed2015378c9ef44c10fdbe1fa0b305930 [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>
15
16#include <ui/DisplayInfo.h>
17#include <utils/String8.h>
18
19namespace android {
20
21using Transaction = SurfaceComposerClient::Transaction;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -080022using ui::ColorMode;
Ana Krulec13be8ad2018-08-21 02:43:56 +000023
24namespace {
25const String8 DISPLAY_NAME("Credentials Display Test");
26const String8 SURFACE_NAME("Test Surface Name");
Ana Krulec13be8ad2018-08-21 02:43:56 +000027const uint32_t ROTATION = 0;
28const float FRAME_SCALE = 1.0f;
29} // namespace
30
31/**
32 * This class tests the CheckCredentials method in SurfaceFlinger.
33 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
34 * return anything meaningful.
35 */
36class CredentialsTest : public ::testing::Test {
37protected:
38 void SetUp() override {
39 // Start the tests as root.
40 seteuid(AID_ROOT);
41
42 ASSERT_NO_FATAL_FAILURE(initClient());
43 }
44
45 void TearDown() override {
46 mComposerClient->dispose();
47 mBGSurfaceControl.clear();
48 mComposerClient.clear();
49 // Finish the tests as root.
50 seteuid(AID_ROOT);
51 }
52
53 sp<IBinder> mDisplay;
54 sp<IBinder> mVirtualDisplay;
55 sp<SurfaceComposerClient> mComposerClient;
56 sp<SurfaceControl> mBGSurfaceControl;
57 sp<SurfaceControl> mVirtualSurfaceControl;
58
59 void initClient() {
60 mComposerClient = new SurfaceComposerClient;
61 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
62 }
63
64 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080065 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
66 ASSERT_FALSE(mDisplay == nullptr);
67
Ana Krulec13be8ad2018-08-21 02:43:56 +000068 DisplayInfo info;
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080069 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
Ana Krulec13be8ad2018-08-21 02:43:56 +000070 const ssize_t displayWidth = info.w;
71 const ssize_t displayHeight = info.h;
72
73 // Background surface
74 mBGSurfaceControl =
75 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
76 PIXEL_FORMAT_RGBA_8888, 0);
77 ASSERT_TRUE(mBGSurfaceControl != nullptr);
78 ASSERT_TRUE(mBGSurfaceControl->isValid());
79
80 Transaction t;
81 t.setDisplayLayerStack(mDisplay, 0);
82 ASSERT_EQ(NO_ERROR,
83 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
84 }
85
86 void setupVirtualDisplay() {
87 mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
88 const ssize_t displayWidth = 100;
89 const ssize_t displayHeight = 100;
90
91 // Background surface
92 mVirtualSurfaceControl =
93 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
94 PIXEL_FORMAT_RGBA_8888, 0);
95 ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
96 ASSERT_TRUE(mVirtualSurfaceControl->isValid());
97
98 Transaction t;
99 t.setDisplayLayerStack(mVirtualDisplay, 0);
100 ASSERT_EQ(NO_ERROR,
101 t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
102 .show(mVirtualSurfaceControl)
103 .apply());
104 }
105
106 /**
107 * Sets UID to imitate Graphic's process.
108 */
109 void setGraphicsUID() {
110 seteuid(AID_ROOT);
111 seteuid(AID_GRAPHICS);
112 }
113
114 /**
115 * Sets UID to imitate System's process.
116 */
117 void setSystemUID() {
118 seteuid(AID_ROOT);
119 seteuid(AID_SYSTEM);
120 }
121
122 /**
123 * Sets UID to imitate a process that doesn't have any special privileges in
124 * our code.
125 */
126 void setBinUID() {
127 seteuid(AID_ROOT);
128 seteuid(AID_BIN);
129 }
130
131 /**
132 * Template function the check a condition for different types of users: root
133 * graphics, system, and non-supported user. Root, graphics, and system should
134 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
135 */
136 template <typename T>
137 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
138 // Check with root.
139 seteuid(AID_ROOT);
140 ASSERT_EQ(privilegedValue, condition());
141
142 // Check as a Graphics user.
143 setGraphicsUID();
144 ASSERT_EQ(privilegedValue, condition());
145
146 // Check as a system user.
147 setSystemUID();
148 ASSERT_EQ(privilegedValue, condition());
149
150 // Check as a non-supported user.
151 setBinUID();
152 ASSERT_EQ(unprivilegedValue, condition());
153 }
154};
155
156TEST_F(CredentialsTest, ClientInitTest) {
157 // Root can init can init the client.
158 ASSERT_NO_FATAL_FAILURE(initClient());
159
160 // Graphics can init the client.
161 setGraphicsUID();
162 ASSERT_NO_FATAL_FAILURE(initClient());
163
164 // System can init the client.
165 setSystemUID();
166 ASSERT_NO_FATAL_FAILURE(initClient());
167
Robert Carrb89ea9d2018-12-10 13:01:14 -0800168 // Anyone else can init the client.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000169 setBinUID();
170 mComposerClient = new SurfaceComposerClient;
Robert Carrb89ea9d2018-12-10 13:01:14 -0800171 ASSERT_NO_FATAL_FAILURE(initClient());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000172}
173
174TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800175 std::function<bool()> condition = [] {
176 return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000177 };
178 // Anyone can access display information.
179 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
180}
181
182TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
183 // The following methods are tested with a UID that is not root, graphics,
184 // or system, to show that anyone can access them.
185 setBinUID();
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800186 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000187 ASSERT_TRUE(display != nullptr);
188
189 DisplayInfo info;
190 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
191
192 Vector<DisplayInfo> configs;
193 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
194
195 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
196
197 ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
198 SurfaceComposerClient::getActiveColorMode(display));
199}
200
201TEST_F(CredentialsTest, GetDisplayColorModesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800202 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000203 std::function<status_t()> condition = [=]() {
204 Vector<ui::ColorMode> outColorModes;
205 return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
206 };
207 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
208}
209
Daniel Solomon42d04562019-01-20 21:03:19 -0800210TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800211 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Daniel Solomon42d04562019-01-20 21:03:19 -0800212 std::function<status_t()> condition = [=]() {
213 ui::DisplayPrimaries primaries;
214 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
215 };
216 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
217}
218
Ana Krulec13be8ad2018-08-21 02:43:56 +0000219TEST_F(CredentialsTest, SetActiveConfigTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800220 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000221 std::function<status_t()> condition = [=]() {
222 return SurfaceComposerClient::setActiveConfig(display, 0);
223 };
224 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
225}
226
227TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800228 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000229 std::function<status_t()> condition = [=]() {
230 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
231 };
232 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
233}
234
Ana Krulec13be8ad2018-08-21 02:43:56 +0000235TEST_F(CredentialsTest, CreateDisplayTest) {
236 std::function<bool()> condition = [=]() {
237 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
238 return testDisplay.get() != nullptr;
239 };
240 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
241
242 condition = [=]() {
243 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
244 return testDisplay.get() != nullptr;
245 };
246 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
247}
248
249TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
250 setupVirtualDisplay();
251
252 DisplayInfo info;
253 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
254 SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
255 // This test currently fails. TODO(b/112002626): Find a way to properly create
256 // a display in the test environment, so that destroy display can remove it.
257 ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
258}
259
260TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800261 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000262 std::function<status_t()> condition = [=]() {
263 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700264 return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
265 ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
266 0 /*reqHeight*/, false, ROTATION, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000267 };
268 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
269}
270
271TEST_F(CredentialsTest, CaptureLayersTest) {
272 setupBackgroundSurface();
273 sp<GraphicBuffer> outBuffer;
274 std::function<status_t()> condition = [=]() {
275 sp<GraphicBuffer> outBuffer;
Peiyong Lin0e003c92018-09-17 11:09:51 -0700276 return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
277 ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
278 Rect(), FRAME_SCALE, &outBuffer);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000279 };
280 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
281}
282
283/**
284 * The following tests are for methods accessible directly through SurfaceFlinger.
285 */
286
287/**
288 * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
289 * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
290 * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
291 * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
292 * the consumer of a buffer queue is SurfaceFlinger.
293 */
294TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
295 setupBackgroundSurface();
296 sp<IGraphicBufferProducer> producer =
297 mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
298 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
299
300 std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
301 // Anyone should be able to check if the consumer of the buffer queue is SF.
302 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
303}
304
305TEST_F(CredentialsTest, GetLayerDebugInfo) {
306 setupBackgroundSurface();
307 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
308
309 // Historically, only root and shell can access the getLayerDebugInfo which
310 // is called when we call dumpsys. I don't see a reason why we should change this.
311 std::vector<LayerDebugInfo> outLayers;
312 // Check with root.
313 seteuid(AID_ROOT);
314 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
315
316 // Check as a shell.
317 seteuid(AID_SHELL);
318 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
319
320 // Check as anyone else.
321 seteuid(AID_ROOT);
322 seteuid(AID_BIN);
323 ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
324}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800325
326TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800327 const auto display = SurfaceComposerClient::getInternalDisplayToken();
328 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800329 bool result = false;
330 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
331 ASSERT_EQ(NO_ERROR, error);
332 bool hasWideColorMode = false;
333 Vector<ColorMode> colorModes;
334 SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
335 for (ColorMode colorMode : colorModes) {
336 switch (colorMode) {
337 case ColorMode::DISPLAY_P3:
338 case ColorMode::ADOBE_RGB:
339 case ColorMode::DCI_P3:
340 hasWideColorMode = true;
341 break;
342 default:
343 break;
344 }
345 }
346 ASSERT_EQ(hasWideColorMode, result);
347}
348
349TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800350 const auto display = SurfaceComposerClient::getInternalDisplayToken();
351 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800352 std::function<status_t()> condition = [=]() {
353 bool result = false;
354 return SurfaceComposerClient::isWideColorDisplay(display, &result);
355 };
356 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
357}
358
Ana Krulec13be8ad2018-08-21 02:43:56 +0000359} // namespace android