• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 #define LOG_TAG "WindowInfo"
18 #define LOG_NDEBUG 0
19 
20 #include <type_traits>
21 
22 #include <binder/Parcel.h>
23 #include <gui/WindowInfo.h>
24 
25 #include <log/log.h>
26 
27 namespace android::gui {
28 
29 namespace {
30 
operator <<(std::ostream & out,const sp<IBinder> & binder)31 std::ostream& operator<<(std::ostream& out, const sp<IBinder>& binder) {
32     if (binder == nullptr) {
33         out << "<null>";
34     } else {
35         out << binder.get();
36     }
37     return out;
38 }
39 
operator <<(std::ostream & out,const Region & region)40 std::ostream& operator<<(std::ostream& out, const Region& region) {
41     if (region.isEmpty()) {
42         out << "<empty>";
43         return out;
44     }
45 
46     bool first = true;
47     Region::const_iterator cur = region.begin();
48     Region::const_iterator const tail = region.end();
49     while (cur != tail) {
50         if (first) {
51             first = false;
52         } else {
53             out << "|";
54         }
55         out << "[" << cur->left << "," << cur->top << "][" << cur->right << "," << cur->bottom
56             << "]";
57         cur++;
58     }
59     return out;
60 }
61 
writeTransform(android::Parcel * parcel,const ui::Transform & transform)62 status_t writeTransform(android::Parcel* parcel, const ui::Transform& transform) {
63     return parcel->writeFloat(transform.dsdx()) ?:
64             parcel->writeFloat(transform.dtdx()) ?:
65             parcel->writeFloat(transform.tx()) ?:
66             parcel->writeFloat(transform.dtdy()) ?:
67             parcel->writeFloat(transform.dsdy()) ?:
68             parcel->writeFloat(transform.ty());
69 }
70 
readTransform(const android::Parcel * parcel,ui::Transform & transform)71 status_t readTransform(const android::Parcel* parcel, ui::Transform& transform) {
72     float dsdx, dtdx, tx, dtdy, dsdy, ty;
73 
74     const status_t status = parcel->readFloat(&dsdx) ?:
75             parcel->readFloat(&dtdx) ?:
76             parcel->readFloat(&tx) ?:
77             parcel->readFloat(&dtdy) ?:
78             parcel->readFloat(&dsdy) ?:
79             parcel->readFloat(&ty);
80     if (status != OK) {
81         return status;
82     }
83 
84     transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
85     return OK;
86 }
87 
88 } // namespace
89 
setInputConfig(ftl::Flags<InputConfig> config,bool value)90 void WindowInfo::setInputConfig(ftl::Flags<InputConfig> config, bool value) {
91     if (value) {
92         inputConfig |= config;
93         return;
94     }
95     inputConfig &= ~config;
96 }
97 
addTouchableRegion(const Rect & region)98 void WindowInfo::addTouchableRegion(const Rect& region) {
99     touchableRegion.orSelf(region);
100 }
101 
isSpy() const102 bool WindowInfo::isSpy() const {
103     return inputConfig.test(InputConfig::SPY);
104 }
105 
interceptsStylus() const106 bool WindowInfo::interceptsStylus() const {
107     return inputConfig.test(InputConfig::INTERCEPTS_STYLUS);
108 }
109 
overlaps(const WindowInfo * other) const110 bool WindowInfo::overlaps(const WindowInfo* other) const {
111     return !frame.isEmpty() && frame.left < other->frame.right && frame.right > other->frame.left &&
112             frame.top < other->frame.bottom && frame.bottom > other->frame.top;
113 }
114 
operator ==(const WindowInfo & info) const115 bool WindowInfo::operator==(const WindowInfo& info) const {
116     return info.token == token && info.id == id && info.name == name &&
117             info.dispatchingTimeout == dispatchingTimeout && info.frame == frame &&
118             info.contentSize == contentSize && info.surfaceInset == surfaceInset &&
119             info.globalScaleFactor == globalScaleFactor && info.transform == transform &&
120             info.touchableRegion.hasSameRects(touchableRegion) &&
121             info.touchOcclusionMode == touchOcclusionMode && info.ownerPid == ownerPid &&
122             info.ownerUid == ownerUid && info.packageName == packageName &&
123             info.inputConfig == inputConfig && info.displayId == displayId &&
124             info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
125             info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType &&
126             info.layoutParamsFlags == layoutParamsFlags &&
127             info.canOccludePresentation == canOccludePresentation;
128 }
129 
writeToParcel(android::Parcel * parcel) const130 status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
131     if (parcel == nullptr) {
132         ALOGE("%s: Null parcel", __func__);
133         return BAD_VALUE;
134     }
135     if (name.empty()) {
136         parcel->writeInt32(0);
137         return OK;
138     }
139     parcel->writeInt32(1);
140 
141     // Ensure that the size of custom types are what we expect for writing into the parcel.
142     static_assert(sizeof(inputConfig) == 4u);
143     static_assert(sizeof(ownerPid.val()) == 4u);
144     static_assert(sizeof(ownerUid.val()) == 4u);
145 
146     // clang-format off
147     status_t status = parcel->writeStrongBinder(token) ?:
148         parcel->writeInt64(dispatchingTimeout.count()) ?:
149         parcel->writeInt32(id) ?:
150         parcel->writeUtf8AsUtf16(name) ?:
151         parcel->writeInt32(layoutParamsFlags.get()) ?:
152         parcel->writeInt32(
153                 static_cast<std::underlying_type_t<WindowInfo::Type>>(layoutParamsType)) ?:
154         parcel->write(frame) ?:
155         parcel->writeInt32(contentSize.width) ?:
156         parcel->writeInt32(contentSize.height) ?:
157         parcel->writeInt32(surfaceInset) ?:
158         parcel->writeFloat(globalScaleFactor) ?:
159         parcel->writeFloat(alpha) ?:
160         writeTransform(parcel, transform) ?:
161         parcel->writeInt32(static_cast<int32_t>(touchOcclusionMode)) ?:
162         parcel->writeInt32(ownerPid.val()) ?:
163         parcel->writeInt32(ownerUid.val()) ?:
164         parcel->writeUtf8AsUtf16(packageName) ?:
165         parcel->writeInt32(inputConfig.get()) ?:
166         parcel->writeInt32(displayId.val()) ?:
167         applicationInfo.writeToParcel(parcel) ?:
168         parcel->write(touchableRegion) ?:
169         parcel->writeBool(replaceTouchableRegionWithCrop) ?:
170         parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
171         parcel->writeStrongBinder(windowToken) ?:
172         parcel->writeStrongBinder(focusTransferTarget) ?:
173         parcel->writeBool(canOccludePresentation) ?:
174         parcel->writeBool(cloneLayerStackTransform.has_value());
175     // clang-format on
176     if (cloneLayerStackTransform) {
177         status = status ?: writeTransform(parcel, *cloneLayerStackTransform);
178     }
179     return status;
180 }
181 
readFromParcel(const android::Parcel * parcel)182 status_t WindowInfo::readFromParcel(const android::Parcel* parcel) {
183     if (parcel == nullptr) {
184         ALOGE("%s: Null parcel", __func__);
185         return BAD_VALUE;
186     }
187     if (parcel->readInt32() == 0) {
188         return OK;
189     }
190 
191     token = parcel->readStrongBinder();
192     dispatchingTimeout = static_cast<decltype(dispatchingTimeout)>(parcel->readInt64());
193     status_t status = parcel->readInt32(&id) ?: parcel->readUtf8FromUtf16(&name);
194     if (status != OK) {
195         return status;
196     }
197 
198     int32_t lpFlags, lpType, touchOcclusionModeInt, inputConfigInt, ownerPidInt, ownerUidInt,
199             displayIdInt;
200     sp<IBinder> touchableRegionCropHandleSp;
201     bool hasCloneLayerStackTransform = false;
202 
203     // clang-format off
204     status = parcel->readInt32(&lpFlags) ?:
205         parcel->readInt32(&lpType) ?:
206         parcel->read(frame) ?:
207         parcel->readInt32(&contentSize.width) ?:
208         parcel->readInt32(&contentSize.height) ?:
209         parcel->readInt32(&surfaceInset) ?:
210         parcel->readFloat(&globalScaleFactor) ?:
211         parcel->readFloat(&alpha) ?:
212         readTransform(parcel, /*byRef*/ transform) ?:
213         parcel->readInt32(&touchOcclusionModeInt) ?:
214         parcel->readInt32(&ownerPidInt) ?:
215         parcel->readInt32(&ownerUidInt) ?:
216         parcel->readUtf8FromUtf16(&packageName) ?:
217         parcel->readInt32(&inputConfigInt) ?:
218         parcel->readInt32(&displayIdInt) ?:
219         applicationInfo.readFromParcel(parcel) ?:
220         parcel->read(touchableRegion) ?:
221         parcel->readBool(&replaceTouchableRegionWithCrop) ?:
222         parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
223         parcel->readNullableStrongBinder(&windowToken) ?:
224         parcel->readNullableStrongBinder(&focusTransferTarget) ?:
225         parcel->readBool(&canOccludePresentation)?:
226         parcel->readBool(&hasCloneLayerStackTransform);
227     // clang-format on
228 
229     if (status != OK) {
230         return status;
231     }
232 
233     layoutParamsFlags = ftl::Flags<Flag>(lpFlags);
234     layoutParamsType = static_cast<Type>(lpType);
235     touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt);
236     inputConfig = ftl::Flags<InputConfig>(inputConfigInt);
237     ownerPid = Pid{ownerPidInt};
238     ownerUid = Uid{static_cast<uid_t>(ownerUidInt)};
239     touchableRegionCropHandle = touchableRegionCropHandleSp;
240     displayId = ui::LogicalDisplayId{displayIdInt};
241 
242     cloneLayerStackTransform =
243             hasCloneLayerStackTransform ? std::make_optional<ui::Transform>() : std::nullopt;
244     if (cloneLayerStackTransform) {
245         status = readTransform(parcel, /*byRef*/ *cloneLayerStackTransform);
246         if (status != OK) {
247             return status;
248         }
249     }
250 
251     return OK;
252 }
253 
WindowInfoHandle()254 WindowInfoHandle::WindowInfoHandle() {}
255 
~WindowInfoHandle()256 WindowInfoHandle::~WindowInfoHandle() {}
257 
WindowInfoHandle(const WindowInfoHandle & other)258 WindowInfoHandle::WindowInfoHandle(const WindowInfoHandle& other) : mInfo(other.mInfo) {}
259 
WindowInfoHandle(const WindowInfo & other)260 WindowInfoHandle::WindowInfoHandle(const WindowInfo& other) : mInfo(other) {}
261 
writeToParcel(android::Parcel * parcel) const262 status_t WindowInfoHandle::writeToParcel(android::Parcel* parcel) const {
263     return mInfo.writeToParcel(parcel);
264 }
265 
readFromParcel(const android::Parcel * parcel)266 status_t WindowInfoHandle::readFromParcel(const android::Parcel* parcel) {
267     return mInfo.readFromParcel(parcel);
268 }
269 
releaseChannel()270 void WindowInfoHandle::releaseChannel() {
271     mInfo.token.clear();
272 }
273 
getToken() const274 sp<IBinder> WindowInfoHandle::getToken() const {
275     return mInfo.token;
276 }
277 
updateFrom(sp<WindowInfoHandle> handle)278 void WindowInfoHandle::updateFrom(sp<WindowInfoHandle> handle) {
279     mInfo = handle->mInfo;
280 }
281 
operator <<(std::ostream & out,const WindowInfo & info)282 std::ostream& operator<<(std::ostream& out, const WindowInfo& info) {
283     out << "name=" << info.name << ", id=" << info.id << ", displayId=" << info.displayId
284         << ", inputConfig=" << info.inputConfig.string() << ", alpha=" << info.alpha << ", frame=["
285         << info.frame.left << "," << info.frame.top << "][" << info.frame.right << ","
286         << info.frame.bottom << "], globalScale=" << info.globalScaleFactor
287         << ", applicationInfo.name=" << info.applicationInfo.name
288         << ", applicationInfo.token=" << info.applicationInfo.token
289         << ", touchableRegion=" << info.touchableRegion << ", ownerPid=" << info.ownerPid.toString()
290         << ", ownerUid=" << info.ownerUid.toString() << ", dispatchingTimeout="
291         << std::chrono::duration_cast<std::chrono::milliseconds>(info.dispatchingTimeout).count()
292         << "ms, token=" << info.token.get()
293         << ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode);
294     if (info.canOccludePresentation) out << ", canOccludePresentation";
295     std::string transform;
296     info.transform.dump(transform, "transform", "    ");
297     out << "\n" << transform;
298     return out;
299 }
300 
operator <<(std::ostream & out,const WindowInfoHandle & window)301 std::ostream& operator<<(std::ostream& out, const WindowInfoHandle& window) {
302     const WindowInfo& info = *window.getInfo();
303     out << info;
304     return out;
305 }
306 
307 } // namespace android::gui
308