1 /*
2 * Copyright (C) 2019 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 #include "InputTarget.h"
18
19 #include <android-base/logging.h>
20 #include <android-base/stringprintf.h>
21 #include <input/PrintTools.h>
22 #include <inttypes.h>
23 #include <string>
24
25 using android::base::Error;
26 using android::base::Result;
27 using android::base::StringPrintf;
28
29 namespace android::inputdispatcher {
30
31 namespace {
32
33 const static ui::Transform kIdentityTransform{};
34
35 }
36
InputTarget(const std::shared_ptr<Connection> & connection,ftl::Flags<Flags> flags)37 InputTarget::InputTarget(const std::shared_ptr<Connection>& connection, ftl::Flags<Flags> flags)
38 : connection(connection), flags(flags) {}
39
addPointers(std::bitset<MAX_POINTER_ID+1> newPointerIds,const ui::Transform & transform)40 Result<void> InputTarget::addPointers(std::bitset<MAX_POINTER_ID + 1> newPointerIds,
41 const ui::Transform& transform) {
42 // The pointerIds can be empty, but still a valid InputTarget. This can happen when there is no
43 // valid pointer property from the input event.
44 if (newPointerIds.none()) {
45 setDefaultPointerTransform(transform);
46 return {};
47 }
48
49 // Ensure that the new set of pointers doesn't overlap with the current set of pointers.
50 if ((getPointerIds() & newPointerIds).any()) {
51 return Error() << __func__ << " - overlap with incoming pointers "
52 << bitsetToString(newPointerIds) << " in " << *this;
53 }
54
55 for (auto& [existingTransform, existingPointers] : mPointerTransforms) {
56 if (transform == existingTransform) {
57 existingPointers |= newPointerIds;
58 return {};
59 }
60 }
61 mPointerTransforms.emplace_back(transform, newPointerIds);
62 return {};
63 }
64
setDefaultPointerTransform(const ui::Transform & transform)65 void InputTarget::setDefaultPointerTransform(const ui::Transform& transform) {
66 mPointerTransforms = {{transform, {}}};
67 }
68
useDefaultPointerTransform() const69 bool InputTarget::useDefaultPointerTransform() const {
70 return mPointerTransforms.size() <= 1;
71 }
72
getDefaultPointerTransform() const73 const ui::Transform& InputTarget::getDefaultPointerTransform() const {
74 if (!useDefaultPointerTransform()) {
75 LOG(FATAL) << __func__ << ": Not using default pointer transform";
76 }
77 return mPointerTransforms.size() == 1 ? mPointerTransforms[0].first : kIdentityTransform;
78 }
79
getTransformForPointer(int32_t pointerId) const80 const ui::Transform& InputTarget::getTransformForPointer(int32_t pointerId) const {
81 for (const auto& [transform, ids] : mPointerTransforms) {
82 if (ids.test(pointerId)) {
83 return transform;
84 }
85 }
86
87 LOG(FATAL) << __func__
88 << ": Cannot get transform: The following Pointer ID does not exist in target: "
89 << pointerId;
90 return kIdentityTransform;
91 }
92
getPointerInfoString() const93 std::string InputTarget::getPointerInfoString() const {
94 std::string out = "\n";
95 if (useDefaultPointerTransform()) {
96 const ui::Transform& transform = getDefaultPointerTransform();
97 transform.dump(out, "default", " ");
98 return out;
99 }
100
101 for (const auto& [transform, ids] : mPointerTransforms) {
102 const std::string name = "pointerIds " + bitsetToString(ids) + ":";
103 transform.dump(out, name.c_str(), " ");
104 }
105 return out;
106 }
107
getPointerIds() const108 std::bitset<MAX_POINTER_ID + 1> InputTarget::getPointerIds() const {
109 PointerIds allIds;
110 for (const auto& [_, ids] : mPointerTransforms) {
111 allIds |= ids;
112 }
113 return allIds;
114 }
115
operator <<(std::ostream & out,const InputTarget & target)116 std::ostream& operator<<(std::ostream& out, const InputTarget& target) {
117 out << "{connection=";
118 if (target.connection != nullptr) {
119 out << target.connection->getInputChannelName();
120 } else {
121 out << "<null>";
122 }
123 out << ", windowHandle=";
124 if (target.windowHandle != nullptr) {
125 out << target.windowHandle->getName();
126 } else {
127 out << "<null>";
128 }
129 out << ", dispatchMode=" << ftl::enum_string(target.dispatchMode).c_str();
130 out << ", targetFlags=" << target.flags.string();
131 out << ", pointers=" << target.getPointerInfoString();
132 out << "}";
133 return out;
134 }
135
136 } // namespace android::inputdispatcher
137