blob: ef3dd65d4668bfbbd70601b3d1868ec63c64d0a6 [file] [log] [blame]
Vishnu Nairc519ff72021-01-21 08:23:08 -08001/*
2 * Copyright (C) 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
19#include "../FocusResolver.h"
20
21// atest inputflinger_tests:FocusResolverTest
22
23namespace android::inputdispatcher {
24
25class FakeWindowHandle : public InputWindowHandle {
26public:
27 FakeWindowHandle(const std::string& name, const sp<IBinder>& token, bool focusable,
28 bool visible) {
29 mInfo.token = token;
30 mInfo.name = name;
31 mInfo.visible = visible;
32 mInfo.focusable = focusable;
33 }
34
35 bool updateInfo() { return true; }
36 void setFocusable(bool focusable) { mInfo.focusable = focusable; }
37 void setVisible(bool visible) { mInfo.visible = visible; }
38};
39
40TEST(FocusResolverTest, SetFocusedWindow) {
41 sp<IBinder> focusableWindowToken = new BBinder();
42 sp<IBinder> invisibleWindowToken = new BBinder();
43 sp<IBinder> unfocusableWindowToken = new BBinder();
44 std::vector<sp<InputWindowHandle>> windows;
45 windows.push_back(new FakeWindowHandle("Focusable", focusableWindowToken, true /* focusable */,
46 true /* visible */));
47 windows.push_back(new FakeWindowHandle("Invisible", invisibleWindowToken, true /* focusable */,
48 false /* visible */));
49 windows.push_back(new FakeWindowHandle("unfocusable", unfocusableWindowToken,
50 false /* focusable */, true /* visible */));
51
52 // focusable window can get focused
53 FocusRequest request;
54 request.displayId = 42;
55 request.token = focusableWindowToken;
56 FocusResolver focusResolver;
57 std::optional<FocusResolver::FocusChanges> changes =
58 focusResolver.setFocusedWindow(request, windows);
59 ASSERT_EQ(nullptr, changes->oldFocus);
60 ASSERT_EQ(focusableWindowToken, changes->newFocus);
61 ASSERT_EQ(request.displayId, changes->displayId);
62
63 // invisible window cannot get focused
64 request.token = invisibleWindowToken;
65 changes = focusResolver.setFocusedWindow(request, windows);
66 ASSERT_EQ(focusableWindowToken, changes->oldFocus);
67 ASSERT_EQ(nullptr, changes->newFocus);
68
69 // unfocusableWindowToken window cannot get focused
70 request.token = unfocusableWindowToken;
71 changes = focusResolver.setFocusedWindow(request, windows);
72 ASSERT_FALSE(changes);
73}
74
75TEST(FocusResolverTest, SetFocusedMirroredWindow) {
76 sp<IBinder> focusableWindowToken = new BBinder();
77 sp<IBinder> invisibleWindowToken = new BBinder();
78 sp<IBinder> unfocusableWindowToken = new BBinder();
79 std::vector<sp<InputWindowHandle>> windows;
80 windows.push_back(new FakeWindowHandle("Mirror1", focusableWindowToken, true /* focusable */,
81 true /* visible */));
82 windows.push_back(new FakeWindowHandle("Mirror1", focusableWindowToken, true /* focusable */,
83 true /* visible */));
84
85 windows.push_back(new FakeWindowHandle("Mirror2Visible", invisibleWindowToken,
86 true /* focusable */, true /* visible */));
87 windows.push_back(new FakeWindowHandle("Mirror2Invisible", invisibleWindowToken,
88 true /* focusable */, false /* visible */));
89
90 windows.push_back(new FakeWindowHandle("Mirror3Focusable", unfocusableWindowToken,
91 true /* focusable */, true /* visible */));
92 windows.push_back(new FakeWindowHandle("Mirror3Unfocusable", unfocusableWindowToken,
93 false /* focusable */, true /* visible */));
94
95 // mirrored window can get focused
96 FocusRequest request;
97 request.displayId = 42;
98 request.token = focusableWindowToken;
99 FocusResolver focusResolver;
100 std::optional<FocusResolver::FocusChanges> changes =
101 focusResolver.setFocusedWindow(request, windows);
102 ASSERT_EQ(nullptr, changes->oldFocus);
103 ASSERT_EQ(focusableWindowToken, changes->newFocus);
104
105 // mirrored window with one visible window can get focused
106 request.token = invisibleWindowToken;
107 changes = focusResolver.setFocusedWindow(request, windows);
108 ASSERT_EQ(focusableWindowToken, changes->oldFocus);
109 ASSERT_EQ(invisibleWindowToken, changes->newFocus);
110
111 // mirrored window with one or more unfocusable window cannot get focused
112 request.token = unfocusableWindowToken;
113 changes = focusResolver.setFocusedWindow(request, windows);
114 ASSERT_FALSE(changes);
115}
116
117TEST(FocusResolverTest, SetInputWindows) {
118 sp<IBinder> focusableWindowToken = new BBinder();
119 std::vector<sp<InputWindowHandle>> windows;
120 sp<FakeWindowHandle> window = new FakeWindowHandle("Focusable", focusableWindowToken,
121 true /* focusable */, true /* visible */);
122 windows.push_back(window);
123
124 // focusable window can get focused
125 FocusRequest request;
126 request.displayId = 42;
127 request.token = focusableWindowToken;
128 FocusResolver focusResolver;
129 std::optional<FocusResolver::FocusChanges> changes =
130 focusResolver.setFocusedWindow(request, windows);
131 ASSERT_EQ(focusableWindowToken, changes->newFocus);
132
133 // Window visibility changes and the window loses focused
134 window->setVisible(false);
135 changes = focusResolver.setInputWindows(request.displayId, windows);
136 ASSERT_EQ(nullptr, changes->newFocus);
137 ASSERT_EQ(focusableWindowToken, changes->oldFocus);
138}
139
140TEST(FocusResolverTest, FocusRequestsCanBePending) {
141 sp<IBinder> invisibleWindowToken = new BBinder();
142 std::vector<sp<InputWindowHandle>> windows;
143
144 sp<FakeWindowHandle> invisibleWindow =
145 new FakeWindowHandle("Invisible", invisibleWindowToken, true /* focusable */,
146 false /* visible */);
147 windows.push_back(invisibleWindow);
148
149 // invisible window cannot get focused
150 FocusRequest request;
151 request.displayId = 42;
152 request.token = invisibleWindowToken;
153 FocusResolver focusResolver;
154 std::optional<FocusResolver::FocusChanges> changes =
155 focusResolver.setFocusedWindow(request, windows);
156 ASSERT_FALSE(changes);
157
158 // Window visibility changes and the window gets focused
159 invisibleWindow->setVisible(true);
160 changes = focusResolver.setInputWindows(request.displayId, windows);
161 ASSERT_EQ(nullptr, changes->oldFocus);
162 ASSERT_EQ(invisibleWindowToken, changes->newFocus);
163}
164
165} // namespace android::inputdispatcher