xref: /aosp_15_r20/frameworks/native/services/inputflinger/dispatcher/FocusResolver.h (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 
17*38e8c45fSAndroid Build Coastguard Worker #pragma once
18*38e8c45fSAndroid Build Coastguard Worker 
19*38e8c45fSAndroid Build Coastguard Worker #include <stdint.h>
20*38e8c45fSAndroid Build Coastguard Worker #include <optional>
21*38e8c45fSAndroid Build Coastguard Worker #include <unordered_map>
22*38e8c45fSAndroid Build Coastguard Worker 
23*38e8c45fSAndroid Build Coastguard Worker #include <android/gui/FocusRequest.h>
24*38e8c45fSAndroid Build Coastguard Worker #include <binder/Binder.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <gui/WindowInfo.h>
26*38e8c45fSAndroid Build Coastguard Worker 
27*38e8c45fSAndroid Build Coastguard Worker namespace android::inputdispatcher {
28*38e8c45fSAndroid Build Coastguard Worker 
29*38e8c45fSAndroid Build Coastguard Worker // Keeps track of the focused window per display. The class listens to updates from input dispatcher
30*38e8c45fSAndroid Build Coastguard Worker // and provides focus changes.
31*38e8c45fSAndroid Build Coastguard Worker //
32*38e8c45fSAndroid Build Coastguard Worker // Focus Policy
33*38e8c45fSAndroid Build Coastguard Worker //   Window focusabilty - A window token can be focused if there is at least one window handle that
34*38e8c45fSAndroid Build Coastguard Worker //   is visible with the same token and all window handles with the same token are focusable.
35*38e8c45fSAndroid Build Coastguard Worker //   See FocusResolver::isTokenFocusable
36*38e8c45fSAndroid Build Coastguard Worker //
37*38e8c45fSAndroid Build Coastguard Worker //   Focus request - Request will be granted if the window is focusable. If it's not
38*38e8c45fSAndroid Build Coastguard Worker //   focusable, then the request is persisted and granted when it becomes focusable. The currently
39*38e8c45fSAndroid Build Coastguard Worker //   focused window will lose focus and any pending keys will be added to a queue so it can be sent
40*38e8c45fSAndroid Build Coastguard Worker //   to the window when it gets focus.
41*38e8c45fSAndroid Build Coastguard Worker //
42*38e8c45fSAndroid Build Coastguard Worker //   Condition focus request - Request with a focus token specified. Request will be granted if the
43*38e8c45fSAndroid Build Coastguard Worker //   window is focusable and the focus token is the currently focused. Otherwise, the request is
44*38e8c45fSAndroid Build Coastguard Worker //   dropped. Conditional focus requests are not persisted. The window will lose focus and go back
45*38e8c45fSAndroid Build Coastguard Worker //   to the focus token if it becomes not focusable.
46*38e8c45fSAndroid Build Coastguard Worker //
47*38e8c45fSAndroid Build Coastguard Worker //   Window handle updates - Focus is lost when the currently focused window becomes not focusable.
48*38e8c45fSAndroid Build Coastguard Worker //   If the previous focus request is focusable, then we will try to grant that window focus.
49*38e8c45fSAndroid Build Coastguard Worker class FocusResolver {
50*38e8c45fSAndroid Build Coastguard Worker public:
51*38e8c45fSAndroid Build Coastguard Worker     // Returns the focused window token on the specified display.
52*38e8c45fSAndroid Build Coastguard Worker     sp<IBinder> getFocusedWindowToken(ui::LogicalDisplayId displayId) const;
53*38e8c45fSAndroid Build Coastguard Worker 
54*38e8c45fSAndroid Build Coastguard Worker     struct FocusChanges {
55*38e8c45fSAndroid Build Coastguard Worker         sp<IBinder> oldFocus;
56*38e8c45fSAndroid Build Coastguard Worker         sp<IBinder> newFocus;
57*38e8c45fSAndroid Build Coastguard Worker         ui::LogicalDisplayId displayId;
58*38e8c45fSAndroid Build Coastguard Worker         std::string reason;
59*38e8c45fSAndroid Build Coastguard Worker     };
60*38e8c45fSAndroid Build Coastguard Worker     std::optional<FocusResolver::FocusChanges> setInputWindows(
61*38e8c45fSAndroid Build Coastguard Worker             ui::LogicalDisplayId displayId,
62*38e8c45fSAndroid Build Coastguard Worker             const std::vector<sp<android::gui::WindowInfoHandle>>& windows);
63*38e8c45fSAndroid Build Coastguard Worker     std::optional<FocusResolver::FocusChanges> setFocusedWindow(
64*38e8c45fSAndroid Build Coastguard Worker             const android::gui::FocusRequest& request,
65*38e8c45fSAndroid Build Coastguard Worker             const std::vector<sp<android::gui::WindowInfoHandle>>& windows);
66*38e8c45fSAndroid Build Coastguard Worker 
67*38e8c45fSAndroid Build Coastguard Worker     // Display has been removed from the system, clean up old references.
68*38e8c45fSAndroid Build Coastguard Worker     void displayRemoved(ui::LogicalDisplayId displayId);
69*38e8c45fSAndroid Build Coastguard Worker 
70*38e8c45fSAndroid Build Coastguard Worker     // exposed for debugging
hasFocusedWindowTokens()71*38e8c45fSAndroid Build Coastguard Worker     bool hasFocusedWindowTokens() const { return !mFocusedWindowTokenByDisplay.empty(); }
72*38e8c45fSAndroid Build Coastguard Worker     std::string dumpFocusedWindows() const;
73*38e8c45fSAndroid Build Coastguard Worker     std::string dump() const;
74*38e8c45fSAndroid Build Coastguard Worker 
75*38e8c45fSAndroid Build Coastguard Worker private:
76*38e8c45fSAndroid Build Coastguard Worker     enum class Focusability {
77*38e8c45fSAndroid Build Coastguard Worker         OK,
78*38e8c45fSAndroid Build Coastguard Worker         NO_WINDOW,
79*38e8c45fSAndroid Build Coastguard Worker         NOT_FOCUSABLE,
80*38e8c45fSAndroid Build Coastguard Worker         NOT_VISIBLE,
81*38e8c45fSAndroid Build Coastguard Worker 
82*38e8c45fSAndroid Build Coastguard Worker         ftl_last = NOT_VISIBLE
83*38e8c45fSAndroid Build Coastguard Worker     };
84*38e8c45fSAndroid Build Coastguard Worker 
85*38e8c45fSAndroid Build Coastguard Worker     // Checks if the window token can be focused on a display. The token can be focused if there is
86*38e8c45fSAndroid Build Coastguard Worker     // at least one window handle that is visible with the same token and all window handles with
87*38e8c45fSAndroid Build Coastguard Worker     // the same token are focusable.
88*38e8c45fSAndroid Build Coastguard Worker     //
89*38e8c45fSAndroid Build Coastguard Worker     // In the case of mirroring, two windows may share the same window token and their visibility
90*38e8c45fSAndroid Build Coastguard Worker     // might be different. Example, the mirrored window can cover the window its mirroring. However,
91*38e8c45fSAndroid Build Coastguard Worker     // we expect the focusability of the windows to match since its hard to reason why one window
92*38e8c45fSAndroid Build Coastguard Worker     // can receive focus events and the other cannot when both are backed by the same input channel.
93*38e8c45fSAndroid Build Coastguard Worker     //
94*38e8c45fSAndroid Build Coastguard Worker     static Focusability isTokenFocusable(
95*38e8c45fSAndroid Build Coastguard Worker             const sp<IBinder>& token,
96*38e8c45fSAndroid Build Coastguard Worker             const std::vector<sp<android::gui::WindowInfoHandle>>& windows,
97*38e8c45fSAndroid Build Coastguard Worker             sp<android::gui::WindowInfoHandle>& outFocusableWindow);
98*38e8c45fSAndroid Build Coastguard Worker 
99*38e8c45fSAndroid Build Coastguard Worker     static FocusResolver::Focusability getResolvedFocusWindow(
100*38e8c45fSAndroid Build Coastguard Worker             const sp<IBinder>& token,
101*38e8c45fSAndroid Build Coastguard Worker             const std::vector<sp<android::gui::WindowInfoHandle>>& windows,
102*38e8c45fSAndroid Build Coastguard Worker             sp<android::gui::WindowInfoHandle>& outFocusableWindow);
103*38e8c45fSAndroid Build Coastguard Worker 
104*38e8c45fSAndroid Build Coastguard Worker     // Focus tracking for keys, trackball, etc. A window token can be associated with one or
105*38e8c45fSAndroid Build Coastguard Worker     // more InputWindowHandles. If a window is mirrored, the window and its mirror will share
106*38e8c45fSAndroid Build Coastguard Worker     // the same token. Focus is tracked by the token per display and the events are dispatched
107*38e8c45fSAndroid Build Coastguard Worker     // to the channel associated by this token.
108*38e8c45fSAndroid Build Coastguard Worker     typedef std::pair<std::string /* name */, sp<IBinder>> NamedToken;
109*38e8c45fSAndroid Build Coastguard Worker     std::unordered_map<ui::LogicalDisplayId /* displayId */, NamedToken>
110*38e8c45fSAndroid Build Coastguard Worker             mFocusedWindowTokenByDisplay;
111*38e8c45fSAndroid Build Coastguard Worker 
112*38e8c45fSAndroid Build Coastguard Worker     // This map will store the focus request per display. When the input window handles are updated,
113*38e8c45fSAndroid Build Coastguard Worker     // the current request will be checked to see if it can be processed at that time.
114*38e8c45fSAndroid Build Coastguard Worker     std::unordered_map<ui::LogicalDisplayId /* displayId */, android::gui::FocusRequest>
115*38e8c45fSAndroid Build Coastguard Worker             mFocusRequestByDisplay;
116*38e8c45fSAndroid Build Coastguard Worker 
117*38e8c45fSAndroid Build Coastguard Worker     // Last reason for not granting a focus request. This is used to add more debug information
118*38e8c45fSAndroid Build Coastguard Worker     // in the event logs.
119*38e8c45fSAndroid Build Coastguard Worker     std::unordered_map<ui::LogicalDisplayId /* displayId */, Focusability>
120*38e8c45fSAndroid Build Coastguard Worker             mLastFocusResultByDisplay;
121*38e8c45fSAndroid Build Coastguard Worker 
122*38e8c45fSAndroid Build Coastguard Worker     std::optional<FocusResolver::FocusChanges> updateFocusedWindow(
123*38e8c45fSAndroid Build Coastguard Worker             ui::LogicalDisplayId displayId, const std::string& reason, const sp<IBinder>& token,
124*38e8c45fSAndroid Build Coastguard Worker             const std::string& tokenName = "");
125*38e8c45fSAndroid Build Coastguard Worker     std::optional<android::gui::FocusRequest> getFocusRequest(ui::LogicalDisplayId displayId);
126*38e8c45fSAndroid Build Coastguard Worker };
127*38e8c45fSAndroid Build Coastguard Worker 
128*38e8c45fSAndroid Build Coastguard Worker } // namespace android::inputdispatcher
129