• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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