blob: e067ad9f373ad0d662064eb088f5fe1755c205c1 [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#pragma once
18
19#include <stdint.h>
20#include <optional>
21#include <unordered_map>
22
23#include <android/FocusRequest.h>
24#include <binder/Binder.h>
25#include <input/InputWindow.h>
26
27namespace 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 the window is not
38// visible, then the request is kept in a pending state and granted when it becomes visible.
39// If window becomes not focusable, or another request comes in, the pending request is dropped.
40//
41// Window handle updates - Focus is lost when the currently focused window becomes not focusable.
42class FocusResolver {
43public:
44 // Returns the focused window token on the specified display.
45 sp<IBinder> getFocusedWindowToken(int32_t displayId) const;
46
47 struct FocusChanges {
48 sp<IBinder> oldFocus;
49 sp<IBinder> newFocus;
50 int32_t displayId;
51 std::string reason;
52 };
53 std::optional<FocusResolver::FocusChanges> setInputWindows(
54 int32_t displayId, const std::vector<sp<InputWindowHandle>>& windows);
55 std::optional<FocusResolver::FocusChanges> setFocusedWindow(
56 const FocusRequest& request, const std::vector<sp<InputWindowHandle>>& windows);
57
58 // exposed for debugging
59 bool hasFocusedWindowTokens() const { return !mFocusedWindowTokenByDisplay.empty(); }
60 std::string dumpFocusedWindows() const;
61 std::string dump() const;
62
63private:
64 enum class FocusResult {
65 OK,
66 NO_WINDOW,
67 NOT_FOCUSABLE,
68 NOT_VISIBLE,
69 };
70
71 // Checks if the window token can be focused on a display. The token can be focused if there is
72 // at least one window handle that is visible with the same token and all window handles with
73 // the same token are focusable.
74 //
75 // In the case of mirroring, two windows may share the same window token and their visibility
76 // might be different. Example, the mirrored window can cover the window its mirroring. However,
77 // we expect the focusability of the windows to match since its hard to reason why one window
78 // can receive focus events and the other cannot when both are backed by the same input channel.
79 //
80 static FocusResult isTokenFocusable(const sp<IBinder>& token,
81 const std::vector<sp<InputWindowHandle>>& windows);
82
83 // Focus tracking for keys, trackball, etc. A window token can be associated with one or
84 // more InputWindowHandles. If a window is mirrored, the window and its mirror will share
85 // the same token. Focus is tracked by the token per display and the events are dispatched
86 // to the channel associated by this token.
87 typedef std::pair<std::string /* name */, sp<IBinder>> NamedToken;
88 std::unordered_map<int32_t /* displayId */, NamedToken> mFocusedWindowTokenByDisplay;
89
90 // This map will store a single pending focus request per display that cannot be currently
91 // processed. This can happen if the window requested to be focused is not currently visible.
92 // Such a window might become visible later, and these requests would be processed at that time.
93 std::unordered_map<int32_t /* displayId */, FocusRequest> mPendingFocusRequests;
94
95 std::optional<FocusResolver::FocusChanges> updateFocusedWindow(
96 int32_t displayId, const std::string& reason, const sp<IBinder>& token,
97 const std::string& tokenName = "");
98 std::optional<FocusRequest> getPendingRequest(int32_t displayId);
99};
100
101} // namespace android::inputdispatcher