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