blob: 9302463190d7a1eb057fe4e85c846b2da9e62fc4 [file] [log] [blame]
chaviw8ffc7b82020-08-18 11:25:37 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Ana Krulec13be8ad2018-08-21 02:43:56 +000021#include <gtest/gtest.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000022#include <gui/ISurfaceComposer.h>
23#include <gui/LayerDebugInfo.h>
24#include <gui/Surface.h>
25#include <gui/SurfaceComposerClient.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000026#include <private/android_filesystem_config.h>
27#include <private/gui/ComposerService.h>
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080028#include <ui/DisplayConfig.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000029#include <utils/String8.h>
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080030#include <functional>
chaviw8ffc7b82020-08-18 11:25:37 -070031#include "utils/ScreenshotUtils.h"
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080032
Ana Krulec13be8ad2018-08-21 02:43:56 +000033namespace android {
34
35using Transaction = SurfaceComposerClient::Transaction;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -080036using ui::ColorMode;
Ana Krulec13be8ad2018-08-21 02:43:56 +000037
38namespace {
39const String8 DISPLAY_NAME("Credentials Display Test");
40const String8 SURFACE_NAME("Test Surface Name");
Ana Krulec13be8ad2018-08-21 02:43:56 +000041} // namespace
42
43/**
44 * This class tests the CheckCredentials method in SurfaceFlinger.
45 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
46 * return anything meaningful.
47 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080048
49// TODO(b/129481165): remove the #pragma below and fix conversion issues
50#pragma clang diagnostic push
51#pragma clang diagnostic ignored "-Wconversion"
Ana Krulec13be8ad2018-08-21 02:43:56 +000052class CredentialsTest : public ::testing::Test {
53protected:
54 void SetUp() override {
55 // Start the tests as root.
56 seteuid(AID_ROOT);
57
58 ASSERT_NO_FATAL_FAILURE(initClient());
59 }
60
61 void TearDown() override {
62 mComposerClient->dispose();
63 mBGSurfaceControl.clear();
64 mComposerClient.clear();
65 // Finish the tests as root.
66 seteuid(AID_ROOT);
67 }
68
69 sp<IBinder> mDisplay;
70 sp<IBinder> mVirtualDisplay;
71 sp<SurfaceComposerClient> mComposerClient;
72 sp<SurfaceControl> mBGSurfaceControl;
73 sp<SurfaceControl> mVirtualSurfaceControl;
74
75 void initClient() {
76 mComposerClient = new SurfaceComposerClient;
77 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
78 }
79
80 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080081 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
82 ASSERT_FALSE(mDisplay == nullptr);
83
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080084 DisplayConfig config;
85 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config));
Ana Krulec13be8ad2018-08-21 02:43:56 +000086
87 // Background surface
88 mBGSurfaceControl =
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080089 mComposerClient->createSurface(SURFACE_NAME, config.resolution.getWidth(),
90 config.resolution.getHeight(),
Ana Krulec13be8ad2018-08-21 02:43:56 +000091 PIXEL_FORMAT_RGBA_8888, 0);
92 ASSERT_TRUE(mBGSurfaceControl != nullptr);
93 ASSERT_TRUE(mBGSurfaceControl->isValid());
94
95 Transaction t;
96 t.setDisplayLayerStack(mDisplay, 0);
97 ASSERT_EQ(NO_ERROR,
98 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
99 }
100
Ana Krulec13be8ad2018-08-21 02:43:56 +0000101 /**
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());
chaviwd4a61642020-09-01 14:53:46 -0700148
149 // Check as shell since shell has some additional permissions
150 seteuid(AID_SHELL);
151 ASSERT_EQ(unprivilegedValue, condition());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000152 }
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
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800188 DisplayConfig config;
189 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000190
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -0800191 Vector<DisplayConfig> configs;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000192 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
193
arthurhung79e81aa2020-08-28 00:09:19 +0800194 ASSERT_TRUE(SurfaceComposerClient::getActiveConfig(display) >= 0);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000195
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
Steven Thomasa87ed452020-01-03 16:10:05 -0800218TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800219 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Steven Thomasa87ed452020-01-03 16:10:05 -0800220 int32_t defaultConfig;
Marin Shalamanov30b0b3c2020-10-13 19:15:06 +0200221 bool allowGroupSwitching;
Steven Thomasf734df42020-04-13 21:09:28 -0700222 float primaryFpsMin;
223 float primaryFpsMax;
224 float appRequestFpsMin;
225 float appRequestFpsMax;
226 status_t res =
227 SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
Marin Shalamanov30b0b3c2020-10-13 19:15:06 +0200228 &allowGroupSwitching,
Steven Thomasf734df42020-04-13 21:09:28 -0700229 &primaryFpsMin, &primaryFpsMax,
230 &appRequestFpsMin,
231 &appRequestFpsMax);
Steven Thomasa87ed452020-01-03 16:10:05 -0800232 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000233 std::function<status_t()> condition = [=]() {
Steven Thomasf734df42020-04-13 21:09:28 -0700234 return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig,
Marin Shalamanov30b0b3c2020-10-13 19:15:06 +0200235 allowGroupSwitching,
Steven Thomasf734df42020-04-13 21:09:28 -0700236 primaryFpsMin, primaryFpsMax,
237 appRequestFpsMin,
238 appRequestFpsMax);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000239 };
240 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
241}
242
243TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800244 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000245 std::function<status_t()> condition = [=]() {
246 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
247 };
248 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
249}
250
Ana Krulec13be8ad2018-08-21 02:43:56 +0000251TEST_F(CredentialsTest, CreateDisplayTest) {
chaviwd4a61642020-09-01 14:53:46 -0700252 // Only graphics and system processes can create a secure display.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000253 std::function<bool()> condition = [=]() {
254 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
255 return testDisplay.get() != nullptr;
256 };
chaviwd4a61642020-09-01 14:53:46 -0700257
258 // Check with root.
259 seteuid(AID_ROOT);
260 ASSERT_FALSE(condition());
261
262 // Check as a Graphics user.
263 setGraphicsUID();
264 ASSERT_TRUE(condition());
265
266 // Check as a system user.
267 setSystemUID();
268 ASSERT_TRUE(condition());
269
270 // Check as a non-supported user.
271 setBinUID();
272 ASSERT_FALSE(condition());
273
274 // Check as shell since shell has some additional permissions
275 seteuid(AID_SHELL);
276 ASSERT_FALSE(condition());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000277
278 condition = [=]() {
279 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
280 return testDisplay.get() != nullptr;
281 };
282 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
283}
284
Ana Krulec13be8ad2018-08-21 02:43:56 +0000285TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800286 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000287 std::function<status_t()> condition = [=]() {
288 sp<GraphicBuffer> outBuffer;
chaviw690db382020-07-27 16:46:46 -0700289 DisplayCaptureArgs captureArgs;
290 captureArgs.displayToken = display;
291 ScreenCaptureResults captureResults;
chaviw8ffc7b82020-08-18 11:25:37 -0700292 return ScreenCapture::captureDisplay(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000293 };
294 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
295}
296
297TEST_F(CredentialsTest, CaptureLayersTest) {
298 setupBackgroundSurface();
299 sp<GraphicBuffer> outBuffer;
300 std::function<status_t()> condition = [=]() {
chaviw26c52482020-07-28 16:25:52 -0700301 LayerCaptureArgs captureArgs;
302 captureArgs.layerHandle = mBGSurfaceControl->getHandle();
303 captureArgs.sourceCrop = {0, 0, 1, 1};
304
305 ScreenCaptureResults captureResults;
chaviw8ffc7b82020-08-18 11:25:37 -0700306 return ScreenCapture::captureLayers(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000307 };
308 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
309}
310
311/**
312 * The following tests are for methods accessible directly through SurfaceFlinger.
313 */
314
315/**
316 * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
317 * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
318 * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
319 * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
320 * the consumer of a buffer queue is SurfaceFlinger.
321 */
322TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
323 setupBackgroundSurface();
324 sp<IGraphicBufferProducer> producer =
325 mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
326 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
327
328 std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
329 // Anyone should be able to check if the consumer of the buffer queue is SF.
330 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
331}
332
333TEST_F(CredentialsTest, GetLayerDebugInfo) {
334 setupBackgroundSurface();
335 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
336
337 // Historically, only root and shell can access the getLayerDebugInfo which
338 // is called when we call dumpsys. I don't see a reason why we should change this.
339 std::vector<LayerDebugInfo> outLayers;
340 // Check with root.
341 seteuid(AID_ROOT);
342 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
343
344 // Check as a shell.
345 seteuid(AID_SHELL);
346 ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
347
348 // Check as anyone else.
349 seteuid(AID_ROOT);
350 seteuid(AID_BIN);
351 ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
352}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800353
354TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800355 const auto display = SurfaceComposerClient::getInternalDisplayToken();
356 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800357 bool result = false;
358 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
359 ASSERT_EQ(NO_ERROR, error);
360 bool hasWideColorMode = false;
361 Vector<ColorMode> colorModes;
362 SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
363 for (ColorMode colorMode : colorModes) {
364 switch (colorMode) {
365 case ColorMode::DISPLAY_P3:
366 case ColorMode::ADOBE_RGB:
367 case ColorMode::DCI_P3:
368 hasWideColorMode = true;
369 break;
370 default:
371 break;
372 }
373 }
374 ASSERT_EQ(hasWideColorMode, result);
375}
376
377TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800378 const auto display = SurfaceComposerClient::getInternalDisplayToken();
379 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800380 std::function<status_t()> condition = [=]() {
381 bool result = false;
382 return SurfaceComposerClient::isWideColorDisplay(display, &result);
383 };
384 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
385}
386
Peiyong Lind1fedb42019-03-11 17:48:41 -0700387TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
388 const auto display = SurfaceComposerClient::getInternalDisplayToken();
389 ASSERT_FALSE(display == nullptr);
390 ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
391 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
392}
393
Ana Krulec13be8ad2018-08-21 02:43:56 +0000394} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800395
396// TODO(b/129481165): remove the #pragma below and fix conversion issues
397#pragma clang diagnostic pop // ignored "-Wconversion"