Merge "Extract RenderArea elements into screenshot args" into main
diff --git a/include/input/DisplayTopologyGraph.h b/include/input/DisplayTopologyGraph.h
index f3f5148..3ae865a 100644
--- a/include/input/DisplayTopologyGraph.h
+++ b/include/input/DisplayTopologyGraph.h
@@ -42,7 +42,9 @@
*/
struct DisplayTopologyAdjacentDisplay {
ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID;
+ // Position of the adjacent display, relative to the source display.
DisplayTopologyPosition position;
+ // The offset in DP of the adjacent display, relative to the source display.
float offsetDp;
};
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index f5df8d5..2c2e2c8 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -30,10 +30,14 @@
* not be added with this flag for privacy concerns.
*/
ADD_SERVICE_ALLOW_ISOLATED = 1 << 0,
+ /**
+ * Allows services to dump sections according to priorities and format
+ */
ADD_SERVICE_DUMP_FLAG_PRIORITY_CRITICAL = 1 << 1,
ADD_SERVICE_DUMP_FLAG_PRIORITY_HIGH = 1 << 2,
ADD_SERVICE_DUMP_FLAG_PRIORITY_NORMAL = 1 << 3,
ADD_SERVICE_DUMP_FLAG_PRIORITY_DEFAULT = 1 << 4,
+ ADD_SERVICE_DUMP_FLAG_PROTO = 1 << 5,
// All other bits are reserved for internal usage
};
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index d6ac4ac..14bc5d2 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -63,6 +63,9 @@
if (flags & AServiceManager_AddServiceFlag::ADD_SERVICE_DUMP_FLAG_PRIORITY_DEFAULT) {
dumpFlags |= IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT;
}
+ if (flags & AServiceManager_AddServiceFlag::ADD_SERVICE_DUMP_FLAG_PROTO) {
+ dumpFlags |= IServiceManager::DUMP_FLAG_PROTO;
+ }
if (dumpFlags == 0) {
dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT;
}
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
index c0c0aae..339ce4b 100644
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ b/libs/binder/tests/binderAllocationLimits.cpp
@@ -22,17 +22,33 @@
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
#include <cutils/trace.h>
+#include <gtest/gtest-spi.h>
#include <gtest/gtest.h>
#include <utils/CallStack.h>
#include <malloc.h>
+#include <atomic>
#include <functional>
+#include <numeric>
#include <vector>
using namespace android::binder::impl;
static android::String8 gEmpty(""); // make sure first allocation from optimization runs
+struct State {
+ State(std::vector<size_t>&& expectedMallocs) : expectedMallocs(std::move(expectedMallocs)) {}
+ ~State() {
+ size_t num = numMallocs.load();
+ if (expectedMallocs.size() != num) {
+ ADD_FAILURE() << "Expected " << expectedMallocs.size() << " allocations, but got "
+ << num;
+ }
+ }
+ const std::vector<size_t> expectedMallocs;
+ std::atomic<size_t> numMallocs;
+};
+
struct DestructionAction {
DestructionAction(std::function<void()> f) : mF(std::move(f)) {}
~DestructionAction() { mF(); };
@@ -95,8 +111,7 @@
// Action to execute when malloc is hit. Supports nesting. Malloc is not
// restricted when the allocation hook is being processed.
-__attribute__((warn_unused_result))
-DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
+__attribute__((warn_unused_result)) DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
MallocHooks before = MallocHooks::save();
LambdaHooks::lambdas.emplace_back(std::move(f));
LambdaHooks::lambda_malloc_hooks.overwrite();
@@ -106,6 +121,22 @@
});
}
+DestructionAction setExpectedMallocs(std::vector<size_t>&& expected) {
+ auto state = std::make_shared<State>(std::move(expected));
+ return OnMalloc([state = state](size_t bytes) {
+ size_t num = state->numMallocs.fetch_add(1);
+ if (num >= state->expectedMallocs.size() || state->expectedMallocs[num] != bytes) {
+ ADD_FAILURE() << "Unexpected allocation number " << num << " of size " << bytes
+ << " bytes" << std::endl
+ << android::CallStack::stackToString("UNEXPECTED ALLOCATION",
+ android::CallStack::getCurrent(
+ 4 /*ignoreDepth*/)
+ .get())
+ << std::endl;
+ }
+ });
+}
+
// exported symbol, to force compiler not to optimize away pointers we set here
const void* imaginary_use;
@@ -119,16 +150,53 @@
imaginary_use = new int[10];
}
+ delete[] reinterpret_cast<const int*>(imaginary_use);
EXPECT_EQ(mallocs, 1u);
}
+TEST(TestTheTest, OnMallocWithExpectedMallocs) {
+ std::vector<size_t> expectedMallocs = {
+ 4,
+ 16,
+ 8,
+ };
+ {
+ const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
+ imaginary_use = new int32_t[1];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[4];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[2];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ }
+}
+
+TEST(TestTheTest, OnMallocWithExpectedMallocsWrongSize) {
+ std::vector<size_t> expectedMallocs = {
+ 4,
+ 16,
+ 100000,
+ };
+ EXPECT_NONFATAL_FAILURE(
+ {
+ const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
+ imaginary_use = new int32_t[1];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[4];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ imaginary_use = new int32_t[2];
+ delete[] reinterpret_cast<const int*>(imaginary_use);
+ },
+ "Unexpected allocation number 2 of size 8 bytes");
+}
__attribute__((warn_unused_result))
DestructionAction ScopeDisallowMalloc() {
return OnMalloc([&](size_t bytes) {
- ADD_FAILURE() << "Unexpected allocation: " << bytes;
+ FAIL() << "Unexpected allocation: " << bytes;
using android::CallStack;
- std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION", CallStack::getCurrent(4 /*ignoreDepth*/).get())
+ std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION",
+ CallStack::getCurrent(4 /*ignoreDepth*/).get())
<< std::endl;
});
}
@@ -224,6 +292,51 @@
EXPECT_EQ(mallocs, 1u);
}
+TEST(BinderAccessorAllocation, AddAccessorCheckService) {
+ // Need to call defaultServiceManager() before checking malloc because it
+ // will allocate an instance in the call_once
+ const auto sm = defaultServiceManager();
+ const std::string kInstanceName1 = "foo.bar.IFoo/default";
+ const std::string kInstanceName2 = "foo.bar.IFoo2/default";
+ const String16 kInstanceName16(kInstanceName1.c_str());
+ std::vector<size_t> expectedMallocs = {
+ // addAccessorProvider
+ 112, // new AccessorProvider
+ 16, // new AccessorProviderEntry
+ // checkService
+ 45, // String8 from String16 in CppShim::checkService
+ 128, // writeInterfaceToken
+ 16, // getInjectedAccessor, new AccessorProviderEntry
+ 66, // getInjectedAccessor, String16
+ 45, // String8 from String16 in AccessorProvider::provide
+ };
+ std::set<std::string> supportedInstances = {kInstanceName1, kInstanceName2};
+ auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
+
+ auto receipt =
+ android::addAccessorProvider(std::move(supportedInstances),
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+ EXPECT_FALSE(receipt.expired());
+
+ sp<IBinder> binder = sm->checkService(kInstanceName16);
+
+ status_t status = android::removeAccessorProvider(receipt);
+}
+
+TEST(BinderAccessorAllocation, AddAccessorEmpty) {
+ std::vector<size_t> expectedMallocs = {
+ 48, // From ALOGE with empty set of instances
+ };
+ std::set<std::string> supportedInstances = {};
+ auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
+
+ auto receipt =
+ android::addAccessorProvider(std::move(supportedInstances),
+ [&](const String16&) -> sp<IBinder> { return nullptr; });
+
+ EXPECT_TRUE(receipt.expired());
+}
+
TEST(RpcBinderAllocation, SetupRpcServer) {
std::string tmp = getenv("TMPDIR") ?: "/tmp";
std::string addr = tmp + "/binderRpcBenchmark";
@@ -255,6 +368,7 @@
}
int main(int argc, char** argv) {
+ LOG(INFO) << "Priming static log variables for binderAllocationLimits.";
if (getenv("LIBC_HOOKS_ENABLE") == nullptr) {
CHECK(0 == setenv("LIBC_HOOKS_ENABLE", "1", true /*overwrite*/));
execv(argv[0], argv);
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 389fb7f..cd6fe90 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -27,9 +27,9 @@
name: "inputconstants_aidl",
srcs: [
"android/os/IInputConstants.aidl",
+ "android/os/InputConfig.aidl",
"android/os/InputEventInjectionResult.aidl",
"android/os/InputEventInjectionSync.aidl",
- "android/os/InputConfig.aidl",
"android/os/MotionEventFlag.aidl",
"android/os/PointerIconType.aidl",
],
@@ -85,56 +85,56 @@
source_stem: "bindings",
bindgen_flags: [
- "--verbose",
- "--allowlist-var=AMOTION_EVENT_ACTION_CANCEL",
- "--allowlist-var=AMOTION_EVENT_ACTION_UP",
- "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_DOWN",
- "--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
- "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
- "--allowlist-var=MAX_POINTER_ID",
- "--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
- "--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
- "--allowlist-var=AINPUT_SOURCE_CLASS_POINTER",
- "--allowlist-var=AINPUT_SOURCE_CLASS_NAVIGATION",
- "--allowlist-var=AINPUT_SOURCE_CLASS_POSITION",
- "--allowlist-var=AINPUT_SOURCE_CLASS_JOYSTICK",
- "--allowlist-var=AINPUT_SOURCE_UNKNOWN",
- "--allowlist-var=AINPUT_SOURCE_KEYBOARD",
- "--allowlist-var=AINPUT_SOURCE_DPAD",
- "--allowlist-var=AINPUT_SOURCE_GAMEPAD",
- "--allowlist-var=AINPUT_SOURCE_TOUCHSCREEN",
- "--allowlist-var=AINPUT_SOURCE_MOUSE",
- "--allowlist-var=AINPUT_SOURCE_STYLUS",
- "--allowlist-var=AINPUT_SOURCE_BLUETOOTH_STYLUS",
- "--allowlist-var=AINPUT_SOURCE_TRACKBALL",
- "--allowlist-var=AINPUT_SOURCE_MOUSE_RELATIVE",
- "--allowlist-var=AINPUT_SOURCE_TOUCHPAD",
- "--allowlist-var=AINPUT_SOURCE_TOUCH_NAVIGATION",
- "--allowlist-var=AINPUT_SOURCE_JOYSTICK",
- "--allowlist-var=AINPUT_SOURCE_HDMI",
- "--allowlist-var=AINPUT_SOURCE_SENSOR",
- "--allowlist-var=AINPUT_SOURCE_ROTARY_ENCODER",
+ "--allowlist-var=AINPUT_KEYBOARD_TYPE_ALPHABETIC",
"--allowlist-var=AINPUT_KEYBOARD_TYPE_NONE",
"--allowlist-var=AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC",
- "--allowlist-var=AINPUT_KEYBOARD_TYPE_ALPHABETIC",
- "--allowlist-var=AMETA_NONE",
- "--allowlist-var=AMETA_ALT_ON",
+ "--allowlist-var=AINPUT_SOURCE_BLUETOOTH_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POINTER",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POSITION",
+ "--allowlist-var=AINPUT_SOURCE_DPAD",
+ "--allowlist-var=AINPUT_SOURCE_GAMEPAD",
+ "--allowlist-var=AINPUT_SOURCE_HDMI",
+ "--allowlist-var=AINPUT_SOURCE_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_KEYBOARD",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE_RELATIVE",
+ "--allowlist-var=AINPUT_SOURCE_ROTARY_ENCODER",
+ "--allowlist-var=AINPUT_SOURCE_SENSOR",
+ "--allowlist-var=AINPUT_SOURCE_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHPAD",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHSCREEN",
+ "--allowlist-var=AINPUT_SOURCE_TOUCH_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_TRACKBALL",
+ "--allowlist-var=AINPUT_SOURCE_UNKNOWN",
"--allowlist-var=AMETA_ALT_LEFT_ON",
+ "--allowlist-var=AMETA_ALT_ON",
"--allowlist-var=AMETA_ALT_RIGHT_ON",
- "--allowlist-var=AMETA_SHIFT_ON",
- "--allowlist-var=AMETA_SHIFT_LEFT_ON",
- "--allowlist-var=AMETA_SHIFT_RIGHT_ON",
- "--allowlist-var=AMETA_SYM_ON",
- "--allowlist-var=AMETA_FUNCTION_ON",
- "--allowlist-var=AMETA_CTRL_ON",
- "--allowlist-var=AMETA_CTRL_LEFT_ON",
- "--allowlist-var=AMETA_CTRL_RIGHT_ON",
- "--allowlist-var=AMETA_META_ON",
- "--allowlist-var=AMETA_META_LEFT_ON",
- "--allowlist-var=AMETA_META_RIGHT_ON",
"--allowlist-var=AMETA_CAPS_LOCK_ON",
+ "--allowlist-var=AMETA_CTRL_LEFT_ON",
+ "--allowlist-var=AMETA_CTRL_ON",
+ "--allowlist-var=AMETA_CTRL_RIGHT_ON",
+ "--allowlist-var=AMETA_FUNCTION_ON",
+ "--allowlist-var=AMETA_META_LEFT_ON",
+ "--allowlist-var=AMETA_META_ON",
+ "--allowlist-var=AMETA_META_RIGHT_ON",
+ "--allowlist-var=AMETA_NONE",
"--allowlist-var=AMETA_NUM_LOCK_ON",
"--allowlist-var=AMETA_SCROLL_LOCK_ON",
+ "--allowlist-var=AMETA_SHIFT_LEFT_ON",
+ "--allowlist-var=AMETA_SHIFT_ON",
+ "--allowlist-var=AMETA_SHIFT_RIGHT_ON",
+ "--allowlist-var=AMETA_SYM_ON",
+ "--allowlist-var=AMOTION_EVENT_ACTION_CANCEL",
+ "--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
+ "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_DOWN",
+ "--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
+ "--allowlist-var=AMOTION_EVENT_ACTION_UP",
+ "--allowlist-var=MAX_POINTER_ID",
+ "--verbose",
],
static_libs: [
@@ -143,9 +143,9 @@
],
shared_libs: ["libc++"],
header_libs: [
- "native_headers",
- "jni_headers",
"flatbuffer_headers",
+ "jni_headers",
+ "native_headers",
],
}
@@ -179,8 +179,8 @@
host_supported: true,
cflags: [
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
],
srcs: [
"FromRustToCpp.cpp",
@@ -205,15 +205,15 @@
cpp_std: "c++20",
host_supported: true,
cflags: [
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
"-Wno-unused-parameter",
- "-Wthread-safety",
"-Wshadow",
"-Wshadow-field-in-constructor-modified",
"-Wshadow-uncaptured-local",
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ "-Wthread-safety",
],
srcs: [
"AccelerationCurve.cpp",
@@ -225,10 +225,10 @@
"InputEventLabels.cpp",
"InputTransport.cpp",
"InputVerifier.cpp",
- "Keyboard.cpp",
"KeyCharacterMap.cpp",
- "KeyboardClassifier.cpp",
"KeyLayoutMap.cpp",
+ "Keyboard.cpp",
+ "KeyboardClassifier.cpp",
"MotionPredictor.cpp",
"MotionPredictorMetricsManager.cpp",
"OneEuroFilter.cpp",
@@ -262,13 +262,13 @@
shared_libs: [
"android.companion.virtualdevice.flags-aconfig-cc",
+ "libPlatformProperties",
"libaconfig_storage_read_api_cc",
"libbase",
"libbinder",
"libbinder_ndk",
"libcutils",
"liblog",
- "libPlatformProperties",
"libtinyxml2",
"libutils",
"libz", // needed by libkernelconfigs
@@ -287,15 +287,15 @@
static_libs: [
"inputconstants-cpp",
- "libui-types",
- "libtflite_static",
"libkernelconfigs",
+ "libtflite_static",
+ "libui-types",
],
whole_static_libs: [
"com.android.input.flags-aconfig-cc",
- "libinput_rust_ffi",
"iinputflinger_aidl_lib_static",
+ "libinput_rust_ffi",
],
export_static_lib_headers: [
@@ -310,8 +310,8 @@
target: {
android: {
required: [
- "motion_predictor_model_prebuilt",
"motion_predictor_model_config",
+ "motion_predictor_model_prebuilt",
],
static_libs: [
"libstatslog_libinput",
@@ -372,9 +372,9 @@
cpp_std: "c++20",
host_supported: true,
shared_libs: [
- "libutils",
"libbase",
"liblog",
+ "libutils",
],
}
diff --git a/libs/input/rust/Android.bp b/libs/input/rust/Android.bp
index 63853f7..fae9074 100644
--- a/libs/input/rust/Android.bp
+++ b/libs/input/rust/Android.bp
@@ -18,12 +18,12 @@
srcs: ["lib.rs"],
host_supported: true,
rustlibs: [
+ "inputconstants-rust",
"libbitflags",
"libcxx",
"libinput_bindgen",
- "liblogger",
"liblog_rust",
- "inputconstants-rust",
+ "liblogger",
"libserde",
"libserde_json",
],
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 85a37fe..968fa5f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -16,16 +16,16 @@
"BlockingQueue_test.cpp",
"IdGenerator_test.cpp",
"InputChannel_test.cpp",
- "InputConsumer_test.cpp",
"InputConsumerFilteredResampling_test.cpp",
"InputConsumerResampling_test.cpp",
+ "InputConsumer_test.cpp",
"InputDevice_test.cpp",
"InputEvent_test.cpp",
- "InputPublisherAndConsumer_test.cpp",
"InputPublisherAndConsumerNoResampling_test.cpp",
+ "InputPublisherAndConsumer_test.cpp",
"InputVerifier_test.cpp",
- "MotionPredictor_test.cpp",
"MotionPredictorMetricsManager_test.cpp",
+ "MotionPredictor_test.cpp",
"OneEuroFilter_test.cpp",
"Resampler_test.cpp",
"RingBuffer_test.cpp",
@@ -53,8 +53,8 @@
],
cflags: [
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
"-Wno-unused-parameter",
],
sanitize: {
@@ -68,26 +68,26 @@
memtag_heap: true,
undefined: true,
misc_undefined: [
- "bounds",
"all",
+ "bounds",
],
},
},
shared_libs: [
+ "libPlatformProperties",
"libaconfig_storage_read_api_cc",
"libbase",
"libbinder",
"libcutils",
"liblog",
- "libPlatformProperties",
"libstatslog",
"libtinyxml2",
"libutils",
"server_configurable_flags",
],
data: [
- "data/*",
":motion_predictor_model",
+ "data/*",
],
test_options: {
unit_test: true,
@@ -117,10 +117,10 @@
"-Wextra",
],
shared_libs: [
- "libinput",
- "libcutils",
- "libutils",
- "libbinder",
"libbase",
+ "libbinder",
+ "libcutils",
+ "libinput",
+ "libutils",
],
}
diff --git a/libs/tracing_perfetto/tracing_perfetto_internal.cpp b/libs/tracing_perfetto/tracing_perfetto_internal.cpp
index f92f6df..4478732 100644
--- a/libs/tracing_perfetto/tracing_perfetto_internal.cpp
+++ b/libs/tracing_perfetto/tracing_perfetto_internal.cpp
@@ -14,15 +14,16 @@
* limitations under the License.
*/
+// Should match the definitions in: frameworks/native/cmds/atrace/atrace.cpp
#define FRAMEWORK_CATEGORIES(C) \
C(always, "always", "Always category") \
- C(graphics, "graphics", "Graphics category") \
+ C(graphics, "gfx", "Graphics category") \
C(input, "input", "Input category") \
C(view, "view", "View category") \
C(webview, "webview", "WebView category") \
C(windowmanager, "wm", "WindowManager category") \
C(activitymanager, "am", "ActivityManager category") \
- C(syncmanager, "syncmanager", "SyncManager category") \
+ C(syncmanager, "sm", "SyncManager category") \
C(audio, "audio", "Audio category") \
C(video, "video", "Video category") \
C(camera, "camera", "Camera category") \
@@ -33,7 +34,7 @@
C(rs, "rs", "RS category") \
C(bionic, "bionic", "Bionic category") \
C(power, "power", "Power category") \
- C(packagemanager, "packagemanager", "PackageManager category") \
+ C(packagemanager, "pm", "PackageManager category") \
C(systemserver, "ss", "System Server category") \
C(database, "database", "Database category") \
C(network, "network", "Network category") \
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index ca92ab5..107fd20 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -32,15 +32,15 @@
host_supported: true,
cpp_std: "c++20",
cflags: [
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
"-Wall",
- "-Wextra",
"-Werror",
+ "-Wextra",
"-Wno-unused-parameter",
- "-Wthread-safety",
"-Wshadow",
"-Wshadow-field-in-constructor-modified",
"-Wshadow-uncaptured-local",
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ "-Wthread-safety",
],
sanitize: {
misc_undefined: [
@@ -62,8 +62,8 @@
memtag_heap: true,
undefined: true,
misc_undefined: [
- "bounds",
"all",
+ "bounds",
],
},
},
@@ -114,16 +114,16 @@
"liblog",
"libprotobuf-cpp-lite",
"libstatslog",
- "libutils",
"libstatspull",
"libstatssocket",
+ "libutils",
"packagemanager_aidl-cpp",
"server_configurable_flags",
],
static_libs: [
"libattestation",
- "libperfetto_client_experimental",
"libpalmrejection",
+ "libperfetto_client_experimental",
"libui-types",
],
generated_headers: [
@@ -161,10 +161,10 @@
shared_libs: [
// This should consist only of dependencies from inputflinger. Other dependencies should be
// in cc_defaults so that they are included in the tests.
+ "libPlatformProperties",
"libinputflinger_base",
"libinputreader",
"libinputreporter",
- "libPlatformProperties",
],
static_libs: [
"libinputdispatcher",
@@ -185,8 +185,8 @@
name: "libinputflinger_headers",
host_supported: true,
export_include_dirs: [
- "include",
".",
+ "include",
],
header_libs: [
"libchrome-gestures_headers",
@@ -247,49 +247,40 @@
phony {
name: "checkinput",
required: [
- // native targets
- "libgui_test",
- "libinput",
- "libinputreader_static",
- "libinputflinger",
- "inputflinger_tests",
- "inputflinger_benchmarks",
- "libinput_tests",
- "libpalmrejection_test",
- "libandroid_runtime",
- "libinputservice_test",
"Bug-115739809",
- "StructLayout_test",
-
- // jni
- "libservices.core",
-
- // rust targets
- "libinput_rust_test",
-
- // native fuzzers
- "inputflinger_latencytracker_fuzzer",
- "inputflinger_cursor_input_fuzzer",
- "inputflinger_keyboard_input_fuzzer",
- "inputflinger_multitouch_input_fuzzer",
- "inputflinger_switch_input_fuzzer",
- "inputflinger_touchpad_input_fuzzer",
- "inputflinger_input_reader_fuzzer",
- "inputflinger_blocking_queue_fuzzer",
- "inputflinger_input_classifier_fuzzer",
- "inputflinger_input_dispatcher_fuzzer",
-
- // Java/Kotlin targets
- "CtsWindowManagerDeviceWindow",
- "InputTests",
"CtsHardwareTestCases",
"CtsInputTestCases",
+ "CtsSecurityBulletinHostTestCases",
+ "CtsSecurityTestCases",
"CtsViewTestCases",
"CtsWidgetTestCases",
+ "CtsWindowManagerDeviceWindow",
"FrameworksCoreTests",
"FrameworksServicesTests",
- "CtsSecurityTestCases",
- "CtsSecurityBulletinHostTestCases",
+ "InputTests",
+ "StructLayout_test",
+ "inputflinger_benchmarks",
+ "inputflinger_blocking_queue_fuzzer",
+ "inputflinger_cursor_input_fuzzer",
+ "inputflinger_input_classifier_fuzzer",
+ "inputflinger_input_dispatcher_fuzzer",
+ "inputflinger_input_reader_fuzzer",
+ "inputflinger_keyboard_input_fuzzer",
+ "inputflinger_latencytracker_fuzzer",
+ "inputflinger_multitouch_input_fuzzer",
+ "inputflinger_switch_input_fuzzer",
+ "inputflinger_tests",
+ "inputflinger_touchpad_input_fuzzer",
+ "libandroid_runtime",
+ "libgui_test",
+ "libinput",
+ "libinput_rust_test",
+ "libinput_tests",
+ "libinputflinger",
+ "libinputreader_static",
+ "libinputservice_test",
+ "libpalmrejection_test",
+ "libservices.core",
"monkey_test",
],
}
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
index 2ef94fb..bb4e617 100644
--- a/services/inputflinger/InputFilter.cpp
+++ b/services/inputflinger/InputFilter.cpp
@@ -56,7 +56,7 @@
void InputFilter::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
mDeviceInfos.clear();
mDeviceInfos.reserve(args.inputDeviceInfos.size());
- for (auto info : args.inputDeviceInfos) {
+ for (const auto& info : args.inputDeviceInfos) {
AidlDeviceInfo& aidlInfo = mDeviceInfos.emplace_back();
aidlInfo.deviceId = info.getId();
aidlInfo.external = info.isExternal();
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 9f91285..3140dc8 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "PointerChoreographer"
#include <android-base/logging.h>
+#include <android/configuration.h>
#include <com_android_input_flags.h>
#if defined(__ANDROID__)
#include <gui/SurfaceComposerClient.h>
@@ -114,6 +115,17 @@
}
}
+// The standardised medium display density for which 1 px = 1 dp
+constexpr int32_t DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM;
+
+inline float pxToDp(int px, int dpi) {
+ return static_cast<float>(px * DENSITY_MEDIUM) / static_cast<float>(dpi);
+}
+
+inline int dpToPx(float dp, int dpi) {
+ return static_cast<int>((dp * dpi) / DENSITY_MEDIUM);
+}
+
} // namespace
// --- PointerChoreographer ---
@@ -385,8 +397,7 @@
pc.fade(PointerControllerInterface::Transition::IMMEDIATE);
pc.setDisplayViewport(destinationViewport);
vec2 destinationPosition =
- calculatePositionOnDestinationViewport(destinationViewport,
- cursorOffset - destinationOffset,
+ calculatePositionOnDestinationViewport(destinationViewport, destinationOffset,
sourceBoundary);
// Transform position back to un-rotated coordinate space before sending it to controller
@@ -990,10 +1001,10 @@
return ConstructorDelegate(std::move(ctor));
}
-std::optional<std::pair<const DisplayViewport*, float /*offset*/>>
+std::optional<std::pair<const DisplayViewport*, float /*offsetPx*/>>
PointerChoreographer::findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
const DisplayTopologyPosition sourceBoundary,
- float cursorOffset) const {
+ int32_t sourceCursorOffsetPx) const {
const auto& sourceNode = mTopology.graph.find(sourceDisplayId);
if (sourceNode == mTopology.graph.end()) {
// Topology is likely out of sync with viewport info, wait for it to be updated
@@ -1004,22 +1015,32 @@
if (adjacentDisplay.position != sourceBoundary) {
continue;
}
- const DisplayViewport* destinationViewport =
- findViewportByIdLocked(adjacentDisplay.displayId);
- if (destinationViewport == nullptr) {
+ const DisplayViewport* adjacentViewport = findViewportByIdLocked(adjacentDisplay.displayId);
+ if (adjacentViewport == nullptr) {
// Topology is likely out of sync with viewport info, wait for them to be updated
LOG(WARNING) << "Cannot find viewport for adjacent display "
<< adjacentDisplay.displayId << "of source display " << sourceDisplayId;
continue;
}
- // target position must be within target display boundary
- const int32_t edgeSize = sourceBoundary == DisplayTopologyPosition::TOP ||
+ // As displays can have different densities we need to do all calculations in
+ // density-independent-pixels a.k.a. dp values.
+ const int sourceDensity = mTopology.displaysDensity.at(sourceDisplayId);
+ const int adjacentDisplayDensity = mTopology.displaysDensity.at(adjacentDisplay.displayId);
+ const float sourceCursorOffsetDp = pxToDp(sourceCursorOffsetPx, sourceDensity);
+ const int32_t edgeSizePx = sourceBoundary == DisplayTopologyPosition::TOP ||
sourceBoundary == DisplayTopologyPosition::BOTTOM
- ? (destinationViewport->logicalRight - destinationViewport->logicalLeft)
- : (destinationViewport->logicalBottom - destinationViewport->logicalTop);
- if (cursorOffset >= adjacentDisplay.offsetDp &&
- cursorOffset <= adjacentDisplay.offsetDp + edgeSize) {
- return std::make_pair(destinationViewport, adjacentDisplay.offsetDp);
+ ? (adjacentViewport->logicalRight - adjacentViewport->logicalLeft)
+ : (adjacentViewport->logicalBottom - adjacentViewport->logicalTop);
+ const float adjacentEdgeSizeDp = pxToDp(edgeSizePx, adjacentDisplayDensity);
+ // Target position must be within target display boundary.
+ // Cursor should also be able to cross displays when only display corners are touching and
+ // there may be zero overlapping pixels. To accommodate this we have margin of one pixel
+ // around the end of the overlapping edge.
+ if (sourceCursorOffsetDp >= adjacentDisplay.offsetDp &&
+ sourceCursorOffsetDp <= adjacentDisplay.offsetDp + adjacentEdgeSizeDp) {
+ const int destinationOffsetPx =
+ dpToPx(sourceCursorOffsetDp - adjacentDisplay.offsetDp, adjacentDisplayDensity);
+ return std::make_pair(adjacentViewport, destinationOffsetPx);
}
}
return std::nullopt;
diff --git a/services/inputflinger/PointerChoreographer.h b/services/inputflinger/PointerChoreographer.h
index c2f5ec0..a9d971a 100644
--- a/services/inputflinger/PointerChoreographer.h
+++ b/services/inputflinger/PointerChoreographer.h
@@ -163,10 +163,10 @@
void handleUnconsumedDeltaLocked(PointerControllerInterface& pc, const vec2& unconsumedDelta)
REQUIRES(getLock());
- std::optional<std::pair<const DisplayViewport*, float /*offset*/>> findDestinationDisplayLocked(
- const ui::LogicalDisplayId sourceDisplayId,
- const DisplayTopologyPosition sourceBoundary, float cursorOffset) const
- REQUIRES(getLock());
+ std::optional<std::pair<const DisplayViewport*, float /*offsetPx*/>>
+ findDestinationDisplayLocked(const ui::LogicalDisplayId sourceDisplayId,
+ const DisplayTopologyPosition sourceBoundary,
+ int32_t sourceCursorOffsetPx) const REQUIRES(getLock());
/* Topology is initialized with default-constructed value, which is an empty topology. Till we
* receive setDisplayTopology call.
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 8b2b843..1aa8b2b 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -49,8 +49,8 @@
"LatencyAggregatorWithHistograms.cpp",
"LatencyTracker.cpp",
"Monitor.cpp",
- "TouchedWindow.cpp",
"TouchState.cpp",
+ "TouchedWindow.cpp",
"trace/*.cpp",
],
}
@@ -71,9 +71,9 @@
"liblog",
"libprotobuf-cpp-lite",
"libstatslog",
- "libutils",
"libstatspull",
"libstatssocket",
+ "libutils",
"packagemanager_aidl-cpp",
"server_configurable_flags",
],
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 098019f..11ba592 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1267,13 +1267,9 @@
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
// The event is stale. However, only drop stale events if there isn't an ongoing
// gesture. That would allow us to complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
- const TouchState& touchState = touchStateIt->second;
- if (!touchState.hasTouchingPointers(motionEntry->deviceId) &&
- !touchState.hasHoveringPointers(motionEntry->deviceId)) {
- dropReason = DropReason::STALE;
- }
+ if (!mTouchStates.hasTouchingOrHoveringPointers(motionEntry->displayId,
+ motionEntry->deviceId)) {
+ dropReason = DropReason::STALE;
}
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
@@ -1355,7 +1351,8 @@
// Alternatively, maybe there's a spy window that could handle this event.
const std::vector<sp<WindowInfoHandle>> touchedSpies =
mWindowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus,
- motionEntry.deviceId, mTouchStatesByDisplay);
+ motionEntry.deviceId,
+ mTouchStates.mTouchStatesByDisplay);
for (const auto& windowHandle : touchedSpies) {
const std::shared_ptr<Connection> connection =
mConnectionManager.getConnection(windowHandle->getToken());
@@ -1480,15 +1477,16 @@
return nullptr;
}
-std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
- ui::LogicalDisplayId displayId, const sp<WindowInfoHandle>& touchedWindow,
- int32_t pointerId) const {
+std::vector<InputTarget> InputDispatcher::DispatcherTouchState::findOutsideTargets(
+ ui::LogicalDisplayId displayId, const sp<gui::WindowInfoHandle>& touchedWindow,
+ int32_t pointerId, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos, std::function<void()> dump) {
if (touchedWindow == nullptr) {
return {};
}
// Traverse windows from front to back until we encounter the touched window.
std::vector<InputTarget> outsideTargets;
- const auto& windowHandles = mWindowInfos.getWindowHandlesForDisplay(displayId);
+ const auto& windowHandles = windowInfos.getWindowHandlesForDisplay(displayId);
for (const sp<WindowInfoHandle>& windowHandle : windowHandles) {
if (windowHandle == touchedWindow) {
// Stop iterating once we found a touched window. Any WATCH_OUTSIDE_TOUCH window
@@ -1500,9 +1498,13 @@
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(pointerId);
- addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::OUTSIDE,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- /*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
+ DispatcherTouchState::addPointerWindowTarget(windowHandle,
+ InputTarget::DispatchMode::OUTSIDE,
+ ftl::Flags<InputTarget::Flags>(),
+ pointerIds,
+ /*firstDownTimeInTarget=*/std::nullopt,
+ connections, windowInfos, dump,
+ outsideTargets);
}
}
return outsideTargets;
@@ -1709,9 +1711,7 @@
synthesizeCancelationEventsForAllConnectionsLocked(options);
// Remove all active pointers from this device
- for (auto& [_, touchState] : mTouchStatesByDisplay) {
- touchState.removeAllPointersForDevice(entry.deviceId);
- }
+ mTouchStates.removeAllPointersForDevice(entry.deviceId);
return true;
}
@@ -2073,7 +2073,16 @@
}
Result<std::vector<InputTarget>, InputEventInjectionResult> result =
- findTouchedWindowTargetsLocked(currentTime, *entry);
+ mTouchStates
+ .findTouchedWindowTargets(currentTime, *entry, mConnectionManager,
+ mWindowInfos,
+ mDragState ? mDragState->dragWindow : nullptr,
+ std::bind_front(&InputDispatcher::
+ addDragEventLocked,
+ this),
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this));
if (result.ok()) {
inputTargets = std::move(*result);
@@ -2318,7 +2327,8 @@
}
// Drop key events if requested by input feature
- if (focusedWindowHandle != nullptr && shouldDropInput(entry, focusedWindowHandle)) {
+ if (focusedWindowHandle != nullptr &&
+ shouldDropInput(entry, focusedWindowHandle, mWindowInfos)) {
return injectionError(InputEventInjectionResult::FAILED);
}
@@ -2387,8 +2397,12 @@
return focusedWindowHandle;
}
-base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
-InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
+base::Result<std::vector<InputTarget>, os::InputEventInjectionResult>
+InputDispatcher::DispatcherTouchState::findTouchedWindowTargets(
+ nsecs_t currentTime, const MotionEntry& entry, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ const sp<android::gui::WindowInfoHandle> dragWindow,
+ std::function<void(const MotionEntry&)> addDragEvent, std::function<void()> dump) {
ATRACE_CALL();
std::vector<InputTarget> targets;
@@ -2448,10 +2462,12 @@
// be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
const bool isStylus = isPointerFromStylus(entry, pointerIndex);
sp<WindowInfoHandle> newTouchedWindowHandle =
- mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
+ windowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
if (isDown) {
- targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointer.id);
+ targets += DispatcherTouchState::findOutsideTargets(displayId, newTouchedWindowHandle,
+ pointer.id, connections,
+ windowInfos, dump);
}
LOG_IF(INFO, newTouchedWindowHandle == nullptr)
<< "No new touched window at (" << std::format("{:.1f}, {:.1f}", x, y)
@@ -2464,8 +2480,8 @@
}
std::vector<sp<WindowInfoHandle>> newTouchedWindows =
- mWindowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId,
- mTouchStatesByDisplay);
+ windowInfos.findTouchedSpyWindowsAt(displayId, x, y, isStylus, entry.deviceId,
+ mTouchStatesByDisplay);
if (newTouchedWindowHandle != nullptr) {
// Process the foreground window first so that it is the first to receive the event.
newTouchedWindows.insert(newTouchedWindows.begin(), newTouchedWindowHandle);
@@ -2478,7 +2494,8 @@
}
for (const sp<WindowInfoHandle>& windowHandle : newTouchedWindows) {
- if (!canWindowReceiveMotionLocked(windowHandle, entry)) {
+ if (!canWindowReceiveMotion(windowHandle, entry, connections, windowInfos,
+ mTouchStatesByDisplay)) {
continue;
}
@@ -2489,21 +2506,9 @@
}
// Set target flags.
- ftl::Flags<InputTarget::Flags> targetFlags;
-
- if (canReceiveForegroundTouches(*windowHandle->getInfo())) {
- // There should only be one touched window that can be "foreground" for the pointer.
- targetFlags |= InputTarget::Flags::FOREGROUND;
- }
-
- if (isSplit) {
- targetFlags |= InputTarget::Flags::SPLIT;
- }
- if (mWindowInfos.isWindowObscuredAtPoint(windowHandle, x, y)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
- } else if (mWindowInfos.isWindowObscured(windowHandle)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ ftl::Flags<InputTarget::Flags> targetFlags =
+ DispatcherTouchState::getTargetFlags(windowHandle, {x, y}, isSplit,
+ windowInfos);
// Update the temporary touch state.
@@ -2521,7 +2526,7 @@
if (!addResult.ok()) {
LOG(ERROR) << "Error while processing " << entry << " for "
<< windowHandle->getName();
- logDispatchStateLocked();
+ dump();
}
// If this is the pointer going down and the touched window has a wallpaper
// then also add the touched wallpaper windows so they are locked in for the
@@ -2533,7 +2538,7 @@
windowHandle->getInfo()->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
sp<WindowInfoHandle> wallpaper =
- mWindowInfos.findWallpaperWindowBelow(windowHandle);
+ windowInfos.findWallpaperWindowBelow(windowHandle);
if (wallpaper != nullptr) {
ftl::Flags<InputTarget::Flags> wallpaperFlags =
InputTarget::Flags::WINDOW_IS_OBSCURED |
@@ -2592,7 +2597,7 @@
tempTouchState.removeHoveringPointer(entry.deviceId, pointerId);
}
- addDragEventLocked(entry);
+ addDragEvent(entry);
// Check whether touches should slip outside of the current foreground window.
if (maskedAction == AMOTION_EVENT_ACTION_MOVE && entry.getPointerCount() == 1 &&
@@ -2603,7 +2608,7 @@
tempTouchState.getFirstForegroundWindowHandle(entry.deviceId);
LOG_ALWAYS_FATAL_IF(oldTouchedWindowHandle == nullptr);
sp<WindowInfoHandle> newTouchedWindowHandle =
- mWindowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
+ windowInfos.findTouchedWindowAt(displayId, x, y, isStylus);
// Verify targeted injection.
if (const auto err = verifyTargetedInjection(newTouchedWindowHandle, entry); err) {
@@ -2613,7 +2618,8 @@
// Do not slide events to the window which can not receive motion event
if (newTouchedWindowHandle != nullptr &&
- !canWindowReceiveMotionLocked(newTouchedWindowHandle, entry)) {
+ !canWindowReceiveMotion(newTouchedWindowHandle, entry, connections, windowInfos,
+ mTouchStatesByDisplay)) {
newTouchedWindowHandle = nullptr;
}
@@ -2630,26 +2636,18 @@
const TouchedWindow& touchedWindow =
tempTouchState.getTouchedWindow(oldTouchedWindowHandle);
- addPointerWindowTargetLocked(oldTouchedWindowHandle,
- InputTarget::DispatchMode::SLIPPERY_EXIT,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- touchedWindow.getDownTimeInTarget(entry.deviceId),
- targets);
+ DispatcherTouchState::
+ addPointerWindowTarget(oldTouchedWindowHandle,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ touchedWindow.getDownTimeInTarget(entry.deviceId),
+ connections, windowInfos, dump, targets);
// Make a slippery entrance into the new window.
- ftl::Flags<InputTarget::Flags> targetFlags;
- if (canReceiveForegroundTouches(*newTouchedWindowHandle->getInfo())) {
- targetFlags |= InputTarget::Flags::FOREGROUND;
- }
- if (isSplit) {
- targetFlags |= InputTarget::Flags::SPLIT;
- }
- if (mWindowInfos.isWindowObscuredAtPoint(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
- } else if (mWindowInfos.isWindowObscured(newTouchedWindowHandle)) {
- targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
- }
+ ftl::Flags<InputTarget::Flags> targetFlags =
+ DispatcherTouchState::getTargetFlags(newTouchedWindowHandle, {x, y},
+ isSplit, windowInfos);
tempTouchState.addOrUpdateWindow(newTouchedWindowHandle,
InputTarget::DispatchMode::SLIPPERY_ENTER,
@@ -2657,8 +2655,10 @@
entry.eventTime);
// Check if the wallpaper window should deliver the corresponding event.
- slipWallpaperTouch(targetFlags, oldTouchedWindowHandle, newTouchedWindowHandle,
- tempTouchState, entry, targets);
+ DispatcherTouchState::slipWallpaperTouch(targetFlags, oldTouchedWindowHandle,
+ newTouchedWindowHandle, tempTouchState,
+ entry, targets, connections, windowInfos,
+ dump);
tempTouchState.removeTouchingPointerFromWindow(entry.deviceId, pointer.id,
oldTouchedWindowHandle);
}
@@ -2671,7 +2671,7 @@
std::vector<PointerProperties> touchingPointers{entry.pointerProperties[pointerIndex]};
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
// Ignore drag window for it should just track one pointer.
- if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
+ if (dragWindow == touchedWindow.windowHandle) {
continue;
}
if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
@@ -2685,17 +2685,17 @@
// Update dispatching for hover enter and exit.
{
std::vector<TouchedWindow> hoveringWindows =
- getHoveringWindowsLocked(oldState, tempTouchState, entry,
- std::bind_front(&InputDispatcher::logDispatchStateLocked,
- this));
+ getHoveringWindowsLocked(oldState, tempTouchState, entry, dump);
// Hardcode to single hovering pointer for now.
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(entry.pointerProperties[0].id);
for (const TouchedWindow& touchedWindow : hoveringWindows) {
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags, pointerIds,
- touchedWindow.getDownTimeInTarget(entry.deviceId),
- targets);
+ DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle,
+ touchedWindow.dispatchMode,
+ touchedWindow.targetFlags, pointerIds,
+ touchedWindow.getDownTimeInTarget(
+ entry.deviceId),
+ connections, windowInfos, dump, targets);
}
}
@@ -2724,7 +2724,7 @@
for (InputTarget& target : targets) {
if (target.dispatchMode == InputTarget::DispatchMode::OUTSIDE) {
sp<WindowInfoHandle> targetWindow =
- mWindowInfos.findWindowHandle(target.connection->getToken());
+ windowInfos.findWindowHandle(target.connection->getToken());
if (targetWindow->getInfo()->ownerUid != foregroundWindowUid) {
target.flags |= InputTarget::Flags::ZERO_COORDS;
}
@@ -2748,9 +2748,13 @@
if (touchingPointers.empty()) {
continue;
}
- addPointerWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.dispatchMode,
- touchedWindow.targetFlags, getPointerIds(touchingPointers),
- touchedWindow.getDownTimeInTarget(entry.deviceId), targets);
+ DispatcherTouchState::addPointerWindowTarget(touchedWindow.windowHandle,
+ touchedWindow.dispatchMode,
+ touchedWindow.targetFlags,
+ getPointerIds(touchingPointers),
+ touchedWindow.getDownTimeInTarget(
+ entry.deviceId),
+ connections, windowInfos, dump, targets);
}
// During targeted injection, only allow owned targets to receive events
@@ -2953,11 +2957,12 @@
}
}
-void InputDispatcher::addPointerWindowTargetLocked(
+void InputDispatcher::DispatcherTouchState::addPointerWindowTarget(
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,
- std::vector<InputTarget>& inputTargets) const REQUIRES(mLock) {
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump, std::vector<InputTarget>& inputTargets) {
if (pointerIds.none()) {
for (const auto& target : inputTargets) {
LOG(INFO) << "Target: " << target;
@@ -2982,19 +2987,17 @@
it = inputTargets.end();
}
- const WindowInfo* windowInfo = windowHandle->getInfo();
+ const WindowInfo& windowInfo = *windowHandle->getInfo();
if (it == inputTargets.end()) {
- std::shared_ptr<Connection> connection =
- mConnectionManager.getConnection(windowHandle->getToken());
+ std::shared_ptr<Connection> connection = connections.getConnection(windowInfo.token);
if (connection == nullptr) {
- ALOGW("Not creating InputTarget for %s, no input channel",
- windowHandle->getName().c_str());
+ ALOGW("Not creating InputTarget for %s, no input channel", windowInfo.name.c_str());
return;
}
inputTargets.push_back(
createInputTarget(connection, windowHandle, dispatchMode, targetFlags,
- mWindowInfos.getRawTransform(*windowHandle->getInfo()),
+ windowInfos.getRawTransform(*windowHandle->getInfo()),
firstDownTimeInTarget));
it = inputTargets.end() - 1;
}
@@ -3007,14 +3010,14 @@
LOG(ERROR) << __func__ << ": Flags don't match! new targetFlags=" << targetFlags.string()
<< ", it=" << *it;
}
- if (it->globalScaleFactor != windowInfo->globalScaleFactor) {
+ if (it->globalScaleFactor != windowInfo.globalScaleFactor) {
LOG(ERROR) << __func__ << ": Mismatch! it->globalScaleFactor=" << it->globalScaleFactor
- << ", windowInfo->globalScaleFactor=" << windowInfo->globalScaleFactor;
+ << ", windowInfo->globalScaleFactor=" << windowInfo.globalScaleFactor;
}
- Result<void> result = it->addPointers(pointerIds, windowInfo->transform);
+ Result<void> result = it->addPointers(pointerIds, windowInfo.transform);
if (!result.ok()) {
- logDispatchStateLocked();
+ dump();
LOG(FATAL) << result.error().message();
}
}
@@ -4069,7 +4072,7 @@
// Generate cancellations for touched windows first. This is to avoid generating cancellations
// through a non-touched window if there are more than one window for an input channel.
if (cancelPointers) {
- for (const auto& [displayId, touchState] : mTouchStatesByDisplay) {
+ for (const auto& [displayId, touchState] : mTouchStates.mTouchStatesByDisplay) {
if (options.displayId.has_value() && options.displayId != displayId) {
continue;
}
@@ -4204,9 +4207,15 @@
sendDropWindowCommandLocked(nullptr, /*x=*/0, /*y=*/0);
mDragState.reset();
}
- addPointerWindowTargetLocked(window, InputTarget::DispatchMode::AS_IS,
- ftl::Flags<InputTarget::Flags>(), pointerIds,
- motionEntry.downTime, targets);
+ DispatcherTouchState::
+ addPointerWindowTarget(window, InputTarget::DispatchMode::AS_IS,
+ ftl::Flags<InputTarget::Flags>(), pointerIds,
+ motionEntry.downTime, mConnectionManager,
+ mWindowInfos,
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this),
+ targets);
} else {
targets.emplace_back(fallbackTarget);
// Since we don't have a window, use the display transform as the raw transform.
@@ -4268,7 +4277,8 @@
}
const auto [_, touchedWindowState, displayId] =
- findTouchStateWindowAndDisplay(connection->getToken(), mTouchStatesByDisplay);
+ findTouchStateWindowAndDisplay(connection->getToken(),
+ mTouchStates.mTouchStatesByDisplay);
if (touchedWindowState == nullptr) {
LOG(FATAL) << __func__ << ": Touch state is out of sync: No touched window for token";
}
@@ -4290,9 +4300,14 @@
pointerIndex++) {
pointerIds.set(motionEntry.pointerProperties[pointerIndex].id);
}
- addPointerWindowTargetLocked(windowHandle, InputTarget::DispatchMode::AS_IS,
- targetFlags, pointerIds, motionEntry.downTime,
- targets);
+ DispatcherTouchState::
+ addPointerWindowTarget(windowHandle, InputTarget::DispatchMode::AS_IS,
+ targetFlags, pointerIds, motionEntry.downTime,
+ mConnectionManager, mWindowInfos,
+ std::bind_front(&InputDispatcher::
+ logDispatchStateLocked,
+ this),
+ targets);
} else {
targets.emplace_back(connection, targetFlags);
// Since we don't have a window, use the display transform as the raw transform.
@@ -4559,13 +4574,8 @@
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// Set the flag anyway if we already have an ongoing gesture. That would allow us to
// complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(args.displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
- const TouchState& touchState = touchStateIt->second;
- if (touchState.hasTouchingPointers(args.deviceId) ||
- touchState.hasHoveringPointers(args.deviceId)) {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
- }
+ if (mTouchStates.hasTouchingOrHoveringPointers(args.displayId, args.deviceId)) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
@@ -4871,13 +4881,8 @@
if (!(policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// Set the flag anyway if we already have an ongoing motion gesture. That
// would allow us to complete the processing of the current stroke.
- const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
- if (touchStateIt != mTouchStatesByDisplay.end()) {
- const TouchState& touchState = touchStateIt->second;
- if (touchState.hasTouchingPointers(resolvedDeviceId) ||
- touchState.hasHoveringPointers(resolvedDeviceId)) {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
- }
+ if (mTouchStates.hasTouchingOrHoveringPointers(displayId, resolvedDeviceId)) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
@@ -5266,9 +5271,11 @@
return dump;
}
-bool InputDispatcher::canWindowReceiveMotionLocked(
+bool InputDispatcher::canWindowReceiveMotion(
const sp<android::gui::WindowInfoHandle>& window,
- const android::inputdispatcher::MotionEntry& motionEntry) const {
+ const android::inputdispatcher::MotionEntry& motionEntry,
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStates) {
const WindowInfo& info = *window->getInfo();
// Skip spy window targets that are not valid for targeted injection.
@@ -5287,7 +5294,7 @@
return false;
}
- std::shared_ptr<Connection> connection = mConnectionManager.getConnection(window->getToken());
+ std::shared_ptr<Connection> connection = connections.getConnection(window->getToken());
if (connection == nullptr) {
ALOGW("Not sending touch to %s because there's no corresponding connection",
window->getName().c_str());
@@ -5302,8 +5309,8 @@
// Drop events that can't be trusted due to occlusion
const auto [x, y] = resolveTouchedPosition(motionEntry);
DispatcherWindowInfo::TouchOcclusionInfo occlusionInfo =
- mWindowInfos.computeTouchOcclusionInfo(window, x, y);
- if (!mWindowInfos.isTouchTrusted(occlusionInfo)) {
+ windowInfos.computeTouchOcclusionInfo(window, x, y);
+ if (!windowInfos.isTouchTrusted(occlusionInfo)) {
if (DEBUG_TOUCH_OCCLUSION) {
ALOGD("Stack of obscuring windows during untrusted touch (%.1f, %.1f):", x, y);
for (const auto& log : occlusionInfo.debugInfo) {
@@ -5316,13 +5323,13 @@
}
// Drop touch events if requested by input feature
- if (shouldDropInput(motionEntry, window)) {
+ if (shouldDropInput(motionEntry, window, windowInfos)) {
return false;
}
// Ignore touches if stylus is down anywhere on screen
if (info.inputConfig.test(WindowInfo::InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH) &&
- isStylusActiveInDisplay(info.displayId, mTouchStatesByDisplay)) {
+ isStylusActiveInDisplay(info.displayId, touchStates)) {
LOG(INFO) << "Dropping touch from " << window->getName() << " because stylus is active";
return false;
}
@@ -5446,70 +5453,38 @@
onFocusChangedLocked(*changes, traceContext.getTracker(), removedFocusedWindowHandle);
}
- if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
- TouchState& state = it->second;
- for (size_t i = 0; i < state.windows.size();) {
- TouchedWindow& touchedWindow = state.windows[i];
- if (mWindowInfos.isWindowPresent(touchedWindow.windowHandle)) {
- i++;
- continue;
- }
- LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
- << " in display %" << displayId;
- CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
- "touched window was removed", traceContext.getTracker());
- synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
- // Since we are about to drop the touch, cancel the events for the wallpaper as
- // well.
- if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
- touchedWindow.windowHandle->getInfo()->inputConfig.test(
- gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
- for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
- if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
- options.deviceId = deviceId;
- synthesizeCancelationEventsForWindowLocked(ww, options);
- }
- }
- }
- state.windows.erase(state.windows.begin() + i);
- }
-
- // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
- // could just clear the state here.
- if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
- std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
- windowHandles.end()) {
- ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
- sendDropWindowCommandLocked(nullptr, 0, 0);
- mDragState.reset();
+ CancelationOptions pointerCancellationOptions(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ "touched window was removed",
+ traceContext.getTracker());
+ CancelationOptions hoverCancellationOptions(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
+ "WindowInfo changed", traceContext.getTracker());
+ const std::list<DispatcherTouchState::CancellationArgs> cancellations =
+ mTouchStates.updateFromWindowInfo(displayId, mWindowInfos);
+ for (const auto& cancellationArgs : cancellations) {
+ switch (cancellationArgs.mode) {
+ case CancelationOptions::Mode::CANCEL_POINTER_EVENTS:
+ pointerCancellationOptions.deviceId = cancellationArgs.deviceId;
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
+ pointerCancellationOptions);
+ break;
+ case CancelationOptions::Mode::CANCEL_HOVER_EVENTS:
+ hoverCancellationOptions.deviceId = cancellationArgs.deviceId;
+ synthesizeCancelationEventsForWindowLocked(cancellationArgs.windowHandle,
+ hoverCancellationOptions);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unexpected cancellation Mode");
}
}
- // Check if the hovering should stop because the window is no longer eligible to receive it
- // (for example, if the touchable region changed)
- if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
- TouchState& state = it->second;
- for (TouchedWindow& touchedWindow : state.windows) {
- std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
- [this, displayId, &touchedWindow](const PointerProperties& properties, float x,
- float y) REQUIRES(mLock) {
- const bool isStylus = properties.toolType == ToolType::STYLUS;
- const ui::Transform displayTransform =
- mWindowInfos.getDisplayTransform(displayId);
- const bool stillAcceptsTouch =
- windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(),
- displayId, x, y, isStylus, displayTransform);
- return !stillAcceptsTouch;
- });
-
- for (DeviceId deviceId : erasedDevices) {
- CancelationOptions options(CancelationOptions::Mode::CANCEL_HOVER_EVENTS,
- "WindowInfo changed",
- traceContext.getTracker());
- options.deviceId = deviceId;
- synthesizeCancelationEventsForWindowLocked(touchedWindow.windowHandle, options);
- }
- }
+ // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We
+ // could just clear the state here.
+ if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId &&
+ std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) ==
+ windowHandles.end()) {
+ ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str());
+ sendDropWindowCommandLocked(nullptr, 0, 0);
+ mDragState.reset();
}
// Release information for windows that are no longer present.
@@ -5526,6 +5501,76 @@
}
}
+std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
+InputDispatcher::DispatcherTouchState::updateFromWindowInfo(
+ ui::LogicalDisplayId displayId, const DispatcherWindowInfo& windowInfos) {
+ std::list<CancellationArgs> cancellations;
+ if (const auto& it = mTouchStatesByDisplay.find(displayId); it != mTouchStatesByDisplay.end()) {
+ TouchState& state = it->second;
+ cancellations = eraseRemovedWindowsFromWindowInfo(state, displayId, windowInfos);
+ cancellations.splice(cancellations.end(),
+ updateHoveringStateFromWindowInfo(state, displayId, windowInfos));
+ }
+ return cancellations;
+}
+
+std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
+InputDispatcher::DispatcherTouchState::eraseRemovedWindowsFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId,
+ const DispatcherWindowInfo& windowInfos) {
+ std::list<CancellationArgs> cancellations;
+ for (auto it = state.windows.begin(); it != state.windows.end();) {
+ TouchedWindow& touchedWindow = *it;
+ if (windowInfos.isWindowPresent(touchedWindow.windowHandle)) {
+ it++;
+ continue;
+ }
+ LOG(INFO) << "Touched window was removed: " << touchedWindow.windowHandle->getName()
+ << " in display %" << displayId;
+ cancellations.emplace_back(touchedWindow.windowHandle,
+ CancelationOptions::Mode::CANCEL_POINTER_EVENTS, std::nullopt);
+ // Since we are about to drop the touch, cancel the events for the wallpaper as well.
+ if (touchedWindow.targetFlags.test(InputTarget::Flags::FOREGROUND) &&
+ touchedWindow.windowHandle->getInfo()->inputConfig.test(
+ gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER)) {
+ for (const DeviceId deviceId : touchedWindow.getTouchingDeviceIds()) {
+ if (const auto& ww = state.getWallpaperWindow(deviceId); ww != nullptr) {
+ cancellations.emplace_back(ww, CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
+ deviceId);
+ }
+ }
+ }
+ it = state.windows.erase(it);
+ }
+ return cancellations;
+}
+
+std::list<InputDispatcher::DispatcherTouchState::CancellationArgs>
+InputDispatcher::DispatcherTouchState::updateHoveringStateFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId,
+ const DispatcherWindowInfo& windowInfos) {
+ std::list<CancellationArgs> cancellations;
+ // Check if the hovering should stop because the window is no longer eligible to receive it
+ // (for example, if the touchable region changed)
+ ui::Transform displayTransform = windowInfos.getDisplayTransform(displayId);
+ for (TouchedWindow& touchedWindow : state.windows) {
+ std::vector<DeviceId> erasedDevices = touchedWindow.eraseHoveringPointersIf(
+ [&](const PointerProperties& properties, float x, float y) {
+ const bool isStylus = properties.toolType == ToolType::STYLUS;
+ const bool stillAcceptsTouch =
+ windowAcceptsTouchAt(*touchedWindow.windowHandle->getInfo(), displayId,
+ x, y, isStylus, displayTransform);
+ return !stillAcceptsTouch;
+ });
+
+ for (DeviceId deviceId : erasedDevices) {
+ cancellations.emplace_back(touchedWindow.windowHandle,
+ CancelationOptions::Mode::CANCEL_HOVER_EVENTS, deviceId);
+ }
+ }
+ return cancellations;
+}
+
void InputDispatcher::setFocusedApplication(
ui::LogicalDisplayId displayId,
const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
@@ -5793,7 +5838,7 @@
// Find the target touch state and touched window by fromToken.
auto [state, touchedWindow, displayId] =
- findTouchStateWindowAndDisplay(fromToken, mTouchStatesByDisplay);
+ findTouchStateWindowAndDisplay(fromToken, mTouchStates.mTouchStatesByDisplay);
if (state == nullptr || touchedWindow == nullptr) {
ALOGD("Touch transfer failed because from window is not being touched.");
@@ -5885,11 +5930,10 @@
* Return null if there are no windows touched on that display, or if more than one foreground
* window is being touched.
*/
-sp<WindowInfoHandle> InputDispatcher::findTouchedForegroundWindow(
- const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay,
- ui::LogicalDisplayId displayId) {
- const auto stateIt = touchStatesByDisplay.find(displayId);
- if (stateIt == touchStatesByDisplay.end()) {
+sp<WindowInfoHandle> InputDispatcher::DispatcherTouchState::findTouchedForegroundWindow(
+ ui::LogicalDisplayId displayId) const {
+ const auto stateIt = mTouchStatesByDisplay.find(displayId);
+ if (stateIt == mTouchStatesByDisplay.end()) {
ALOGI("No touch state on display %s", displayId.toString().c_str());
return nullptr;
}
@@ -5925,7 +5969,7 @@
return false;
}
- sp<WindowInfoHandle> from = findTouchedForegroundWindow(mTouchStatesByDisplay, displayId);
+ sp<WindowInfoHandle> from = mTouchStates.findTouchedForegroundWindow(displayId);
if (from == nullptr) {
ALOGE("Could not find a source window in %s for %p", __func__, destChannelToken.get());
return false;
@@ -5953,7 +5997,7 @@
resetNoFocusedWindowTimeoutLocked();
mAnrTracker.clear();
- mTouchStatesByDisplay.clear();
+ mTouchStates.clear();
}
void InputDispatcher::logDispatchStateLocked() const {
@@ -6011,15 +6055,7 @@
dump += mFocusResolver.dump();
dump += dumpPointerCaptureStateLocked();
- if (!mTouchStatesByDisplay.empty()) {
- dump += StringPrintf(INDENT "TouchStatesByDisplay:\n");
- for (const auto& [displayId, state] : mTouchStatesByDisplay) {
- std::string touchStateDump = addLinePrefix(state.dump(), INDENT2);
- dump += INDENT2 + displayId.toString() + " : " + touchStateDump;
- }
- } else {
- dump += INDENT "TouchStates: <no displays touched>\n";
- }
+ dump += addLinePrefix(mTouchStates.dump(), INDENT);
if (mDragState) {
dump += StringPrintf(INDENT "DragState:\n");
@@ -6222,7 +6258,7 @@
}
auto [statePtr, windowPtr, displayId] =
- findTouchStateWindowAndDisplay(token, mTouchStatesByDisplay);
+ findTouchStateWindowAndDisplay(token, mTouchStates.mTouchStatesByDisplay);
if (statePtr == nullptr || windowPtr == nullptr) {
LOG(WARNING)
<< "Attempted to pilfer points from a channel without any on-going pointer streams."
@@ -7037,12 +7073,13 @@
mLooper->wake();
}
-bool InputDispatcher::shouldDropInput(
- const EventEntry& entry, const sp<android::gui::WindowInfoHandle>& windowHandle) const {
+bool InputDispatcher::shouldDropInput(const EventEntry& entry,
+ const sp<WindowInfoHandle>& windowHandle,
+ const DispatcherWindowInfo& windowInfos) {
if (windowHandle->getInfo()->inputConfig.test(WindowInfo::InputConfig::DROP_INPUT) ||
(windowHandle->getInfo()->inputConfig.test(
WindowInfo::InputConfig::DROP_INPUT_IF_OBSCURED) &&
- mWindowInfos.isWindowObscured(windowHandle))) {
+ windowInfos.isWindowObscured(windowHandle))) {
ALOGW("Dropping %s event targeting %s as requested by the input configuration {%s} on "
"display %s.",
ftl::enum_string(entry.type).c_str(), windowHandle->getName().c_str(),
@@ -7067,7 +7104,7 @@
"cancel current touch", traceContext.getTracker());
synthesizeCancelationEventsForAllConnectionsLocked(options);
- mTouchStatesByDisplay.clear();
+ mTouchStates.clear();
}
// Wake up poll loop since there might be work to do.
mLooper->wake();
@@ -7078,11 +7115,11 @@
mMonitorDispatchingTimeout = timeout;
}
-void InputDispatcher::slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
- const sp<WindowInfoHandle>& oldWindowHandle,
- const sp<WindowInfoHandle>& newWindowHandle,
- TouchState& state, const MotionEntry& entry,
- std::vector<InputTarget>& targets) const {
+void InputDispatcher::DispatcherTouchState::slipWallpaperTouch(
+ ftl::Flags<InputTarget::Flags> targetFlags, const sp<WindowInfoHandle>& oldWindowHandle,
+ const sp<WindowInfoHandle>& newWindowHandle, TouchState& state, const MotionEntry& entry,
+ std::vector<InputTarget>& targets, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos, std::function<void()> dump) {
LOG_IF(FATAL, entry.getPointerCount() != 1) << "Entry not eligible for slip: " << entry;
const DeviceId deviceId = entry.deviceId;
const PointerProperties& pointerProperties = entry.pointerProperties[0];
@@ -7095,16 +7132,19 @@
const sp<WindowInfoHandle> oldWallpaper =
oldHasWallpaper ? state.getWallpaperWindow(deviceId) : nullptr;
const sp<WindowInfoHandle> newWallpaper =
- newHasWallpaper ? mWindowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr;
+ newHasWallpaper ? windowInfos.findWallpaperWindowBelow(newWindowHandle) : nullptr;
if (oldWallpaper == newWallpaper) {
return;
}
if (oldWallpaper != nullptr) {
const TouchedWindow& oldTouchedWindow = state.getTouchedWindow(oldWallpaper);
- addPointerWindowTargetLocked(oldWallpaper, InputTarget::DispatchMode::SLIPPERY_EXIT,
- oldTouchedWindow.targetFlags, getPointerIds(pointers),
- oldTouchedWindow.getDownTimeInTarget(deviceId), targets);
+ DispatcherTouchState::addPointerWindowTarget(oldWallpaper,
+ InputTarget::DispatchMode::SLIPPERY_EXIT,
+ oldTouchedWindow.targetFlags,
+ getPointerIds(pointers),
+ oldTouchedWindow.getDownTimeInTarget(deviceId),
+ connections, windowInfos, dump, targets);
state.removeTouchingPointerFromWindow(deviceId, pointerProperties.id, oldWallpaper);
}
@@ -7199,18 +7239,7 @@
ui::LogicalDisplayId displayId, DeviceId deviceId,
int32_t pointerId) {
std::scoped_lock _l(mLock);
- auto touchStateIt = mTouchStatesByDisplay.find(displayId);
- if (touchStateIt == mTouchStatesByDisplay.end()) {
- return false;
- }
- for (const TouchedWindow& window : touchStateIt->second.windows) {
- if (window.windowHandle->getToken() == token &&
- (window.hasTouchingPointer(deviceId, pointerId) ||
- window.hasHoveringPointer(deviceId, pointerId))) {
- return true;
- }
- }
- return false;
+ return mTouchStates.isPointerInWindow(token, displayId, deviceId, pointerId);
}
void InputDispatcher::setInputMethodConnectionIsActive(bool isActive) {
@@ -7355,4 +7384,75 @@
mMaximumObscuringOpacityForTouch = opacity;
}
+ftl::Flags<InputTarget::Flags> InputDispatcher::DispatcherTouchState::getTargetFlags(
+ const sp<WindowInfoHandle>& targetWindow, vec2 targetPosition, bool isSplit,
+ const DispatcherWindowInfo& windowInfos) {
+ ftl::Flags<InputTarget::Flags> targetFlags;
+ if (canReceiveForegroundTouches(*targetWindow->getInfo())) {
+ // There should only be one touched window that can be "foreground" for the pointer.
+ targetFlags |= InputTarget::Flags::FOREGROUND;
+ }
+ if (isSplit) {
+ targetFlags |= InputTarget::Flags::SPLIT;
+ }
+ if (windowInfos.isWindowObscuredAtPoint(targetWindow, targetPosition.x, targetPosition.y)) {
+ targetFlags |= InputTarget::Flags::WINDOW_IS_OBSCURED;
+ } else if (windowInfos.isWindowObscured(targetWindow)) {
+ targetFlags |= InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED;
+ }
+ return targetFlags;
+}
+
+bool InputDispatcher::DispatcherTouchState::hasTouchingOrHoveringPointers(
+ ui::LogicalDisplayId displayId, int32_t deviceId) const {
+ const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt == mTouchStatesByDisplay.end()) {
+ return false;
+ }
+ return touchStateIt->second.hasTouchingPointers(deviceId) ||
+ touchStateIt->second.hasHoveringPointers(deviceId);
+}
+
+bool InputDispatcher::DispatcherTouchState::isPointerInWindow(const sp<android::IBinder>& token,
+ ui::LogicalDisplayId displayId,
+ android::DeviceId deviceId,
+ int32_t pointerId) const {
+ const auto touchStateIt = mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt == mTouchStatesByDisplay.end()) {
+ return false;
+ }
+ for (const TouchedWindow& window : touchStateIt->second.windows) {
+ if (window.windowHandle->getToken() == token &&
+ (window.hasTouchingPointer(deviceId, pointerId) ||
+ window.hasHoveringPointer(deviceId, pointerId))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+std::string InputDispatcher::DispatcherTouchState::dump() const {
+ std::string dump;
+ if (!mTouchStatesByDisplay.empty()) {
+ dump += StringPrintf("TouchStatesByDisplay:\n");
+ for (const auto& [displayId, state] : mTouchStatesByDisplay) {
+ std::string touchStateDump = addLinePrefix(state.dump(), INDENT);
+ dump += INDENT + displayId.toString() + " : " + touchStateDump;
+ }
+ } else {
+ dump += "TouchStates: <no displays touched>\n";
+ }
+ return dump;
+}
+
+void InputDispatcher::DispatcherTouchState::removeAllPointersForDevice(android::DeviceId deviceId) {
+ for (auto& [_, touchState] : mTouchStatesByDisplay) {
+ touchState.removeAllPointersForDevice(deviceId);
+ }
+}
+
+void InputDispatcher::DispatcherTouchState::clear() {
+ mTouchStatesByDisplay.clear();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 415f4c8..f590806 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -350,6 +350,96 @@
DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock);
+ class DispatcherTouchState {
+ public:
+ struct CancellationArgs {
+ const sp<gui::WindowInfoHandle> windowHandle;
+ CancelationOptions::Mode mode;
+ std::optional<DeviceId> deviceId;
+ };
+
+ static void addPointerWindowTarget(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,
+ const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump,
+ std::vector<InputTarget>& inputTargets);
+
+ base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
+ findTouchedWindowTargets(nsecs_t currentTime, const MotionEntry& entry,
+ const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ const sp<android::gui::WindowInfoHandle> dragWindow,
+ std::function<void(const MotionEntry&)> addDragEvent,
+ std::function<void()> dump);
+
+ sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow(
+ ui::LogicalDisplayId displayId) const;
+
+ bool hasTouchingOrHoveringPointers(ui::LogicalDisplayId displayId, int32_t deviceId) const;
+
+ bool isPointerInWindow(const sp<android::IBinder>& token, ui::LogicalDisplayId displayId,
+ DeviceId deviceId, int32_t pointerId) const;
+
+ std::string dump() const;
+
+ // Updates the touchState for display from WindowInfo,
+ // return vector of CancellationArgs for every cancelled touch
+ std::list<CancellationArgs> updateFromWindowInfo(ui::LogicalDisplayId displayId,
+ const DispatcherWindowInfo& windowInfos);
+
+ void removeAllPointersForDevice(DeviceId deviceId);
+
+ void clear();
+
+ std::unordered_map<ui::LogicalDisplayId, TouchState> mTouchStatesByDisplay;
+
+ private:
+ static std::list<CancellationArgs> eraseRemovedWindowsFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId,
+ const DispatcherWindowInfo& windowInfos);
+
+ static std::list<CancellationArgs> updateHoveringStateFromWindowInfo(
+ TouchState& state, ui::LogicalDisplayId displayId,
+ const DispatcherWindowInfo& windowInfos);
+
+ static std::vector<InputTarget> findOutsideTargets(
+ ui::LogicalDisplayId displayId, const sp<gui::WindowInfoHandle>& touchedWindow,
+ int32_t pointerId, const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos, std::function<void()> dump);
+
+ /**
+ * Slip the wallpaper touch if necessary.
+ *
+ * @param targetFlags the target flags
+ * @param oldWindowHandle the old window that the touch slipped out of
+ * @param newWindowHandle the new window that the touch is slipping into
+ * @param state the current touch state. This will be updated if necessary to reflect the
+ * new windows that are receiving touch.
+ * @param deviceId the device id of the current motion being processed
+ * @param pointerProperties the pointer properties of the current motion being processed
+ * @param targets the current targets to add the walpaper ones to
+ * @param eventTime the new downTime for the wallpaper target
+ */
+ static void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
+ const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
+ const sp<android::gui::WindowInfoHandle>& newWindowHandle,
+ TouchState& state, const MotionEntry& entry,
+ std::vector<InputTarget>& targets,
+ const ConnectionManager& connections,
+ const DispatcherWindowInfo& windowInfos,
+ std::function<void()> dump);
+
+ static ftl::Flags<InputTarget::Flags> getTargetFlags(
+ const sp<android::gui::WindowInfoHandle>& targetWindow, vec2 targetPosition,
+ bool isSplit, const DispatcherWindowInfo& windowInfos);
+ };
+
+ DispatcherTouchState mTouchStates GUARDED_BY(mLock);
+
// With each iteration, InputDispatcher nominally processes one queued event,
// a timeout, or a response from an input consumer.
// This method should only be called on the input dispatcher's own thread.
@@ -378,14 +468,6 @@
// to transfer focus to a new application.
std::shared_ptr<const EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
- std::vector<InputTarget> findOutsideTargetsLocked(
- ui::LogicalDisplayId displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow,
- int32_t pointerId) const REQUIRES(mLock);
-
- static sp<android::gui::WindowInfoHandle> findTouchedForegroundWindow(
- const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay,
- ui::LogicalDisplayId displayId);
-
status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
const HmacKeyManager mHmacKeyManager;
@@ -470,8 +552,11 @@
sp<android::gui::WindowInfoHandle> getFocusedWindowHandleLocked(
ui::LogicalDisplayId displayId) const REQUIRES(mLock);
- bool canWindowReceiveMotionLocked(const sp<android::gui::WindowInfoHandle>& window,
- const MotionEntry& motionEntry) const REQUIRES(mLock);
+
+ static bool canWindowReceiveMotion(
+ const sp<android::gui::WindowInfoHandle>& window, const MotionEntry& motionEntry,
+ const ConnectionManager& connections, const DispatcherWindowInfo& windowInfos,
+ const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStates);
// Returns all the input targets (with their respective input channels) from the window handles
// passed as argument.
@@ -486,8 +571,6 @@
const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
- std::unordered_map<ui::LogicalDisplayId /*displayId*/, TouchState> mTouchStatesByDisplay
- GUARDED_BY(mLock);
std::unique_ptr<DragState> mDragState GUARDED_BY(mLock);
void setFocusedApplicationLocked(
@@ -627,20 +710,12 @@
base::Result<sp<android::gui::WindowInfoHandle>, android::os::InputEventInjectionResult>
findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry& entry,
nsecs_t& nextWakeupTime) REQUIRES(mLock);
- base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
- findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) 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,
- std::vector<InputTarget>& inputTargets) const REQUIRES(mLock);
void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
@@ -652,9 +727,9 @@
std::string getApplicationWindowLabel(const InputApplicationHandle* applicationHandle,
const sp<android::gui::WindowInfoHandle>& windowHandle);
- bool shouldDropInput(const EventEntry& entry,
- const sp<android::gui::WindowInfoHandle>& windowHandle) const
- REQUIRES(mLock);
+ static bool shouldDropInput(const EventEntry& entry,
+ const sp<android::gui::WindowInfoHandle>& windowHandle,
+ const DispatcherWindowInfo& windowInfo);
// Manage the dispatch cycle for a single connection.
// These methods are deliberately not Interruptible because doing all of the work
@@ -774,24 +849,6 @@
sp<InputReporterInterface> mReporter;
- /**
- * Slip the wallpaper touch if necessary.
- *
- * @param targetFlags the target flags
- * @param oldWindowHandle the old window that the touch slipped out of
- * @param newWindowHandle the new window that the touch is slipping into
- * @param state the current touch state. This will be updated if necessary to reflect the new
- * windows that are receiving touch.
- * @param deviceId the device id of the current motion being processed
- * @param pointerProperties the pointer properties of the current motion being processed
- * @param targets the current targets to add the walpaper ones to
- * @param eventTime the new downTime for the wallpaper target
- */
- void slipWallpaperTouch(ftl::Flags<InputTarget::Flags> targetFlags,
- const sp<android::gui::WindowInfoHandle>& oldWindowHandle,
- const sp<android::gui::WindowInfoHandle>& newWindowHandle,
- TouchState& state, const MotionEntry& entry,
- std::vector<InputTarget>& targets) const REQUIRES(mLock);
void transferWallpaperTouch(ftl::Flags<InputTarget::Flags> oldTargetFlags,
ftl::Flags<InputTarget::Flags> newTargetFlags,
const sp<android::gui::WindowInfoHandle> fromWindowHandle,
diff --git a/services/inputflinger/rust/Android.bp b/services/inputflinger/rust/Android.bp
index 5b7cc2d..78674e5 100644
--- a/services/inputflinger/rust/Android.bp
+++ b/services/inputflinger/rust/Android.bp
@@ -40,14 +40,14 @@
crate_name: "inputflinger",
srcs: ["lib.rs"],
rustlibs: [
- "libcxx",
- "com.android.server.inputflinger-rust",
"android.hardware.input.common-V1-rust",
+ "com.android.server.inputflinger-rust",
"libbinder_rs",
+ "libcxx",
+ "libinput_rust",
"liblog_rust",
"liblogger",
"libnix",
- "libinput_rust",
],
host_supported: true,
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 368db1b..c0e2060 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -9959,57 +9959,63 @@
InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
rate_limit_user_activity_poke_in_dispatcher))) {
+ // Use current time otherwise events may be dropped due to being stale.
+ const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
+
mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
// First event of type TOUCH. Should poke.
notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(50));
+ currentTime + milliseconds_to_nanoseconds(50));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
+ {{currentTime + milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
ui::LogicalDisplayId::DEFAULT}});
// 80ns > 50ns has passed since previous TOUCH event. Should poke.
notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(130));
+ currentTime + milliseconds_to_nanoseconds(130));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
+ {{currentTime + milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
ui::LogicalDisplayId::DEFAULT}});
// First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
- ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
+ ui::LogicalDisplayId::DEFAULT,
+ currentTime + milliseconds_to_nanoseconds(135));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
+ {{currentTime + milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
ui::LogicalDisplayId::DEFAULT}});
// Within 50ns of previous TOUCH event. Should NOT poke.
notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(140));
+ currentTime + milliseconds_to_nanoseconds(140));
mFakePolicy->assertUserActivityNotPoked();
// Within 50ns of previous OTHER event. Should NOT poke.
notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
- ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
+ ui::LogicalDisplayId::DEFAULT,
+ currentTime + milliseconds_to_nanoseconds(150));
mFakePolicy->assertUserActivityNotPoked();
// Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
// Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(160));
+ currentTime + milliseconds_to_nanoseconds(160));
mFakePolicy->assertUserActivityNotPoked();
// 65ns > 50ns has passed since previous OTHER event. Should poke.
notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
- ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
+ ui::LogicalDisplayId::DEFAULT,
+ currentTime + milliseconds_to_nanoseconds(200));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
+ {{currentTime + milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
ui::LogicalDisplayId::DEFAULT}});
// 170ns > 50ns has passed since previous TOUCH event. Should poke.
notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(300));
+ currentTime + milliseconds_to_nanoseconds(300));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
+ {{currentTime + milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
ui::LogicalDisplayId::DEFAULT}});
// Assert that there's no more user activity poke event.
@@ -10020,20 +10026,22 @@
InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
rate_limit_user_activity_poke_in_dispatcher))) {
+ // Use current time otherwise events may be dropped due to being stale.
+ const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(200));
+ currentTime + milliseconds_to_nanoseconds(200));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
+ {{currentTime + milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
ui::LogicalDisplayId::DEFAULT}});
notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(280));
+ currentTime + milliseconds_to_nanoseconds(280));
mFakePolicy->assertUserActivityNotPoked();
notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- milliseconds_to_nanoseconds(340));
+ currentTime + milliseconds_to_nanoseconds(340));
mFakePolicy->assertUserActivityPoked(
- {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
+ {{currentTime + milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
ui::LogicalDisplayId::DEFAULT}});
}
@@ -10041,14 +10049,16 @@
InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
rate_limit_user_activity_poke_in_dispatcher))) {
+ // Use current time otherwise events may be dropped due to being stale.
+ const nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- 20);
+ currentTime + 20);
mFakePolicy->assertUserActivityPoked();
notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
- 30);
+ currentTime + 30);
mFakePolicy->assertUserActivityPoked();
}
diff --git a/services/inputflinger/tests/PointerChoreographer_test.cpp b/services/inputflinger/tests/PointerChoreographer_test.cpp
index 1ca2998..1286a36 100644
--- a/services/inputflinger/tests/PointerChoreographer_test.cpp
+++ b/services/inputflinger/tests/PointerChoreographer_test.cpp
@@ -2617,12 +2617,17 @@
static constexpr ui::LogicalDisplayId DISPLAY_BOTTOM_ID = ui::LogicalDisplayId{40};
static constexpr ui::LogicalDisplayId DISPLAY_LEFT_ID = ui::LogicalDisplayId{50};
static constexpr ui::LogicalDisplayId DISPLAY_TOP_RIGHT_CORNER_ID = ui::LogicalDisplayId{60};
+ static constexpr ui::LogicalDisplayId DISPLAY_HIGH_DENSITY_ID = ui::LogicalDisplayId{70};
+
+ static constexpr int DENSITY_MEDIUM = 160;
+ static constexpr int DENSITY_HIGH = 320;
PointerChoreographerDisplayTopologyTestFixture() {
com::android::input::flags::connected_displays_cursor(true);
}
protected:
+ // Note: viewport size is in pixels and offsets in topology are in dp
std::vector<DisplayViewport> mViewports{
createViewport(DISPLAY_CENTER_ID, /*width*/ 100, /*height*/ 100, ui::ROTATION_0),
createViewport(DISPLAY_TOP_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_0),
@@ -2631,16 +2636,28 @@
createViewport(DISPLAY_LEFT_ID, /*width*/ 90, /*height*/ 90, ui::ROTATION_270),
createViewport(DISPLAY_TOP_RIGHT_CORNER_ID, /*width*/ 90, /*height*/ 90,
ui::ROTATION_0),
+ // Create a high density display size 100x100 dp i.e. 200x200 px
+ createViewport(DISPLAY_HIGH_DENSITY_ID, /*width*/ 200, /*height*/ 200, ui::ROTATION_0),
};
- DisplayTopologyGraph mTopology{DISPLAY_CENTER_ID,
- {{DISPLAY_CENTER_ID,
- {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 10.0f},
- {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
- {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
- {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
- {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT,
- -90.0f}}}}};
+ DisplayTopologyGraph
+ mTopology{DISPLAY_CENTER_ID,
+ {{DISPLAY_CENTER_ID,
+ {{DISPLAY_TOP_ID, DisplayTopologyPosition::TOP, 50.0f},
+ // Place a high density display on the left of DISPLAY_TOP_ID with 25 dp
+ // gap
+ {DISPLAY_HIGH_DENSITY_ID, DisplayTopologyPosition::TOP, -75.0f},
+ {DISPLAY_RIGHT_ID, DisplayTopologyPosition::RIGHT, 10.0f},
+ {DISPLAY_BOTTOM_ID, DisplayTopologyPosition::BOTTOM, 10.0f},
+ {DISPLAY_LEFT_ID, DisplayTopologyPosition::LEFT, 10.0f},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, DisplayTopologyPosition::RIGHT, -90.0f}}}},
+ {{DISPLAY_CENTER_ID, DENSITY_MEDIUM},
+ {DISPLAY_TOP_ID, DENSITY_MEDIUM},
+ {DISPLAY_RIGHT_ID, DENSITY_MEDIUM},
+ {DISPLAY_BOTTOM_ID, DENSITY_MEDIUM},
+ {DISPLAY_LEFT_ID, DENSITY_MEDIUM},
+ {DISPLAY_TOP_RIGHT_CORNER_ID, DENSITY_MEDIUM},
+ {DISPLAY_HIGH_DENSITY_ID, DENSITY_HIGH}}};
private:
DisplayViewport createViewport(ui::LogicalDisplayId displayId, int32_t width, int32_t height,
@@ -2731,7 +2748,7 @@
ToolType::FINGER, vec2(50, 50) /* initial x/y */,
vec2(25, -100) /* delta x/y */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_ID,
- vec2(50 + 25 - 10,
+ vec2(50 + 25 - 50,
90) /* Bottom edge: (source + delta - offset, height) */),
std::make_tuple("TransitionToBottomDisplay",
AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD, ControllerType::MOUSE,
@@ -2739,11 +2756,12 @@
vec2(25, 100) /* delta x/y */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_BOTTOM_ID,
vec2(50 + 25 - 10, 0) /* Top edge: (source + delta - offset, 0) */),
+ // move towards 25 dp gap between DISPLAY_HIGH_DENSITY_ID and DISPLAY_TOP_ID
std::make_tuple("NoTransitionAtTopOffset", AINPUT_SOURCE_MOUSE,
ControllerType::MOUSE, ToolType::MOUSE,
- vec2(5, 50) /* initial x/y */, vec2(0, -100) /* Move Up */,
+ vec2(35, 50) /* initial x/y */, vec2(0, -100) /* Move Up */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_CENTER_ID,
- vec2(5, 0) /* Top edge */),
+ vec2(35, 0) /* Top edge */),
std::make_tuple("NoTransitionAtRightOffset", AINPUT_SOURCE_MOUSE,
ControllerType::MOUSE, ToolType::MOUSE,
vec2(95, 5) /* initial x/y */, vec2(100, 0) /* Move Right */,
@@ -2764,9 +2782,16 @@
std::make_tuple(
"TransitionAtTopRightCorner", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
ControllerType::MOUSE, ToolType::FINGER, vec2(95, 5) /* initial x/y */,
- vec2(10, -10) /* Move dignally to top right corner */,
+ vec2(10, -10) /* Move diagonally to top right corner */,
PointerChoreographerDisplayTopologyTestFixture::DISPLAY_TOP_RIGHT_CORNER_ID,
- vec2(0, 90) /* bottom left corner */)),
+ vec2(0, 90) /* bottom left corner */),
+ std::make_tuple(
+ "TransitionToHighDpDisplay", AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD,
+ ControllerType::MOUSE, ToolType::MOUSE, vec2(20, 20) /* initial x/y */,
+ vec2(0, -50) /* delta x/y */,
+ PointerChoreographerDisplayTopologyTestFixture::DISPLAY_HIGH_DENSITY_ID,
+ /* Bottom edge: ((source + delta - offset) * density, height) */
+ vec2((20 + 0 + 75) * 2, 200))),
[](const testing::TestParamInfo<PointerChoreographerDisplayTopologyTestFixtureParam>& p) {
return std::string{std::get<0>(p.param)};
});
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
index 48e1954..5000db7 100644
--- a/services/inputflinger/tests/fuzzers/Android.bp
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -33,8 +33,8 @@
"frameworks/native/services/inputflinger",
],
shared_libs: [
- "libinputreader",
"libinputflinger_base",
+ "libinputreader",
],
sanitize: {
hwaddress: true,
diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
index 61ab47a..3a1b426 100644
--- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -40,10 +40,10 @@
using namespace std::chrono_literals;
// Values from Boost.aidl and Mode.aidl.
-static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
-static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
-static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
-static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
+static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(*ndk::enum_range<Boost>().begin());
+static constexpr int64_t LAST_BOOST = static_cast<int64_t>(*(ndk::enum_range<Boost>().end()-1));
+static constexpr int64_t FIRST_MODE = static_cast<int64_t>(*ndk::enum_range<Mode>().begin());
+static constexpr int64_t LAST_MODE = static_cast<int64_t>(*(ndk::enum_range<Mode>().end()-1));
class DurationWrapper : public WorkDuration {
public:
@@ -81,14 +81,17 @@
return;
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
ret = (*hal.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
- if (delay > 0us) {
- testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ break;
}
- state.ResumeTiming();
+ if (delay > 0us) {
+ state.PauseTiming();
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ state.ResumeTiming();
+ }
}
}
@@ -123,14 +126,15 @@
return;
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
ret = (*session.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
- if (ONEWAY_API_DELAY > 0us) {
- testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY)
- .count());
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ break;
}
+ state.PauseTiming();
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY)
+ .count());
state.ResumeTiming();
}
session->close();
@@ -150,11 +154,41 @@
static void BM_PowerHalAidlBenchmarks_setBoost(benchmark::State& state) {
Boost boost = static_cast<Boost>(state.range(0));
+ bool isSupported;
+ std::shared_ptr<IPower> hal = PowerHalLoader::loadAidl();
+
+ if (hal == nullptr) {
+ ALOGV("Power HAL not available, skipping test...");
+ state.SkipWithMessage("Power HAL unavailable");
+ return;
+ }
+
+ ndk::ScopedAStatus ret = hal->isBoostSupported(boost, &isSupported);
+ if (!ret.isOk() || !isSupported) {
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
+
runBenchmark(state, ONEWAY_API_DELAY, &IPower::setBoost, boost, 1);
}
static void BM_PowerHalAidlBenchmarks_setMode(benchmark::State& state) {
Mode mode = static_cast<Mode>(state.range(0));
+ bool isSupported;
+ std::shared_ptr<IPower> hal = PowerHalLoader::loadAidl();
+
+ if (hal == nullptr) {
+ ALOGV("Power HAL not available, skipping test...");
+ state.SkipWithMessage("Power HAL unavailable");
+ return;
+ }
+
+ ndk::ScopedAStatus ret = hal->isModeSupported(mode, &isSupported);
+ if (!ret.isOk() || !isSupported) {
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
+
runBenchmark(state, ONEWAY_API_DELAY, &IPower::setMode, mode, false);
}
@@ -178,12 +212,20 @@
ALOGV("Power HAL does not support this operation, skipping test...");
state.SkipWithMessage("operation unsupported");
return;
+ } else if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ return;
+ } else {
+ appSession->close();
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.getDescription().c_str());
+ break;
+ }
state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.getDescription().c_str());
appSession->close();
state.ResumeTiming();
}
diff --git a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
index effddda..0fda686 100644
--- a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp
@@ -19,9 +19,9 @@
#include <aidl/android/hardware/power/Boost.h>
#include <aidl/android/hardware/power/Mode.h>
#include <benchmark/benchmark.h>
+#include <chrono>
#include <powermanager/PowerHalController.h>
#include <testUtil.h>
-#include <chrono>
using aidl::android::hardware::power::Boost;
using aidl::android::hardware::power::Mode;
@@ -32,10 +32,10 @@
using namespace std::chrono_literals;
// Values from Boost.aidl and Mode.aidl.
-static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(Boost::INTERACTION);
-static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT);
-static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE);
-static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH);
+static constexpr int64_t FIRST_BOOST = static_cast<int64_t>(*ndk::enum_range<Boost>().begin());
+static constexpr int64_t LAST_BOOST = static_cast<int64_t>(*(ndk::enum_range<Boost>().end()-1));
+static constexpr int64_t FIRST_MODE = static_cast<int64_t>(*ndk::enum_range<Mode>().begin());
+static constexpr int64_t LAST_MODE = static_cast<int64_t>(*(ndk::enum_range<Mode>().end()-1));
// Delay between oneway method calls to avoid overflowing the binder buffers.
static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us;
@@ -43,11 +43,27 @@
template <typename T, class... Args0, class... Args1>
static void runBenchmark(benchmark::State& state, HalResult<T> (PowerHalController::*fn)(Args0...),
Args1&&... args1) {
- while (state.KeepRunning()) {
- PowerHalController controller;
+ PowerHalController initController;
+ HalResult<T> result = (initController.*fn)(std::forward<Args1>(args1)...);
+ if (result.isFailed()) {
+ state.SkipWithError(result.errorMessage());
+ return;
+ } else if (result.isUnsupported()) {
+ ALOGV("Power HAL does not support this operation, skipping test...");
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
+
+ for (auto _ : state) {
+ PowerHalController controller; // new controller to avoid caching
HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
+ if (ret.isFailed()) {
+ state.SkipWithError(ret.errorMessage());
+ break;
+ }
state.PauseTiming();
- if (ret.isFailed()) state.SkipWithError("Power HAL request failed");
+ testDelaySpin(
+ std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
state.ResumeTiming();
}
}
@@ -57,22 +73,27 @@
HalResult<T> (PowerHalController::*fn)(Args0...), Args1&&... args1) {
PowerHalController controller;
// First call out of test, to cache HAL service and isSupported result.
- (controller.*fn)(std::forward<Args1>(args1)...);
+ HalResult<T> result = (controller.*fn)(std::forward<Args1>(args1)...);
+ if (result.isFailed()) {
+ state.SkipWithError(result.errorMessage());
+ return;
+ } else if (result.isUnsupported()) {
+ ALOGV("Power HAL does not support this operation, skipping test...");
+ state.SkipWithMessage("operation unsupported");
+ return;
+ }
- while (state.KeepRunning()) {
+ for (auto _ : state) {
HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
if (ret.isFailed()) {
- state.SkipWithError("Power HAL request failed");
+ state.SkipWithError(ret.errorMessage());
+ break;
}
- testDelaySpin(
- std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY).count());
- state.ResumeTiming();
}
}
static void BM_PowerHalControllerBenchmarks_init(benchmark::State& state) {
- while (state.KeepRunning()) {
+ for (auto _ : state) {
PowerHalController controller;
controller.init();
}
@@ -90,12 +111,12 @@
static void BM_PowerHalControllerBenchmarks_setBoost(benchmark::State& state) {
Boost boost = static_cast<Boost>(state.range(0));
- runBenchmark(state, &PowerHalController::setBoost, boost, 0);
+ runBenchmark(state, &PowerHalController::setBoost, boost, 1);
}
static void BM_PowerHalControllerBenchmarks_setBoostCached(benchmark::State& state) {
Boost boost = static_cast<Boost>(state.range(0));
- runCachedBenchmark(state, &PowerHalController::setBoost, boost, 0);
+ runCachedBenchmark(state, &PowerHalController::setBoost, boost, 1);
}
static void BM_PowerHalControllerBenchmarks_setMode(benchmark::State& state) {
diff --git a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
index bcb376b..95fd0c2 100644
--- a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
@@ -54,14 +54,17 @@
return;
}
- while (state.KeepRunning()) {
+ for (auto _ : state) {
Return<R> ret = (*hal.*fn)(std::forward<Args1>(args1)...);
- state.PauseTiming();
- if (!ret.isOk()) state.SkipWithError(ret.description().c_str());
- if (delay > 0us) {
- testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ if (!ret.isOk()) {
+ state.SkipWithError(ret.description().c_str());
+ break;
}
- state.ResumeTiming();
+ if (delay > 0us) {
+ state.PauseTiming();
+ testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(delay).count());
+ state.ResumeTiming();
+ }
}
}
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 8c80dd8..9ecd101 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -11,7 +11,7 @@
name: "sensorservice_flags",
package: "com.android.frameworks.sensorservice.flags",
container: "system",
- srcs: ["senserservice_flags.aconfig"],
+ srcs: ["sensorservice_flags.aconfig"],
}
cc_aconfig_library {
@@ -61,38 +61,38 @@
],
shared_libs: [
- "libcutils",
- "libhardware",
- "libhardware_legacy",
- "libutils",
- "liblog",
- "libactivitymanager_aidl",
- "libbatterystats_aidl",
- "libbinder",
- "libsensor",
- "libsensorprivacy",
- "libpermission",
- "libprotoutil",
- "libcrypto",
- "libbase",
- "libhidlbase",
- "libfmq",
- "libbinder_ndk",
- "packagemanager_aidl-cpp",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
"android.hardware.sensors@2.1",
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
- "server_configurable_flags",
"libaconfig_storage_read_api_cc",
+ "libactivitymanager_aidl",
+ "libbase",
+ "libbatterystats_aidl",
+ "libbinder",
+ "libbinder_ndk",
+ "libcrypto",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhardware_legacy",
+ "libhidlbase",
+ "liblog",
+ "libpermission",
+ "libprotoutil",
+ "libsensor",
+ "libsensorprivacy",
+ "libutils",
+ "packagemanager_aidl-cpp",
+ "server_configurable_flags",
],
static_libs: [
- "libaidlcommonsupport",
- "android.hardware.sensors@1.0-convert",
"android.hardware.sensors-V1-convert",
"android.hardware.sensors-V3-ndk",
+ "android.hardware.sensors@1.0-convert",
+ "libaidlcommonsupport",
"sensorservice_flags_c_lib",
],
@@ -100,9 +100,9 @@
export_shared_lib_headers: [
"libactivitymanager_aidl",
+ "libpermission",
"libsensor",
"libsensorprivacy",
- "libpermission",
],
afdo: true,
@@ -120,9 +120,9 @@
srcs: ["main_sensorservice.cpp"],
shared_libs: [
- "libsensorservice",
- "libsensorprivacy",
"libbinder",
+ "libsensorprivacy",
+ "libsensorservice",
"libutils",
],
diff --git a/services/sensorservice/senserservice_flags.aconfig b/services/sensorservice/sensorservice_flags.aconfig
similarity index 79%
rename from services/sensorservice/senserservice_flags.aconfig
rename to services/sensorservice/sensorservice_flags.aconfig
index 7abfbaa..452b428 100644
--- a/services/sensorservice/senserservice_flags.aconfig
+++ b/services/sensorservice/sensorservice_flags.aconfig
@@ -28,3 +28,13 @@
description: "When this flag is enabled, sensor service will only erase dynamic sensor data at the end of the threadLoop to prevent race condition."
bug: "329020894"
}
+
+flag {
+ name: "enforce_permissions_for_all_target_sdk"
+ namespace: "sensors"
+ description: "When this flag is enabled, sensor service will enforce permissions for all target sdks."
+ bug: "389176817"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index fece312..008b057 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -654,7 +654,7 @@
// We try to do this by moving the deadline. Since the queue could be stuffed by more
// than one buffer, we take the last latch time as reference and give one vsync
// worth of time for the frame to be ready.
- nsecs_t adjustedDeadline = mLastLatchTime + refreshRate.getPeriodNsecs();
+ nsecs_t adjustedDeadline = mLastLatchTime + displayFrameRenderRate.getPeriodNsecs();
if (adjustedDeadline > mActuals.endTime) {
mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7e3d109..1dc7b2e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2975,22 +2975,21 @@
}
int index = 0;
- std::array<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary = {0};
+ ftl::StaticVector<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary;
auto lastLayerStack = ui::INVALID_LAYER_STACK;
for (auto& [layer, layerFE] : layers) {
CompositionResult compositionResult{layerFE->stealCompositionResult()};
- if (index < compositionSummary.size()) {
- if (lastLayerStack != ui::INVALID_LAYER_STACK &&
- lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
+ if (lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
+ if (lastLayerStack != ui::INVALID_LAYER_STACK) {
// add a space to separate displays
- compositionSummary[index++] = ' ';
+ compositionSummary.push_back(' ');
}
lastLayerStack = layerFE->mSnapshot->outputFilter.layerStack;
- compositionSummary[index++] = layerFE->mSnapshot->classifyCompositionForDebug(
- layerFE->getHwcCompositionType());
- if (layerFE->mSnapshot->hasEffect()) {
- compositedWorkload |= adpf::Workload::EFFECTS;
- }
+ }
+ compositionSummary.push_back(
+ layerFE->mSnapshot->classifyCompositionForDebug(layerFE->getHwcCompositionType()));
+ if (layerFE->mSnapshot->hasEffect()) {
+ compositedWorkload |= adpf::Workload::EFFECTS;
}
if (compositionResult.lastClientCompositionFence) {
@@ -3007,7 +3006,8 @@
SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
ftl::Concat("Layers: ", layers.size(), " ",
ftl::truncated<WorkloadTracer::COMPOSITION_SUMMARY_SIZE>(
- compositionSummary.data()))
+ std::string_view(compositionSummary.begin(),
+ compositionSummary.size())))
.c_str());
mPowerAdvisor->setCompositedWorkload(compositedWorkload);
@@ -4602,27 +4602,6 @@
status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinder>& handle,
const sp<Layer>& layer, const wp<Layer>& parent,
uint32_t* outTransformHint) {
- if (mNumLayers >= MAX_LAYERS) {
- static std::atomic<nsecs_t> lasttime{0};
- nsecs_t now = systemTime();
- if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
- ALOGE("AddClientLayer already dumped 10s before");
- return NO_MEMORY;
- } else {
- lasttime = now;
- }
-
- ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
- MAX_LAYERS);
- static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
- ALOGE("Dumping on-screen layers.");
- mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
- ALOGE("Dumping off-screen layers.");
- mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
- }));
- return NO_MEMORY;
- }
-
if (outTransformHint) {
*outTransformHint = mActiveDisplayTransformHint;
}
@@ -5405,14 +5384,13 @@
mirrorArgs.addToRoot = true;
mirrorArgs.layerStackToMirror = layerStack;
result = createEffectLayer(mirrorArgs, &outResult.handle, &rootMirrorLayer);
+ if (result != NO_ERROR) {
+ return result;
+ }
outResult.layerId = rootMirrorLayer->sequence;
outResult.layerName = String16(rootMirrorLayer->getDebugName());
- result |= addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
- nullptr /* parent */, nullptr /* outTransformHint */);
- }
-
- if (result != NO_ERROR) {
- return result;
+ addClientLayer(mirrorArgs, outResult.handle, rootMirrorLayer /* layer */,
+ nullptr /* parent */, nullptr /* outTransformHint */);
}
setTransactionFlags(eTransactionFlushNeeded);
@@ -5432,6 +5410,9 @@
[[fallthrough]];
case ISurfaceComposerClient::eFXSurfaceEffect: {
result = createBufferStateLayer(args, &outResult.handle, &layer);
+ if (result != NO_ERROR) {
+ return result;
+ }
std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
if (pendingBufferCounter) {
std::string counterName = layer->getPendingBufferCounterName();
@@ -5472,6 +5453,9 @@
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
+ if (checkLayerLeaks() != NO_ERROR) {
+ return NO_MEMORY;
+ }
*outLayer = getFactory().createBufferStateLayer(args);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
@@ -5479,11 +5463,38 @@
status_t SurfaceFlinger::createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
+ if (checkLayerLeaks() != NO_ERROR) {
+ return NO_MEMORY;
+ }
*outLayer = getFactory().createEffectLayer(args);
*handle = (*outLayer)->getHandle();
return NO_ERROR;
}
+status_t SurfaceFlinger::checkLayerLeaks() {
+ if (mNumLayers >= MAX_LAYERS) {
+ static std::atomic<nsecs_t> lasttime{0};
+ nsecs_t now = systemTime();
+ if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
+ ALOGE("CreateLayer already dumped 10s before");
+ return NO_MEMORY;
+ } else {
+ lasttime = now;
+ }
+
+ ALOGE("CreateLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
+ MAX_LAYERS);
+ static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
+ ALOGE("Dumping on-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
+ ALOGE("Dumping off-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
+ }));
+ return NO_MEMORY;
+ }
+ return NO_ERROR;
+}
+
void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer, uint32_t layerId) {
{
// Used to remove stalled transactions which uses an internal lock.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index fa255ea..935a2da 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -838,6 +838,9 @@
status_t createEffectLayer(const LayerCreationArgs& args, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
+ // Checks if there are layer leaks before creating layer
+ status_t checkLayerLeaks();
+
status_t mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
gui::CreateSurfaceResult& outResult);