blob: 6549a224e69263995d9531daca9cfbf63eea8cf5 [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>
Ana Krulec13be8ad2018-08-21 02:43:56 +000023#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>
Huihong Luo05539a12022-02-23 10:29:40 -080027#include <private/gui/ComposerServiceAIDL.h>
Marin Shalamanova7fe3042021-01-29 21:02:08 +010028#include <ui/DisplayMode.h>
Marin Shalamanov228f46b2021-01-28 21:11:45 +010029#include <ui/DynamicDisplayInfo.h>
Ana Krulec13be8ad2018-08-21 02:43:56 +000030#include <utils/String8.h>
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080031#include <functional>
chaviw8ffc7b82020-08-18 11:25:37 -070032#include "utils/ScreenshotUtils.h"
Dominik Laskowski3cb3d4e2019-11-21 11:14:45 -080033
Ana Krulec13be8ad2018-08-21 02:43:56 +000034namespace android {
35
36using Transaction = SurfaceComposerClient::Transaction;
Huihong Luo05539a12022-02-23 10:29:40 -080037using gui::LayerDebugInfo;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -080038using ui::ColorMode;
Ana Krulec13be8ad2018-08-21 02:43:56 +000039
40namespace {
41const String8 DISPLAY_NAME("Credentials Display Test");
42const String8 SURFACE_NAME("Test Surface Name");
Ana Krulec13be8ad2018-08-21 02:43:56 +000043} // namespace
44
45/**
46 * This class tests the CheckCredentials method in SurfaceFlinger.
47 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
48 * return anything meaningful.
49 */
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080050
51// TODO(b/129481165): remove the #pragma below and fix conversion issues
52#pragma clang diagnostic push
53#pragma clang diagnostic ignored "-Wconversion"
Ana Krulec13be8ad2018-08-21 02:43:56 +000054class CredentialsTest : public ::testing::Test {
55protected:
56 void SetUp() override {
57 // Start the tests as root.
58 seteuid(AID_ROOT);
59
60 ASSERT_NO_FATAL_FAILURE(initClient());
61 }
62
63 void TearDown() override {
64 mComposerClient->dispose();
65 mBGSurfaceControl.clear();
66 mComposerClient.clear();
67 // Finish the tests as root.
68 seteuid(AID_ROOT);
69 }
70
71 sp<IBinder> mDisplay;
72 sp<IBinder> mVirtualDisplay;
73 sp<SurfaceComposerClient> mComposerClient;
74 sp<SurfaceControl> mBGSurfaceControl;
75 sp<SurfaceControl> mVirtualSurfaceControl;
76
77 void initClient() {
78 mComposerClient = new SurfaceComposerClient;
79 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
80 }
81
82 void setupBackgroundSurface() {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -080083 mDisplay = SurfaceComposerClient::getInternalDisplayToken();
84 ASSERT_FALSE(mDisplay == nullptr);
85
Marin Shalamanova7fe3042021-01-29 21:02:08 +010086 ui::DisplayMode mode;
87 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode));
Ana Krulec13be8ad2018-08-21 02:43:56 +000088
89 // Background surface
Marin Shalamanova7fe3042021-01-29 21:02:08 +010090 mBGSurfaceControl = mComposerClient->createSurface(SURFACE_NAME, mode.resolution.getWidth(),
91 mode.resolution.getHeight(),
92 PIXEL_FORMAT_RGBA_8888, 0);
Ana Krulec13be8ad2018-08-21 02:43:56 +000093 ASSERT_TRUE(mBGSurfaceControl != nullptr);
94 ASSERT_TRUE(mBGSurfaceControl->isValid());
95
96 Transaction t;
Dominik Laskowski29fa1462021-04-27 15:51:50 -070097 t.setDisplayLayerStack(mDisplay, ui::DEFAULT_LAYER_STACK);
Ana Krulec13be8ad2018-08-21 02:43:56 +000098 ASSERT_EQ(NO_ERROR,
99 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
100 }
101
Ana Krulec13be8ad2018-08-21 02:43:56 +0000102 /**
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());
chaviwd4a61642020-09-01 14:53:46 -0700149
150 // Check as shell since shell has some additional permissions
151 seteuid(AID_SHELL);
152 ASSERT_EQ(unprivilegedValue, condition());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000153 }
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
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100189 ui::DisplayMode mode;
190 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000191
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100192 Vector<ui::DisplayMode> modes;
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100193 ui::DynamicDisplayInfo info;
194 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info));
Ana Krulec13be8ad2018-08-21 02:43:56 +0000195}
196
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100197TEST_F(CredentialsTest, GetDynamicDisplayInfoTest) {
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 = [=]() {
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100200 ui::DynamicDisplayInfo info;
201 return SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000202 };
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();
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100217 ui::DisplayModeId defaultMode;
Marin Shalamanov30b0b3c2020-10-13 19:15:06 +0200218 bool allowGroupSwitching;
Steven Thomasf734df42020-04-13 21:09:28 -0700219 float primaryFpsMin;
220 float primaryFpsMax;
221 float appRequestFpsMin;
222 float appRequestFpsMax;
223 status_t res =
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100224 SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &defaultMode,
225 &allowGroupSwitching, &primaryFpsMin,
226 &primaryFpsMax, &appRequestFpsMin,
227 &appRequestFpsMax);
Steven Thomasa87ed452020-01-03 16:10:05 -0800228 ASSERT_EQ(res, NO_ERROR);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000229 std::function<status_t()> condition = [=]() {
Marin Shalamanova7fe3042021-01-29 21:02:08 +0100230 return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, defaultMode,
231 allowGroupSwitching, primaryFpsMin,
232 primaryFpsMax, appRequestFpsMin,
233 appRequestFpsMax);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000234 };
235 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
236}
237
238TEST_F(CredentialsTest, SetActiveColorModeTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800239 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000240 std::function<status_t()> condition = [=]() {
241 return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
242 };
243 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
244}
245
Ana Krulec13be8ad2018-08-21 02:43:56 +0000246TEST_F(CredentialsTest, CreateDisplayTest) {
chaviwd4a61642020-09-01 14:53:46 -0700247 // Only graphics and system processes can create a secure display.
Ana Krulec13be8ad2018-08-21 02:43:56 +0000248 std::function<bool()> condition = [=]() {
249 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
250 return testDisplay.get() != nullptr;
251 };
chaviwd4a61642020-09-01 14:53:46 -0700252
253 // Check with root.
254 seteuid(AID_ROOT);
255 ASSERT_FALSE(condition());
256
257 // Check as a Graphics user.
258 setGraphicsUID();
259 ASSERT_TRUE(condition());
260
261 // Check as a system user.
262 setSystemUID();
263 ASSERT_TRUE(condition());
264
265 // Check as a non-supported user.
266 setBinUID();
267 ASSERT_FALSE(condition());
268
269 // Check as shell since shell has some additional permissions
270 seteuid(AID_SHELL);
271 ASSERT_FALSE(condition());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000272
273 condition = [=]() {
274 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
275 return testDisplay.get() != nullptr;
276 };
277 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
278}
279
Ana Krulec13be8ad2018-08-21 02:43:56 +0000280TEST_F(CredentialsTest, CaptureTest) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800281 const auto display = SurfaceComposerClient::getInternalDisplayToken();
Ana Krulec13be8ad2018-08-21 02:43:56 +0000282 std::function<status_t()> condition = [=]() {
283 sp<GraphicBuffer> outBuffer;
chaviw690db382020-07-27 16:46:46 -0700284 DisplayCaptureArgs captureArgs;
285 captureArgs.displayToken = display;
286 ScreenCaptureResults captureResults;
chaviw8ffc7b82020-08-18 11:25:37 -0700287 return ScreenCapture::captureDisplay(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000288 };
289 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
290}
291
292TEST_F(CredentialsTest, CaptureLayersTest) {
293 setupBackgroundSurface();
294 sp<GraphicBuffer> outBuffer;
295 std::function<status_t()> condition = [=]() {
chaviw26c52482020-07-28 16:25:52 -0700296 LayerCaptureArgs captureArgs;
297 captureArgs.layerHandle = mBGSurfaceControl->getHandle();
298 captureArgs.sourceCrop = {0, 0, 1, 1};
299
300 ScreenCaptureResults captureResults;
chaviw8ffc7b82020-08-18 11:25:37 -0700301 return ScreenCapture::captureLayers(captureArgs, captureResults);
Ana Krulec13be8ad2018-08-21 02:43:56 +0000302 };
303 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
304}
305
306/**
307 * The following tests are for methods accessible directly through SurfaceFlinger.
308 */
Ana Krulec13be8ad2018-08-21 02:43:56 +0000309TEST_F(CredentialsTest, GetLayerDebugInfo) {
310 setupBackgroundSurface();
Huihong Luo05539a12022-02-23 10:29:40 -0800311 sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000312
313 // Historically, only root and shell can access the getLayerDebugInfo which
314 // is called when we call dumpsys. I don't see a reason why we should change this.
315 std::vector<LayerDebugInfo> outLayers;
316 // Check with root.
317 seteuid(AID_ROOT);
Huihong Luo05539a12022-02-23 10:29:40 -0800318 binder::Status status = sf->getLayerDebugInfo(&outLayers);
319 ASSERT_EQ(NO_ERROR, status.transactionError());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000320
321 // Check as a shell.
322 seteuid(AID_SHELL);
Huihong Luo05539a12022-02-23 10:29:40 -0800323 status = sf->getLayerDebugInfo(&outLayers);
324 ASSERT_EQ(NO_ERROR, status.transactionError());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000325
326 // Check as anyone else.
327 seteuid(AID_ROOT);
328 seteuid(AID_BIN);
Huihong Luo05539a12022-02-23 10:29:40 -0800329 status = sf->getLayerDebugInfo(&outLayers);
330 ASSERT_EQ(PERMISSION_DENIED, status.transactionError());
Ana Krulec13be8ad2018-08-21 02:43:56 +0000331}
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800332
333TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800334 const auto display = SurfaceComposerClient::getInternalDisplayToken();
335 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800336 bool result = false;
337 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
338 ASSERT_EQ(NO_ERROR, error);
339 bool hasWideColorMode = false;
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100340 ui::DynamicDisplayInfo info;
341 SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
342 const auto& colorModes = info.supportedColorModes;
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800343 for (ColorMode colorMode : colorModes) {
344 switch (colorMode) {
345 case ColorMode::DISPLAY_P3:
346 case ColorMode::ADOBE_RGB:
347 case ColorMode::DCI_P3:
348 hasWideColorMode = true;
349 break;
350 default:
351 break;
352 }
353 }
354 ASSERT_EQ(hasWideColorMode, result);
355}
356
357TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
Dominik Laskowskidcb38bb2019-01-25 02:35:50 -0800358 const auto display = SurfaceComposerClient::getInternalDisplayToken();
359 ASSERT_FALSE(display == nullptr);
Peiyong Lin4f3fddf2019-01-24 17:21:24 -0800360 std::function<status_t()> condition = [=]() {
361 bool result = false;
362 return SurfaceComposerClient::isWideColorDisplay(display, &result);
363 };
364 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
365}
366
Peiyong Lind1fedb42019-03-11 17:48:41 -0700367TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
368 const auto display = SurfaceComposerClient::getInternalDisplayToken();
369 ASSERT_FALSE(display == nullptr);
Marin Shalamanov228f46b2021-01-28 21:11:45 +0100370 ui::DynamicDisplayInfo info;
371 SurfaceComposerClient::getDynamicDisplayInfo(display, &info);
372 ColorMode colorMode = info.activeColorMode;
Peiyong Lind1fedb42019-03-11 17:48:41 -0700373 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
374}
375
Ana Krulec13be8ad2018-08-21 02:43:56 +0000376} // namespace android
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -0800377
378// TODO(b/129481165): remove the #pragma below and fix conversion issues
379#pragma clang diagnostic pop // ignored "-Wconversion"