1 /*
2 * Copyright 2021 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 #include <gtest/gtest.h>
18 #include <gui/SurfaceComposerClient.h>
19 #include <gui/WindowInfosUpdate.h>
20 #include <private/android_filesystem_config.h>
21 #include <cstdint>
22 #include <future>
23 #include "utils/WindowInfosListenerUtils.h"
24
25 namespace android {
26 using Transaction = SurfaceComposerClient::Transaction;
27 using gui::DisplayInfo;
28 using gui::WindowInfo;
29 constexpr auto findMatchingWindowInfo = WindowInfosListenerUtils::findMatchingWindowInfo;
30
31 using WindowInfosPredicate = std::function<bool(const std::vector<WindowInfo>&)>;
32
33 class WindowInfosListenerTest : public ::testing::Test {
34 protected:
SetUp()35 void SetUp() override {
36 seteuid(AID_SYSTEM);
37 mClient = sp<SurfaceComposerClient>::make();
38 }
39
TearDown()40 void TearDown() override { seteuid(AID_ROOT); }
41
42 sp<SurfaceComposerClient> mClient;
43 WindowInfosListenerUtils mWindowInfosListenerUtils;
44
waitForWindowInfosPredicate(const WindowInfosPredicate & predicate)45 bool waitForWindowInfosPredicate(const WindowInfosPredicate& predicate) {
46 return mWindowInfosListenerUtils.waitForWindowInfosPredicate(std::move(predicate));
47 }
48 };
49
TEST_F(WindowInfosListenerTest,WindowInfoAddedAndRemoved)50 TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) {
51 std::string name = "Test Layer";
52 sp<IBinder> token = sp<BBinder>::make();
53 WindowInfo windowInfo;
54 windowInfo.name = name;
55 windowInfo.token = token;
56 sp<SurfaceControl> surfaceControl =
57 mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
58 ISurfaceComposerClient::eFXSurfaceBufferState);
59
60 Transaction()
61 .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
62 .show(surfaceControl)
63 .setLayer(surfaceControl, INT32_MAX - 1)
64 .setInputWindowInfo(surfaceControl, windowInfo)
65 .apply();
66
67 auto windowPresent = [&](const std::vector<WindowInfo>& windowInfos) {
68 return findMatchingWindowInfo(windowInfo, windowInfos);
69 };
70 ASSERT_TRUE(waitForWindowInfosPredicate(windowPresent));
71
72 Transaction().reparent(surfaceControl, nullptr).apply();
73
74 auto windowNotPresent = [&](const std::vector<WindowInfo>& windowInfos) {
75 return !findMatchingWindowInfo(windowInfo, windowInfos);
76 };
77 ASSERT_TRUE(waitForWindowInfosPredicate(windowNotPresent));
78 }
79
TEST_F(WindowInfosListenerTest,WindowInfoChanged)80 TEST_F(WindowInfosListenerTest, WindowInfoChanged) {
81 std::string name = "Test Layer";
82 sp<IBinder> token = sp<BBinder>::make();
83 WindowInfo windowInfo;
84 windowInfo.name = name;
85 windowInfo.token = token;
86 sp<SurfaceControl> surfaceControl =
87 mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
88 ISurfaceComposerClient::eFXSurfaceBufferState);
89 const Rect crop(0, 0, 100, 100);
90 Transaction()
91 .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
92 .show(surfaceControl)
93 .setLayer(surfaceControl, INT32_MAX - 1)
94 .setCrop(surfaceControl, crop)
95 .setInputWindowInfo(surfaceControl, windowInfo)
96 .apply();
97
98 auto windowIsPresentAndTouchableRegionEmpty = [&](const std::vector<WindowInfo>& windowInfos) {
99 auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
100 if (!foundWindowInfo) {
101 return false;
102 }
103 return foundWindowInfo->touchableRegion.isEmpty();
104 };
105 ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionEmpty));
106
107 windowInfo.addTouchableRegion({0, 0, 50, 50});
108 Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply();
109
110 auto windowIsPresentAndTouchableRegionMatches =
111 [&](const std::vector<WindowInfo>& windowInfos) {
112 auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
113 if (!foundWindowInfo) {
114 return false;
115 }
116
117 auto touchableRegion =
118 foundWindowInfo->transform.transform(foundWindowInfo->touchableRegion);
119 return touchableRegion.hasSameRects(windowInfo.touchableRegion);
120 };
121 ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionMatches));
122 }
123
124 } // namespace android
125