blob: 353b8139cad641182c28745e05a1c037ddcfc64f [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
Huihong Luo05539a12022-02-23 10:29:40 -080021#include <android/gui/ISurfaceComposer.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000022#include <gtest/gtest.h>
Huihong Luo3bdef862022-03-03 11:57:19 -080023#include <gui/AidlStatusUtil.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000024#include <gui/LayerDebugInfo.h>
25#include <gui/Surface.h>
26#include <gui/SurfaceComposerClient.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000027#include <private/android_filesystem_config.h>
Huihong Luo05539a12022-02-23 10:29:40 -080028#include <private/gui/ComposerServiceAIDL.h>
Marin Shalamanova7fe3042021-01-29 21:02:08 +010029#include <ui/DisplayMode.h>
Marin Shalamanov228f46b2021-01-28 21:11:45 +010030#include <ui/DynamicDisplayInfo.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000031#include <utils/String8.h>
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080032#include <functional>
chaviw8ffc7b82020-08-18 11:25:37 -070033#include "utils/ScreenshotUtils.h"
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080034
Ana Krulec13be8ad2018-08-21 02:43:56 +000035namespace android {
36
37using Transaction = SurfaceComposerClient::Transaction;
Huihong Luo05539a12022-02-23 10:29:40 -080038using gui::LayerDebugInfo;
Huihong Luo3bdef862022-03-03 11:57:19 -080039using gui::aidl_utils::statusTFromBinderStatus;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -080040using ui::ColorMode;
Ana Krulec13be8ad2018-08-21 02:43:56 +000041
42namespace {
43const String8 DISPLAY_NAME("Credentials Display Test");
44const String8 SURFACE_NAME("Test Surface Name");
Ana Krulec13be8ad2018-08-21 02:43:56 +000045} // namespace
46
47/**
48 * This class tests the CheckCredentials method in SurfaceFlinger.
49 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
50 * return anything meaningful.
51 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080052
53// TODO(b/129481165): remove the #pragma below and fix conversion issues
54#pragma clang diagnostic push
55#pragma clang diagnostic ignored "-Wconversion"
Ana Krulec13be8ad2018-08-21 02:43:56 +000056class CredentialsTest : public ::testing::Test {
57protected:
58 void SetUp() override {
59 // Start the tests as root.
60 seteuid(AID_ROOT);
61
62 ASSERT_NO_FATAL_FAILURE(initClient());
63 }
64
65 void TearDown() override {
66 mComposerClient->dispose();
67 mBGSurfaceControl.clear();
68 mComposerClient.clear();
69 // Finish the tests as root.
70 seteuid(AID_ROOT);
71 }
72
73 sp<IBinder> mDisplay;
74 sp<IBinder> mVirtualDisplay;
75 sp<SurfaceComposerClient> mComposerClient;
76 sp<SurfaceControl> mBGSurfaceControl;
77 sp<SurfaceControl> mVirtualSurfaceControl;
78
79 void initClient() {
Ady Abrahamd11bade2022-08-01 16:18:03 -070080 mComposerClient = sp<SurfaceComposerClient>::make();
Ana Krulec13be8ad2018-08-21 02:43:56 +000081 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
82 }
83
84 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080085 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
86 ASSERT_FALSE(mDisplay == nullptr);
87
Marin Shalamanova7fe3042021-01-29 21:02:08 +010088 ui::DisplayMode mode;
89 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode));
Ana Krulec13be8ad2018-08-21 02:43:56 +000090
91 // Background surface
Marin Shalamanova7fe3042021-01-29 21:02:08 +010092 mBGSurfaceControl = mComposerClient->createSurface(SURFACE_NAME, mode.resolution.getWidth(),
93 mode.resolution.getHeight(),
94 PIXEL_FORMAT_RGBA_8888, 0);
Ana Krulec13be8ad2018-08-21 02:43:56 +000095 ASSERT_TRUE(mBGSurfaceControl != nullptr);
96 ASSERT_TRUE(mBGSurfaceControl->isValid());
97
98 Transaction t;
Dominik Laskowski29fa1462021-04-27 15:51:50 -070099 t.setDisplayLayerStack(mDisplay, ui::DEFAULT_LAYER_STACK);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000100 ASSERT_EQ(NO_ERROR,
101 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
102 }
103
Ana Krulec13be8ad2018-08-21 02:43:56 +0000104 /**
105 * Sets UID to imitate Graphic's process.
106 */
107 void setGraphicsUID() {
108 seteuid(AID_ROOT);
109 seteuid(AID_GRAPHICS);
110 }
111
112 /**
113 * Sets UID to imitate System's process.
114 */
115 void setSystemUID() {
116 seteuid(AID_ROOT);
117 seteuid(AID_SYSTEM);
118 }
119
120 /**
121 * Sets UID to imitate a process that doesn't have any special privileges in
122 * our code.
123 */
124 void setBinUID() {
125 seteuid(AID_ROOT);
126 seteuid(AID_BIN);
127 }
128
129 /**
130 * Template function the check a condition for different types of users: root
131 * graphics, system, and non-supported user. Root, graphics, and system should
132 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
133 */
134 template <typename T>
135 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
136 // Check with root.
137 seteuid(AID_ROOT);
138 ASSERT_EQ(privilegedValue, condition());
139
140 // Check as a Graphics user.
141 setGraphicsUID();
142 ASSERT_EQ(privilegedValue, condition());
143
144 // Check as a system user.
145 setSystemUID();
146 ASSERT_EQ(privilegedValue, condition());
147
148 // Check as a non-supported user.
149 setBinUID();
150 ASSERT_EQ(unprivilegedValue, condition());
chaviwd4a61642020-09-01 14:53:46 -0700151
152 // Check as shell since shell has some additional permissions
153 seteuid(AID_SHELL);
154 ASSERT_EQ(unprivilegedValue, condition());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000155 }
156};
157
158TEST_F(CredentialsTest, ClientInitTest) {
159 // Root can init can init the client.
160 ASSERT_NO_FATAL_FAILURE(initClient());
161
162 // Graphics can init the client.
163 setGraphicsUID();
164 ASSERT_NO_FATAL_FAILURE(initClient());
165
166 // System can init the client.
167 setSystemUID();
168 ASSERT_NO_FATAL_FAILURE(initClient());
169
Robert Carrb89ea9d2018-12-10 13:01:14 -0800170 // Anyone else can init the client.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000171 setBinUID();
Ady Abrahamd11bade2022-08-01 16:18:03 -0700172 mComposerClient = sp<SurfaceComposerClient>::make();
Robert Carrb89ea9d2018-12-10 13:01:14 -0800173 ASSERT_NO_FATAL_FAILURE(initClient());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000174}
175
176TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800177 std::function<bool()> condition = [] {
178 return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
Ana Krulec13be8ad2018-08-21 02:43:56 +0000179 };
180 // Anyone can access display information.
181 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
182}
183
184TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
185 // The following methods are tested with a UID that is not root, graphics,
186 // or system, to show that anyone can access them.
187 setBinUID();
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800188 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000189 ASSERT_TRUE(display != nullptr);
190
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100191 ui::DisplayMode mode;
192 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000193
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100194 Vector<ui::DisplayMode> modes;
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100195 ui::DynamicDisplayInfo info;
196 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000197}
198
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100199TEST_F(CredentialsTest, GetDynamicDisplayInfoTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800200 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000201 std::function<status_t()> condition = [=]() {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100202 ui::DynamicDisplayInfo info;
203 return SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000204 };
205 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
206}
207
Daniel Solomon42d04562019-01-20 21:03:19 -0800208TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800209 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Daniel Solomon42d04562019-01-20 21:03:19 -0800210 std::function<status_t()> condition = [=]() {
211 ui::DisplayPrimaries primaries;
212 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
213 };
214 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
215}
216
Steven Thomasa87ed452020-01-03 16:10:05 -0800217TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800218 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100219 ui::DisplayModeId defaultMode;
Marin Shalamanov30b0b3c2020-10-13 19:15:06 +0200220 bool allowGroupSwitching;
Steven Thomasf734df42020-04-13 21:09:28 -0700221 float primaryFpsMin;
222 float primaryFpsMax;
223 float appRequestFpsMin;
224 float appRequestFpsMax;
225 status_t res =
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100226 SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &defaultMode,
227 &allowGroupSwitching, &primaryFpsMin,
228 &primaryFpsMax, &appRequestFpsMin,
229 &appRequestFpsMax);
Steven Thomasa87ed452020-01-03 16:10:05 -0800230 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000231 std::function<status_t()> condition = [=]() {
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100232 return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, defaultMode,
233 allowGroupSwitching, primaryFpsMin,
234 primaryFpsMax, appRequestFpsMin,
235 appRequestFpsMax);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000236 };
237 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
238}
239
240TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800241 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000242 std::function<status_t()> condition = [=]() {
243 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
244 };
245 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
246}
247
Ana Krulec13be8ad2018-08-21 02:43:56 +0000248TEST_F(CredentialsTest, CreateDisplayTest) {
chaviwd4a61642020-09-01 14:53:46 -0700249 // Only graphics and system processes can create a secure display.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000250 std::function<bool()> condition = [=]() {
251 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
252 return testDisplay.get() != nullptr;
253 };
chaviwd4a61642020-09-01 14:53:46 -0700254
255 // Check with root.
256 seteuid(AID_ROOT);
257 ASSERT_FALSE(condition());
258
259 // Check as a Graphics user.
260 setGraphicsUID();
261 ASSERT_TRUE(condition());
262
263 // Check as a system user.
264 setSystemUID();
265 ASSERT_TRUE(condition());
266
267 // Check as a non-supported user.
268 setBinUID();
269 ASSERT_FALSE(condition());
270
271 // Check as shell since shell has some additional permissions
272 seteuid(AID_SHELL);
273 ASSERT_FALSE(condition());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000274
275 condition = [=]() {
276 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
277 return testDisplay.get() != nullptr;
278 };
279 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
280}
281
Ana Krulec13be8ad2018-08-21 02:43:56 +0000282TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800283 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000284 std::function<status_t()> condition = [=]() {
285 sp<GraphicBuffer> outBuffer;
chaviw690db382020-07-27 16:46:46 -0700286 DisplayCaptureArgs captureArgs;
287 captureArgs.displayToken = display;
288 ScreenCaptureResults captureResults;
chaviw8ffc7b82020-08-18 11:25:37 -0700289 return ScreenCapture::captureDisplay(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000290 };
291 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
292}
293
294TEST_F(CredentialsTest, CaptureLayersTest) {
295 setupBackgroundSurface();
296 sp<GraphicBuffer> outBuffer;
297 std::function<status_t()> condition = [=]() {
chaviw26c52482020-07-28 16:25:52 -0700298 LayerCaptureArgs captureArgs;
299 captureArgs.layerHandle = mBGSurfaceControl->getHandle();
300 captureArgs.sourceCrop = {0, 0, 1, 1};
301
302 ScreenCaptureResults captureResults;
chaviw8ffc7b82020-08-18 11:25:37 -0700303 return ScreenCapture::captureLayers(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000304 };
305 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
306}
307
308/**
309 * The following tests are for methods accessible directly through SurfaceFlinger.
310 */
Ana Krulec13be8ad2018-08-21 02:43:56 +0000311TEST_F(CredentialsTest, GetLayerDebugInfo) {
312 setupBackgroundSurface();
Huihong Luo05539a12022-02-23 10:29:40 -0800313 sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000314
315 // Historically, only root and shell can access the getLayerDebugInfo which
316 // is called when we call dumpsys. I don't see a reason why we should change this.
317 std::vector<LayerDebugInfo> outLayers;
318 // Check with root.
319 seteuid(AID_ROOT);
Huihong Luo05539a12022-02-23 10:29:40 -0800320 binder::Status status = sf->getLayerDebugInfo(&outLayers);
Huihong Luo3bdef862022-03-03 11:57:19 -0800321 ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000322
323 // Check as a shell.
324 seteuid(AID_SHELL);
Huihong Luo05539a12022-02-23 10:29:40 -0800325 status = sf->getLayerDebugInfo(&outLayers);
Huihong Luo3bdef862022-03-03 11:57:19 -0800326 ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000327
328 // Check as anyone else.
329 seteuid(AID_ROOT);
330 seteuid(AID_BIN);
Huihong Luo05539a12022-02-23 10:29:40 -0800331 status = sf->getLayerDebugInfo(&outLayers);
Huihong Luo3bdef862022-03-03 11:57:19 -0800332 ASSERT_EQ(PERMISSION_DENIED, statusTFromBinderStatus(status));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000333}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800334
335TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800336 const auto display = SurfaceComposerClient::getInternalDisplayToken();
337 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800338 bool result = false;
339 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
340 ASSERT_EQ(NO_ERROR, error);
341 bool hasWideColorMode = false;
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100342 ui::DynamicDisplayInfo info;
343 SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
344 const auto& colorModes = info.supportedColorModes;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800345 for (ColorMode colorMode : colorModes) {
346 switch (colorMode) {
347 case ColorMode::DISPLAY_P3:
348 case ColorMode::ADOBE_RGB:
349 case ColorMode::DCI_P3:
350 hasWideColorMode = true;
351 break;
352 default:
353 break;
354 }
355 }
356 ASSERT_EQ(hasWideColorMode, result);
357}
358
359TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800360 const auto display = SurfaceComposerClient::getInternalDisplayToken();
361 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800362 std::function<status_t()> condition = [=]() {
363 bool result = false;
364 return SurfaceComposerClient::isWideColorDisplay(display, &result);
365 };
366 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
367}
368
Peiyong Lind1fedb42019-03-11 17:48:41 -0700369TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
370 const auto display = SurfaceComposerClient::getInternalDisplayToken();
371 ASSERT_FALSE(display == nullptr);
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100372 ui::DynamicDisplayInfo info;
373 SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
374 ColorMode colorMode = info.activeColorMode;
Peiyong Lind1fedb42019-03-11 17:48:41 -0700375 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
376}
377
Ana Krulec13be8ad2018-08-21 02:43:56 +0000378} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800379
380// TODO(b/129481165): remove the #pragma below and fix conversion issues
381#pragma clang diagnostic pop // ignored "-Wconversion"