xref: /aosp_15_r20/frameworks/native/services/inputflinger/dispatcher/FocusResolver.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker  * Copyright (C) 2021 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker  *
4*38e8c45fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker  *
8*38e8c45fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker  *
10*38e8c45fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker  * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker  */
16*38e8c45fSAndroid Build Coastguard Worker #include <optional>
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "InputDispatcher"
18*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_INPUT
19*38e8c45fSAndroid Build Coastguard Worker 
20*38e8c45fSAndroid Build Coastguard Worker #define INDENT "  "
21*38e8c45fSAndroid Build Coastguard Worker #define INDENT2 "    "
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker #include <inttypes.h>
24*38e8c45fSAndroid Build Coastguard Worker 
25*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <binder/Binder.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <ftl/enum.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <gui/WindowInfo.h>
29*38e8c45fSAndroid Build Coastguard Worker #include <unordered_set>
30*38e8c45fSAndroid Build Coastguard Worker 
31*38e8c45fSAndroid Build Coastguard Worker #include "DebugConfig.h"
32*38e8c45fSAndroid Build Coastguard Worker #include "FocusResolver.h"
33*38e8c45fSAndroid Build Coastguard Worker 
34*38e8c45fSAndroid Build Coastguard Worker using android::gui::FocusRequest;
35*38e8c45fSAndroid Build Coastguard Worker using android::gui::WindowInfoHandle;
36*38e8c45fSAndroid Build Coastguard Worker 
37*38e8c45fSAndroid Build Coastguard Worker namespace android::inputdispatcher {
38*38e8c45fSAndroid Build Coastguard Worker 
39*38e8c45fSAndroid Build Coastguard Worker template <typename T>
40*38e8c45fSAndroid Build Coastguard Worker struct SpHash {
operator ()android::inputdispatcher::SpHash41*38e8c45fSAndroid Build Coastguard Worker     size_t operator()(const sp<T>& k) const { return std::hash<T*>()(k.get()); }
42*38e8c45fSAndroid Build Coastguard Worker };
43*38e8c45fSAndroid Build Coastguard Worker 
getFocusedWindowToken(ui::LogicalDisplayId displayId) const44*38e8c45fSAndroid Build Coastguard Worker sp<IBinder> FocusResolver::getFocusedWindowToken(ui::LogicalDisplayId displayId) const {
45*38e8c45fSAndroid Build Coastguard Worker     auto it = mFocusedWindowTokenByDisplay.find(displayId);
46*38e8c45fSAndroid Build Coastguard Worker     return it != mFocusedWindowTokenByDisplay.end() ? it->second.second : nullptr;
47*38e8c45fSAndroid Build Coastguard Worker }
48*38e8c45fSAndroid Build Coastguard Worker 
getFocusRequest(ui::LogicalDisplayId displayId)49*38e8c45fSAndroid Build Coastguard Worker std::optional<FocusRequest> FocusResolver::getFocusRequest(ui::LogicalDisplayId displayId) {
50*38e8c45fSAndroid Build Coastguard Worker     auto it = mFocusRequestByDisplay.find(displayId);
51*38e8c45fSAndroid Build Coastguard Worker     return it != mFocusRequestByDisplay.end() ? std::make_optional<>(it->second) : std::nullopt;
52*38e8c45fSAndroid Build Coastguard Worker }
53*38e8c45fSAndroid Build Coastguard Worker 
54*38e8c45fSAndroid Build Coastguard Worker /**
55*38e8c45fSAndroid Build Coastguard Worker  * 'setInputWindows' is called when the window properties change. Here we will check whether the
56*38e8c45fSAndroid Build Coastguard Worker  * currently focused window can remain focused. If the currently focused window remains eligible
57*38e8c45fSAndroid Build Coastguard Worker  * for focus ('isTokenFocusable' returns OK), then we will continue to grant it focus otherwise
58*38e8c45fSAndroid Build Coastguard Worker  * we will check if the previous focus request is eligible to receive focus.
59*38e8c45fSAndroid Build Coastguard Worker  */
setInputWindows(ui::LogicalDisplayId displayId,const std::vector<sp<WindowInfoHandle>> & windows)60*38e8c45fSAndroid Build Coastguard Worker std::optional<FocusResolver::FocusChanges> FocusResolver::setInputWindows(
61*38e8c45fSAndroid Build Coastguard Worker         ui::LogicalDisplayId displayId, const std::vector<sp<WindowInfoHandle>>& windows) {
62*38e8c45fSAndroid Build Coastguard Worker     std::string removeFocusReason;
63*38e8c45fSAndroid Build Coastguard Worker 
64*38e8c45fSAndroid Build Coastguard Worker     const std::optional<FocusRequest> request = getFocusRequest(displayId);
65*38e8c45fSAndroid Build Coastguard Worker     const sp<IBinder> currentFocus = getFocusedWindowToken(displayId);
66*38e8c45fSAndroid Build Coastguard Worker 
67*38e8c45fSAndroid Build Coastguard Worker     // Find the next focused token based on the latest FocusRequest. If the requested focus window
68*38e8c45fSAndroid Build Coastguard Worker     // cannot be focused, focus will be removed.
69*38e8c45fSAndroid Build Coastguard Worker     if (request) {
70*38e8c45fSAndroid Build Coastguard Worker         sp<IBinder> requestedFocus = request->token;
71*38e8c45fSAndroid Build Coastguard Worker         sp<WindowInfoHandle> resolvedFocusWindow;
72*38e8c45fSAndroid Build Coastguard Worker         Focusability result = getResolvedFocusWindow(requestedFocus, windows, resolvedFocusWindow);
73*38e8c45fSAndroid Build Coastguard Worker         if (result == Focusability::OK && resolvedFocusWindow->getToken() == currentFocus) {
74*38e8c45fSAndroid Build Coastguard Worker             return std::nullopt;
75*38e8c45fSAndroid Build Coastguard Worker         }
76*38e8c45fSAndroid Build Coastguard Worker         const Focusability previousResult = mLastFocusResultByDisplay[displayId];
77*38e8c45fSAndroid Build Coastguard Worker         mLastFocusResultByDisplay[displayId] = result;
78*38e8c45fSAndroid Build Coastguard Worker         if (result == Focusability::OK) {
79*38e8c45fSAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL_IF(!resolvedFocusWindow,
80*38e8c45fSAndroid Build Coastguard Worker                                 "Focused window should be non-null when result is OK!");
81*38e8c45fSAndroid Build Coastguard Worker             return updateFocusedWindow(displayId,
82*38e8c45fSAndroid Build Coastguard Worker                                        "Window became focusable. Previous reason: " +
83*38e8c45fSAndroid Build Coastguard Worker                                                ftl::enum_string(previousResult),
84*38e8c45fSAndroid Build Coastguard Worker                                        resolvedFocusWindow->getToken(),
85*38e8c45fSAndroid Build Coastguard Worker                                        resolvedFocusWindow->getName());
86*38e8c45fSAndroid Build Coastguard Worker         }
87*38e8c45fSAndroid Build Coastguard Worker         removeFocusReason = ftl::enum_string(result);
88*38e8c45fSAndroid Build Coastguard Worker     }
89*38e8c45fSAndroid Build Coastguard Worker 
90*38e8c45fSAndroid Build Coastguard Worker     // Focused window is no longer focusable and we don't have a suitable focus request to grant.
91*38e8c45fSAndroid Build Coastguard Worker     // Remove focus if needed.
92*38e8c45fSAndroid Build Coastguard Worker     return updateFocusedWindow(displayId, removeFocusReason, nullptr);
93*38e8c45fSAndroid Build Coastguard Worker }
94*38e8c45fSAndroid Build Coastguard Worker 
setFocusedWindow(const FocusRequest & request,const std::vector<sp<WindowInfoHandle>> & windows)95*38e8c45fSAndroid Build Coastguard Worker std::optional<FocusResolver::FocusChanges> FocusResolver::setFocusedWindow(
96*38e8c45fSAndroid Build Coastguard Worker         const FocusRequest& request, const std::vector<sp<WindowInfoHandle>>& windows) {
97*38e8c45fSAndroid Build Coastguard Worker     const ui::LogicalDisplayId displayId = ui::LogicalDisplayId{request.displayId};
98*38e8c45fSAndroid Build Coastguard Worker     const sp<IBinder> currentFocus = getFocusedWindowToken(displayId);
99*38e8c45fSAndroid Build Coastguard Worker     if (currentFocus == request.token) {
100*38e8c45fSAndroid Build Coastguard Worker         ALOGD_IF(DEBUG_FOCUS, "setFocusedWindow %s on display %s ignored, reason: already focused",
101*38e8c45fSAndroid Build Coastguard Worker                  request.windowName.c_str(), displayId.toString().c_str());
102*38e8c45fSAndroid Build Coastguard Worker         return std::nullopt;
103*38e8c45fSAndroid Build Coastguard Worker     }
104*38e8c45fSAndroid Build Coastguard Worker 
105*38e8c45fSAndroid Build Coastguard Worker     sp<WindowInfoHandle> resolvedFocusWindow;
106*38e8c45fSAndroid Build Coastguard Worker     Focusability result = getResolvedFocusWindow(request.token, windows, resolvedFocusWindow);
107*38e8c45fSAndroid Build Coastguard Worker     // Update focus request. The focus resolver will always try to handle this request if there is
108*38e8c45fSAndroid Build Coastguard Worker     // no focused window on the display.
109*38e8c45fSAndroid Build Coastguard Worker     mFocusRequestByDisplay[displayId] = request;
110*38e8c45fSAndroid Build Coastguard Worker     mLastFocusResultByDisplay[displayId] = result;
111*38e8c45fSAndroid Build Coastguard Worker 
112*38e8c45fSAndroid Build Coastguard Worker     if (result == Focusability::OK) {
113*38e8c45fSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(!resolvedFocusWindow,
114*38e8c45fSAndroid Build Coastguard Worker                             "Focused window should be non-null when result is OK!");
115*38e8c45fSAndroid Build Coastguard Worker         return updateFocusedWindow(displayId, "setFocusedWindow", resolvedFocusWindow->getToken(),
116*38e8c45fSAndroid Build Coastguard Worker                                    resolvedFocusWindow->getName());
117*38e8c45fSAndroid Build Coastguard Worker     }
118*38e8c45fSAndroid Build Coastguard Worker 
119*38e8c45fSAndroid Build Coastguard Worker     // The requested window is not currently focusable. Wait for the window to become focusable
120*38e8c45fSAndroid Build Coastguard Worker     // but remove focus from the current window so that input events can go into a pending queue
121*38e8c45fSAndroid Build Coastguard Worker     // and be sent to the window when it becomes focused.
122*38e8c45fSAndroid Build Coastguard Worker     return updateFocusedWindow(displayId, "Waiting for window because " + ftl::enum_string(result),
123*38e8c45fSAndroid Build Coastguard Worker                                nullptr);
124*38e8c45fSAndroid Build Coastguard Worker }
125*38e8c45fSAndroid Build Coastguard Worker 
getResolvedFocusWindow(const sp<IBinder> & token,const std::vector<sp<WindowInfoHandle>> & windows,sp<WindowInfoHandle> & outFocusableWindow)126*38e8c45fSAndroid Build Coastguard Worker FocusResolver::Focusability FocusResolver::getResolvedFocusWindow(
127*38e8c45fSAndroid Build Coastguard Worker         const sp<IBinder>& token, const std::vector<sp<WindowInfoHandle>>& windows,
128*38e8c45fSAndroid Build Coastguard Worker         sp<WindowInfoHandle>& outFocusableWindow) {
129*38e8c45fSAndroid Build Coastguard Worker     sp<IBinder> curFocusCandidate = token;
130*38e8c45fSAndroid Build Coastguard Worker     bool focusedWindowFound = false;
131*38e8c45fSAndroid Build Coastguard Worker 
132*38e8c45fSAndroid Build Coastguard Worker     // Keep track of all windows reached to prevent a cyclical transferFocus request.
133*38e8c45fSAndroid Build Coastguard Worker     std::unordered_set<sp<IBinder>, SpHash<IBinder>> tokensReached;
134*38e8c45fSAndroid Build Coastguard Worker 
135*38e8c45fSAndroid Build Coastguard Worker     while (curFocusCandidate != nullptr && tokensReached.count(curFocusCandidate) == 0) {
136*38e8c45fSAndroid Build Coastguard Worker         tokensReached.emplace(curFocusCandidate);
137*38e8c45fSAndroid Build Coastguard Worker         Focusability result = isTokenFocusable(curFocusCandidate, windows, outFocusableWindow);
138*38e8c45fSAndroid Build Coastguard Worker         if (result == Focusability::OK) {
139*38e8c45fSAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL_IF(!outFocusableWindow,
140*38e8c45fSAndroid Build Coastguard Worker                                 "Focused window should be non-null when result is OK!");
141*38e8c45fSAndroid Build Coastguard Worker             focusedWindowFound = true;
142*38e8c45fSAndroid Build Coastguard Worker             // outFocusableWindow has been updated by isTokenFocusable to contain
143*38e8c45fSAndroid Build Coastguard Worker             // the window info for curFocusCandidate. See if we can grant focus
144*38e8c45fSAndroid Build Coastguard Worker             // to the token that it wants to transfer its focus to.
145*38e8c45fSAndroid Build Coastguard Worker             curFocusCandidate = outFocusableWindow->getInfo()->focusTransferTarget;
146*38e8c45fSAndroid Build Coastguard Worker         }
147*38e8c45fSAndroid Build Coastguard Worker 
148*38e8c45fSAndroid Build Coastguard Worker         // If the initial token is not focusable, return early with the failed result.
149*38e8c45fSAndroid Build Coastguard Worker         if (!focusedWindowFound) {
150*38e8c45fSAndroid Build Coastguard Worker             return result;
151*38e8c45fSAndroid Build Coastguard Worker         }
152*38e8c45fSAndroid Build Coastguard Worker     }
153*38e8c45fSAndroid Build Coastguard Worker 
154*38e8c45fSAndroid Build Coastguard Worker     return focusedWindowFound ? Focusability::OK : Focusability::NO_WINDOW;
155*38e8c45fSAndroid Build Coastguard Worker }
156*38e8c45fSAndroid Build Coastguard Worker 
isTokenFocusable(const sp<IBinder> & token,const std::vector<sp<WindowInfoHandle>> & windows,sp<WindowInfoHandle> & outFocusableWindow)157*38e8c45fSAndroid Build Coastguard Worker FocusResolver::Focusability FocusResolver::isTokenFocusable(
158*38e8c45fSAndroid Build Coastguard Worker         const sp<IBinder>& token, const std::vector<sp<WindowInfoHandle>>& windows,
159*38e8c45fSAndroid Build Coastguard Worker         sp<WindowInfoHandle>& outFocusableWindow) {
160*38e8c45fSAndroid Build Coastguard Worker     bool allWindowsAreFocusable = true;
161*38e8c45fSAndroid Build Coastguard Worker     bool windowFound = false;
162*38e8c45fSAndroid Build Coastguard Worker     sp<WindowInfoHandle> visibleWindowHandle = nullptr;
163*38e8c45fSAndroid Build Coastguard Worker     for (const sp<WindowInfoHandle>& window : windows) {
164*38e8c45fSAndroid Build Coastguard Worker         if (window->getToken() != token) {
165*38e8c45fSAndroid Build Coastguard Worker             continue;
166*38e8c45fSAndroid Build Coastguard Worker         }
167*38e8c45fSAndroid Build Coastguard Worker         windowFound = true;
168*38e8c45fSAndroid Build Coastguard Worker         if (!window->getInfo()->inputConfig.test(gui::WindowInfo::InputConfig::NOT_VISIBLE)) {
169*38e8c45fSAndroid Build Coastguard Worker             // Check if at least a single window is visible.
170*38e8c45fSAndroid Build Coastguard Worker             visibleWindowHandle = window;
171*38e8c45fSAndroid Build Coastguard Worker         }
172*38e8c45fSAndroid Build Coastguard Worker         if (window->getInfo()->inputConfig.test(gui::WindowInfo::InputConfig::NOT_FOCUSABLE)) {
173*38e8c45fSAndroid Build Coastguard Worker             // Check if all windows with the window token are focusable.
174*38e8c45fSAndroid Build Coastguard Worker             allWindowsAreFocusable = false;
175*38e8c45fSAndroid Build Coastguard Worker             break;
176*38e8c45fSAndroid Build Coastguard Worker         }
177*38e8c45fSAndroid Build Coastguard Worker     }
178*38e8c45fSAndroid Build Coastguard Worker 
179*38e8c45fSAndroid Build Coastguard Worker     if (!windowFound) {
180*38e8c45fSAndroid Build Coastguard Worker         return Focusability::NO_WINDOW;
181*38e8c45fSAndroid Build Coastguard Worker     }
182*38e8c45fSAndroid Build Coastguard Worker     if (!allWindowsAreFocusable) {
183*38e8c45fSAndroid Build Coastguard Worker         return Focusability::NOT_FOCUSABLE;
184*38e8c45fSAndroid Build Coastguard Worker     }
185*38e8c45fSAndroid Build Coastguard Worker     if (!visibleWindowHandle) {
186*38e8c45fSAndroid Build Coastguard Worker         return Focusability::NOT_VISIBLE;
187*38e8c45fSAndroid Build Coastguard Worker     }
188*38e8c45fSAndroid Build Coastguard Worker 
189*38e8c45fSAndroid Build Coastguard Worker     // Only set the outFoundWindow if the window can be focused
190*38e8c45fSAndroid Build Coastguard Worker     outFocusableWindow = visibleWindowHandle;
191*38e8c45fSAndroid Build Coastguard Worker     return Focusability::OK;
192*38e8c45fSAndroid Build Coastguard Worker }
193*38e8c45fSAndroid Build Coastguard Worker 
updateFocusedWindow(ui::LogicalDisplayId displayId,const std::string & reason,const sp<IBinder> & newFocus,const std::string & tokenName)194*38e8c45fSAndroid Build Coastguard Worker std::optional<FocusResolver::FocusChanges> FocusResolver::updateFocusedWindow(
195*38e8c45fSAndroid Build Coastguard Worker         ui::LogicalDisplayId displayId, const std::string& reason, const sp<IBinder>& newFocus,
196*38e8c45fSAndroid Build Coastguard Worker         const std::string& tokenName) {
197*38e8c45fSAndroid Build Coastguard Worker     sp<IBinder> oldFocus = getFocusedWindowToken(displayId);
198*38e8c45fSAndroid Build Coastguard Worker     if (newFocus == oldFocus) {
199*38e8c45fSAndroid Build Coastguard Worker         return std::nullopt;
200*38e8c45fSAndroid Build Coastguard Worker     }
201*38e8c45fSAndroid Build Coastguard Worker     if (newFocus) {
202*38e8c45fSAndroid Build Coastguard Worker         mFocusedWindowTokenByDisplay[displayId] = {tokenName, newFocus};
203*38e8c45fSAndroid Build Coastguard Worker     } else {
204*38e8c45fSAndroid Build Coastguard Worker         mFocusedWindowTokenByDisplay.erase(displayId);
205*38e8c45fSAndroid Build Coastguard Worker     }
206*38e8c45fSAndroid Build Coastguard Worker 
207*38e8c45fSAndroid Build Coastguard Worker     return {{oldFocus, newFocus, displayId, reason}};
208*38e8c45fSAndroid Build Coastguard Worker }
209*38e8c45fSAndroid Build Coastguard Worker 
dumpFocusedWindows() const210*38e8c45fSAndroid Build Coastguard Worker std::string FocusResolver::dumpFocusedWindows() const {
211*38e8c45fSAndroid Build Coastguard Worker     if (mFocusedWindowTokenByDisplay.empty()) {
212*38e8c45fSAndroid Build Coastguard Worker         return INDENT "FocusedWindows: <none>\n";
213*38e8c45fSAndroid Build Coastguard Worker     }
214*38e8c45fSAndroid Build Coastguard Worker 
215*38e8c45fSAndroid Build Coastguard Worker     std::string dump;
216*38e8c45fSAndroid Build Coastguard Worker     dump += INDENT "FocusedWindows:\n";
217*38e8c45fSAndroid Build Coastguard Worker     for (const auto& [displayId, namedToken] : mFocusedWindowTokenByDisplay) {
218*38e8c45fSAndroid Build Coastguard Worker         dump += base::StringPrintf(INDENT2 "displayId=%s, name='%s'\n",
219*38e8c45fSAndroid Build Coastguard Worker                                    displayId.toString().c_str(), namedToken.first.c_str());
220*38e8c45fSAndroid Build Coastguard Worker     }
221*38e8c45fSAndroid Build Coastguard Worker     return dump;
222*38e8c45fSAndroid Build Coastguard Worker }
223*38e8c45fSAndroid Build Coastguard Worker 
dump() const224*38e8c45fSAndroid Build Coastguard Worker std::string FocusResolver::dump() const {
225*38e8c45fSAndroid Build Coastguard Worker     std::string dump = dumpFocusedWindows();
226*38e8c45fSAndroid Build Coastguard Worker     if (mFocusRequestByDisplay.empty()) {
227*38e8c45fSAndroid Build Coastguard Worker         return dump + INDENT "FocusRequests: <none>\n";
228*38e8c45fSAndroid Build Coastguard Worker     }
229*38e8c45fSAndroid Build Coastguard Worker 
230*38e8c45fSAndroid Build Coastguard Worker     dump += INDENT "FocusRequests:\n";
231*38e8c45fSAndroid Build Coastguard Worker     for (const auto& [displayId, request] : mFocusRequestByDisplay) {
232*38e8c45fSAndroid Build Coastguard Worker         auto it = mLastFocusResultByDisplay.find(displayId);
233*38e8c45fSAndroid Build Coastguard Worker         std::string result =
234*38e8c45fSAndroid Build Coastguard Worker                 it != mLastFocusResultByDisplay.end() ? ftl::enum_string(it->second) : "";
235*38e8c45fSAndroid Build Coastguard Worker         dump += base::StringPrintf(INDENT2 "displayId=%s, name='%s' result='%s'\n",
236*38e8c45fSAndroid Build Coastguard Worker                                    displayId.toString().c_str(), request.windowName.c_str(),
237*38e8c45fSAndroid Build Coastguard Worker                                    result.c_str());
238*38e8c45fSAndroid Build Coastguard Worker     }
239*38e8c45fSAndroid Build Coastguard Worker     return dump;
240*38e8c45fSAndroid Build Coastguard Worker }
241*38e8c45fSAndroid Build Coastguard Worker 
displayRemoved(ui::LogicalDisplayId displayId)242*38e8c45fSAndroid Build Coastguard Worker void FocusResolver::displayRemoved(ui::LogicalDisplayId displayId) {
243*38e8c45fSAndroid Build Coastguard Worker     mFocusRequestByDisplay.erase(displayId);
244*38e8c45fSAndroid Build Coastguard Worker     mLastFocusResultByDisplay.erase(displayId);
245*38e8c45fSAndroid Build Coastguard Worker }
246*38e8c45fSAndroid Build Coastguard Worker 
247*38e8c45fSAndroid Build Coastguard Worker } // namespace android::inputdispatcher
248