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 <private/android_filesystem_config.h>
20 #include <future>
21 #include "utils/TransactionUtils.h"
22 
23 namespace android {
24 using Transaction = SurfaceComposerClient::Transaction;
25 using gui::WindowInfo;
26 
27 class WindowInfosListenerTest : public ::testing::Test {
28 protected:
SetUp()29     void SetUp() override {
30         seteuid(AID_SYSTEM);
31         mClient = new SurfaceComposerClient;
32         mWindowInfosListener = new SyncWindowInfosListener();
33         mClient->addWindowInfosListener(mWindowInfosListener);
34     }
35 
TearDown()36     void TearDown() override {
37         mClient->removeWindowInfosListener(mWindowInfosListener);
38         seteuid(AID_ROOT);
39     }
40 
41     struct SyncWindowInfosListener : public gui::WindowInfosListener {
42     public:
onWindowInfosChangedandroid::WindowInfosListenerTest::SyncWindowInfosListener43         void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos) override {
44             windowInfosPromise.set_value(windowInfos);
45         }
46 
waitForWindowInfosandroid::WindowInfosListenerTest::SyncWindowInfosListener47         std::vector<WindowInfo> waitForWindowInfos() {
48             std::future<std::vector<WindowInfo>> windowInfosFuture =
49                     windowInfosPromise.get_future();
50             std::vector<WindowInfo> windowInfos = windowInfosFuture.get();
51             windowInfosPromise = std::promise<std::vector<WindowInfo>>();
52             return windowInfos;
53         }
54 
55     private:
56         std::promise<std::vector<WindowInfo>> windowInfosPromise;
57     };
58 
59     sp<SurfaceComposerClient> mClient;
60     sp<SyncWindowInfosListener> mWindowInfosListener;
61 };
62 
findMatchingWindowInfo(WindowInfo targetWindowInfo,std::vector<WindowInfo> windowInfos)63 std::optional<WindowInfo> findMatchingWindowInfo(WindowInfo targetWindowInfo,
64                                                  std::vector<WindowInfo> windowInfos) {
65     std::optional<WindowInfo> foundWindowInfo = std::nullopt;
66     for (WindowInfo windowInfo : windowInfos) {
67         if (windowInfo.token == targetWindowInfo.token) {
68             foundWindowInfo = std::make_optional<>(windowInfo);
69             break;
70         }
71     }
72 
73     return foundWindowInfo;
74 }
75 
TEST_F(WindowInfosListenerTest,WindowInfoAddedAndRemoved)76 TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) {
77     std::string name = "Test Layer";
78     sp<IBinder> token = new BBinder();
79     WindowInfo windowInfo;
80     windowInfo.name = name;
81     windowInfo.token = token;
82     sp<SurfaceControl> surfaceControl =
83             mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
84                                    ISurfaceComposerClient::eFXSurfaceBufferState);
85 
86     Transaction()
87             .setLayerStack(surfaceControl, 0)
88             .show(surfaceControl)
89             .setLayer(surfaceControl, INT32_MAX - 1)
90             .setInputWindowInfo(surfaceControl, windowInfo)
91             .apply();
92 
93     std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos();
94     std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
95     ASSERT_NE(std::nullopt, foundWindowInfo);
96 
97     Transaction().reparent(surfaceControl, nullptr).apply();
98 
99     windowInfos = mWindowInfosListener->waitForWindowInfos();
100     foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
101     ASSERT_EQ(std::nullopt, foundWindowInfo);
102 }
103 
TEST_F(WindowInfosListenerTest,WindowInfoChanged)104 TEST_F(WindowInfosListenerTest, WindowInfoChanged) {
105     std::string name = "Test Layer";
106     sp<IBinder> token = new BBinder();
107     WindowInfo windowInfo;
108     windowInfo.name = name;
109     windowInfo.token = token;
110     sp<SurfaceControl> surfaceControl =
111             mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888,
112                                    ISurfaceComposerClient::eFXSurfaceBufferState);
113     const Rect crop(0, 0, 100, 100);
114     Transaction()
115             .setLayerStack(surfaceControl, 0)
116             .show(surfaceControl)
117             .setLayer(surfaceControl, INT32_MAX - 1)
118             .setCrop(surfaceControl, crop)
119             .setInputWindowInfo(surfaceControl, windowInfo)
120             .apply();
121 
122     std::vector<WindowInfo> windowInfos = mWindowInfosListener->waitForWindowInfos();
123     std::optional<WindowInfo> foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
124     ASSERT_NE(std::nullopt, foundWindowInfo);
125     ASSERT_TRUE(foundWindowInfo->touchableRegion.isEmpty());
126 
127     Rect touchableRegions(0, 0, 50, 50);
128     windowInfo.addTouchableRegion(Rect(0, 0, 50, 50));
129     Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply();
130 
131     windowInfos = mWindowInfosListener->waitForWindowInfos();
132     foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos);
133     ASSERT_NE(std::nullopt, foundWindowInfo);
134     ASSERT_TRUE(foundWindowInfo->touchableRegion.hasSameRects(windowInfo.touchableRegion));
135 }
136 
137 } // namespace android
138