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