1 /*
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
21 #include <android/gui/ISurfaceComposer.h>
22 #include <gtest/gtest.h>
23 #include <gui/AidlStatusUtil.h>
24 #include <gui/LayerDebugInfo.h>
25 #include <gui/Surface.h>
26 #include <gui/SurfaceComposerClient.h>
27 #include <private/android_filesystem_config.h>
28 #include <private/gui/ComposerServiceAIDL.h>
29 #include <ui/DisplayMode.h>
30 #include <ui/DynamicDisplayInfo.h>
31 #include <utils/String8.h>
32 #include <functional>
33 #include "utils/ScreenshotUtils.h"
34 #include "utils/WindowInfosListenerUtils.h"
35
36 namespace android {
37
38 using Transaction = SurfaceComposerClient::Transaction;
39 using gui::LayerDebugInfo;
40 using gui::aidl_utils::statusTFromBinderStatus;
41 using ui::ColorMode;
42
43 namespace {
44 const String8 DISPLAY_NAME("Credentials Display Test");
45 const String8 SURFACE_NAME("Test Surface Name");
46 } // namespace
47
48 /**
49 * This class tests the CheckCredentials method in SurfaceFlinger.
50 * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
51 * return anything meaningful.
52 */
53
54 // TODO(b/129481165): remove the #pragma below and fix conversion issues
55 #pragma clang diagnostic push
56 #pragma clang diagnostic ignored "-Wconversion"
57 class CredentialsTest : public ::testing::Test {
58 protected:
SetUp()59 void SetUp() override { ASSERT_NO_FATAL_FAILURE(initClient()); }
60
TearDown()61 void TearDown() override {
62 mComposerClient->dispose();
63 mBGSurfaceControl.clear();
64 mComposerClient.clear();
65 }
66
67 sp<IBinder> mDisplay;
68 sp<IBinder> mVirtualDisplay;
69 sp<SurfaceComposerClient> mComposerClient;
70 sp<SurfaceControl> mBGSurfaceControl;
71 sp<SurfaceControl> mVirtualSurfaceControl;
72
initClient()73 void initClient() {
74 mComposerClient = sp<SurfaceComposerClient>::make();
75 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
76 }
77
getFirstDisplayToken()78 static sp<IBinder> getFirstDisplayToken() {
79 const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
80 if (ids.empty()) {
81 return nullptr;
82 }
83
84 return SurfaceComposerClient::getPhysicalDisplayToken(ids.front());
85 }
86
getFirstDisplayId()87 static std::optional<uint64_t> getFirstDisplayId() {
88 const auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
89 if (ids.empty()) {
90 return std::nullopt;
91 }
92
93 return ids.front().value;
94 }
95
setupBackgroundSurface()96 void setupBackgroundSurface() {
97 mDisplay = getFirstDisplayToken();
98 ASSERT_FALSE(mDisplay == nullptr);
99
100 ui::DisplayMode mode;
101 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode));
102
103 // Background surface
104 mBGSurfaceControl = mComposerClient->createSurface(SURFACE_NAME, mode.resolution.getWidth(),
105 mode.resolution.getHeight(),
106 PIXEL_FORMAT_RGBA_8888, 0);
107 ASSERT_TRUE(mBGSurfaceControl != nullptr);
108 ASSERT_TRUE(mBGSurfaceControl->isValid());
109
110 Transaction t;
111 t.setDisplayLayerStack(mDisplay, ui::DEFAULT_LAYER_STACK);
112 ASSERT_EQ(NO_ERROR,
113 t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
114 }
115
116 /**
117 * Template function the check a condition for different types of users: root
118 * graphics, system, and non-supported user. Root, graphics, and system should
119 * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
120 */
121 template <typename T>
checkWithPrivileges(std::function<T ()> condition,T privilegedValue,T unprivilegedValue)122 void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
123 // Check with root.
124 {
125 UIDFaker f(AID_SYSTEM);
126 ASSERT_EQ(privilegedValue, condition());
127 }
128
129 // Check as a Graphics user.
130 {
131 UIDFaker f(AID_GRAPHICS);
132 ASSERT_EQ(privilegedValue, condition());
133 }
134
135 // Check as a system user.
136 {
137 UIDFaker f(AID_SYSTEM);
138 ASSERT_EQ(privilegedValue, condition());
139 }
140
141 // Check as a non-supported user.
142 {
143 UIDFaker f(AID_BIN);
144 ASSERT_EQ(unprivilegedValue, condition());
145 }
146
147 // Check as shell since shell has some additional permissions
148 {
149 UIDFaker f(AID_SHELL);
150 ASSERT_EQ(privilegedValue, condition());
151 }
152 }
153 };
154
TEST_F(CredentialsTest,ClientInitTest)155 TEST_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 {
161 UIDFaker f(AID_GRAPHICS);
162 ASSERT_NO_FATAL_FAILURE(initClient());
163 }
164
165 // System can init the client.
166 {
167 UIDFaker f(AID_SYSTEM);
168 ASSERT_NO_FATAL_FAILURE(initClient());
169 }
170
171 // Anyone else can init the client.
172 {
173 UIDFaker f(AID_BIN);
174 mComposerClient = sp<SurfaceComposerClient>::make();
175 ASSERT_NO_FATAL_FAILURE(initClient());
176 }
177 }
178
TEST_F(CredentialsTest,GetBuiltInDisplayAccessTest)179 TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
180 std::function<bool()> condition = [] { return getFirstDisplayToken() != nullptr; };
181 // Anyone can access display information.
182 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
183 }
184
TEST_F(CredentialsTest,AllowedGetterMethodsTest)185 TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
186 // The following methods are tested with a UID that is not root, graphics,
187 // or system, to show that anyone can access them.
188 UIDFaker f(AID_BIN);
189 const auto id = getFirstDisplayId();
190 ASSERT_TRUE(id);
191 ui::DynamicDisplayInfo info;
192 ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfoFromId(*id, &info));
193 }
194
TEST_F(CredentialsTest,GetDynamicDisplayInfoTest)195 TEST_F(CredentialsTest, GetDynamicDisplayInfoTest) {
196 const auto id = getFirstDisplayId();
197 ASSERT_TRUE(id);
198 std::function<status_t()> condition = [=]() {
199 ui::DynamicDisplayInfo info;
200 return SurfaceComposerClient::getDynamicDisplayInfoFromId(*id, &info);
201 };
202 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
203 }
204
TEST_F(CredentialsTest,GetDisplayNativePrimariesTest)205 TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
206 const auto display = getFirstDisplayToken();
207 std::function<status_t()> condition = [=]() {
208 ui::DisplayPrimaries primaries;
209 return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
210 };
211 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
212 }
213
TEST_F(CredentialsTest,SetDesiredDisplayConfigsTest)214 TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
215 const auto display = getFirstDisplayToken();
216 gui::DisplayModeSpecs specs;
217 status_t res = SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &specs);
218 ASSERT_EQ(res, NO_ERROR);
219 gui::DisplayModeSpecs setSpecs;
220 std::function<status_t()> condition = [=]() {
221 return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, specs);
222 };
223 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
224 }
225
TEST_F(CredentialsTest,SetActiveColorModeTest)226 TEST_F(CredentialsTest, SetActiveColorModeTest) {
227 const auto display = getFirstDisplayToken();
228 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
TEST_F(CredentialsTest,CreateDisplayTest)234 TEST_F(CredentialsTest, CreateDisplayTest) {
235 // Only graphics and system processes can create a secure display.
236 std::function<bool()> condition = [=]() {
237 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
238 return testDisplay.get() != nullptr;
239 };
240
241 // Check with root.
242 {
243 UIDFaker f(AID_ROOT);
244 ASSERT_FALSE(condition());
245 }
246
247 // Check as a Graphics user.
248 {
249 UIDFaker f(AID_GRAPHICS);
250 ASSERT_TRUE(condition());
251 }
252
253 // Check as a system user.
254 {
255 UIDFaker f(AID_SYSTEM);
256 ASSERT_TRUE(condition());
257 }
258
259 // Check as a non-supported user.
260 {
261 UIDFaker f(AID_BIN);
262 ASSERT_FALSE(condition());
263 }
264
265 // Check as shell since shell has some additional permissions
266 {
267 UIDFaker f(AID_SHELL);
268 ASSERT_FALSE(condition());
269 }
270
271 condition = [=]() {
272 sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
273 return testDisplay.get() != nullptr;
274 };
275 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
276 }
277
TEST_F(CredentialsTest,CaptureTest)278 TEST_F(CredentialsTest, CaptureTest) {
279 const auto display = getFirstDisplayToken();
280 std::function<status_t()> condition = [=]() {
281 sp<GraphicBuffer> outBuffer;
282 DisplayCaptureArgs captureArgs;
283 captureArgs.displayToken = display;
284 ScreenCaptureResults captureResults;
285 return ScreenCapture::captureDisplay(captureArgs, captureResults);
286 };
287 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
288 }
289
TEST_F(CredentialsTest,CaptureLayersTest)290 TEST_F(CredentialsTest, CaptureLayersTest) {
291 setupBackgroundSurface();
292 sp<GraphicBuffer> outBuffer;
293 std::function<status_t()> condition = [=]() {
294 LayerCaptureArgs captureArgs;
295 captureArgs.layerHandle = mBGSurfaceControl->getHandle();
296 captureArgs.sourceCrop = {0, 0, 1, 1};
297
298 ScreenCaptureResults captureResults;
299 return ScreenCapture::captureLayers(captureArgs, captureResults);
300 };
301 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
302 }
303
304 /**
305 * The following tests are for methods accessible directly through SurfaceFlinger.
306 */
TEST_F(CredentialsTest,GetLayerDebugInfo)307 TEST_F(CredentialsTest, GetLayerDebugInfo) {
308 setupBackgroundSurface();
309 sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
310
311 // Historically, only root and shell can access the getLayerDebugInfo which
312 // is called when we call dumpsys. I don't see a reason why we should change this.
313 std::vector<LayerDebugInfo> outLayers;
314 binder::Status status = binder::Status::ok();
315 // Check with root.
316 {
317 UIDFaker f(AID_ROOT);
318 status = sf->getLayerDebugInfo(&outLayers);
319 ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
320 }
321
322 // Check as a shell.
323 {
324 UIDFaker f(AID_SHELL);
325 status = sf->getLayerDebugInfo(&outLayers);
326 ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
327 }
328
329 // Check as anyone else.
330 {
331 UIDFaker f(AID_BIN);
332 status = sf->getLayerDebugInfo(&outLayers);
333 ASSERT_EQ(PERMISSION_DENIED, statusTFromBinderStatus(status));
334 }
335 }
336
TEST_F(CredentialsTest,IsWideColorDisplayBasicCorrectness)337 TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
338 const auto display = getFirstDisplayToken();
339 ASSERT_FALSE(display == nullptr);
340 bool result = false;
341 status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
342 ASSERT_EQ(NO_ERROR, error);
343 bool hasWideColorMode = false;
344 const auto id = getFirstDisplayId();
345 ASSERT_TRUE(id);
346 ui::DynamicDisplayInfo info;
347 SurfaceComposerClient::getDynamicDisplayInfoFromId(*id, &info);
348 const auto& colorModes = info.supportedColorModes;
349 for (ColorMode colorMode : colorModes) {
350 switch (colorMode) {
351 case ColorMode::DISPLAY_P3:
352 case ColorMode::ADOBE_RGB:
353 case ColorMode::DCI_P3:
354 hasWideColorMode = true;
355 break;
356 default:
357 break;
358 }
359 }
360 ASSERT_EQ(hasWideColorMode, result);
361 }
362
TEST_F(CredentialsTest,IsWideColorDisplayWithPrivileges)363 TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
364 const auto display = getFirstDisplayToken();
365 ASSERT_FALSE(display == nullptr);
366 std::function<status_t()> condition = [=]() {
367 bool result = false;
368 return SurfaceComposerClient::isWideColorDisplay(display, &result);
369 };
370 ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
371 }
372
TEST_F(CredentialsTest,GetActiveColorModeBasicCorrectness)373 TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
374 const auto id = getFirstDisplayId();
375 ASSERT_TRUE(id);
376 ui::DynamicDisplayInfo info;
377 SurfaceComposerClient::getDynamicDisplayInfoFromId(*id, &info);
378 ColorMode colorMode = info.activeColorMode;
379 ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
380 }
381
TEST_F(CredentialsTest,TransactionPermissionTest)382 TEST_F(CredentialsTest, TransactionPermissionTest) {
383 WindowInfosListenerUtils windowInfosListenerUtils;
384 std::string name = "Test Layer";
385 sp<IBinder> token = sp<BBinder>::make();
386 WindowInfo windowInfo;
387 windowInfo.name = name;
388 windowInfo.token = token;
389 sp<SurfaceControl> surfaceControl =
390 mComposerClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
391 ISurfaceComposerClient::eFXSurfaceBufferState);
392 const Rect crop(0, 0, 100, 100);
393 {
394 UIDFaker f(AID_SYSTEM);
395 Transaction()
396 .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
397 .show(surfaceControl)
398 .setLayer(surfaceControl, INT32_MAX - 1)
399 .setCrop(surfaceControl, crop)
400 .setInputWindowInfo(surfaceControl, windowInfo)
401 .apply();
402 }
403
404 // Called from non privileged process
405 Transaction().setTrustedOverlay(surfaceControl, true);
406 {
407 UIDFaker f(AID_SYSTEM);
408 auto windowIsPresentAndNotTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
409 auto foundWindowInfo =
410 WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
411 if (!foundWindowInfo) {
412 return false;
413 }
414 return !foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY);
415 };
416 windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndNotTrusted);
417 }
418
419 {
420 UIDFaker f(AID_SYSTEM);
421 Transaction().setTrustedOverlay(surfaceControl, true);
422 auto windowIsPresentAndTrusted = [&](const std::vector<WindowInfo>& windowInfos) {
423 auto foundWindowInfo =
424 WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos);
425 if (!foundWindowInfo) {
426 return false;
427 }
428 return foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY);
429 };
430 windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndTrusted);
431 }
432 }
433
434 } // namespace android
435
436 // TODO(b/129481165): remove the #pragma below and fix conversion issues
437 #pragma clang diagnostic pop // ignored "-Wconversion"
438