Merge "SF: Add EDID-ID Fabrication Logic" into main
diff --git a/include/android/input.h b/include/android/input.h
index 5f44550..ee98d7a 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -849,7 +849,6 @@
* Refer to the documentation on the MotionEvent class for descriptions of each button.
*/
enum {
- // LINT.IfChange(AMOTION_EVENT_BUTTON)
/** primary */
AMOTION_EVENT_BUTTON_PRIMARY = 1 << 0,
/** secondary */
@@ -862,7 +861,6 @@
AMOTION_EVENT_BUTTON_FORWARD = 1 << 4,
AMOTION_EVENT_BUTTON_STYLUS_PRIMARY = 1 << 5,
AMOTION_EVENT_BUTTON_STYLUS_SECONDARY = 1 << 6,
- // LINT.ThenChange(/frameworks/native/libs/input/rust/input.rs)
};
/**
diff --git a/include/input/InputVerifier.h b/include/input/InputVerifier.h
index 7d3fb46..14dd463 100644
--- a/include/input/InputVerifier.h
+++ b/include/input/InputVerifier.h
@@ -47,10 +47,9 @@
InputVerifier(const std::string& name);
android::base::Result<void> processMovement(int32_t deviceId, int32_t source, int32_t action,
- int32_t actionButton, uint32_t pointerCount,
+ uint32_t pointerCount,
const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, int32_t flags,
- int32_t buttonState);
+ const PointerCoords* pointerCoords, int32_t flags);
void resetDevice(int32_t deviceId);
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index f191b97..cdc53ff 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -853,8 +853,12 @@
void IPCThreadState::stopProcess(bool /*immediate*/)
{
- ALOGI("IPCThreadState::stopProcess() (deprecated) called. Exiting process.");
- exit(0);
+ //ALOGI("**** STOPPING PROCESS");
+ (void)flushCommands();
+ int fd = mProcess->mDriverFD;
+ mProcess->mDriverFD = -1;
+ close(fd);
+ //kill(getpid(), SIGKILL);
}
status_t IPCThreadState::transact(int32_t handle,
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index 1fde45b..dce7778 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -41,6 +41,7 @@
],
srcs: [
+ "FeatureOverrides.cpp",
"GpuStatsInfo.cpp",
"GraphicsEnv.cpp",
"IGpuService.cpp",
diff --git a/libs/graphicsenv/FeatureOverrides.cpp b/libs/graphicsenv/FeatureOverrides.cpp
new file mode 100644
index 0000000..6974da9
--- /dev/null
+++ b/libs/graphicsenv/FeatureOverrides.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <graphicsenv/FeatureOverrides.h>
+
+#include <android-base/stringprintf.h>
+
+namespace android {
+
+using base::StringAppendF;
+
+std::string FeatureConfig::toString() const {
+ std::string result;
+ StringAppendF(&result, "Feature: %s\n", mFeatureName.c_str());
+ StringAppendF(&result, " Status: %s\n", mEnabled ? "enabled" : "disabled");
+
+ return result;
+}
+
+std::string FeatureOverrides::toString() const {
+ std::string result;
+ result.append("Global Features:\n");
+ for (auto& cfg : mGlobalFeatures) {
+ result.append(" " + cfg.toString());
+ }
+ result.append("\n");
+ result.append("Package Features:\n");
+ for (const auto& packageFeature : mPackageFeatures) {
+ result.append(" Package:");
+ StringAppendF(&result, " %s\n", packageFeature.first.c_str());
+ for (auto& cfg : packageFeature.second) {
+ result.append(" " + cfg.toString());
+ }
+ }
+
+ return result;
+}
+
+} // namespace android
diff --git a/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h b/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h
index 2ef54ad..2b94187 100644
--- a/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h
+++ b/libs/graphicsenv/include/graphicsenv/FeatureOverrides.h
@@ -27,6 +27,7 @@
FeatureConfig() = default;
FeatureConfig(const FeatureConfig&) = default;
virtual ~FeatureConfig() = default;
+ std::string toString() const;
std::string mFeatureName;
bool mEnabled;
@@ -41,6 +42,7 @@
FeatureOverrides() = default;
FeatureOverrides(const FeatureOverrides&) = default;
virtual ~FeatureOverrides() = default;
+ std::string toString() const;
std::vector<FeatureConfig> mGlobalFeatures;
/* Key: Package Name, Value: Package's Feature Configs */
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index d9c10ad..389fb7f 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -91,13 +91,6 @@
"--allowlist-var=AMOTION_EVENT_ACTION_POINTER_DOWN",
"--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
"--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
- "--allowlist-var=AMOTION_EVENT_BUTTON_PRIMARY",
- "--allowlist-var=AMOTION_EVENT_BUTTON_SECONDARY",
- "--allowlist-var=AMOTION_EVENT_BUTTON_TERTIARY",
- "--allowlist-var=AMOTION_EVENT_BUTTON_BACK",
- "--allowlist-var=AMOTION_EVENT_BUTTON_FORWARD",
- "--allowlist-var=AMOTION_EVENT_BUTTON_STYLUS_PRIMARY",
- "--allowlist-var=AMOTION_EVENT_BUTTON_STYLUS_SECONDARY",
"--allowlist-var=MAX_POINTER_ID",
"--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
"--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index d388d48..56ccaab 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -651,9 +651,9 @@
const status_t status = mChannel->sendMessage(&msg);
if (status == OK && verifyEvents()) {
- Result<void> result = mInputVerifier.processMovement(deviceId, source, action, actionButton,
- pointerCount, pointerProperties,
- pointerCoords, flags, buttonState);
+ Result<void> result =
+ mInputVerifier.processMovement(deviceId, source, action, pointerCount,
+ pointerProperties, pointerCoords, flags);
if (!result.ok()) {
LOG(ERROR) << "Bad stream: " << result.error();
return BAD_VALUE;
diff --git a/libs/input/InputVerifier.cpp b/libs/input/InputVerifier.cpp
index e8d4c73..cec2445 100644
--- a/libs/input/InputVerifier.cpp
+++ b/libs/input/InputVerifier.cpp
@@ -34,10 +34,9 @@
: mVerifier(android::input::verifier::create(rust::String::lossy(name))){};
Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t source, int32_t action,
- int32_t actionButton, uint32_t pointerCount,
+ uint32_t pointerCount,
const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, int32_t flags,
- int32_t buttonState) {
+ const PointerCoords* pointerCoords, int32_t flags) {
std::vector<RustPointerProperties> rpp;
for (size_t i = 0; i < pointerCount; i++) {
rpp.emplace_back(RustPointerProperties{.id = pointerProperties[i].id});
@@ -45,9 +44,7 @@
rust::Slice<const RustPointerProperties> properties{rpp.data(), rpp.size()};
rust::String errorMessage =
android::input::verifier::process_movement(*mVerifier, deviceId, source, action,
- actionButton, properties,
- static_cast<uint32_t>(flags),
- static_cast<uint32_t>(buttonState));
+ properties, static_cast<uint32_t>(flags));
if (errorMessage.empty()) {
return {};
} else {
diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs
index 5e487ab..90f509d 100644
--- a/libs/input/rust/input.rs
+++ b/libs/input/rust/input.rs
@@ -101,7 +101,6 @@
/// A rust enum representation of a MotionEvent action.
#[repr(u32)]
-#[derive(PartialEq)]
pub enum MotionAction {
/// ACTION_DOWN
Down = input_bindgen::AMOTION_EVENT_ACTION_DOWN,
@@ -195,27 +194,6 @@
}
bitflags! {
- /// MotionEvent buttons.
- #[derive(Clone, Copy, Debug, Default, PartialEq)]
- pub struct MotionButton: u32 {
- /// Primary button (e.g. the left mouse button)
- const Primary = input_bindgen::AMOTION_EVENT_BUTTON_PRIMARY;
- /// Secondary button (e.g. the right mouse button)
- const Secondary = input_bindgen::AMOTION_EVENT_BUTTON_SECONDARY;
- /// Tertiary button (e.g. the middle mouse button)
- const Tertiary = input_bindgen::AMOTION_EVENT_BUTTON_TERTIARY;
- /// Back button
- const Back = input_bindgen::AMOTION_EVENT_BUTTON_BACK;
- /// Forward button
- const Forward = input_bindgen::AMOTION_EVENT_BUTTON_FORWARD;
- /// Primary stylus button
- const StylusPrimary = input_bindgen::AMOTION_EVENT_BUTTON_STYLUS_PRIMARY;
- /// Secondary stylus button
- const StylusSecondary = input_bindgen::AMOTION_EVENT_BUTTON_STYLUS_SECONDARY;
- }
-}
-
-bitflags! {
/// MotionEvent flags.
/// The source of truth for the flag definitions are the MotionEventFlag AIDL enum.
/// The flag values are redefined here as a bitflags API.
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index 55dc56f..b1d7760 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -17,14 +17,13 @@
//! Contains the InputVerifier, used to validate a stream of input events.
use crate::ffi::RustPointerProperties;
-use crate::input::{DeviceId, MotionAction, MotionButton, MotionFlags, Source, SourceClass};
+use crate::input::{DeviceId, MotionAction, MotionFlags, Source, SourceClass};
use log::info;
use std::collections::HashMap;
use std::collections::HashSet;
fn verify_event(
action: MotionAction,
- action_button: MotionButton,
pointer_properties: &[RustPointerProperties],
flags: &MotionFlags,
) -> Result<(), String> {
@@ -32,14 +31,6 @@
if pointer_count < 1 {
return Err(format!("Invalid {} event: no pointers", action));
}
- if action_button != MotionButton::empty()
- && action != MotionAction::ButtonPress
- && action != MotionAction::ButtonRelease
- {
- return Err(format!(
- "Invalid {action} event: has action button {action_button:?} but is not a button action"
- ));
- }
match action {
MotionAction::Down
| MotionAction::HoverEnter
@@ -69,118 +60,17 @@
}
}
- MotionAction::ButtonPress | MotionAction::ButtonRelease => {
- let button_count = action_button.iter().count();
- if button_count != 1 {
- return Err(format!(
- "Invalid {action} event: must specify a single action button, not \
- {button_count} action buttons"
- ));
- }
- }
-
_ => {}
}
Ok(())
}
-/// Keeps track of the button state for a single device and verifies events against it.
-#[derive(Default)]
-struct ButtonVerifier {
- /// The current button state of the device.
- button_state: MotionButton,
-
- /// The set of "pending buttons", which were seen in the last DOWN event's button state but
- /// for which we haven't seen BUTTON_PRESS events yet.
- ///
- /// We allow DOWN events to include buttons in their state for which BUTTON_PRESS events haven't
- /// been sent yet. In that case, the DOWN should be immediately followed by BUTTON_PRESS events
- /// for those buttons, building up to a button state matching that of the DOWN. For example, if
- /// the user presses the primary and secondary buttons at exactly the same time, we'd expect
- /// this sequence:
- ///
- /// | Action | Action button | Button state |
- /// |----------------|---------------|------------------------|
- /// | `HOVER_EXIT` | - | - |
- /// | `DOWN` | - | `PRIMARY`, `SECONDARY` |
- /// | `BUTTON_PRESS` | `PRIMARY` | `PRIMARY` |
- /// | `BUTTON_PRESS` | `SECONDARY` | `PRIMARY`, `SECONDARY` |
- /// | `MOVE` | - | `PRIMARY`, `SECONDARY` |
- pending_buttons: MotionButton,
-}
-
-impl ButtonVerifier {
- pub fn process_action(
- &mut self,
- action: MotionAction,
- action_button: MotionButton,
- button_state: MotionButton,
- ) -> Result<(), String> {
- if !self.pending_buttons.is_empty() {
- // We just saw a DOWN with some additional buttons in its state, so it should be
- // immediately followed by ButtonPress events for those buttons.
- if action != MotionAction::ButtonPress || !self.pending_buttons.contains(action_button)
- {
- return Err(format!(
- "After DOWN event, expected BUTTON_PRESS event(s) for {:?}, but got {} with \
- action button {:?}",
- self.pending_buttons, action, action_button
- ));
- } else {
- self.pending_buttons -= action_button;
- }
- }
- let expected_state = match action {
- MotionAction::Down => {
- if self.button_state - button_state != MotionButton::empty() {
- return Err(format!(
- "DOWN event button state is missing {:?}",
- self.button_state - button_state
- ));
- }
- self.pending_buttons = button_state - self.button_state;
- // We've already checked that the state isn't missing any already-down buttons, and
- // extra buttons are valid on DOWN actions, so bypass the expected state check.
- button_state
- }
- MotionAction::ButtonPress => {
- if self.button_state.contains(action_button) {
- return Err(format!(
- "Duplicate BUTTON_PRESS; button state already contains {action_button:?}"
- ));
- }
- self.button_state | action_button
- }
- MotionAction::ButtonRelease => {
- if !self.button_state.contains(action_button) {
- return Err(format!(
- "Invalid BUTTON_RELEASE; button state doesn't contain {action_button:?}"
- ));
- }
- self.button_state - action_button
- }
- _ => self.button_state,
- };
- if button_state != expected_state {
- return Err(format!(
- "Expected {action} button state to be {expected_state:?}, but was {button_state:?}"
- ));
- }
- // DOWN events can have pending buttons, so don't update the state for them.
- if action != MotionAction::Down {
- self.button_state = button_state;
- }
- Ok(())
- }
-}
-
/// The InputVerifier is used to validate a stream of input events.
pub struct InputVerifier {
name: String,
should_log: bool,
touching_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
hovering_pointer_ids_by_device: HashMap<DeviceId, HashSet<i32>>,
- button_verifier_by_device: HashMap<DeviceId, ButtonVerifier>,
}
impl InputVerifier {
@@ -196,22 +86,18 @@
should_log,
touching_pointer_ids_by_device: HashMap::new(),
hovering_pointer_ids_by_device: HashMap::new(),
- button_verifier_by_device: HashMap::new(),
}
}
/// Process a pointer movement event from an InputDevice.
/// If the event is not valid, we return an error string that describes the issue.
- #[allow(clippy::too_many_arguments)]
pub fn process_movement(
&mut self,
device_id: DeviceId,
source: Source,
action: u32,
- action_button: MotionButton,
pointer_properties: &[RustPointerProperties],
flags: MotionFlags,
- button_state: MotionButton,
) -> Result<(), String> {
if !source.is_from_class(SourceClass::Pointer) {
// Skip non-pointer sources like MOUSE_RELATIVE for now
@@ -228,13 +114,7 @@
);
}
- verify_event(action.into(), action_button, pointer_properties, &flags)?;
-
- self.button_verifier_by_device.entry(device_id).or_default().process_action(
- action.into(),
- action_button,
- button_state,
- )?;
+ verify_event(action.into(), pointer_properties, &flags)?;
match action.into() {
MotionAction::Down => {
@@ -408,7 +288,6 @@
#[cfg(test)]
mod tests {
- use crate::input::MotionButton;
use crate::input_verifier::InputVerifier;
use crate::DeviceId;
use crate::MotionFlags;
@@ -428,10 +307,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_err());
}
@@ -445,10 +322,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -456,10 +331,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -467,10 +340,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
}
@@ -484,10 +355,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
// POINTER 1 DOWN
@@ -499,10 +368,8 @@
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN
| (1 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- MotionButton::empty(),
&two_pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
// POINTER 0 UP
@@ -512,10 +379,8 @@
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_POINTER_UP
| (0 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- MotionButton::empty(),
&two_pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
// ACTION_UP for pointer id=1
@@ -525,10 +390,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
- MotionButton::empty(),
&pointer_1_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
}
@@ -542,10 +405,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -553,10 +414,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -564,10 +423,8 @@
DeviceId(2),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -575,10 +432,8 @@
DeviceId(2),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -586,10 +441,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
}
@@ -603,10 +456,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -614,10 +465,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::CANCELED,
- MotionButton::empty(),
)
.is_ok());
}
@@ -631,10 +480,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
assert!(verifier
@@ -642,10 +489,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(), // forgot to set FLAG_CANCELED
- MotionButton::empty(),
)
.is_err());
}
@@ -659,10 +504,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_err());
}
@@ -676,10 +519,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
@@ -688,10 +529,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
@@ -700,10 +539,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
@@ -712,10 +549,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
}
@@ -729,10 +564,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
@@ -741,10 +574,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_err());
}
@@ -760,10 +591,8 @@
DeviceId(2),
Source::MouseRelative,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
}
@@ -778,10 +607,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
// POINTER 1 DOWN
@@ -793,10 +620,8 @@
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_POINTER_DOWN
| (1 << input_bindgen::AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- MotionButton::empty(),
&two_pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
)
.is_ok());
// MOVE event with 1 pointer missing (the pointer with id = 1). It should be rejected
@@ -805,470 +630,8 @@
DeviceId(1),
Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
&pointer_properties,
MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn correct_button_press() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- }
-
- #[test]
- fn button_press_without_action_button() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn button_press_with_multiple_action_buttons() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Back | MotionButton::Forward,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back | MotionButton::Forward,
- )
- .is_err());
- }
-
- #[test]
- fn button_press_without_action_button_in_state() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn button_release_with_action_button_in_state() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_err());
- }
-
- #[test]
- fn nonbutton_action_with_action_button() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn nonbutton_action_with_action_button_and_state() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_err());
- }
-
- #[test]
- fn nonbutton_action_with_button_state_change() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back,
- )
- .is_err());
- }
-
- #[test]
- fn nonbutton_action_missing_button_state() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Back,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn up_without_button_release() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- // This UP event shouldn't change the button state; a BUTTON_RELEASE before it should.
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_UP,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn button_press_for_already_pressed_button() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Back,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Back,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back,
- )
- .is_err());
- }
-
- #[test]
- fn button_release_for_unpressed_button() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- MotionButton::Back,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
- )
- .is_err());
- }
-
- #[test]
- fn correct_multiple_button_presses_without_down() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Back,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Forward,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back | MotionButton::Forward,
- )
- .is_ok());
- }
-
- #[test]
- fn correct_down_with_button_press() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary | MotionButton::Secondary,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Secondary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary | MotionButton::Secondary,
- )
- .is_ok());
- // Also check that the MOVE afterwards is OK, as that's where errors would be raised if not
- // enough BUTTON_PRESSes were sent.
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary | MotionButton::Secondary,
- )
- .is_ok());
- }
-
- #[test]
- fn down_with_button_state_change_not_followed_by_button_press() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- // The DOWN event itself is OK, but it needs to be immediately followed by a BUTTON_PRESS.
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_err());
- }
-
- #[test]
- fn down_with_button_state_change_not_followed_by_enough_button_presses() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary | MotionButton::Secondary,
- )
- .is_ok());
- // The DOWN event itself is OK, but it needs to be immediately followed by two
- // BUTTON_PRESSes, one for each button.
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Primary,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_MOVE,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Primary,
- )
- .is_err());
- }
-
- #[test]
- fn down_missing_already_pressed_button() {
- let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
- let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_BUTTON_PRESS,
- MotionButton::Back,
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::Back,
- )
- .is_ok());
- assert!(verifier
- .process_movement(
- DeviceId(1),
- Source::Mouse,
- input_bindgen::AMOTION_EVENT_ACTION_DOWN,
- MotionButton::empty(),
- &pointer_properties,
- MotionFlags::empty(),
- MotionButton::empty(),
)
.is_err());
}
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index 1d5793b..4f4ea85 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -24,8 +24,8 @@
pub use data_store::{DataStore, DefaultFileReaderWriter};
pub use input::{
- DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionButton,
- MotionFlags, Source,
+ DeviceClass, DeviceId, InputDevice, KeyboardType, ModifierState, MotionAction, MotionFlags,
+ Source,
};
pub use input_verifier::InputVerifier;
pub use keyboard_classifier::KeyboardClassifier;
@@ -58,16 +58,13 @@
type InputVerifier;
#[cxx_name = create]
fn create_input_verifier(name: String) -> Box<InputVerifier>;
- #[allow(clippy::too_many_arguments)]
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
source: u32,
action: u32,
- action_button: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
- button_state: u32,
) -> String;
fn reset_device(verifier: &mut InputVerifier, device_id: i32);
}
@@ -122,16 +119,13 @@
Box::new(InputVerifier::new(&name, ffi::shouldLog("InputVerifierLogEvents")))
}
-#[allow(clippy::too_many_arguments)]
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
source: u32,
action: u32,
- action_button: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
- button_state: u32,
) -> String {
let motion_flags = MotionFlags::from_bits(flags);
if motion_flags.is_none() {
@@ -141,28 +135,12 @@
flags
);
}
- let motion_action_button = MotionButton::from_bits(action_button);
- if motion_action_button.is_none() {
- panic!(
- "The conversion of action button 0x{action_button:08x} failed, please check if some \
- buttons need to be added to MotionButton."
- );
- }
- let motion_button_state = MotionButton::from_bits(button_state);
- if motion_button_state.is_none() {
- panic!(
- "The conversion of button state 0x{button_state:08x} failed, please check if some \
- buttons need to be added to MotionButton."
- );
- }
let result = verifier.process_movement(
DeviceId(device_id),
Source::from_bits(source).unwrap(),
action,
- motion_action_button.unwrap(),
pointer_properties,
motion_flags.unwrap(),
- motion_button_state.unwrap(),
);
match result {
Ok(()) => "".to_string(),
diff --git a/libs/input/tests/InputVerifier_test.cpp b/libs/input/tests/InputVerifier_test.cpp
index 8e0d906..5bb1d56 100644
--- a/libs/input/tests/InputVerifier_test.cpp
+++ b/libs/input/tests/InputVerifier_test.cpp
@@ -49,9 +49,9 @@
const Result<void> result =
verifier.processMovement(/*deviceId=*/0, AINPUT_SOURCE_CLASS_POINTER,
- AMOTION_EVENT_ACTION_DOWN, /*actionButton=*/0,
+ AMOTION_EVENT_ACTION_DOWN,
/*pointerCount=*/properties.size(), properties.data(),
- coords.data(), /*flags=*/0, /*buttonState=*/0);
+ coords.data(), /*flags=*/0);
ASSERT_RESULT_OK(result);
}
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index 14d08ee..5f2d1b1 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -838,8 +838,7 @@
LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface);
LOG_ALWAYS_FATAL_IF(canvas == dstCanvas);
- // save a snapshot of the activeSurface to use as input to the blur shaders
- blurInput = activeSurface->makeImageSnapshot();
+ blurInput = activeSurface->makeTemporaryImage();
// blit the offscreen framebuffer into the destination AHB. This ensures that
// even if the blurred image does not cover the screen (for example, during
@@ -853,12 +852,9 @@
dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()),
String8::format("SurfaceID|%" PRId64, id).c_str(),
nullptr);
- dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint);
- } else {
- activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint);
}
+ dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint);
}
-
// assign dstCanvas to canvas and ensure that the canvas state is up to date
canvas = dstCanvas;
surfaceAutoSaveRestore.replace(canvas);
@@ -891,12 +887,6 @@
if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) {
std::unordered_map<uint32_t, sk_sp<SkImage>> cachedBlurs;
- // if multiple layers have blur, then we need to take a snapshot now because
- // only the lowest layer will have blurImage populated earlier
- if (!blurInput) {
- blurInput = activeSurface->makeImageSnapshot();
- }
-
// rect to be blurred in the coordinate space of blurInput
SkRect blurRect = canvas->getTotalMatrix().mapRect(bounds.rect());
@@ -920,6 +910,29 @@
// TODO(b/182216890): Filter out empty layers earlier
if (blurRect.width() > 0 && blurRect.height() > 0) {
+ // if multiple layers have blur, then we need to take a snapshot now because
+ // only the lowest layer will have blurImage populated earlier
+ if (!blurInput) {
+ bool requiresCrossFadeWithBlurInput = false;
+ if (layer.backgroundBlurRadius > 0 &&
+ layer.backgroundBlurRadius < mBlurFilter->getMaxCrossFadeRadius()) {
+ requiresCrossFadeWithBlurInput = true;
+ }
+ for (auto region : layer.blurRegions) {
+ if (region.blurRadius < mBlurFilter->getMaxCrossFadeRadius()) {
+ requiresCrossFadeWithBlurInput = true;
+ }
+ }
+ if (requiresCrossFadeWithBlurInput) {
+ // If we require cross fading with the blur input, we need to make sure we
+ // make a copy of the surface to the image since we will be writing to the
+ // surface while sampling the blurInput.
+ blurInput = activeSurface->makeImageSnapshot();
+ } else {
+ blurInput = activeSurface->makeTemporaryImage();
+ }
+ }
+
if (layer.backgroundBlurRadius > 0) {
SFTRACE_NAME("BackgroundBlur");
auto blurredImage = mBlurFilter->generate(context, layer.backgroundBlurRadius,
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index cd1bd71..8edf98e 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -90,6 +90,8 @@
linearSampling, &blurMatrix);
if (blurRadius < mMaxCrossFadeRadius) {
+ LOG_ALWAYS_FATAL_IF(!input);
+
// For sampling Skia's API expects the inverse of what logically seems appropriate. In this
// case you might expect the matrix to simply be the canvas matrix.
SkMatrix inputMatrix;
diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
index 8c52c57..b03ebe3 100644
--- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
@@ -64,7 +64,7 @@
SkSamplingOptions{SkFilterMode::kLinear, SkMipmapMode::kNone},
&paint,
SkCanvas::SrcRectConstraint::kFast_SrcRectConstraint);
- return surface->makeImageSnapshot();
+ return surface->makeTemporaryImage();
}
} // namespace skia
diff --git a/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp
index ef57c30..897f5cf 100644
--- a/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurDualFilter.cpp
@@ -167,14 +167,14 @@
}
// Next the remaining downscale blur passes.
for (int i = 0; i < filterPasses; i++) {
- blurInto(surfaces[i + 1], surfaces[i]->makeImageSnapshot(), kWeights[1 + i] * step, 1.0f);
+ blurInto(surfaces[i + 1], surfaces[i]->makeTemporaryImage(), kWeights[1 + i] * step, 1.0f);
}
// Finally blur+upscale back to our original size.
for (int i = filterPasses - 1; i >= 0; i--) {
- blurInto(surfaces[i], surfaces[i + 1]->makeImageSnapshot(), kWeights[4 - i] * step,
+ blurInto(surfaces[i], surfaces[i + 1]->makeTemporaryImage(), kWeights[4 - i] * step,
std::min(1.0f, filterDepth - i));
}
- return surfaces[0]->makeImageSnapshot();
+ return surfaces[0]->makeTemporaryImage();
}
} // namespace skia
diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
index defaf6e..f71a63d 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
@@ -70,7 +70,7 @@
paint.setShader(std::move(shader));
paint.setBlendMode(SkBlendMode::kSrc);
surface->getCanvas()->drawPaint(paint);
- return surface->makeImageSnapshot();
+ return surface->makeTemporaryImage();
}
sk_sp<SkImage> KawaseBlurFilter::generate(SkiaGpuContext* context, const uint32_t blurRadius,
diff --git a/libs/renderengine/skia/filters/MouriMap.cpp b/libs/renderengine/skia/filters/MouriMap.cpp
index aa12cef..5dc36e6 100644
--- a/libs/renderengine/skia/filters/MouriMap.cpp
+++ b/libs/renderengine/skia/filters/MouriMap.cpp
@@ -104,7 +104,7 @@
paint.setShader(std::move(shader));
paint.setBlendMode(SkBlendMode::kSrc);
surface->getCanvas()->drawPaint(paint);
- return surface->makeImageSnapshot();
+ return surface->makeTemporaryImage();
}
} // namespace
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index a8cd7f9..beb4c92 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -928,6 +928,7 @@
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
: mPolicy(policy),
+ mLooper(sp<Looper>::make(false)),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
@@ -938,6 +939,7 @@
mDispatchFrozen(false),
mInputFilterEnabled(false),
mMaximumObscuringOpacityForTouch(1.0f),
+ mConnectionManager(mLooper),
mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID),
@@ -948,7 +950,6 @@
: std::move(std::unique_ptr<InputEventTimelineProcessor>(
new LatencyAggregator()))),
mLatencyTracker(*mInputEventTimelineProcessor) {
- mLooper = sp<Looper>::make(false);
mReporter = createInputReporter();
mWindowInfoListener = sp<DispatcherWindowListener>::make(*this);
@@ -971,11 +972,6 @@
releasePendingEventLocked();
drainInboundQueueLocked();
mCommandQueue.clear();
-
- while (!mConnectionsByToken.empty()) {
- std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
- removeInputChannelLocked(connection, /*notify=*/false);
- }
}
status_t InputDispatcher::start() {
@@ -1092,9 +1088,13 @@
}
// If we reached here, we have an unresponsive connection.
- std::shared_ptr<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(mAnrTracker.firstToken());
if (connection == nullptr) {
ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
+ // As we no longer have entry for this connection, remove it form Anr tracker to prevent
+ // samme error being logged multiple times.
+ mAnrTracker.eraseToken(mAnrTracker.firstToken());
return nextAnrCheck;
}
connection->responsive = false;
@@ -1344,7 +1344,7 @@
motionEntry.deviceId, mTouchStatesByDisplay);
for (const auto& windowHandle : touchedSpies) {
const std::shared_ptr<Connection> connection =
- getConnectionLocked(windowHandle->getToken());
+ mConnectionManager.getConnection(windowHandle->getToken());
if (connection != nullptr && connection->responsive) {
// This spy window could take more input. Drop all events preceding this
// event, so that the spy window can get a chance to receive the stream.
@@ -1727,7 +1727,8 @@
void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime,
std::shared_ptr<const FocusEntry> entry) {
- std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(entry->connectionToken);
if (connection == nullptr) {
return; // Connection has gone away
}
@@ -1795,7 +1796,7 @@
}
}
- auto connection = getConnectionLocked(token);
+ auto connection = mConnectionManager.getConnection(token);
if (connection == nullptr) {
// Window has gone away, clean up Pointer Capture state.
mWindowTokenWithPointerCapture = nullptr;
@@ -1834,7 +1835,7 @@
if (token == nullptr) {
continue;
}
- std::shared_ptr<Connection> connection = getConnectionLocked(token);
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(token);
if (connection == nullptr) {
continue; // Connection has gone away
}
@@ -2127,7 +2128,8 @@
void InputDispatcher::dispatchDragLocked(nsecs_t currentTime,
std::shared_ptr<const DragEntry> entry) {
- std::shared_ptr<Connection> connection = getConnectionLocked(entry->connectionToken);
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(entry->connectionToken);
if (connection == nullptr) {
return; // Connection has gone away
}
@@ -2371,26 +2373,6 @@
return focusedWindowHandle;
}
-/**
- * Given a list of monitors, remove the ones we cannot find a connection for, and the ones
- * that are currently unresponsive.
- */
-std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked(
- const std::vector<Monitor>& monitors) const {
- std::vector<Monitor> responsiveMonitors;
- std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors),
- [](const Monitor& monitor) REQUIRES(mLock) {
- std::shared_ptr<Connection> connection = monitor.connection;
- if (!connection->responsive) {
- ALOGW("Unresponsive monitor %s will not get the new gesture",
- connection->getInputChannelName().c_str());
- return false;
- }
- return true;
- });
- return responsiveMonitors;
-}
-
base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) {
ATRACE_CALL();
@@ -2933,7 +2915,8 @@
const WindowInfo* windowInfo = windowHandle->getInfo();
if (it == inputTargets.end()) {
- std::shared_ptr<Connection> connection = getConnectionLocked(windowHandle->getToken());
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(windowHandle->getToken());
if (connection == nullptr) {
ALOGW("Not creating InputTarget for %s, no input channel",
windowHandle->getName().c_str());
@@ -2987,7 +2970,8 @@
const WindowInfo* windowInfo = windowHandle->getInfo();
if (it == inputTargets.end()) {
- std::shared_ptr<Connection> connection = getConnectionLocked(windowHandle->getToken());
+ std::shared_ptr<Connection> connection =
+ mConnectionManager.getConnection(windowHandle->getToken());
if (connection == nullptr) {
ALOGW("Not creating InputTarget for %s, no input channel",
windowHandle->getName().c_str());
@@ -3022,18 +3006,30 @@
void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
ui::LogicalDisplayId displayId) {
- auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
- if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
+ mConnectionManager
+ .forEachGlobalMonitorConnection(displayId,
+ [&](const std::shared_ptr<Connection>& connection) {
+ if (!connection->responsive) {
+ ALOGW("Ignoring unrsponsive monitor: %s",
+ connection->getInputChannelName()
+ .c_str());
+ return;
+ }
- for (const Monitor& monitor : selectResponsiveMonitorsLocked(monitorsIt->second)) {
- InputTarget target{monitor.connection};
- // target.firstDownTimeInTarget is not set for global monitors. It is only required in split
- // touch and global monitoring works as intended even without setting firstDownTimeInTarget.
- // Since global monitors don't have windows, use the display transform as the raw transform.
- target.rawTransform = mWindowInfos.getDisplayTransform(displayId);
- target.setDefaultPointerTransform(target.rawTransform);
- inputTargets.push_back(target);
- }
+ InputTarget target{connection};
+ // target.firstDownTimeInTarget is not set for
+ // global monitors. It is only required in split
+ // touch and global monitoring works as intended
+ // even without setting firstDownTimeInTarget. Since
+ // global monitors don't have windows, use the
+ // display transform as the raw transform.
+ base::ScopedLockAssertion assumeLocked(mLock);
+ target.rawTransform =
+ mWindowInfos.getDisplayTransform(displayId);
+ target.setDefaultPointerTransform(
+ target.rawTransform);
+ inputTargets.push_back(target);
+ });
}
/**
@@ -3992,7 +3988,7 @@
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
std::scoped_lock _l(mLock);
- std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(connectionToken);
if (connection == nullptr) {
ALOGW("Received looper callback for unknown input channel token %p. events=0x%x",
connectionToken.get(), events);
@@ -4100,12 +4096,12 @@
void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked(
const CancelationOptions& options) {
- for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
- for (const Monitor& monitor : monitors) {
- synthesizeCancelationEventsForConnectionLocked(monitor.connection, options,
- /*window=*/nullptr);
- }
- }
+ mConnectionManager.forEachGlobalMonitorConnection(
+ [&](const std::shared_ptr<Connection>& connection) {
+ base::ScopedLockAssertion assumeLocked(mLock);
+ synthesizeCancelationEventsForConnectionLocked(connection, options,
+ /*window=*/nullptr);
+ });
}
void InputDispatcher::synthesizeCancelationEventsForWindowLocked(
@@ -4123,7 +4119,7 @@
}
std::shared_ptr<Connection> resolvedConnection =
- connection ? connection : getConnectionLocked(windowHandle->getToken());
+ connection ? connection : mConnectionManager.getConnection(windowHandle->getToken());
if (!resolvedConnection) {
LOG(DEBUG) << __func__ << "No connection found for window: " << windowHandle->getName();
return;
@@ -4541,9 +4537,8 @@
args.displayId.toString().c_str()));
Result<void> result =
it->second.processMovement(args.deviceId, args.source, args.action,
- args.actionButton, args.getPointerCount(),
- args.pointerProperties.data(), args.pointerCoords.data(),
- args.flags, args.buttonState);
+ args.getPointerCount(), args.pointerProperties.data(),
+ args.pointerCoords.data(), args.flags);
if (!result.ok()) {
LOG(FATAL) << "Bad stream: " << result.error() << " caused by " << args.dump();
}
@@ -4744,10 +4739,9 @@
Result<void> result =
verifier.processMovement(deviceId, motionEvent.getSource(), motionEvent.getAction(),
- motionEvent.getActionButton(), motionEvent.getPointerCount(),
+ motionEvent.getPointerCount(),
motionEvent.getPointerProperties(),
- motionEvent.getSamplePointerCoords(), flags,
- motionEvent.getButtonState());
+ motionEvent.getSamplePointerCoords(), flags);
if (!result.ok()) {
logDispatchStateLocked();
LOG(ERROR) << "Inconsistent event: " << motionEvent << ", reason: " << result.error();
@@ -5290,7 +5284,7 @@
return false;
}
- std::shared_ptr<Connection> connection = getConnectionLocked(window->getToken());
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(window->getToken());
if (connection == nullptr) {
ALOGW("Not sending touch to %s because there's no corresponding connection",
window->getName().c_str());
@@ -5353,7 +5347,7 @@
std::vector<sp<WindowInfoHandle>> newHandles;
for (const sp<WindowInfoHandle>& handle : windowInfoHandles) {
const WindowInfo* info = handle->getInfo();
- if (getConnectionLocked(handle->getToken()) == nullptr) {
+ if (mConnectionManager.getConnection(handle->getToken()) == nullptr) {
const bool noInputChannel =
info->inputConfig.test(WindowInfo::InputConfig::NO_INPUT_CHANNEL);
const bool canReceiveInput =
@@ -5859,8 +5853,8 @@
// Synthesize cancel for old window and down for new window.
ScopedSyntheticEventTracer traceContext(mTracer);
- std::shared_ptr<Connection> fromConnection = getConnectionLocked(fromToken);
- std::shared_ptr<Connection> toConnection = getConnectionLocked(toToken);
+ std::shared_ptr<Connection> fromConnection = mConnectionManager.getConnection(fromToken);
+ std::shared_ptr<Connection> toConnection = mConnectionManager.getConnection(toToken);
if (fromConnection != nullptr && toConnection != nullptr) {
fromConnection->inputState.mergePointerStateTo(toConnection->inputState);
CancelationOptions options(CancelationOptions::Mode::CANCEL_POINTER_EVENTS,
@@ -6035,18 +6029,10 @@
dump += addLinePrefix(mWindowInfos.dumpDisplayAndWindowInfo(), INDENT);
- if (!mGlobalMonitorsByDisplay.empty()) {
- for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
- dump += StringPrintf(INDENT "Global monitors on display %s:\n",
- displayId.toString().c_str());
- dumpMonitors(dump, monitors);
- }
- } else {
- dump += INDENT "Global Monitors: <none>\n";
- }
-
const nsecs_t currentTime = now();
+ dump += addLinePrefix(mConnectionManager.dump(currentTime), INDENT);
+
// Dump recently dispatched or dropped events from oldest to newest.
if (!mRecentQueue.empty()) {
dump += StringPrintf(INDENT "RecentQueue: length=%zu\n", mRecentQueue.size());
@@ -6088,37 +6074,6 @@
dump += INDENT "CommandQueue: <empty>\n";
}
- if (!mConnectionsByToken.empty()) {
- dump += INDENT "Connections:\n";
- for (const auto& [token, connection] : mConnectionsByToken) {
- dump += StringPrintf(INDENT2 "%i: channelName='%s', "
- "status=%s, monitor=%s, responsive=%s\n",
- connection->inputPublisher.getChannel().getFd(),
- connection->getInputChannelName().c_str(),
- ftl::enum_string(connection->status).c_str(),
- toString(connection->monitor), toString(connection->responsive));
-
- if (!connection->outboundQueue.empty()) {
- dump += StringPrintf(INDENT3 "OutboundQueue: length=%zu\n",
- connection->outboundQueue.size());
- dump += dumpQueue(connection->outboundQueue, currentTime);
- }
-
- if (!connection->waitQueue.empty()) {
- dump += StringPrintf(INDENT3 "WaitQueue: length=%zu\n",
- connection->waitQueue.size());
- dump += dumpQueue(connection->waitQueue, currentTime);
- }
- std::string inputStateDump = streamableToString(connection->inputState);
- if (!inputStateDump.empty()) {
- dump += INDENT3 "InputState: ";
- dump += inputStateDump + "\n";
- }
- }
- } else {
- dump += INDENT "Connections: <none>\n";
- }
-
if (!mTouchModePerDisplay.empty()) {
dump += INDENT "TouchModePerDisplay:\n";
for (const auto& [displayId, touchMode] : mTouchModePerDisplay) {
@@ -6139,16 +6094,6 @@
dump += mTracer == nullptr ? "Disabled" : "Enabled";
}
-void InputDispatcher::dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const {
- const size_t numMonitors = monitors.size();
- for (size_t i = 0; i < numMonitors; i++) {
- const Monitor& monitor = monitors[i];
- const std::shared_ptr<Connection>& connection = monitor.connection;
- dump += StringPrintf(INDENT2 "%zu: '%s', ", i, connection->getInputChannelName().c_str());
- dump += "\n";
- }
-}
-
class LooperEventCallback : public LooperCallback {
public:
LooperEventCallback(std::function<int(int events)> callback) : mCallback(callback) {}
@@ -6174,21 +6119,10 @@
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
- const int fd = serverChannel->getFd();
- std::shared_ptr<Connection> connection =
- std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
- mIdGenerator);
-
- auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
- if (!inserted) {
- ALOGE("Created a new connection, but the token %p is already known", token.get());
- }
-
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
- mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
- nullptr);
+ mConnectionManager.createConnection(std::move(serverChannel), mIdGenerator, callback);
} // release lock
// Wake the looper because some connections have changed.
@@ -6214,23 +6148,11 @@
}
const sp<IBinder>& token = serverChannel->getConnectionToken();
- const int fd = serverChannel->getFd();
- std::shared_ptr<Connection> connection =
- std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/true,
- mIdGenerator);
-
- auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
- if (!inserted) {
- ALOGE("Created a new connection, but the token %p is already known", token.get());
- }
-
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
- mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
-
- mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
- nullptr);
+ mConnectionManager.createGlobalInputMonitor(displayId, std::move(serverChannel),
+ mIdGenerator, pid, callback);
}
// Wake the looper because some connections have changed.
@@ -6241,7 +6163,7 @@
status_t InputDispatcher::removeInputChannel(const sp<IBinder>& connectionToken) {
{ // acquire lock
std::scoped_lock _l(mLock);
- std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
+ std::shared_ptr<Connection> connection = mConnectionManager.getConnection(connectionToken);
if (connection == nullptr) {
// Connection can be removed via socket hang up or an explicit call to
// 'removeInputChannel'
@@ -6264,19 +6186,14 @@
bool notify) {
LOG_ALWAYS_FATAL_IF(connection == nullptr);
abortBrokenDispatchCycleLocked(connection, notify);
- removeConnectionLocked(connection);
- if (connection->monitor) {
- removeMonitorChannelLocked(connection->getToken());
- }
+ mAnrTracker.eraseToken(connection->getToken());
+ mConnectionManager.removeConnection(connection);
- mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
-
- connection->status = Connection::Status::ZOMBIE;
return OK;
}
-void InputDispatcher::removeMonitorChannelLocked(const sp<IBinder>& connectionToken) {
+void InputDispatcher::ConnectionManager::removeMonitorChannel(const sp<IBinder>& connectionToken) {
for (auto it = mGlobalMonitorsByDisplay.begin(); it != mGlobalMonitorsByDisplay.end();) {
auto& [displayId, monitors] = *it;
std::erase_if(monitors, [connectionToken](const Monitor& monitor) {
@@ -6297,7 +6214,8 @@
}
status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
- const std::shared_ptr<Connection> requestingConnection = getConnectionLocked(token);
+ const std::shared_ptr<Connection> requestingConnection =
+ mConnectionManager.getConnection(token);
if (!requestingConnection) {
LOG(WARNING)
<< "Attempted to pilfer pointers from an un-registered channel or invalid token";
@@ -6404,7 +6322,8 @@
} // release lock
}
-std::optional<gui::Pid> InputDispatcher::findMonitorPidByTokenLocked(const sp<IBinder>& token) {
+std::optional<gui::Pid> InputDispatcher::ConnectionManager::findMonitorPidByToken(
+ const sp<IBinder>& token) const {
for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
for (const Monitor& monitor : monitors) {
if (monitor.connection->getToken() == token) {
@@ -6415,7 +6334,7 @@
return std::nullopt;
}
-std::shared_ptr<Connection> InputDispatcher::getConnectionLocked(
+std::shared_ptr<Connection> InputDispatcher::ConnectionManager::getConnection(
const sp<IBinder>& inputConnectionToken) const {
if (inputConnectionToken == nullptr) {
return nullptr;
@@ -6430,19 +6349,6 @@
return nullptr;
}
-std::string InputDispatcher::getConnectionNameLocked(const sp<IBinder>& connectionToken) const {
- std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
- if (connection == nullptr) {
- return "<nullptr>";
- }
- return connection->getInputChannelName();
-}
-
-void InputDispatcher::removeConnectionLocked(const std::shared_ptr<Connection>& connection) {
- mAnrTracker.eraseToken(connection->getToken());
- mConnectionsByToken.erase(connection->getToken());
-}
-
void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled,
@@ -6667,7 +6573,7 @@
if (connection.monitor) {
ALOGW("Monitor %s is unresponsive: %s", connection.getInputChannelName().c_str(),
reason.c_str());
- pid = findMonitorPidByTokenLocked(connectionToken);
+ pid = mConnectionManager.findMonitorPidByToken(connectionToken);
} else {
// The connection is a window
ALOGW("Window %s is unresponsive: %s", connection.getInputChannelName().c_str(),
@@ -6687,7 +6593,7 @@
const sp<IBinder>& connectionToken = connection.getToken();
std::optional<gui::Pid> pid;
if (connection.monitor) {
- pid = findMonitorPidByTokenLocked(connectionToken);
+ pid = mConnectionManager.findMonitorPidByToken(connectionToken);
} else {
// The connection is a window
const sp<WindowInfoHandle> handle = mWindowInfos.findWindowHandle(connectionToken);
@@ -7248,10 +7154,10 @@
state.addOrUpdateWindow(newWallpaper, InputTarget::DispatchMode::AS_IS, wallpaperFlags,
deviceId, pointers, downTimeInTarget);
std::shared_ptr<Connection> wallpaperConnection =
- getConnectionLocked(newWallpaper->getToken());
+ mConnectionManager.getConnection(newWallpaper->getToken());
if (wallpaperConnection != nullptr) {
std::shared_ptr<Connection> toConnection =
- getConnectionLocked(toWindowHandle->getToken());
+ mConnectionManager.getConnection(toWindowHandle->getToken());
toConnection->inputState.mergePointerStateTo(wallpaperConnection->inputState);
synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, wallpaperConnection,
wallpaperFlags, traceTracker);
@@ -7315,4 +7221,132 @@
}
}
+InputDispatcher::ConnectionManager::ConnectionManager(const sp<android::Looper>& looper)
+ : mLooper(looper) {}
+
+// This destructor is required to ensure cleanup of each input connection, so that the fd is
+// removed from the looper.
+InputDispatcher::ConnectionManager::~ConnectionManager() {
+ while (!mConnectionsByToken.empty()) {
+ std::shared_ptr<Connection> connection = mConnectionsByToken.begin()->second;
+ removeConnection(connection);
+ }
+}
+
+void InputDispatcher::ConnectionManager::forEachGlobalMonitorConnection(
+ std::function<void(const std::shared_ptr<Connection>&)> f) const {
+ for (const auto& [_, monitors] : mGlobalMonitorsByDisplay) {
+ for (const Monitor& monitor : monitors) {
+ f(monitor.connection);
+ }
+ }
+}
+
+void InputDispatcher::ConnectionManager::forEachGlobalMonitorConnection(
+ ui::LogicalDisplayId displayId,
+ std::function<void(const std::shared_ptr<Connection>&)> f) const {
+ auto monitorsIt = mGlobalMonitorsByDisplay.find(displayId);
+ if (monitorsIt == mGlobalMonitorsByDisplay.end()) return;
+
+ for (const Monitor& monitor : monitorsIt->second) {
+ f(monitor.connection);
+ }
+}
+
+void InputDispatcher::ConnectionManager::createGlobalInputMonitor(
+ ui::LogicalDisplayId displayId, std::unique_ptr<InputChannel>&& inputChannel,
+ const android::IdGenerator& idGenerator, gui::Pid pid, std::function<int(int)> callback) {
+ const int fd = inputChannel->getFd();
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(std::move(inputChannel), /*monitor=*/true, idGenerator);
+ sp<IBinder> token = connection->getToken();
+ auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
+ if (!inserted) {
+ ALOGE("Created a new connection, but the token %p is already known", token.get());
+ }
+ mGlobalMonitorsByDisplay[displayId].emplace_back(connection, pid);
+
+ mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback), nullptr);
+}
+
+void InputDispatcher::ConnectionManager::createConnection(
+ std::unique_ptr<InputChannel>&& inputChannel, const android::IdGenerator& idGenerator,
+ std::function<int(int)> callback) {
+ const int fd = inputChannel->getFd();
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(std::move(inputChannel), /*monitor=*/false, idGenerator);
+ sp<IBinder> token = connection->getToken();
+ auto [_, inserted] = mConnectionsByToken.try_emplace(token, connection);
+ if (!inserted) {
+ ALOGE("Created a new connection, but the token %p is already known", token.get());
+ }
+
+ mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback), nullptr);
+}
+
+status_t InputDispatcher::ConnectionManager::removeConnection(
+ const std::shared_ptr<Connection>& connection) {
+ mConnectionsByToken.erase(connection->getToken());
+
+ if (connection->monitor) {
+ removeMonitorChannel(connection->getToken());
+ }
+
+ mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
+
+ connection->status = Connection::Status::ZOMBIE;
+ return OK;
+}
+
+std::string InputDispatcher::ConnectionManager::dump(nsecs_t currentTime) const {
+ std::string dump;
+ if (!mGlobalMonitorsByDisplay.empty()) {
+ for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) {
+ dump += StringPrintf("Global monitors on display %s:\n", displayId.toString().c_str());
+ const size_t numMonitors = monitors.size();
+ for (size_t i = 0; i < numMonitors; i++) {
+ const Monitor& monitor = monitors[i];
+ const std::shared_ptr<Connection>& connection = monitor.connection;
+ dump += StringPrintf(INDENT "%zu: '%s', ", i,
+ connection->getInputChannelName().c_str());
+ dump += "\n";
+ }
+ }
+ } else {
+ dump += "Global Monitors: <none>\n";
+ }
+
+ if (!mConnectionsByToken.empty()) {
+ dump += "Connections:\n";
+ for (const auto& [token, connection] : mConnectionsByToken) {
+ dump += StringPrintf(INDENT "%i: channelName='%s', "
+ "status=%s, monitor=%s, responsive=%s\n",
+ connection->inputPublisher.getChannel().getFd(),
+ connection->getInputChannelName().c_str(),
+ ftl::enum_string(connection->status).c_str(),
+ toString(connection->monitor), toString(connection->responsive));
+
+ if (!connection->outboundQueue.empty()) {
+ dump += StringPrintf(INDENT2 "OutboundQueue: length=%zu\n",
+ connection->outboundQueue.size());
+ dump += dumpQueue(connection->outboundQueue, currentTime);
+ }
+
+ if (!connection->waitQueue.empty()) {
+ dump += StringPrintf(INDENT2 "WaitQueue: length=%zu\n",
+ connection->waitQueue.size());
+ dump += dumpQueue(connection->waitQueue, currentTime);
+ }
+ std::string inputStateDump = streamableToString(connection->inputState);
+ if (!inputStateDump.empty()) {
+ dump += INDENT2 "InputState: ";
+ dump += inputStateDump + "\n";
+ }
+ }
+ } else {
+ dump += "Connections: <none>\n";
+ }
+ return dump;
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index bca1c67..7bfa738 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -260,13 +260,6 @@
const std::unordered_map<ui::LogicalDisplayId, TouchState>& touchStatesByDisplay,
ui::LogicalDisplayId displayId);
- std::shared_ptr<Connection> getConnectionLocked(const sp<IBinder>& inputConnectionToken) const
- REQUIRES(mLock);
-
- std::string getConnectionNameLocked(const sp<IBinder>& connectionToken) const REQUIRES(mLock);
-
- void removeConnectionLocked(const std::shared_ptr<Connection>& connection) REQUIRES(mLock);
-
status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
template <typename T>
@@ -274,17 +267,6 @@
std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); }
};
- // All registered connections mapped by input channel token.
- std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
- mConnectionsByToken GUARDED_BY(mLock);
-
- // Find a monitor pid by the provided token.
- std::optional<gui::Pid> findMonitorPidByTokenLocked(const sp<IBinder>& token) REQUIRES(mLock);
-
- // Input channels that will receive a copy of all input events sent to the provided display.
- std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay
- GUARDED_BY(mLock);
-
const HmacKeyManager mHmacKeyManager;
const std::array<uint8_t, 32> getSignature(const MotionEntry& motionEntry,
const DispatchEntry& dispatchEntry) const;
@@ -417,6 +399,48 @@
DispatcherWindowInfo mWindowInfos GUARDED_BY(mLock);
+ class ConnectionManager {
+ public:
+ ConnectionManager(const sp<Looper>& lopper);
+ ~ConnectionManager();
+
+ std::shared_ptr<Connection> getConnection(const sp<IBinder>& inputConnectionToken) const;
+
+ // Find a monitor pid by the provided token.
+ std::optional<gui::Pid> findMonitorPidByToken(const sp<IBinder>& token) const;
+ void forEachGlobalMonitorConnection(
+ std::function<void(const std::shared_ptr<Connection>&)> f) const;
+ void forEachGlobalMonitorConnection(
+ ui::LogicalDisplayId displayId,
+ std::function<void(const std::shared_ptr<Connection>&)> f) const;
+
+ void createGlobalInputMonitor(ui::LogicalDisplayId displayId,
+ std::unique_ptr<InputChannel>&& inputChannel,
+ const IdGenerator& idGenerator, gui::Pid pid,
+ std::function<int(int)> callback);
+
+ status_t removeConnection(const std::shared_ptr<Connection>& connection);
+
+ void createConnection(std::unique_ptr<InputChannel>&& inputChannel,
+ const IdGenerator& idGenerator, std::function<int(int)> callback);
+
+ std::string dump(nsecs_t currentTime) const;
+
+ private:
+ const sp<Looper> mLooper;
+
+ // All registered connections mapped by input channel token.
+ std::unordered_map<sp<IBinder>, std::shared_ptr<Connection>, StrongPointerHash<IBinder>>
+ mConnectionsByToken;
+
+ // Input channels that will receive a copy of all input events sent to the provided display.
+ std::unordered_map<ui::LogicalDisplayId, std::vector<Monitor>> mGlobalMonitorsByDisplay;
+
+ void removeMonitorChannel(const sp<IBinder>& connectionToken);
+ };
+
+ ConnectionManager mConnectionManager GUARDED_BY(mLock);
+
void setInputWindowsLocked(
const std::vector<sp<android::gui::WindowInfoHandle>>& inputWindowHandles,
ui::LogicalDisplayId displayId) REQUIRES(mLock);
@@ -582,8 +606,6 @@
nsecs_t& nextWakeupTime) REQUIRES(mLock);
base::Result<std::vector<InputTarget>, android::os::InputEventInjectionResult>
findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry& entry) REQUIRES(mLock);
- std::vector<Monitor> selectResponsiveMonitorsLocked(
- const std::vector<Monitor>& gestureMonitors) const REQUIRES(mLock);
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
InputTarget::DispatchMode dispatchMode,
@@ -689,12 +711,9 @@
// Dump state.
void dumpDispatchStateLocked(std::string& dump) const REQUIRES(mLock);
- void dumpMonitors(std::string& dump, const std::vector<Monitor>& monitors) const;
void logDispatchStateLocked() const REQUIRES(mLock);
std::string dumpPointerCaptureStateLocked() const REQUIRES(mLock);
- // Registration.
- void removeMonitorChannelLocked(const sp<IBinder>& connectionToken) REQUIRES(mLock);
status_t removeInputChannelLocked(const std::shared_ptr<Connection>& connection, bool notify)
REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp b/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp
index 881a96b..4da05c1 100644
--- a/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp
+++ b/services/inputflinger/dispatcher/LatencyAggregatorWithHistograms.cpp
@@ -133,10 +133,11 @@
}
void LatencyAggregatorWithHistograms::processStatistics(const InputEventTimeline& timeline) {
- // Only gather data for Down, Move and Up motion events and Key events
+ // Only gather data for Down, Move, Up and Scroll motion events and Key events
if (!(timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_DOWN ||
timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_MOVE ||
timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_UP ||
+ timeline.inputEventActionType == InputEventActionType::MOTION_ACTION_SCROLL ||
timeline.inputEventActionType == InputEventActionType::KEY))
return;
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
index 535c7ae..9039751 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
@@ -16,9 +16,7 @@
#include "AndroidInputEventProtoConverter.h"
-#include <android/input.h>
#include <android-base/logging.h>
-#include <input/Input.h>
#include <perfetto/trace/android/android_input_event.pbzero.h>
namespace android::inputdispatcher::trace {
@@ -73,12 +71,6 @@
const auto& coords = event.pointerCoords[i];
auto bits = BitSet64(coords.bits);
- if (isFromSource(event.source, AINPUT_SOURCE_CLASS_POINTER)) {
- // Always include the X and Y axes for pointer events, since the
- // bits will not be marked if the value is 0.
- bits.markBit(AMOTION_EVENT_AXIS_X);
- bits.markBit(AMOTION_EVENT_AXIS_Y);
- }
for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
const auto axis = bits.clearFirstMarkedBit();
auto axisEntry = pointer->add_axis_value();
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 24919b6..207806d 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -1085,7 +1085,7 @@
return mReader->mEventHub.get();
}
-int32_t InputReader::ContextImpl::getNextId() {
+int32_t InputReader::ContextImpl::getNextId() const {
return mIdGenerator.nextId();
}
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 1403ca2..931766b 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -154,7 +154,7 @@
REQUIRES(mReader->mLock) override;
InputReaderPolicyInterface* getPolicy() REQUIRES(mReader->mLock) override;
EventHubInterface* getEventHub() REQUIRES(mReader->mLock) override;
- int32_t getNextId() NO_THREAD_SAFETY_ANALYSIS override;
+ int32_t getNextId() const NO_THREAD_SAFETY_ANALYSIS override;
void updateLedMetaState(int32_t metaState) REQUIRES(mReader->mLock) override;
int32_t getLedMetaState() REQUIRES(mReader->mLock) REQUIRES(mLock) override;
void setPreventingTouchpadTaps(bool prevent) REQUIRES(mReader->mLock)
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index e0e0ac2..20ed74f 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -55,7 +55,7 @@
virtual InputReaderPolicyInterface* getPolicy() = 0;
virtual EventHubInterface* getEventHub() = 0;
- virtual int32_t getNextId() = 0;
+ virtual int32_t getNextId() const = 0;
virtual void updateLedMetaState(int32_t metaState) = 0;
virtual int32_t getLedMetaState() = 0;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 9f584a0..e21c2f9 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -419,7 +419,7 @@
}
}
-std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> CursorInputMapper::getAssociatedDisplayId() const {
return mDisplayId;
}
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 773619c..301632f 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -63,7 +63,7 @@
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
- virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
private:
// Amount that trackball needs to move in order to generate a key event.
@@ -115,7 +115,6 @@
ui::Rotation mOrientation{ui::ROTATION_0};
FloatRect mBoundsInLogicalDisplay{};
- // The button state as of the last sync.
int32_t mButtonState;
nsecs_t mDownTime;
nsecs_t mLastEventTime;
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index d4a86ac..630c3d9 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -66,11 +66,12 @@
virtual ~InputMapper();
- inline int32_t getDeviceId() { return mDeviceContext.getId(); }
+ inline int32_t getDeviceId() const { return mDeviceContext.getId(); }
inline InputDeviceContext& getDeviceContext() { return mDeviceContext; }
inline InputDeviceContext& getDeviceContext() const { return mDeviceContext; };
inline const std::string getDeviceName() const { return mDeviceContext.getName(); }
inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }
+ inline const InputReaderContext* getContext() const { return mDeviceContext.getContext(); }
inline InputReaderPolicyInterface* getPolicy() { return getContext()->getPolicy(); }
virtual uint32_t getSources() const = 0;
@@ -114,7 +115,9 @@
[[nodiscard]] virtual std::list<NotifyArgs> updateExternalStylusState(const StylusState& state);
- virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() { return std::nullopt; }
+ virtual std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const {
+ return std::nullopt;
+ }
virtual void updateLedState(bool reset) {}
virtual std::optional<HardwareProperties> getTouchpadHardwareProperties();
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index fe3e4c2..400792b 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -104,14 +104,14 @@
return mMapperSource;
}
-ui::Rotation KeyboardInputMapper::getOrientation() {
+ui::Rotation KeyboardInputMapper::getOrientation() const {
if (mViewport) {
return mViewport->orientation;
}
return ui::ROTATION_0;
}
-ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() {
+ui::LogicalDisplayId KeyboardInputMapper::getDisplayId() const {
if (mViewport) {
return mViewport->displayId;
}
@@ -471,7 +471,7 @@
}
}
-std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> KeyboardInputMapper::getAssociatedDisplayId() const {
if (mViewport) {
return std::make_optional(mViewport->displayId);
}
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 7d9b3e4..9e2a81b 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -47,7 +47,7 @@
int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override;
int32_t getMetaState() override;
- std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
void updateLedState(bool reset) override;
private:
@@ -96,8 +96,8 @@
void configureParameters();
void dumpParameters(std::string& dump) const;
- ui::Rotation getOrientation();
- ui::LogicalDisplayId getDisplayId();
+ ui::Rotation getOrientation() const;
+ ui::LogicalDisplayId getDisplayId() const;
[[nodiscard]] std::list<NotifyArgs> processKey(nsecs_t when, nsecs_t readTime, bool down,
int32_t scanCode, int32_t usageCode);
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 6efaeca..5cfda03 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -3666,7 +3666,7 @@
int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords,
const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision,
- float yPrecision, nsecs_t downTime, MotionClassification classification) {
+ float yPrecision, nsecs_t downTime, MotionClassification classification) const {
std::vector<PointerCoords> pointerCoords;
std::vector<PointerProperties> pointerProperties;
uint32_t pointerCount = 0;
@@ -3992,7 +3992,7 @@
return true;
}
-std::optional<ui::LogicalDisplayId> TouchInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> TouchInputMapper::getAssociatedDisplayId() const {
return mParameters.hasAssociatedDisplay ? std::make_optional(mViewport.displayId)
: std::nullopt;
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index eb4326f..96fc61b 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -185,7 +185,7 @@
[[nodiscard]] std::list<NotifyArgs> timeoutExpired(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> updateExternalStylusState(
const StylusState& state) override;
- std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
protected:
CursorButtonAccumulator mCursorButtonAccumulator;
@@ -840,7 +840,7 @@
int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
int32_t edgeFlags, const PropertiesArray& properties, const CoordsArray& coords,
const IdToIndexArray& idToIndex, BitSet32 idBits, int32_t changedId, float xPrecision,
- float yPrecision, nsecs_t downTime, MotionClassification classification);
+ float yPrecision, nsecs_t downTime, MotionClassification classification) const;
// Returns if this touch device is a touch screen with an associated display.
bool isTouchScreen();
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 0df3364..18a7102 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -506,7 +506,7 @@
return out;
}
-std::optional<ui::LogicalDisplayId> TouchpadInputMapper::getAssociatedDisplayId() {
+std::optional<ui::LogicalDisplayId> TouchpadInputMapper::getAssociatedDisplayId() const {
return mDisplayId;
}
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 56553c9..9f53a7b 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -66,7 +66,7 @@
using MetricsIdentifier = std::tuple<uint16_t /*busId*/, uint16_t /*vendorId*/,
uint16_t /*productId*/, uint16_t /*version*/>;
- std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() override;
+ std::optional<ui::LogicalDisplayId> getAssociatedDisplayId() const override;
std::optional<HardwareProperties> getTouchpadHardwareProperties() override;
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
index 827076a..480e276 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp
@@ -14,11 +14,15 @@
* limitations under the License.
*/
+#include "../Macros.h"
+
#include "gestures/GestureConverter.h"
+#include <ios>
#include <optional>
#include <sstream>
+#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <com_android_input_flags.h>
#include <ftl/enum.h>
@@ -250,6 +254,18 @@
const Gesture& gesture) {
std::list<NotifyArgs> out = {};
+ if (mCurrentClassification != MotionClassification::NONE) {
+ // Handling button changes during an ongoing gesture would be tricky, as we'd have to avoid
+ // sending duplicate DOWN events or premature UP events (e.g. if the gesture ended but the
+ // button was still down). It would also make handling touchpad events more difficult for
+ // apps, which would have to handle cases where e.g. a scroll gesture ends (and therefore
+ // the event lose the TWO_FINGER_SWIPE classification) but there isn't an UP because the
+ // button's still down. It's unclear how one should even handle button changes during most
+ // gestures, and they're probably accidental anyway. So, instead, just ignore them.
+ LOG(INFO) << "Ignoring button change because a gesture is ongoing.";
+ return out;
+ }
+
PointerCoords coords;
coords.clear();
coords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0);
@@ -312,6 +328,15 @@
for (uint32_t button = 1; button <= GESTURES_BUTTON_FORWARD; button <<= 1) {
if (buttonsReleased & button) {
uint32_t actionButton = gesturesButtonToMotionEventButton(button);
+ if (!(newButtonState & actionButton)) {
+ // We must have received the ButtonsChange gesture that put this button down during
+ // another gesture, and therefore dropped the BUTTON_PRESS action for it, or
+ // released the button when another gesture began during its press. Drop the
+ // BUTTON_RELEASE too to keep the stream consistent.
+ LOG(INFO) << "Dropping release event for button 0x" << std::hex << actionButton
+ << " as it wasn't in the button state.";
+ continue;
+ }
newButtonState &= ~actionButton;
out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
actionButton, newButtonState, /* pointerCount= */ 1,
@@ -362,7 +387,7 @@
std::list<NotifyArgs> out;
PointerCoords& coords = mFakeFingerCoords[0];
if (mCurrentClassification != MotionClassification::TWO_FINGER_SWIPE) {
- out += exitHover(when, readTime);
+ out += prepareForFakeFingerGesture(when, readTime);
mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
coords.clear();
@@ -421,7 +446,7 @@
std::list<NotifyArgs> out;
mDownTime = when;
mCurrentClassification = MotionClassification::TWO_FINGER_SWIPE;
- out += exitHover(when, readTime);
+ out += prepareForFakeFingerGesture(when, readTime);
out.push_back(makeMotionArgs(when, readTime, AMOTION_EVENT_ACTION_DOWN,
/*actionButton=*/0, /*buttonState=*/0,
/*pointerCount=*/1, &coords));
@@ -479,7 +504,7 @@
// separate swipes with an appropriate lift event between them, so we don't have to worry
// about the finger count changing mid-swipe.
- out += exitHover(when, readTime);
+ out += prepareForFakeFingerGesture(when, readTime);
mCurrentClassification = MotionClassification::MULTI_FINGER_SWIPE;
@@ -567,9 +592,7 @@
LOG_ALWAYS_FATAL_IF(gesture.details.pinch.zoom_state != GESTURES_ZOOM_START,
"First pinch gesture does not have the START zoom state (%d instead).",
gesture.details.pinch.zoom_state);
- std::list<NotifyArgs> out;
-
- out += exitHover(when, readTime);
+ std::list<NotifyArgs> out = prepareForFakeFingerGesture(when, readTime);
mCurrentClassification = MotionClassification::PINCH;
mPinchFingerSeparation = INITIAL_PINCH_SEPARATION_PX;
@@ -644,6 +667,16 @@
}
}
+std::list<NotifyArgs> GestureConverter::prepareForFakeFingerGesture(nsecs_t when,
+ nsecs_t readTime) {
+ std::list<NotifyArgs> out;
+ if (isPointerDown(mButtonState)) {
+ out += releaseAllButtons(when, readTime);
+ }
+ out += exitHover(when, readTime);
+ return out;
+}
+
NotifyMotionArgs GestureConverter::makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action) {
PointerCoords coords;
coords.clear();
diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.h b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
index 1f6acd3..ae85e3a 100644
--- a/services/inputflinger/reader/mapper/gestures/GestureConverter.h
+++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.h
@@ -92,6 +92,8 @@
[[nodiscard]] std::list<NotifyArgs> enterHover(nsecs_t when, nsecs_t readTime);
[[nodiscard]] std::list<NotifyArgs> exitHover(nsecs_t when, nsecs_t readTime);
+ [[nodiscard]] std::list<NotifyArgs> prepareForFakeFingerGesture(nsecs_t when, nsecs_t readTime);
+
NotifyMotionArgs makeHoverEvent(nsecs_t when, nsecs_t readTime, int32_t action);
NotifyMotionArgs makeMotionArgs(nsecs_t when, nsecs_t readTime, int32_t action,
diff --git a/services/inputflinger/tests/CursorInputMapper_test.cpp b/services/inputflinger/tests/CursorInputMapper_test.cpp
index 18e0b30..594ee3b 100644
--- a/services/inputflinger/tests/CursorInputMapper_test.cpp
+++ b/services/inputflinger/tests/CursorInputMapper_test.cpp
@@ -141,9 +141,9 @@
*/
class CursorInputMapperUnitTestBase : public InputMapperUnitTest {
protected:
- void SetUp() override { SetUpWithBus(BUS_USB); }
- void SetUpWithBus(int bus) override {
- InputMapperUnitTest::SetUpWithBus(bus);
+ void SetUp() override { SetUp(BUS_USB, /*isExternal=*/false); }
+ void SetUp(int bus, bool isExternal) override {
+ InputMapperUnitTest::SetUp(bus, isExternal);
// Current scan code state - all keys are UP by default
setScanCodeState(KeyState::UP,
@@ -1142,7 +1142,9 @@
class BluetoothCursorInputMapperUnitTest : public CursorInputMapperUnitTestBase {
protected:
- void SetUp() override { SetUpWithBus(BUS_BLUETOOTH); }
+ void SetUp() override {
+ CursorInputMapperUnitTestBase::SetUp(BUS_BLUETOOTH, /*isExternal=*/true);
+ }
};
TEST_F(BluetoothCursorInputMapperUnitTest, TimestampSmoothening) {
diff --git a/services/inputflinger/tests/GestureConverter_test.cpp b/services/inputflinger/tests/GestureConverter_test.cpp
index 8fa439d..fd9884b 100644
--- a/services/inputflinger/tests/GestureConverter_test.cpp
+++ b/services/inputflinger/tests/GestureConverter_test.cpp
@@ -15,11 +15,15 @@
*/
#include <memory>
+#include <tuple>
+#include <android-base/result-gmock.h>
+#include <android-base/result.h>
#include <com_android_input_flags.h>
#include <flag_macros.h>
#include <gestures/GestureConverter.h>
#include <gtest/gtest.h>
+#include <input/InputVerifier.h>
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
@@ -43,8 +47,12 @@
const auto TOUCHPAD_PALM_REJECTION_V2 =
ACONFIG_FLAG(input_flags, enable_v2_touchpad_typing_palm_rejection);
+constexpr stime_t ARBITRARY_GESTURE_TIME = 1.2;
+constexpr stime_t GESTURE_TIME = ARBITRARY_GESTURE_TIME;
+
} // namespace
+using android::base::testing::Ok;
using testing::AllOf;
using testing::Each;
using testing::ElementsAre;
@@ -55,9 +63,8 @@
protected:
static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
static constexpr int32_t EVENTHUB_ID = 1;
- static constexpr stime_t ARBITRARY_GESTURE_TIME = 1.2;
- void SetUp() {
+ GestureConverterTest() {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = sp<FakeInputReaderPolicy>::make();
mFakeListener = std::make_unique<TestInputListener>();
@@ -1698,4 +1705,135 @@
WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE))));
}
+/**
+ * Tests that the event stream output by the converter remains consistent when converting sequences
+ * of Gestures interleaved with button presses in various ways. Takes tuples of three Gestures: one
+ * that starts the gesture sequence, one that continues it (which may or may not be used in a
+ * particular test case), and one that ends it.
+ */
+class GestureConverterConsistencyTest
+ : public GestureConverterTest,
+ public testing::WithParamInterface<std::tuple<Gesture, Gesture, Gesture>> {
+protected:
+ GestureConverterConsistencyTest()
+ : GestureConverterTest(),
+ mParamStartGesture(std::get<0>(GetParam())),
+ mParamContinueGesture(std::get<1>(GetParam())),
+ mParamEndGesture(std::get<2>(GetParam())),
+ mDeviceContext(*mDevice, EVENTHUB_ID),
+ mConverter(*mReader->getContext(), mDeviceContext, DEVICE_ID),
+ mVerifier("Test verifier") {
+ mConverter.setDisplayId(ui::LogicalDisplayId::DEFAULT);
+ }
+
+ base::Result<void> processMotionArgs(NotifyMotionArgs arg) {
+ return mVerifier.processMovement(arg.deviceId, arg.source, arg.action,
+ arg.getPointerCount(), arg.pointerProperties.data(),
+ arg.pointerCoords.data(), arg.flags);
+ }
+
+ void verifyArgsFromGesture(const Gesture& gesture, size_t gestureIndex) {
+ std::list<NotifyArgs> args =
+ mConverter.handleGesture(ARBITRARY_TIME, READ_TIME, ARBITRARY_TIME, gesture);
+ for (const NotifyArgs& notifyArg : args) {
+ const NotifyMotionArgs& arg = std::get<NotifyMotionArgs>(notifyArg);
+ ASSERT_THAT(processMotionArgs(arg), Ok())
+ << "when processing " << arg.dump() << "\nfrom gesture " << gestureIndex << ": "
+ << gesture.String();
+ }
+ }
+
+ void verifyArgsFromGestures(const std::vector<Gesture>& gestures) {
+ for (size_t i = 0; i < gestures.size(); i++) {
+ ASSERT_NO_FATAL_FAILURE(verifyArgsFromGesture(gestures[i], i));
+ }
+ }
+
+ Gesture mParamStartGesture;
+ Gesture mParamContinueGesture;
+ Gesture mParamEndGesture;
+
+ InputDeviceContext mDeviceContext;
+ GestureConverter mConverter;
+ InputVerifier mVerifier;
+};
+
+TEST_P(GestureConverterConsistencyTest, ButtonChangesDuringGesture) {
+ verifyArgsFromGestures({
+ mParamStartGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamContinueGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ mParamEndGesture,
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, ButtonDownDuringGestureAndUpAfterEnd) {
+ verifyArgsFromGestures({
+ mParamStartGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamContinueGesture,
+ mParamEndGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, GestureStartAndEndDuringButtonDown) {
+ verifyArgsFromGestures({
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamStartGesture,
+ mParamContinueGesture,
+ mParamEndGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, GestureStartsWhileButtonDownAndEndsAfterUp) {
+ verifyArgsFromGestures({
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_NONE, /*is_tap=*/false),
+ mParamStartGesture,
+ mParamContinueGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_NONE, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ mParamEndGesture,
+ });
+}
+
+TEST_P(GestureConverterConsistencyTest, TapToClickDuringGesture) {
+ verifyArgsFromGestures({
+ mParamStartGesture,
+ Gesture(kGestureButtonsChange, GESTURE_TIME, GESTURE_TIME,
+ /*down=*/GESTURES_BUTTON_LEFT, /*up=*/GESTURES_BUTTON_LEFT, /*is_tap=*/false),
+ mParamEndGesture,
+ });
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ GestureAndButtonInterleavings, GestureConverterConsistencyTest,
+ testing::Values(
+ std::make_tuple(Gesture(kGestureScroll, GESTURE_TIME, GESTURE_TIME, 0, -10),
+ Gesture(kGestureScroll, GESTURE_TIME, GESTURE_TIME, 0, -5),
+ Gesture(kGestureFling, GESTURE_TIME, GESTURE_TIME, 1, 1,
+ GESTURES_FLING_START)),
+ std::make_tuple(Gesture(kGestureSwipe, GESTURE_TIME, GESTURE_TIME, 0, -10),
+ Gesture(kGestureSwipe, GESTURE_TIME, GESTURE_TIME, 0, 5),
+ Gesture(kGestureSwipeLift, GESTURE_TIME, GESTURE_TIME)),
+ std::make_tuple(Gesture(kGestureFourFingerSwipe, GESTURE_TIME, GESTURE_TIME, 0,
+ -10),
+ Gesture(kGestureFourFingerSwipe, GESTURE_TIME, GESTURE_TIME, 0, 5),
+ Gesture(kGestureFourFingerSwipeLift, GESTURE_TIME, GESTURE_TIME)),
+ std::make_tuple(Gesture(kGesturePinch, GESTURE_TIME, GESTURE_TIME,
+ /*dz=*/1, GESTURES_ZOOM_START),
+ Gesture(kGesturePinch, GESTURE_TIME, GESTURE_TIME,
+ /*dz=*/0.8, GESTURES_ZOOM_UPDATE),
+ Gesture(kGesturePinch, GESTURE_TIME, GESTURE_TIME,
+ /*dz=*/1, GESTURES_ZOOM_END))));
+
} // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e8f32bf..6b4c4b7 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -12371,69 +12371,43 @@
}
void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
- bool consumeButtonPress = false;
switch (fromSource) {
- case AINPUT_SOURCE_TOUCHSCREEN: {
+ case AINPUT_SOURCE_TOUCHSCREEN:
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
ui::LogicalDisplayId::DEFAULT, {50, 50}))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
break;
- }
- case AINPUT_SOURCE_STYLUS: {
- PointerBuilder pointer = PointerBuilder(0, ToolType::STYLUS).x(50).y(50);
+ case AINPUT_SOURCE_STYLUS:
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
AINPUT_SOURCE_STYLUS)
.buttonState(
AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
- .pointer(pointer)
+ .pointer(PointerBuilder(0, ToolType::STYLUS)
+ .x(50)
+ .y(50))
.build()));
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(*mDispatcher,
- MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
- AINPUT_SOURCE_STYLUS)
- .actionButton(
- AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
- .buttonState(
- AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
- .pointer(pointer)
- .build()));
- consumeButtonPress = true;
break;
- }
- case AINPUT_SOURCE_MOUSE: {
- PointerBuilder pointer =
- PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE).x(50).y(50);
+ case AINPUT_SOURCE_MOUSE:
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
AINPUT_SOURCE_MOUSE)
.buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(pointer)
+ .pointer(PointerBuilder(MOUSE_POINTER_ID,
+ ToolType::MOUSE)
+ .x(50)
+ .y(50))
.build()));
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(*mDispatcher,
- MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
- AINPUT_SOURCE_MOUSE)
- .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
- .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
- .pointer(pointer)
- .build()));
- consumeButtonPress = true;
break;
- }
- default: {
+ default:
FAIL() << "Source " << fromSource << " doesn't support drag and drop";
- }
}
// Window should receive motion event.
mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
- if (consumeButtonPress) {
- mWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
- }
// Spy window should also receive motion event
mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
}
@@ -12633,16 +12607,6 @@
// Move to another window and release button, expect to drop item.
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
- MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- AINPUT_SOURCE_STYLUS)
- .actionButton(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
- .buttonState(0)
- .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
- .build()))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- mDragWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
.buttonState(0)
.pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
@@ -12884,18 +12848,6 @@
// drop to another window.
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
- MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- AINPUT_SOURCE_MOUSE)
- .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
- .buttonState(0)
- .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
- .x(150)
- .y(50))
- .build()))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- mDragWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(*mDispatcher,
MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
.buttonState(0)
.pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index 8235c90..77f42f2 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -30,7 +30,7 @@
using testing::Return;
using testing::ReturnRef;
-void InputMapperUnitTest::SetUpWithBus(int bus) {
+void InputMapperUnitTest::SetUp(int bus, bool isExternal) {
mFakePolicy = sp<FakeInputReaderPolicy>::make();
EXPECT_CALL(mMockInputReaderContext, getPolicy()).WillRepeatedly(Return(mFakePolicy.get()));
@@ -46,8 +46,9 @@
return mPropertyMap;
});
- mDevice = std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID,
- /*generation=*/2, mIdentifier);
+ mDevice =
+ std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID,
+ /*generation=*/2, mIdentifier, isExternal);
ON_CALL((*mDevice), getConfiguration).WillByDefault(ReturnRef(mPropertyMap));
mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID);
}
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
index 10ef6f1..edc87a3 100644
--- a/services/inputflinger/tests/InputMapperTest.h
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -40,8 +40,8 @@
protected:
static constexpr int32_t EVENTHUB_ID = 1;
static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
- virtual void SetUp() override { SetUpWithBus(0); }
- virtual void SetUpWithBus(int bus);
+ virtual void SetUp() override { SetUp(/*bus=*/0, /*isExternal=*/false); }
+ virtual void SetUp(int bus, bool isExternal);
void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution,
int32_t flat = 0, int32_t fuzz = 0);
diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h
index ac616d0..dce5472 100644
--- a/services/inputflinger/tests/InterfaceMocks.h
+++ b/services/inputflinger/tests/InterfaceMocks.h
@@ -68,7 +68,7 @@
MOCK_METHOD(InputReaderPolicyInterface*, getPolicy, (), (override));
MOCK_METHOD(EventHubInterface*, getEventHub, (), (override));
- int32_t getNextId() override { return 1; };
+ int32_t getNextId() const override { return 1; };
MOCK_METHOD(void, updateLedMetaState, (int32_t metaState), (override));
MOCK_METHOD(int32_t, getLedMetaState, (), (override));
@@ -196,14 +196,14 @@
class MockInputDevice : public InputDevice {
public:
MockInputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- const InputDeviceIdentifier& identifier)
- : InputDevice(context, id, generation, identifier) {}
+ const InputDeviceIdentifier& identifier, bool isExternal)
+ : InputDevice(context, id, generation, identifier), mIsExternal(isExternal) {}
MOCK_METHOD(uint32_t, getSources, (), (const, override));
MOCK_METHOD(std::optional<DisplayViewport>, getAssociatedViewport, (), (const));
MOCK_METHOD(KeyboardType, getKeyboardType, (), (const, override));
MOCK_METHOD(bool, isEnabled, (), ());
- MOCK_METHOD(bool, isExternal, (), (override));
+ bool isExternal() override { return mIsExternal; }
MOCK_METHOD(void, dump, (std::string& dump, const std::string& eventHubDevStr), ());
MOCK_METHOD(void, addEmptyEventHubDevice, (int32_t eventHubId), ());
@@ -266,5 +266,6 @@
private:
int32_t mGeneration = 0;
+ const bool mIsExternal;
};
} // namespace android
diff --git a/services/inputflinger/tests/KeyboardInputMapper_test.cpp b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
index 1dd32c4..17acdd4 100644
--- a/services/inputflinger/tests/KeyboardInputMapper_test.cpp
+++ b/services/inputflinger/tests/KeyboardInputMapper_test.cpp
@@ -1085,10 +1085,9 @@
class KeyboardInputMapperTest_ExternalAlphabeticDevice : public KeyboardInputMapperUnitTest {
protected:
void SetUp() override {
- InputMapperUnitTest::SetUp();
+ InputMapperUnitTest::SetUp(/*bus=*/0, /*isExternal=*/true);
ON_CALL((*mDevice), getSources).WillByDefault(Return(AINPUT_SOURCE_KEYBOARD));
ON_CALL((*mDevice), getKeyboardType).WillByDefault(Return(KeyboardType::ALPHABETIC));
- ON_CALL((*mDevice), isExternal).WillByDefault(Return(true));
EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID))
.WillRepeatedly(Return(InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY |
InputDeviceClass::EXTERNAL));
@@ -1102,10 +1101,9 @@
class KeyboardInputMapperTest_ExternalNonAlphabeticDevice : public KeyboardInputMapperUnitTest {
protected:
void SetUp() override {
- InputMapperUnitTest::SetUp();
+ InputMapperUnitTest::SetUp(/*bus=*/0, /*isExternal=*/true);
ON_CALL((*mDevice), getSources).WillByDefault(Return(AINPUT_SOURCE_KEYBOARD));
ON_CALL((*mDevice), getKeyboardType).WillByDefault(Return(KeyboardType::NON_ALPHABETIC));
- ON_CALL((*mDevice), isExternal).WillByDefault(Return(true));
EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID))
.WillRepeatedly(Return(InputDeviceClass::KEYBOARD | InputDeviceClass::EXTERNAL));
mMapper = createInputMapper<KeyboardInputMapper>(*mDeviceContext, mReaderConfiguration,
diff --git a/services/inputflinger/tests/LatencyTracker_test.cpp b/services/inputflinger/tests/LatencyTracker_test.cpp
index ca0f1e8..1cfaaa8 100644
--- a/services/inputflinger/tests/LatencyTracker_test.cpp
+++ b/services/inputflinger/tests/LatencyTracker_test.cpp
@@ -57,6 +57,7 @@
}
const auto FIRST_TOUCH_POINTER = PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200);
+const auto FIRST_MOUSE_POINTER = PointerBuilder(/*id=*/1, ToolType::MOUSE);
/**
* This is a convenience method for comparing timelines that also prints the difference between
@@ -491,8 +492,13 @@
/*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS},
InputEventActionType::KEY);
- InputEventTimeline unknownTimeline(
+ InputEventTimeline motionScrollTimeline(
/*eventTime*/ 12, /*readTime*/ 13,
+ /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::MOUSE},
+ InputEventActionType::MOTION_ACTION_SCROLL);
+
+ InputEventTimeline unknownTimeline(
+ /*eventTime*/ 14, /*readTime*/ 15,
/*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
InputEventActionType::UNKNOWN_INPUT_EVENT);
@@ -529,8 +535,15 @@
.readTime(keyUpTimeline.readTime)
.deviceId(DEVICE_ID)
.build());
+ mTracker->trackListener(
+ MotionArgsBuilder(AMOTION_EVENT_ACTION_SCROLL, AINPUT_SOURCE_MOUSE, inputEventId + 5)
+ .eventTime(motionScrollTimeline.eventTime)
+ .readTime(motionScrollTimeline.readTime)
+ .deviceId(DEVICE_ID)
+ .pointer(FIRST_MOUSE_POINTER)
+ .build());
mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN,
- AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 5)
+ AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 6)
.eventTime(unknownTimeline.eventTime)
.readTime(unknownTimeline.readTime)
.deviceId(DEVICE_ID)
@@ -541,7 +554,8 @@
std::vector<InputEventTimeline> expectedTimelines = {motionDownTimeline, motionMoveTimeline,
motionUpTimeline, keyDownTimeline,
- keyUpTimeline, unknownTimeline};
+ keyUpTimeline, motionScrollTimeline,
+ unknownTimeline};
assertReceivedTimelines(expectedTimelines);
}
diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
index d15048d..0ea22d4 100644
--- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
+++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp
@@ -53,8 +53,9 @@
*/
class MultiTouchInputMapperUnitTest : public InputMapperUnitTest {
protected:
- void SetUp() override {
- InputMapperUnitTest::SetUp();
+ void SetUp() override { SetUp(/*bus=*/0, /*isExternal=*/false); }
+ void SetUp(int bus, bool isExternal) override {
+ InputMapperUnitTest::SetUp(bus, isExternal);
// Present scan codes
expectScanCodes(/*present=*/true,
diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
index 157bee3..548df22 100644
--- a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
+++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp
@@ -89,9 +89,9 @@
*/
class RotaryEncoderInputMapperTest : public InputMapperUnitTest {
protected:
- void SetUp() override { SetUpWithBus(BUS_USB); }
- void SetUpWithBus(int bus) override {
- InputMapperUnitTest::SetUpWithBus(bus);
+ void SetUp() override { SetUp(/*bus=*/0, /*isExternal=*/false); }
+ void SetUp(int bus, bool isExternal) override {
+ InputMapperUnitTest::SetUp(bus, isExternal);
EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL))
.WillRepeatedly(Return(true));
diff --git a/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
index abce931..31db2fe 100644
--- a/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputDispatcherFuzzer.cpp
@@ -48,9 +48,9 @@
auto [it, _] = mVerifiers.emplace(args.displayId, "Fuzz Verifier");
InputVerifier& verifier = it->second;
const Result<void> result =
- verifier.processMovement(args.deviceId, args.source, args.action, args.actionButton,
+ verifier.processMovement(args.deviceId, args.source, args.action,
args.getPointerCount(), args.pointerProperties.data(),
- args.pointerCoords.data(), args.flags, args.buttonState);
+ args.pointerCoords.data(), args.flags);
if (result.ok()) {
return args;
}
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index a1da39a..846260a 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -346,7 +346,7 @@
}
InputReaderPolicyInterface* getPolicy() override { return mPolicy.get(); }
EventHubInterface* getEventHub() override { return mEventHub.get(); }
- int32_t getNextId() override { return mFdp->ConsumeIntegral<int32_t>(); }
+ int32_t getNextId() const override { return mFdp->ConsumeIntegral<int32_t>(); }
void updateLedMetaState(int32_t metaState) override{};
int32_t getLedMetaState() override { return mFdp->ConsumeIntegral<int32_t>(); };
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 05f7d1b..ea7d6d7 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -26,15 +26,15 @@
cc_defaults {
name: "surfaceflinger_defaults",
cflags: [
+ "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
"-Wall",
+ "-Wconversion",
"-Werror",
"-Wextra",
"-Wformat",
"-Wthread-safety",
- "-Wunused",
"-Wunreachable-code",
- "-Wconversion",
- "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
+ "-Wunused",
],
}
@@ -43,39 +43,41 @@
defaults: [
"android.hardware.graphics.composer3-ndk_shared",
"librenderengine_deps",
- "libtimestats_deps",
"libsurfaceflinger_common_deps",
- "surfaceflinger_defaults",
"libsurfaceflinger_proto_deps",
+ "libtimestats_deps",
"poweradvisor_deps",
+ "surfaceflinger_defaults",
],
cflags: [
- "-DLOG_TAG=\"SurfaceFlinger\"",
- "-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DLOG_TAG=\"SurfaceFlinger\"",
],
shared_libs: [
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
"android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.2",
- "android.hardware.common-V2-ndk",
- "android.hardware.common.fmq-V1-ndk",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.4",
"android.os.flags-aconfig-cc-host",
+ "libEGL",
+ "libGLESv1_CM",
+ "libGLESv2",
+ "libSurfaceFlingerProp",
+ "libaconfig_storage_read_api_cc",
"libbase",
"libbinder",
"libbinder_ndk",
"libcutils",
- "libEGL",
"libfmq",
- "libGLESv1_CM",
- "libGLESv2",
"libgui",
"libhidlbase",
"liblog",
@@ -86,8 +88,6 @@
"libsync",
"libui",
"libutils",
- "libSurfaceFlingerProp",
- "libaconfig_storage_read_api_cc",
],
static_libs: [
"iinputflinger_aidl_lib_static",
@@ -105,11 +105,11 @@
"libtonemap",
],
header_libs: [
+ "android.hardware.graphics.composer3-command-buffer",
"android.hardware.graphics.composer@2.1-command-buffer",
"android.hardware.graphics.composer@2.2-command-buffer",
"android.hardware.graphics.composer@2.3-command-buffer",
"android.hardware.graphics.composer@2.4-command-buffer",
- "android.hardware.graphics.composer3-command-buffer",
],
export_static_lib_headers: [
"libcompositionengine",
@@ -125,8 +125,8 @@
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.4",
- "libpowermanager",
"libhidlbase",
+ "libpowermanager",
],
// TODO (marissaw): this library is not used by surfaceflinger. This is here so
// the library compiled in a way that is accessible to system partition when running
@@ -177,7 +177,6 @@
filegroup {
name: "libsurfaceflinger_backend_sources",
srcs: [
- "PowerAdvisor/*.cpp",
"DisplayHardware/AidlComposerHal.cpp",
"DisplayHardware/ComposerHal.cpp",
"DisplayHardware/FramebufferSurface.cpp",
@@ -185,6 +184,7 @@
"DisplayHardware/HWComposer.cpp",
"DisplayHardware/HidlComposerHal.cpp",
"DisplayHardware/VirtualDisplaySurface.cpp",
+ "PowerAdvisor/*.cpp",
],
}
@@ -208,21 +208,20 @@
"DisplayDevice.cpp",
"DisplayRenderArea.cpp",
"Effects/Daltonizer.cpp",
- "FrontEnd/LayerCreationArgs.cpp",
- "FrontEnd/LayerHandle.cpp",
- "FrontEnd/LayerSnapshot.cpp",
- "FrontEnd/LayerSnapshotBuilder.cpp",
- "FrontEnd/LayerHierarchy.cpp",
- "FrontEnd/LayerLifecycleManager.cpp",
- "FrontEnd/RequestedLayerState.cpp",
- "FrontEnd/TransactionHandler.cpp",
"FpsReporter.cpp",
"FrameTracer/FrameTracer.cpp",
"FrameTracker.cpp",
+ "FrontEnd/LayerCreationArgs.cpp",
+ "FrontEnd/LayerHandle.cpp",
+ "FrontEnd/LayerHierarchy.cpp",
+ "FrontEnd/LayerLifecycleManager.cpp",
+ "FrontEnd/LayerSnapshot.cpp",
+ "FrontEnd/LayerSnapshotBuilder.cpp",
+ "FrontEnd/RequestedLayerState.cpp",
+ "FrontEnd/TransactionHandler.cpp",
"HdrLayerInfoReporter.cpp",
"HdrSdrRatioOverlay.cpp",
"Jank/JankTracker.cpp",
- "WindowInfosListenerInvoker.cpp",
"Layer.cpp",
"LayerFE.cpp",
"LayerProtoHelper.cpp",
@@ -234,10 +233,10 @@
"RenderArea.cpp",
"Scheduler/EventThread.cpp",
"Scheduler/FrameRateOverrideMappings.cpp",
- "Scheduler/OneShotTimer.cpp",
"Scheduler/LayerHistory.cpp",
"Scheduler/LayerInfo.cpp",
"Scheduler/MessageQueue.cpp",
+ "Scheduler/OneShotTimer.cpp",
"Scheduler/RefreshRateSelector.cpp",
"Scheduler/Scheduler.cpp",
"Scheduler/SmallAreaDetectionAllowMappings.cpp",
@@ -253,19 +252,20 @@
"Tracing/LayerDataSource.cpp",
"Tracing/LayerTracing.cpp",
"Tracing/TransactionDataSource.cpp",
- "Tracing/TransactionTracing.cpp",
"Tracing/TransactionProtoParser.cpp",
+ "Tracing/TransactionTracing.cpp",
"Tracing/tools/LayerTraceGenerator.cpp",
"TransactionCallbackInvoker.cpp",
"TunnelModeEnabledReporter.cpp",
+ "WindowInfosListenerInvoker.cpp",
],
}
cc_defaults {
name: "libsurfaceflinger_binary",
defaults: [
- "surfaceflinger_defaults",
"libsurfaceflinger_production_defaults",
+ "surfaceflinger_defaults",
],
cflags: [
"-DLOG_TAG=\"SurfaceFlinger\"",
@@ -331,9 +331,9 @@
"android.hardware.configstore@1.1",
"android.hardware.graphics.common@1.2",
"libhidlbase",
+ "liblog",
"libui",
"libutils",
- "liblog",
],
static_libs: [
"libSurfaceFlingerProperties",
@@ -354,10 +354,10 @@
generated_headers: ["statslog_surfaceflinger.h"],
export_generated_headers: ["statslog_surfaceflinger.h"],
shared_libs: [
+ "android.os.statsbootstrap_aidl-cpp",
"libbinder",
"libstatsbootstrap",
"libutils",
- "android.os.statsbootstrap_aidl-cpp",
],
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7f94428..c47943f 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -138,13 +138,13 @@
}
std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId hwcDisplayId,
- hal::Connection connection) {
- switch (connection) {
- case hal::Connection::CONNECTED:
+ HotplugEvent event) {
+ switch (event) {
+ case HotplugEvent::Connected:
return onHotplugConnect(hwcDisplayId);
- case hal::Connection::DISCONNECTED:
+ case HotplugEvent::Disconnected:
return onHotplugDisconnect(hwcDisplayId);
- case hal::Connection::INVALID:
+ case HotplugEvent::LinkUnstable:
return {};
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b1b997a..d60f6ff 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -231,11 +231,12 @@
// Events handling ---------------------------------------------------------
- // Returns stable display ID (and display name on connection of new or previously disconnected
- // display), or std::nullopt if hotplug event was ignored.
+ enum class HotplugEvent { Connected, Disconnected, LinkUnstable };
+
+ // Returns the stable display ID of the display for which the hotplug event was received, or
+ // std::nullopt if hotplug event was ignored.
// This function is called from SurfaceFlinger.
- virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId,
- hal::Connection) = 0;
+ virtual std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, HotplugEvent) = 0;
// If true we'll update the DeviceProductInfo on subsequent hotplug connected events.
// TODO(b/157555476): Remove when the framework has proper support for headless mode
@@ -435,9 +436,7 @@
// Events handling ---------------------------------------------------------
- // Returns PhysicalDisplayId (and display name on connection of new or previously disconnected
- // display), or std::nullopt if hotplug event was ignored.
- std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, hal::Connection) override;
+ std::optional<DisplayIdentificationInfo> onHotplug(hal::HWDisplayId, HotplugEvent) override;
bool updatesDeviceProductInfoOnHotplugReconnect() const override;
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 86d7388..fece312 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -611,7 +611,11 @@
mFrameReadyMetadata = FrameReadyMetadata::OnTimeFinish;
}
- if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
+ const nsecs_t presentThreshold =
+ FlagManager::getInstance().increase_missed_frame_jank_threshold()
+ ? mJankClassificationThresholds.presentThresholdExtended
+ : mJankClassificationThresholds.presentThresholdLegacy;
+ if (std::abs(presentDelta) > presentThreshold) {
mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
: FramePresentMetadata::EarlyPresent;
// Jank that is missing by less than the render rate period is classified as partial jank,
@@ -629,9 +633,8 @@
} else if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present early
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= refreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= refreshRate.getPeriodNsecs() - presentThreshold) {
// Delta factor of vsync
mJankType = JankType::SurfaceFlingerScheduling;
} else {
@@ -667,9 +670,8 @@
if (!(mJankType & JankType::BufferStuffing)) {
// In a stuffed state, if the app finishes on time and there is no display frame
// jank, only buffer stuffing is the root cause of the jank.
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= refreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= refreshRate.getPeriodNsecs() - presentThreshold) {
// Delta factor of vsync
mJankType |= JankType::SurfaceFlingerScheduling;
} else {
@@ -1091,7 +1093,11 @@
? std::abs(presentDelta) % mRefreshRate.getPeriodNsecs()
: 0;
- if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
+ nsecs_t presentThreshold = FlagManager::getInstance().increase_missed_frame_jank_threshold()
+ ? mJankClassificationThresholds.presentThresholdExtended
+ : mJankClassificationThresholds.presentThresholdLegacy;
+
+ if (std::abs(presentDelta) > presentThreshold) {
mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
: FramePresentMetadata::EarlyPresent;
// Jank that is missing by less than the render rate period is classified as partial jank,
@@ -1122,9 +1128,8 @@
if (mFramePresentMetadata == FramePresentMetadata::EarlyPresent) {
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present early
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold)) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= (mRefreshRate.getPeriodNsecs() - presentThreshold)) {
// Delta is a factor of vsync if its within the presentTheshold on either side
// of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
// of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
@@ -1142,7 +1147,7 @@
}
} else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
- mJankClassificationThresholds.presentThreshold ||
+ presentThreshold ||
previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
// The previous frame was either presented in the current frame's expected vsync or
// it was presented even later than the current frame's expected vsync.
@@ -1151,9 +1156,8 @@
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
!(mJankType & JankType::SurfaceFlingerStuffing)) {
// Finish on time, Present late
- if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
- mJankClassificationThresholds.presentThreshold)) {
+ if (deltaToVsync < presentThreshold ||
+ deltaToVsync >= (mRefreshRate.getPeriodNsecs() - presentThreshold)) {
// Delta is a factor of vsync if its within the presentTheshold on either side
// of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
// of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
@@ -1165,8 +1169,7 @@
} else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
mSurfaceFlingerActuals.presentTime - previousPresentTime >
- mRefreshRate.getPeriodNsecs() +
- mJankClassificationThresholds.presentThreshold) {
+ mRefreshRate.getPeriodNsecs() + presentThreshold) {
// Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
// was presented more than a vsync late.
if (mGpuFence != FenceTime::NO_FENCE) {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index a47bd57..9fedb57 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -107,7 +107,10 @@
struct JankClassificationThresholds {
// The various thresholds for App and SF. If the actual timestamp falls within the threshold
// compared to prediction, we treat it as on time.
- nsecs_t presentThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
+ nsecs_t presentThresholdLegacy =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
+ nsecs_t presentThresholdExtended =
+ std::chrono::duration_cast<std::chrono::nanoseconds>(4ms).count();
nsecs_t deadlineThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(0ms).count();
nsecs_t startThreshold = std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
};
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 9119247..86ef6ca 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -1178,7 +1178,7 @@
auto displayInfo = displayInfoOpt.value_or(sDefaultInfo);
if (!requested.hasInputInfo()) {
- snapshot.inputInfo.inputConfig = InputConfig::NO_INPUT_CHANNEL;
+ snapshot.inputInfo.inputConfig |= InputConfig::NO_INPUT_CHANNEL;
}
fillInputFrameInfo(snapshot.inputInfo, displayInfo.transform, snapshot);
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 591ebb2..1d53e71 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -573,7 +573,7 @@
return false;
}
- if ((sidebandStream != nullptr) || (externalTexture != nullptr)) {
+ if (hasBufferOrSidebandStream() || fillsColor()) {
return true;
}
@@ -586,6 +586,15 @@
windowInfo->inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
}
+bool RequestedLayerState::hasBufferOrSidebandStream() const {
+ return ((sidebandStream != nullptr) || (externalTexture != nullptr));
+}
+
+bool RequestedLayerState::fillsColor() const {
+ return !hasBufferOrSidebandStream() && color.r >= 0.0_hf && color.g >= 0.0_hf &&
+ color.b >= 0.0_hf;
+}
+
bool RequestedLayerState::hasBlur() const {
return backgroundBlurRadius > 0 || blurRegions.size() > 0;
}
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index dd861a7..7232379 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -88,6 +88,8 @@
bool hasValidRelativeParent() const;
bool hasInputInfo() const;
bool needsInputInfo() const;
+ bool hasBufferOrSidebandStream() const;
+ bool fillsColor() const;
bool hasBlur() const;
bool hasFrameUpdate() const;
bool hasReadyFrame() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1038b9f..e1c5383 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -135,7 +135,6 @@
#include "DisplayDevice.h"
#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/FramebufferSurface.h"
-#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#include "DisplayRenderArea.h"
@@ -2292,12 +2291,12 @@
void SurfaceFlinger::onComposerHalHotplugEvent(hal::HWDisplayId hwcDisplayId,
DisplayHotplugEvent event) {
if (event == DisplayHotplugEvent::CONNECTED || event == DisplayHotplugEvent::DISCONNECTED) {
- hal::Connection connection = (event == DisplayHotplugEvent::CONNECTED)
- ? hal::Connection::CONNECTED
- : hal::Connection::DISCONNECTED;
+ const HWComposer::HotplugEvent hotplugEvent = event == DisplayHotplugEvent::CONNECTED
+ ? HWComposer::HotplugEvent::Connected
+ : HWComposer::HotplugEvent::Disconnected;
{
std::lock_guard<std::mutex> lock(mHotplugMutex);
- mPendingHotplugEvents.push_back(HotplugEvent{hwcDisplayId, connection});
+ mPendingHotplugEvents.push_back(HotplugEvent{hwcDisplayId, hotplugEvent});
}
if (mScheduler) {
@@ -3658,13 +3657,13 @@
events = std::move(mPendingHotplugEvents);
}
- for (const auto [hwcDisplayId, connection] : events) {
- if (auto info = getHwComposer().onHotplug(hwcDisplayId, connection)) {
+ for (const auto [hwcDisplayId, event] : events) {
+ if (auto info = getHwComposer().onHotplug(hwcDisplayId, event)) {
const auto displayId = info->id;
const ftl::Concat displayString("display ", displayId.value, "(HAL ID ", hwcDisplayId,
')');
- if (connection == hal::Connection::CONNECTED) {
+ if (event == HWComposer::HotplugEvent::Connected) {
const auto activeModeIdOpt =
processHotplugConnect(displayId, hwcDisplayId, std::move(*info),
displayString.c_str());
@@ -3975,9 +3974,6 @@
displaySurface, producer);
if (mScheduler && !display->isVirtual()) {
- // TODO(b/241285876): Annotate `processDisplayAdded` instead.
- ftl::FakeGuard guard(kMainThreadContext);
-
// For hotplug reconnect, renew the registration since display modes have been reloaded.
mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(),
mActiveDisplayId);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 158bf57..a99b39a 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -75,6 +75,7 @@
#include "Display/VirtualDisplaySnapshot.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWC2.h"
+#include "DisplayHardware/HWComposer.h"
#include "DisplayIdGenerator.h"
#include "Effects/Daltonizer.h"
#include "FrontEnd/DisplayInfo.h"
@@ -126,7 +127,6 @@
class FpsReporter;
class TunnelModeEnabledReporter;
class HdrLayerInfoReporter;
-class HWComposer;
class IGraphicBufferProducer;
class Layer;
class MessageBase;
@@ -350,9 +350,6 @@
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
- virtual void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
- REQUIRES(mStateLock);
-
virtual std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
BufferData& bufferData, const char* layerName, uint64_t transactionId);
@@ -1042,6 +1039,8 @@
const sp<compositionengine::DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer) REQUIRES(mStateLock);
void processDisplayChangesLocked() REQUIRES(mStateLock, kMainThreadContext);
+ void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
+ REQUIRES(mStateLock, kMainThreadContext);
void processDisplayRemoved(const wp<IBinder>& displayToken)
REQUIRES(mStateLock, kMainThreadContext);
void processDisplayChanged(const wp<IBinder>& displayToken,
@@ -1279,7 +1278,7 @@
struct HotplugEvent {
hal::HWDisplayId hwcDisplayId;
- hal::Connection connection = hal::Connection::INVALID;
+ HWComposer::HotplugEvent event;
};
bool mIsHdcpViaNegVsync = false;
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 15df152..b1552e6 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -126,6 +126,7 @@
DUMP_ACONFIG_FLAG(adpf_native_session_manager);
DUMP_ACONFIG_FLAG(adpf_use_fmq_channel);
DUMP_ACONFIG_FLAG(graphite_renderengine_preview_rollout);
+ DUMP_ACONFIG_FLAG(increase_missed_frame_jank_threshold);
DUMP_ACONFIG_FLAG(refresh_rate_overlay_on_external_display);
/// Trunk stable readonly flags ///
@@ -300,6 +301,7 @@
FLAG_MANAGER_ACONFIG_FLAG(adpf_gpu_sf, "")
FLAG_MANAGER_ACONFIG_FLAG(adpf_native_session_manager, "");
FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine_preview_rollout, "");
+FLAG_MANAGER_ACONFIG_FLAG(increase_missed_frame_jank_threshold, "");
/// Trunk stable server (R/W) flags from outside SurfaceFlinger ///
FLAG_MANAGER_ACONFIG_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os)
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 147e79e..073302e 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -61,6 +61,7 @@
bool adpf_use_fmq_channel() const;
bool adpf_use_fmq_channel_fixed() const;
bool graphite_renderengine_preview_rollout() const;
+ bool increase_missed_frame_jank_threshold() const;
bool refresh_rate_overlay_on_external_display() const;
/// Trunk stable readonly flags ///
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index b28d269..96ab7ab 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -190,6 +190,13 @@
} # graphite_renderengine_preview_rollout
flag {
+ name: "increase_missed_frame_jank_threshold"
+ namespace: "core_graphics"
+ description: "Increase the jank threshold to 4 milliseconds"
+ bug: "342265411"
+} # increase_missed_frame_jank_threshold
+
+flag {
name: "latch_unsignaled_with_auto_refresh_changed"
namespace: "core_graphics"
description: "Ignore eAutoRefreshChanged with latch unsignaled"
diff --git a/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp b/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp
index c6cbe52..84dc5fc 100644
--- a/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayModeControllerTest.cpp
@@ -67,7 +67,8 @@
setVsyncEnabled(kHwcDisplayId, hal::IComposerClient::Vsync::DISABLE));
EXPECT_CALL(*mComposerHal, onHotplugConnect(kHwcDisplayId));
- const auto infoOpt = mComposer->onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto infoOpt =
+ mComposer->onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(infoOpt);
mDisplayId = infoOpt->id;
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 6e231aa..3fead93 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -360,9 +360,10 @@
// The HWC active configuration id
static constexpr hal::HWConfigId HWC_ACTIVE_CONFIG_ID = 2001;
- static void injectPendingHotplugEvent(DisplayTransactionTest* test, Connection connection) {
+ static void injectPendingHotplugEvent(DisplayTransactionTest* test,
+ HWComposer::HotplugEvent event) {
test->mFlinger.mutablePendingHotplugEvents().emplace_back(
- TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, connection});
+ TestableSurfaceFlinger::HotplugEvent{HWC_DISPLAY_ID, event});
}
// Called by tests to inject a HWC display setup
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 08e4265..54f2259 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -202,10 +202,12 @@
uint32_t* maxDisplayFrames;
size_t maxTokens;
static constexpr pid_t kSurfaceFlingerPid = 666;
- static constexpr nsecs_t kPresentThreshold = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kPresentThresholdLegacy = std::chrono::nanoseconds(2ns).count();
+ static constexpr nsecs_t kPresentThresholdExtended = std::chrono::nanoseconds(4ns).count();
static constexpr nsecs_t kDeadlineThreshold = std::chrono::nanoseconds(0ns).count();
static constexpr nsecs_t kStartThreshold = std::chrono::nanoseconds(2ns).count();
- static constexpr JankClassificationThresholds kTestThresholds{kPresentThreshold,
+ static constexpr JankClassificationThresholds kTestThresholds{kPresentThresholdLegacy,
+ kPresentThresholdExtended,
kDeadlineThreshold,
kStartThreshold};
};
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index ba2d3e2..b34de1a 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -94,7 +94,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 1;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
ASSERT_FALSE(mHwc.isHeadless());
@@ -111,7 +111,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 1;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
EXPECT_CALL(*mHal, getDisplayConnectionType(kHwcDisplayId, _))
@@ -133,7 +133,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 2;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
{
@@ -164,7 +164,7 @@
constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20Fps
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
ASSERT_TRUE(info->preferredDetailedTimingDescriptor.has_value());
@@ -266,7 +266,7 @@
constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20Fps
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
EXPECT_CALL(*mHal, isVrrSupported()).WillRepeatedly(Return(false));
@@ -364,7 +364,7 @@
constexpr hal::HWConfigId kConfigId = 42;
constexpr int32_t kMaxFrameIntervalNs = 50000000; // 20Fps
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
EXPECT_CALL(*mHal, isVrrSupported()).WillRepeatedly(Return(true));
@@ -452,7 +452,7 @@
constexpr hal::HWDisplayId kHwcDisplayId = 1;
expectHotplugConnect(kHwcDisplayId);
- const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
+ const auto info = mHwc.onHotplug(kHwcDisplayId, HWComposer::HotplugEvent::Connected);
ASSERT_TRUE(info);
const auto physicalDisplayId = info->id;
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index 976cecb..35ec536 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -619,14 +619,32 @@
}
}
-TEST_F(LayerLifecycleManagerTest, testInputInfoOfRequestedLayerState) {
- // By default the layer has no buffer, so it doesn't need an input info
- EXPECT_FALSE(getRequestedLayerState(mLifecycleManager, 111)->needsInputInfo());
-
- setBuffer(111);
+TEST_F(LayerLifecycleManagerTest, layerWithBufferNeedsInputInfo) {
+ // If a layer has no buffer or no color, it doesn't have an input info
+ LayerHierarchyTestBase::createRootLayer(3);
+ setColor(3, {-1._hf, -1._hf, -1._hf});
mLifecycleManager.commitChanges();
- EXPECT_TRUE(getRequestedLayerState(mLifecycleManager, 111)->needsInputInfo());
+ EXPECT_FALSE(getRequestedLayerState(mLifecycleManager, 3)->needsInputInfo());
+
+ setBuffer(3);
+ mLifecycleManager.commitChanges();
+
+ EXPECT_TRUE(getRequestedLayerState(mLifecycleManager, 3)->needsInputInfo());
+}
+
+TEST_F(LayerLifecycleManagerTest, layerWithColorNeedsInputInfo) {
+ // If a layer has no buffer or no color, it doesn't have an input info
+ LayerHierarchyTestBase::createRootLayer(4);
+ setColor(4, {-1._hf, -1._hf, -1._hf});
+ mLifecycleManager.commitChanges();
+
+ EXPECT_FALSE(getRequestedLayerState(mLifecycleManager, 4)->needsInputInfo());
+
+ setColor(4, {1._hf, 0._hf, 0._hf});
+ mLifecycleManager.commitChanges();
+
+ EXPECT_TRUE(getRequestedLayerState(mLifecycleManager, 4)->needsInputInfo());
}
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index ab8c733..453c053 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -2045,17 +2045,17 @@
}
TEST_F(LayerSnapshotTest, shouldUpdateInputWhenNoInputInfo) {
- // By default the layer has no buffer, so we don't expect it to have an input info
+ // If a layer has no buffer or no color, it doesn't have an input info
+ setColor(111, {-1._hf, -1._hf, -1._hf});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 12, 121, 122, 1221, 13, 2});
EXPECT_FALSE(getSnapshot(111)->hasInputInfo());
setBuffer(111);
-
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
EXPECT_TRUE(getSnapshot(111)->hasInputInfo());
EXPECT_TRUE(getSnapshot(111)->inputInfo.inputConfig.test(
gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL));
- EXPECT_FALSE(getSnapshot(2)->hasInputInfo());
}
// content dirty test
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
index 9bf344c..1335640 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
@@ -163,7 +163,7 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// --------------------------------------------------------------------
// Call Expectations
@@ -197,7 +197,7 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// --------------------------------------------------------------------
// Invocation
@@ -219,7 +219,7 @@
setupCommonPreconditions<Case>();
// A hotplug disconnect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
// The display is already completely set up.
Case::Display::injectHwcDisplay(this);
@@ -327,9 +327,10 @@
setupCommonPreconditions<Case>();
// A hotplug connect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// A hotplug disconnect event is also enqueued for the same display
- Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ Case::Display::injectPendingHotplugEvent(this,
+ HWComposer::HotplugEvent::Disconnected);
// --------------------------------------------------------------------
// Call Expectations
@@ -378,9 +379,10 @@
existing.inject();
// A hotplug disconnect event is enqueued for a display
- Case::Display::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ Case::Display::injectPendingHotplugEvent(this,
+ HWComposer::HotplugEvent::Disconnected);
// A hotplug connect event is also enqueued for the same display
- Case::Display::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ Case::Display::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// --------------------------------------------------------------------
// Call Expectations
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
index 4e7a174..2d986c6 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
@@ -41,9 +41,9 @@
const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
ASSERT_EQ(2u, pendingEvents.size());
EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
- EXPECT_EQ(Connection::CONNECTED, pendingEvents[0].connection);
+ EXPECT_EQ(HWComposer::HotplugEvent::Connected, pendingEvents[0].event);
EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
- EXPECT_EQ(Connection::DISCONNECTED, pendingEvents[1].connection);
+ EXPECT_EQ(HWComposer::HotplugEvent::Disconnected, pendingEvents[1].event);
}
TEST_F(HotplugTest, schedulesFrameToCommitDisplayTransaction) {
@@ -64,7 +64,7 @@
using PrimaryDisplay = InnerDisplayVariant;
PrimaryDisplay::setupHwcHotplugCallExpectations(this);
PrimaryDisplay::setupHwcGetActiveConfigCallExpectations(this);
- PrimaryDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ PrimaryDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// TODO(b/241286146): Remove this unnecessary call.
EXPECT_CALL(*mComposer,
@@ -80,7 +80,7 @@
using ExternalDisplay = ExternalDisplayWithIdentificationVariant;
ExternalDisplay::setupHwcHotplugCallExpectations(this);
ExternalDisplay::setupHwcGetActiveConfigCallExpectations(this);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// TODO(b/241286146): Remove this unnecessary call.
EXPECT_CALL(*mComposer,
@@ -123,7 +123,7 @@
using PrimaryDisplay = PrimaryDisplayVariant;
PrimaryDisplay::setupHwcHotplugCallExpectations(this);
PrimaryDisplay::setupHwcGetActiveConfigCallExpectations(this);
- PrimaryDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ PrimaryDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// TODO(b/241286146): Remove this unnecessary call.
EXPECT_CALL(*mComposer,
@@ -139,7 +139,7 @@
using ExternalDisplay = ExternalDisplayWithIdentificationVariant;
ExternalDisplay::setupHwcHotplugCallExpectations(this);
ExternalDisplay::setupHwcGetActiveConfigCallExpectations(this);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
// TODO(b/241286146): Remove this unnecessary call.
EXPECT_CALL(*mComposer,
@@ -206,15 +206,15 @@
// A single commit should be scheduled for both configure calls.
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
mFlinger.configure();
EXPECT_TRUE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
// Disconnecting a display that was already disconnected should be a no-op.
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
mFlinger.configure();
// The display should be scheduled for removal during the next commit. At this point, it should
@@ -249,14 +249,14 @@
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1);
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Connected);
mFlinger.configure();
// The hotplug should be rejected, so no HWComposer::DisplayData should be created.
EXPECT_FALSE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
// Disconnecting a display that does not exist should be a no-op.
- ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
+ ExternalDisplay::injectPendingHotplugEvent(this, HWComposer::HotplugEvent::Disconnected);
mFlinger.configure();
EXPECT_FALSE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h
index 7bd85cd..3fa4093 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWComposer.h
@@ -81,7 +81,7 @@
(PhysicalDisplayId, float, float, const Hwc2::Composer::DisplayBrightnessOptions&),
(override));
MOCK_METHOD(std::optional<DisplayIdentificationInfo>, onHotplug,
- (hal::HWDisplayId, hal::Connection), (override));
+ (hal::HWDisplayId, HWComposer::HotplugEvent), (override));
MOCK_METHOD(bool, updatesDeviceProductInfoOnHotplugReconnect, (), (const, override));
MOCK_METHOD(std::optional<PhysicalDisplayId>, onVsync, (hal::HWDisplayId, int64_t));
MOCK_METHOD(void, setVsyncEnabled, (PhysicalDisplayId, hal::Vsync), (override));