Merge "Fix -Wformat compiler warning" into main
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index d73c3a4..11e8120 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -579,11 +579,6 @@
],
}
-filegroup {
- name: "libbinder_rpc_unstable_header",
- srcs: ["include_rpc_unstable/binder_rpc_unstable.hpp"],
-}
-
// libbinder historically contained additional interfaces that provided specific
// functionality in the platform but have nothing to do with binder itself. These
// are moved out of libbinder in order to avoid the overhead of their vtables.
diff --git a/libs/binder/OS_android.cpp b/libs/binder/OS_android.cpp
index 155588d..1eace85 100644
--- a/libs/binder/OS_android.cpp
+++ b/libs/binder/OS_android.cpp
@@ -20,7 +20,8 @@
#include <cutils/trace.h>
#include <utils/misc.h>
-namespace android::binder::os {
+namespace android::binder {
+namespace os {
uint64_t GetThreadId() {
#ifdef BINDER_RPC_SINGLE_THREADED
@@ -43,4 +44,16 @@
atrace_end(tag);
}
-} // namespace android::binder::os
+} // namespace os
+
+// Legacy trace symbol. To be removed once all of downstream rebuilds.
+void atrace_begin(uint64_t tag, const char* name) {
+ os::trace_begin(tag, name);
+}
+
+// Legacy trace symbol. To be removed once all of downstream rebuilds.
+void atrace_end(uint64_t tag) {
+ os::trace_end(tag);
+}
+
+} // namespace android::binder
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index 788abc4..535ce01 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -70,7 +70,7 @@
// TODO(b/184872979): remove once the RPC Binder API is stabilised.
rust_bindgen {
name: "libbinder_rpc_unstable_bindgen",
- wrapper_src: ":libbinder_rpc_unstable_header",
+ wrapper_src: "BinderBindings.hpp",
crate_name: "binder_rpc_unstable_bindgen",
visibility: [":__subpackages__"],
source_stem: "bindings",
diff --git a/libs/binder/rust/rpcbinder/BinderBindings.hpp b/libs/binder/rust/rpcbinder/BinderBindings.hpp
new file mode 100644
index 0000000..7feb965
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/BinderBindings.hpp
@@ -0,0 +1 @@
+#include <binder_rpc_unstable.hpp>
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 6d122c5..e34d31e 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -30,8 +30,8 @@
use std::io::Write;
use std::marker::PhantomData;
use std::ops::Deref;
+use std::os::fd::AsRawFd;
use std::os::raw::c_char;
-use std::os::unix::io::AsRawFd;
use std::ptr;
/// Binder action to perform.
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index ed870b6..7f9348d 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -100,6 +100,7 @@
mod native;
mod parcel;
mod proxy;
+#[cfg(not(target_os = "trusty"))]
mod state;
use binder_ndk_sys as sys;
@@ -116,6 +117,7 @@
get_declared_instances, get_interface, get_service, is_declared, wait_for_interface,
wait_for_service, DeathRecipient, SpIBinder, WpIBinder,
};
+#[cfg(not(target_os = "trusty"))]
pub use state::{ProcessState, ThreadState};
/// Binder result containing a [`Status`] on error.
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index b250012..8ae010e 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -24,13 +24,10 @@
use std::convert::TryFrom;
use std::ffi::{c_void, CStr, CString};
-use std::fs::File;
use std::io::Write;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::os::raw::c_char;
-use std::os::unix::io::FromRawFd;
-use std::slice;
use std::sync::Mutex;
/// Rust wrapper around Binder remotable objects.
@@ -331,6 +328,7 @@
/// contains a `T` pointer in its user data. fd should be a non-owned file
/// descriptor, and args must be an array of null-terminated string
/// pointers with length num_args.
+ #[cfg(not(target_os = "trusty"))]
unsafe extern "C" fn on_dump(
binder: *mut sys::AIBinder,
fd: i32,
@@ -340,9 +338,10 @@
if fd < 0 {
return StatusCode::UNEXPECTED_NULL as status_t;
}
+ use std::os::fd::FromRawFd;
// Safety: Our caller promised that fd is a file descriptor. We don't
// own this file descriptor, so we need to be careful not to drop it.
- let mut file = unsafe { ManuallyDrop::new(File::from_raw_fd(fd)) };
+ let mut file = unsafe { ManuallyDrop::new(std::fs::File::from_raw_fd(fd)) };
if args.is_null() && num_args != 0 {
return StatusCode::UNEXPECTED_NULL as status_t;
@@ -354,7 +353,7 @@
// Safety: Our caller promised that `args` is an array of
// null-terminated string pointers with length `num_args`.
unsafe {
- slice::from_raw_parts(args, num_args as usize)
+ std::slice::from_raw_parts(args, num_args as usize)
.iter()
.map(|s| CStr::from_ptr(*s))
.collect()
@@ -374,6 +373,19 @@
Err(e) => e as status_t,
}
}
+
+ /// Called to handle the `dump` transaction.
+ #[cfg(target_os = "trusty")]
+ unsafe extern "C" fn on_dump(
+ _binder: *mut sys::AIBinder,
+ _fd: i32,
+ _args: *mut *const c_char,
+ _num_args: u32,
+ ) -> status_t {
+ // This operation is not supported on Trusty right now
+ // because we do not have a uniform way of writing to handles
+ StatusCode::INVALID_OPERATION as status_t
+ }
}
impl<T: Remotable> Drop for Binder<T> {
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index dad3379..7434e9d 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -32,8 +32,8 @@
use std::ffi::{c_void, CStr, CString};
use std::fmt;
use std::mem;
+use std::os::fd::AsRawFd;
use std::os::raw::c_char;
-use std::os::unix::io::AsRawFd;
use std::ptr;
use std::sync::Arc;
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index ba8fb39..e4d4de8 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -134,6 +134,10 @@
"IBinderRpcTest.aidl",
"ParcelableCertificateData.aidl",
],
+ flags: [
+ "-Werror",
+ "-Wno-mixed-oneway",
+ ],
backend: {
java: {
enabled: false,
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index fe79f8e..83db6c9 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -16,6 +16,9 @@
"parcelables/SingleDataParcelable.aidl",
"parcelables/GenericDataParcelable.aidl",
],
+ flags: [
+ "-Werror",
+ ],
backend: {
java: {
enabled: true,
diff --git a/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
index dd08f72..9884dbb 100644
--- a/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
+++ b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
@@ -17,7 +17,7 @@
parcelable GenericDataParcelable {
enum JustSomeEnum {
- SOME_ENUMERATOR,
+ ONE_ENUMERATOR,
ANOTHER_ENUMERATOR,
MAYBE_ONE_MORE_ENUMERATOR,
}
diff --git a/libs/binder/trusty/rust/rules.mk b/libs/binder/trusty/rust/rules.mk
new file mode 100644
index 0000000..be90df3
--- /dev/null
+++ b/libs/binder/trusty/rust/rules.mk
@@ -0,0 +1,37 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+LIBBINDER_DIR := $(LOCAL_DIR)/../..
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := $(LIBBINDER_DIR)/rust/src/lib.rs
+
+MODULE_CRATE_NAME := binder
+
+MODULE_LIBRARY_DEPS += \
+ $(LIBBINDER_DIR)/trusty \
+ $(LIBBINDER_DIR)/trusty/ndk \
+ $(LIBBINDER_DIR)/trusty/rust/binder_ndk_sys \
+ external/rust/crates/downcast-rs \
+ trusty/user/base/lib/trusty-sys \
+
+# Trusty does not have `ProcessState`, so there are a few
+# doc links in `IBinder` that are still broken.
+MODULE_RUSTFLAGS += \
+ --allow rustdoc::broken-intra-doc-links \
+
+include make/library.mk
diff --git a/libs/gui/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h
index f7dcbc6..b7aba2b 100644
--- a/libs/gui/include/gui/view/Surface.h
+++ b/libs/gui/include/gui/view/Surface.h
@@ -24,9 +24,9 @@
#include <binder/IBinder.h>
#include <binder/Parcelable.h>
-namespace android {
+#include <gui/IGraphicBufferProducer.h>
-class IGraphicBufferProducer;
+namespace android {
namespace view {
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 198908d..7c15e7c 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -20,7 +20,6 @@
#include <android/binder_parcel.h>
#include <android/native_window.h>
#include <binder/Parcel.h>
-#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <gui/view/Surface.h>
#include <system/window.h>
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6ad3de0..b8cdb3d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -649,7 +649,7 @@
if (newWindows.find(oldWindow) == newWindows.end()) {
TouchedWindow touchedWindow;
touchedWindow.windowHandle = oldWindow;
- touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_EXIT;
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::HOVER_EXIT;
out.push_back(touchedWindow);
}
}
@@ -660,7 +660,7 @@
if (oldWindows.find(newWindow) == oldWindows.end()) {
// Any windows that have this pointer now, and didn't have it before, should get
// HOVER_ENTER
- touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_HOVER_ENTER;
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::HOVER_ENTER;
} else {
// This pointer was already sent to the window. Use ACTION_HOVER_MOVE.
if (CC_UNLIKELY(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE)) {
@@ -674,7 +674,7 @@
}
LOG(severity) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription();
}
- touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS;
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
}
touchedWindow.addHoveringPointer(entry.deviceId, pointerId);
if (canReceiveForegroundTouches(*newWindow->getInfo())) {
@@ -1316,8 +1316,8 @@
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId);
- addPointerWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
- pointerIds,
+ addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
/*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
}
}
@@ -1595,7 +1595,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
entry->dispatchInProgress = true;
std::string message = std::string("Focus ") + (entry->hasFocus ? "entering " : "leaving ") +
channel->getName();
@@ -1669,7 +1668,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
entry->dispatchInProgress = true;
dispatchEventLocked(currentTime, entry, {target});
@@ -1706,7 +1704,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
inputTargets.push_back(target);
}
return inputTargets;
@@ -1822,9 +1819,8 @@
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
std::vector<InputTarget> inputTargets;
- addWindowTargetLocked(focusedWindow,
- InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS,
- getDownTime(*entry), inputTargets);
+ addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
+ InputTarget::Flags::FOREGROUND, getDownTime(*entry), inputTargets);
// Add monitor channels from event's or focused display.
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
@@ -1929,10 +1925,9 @@
findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime, injectionResult);
if (injectionResult == InputEventInjectionResult::SUCCEEDED) {
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
- addWindowTargetLocked(focusedWindow,
- InputTarget::Flags::FOREGROUND |
- InputTarget::Flags::DISPATCH_AS_IS,
- getDownTime(*entry), inputTargets);
+ addWindowTargetLocked(focusedWindow, InputTarget::DispatchMode::AS_IS,
+ InputTarget::Flags::FOREGROUND, getDownTime(*entry),
+ inputTargets);
}
}
if (injectionResult == InputEventInjectionResult::PENDING) {
@@ -1979,7 +1974,6 @@
}
InputTarget target;
target.inputChannel = channel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
entry->dispatchInProgress = true;
dispatchEventLocked(currentTime, entry, {target});
}
@@ -2391,7 +2385,7 @@
}
// Set target flags.
- ftl::Flags<InputTarget::Flags> targetFlags = InputTarget::Flags::DISPATCH_AS_IS;
+ ftl::Flags<InputTarget::Flags> targetFlags;
if (canReceiveForegroundTouches(*windowHandle->getInfo())) {
// There should only be one touched window that can be "foreground" for the pointer.
@@ -2414,8 +2408,8 @@
pointerIds.set(pointerId);
const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN;
- tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, entry.deviceId,
- pointerIds,
+ tempTouchState.addOrUpdateWindow(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, entry.deviceId, pointerIds,
isDownOrPointerDown
? std::make_optional(entry.eventTime)
: std::nullopt);
@@ -2432,13 +2426,14 @@
if (wallpaper != nullptr) {
ftl::Flags<InputTarget::Flags> wallpaperFlags =
InputTarget::Flags::WINDOW_IS_OBSCURED |
- InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED |
- InputTarget::Flags::DISPATCH_AS_IS;
+ InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
if (isSplit) {
wallpaperFlags |= InputTarget::Flags::SPLIT;
}
- tempTouchState.addOrUpdateWindow(wallpaper, wallpaperFlags, entry.deviceId,
- pointerIds, entry.eventTime);
+ tempTouchState.addOrUpdateWindow(wallpaper,
+ InputTarget::DispatchMode::AS_IS,
+ wallpaperFlags, entry.deviceId, pointerIds,
+ entry.eventTime);
}
}
}
@@ -2528,8 +2523,8 @@
const TouchedWindow& touchedWindow =
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
addPointerWindowTargetLocked(oldTouchedWindowHandle,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
- pointerIds,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
touchedWindow.getDownTimeInTarget(entry.deviceId),
targets);
@@ -2538,8 +2533,7 @@
isSplit = !isFromMouse;
}
- ftl::Flags<InputTarget::Flags> targetFlags =
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER;
+ ftl::Flags<InputTarget::Flags> targetFlags;
if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) {
targetFlags |= InputTarget::Flags::FOREGROUND;
}
@@ -2552,8 +2546,10 @@
targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
}
- tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags,
- entry.deviceId, pointerIds, entry.eventTime);
+ tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
+ InputTarget::DispatchMode::SLIPPERY_ENTER,
+ targetFlags, entry.deviceId, pointerIds,
+ entry.eventTime);
// Check if the wallpaper window should deliver the corresponding event.
slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
@@ -2586,7 +2582,8 @@
getHoveringWindowsLocked(oldState, tempTouchState, entry);
for (const TouchedWindow& touchedWindow : hoveringWindows) {
std::optional<InputTarget> target =
- createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
+ createInputTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags,
touchedWindow.getDownTimeInTarget(entry.deviceId));
if (!target) {
continue;
@@ -2623,7 +2620,7 @@
if (foregroundWindowHandle) {
const auto foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
for (InputTarget& target : targets) {
- if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
sp<WindowInfoHandle> targetWindow =
getWindowHandleLocked(target.inputChannel->getConnectionToken());
if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
@@ -2649,8 +2646,8 @@
if (touchingPointers.none()) {
continue;
}
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchingPointers,
+ addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, touchingPointers,
touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
}
@@ -2675,7 +2672,7 @@
// If we only have windows getting ACTION_OUTSIDE, then drop the event, because there is no
// window that is actually receiving the entire gesture.
if (std::all_of(targets.begin(), targets.end(), [](const InputTarget& target) {
- return target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE);
+ return target.dispatchMode == InputTarget::DispatchMode::OUTSIDE;
})) {
LOG(INFO) << "Dropping event because all windows would just receive ACTION_OUTSIDE: "
<< entry.getDescription();
@@ -2685,12 +2682,10 @@
outInjectionResult = InputEventInjectionResult::SUCCEEDED;
+ // Now that we have generated all of the input targets for this event, reset the dispatch
+ // mode for all touched window to AS_IS.
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
- // Targets that we entered in a slippery way will now become AS-IS targets
- if (touchedWindow.targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
- touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER);
- touchedWindow.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
- }
+ touchedWindow.dispatchMode = InputTarget::DispatchMode::AS_IS;
}
// Update final pieces of touch state if the injector had permission.
@@ -2823,7 +2818,7 @@
std::optional<InputTarget> InputDispatcher::createInputTargetLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags,
+ InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget) const {
std::shared_ptr<InputChannel> inputChannel = getInputChannelLocked(windowHandle->getToken());
if (inputChannel == nullptr) {
@@ -2833,6 +2828,7 @@
InputTarget inputTarget;
inputTarget.inputChannel = inputChannel;
inputTarget.windowHandle = windowHandle;
+ inputTarget.dispatchMode = dispatchMode;
inputTarget.flags = targetFlags;
inputTarget.globalScaleFactor = windowHandle->getInfo()->globalScaleFactor;
inputTarget.firstDownTimeInTarget = firstDownTimeInTarget;
@@ -2847,6 +2843,7 @@
}
void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) const {
@@ -2861,7 +2858,8 @@
if (it == inputTargets.end()) {
std::optional<InputTarget> target =
- createInputTargetLocked(windowHandle, targetFlags, firstDownTimeInTarget);
+ createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
+ firstDownTimeInTarget);
if (!target) {
return;
}
@@ -2880,9 +2878,9 @@
void InputDispatcher::addPointerWindowTargetLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags, std::bitset<MAX_POINTER_ID + 1> pointerIds,
- std::optional<nsecs_t> firstDownTimeInTarget, std::vector<InputTarget>& inputTargets) const
- REQUIRES(mLock) {
+ InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
+ std::bitset<MAX_POINTER_ID + 1> pointerIds, std::optional<nsecs_t> firstDownTimeInTarget,
+ std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) {
if (pointerIds.none()) {
for (const auto& target : inputTargets) {
LOG(INFO) << "Target: " << target;
@@ -2903,7 +2901,7 @@
// input targets for hovering pointers and for touching pointers.
// If we picked an existing input target above, but it's for HOVER_EXIT - let's use a new
// target instead.
- if (it != inputTargets.end() && it->flags.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
+ if (it != inputTargets.end() && it->dispatchMode == InputTarget::DispatchMode::HOVER_EXIT) {
// Force the code below to create a new input target
it = inputTargets.end();
}
@@ -2912,7 +2910,8 @@
if (it == inputTargets.end()) {
std::optional<InputTarget> target =
- createInputTargetLocked(windowHandle, targetFlags, firstDownTimeInTarget);
+ createInputTargetLocked(windowHandle, dispatchMode, targetFlags,
+ firstDownTimeInTarget);
if (!target) {
return;
}
@@ -2920,11 +2919,16 @@
it = inputTargets.end() - 1;
}
+ if (it->dispatchMode != dispatchMode) {
+ LOG(ERROR) << __func__ << ": DispatchMode doesn't match! ignoring new mode="
+ << ftl::enum_string(dispatchMode) << ", it=" << *it;
+ }
if (it->flags != targetFlags) {
- LOG(ERROR) << "Flags don't match! targetFlags=" << targetFlags.string() << ", it=" << *it;
+ LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string()
+ << ", it=" << *it;
}
if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
- LOG(ERROR) << "Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
+ LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
<< ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
}
@@ -2939,7 +2943,6 @@
for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
InputTarget target;
target.inputChannel = monitor.inputChannel;
- target.flags = InputTarget::Flags::DISPATCH_AS_IS;
// target.firstDownTimeInTarget is not set for global monitors. It is only required in split
// touch and global monitoring works as intended even without setting firstDownTimeInTarget
if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
@@ -3266,41 +3269,29 @@
connection->getInputChannelName().c_str());
logOutboundMotionDetails(" ", *splitMotionEntry);
}
- enqueueDispatchEntriesLocked(currentTime, connection, std::move(splitMotionEntry),
- inputTarget);
+ enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection,
+ std::move(splitMotionEntry),
+ inputTarget);
return;
}
}
// Not splitting. Enqueue dispatch entries for the event as is.
- enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
+ enqueueDispatchEntryAndStartDispatchCycleLocked(currentTime, connection, eventEntry,
+ inputTarget);
}
-void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const std::shared_ptr<Connection>& connection,
- std::shared_ptr<const EventEntry> eventEntry,
- const InputTarget& inputTarget) {
+void InputDispatcher::enqueueDispatchEntryAndStartDispatchCycleLocked(
+ nsecs_t currentTime, const std::shared_ptr<Connection>& connection,
+ std::shared_ptr<const EventEntry> eventEntry, const InputTarget& inputTarget) {
ATRACE_NAME_IF(ATRACE_ENABLED(),
- StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
+ StringPrintf("enqueueDispatchEntryAndStartDispatchCycleLocked(inputChannel=%s, "
+ "id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id));
- LOG_ALWAYS_FATAL_IF(!inputTarget.flags.any(InputTarget::DISPATCH_MASK),
- "No dispatch flags are set for %s", eventEntry->getDescription().c_str());
const bool wasEmpty = connection->outboundQueue.empty();
- // Enqueue dispatch entries for the requested modes.
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_HOVER_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_OUTSIDE);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_HOVER_ENTER);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_IS);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER);
+ enqueueDispatchEntryLocked(connection, eventEntry, inputTarget);
// If the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) {
@@ -3310,20 +3301,11 @@
void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<const EventEntry> eventEntry,
- const InputTarget& inputTarget,
- ftl::Flags<InputTarget::Flags> dispatchMode) {
- ftl::Flags<InputTarget::Flags> inputTargetFlags = inputTarget.flags;
- if (!inputTargetFlags.any(dispatchMode)) {
- return;
- }
-
- inputTargetFlags.clear(InputTarget::DISPATCH_MASK);
- inputTargetFlags |= dispatchMode;
-
+ const InputTarget& inputTarget) {
// This is a new event.
// Enqueue a new dispatch entry onto the outbound queue for this connection.
std::unique_ptr<DispatchEntry> dispatchEntry =
- createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
+ createDispatchEntry(inputTarget, eventEntry, inputTarget.flags);
// Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
// different EventEntry than what was passed in.
@@ -3349,15 +3331,15 @@
int32_t resolvedAction = motionEntry.action;
int32_t resolvedFlags = motionEntry.flags;
- if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ if (inputTarget.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::HOVER_EXIT) {
resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::HOVER_ENTER) {
resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::SLIPPERY_EXIT) {
resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
+ } else if (inputTarget.dispatchMode == InputTarget::DispatchMode::SLIPPERY_ENTER) {
resolvedAction = AMOTION_EVENT_ACTION_DOWN;
}
if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
@@ -3429,7 +3411,7 @@
<< cancelEvent->getDescription();
std::unique_ptr<DispatchEntry> cancelDispatchEntry =
createDispatchEntry(inputTarget, std::move(cancelEvent),
- InputTarget::Flags::DISPATCH_AS_IS);
+ ftl::Flags<InputTarget::Flags>());
// Send these cancel events to the queue before sending the event from the new
// device.
@@ -3529,7 +3511,7 @@
std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens;
std::vector<std::shared_ptr<Connection>> newConnections;
for (const InputTarget& target : targets) {
- if (target.flags.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
continue; // Skip windows that receive ACTION_OUTSIDE
}
@@ -4006,8 +3988,7 @@
const bool wasEmpty = connection->outboundQueue.empty();
// The target to use if we don't find a window associated with the channel.
- const InputTarget fallbackTarget{.inputChannel = connection->inputChannel,
- .flags = InputTarget::Flags::DISPATCH_AS_IS};
+ const InputTarget fallbackTarget{.inputChannel = connection->inputChannel};
const auto& token = connection->inputChannel->getConnectionToken();
for (size_t i = 0; i < cancelationEvents.size(); i++) {
@@ -4021,8 +4002,8 @@
? std::make_optional(keyEntry.displayId)
: std::nullopt;
if (const auto& window = getWindowHandleLocked(token, targetDisplay); window) {
- addWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
- keyEntry.downTime, targets);
+ addWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
+ /*targetFlags=*/{}, keyEntry.downTime, targets);
} else {
targets.emplace_back(fallbackTarget);
}
@@ -4049,8 +4030,9 @@
sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
mDragState.reset();
}
- addPointerWindowTargetLocked(window, InputTarget::Flags::DISPATCH_AS_IS,
- pointerIds, motionEntry.downTime, targets);
+ addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ motionEntry.downTime, targets);
} else {
targets.emplace_back(fallbackTarget);
const auto it = mDisplayInfos.find(motionEntry.displayId);
@@ -4080,8 +4062,7 @@
}
if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
- enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), targets[0],
- InputTarget::Flags::DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, std::move(cancelationEventEntry), targets[0]);
}
// If the outbound queue was previously empty, start the dispatch cycle going.
@@ -4124,8 +4105,9 @@
pointerIndex++) {
pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
}
- addPointerWindowTargetLocked(windowHandle, targetFlags, pointerIds,
- motionEntry.downTime, targets);
+ addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, pointerIds, motionEntry.downTime,
+ targets);
} else {
targets.emplace_back(InputTarget{.inputChannel = connection->inputChannel,
.flags = targetFlags});
@@ -4154,8 +4136,7 @@
}
if (targets.size() != 1) LOG(FATAL) << __func__ << ": InputTarget not created";
- enqueueDispatchEntryLocked(connection, std::move(downEventEntry), targets[0],
- InputTarget::Flags::DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, std::move(downEventEntry), targets[0]);
}
// If the outbound queue was previously empty, start the dispatch cycle going.
@@ -5502,12 +5483,12 @@
// Add new window.
nsecs_t downTimeInTarget = now();
ftl::Flags<InputTarget::Flags> newTargetFlags =
- oldTargetFlags & (InputTarget::Flags::SPLIT | InputTarget::Flags::DISPATCH_AS_IS);
+ oldTargetFlags & (InputTarget::Flags::SPLIT);
if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
newTargetFlags |= InputTarget::Flags::FOREGROUND;
}
- state->addOrUpdateWindow(toWindowHandle, newTargetFlags, deviceId, pointerIds,
- downTimeInTarget);
+ state->addOrUpdateWindow(toWindowHandle, InputTarget::DispatchMode::AS_IS, newTargetFlags,
+ deviceId, pointerIds, downTimeInTarget);
// Store the dragging window.
if (isDragDrop) {
@@ -6210,8 +6191,7 @@
if (fallbackKeyEntry && connection->status == Connection::Status::NORMAL) {
const InputTarget target{.inputChannel = connection->inputChannel,
.flags = dispatchEntry->targetFlags};
- enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry), target,
- InputTarget::Flags::DISPATCH_AS_IS);
+ enqueueDispatchEntryLocked(connection, std::move(fallbackKeyEntry), target);
}
releaseDispatchEntry(std::move(dispatchEntry));
}
@@ -6854,18 +6834,15 @@
if (oldWallpaper != nullptr) {
const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
- addPointerWindowTargetLocked(oldWallpaper,
- oldTouchedWindow.targetFlags |
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT,
- pointerIds, oldTouchedWindow.getDownTimeInTarget(deviceId),
- targets);
+ addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
+ oldTouchedWindow.targetFlags, pointerIds,
+ oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
state.removeTouchingPointerFromWindow(deviceId, pointerId, oldWallpaper);
}
if (newWallpaper != nullptr) {
- state.addOrUpdateWindow(newWallpaper,
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER |
- InputTarget::Flags::WINDOW_IS_OBSCURED |
+ state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::SLIPPERY_ENTER,
+ InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED,
deviceId, pointerIds);
}
@@ -6901,12 +6878,11 @@
if (newWallpaper != nullptr) {
nsecs_t downTimeInTarget = now();
- ftl::Flags<InputTarget::Flags> wallpaperFlags =
- oldTargetFlags & (InputTarget::Flags::SPLIT | InputTarget::Flags::DISPATCH_AS_IS);
+ ftl::Flags<InputTarget::Flags> wallpaperFlags = oldTargetFlags & InputTarget::Flags::SPLIT;
wallpaperFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED |
InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- state.addOrUpdateWindow(newWallpaper, wallpaperFlags, deviceId, pointerIds,
- downTimeInTarget);
+ state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
+ deviceId, pointerIds, downTimeInTarget);
std::shared_ptr<Connection> wallpaperConnection =
getConnectionLocked(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 8aa4a87..fbbde4b 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -528,13 +528,15 @@
std::optional<InputTarget> createInputTargetLocked(
const sp<android::gui::WindowInfoHandle>& windowHandle,
- ftl::Flags<InputTarget::Flags> targetFlags,
+ InputTarget::DispatchMode dispatchMode, ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget) const REQUIRES(mLock);
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
void addPointerWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags,
std::bitset<MAX_POINTER_ID + 1> pointerIds,
std::optional<nsecs_t> firstDownTimeInTarget,
@@ -580,14 +582,12 @@
const std::shared_ptr<Connection>& connection,
std::shared_ptr<const EventEntry>,
const InputTarget& inputTarget) REQUIRES(mLock);
- void enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const std::shared_ptr<Connection>& connection,
- std::shared_ptr<const EventEntry>,
- const InputTarget& inputTarget) REQUIRES(mLock);
+ void enqueueDispatchEntryAndStartDispatchCycleLocked(
+ nsecs_t currentTime, const std::shared_ptr<Connection>& connection,
+ std::shared_ptr<const EventEntry>, const InputTarget& inputTarget) REQUIRES(mLock);
void enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<const EventEntry>,
- const InputTarget& inputTarget,
- ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock);
+ const InputTarget& inputTarget) REQUIRES(mLock);
status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const;
void startDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputTarget.cpp b/services/inputflinger/dispatcher/InputTarget.cpp
index 343630c..c02c5d6 100644
--- a/services/inputflinger/dispatcher/InputTarget.cpp
+++ b/services/inputflinger/dispatcher/InputTarget.cpp
@@ -95,6 +95,7 @@
} else {
out << "<null>";
}
+ out << ", dispatchMode=" << ftl::enum_string(target.dispatchMode).c_str();
out << ", targetFlags=" << target.flags.string();
out << ", pointers=" << target.getPointerInfoString();
out << "}";
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 8b8a35a..aef866b 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -51,46 +51,39 @@
* the same UID from watching all touches. */
ZERO_COORDS = 1 << 3,
- /* This flag indicates that the event should be sent as is.
- * Should always be set unless the event is to be transmuted. */
- DISPATCH_AS_IS = 1 << 8,
-
- /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
- * of the area of this target and so should instead be delivered as an
- * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
- DISPATCH_AS_OUTSIDE = 1 << 9,
-
- /* This flag indicates that a hover sequence is starting in the given window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- DISPATCH_AS_HOVER_ENTER = 1 << 10,
-
- /* This flag indicates that a hover event happened outside of a window which handled
- * previous hover events, signifying the end of the current hover sequence for that
- * window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- DISPATCH_AS_HOVER_EXIT = 1 << 11,
-
- /* This flag indicates that the event should be canceled.
- * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
- * outside of a window. */
- DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
-
- /* This flag indicates that the event should be dispatched as an initial down.
- * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
- * into a new window. */
- DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
-
/* This flag indicates that the target of a MotionEvent is partly or wholly
* obscured by another visible window above it. The motion event should be
* delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED. */
WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
};
- /* Mask for all dispatch modes. */
- static constexpr const ftl::Flags<InputTarget::Flags> DISPATCH_MASK =
- ftl::Flags<InputTarget::Flags>() | Flags::DISPATCH_AS_IS | Flags::DISPATCH_AS_OUTSIDE |
- Flags::DISPATCH_AS_HOVER_ENTER | Flags::DISPATCH_AS_HOVER_EXIT |
- Flags::DISPATCH_AS_SLIPPERY_EXIT | Flags::DISPATCH_AS_SLIPPERY_ENTER;
+ enum class DispatchMode {
+ /* This flag indicates that the event should be sent as is.
+ * Should always be set unless the event is to be transmuted. */
+ AS_IS,
+ /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
+ * of the area of this target and so should instead be delivered as an
+ * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
+ OUTSIDE,
+ /* This flag indicates that a hover sequence is starting in the given window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ HOVER_ENTER,
+ /* This flag indicates that a hover event happened outside of a window which handled
+ * previous hover events, signifying the end of the current hover sequence for that
+ * window.
+ * The event is transmuted into ACTION_HOVER_ENTER. */
+ HOVER_EXIT,
+ /* This flag indicates that the event should be canceled.
+ * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
+ * outside of a window. */
+ SLIPPERY_EXIT,
+ /* This flag indicates that the event should be dispatched as an initial down.
+ * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
+ * into a new window. */
+ SLIPPERY_ENTER,
+
+ ftl_last = SLIPPERY_ENTER,
+ };
// The input channel to be targeted.
std::shared_ptr<InputChannel> inputChannel;
@@ -98,6 +91,9 @@
// Flags for the input target.
ftl::Flags<Flags> flags;
+ // The dispatch mode that should be used for this target.
+ DispatchMode dispatchMode = DispatchMode::AS_IS;
+
// Scaling factor to apply to MotionEvent as it is delivered.
// (ignored for KeyEvents)
float globalScaleFactor = 1.0f;
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 2ead171..e8d8c18 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -71,6 +71,7 @@
}
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
std::optional<nsecs_t> firstDownTimeInTarget) {
@@ -85,10 +86,8 @@
// An alternative design choice here would have been to compare here by token, but to
// store per-pointer transform.
if (touchedWindow.windowHandle == windowHandle) {
+ touchedWindow.dispatchMode = dispatchMode;
touchedWindow.targetFlags |= targetFlags;
- if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
- touchedWindow.targetFlags.clear(InputTarget::Flags::DISPATCH_AS_IS);
- }
// For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
// downTime set initially. Need to update existing window when a pointer is down for the
// window.
@@ -101,6 +100,7 @@
}
TouchedWindow touchedWindow;
touchedWindow.windowHandle = windowHandle;
+ touchedWindow.dispatchMode = dispatchMode;
touchedWindow.targetFlags = targetFlags;
touchedWindow.addTouchingPointers(deviceId, touchingPointerIds);
if (firstDownTimeInTarget) {
@@ -133,20 +133,6 @@
}
}
-void TouchState::filterNonAsIsTouchWindows() {
- for (size_t i = 0; i < windows.size();) {
- TouchedWindow& window = windows[i];
- if (window.targetFlags.any(InputTarget::Flags::DISPATCH_AS_IS |
- InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
- window.targetFlags.clear(InputTarget::DISPATCH_MASK);
- window.targetFlags |= InputTarget::Flags::DISPATCH_AS_IS;
- i += 1;
- } else {
- windows.erase(windows.begin() + i);
- }
- }
-}
-
void TouchState::cancelPointersForWindowsExcept(DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> pointerIds,
const sp<IBinder>& token) {
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index e79c73b..e0a84e8 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -44,6 +44,7 @@
void removeTouchingPointerFromWindow(DeviceId deviceId, int32_t pointerId,
const sp<android::gui::WindowInfoHandle>& windowHandle);
void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
+ InputTarget::DispatchMode dispatchMode,
ftl::Flags<InputTarget::Flags> targetFlags, DeviceId deviceId,
std::bitset<MAX_POINTER_ID + 1> touchingPointerIds,
std::optional<nsecs_t> firstDownTimeInTarget = std::nullopt);
@@ -54,7 +55,6 @@
void removeAllPointersForDevice(DeviceId deviceId);
void removeWindowByToken(const sp<IBinder>& token);
- void filterNonAsIsTouchWindows();
// Cancel pointers for current set of windows except the window with particular binder token.
void cancelPointersForWindowsExcept(DeviceId deviceId,
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
index 9a31678..c604353 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ b/services/inputflinger/dispatcher/TouchedWindow.h
@@ -31,6 +31,7 @@
// Focus tracking for touch.
struct TouchedWindow {
sp<gui::WindowInfoHandle> windowHandle;
+ InputTarget::DispatchMode dispatchMode = InputTarget::DispatchMode::AS_IS;
ftl::Flags<InputTarget::Flags> targetFlags;
// Hovering
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e220133..e230a91 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -4320,6 +4320,12 @@
// Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
outsideWindow->consumeMotionEvent(
AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
+
+ // Ensure outsideWindow doesn't get any more events for the gesture.
+ mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {PointF{51, 51}}));
+ window->consumeMotionMove();
+ outsideWindow->assertNoEvents();
}
/**
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 7be5fe3..d87eae3 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -101,6 +101,9 @@
// Not HWC-enabled, so it is always client-composited. No need to offload.
continue;
}
+ if (!output->getState().isEnabled) {
+ continue;
+ }
// Only run present in multiple threads if all HWC-enabled displays
// being refreshed support it.
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
index 602dd23..da578e2 100644
--- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -288,6 +288,8 @@
static constexpr GpuVirtualDisplayId kGpuVirtualDisplayId{789u};
static constexpr HalVirtualDisplayId kHalVirtualDisplayId{456u};
+ std::array<impl::OutputCompositionState, 4> mOutputStates;
+
void SetUp() override {
EXPECT_CALL(*mDisplay1, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kDisplayId1)));
@@ -297,6 +299,16 @@
.WillRepeatedly(Return(std::make_optional<DisplayId>(kGpuVirtualDisplayId)));
EXPECT_CALL(*mHalVirtualDisplay, getDisplayId)
.WillRepeatedly(Return(std::make_optional<DisplayId>(kHalVirtualDisplayId)));
+
+ // Most tests will depend on the outputs being enabled.
+ for (auto& state : mOutputStates) {
+ state.isEnabled = true;
+ }
+
+ EXPECT_CALL(*mDisplay1, getState).WillRepeatedly(ReturnRef(mOutputStates[0]));
+ EXPECT_CALL(*mDisplay2, getState).WillRepeatedly(ReturnRef(mOutputStates[1]));
+ EXPECT_CALL(*mVirtualDisplay, getState).WillRepeatedly(ReturnRef(mOutputStates[2]));
+ EXPECT_CALL(*mHalVirtualDisplay, getState).WillRepeatedly(ReturnRef(mOutputStates[3]));
}
void setOutputs(std::initializer_list<std::shared_ptr<mock::Output>> outputs) {
@@ -433,5 +445,43 @@
mEngine.present(mRefreshArgs);
}
+TEST_F(CompositionEngineOffloadTest, dependsOnEnabled) {
+ // Disable mDisplay2.
+ mOutputStates[1].isEnabled = false;
+ EXPECT_CALL(*mDisplay1, supportsOffloadPresent).WillOnce(Return(true));
+
+ // This is not actually called, because it is not enabled, but this distinguishes
+ // from the case where it did not return true.
+ EXPECT_CALL(*mDisplay2, supportsOffloadPresent).WillRepeatedly(Return(true));
+
+ EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(0);
+ EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0);
+
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
+ setOutputs({mDisplay1, mDisplay2});
+
+ mEngine.present(mRefreshArgs);
+}
+
+TEST_F(CompositionEngineOffloadTest, disabledDisplaysDoNotPreventOthersFromOffloading) {
+ // Disable mDisplay2.
+ mOutputStates[1].isEnabled = false;
+ EXPECT_CALL(*mDisplay1, supportsOffloadPresent).WillOnce(Return(true));
+
+ // This is not actually called, because it is not enabled, but this distinguishes
+ // from the case where it did not return true.
+ EXPECT_CALL(*mDisplay2, supportsOffloadPresent).WillRepeatedly(Return(true));
+ EXPECT_CALL(*mHalVirtualDisplay, supportsOffloadPresent).WillOnce(Return(true));
+
+ EXPECT_CALL(*mDisplay1, offloadPresentNextFrame).Times(1);
+ EXPECT_CALL(*mDisplay2, offloadPresentNextFrame).Times(0);
+ EXPECT_CALL(*mHalVirtualDisplay, offloadPresentNextFrame).Times(0);
+
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
+ setOutputs({mDisplay1, mDisplay2, mHalVirtualDisplay});
+
+ mEngine.present(mRefreshArgs);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index a92cc03..ad5e42b 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -708,7 +708,7 @@
ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
(RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
- RequestedLayerState::Changes::AffectsChildren |
+ RequestedLayerState::Changes::AffectsChildren | RequestedLayerState::Changes::Input |
RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
snapshot.changes |= parentChanges;
if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
@@ -1041,6 +1041,19 @@
snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
+ snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
+ ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
+ : parentSnapshot.inputInfo.touchOcclusionMode;
+ if (requested.dropInputMode == gui::DropInputMode::ALL ||
+ parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
+ snapshot.dropInputMode = gui::DropInputMode::ALL;
+ } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
+ parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
+ snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
+ } else {
+ snapshot.dropInputMode = gui::DropInputMode::NONE;
+ }
+
updateVisibility(snapshot, snapshot.isVisible);
if (!needsInputInfo(snapshot, requested)) {
return;
@@ -1064,18 +1077,6 @@
}
snapshot.inputInfo.alpha = snapshot.color.a;
- snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
- ? requested.windowInfoHandle->getInfo()->touchOcclusionMode
- : parentSnapshot.inputInfo.touchOcclusionMode;
- if (requested.dropInputMode == gui::DropInputMode::ALL ||
- parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
- snapshot.dropInputMode = gui::DropInputMode::ALL;
- } else if (requested.dropInputMode == gui::DropInputMode::OBSCURED ||
- parentSnapshot.dropInputMode == gui::DropInputMode::OBSCURED) {
- snapshot.dropInputMode = gui::DropInputMode::OBSCURED;
- } else {
- snapshot.dropInputMode = gui::DropInputMode::NONE;
- }
handleDropInputMode(snapshot, parentSnapshot);
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 21172ca..209df79 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -417,6 +417,8 @@
if (!obj.handleAlive) out << " handleNotAlive";
if (obj.requestedFrameRate.isValid())
out << " requestedFrameRate: {" << obj.requestedFrameRate << "}";
+ if (obj.dropInputMode != gui::DropInputMode::NONE)
+ out << " dropInputMode=" << static_cast<uint32_t>(obj.dropInputMode);
return out;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 848cbb5..1dcc19e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5821,12 +5821,15 @@
}
getHwComposer().setPowerMode(displayId, mode);
- if (displayId == mActiveDisplayId && mode != hal::PowerMode::DOZE_SUSPEND) {
+ if (mode != hal::PowerMode::DOZE_SUSPEND &&
+ (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) {
const bool enable =
mScheduler->getVsyncSchedule(displayId)->getPendingHardwareVsyncState();
requestHardwareVsync(displayId, enable);
- mScheduler->enableSyntheticVsync(false);
+ if (displayId == mActiveDisplayId) {
+ mScheduler->enableSyntheticVsync(false);
+ }
constexpr bool kAllowToEnable = true;
mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
@@ -5835,8 +5838,8 @@
mVisibleRegionsDirty = true;
scheduleComposite(FrameHint::kActive);
} else if (mode == hal::PowerMode::OFF) {
+ const bool currentModeNotDozeSuspend = (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND);
// Turn off the display
-
if (displayId == mActiveDisplayId) {
if (const auto display = getActivatableDisplay()) {
onActiveDisplayChangedLocked(activeDisplay.get(), *display);
@@ -5850,14 +5853,24 @@
strerror(errno));
}
- if (*currentModeOpt != hal::PowerMode::DOZE_SUSPEND) {
- mScheduler->disableHardwareVsync(displayId, true);
+ if (currentModeNotDozeSuspend) {
+ if (!FlagManager::getInstance().multithreaded_present()) {
+ mScheduler->disableHardwareVsync(displayId, true);
+ }
mScheduler->enableSyntheticVsync();
}
}
}
+ if (currentModeNotDozeSuspend && FlagManager::getInstance().multithreaded_present()) {
+ constexpr bool kDisallow = true;
+ mScheduler->disableHardwareVsync(displayId, kDisallow);
+ }
- // Disable VSYNC before turning off the display.
+ // We must disable VSYNC *before* turning off the display. The call to
+ // disableHardwareVsync, above, schedules a task to turn it off after
+ // this method returns. But by that point, the display is OFF, so the
+ // call just updates the pending state, without actually disabling
+ // VSYNC.
requestHardwareVsync(displayId, false);
getHwComposer().setPowerMode(displayId, mode);
@@ -5866,18 +5879,24 @@
} else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) {
// Update display while dozing
getHwComposer().setPowerMode(displayId, mode);
- if (displayId == mActiveDisplayId && *currentModeOpt == hal::PowerMode::DOZE_SUSPEND) {
- ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
- mVisibleRegionsDirty = true;
- scheduleRepaint();
- mScheduler->enableSyntheticVsync(false);
- mScheduler->resyncToHardwareVsync(displayId, true /* allowToEnable */,
- activeMode.get());
+ if (*currentModeOpt == hal::PowerMode::DOZE_SUSPEND &&
+ (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present())) {
+ if (displayId == mActiveDisplayId) {
+ ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
+ mVisibleRegionsDirty = true;
+ scheduleRepaint();
+ mScheduler->enableSyntheticVsync(false);
+ }
+ constexpr bool kAllowToEnable = true;
+ mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, activeMode.get());
}
} else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
+ if (displayId == mActiveDisplayId || FlagManager::getInstance().multithreaded_present()) {
+ constexpr bool kDisallow = true;
+ mScheduler->disableHardwareVsync(displayId, kDisallow);
+ }
if (displayId == mActiveDisplayId) {
- mScheduler->disableHardwareVsync(displayId, true);
mScheduler->enableSyntheticVsync();
}
getHwComposer().setPowerMode(displayId, mode);
@@ -7543,6 +7562,12 @@
return;
}
+ if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) {
+ ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT");
+ invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
+ return;
+ }
+
wp<const DisplayDevice> displayWeak;
ui::LayerStack layerStack;
ui::Size reqSize(args.width, args.height);
@@ -7673,8 +7698,11 @@
std::unordered_set<uint32_t> excludeLayerIds;
ui::Dataspace dataspace = args.dataspace;
- // Call this before holding mStateLock to avoid any deadlocking.
- bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
+ if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) {
+ ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT");
+ invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
+ return;
+ }
{
Mutex::Autolock lock(mStateLock);
@@ -7686,13 +7714,6 @@
return;
}
- if (!canCaptureBlackoutContent &&
- parent->getDrawingState().flags & layer_state_t::eLayerSecure) {
- ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
- invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
- return;
- }
-
Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
if (args.sourceCrop.width() <= 0) {
crop.left = 0;
@@ -7870,8 +7891,6 @@
bool grayscale, const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
- bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
-
auto future = mScheduler->schedule(
[=, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD(
kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> {
@@ -7889,8 +7908,7 @@
ftl::SharedFuture<FenceResult> renderFuture;
renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) {
renderFuture = renderScreenImpl(renderArea, getLayerSnapshots, buffer,
- canCaptureBlackoutContent, regionSampling,
- grayscale, captureResults);
+ regionSampling, grayscale, captureResults);
});
if (captureListener) {
@@ -7917,9 +7935,8 @@
ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl(
std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots,
- const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
- ScreenCaptureResults& captureResults) {
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
+ bool grayscale, ScreenCaptureResults& captureResults) {
ATRACE_CALL();
auto layers = getLayerSnapshots();
@@ -7934,14 +7951,6 @@
layerFE->mSnapshot->geomLayerTransform.inverse();
}
- // We allow the system server to take screenshots of secure layers for
- // use in situations like the Screen-rotation animation and place
- // the impetus on WindowManager to not persist them.
- if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) {
- ALOGW("FB is protected: PERMISSION_DENIED");
- return ftl::yield<FenceResult>(base::unexpected(PERMISSION_DENIED)).share();
- }
-
auto capturedBuffer = buffer;
auto requestedDataspace = renderArea->getReqDataSpace();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 788fe73..c4af271 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -858,8 +858,8 @@
bool grayscale, const sp<IScreenCaptureListener>&);
ftl::SharedFuture<FenceResult> renderScreenImpl(
std::shared_ptr<const RenderArea>, GetLayerSnapshotsFunction,
- const std::shared_ptr<renderengine::ExternalTexture>&, bool canCaptureBlackoutContent,
- bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock)
+ const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
+ bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock)
REQUIRES(kMainThreadContext);
// If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 061e121..18262f6 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -99,25 +99,42 @@
ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
}
- UIDFaker f(AID_SYSTEM);
-
- // By default the system can capture screenshots with secure layers but they
- // will be blacked out
- ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
-
{
- SCOPED_TRACE("as system");
- auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ UIDFaker f(AID_SYSTEM);
+
+ // By default the system can capture screenshots with secure layers but they
+ // will be blacked out
+ ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
+
+ {
+ SCOPED_TRACE("as system");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ mCaptureArgs.captureSecureLayers = true;
+ // AID_SYSTEM is allowed to capture secure content.
+ ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
+ ASSERT_TRUE(mCaptureResults.capturedSecureLayers);
+ ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers);
+ sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
}
- // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
- // to receive them...we are expected to take care with the results.
- mCaptureArgs.captureSecureLayers = true;
- ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
- ASSERT_TRUE(mCaptureResults.capturedSecureLayers);
- ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers);
- sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
+ {
+ // Attempt secure screenshot from shell since it doesn't have CAPTURE_BLACKOUT_CONTENT
+ // permission, but is allowed normal screenshots.
+ UIDFaker faker(AID_SHELL);
+ ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
+ }
+
+ // Remove flag secure from the layer.
+ Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
+ {
+ // Assert that screenshot fails without CAPTURE_BLACKOUT_CONTENT when requesting
+ // captureSecureLayers even if there are no actual secure layers on screen.
+ UIDFaker faker(AID_SHELL);
+ ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
+ }
}
TEST_F(ScreenCaptureTest, CaptureChildSetParentFlagsSecureEUidSystem) {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index ee967979..0b9a030 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -194,7 +194,6 @@
LayerCase::setupForScreenCapture(this);
const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
- constexpr bool forSystem = true;
constexpr bool regionSampling = false;
auto renderArea = DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(),
@@ -216,7 +215,7 @@
usage);
auto future = mFlinger.renderScreenImpl(std::move(renderArea), getLayerSnapshots,
- mCaptureScreenBuffer, forSystem, regionSampling);
+ mCaptureScreenBuffer, regionSampling);
ASSERT_TRUE(future.valid());
const auto fenceResult = future.get();
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index 48f8923..7e9abce 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -478,6 +478,17 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setDropInputMode(uint32_t id, gui::DropInputMode dropInputMode) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eDropInputModeChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.dropInputMode = dropInputMode;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
LayerLifecycleManager mLifecycleManager;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 040a3bf..50cd784 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1162,4 +1162,25 @@
EXPECT_TRUE(getSnapshot(11)->isSecure);
}
+// b/314350323
+TEST_F(LayerSnapshotTest, propagateDropInputMode) {
+ setDropInputMode(1, gui::DropInputMode::ALL);
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .displayChanges = false,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
+ args.rootSnapshot.isSecure = true;
+ update(mSnapshotBuilder, args);
+
+ EXPECT_EQ(getSnapshot(1)->dropInputMode, gui::DropInputMode::ALL);
+ // Ensure child also has the correct drop input mode regardless of whether either layer has
+ // an input channel
+ EXPECT_EQ(getSnapshot(11)->dropInputMode, gui::DropInputMode::ALL);
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp
index ed8d909..844b96c 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp
@@ -188,5 +188,38 @@
scheduler.onHardwareVsyncRequest(mOuterDisplay->getPhysicalId(), true);
}
+TEST_F(FoldableTest, requestVsyncOnPowerOn) {
+ EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true))
+ .Times(1);
+ EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true))
+ .Times(1);
+
+ mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
+ mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
+}
+
+TEST_F(FoldableTest, disableVsyncOnPowerOffPacesetter) {
+ // When the device boots, the inner display should be the pacesetter.
+ ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
+
+ testing::InSequence seq;
+ EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true))
+ .Times(1);
+ EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true))
+ .Times(1);
+
+ // Turning off the pacesetter will result in disabling VSYNC.
+ EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, false))
+ .Times(1);
+
+ mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::ON);
+ mFlinger.setPowerModeInternal(mOuterDisplay, PowerMode::ON);
+
+ mFlinger.setPowerModeInternal(mInnerDisplay, PowerMode::OFF);
+
+ // Other display is now the pacesetter.
+ ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kOuterDisplayId);
+}
+
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index 31e1330..15fe600 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -73,11 +73,13 @@
struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant {
static void setupEnableVsyncCallExpectations(DisplayTransactionTest* test) {
- setupVsyncNoCallExpectations(test);
+ EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, true)).Times(1);
+ EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
}
static void setupDisableVsyncCallExpectations(DisplayTransactionTest* test) {
- setupVsyncNoCallExpectations(test);
+ EXPECT_CALL(test->mFlinger.scheduler()->mockRequestHardwareVsync, Call(_, false)).Times(1);
+ EXPECT_CALL(*test->mEventThread, enableSyntheticVsync(_)).Times(0);
}
};
@@ -298,6 +300,11 @@
// A sample configuration for the external display.
// In addition to not having event thread support, we emulate not having doze
// support.
+// TODO (b/267483230): ExternalDisplay supports the features tracked in
+// DispSyncIsSupportedVariant, but is the follower, so the
+// expectations set by DispSyncIsSupportedVariant don't match (wrong schedule).
+// We need a way to retrieve the proper DisplayId from
+// setupResetModelCallExpectations (or pass it in).
template <typename TransitionVariant>
using ExternalDisplayPowerCase =
DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant<ExternalDisplayVariant>,
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 0909178..ebb05d4 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -493,11 +493,11 @@
auto renderScreenImpl(std::shared_ptr<const RenderArea> renderArea,
SurfaceFlinger::GetLayerSnapshotsFunction traverseLayers,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- bool forSystem, bool regionSampling) {
+ bool regionSampling) {
ScreenCaptureResults captureResults;
return FTL_FAKE_GUARD(kMainThreadContext,
mFlinger->renderScreenImpl(std::move(renderArea), traverseLayers,
- buffer, forSystem, regionSampling,
+ buffer, regionSampling,
false /* grayscale */, captureResults));
}