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