blob: b667a74db0de8cdd485611ce00f0357468cbd465 [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 uint32_t ROTATION = 0;
27const float FRAME_SCALE = 1.0f;
28} // namespace
29
30/**
31 * This class tests the CheckCredentials method in SurfaceFlinger.
32 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
33 * return anything meaningful.
34 */
35class CredentialsTest : public ::testing::Test {
36protected:
37 void SetUp() override {
38 // Start the tests as root.
39 seteuid(AID_ROOT);
40
41 ASSERT_NO_FATAL_FAILURE(initClient());
42 }
43
44 void TearDown() override {
45 mComposerClient->dispose();
46 mBGSurfaceControl.clear();
47 mComposerClient.clear();
48 // Finish the tests as root.
49 seteuid(AID_ROOT);
50 }
51
52 sp<IBinder> mDisplay;
53 sp<IBinder> mVirtualDisplay;
54 sp<SurfaceComposerClient> mComposerClient;
55 sp<SurfaceControl> mBGSurfaceControl;
56 sp<SurfaceControl> mVirtualSurfaceControl;
57
58 void initClient() {
59 mComposerClient = new SurfaceComposerClient;
60 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
61 }
62
63 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080064 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
65 ASSERT_FALSE(mDisplay == nullptr);
66
Ana Krulec13be8ad2018-08-21 02:43:56 +000067 DisplayInfo info;
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080068 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
Ana Krulec13be8ad2018-08-21 02:43:56 +000069 const ssize_t displayWidth = info.w;
70 const ssize_t displayHeight = info.h;
71
72 // Background surface
73 mBGSurfaceControl =
74 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
75 PIXEL_FORMAT_RGBA_8888, 0);
76 ASSERT_TRUE(mBGSurfaceControl != nullptr);
77 ASSERT_TRUE(mBGSurfaceControl->isValid());
78
79 Transaction t;
80 t.setDisplayLayerStack(mDisplay, 0);
81 ASSERT_EQ(NO_ERROR,
82 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
83 }
84
85 void setupVirtualDisplay() {
86 mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
87 const ssize_t displayWidth = 100;
88 const ssize_t displayHeight = 100;
89
90 // Background surface
91 mVirtualSurfaceControl =
92 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
93 PIXEL_FORMAT_RGBA_8888, 0);
94 ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
95 ASSERT_TRUE(mVirtualSurfaceControl->isValid());
96
97 Transaction t;
98 t.setDisplayLayerStack(mVirtualDisplay, 0);
99 ASSERT_EQ(NO_ERROR,
100 t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
101 .show(mVirtualSurfaceControl)
102 .apply());
103 }
104
105 /**
106 * Sets UID to imitate Graphic's process.
107 */
108 void setGraphicsUID() {
109 seteuid(AID_ROOT);
110 seteuid(AID_GRAPHICS);
111 }
112
113 /**
114 * Sets UID to imitate System's process.
115 */
116 void setSystemUID() {
117 seteuid(AID_ROOT);
118 seteuid(AID_SYSTEM);
119 }
120
121 /**
122 * Sets UID to imitate a process that doesn't have any special privileges in
123 * our code.
124 */
125 void setBinUID() {
126 seteuid(AID_ROOT);
127 seteuid(AID_BIN);
128 }
129
130 /**
131 * Template function the check a condition for different types of users: root
132 * graphics, system, and non-supported user. Root, graphics, and system should
133 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
134 */
135 template <typename T>
136 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
137 // Check with root.
138 seteuid(AID_ROOT);
139 ASSERT_EQ(privilegedValue, condition());
140
141 // Check as a Graphics user.
142 setGraphicsUID();
143 ASSERT_EQ(privilegedValue, condition());
144
145 // Check as a system user.
146 setSystemUID();
147 ASSERT_EQ(privilegedValue, condition());
148
149 // Check as a non-supported user.
150 setBinUID();
151 ASSERT_EQ(unprivilegedValue, condition());
152 }
153};
154
155TEST_F(CredentialsTest, ClientInitTest) {
156 // Root can init can init the client.
157 ASSERT_NO_FATAL_FAILURE(initClient());
158
159 // Graphics can init the client.
160 setGraphicsUID();
161 ASSERT_NO_FATAL_FAILURE(initClient());
162
163 // System can init the client.
164 setSystemUID();
165 ASSERT_NO_FATAL_FAILURE(initClient());
166
Robert Carrb89ea9d2018-12-10 13:01:14 -0800167 // Anyone else can init the client.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000168 setBinUID();
169 mComposerClient = new SurfaceComposerClient;
Robert Carrb89ea9d2018-12-10 13:01:14 -0800170 ASSERT_NO_FATAL_FAILURE(initClient());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000171}
172
173TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800174 std::function<bool()> condition = [] {
175 return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000176 };
177 // Anyone can access display information.
178 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
179}
180
181TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
182 // The following methods are tested with a UID that is not root, graphics,
183 // or system, to show that anyone can access them.
184 setBinUID();
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800185 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000186 ASSERT_TRUE(display != nullptr);
187
188 DisplayInfo info;
189 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
190
191 Vector<DisplayInfo> configs;
192 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
193
194 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
195
196 ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
197 SurfaceComposerClient::getActiveColorMode(display));
198}
199
200TEST_F(CredentialsTest, GetDisplayColorModesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800201 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000202 std::function<status_t()> condition = [=]() {
203 Vector<ui::ColorMode> outColorModes;
204 return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
205 };
206 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
207}
208
Daniel Solomon42d04562019-01-20 21:03:19 -0800209TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800210 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Daniel Solomon42d04562019-01-20 21:03:19 -0800211 std::function<status_t()> condition = [=]() {
212 ui::DisplayPrimaries primaries;
213 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
214 };
215 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
216}
217
Ana Krulec13be8ad2018-08-21 02:43:56 +0000218TEST_F(CredentialsTest, SetActiveConfigTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800219 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000220 std::function<status_t()> condition = [=]() {
221 return SurfaceComposerClient::setActiveConfig(display, 0);
222 };
223 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
224}
225
226TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800227 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000228 std::function<status_t()> condition = [=]() {
229 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
230 };
231 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
232}
233
Ana Krulec13be8ad2018-08-21 02:43:56 +0000234TEST_F(CredentialsTest, CreateDisplayTest) {
235 std::function<bool()> condition = [=]() {
236 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
237 return testDisplay.get() != nullptr;
238 };
239 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
240
241 condition = [=]() {
242 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
243 return testDisplay.get() != nullptr;
244 };
245 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
246}
247
248TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
249 setupVirtualDisplay();
250
251 DisplayInfo info;
252 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
253 SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
254 // This test currently fails. TODO(b/112002626): Find a way to properly create
255 // a display in the test environment, so that destroy display can remove it.
256 ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
257}
258
259TEST_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*/,
265 0 /*reqHeight*/, false, ROTATION, &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,
277 Rect(), 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