Merge "[native] Use newer GrDirectContexts::MakeGL" into main
diff --git a/include/input/InputVerifier.h b/include/input/InputVerifier.h
index b857482..14dd463 100644
--- a/include/input/InputVerifier.h
+++ b/include/input/InputVerifier.h
@@ -46,7 +46,7 @@
public:
InputVerifier(const std::string& name);
- android::base::Result<void> processMovement(int32_t deviceId, int32_t action,
+ android::base::Result<void> processMovement(int32_t deviceId, int32_t source, int32_t action,
uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, int32_t flags);
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 9a27d23..f17a654 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -200,6 +200,7 @@
cc_aconfig_library {
name: "libguiflags",
+ host_supported: true,
vendor_available: true,
aconfig_declarations: "libgui_flags",
}
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 36a01d3..ab4af1a 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -90,6 +90,28 @@
"--allowlist-var=AMOTION_EVENT_ACTION_DOWN",
"--allowlist-var=AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT",
"--allowlist-var=MAX_POINTER_ID",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NONE",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_BUTTON",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POINTER",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_POSITION",
+ "--allowlist-var=AINPUT_SOURCE_CLASS_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_UNKNOWN",
+ "--allowlist-var=AINPUT_SOURCE_KEYBOARD",
+ "--allowlist-var=AINPUT_SOURCE_DPAD",
+ "--allowlist-var=AINPUT_SOURCE_GAMEPAD",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHSCREEN",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE",
+ "--allowlist-var=AINPUT_SOURCE_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_BLUETOOTH_STYLUS",
+ "--allowlist-var=AINPUT_SOURCE_TRACKBALL",
+ "--allowlist-var=AINPUT_SOURCE_MOUSE_RELATIVE",
+ "--allowlist-var=AINPUT_SOURCE_TOUCHPAD",
+ "--allowlist-var=AINPUT_SOURCE_TOUCH_NAVIGATION",
+ "--allowlist-var=AINPUT_SOURCE_JOYSTICK",
+ "--allowlist-var=AINPUT_SOURCE_HDMI",
+ "--allowlist-var=AINPUT_SOURCE_SENSOR",
+ "--allowlist-var=AINPUT_SOURCE_ROTARY_ENCODER",
],
static_libs: [
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 1600013..30cedb0 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -632,8 +632,8 @@
MotionEvent::actionToString(action).c_str()));
if (verifyEvents()) {
Result<void> result =
- mInputVerifier.processMovement(deviceId, action, pointerCount, pointerProperties,
- pointerCoords, flags);
+ mInputVerifier.processMovement(deviceId, source, action, pointerCount,
+ pointerProperties, pointerCoords, flags);
if (!result.ok()) {
LOG(FATAL) << "Bad stream: " << result.error();
}
@@ -1276,13 +1276,13 @@
PointerCoords& resampledCoords = touchState.lastResample.pointers[i];
const PointerCoords& currentCoords = current->getPointerById(id);
resampledCoords = currentCoords;
+ resampledCoords.isResampled = true;
if (other->idBits.hasBit(id) && shouldResampleTool(event->getToolType(i))) {
const PointerCoords& otherCoords = other->getPointerById(id);
resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_X,
lerp(currentCoords.getX(), otherCoords.getX(), alpha));
resampledCoords.setAxisValue(AMOTION_EVENT_AXIS_Y,
lerp(currentCoords.getY(), otherCoords.getY(), alpha));
- resampledCoords.isResampled = true;
ALOGD_IF(debugResampling(),
"[%d] - out (%0.3f, %0.3f), cur (%0.3f, %0.3f), "
"other (%0.3f, %0.3f), alpha %0.3f",
diff --git a/libs/input/InputVerifier.cpp b/libs/input/InputVerifier.cpp
index 6c602e0..cec2445 100644
--- a/libs/input/InputVerifier.cpp
+++ b/libs/input/InputVerifier.cpp
@@ -33,7 +33,7 @@
InputVerifier::InputVerifier(const std::string& name)
: mVerifier(android::input::verifier::create(rust::String::lossy(name))){};
-Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t action,
+Result<void> InputVerifier::processMovement(DeviceId deviceId, int32_t source, int32_t action,
uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, int32_t flags) {
@@ -43,8 +43,8 @@
}
rust::Slice<const RustPointerProperties> properties{rpp.data(), rpp.size()};
rust::String errorMessage =
- android::input::verifier::process_movement(*mVerifier, deviceId, action, properties,
- static_cast<uint32_t>(flags));
+ android::input::verifier::process_movement(*mVerifier, deviceId, source, action,
+ properties, static_cast<uint32_t>(flags));
if (errorMessage.empty()) {
return {};
} else {
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index a0563f9..e8575a6 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -27,3 +27,10 @@
description: "Set to true to enable timer support for the touchpad Gestures library"
bug: "297192727"
}
+
+flag {
+ name: "enable_multi_device_input"
+ namespace: "input"
+ description: "Set to true to enable multi-device input: touch and stylus can be active at the same time, but in different windows"
+ bug: "211379801"
+}
diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs
index 9d3b386..9725b00 100644
--- a/libs/input/rust/input.rs
+++ b/libs/input/rust/input.rs
@@ -23,6 +23,54 @@
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct DeviceId(pub i32);
+#[repr(u32)]
+pub enum SourceClass {
+ None = input_bindgen::AINPUT_SOURCE_CLASS_NONE,
+ Button = input_bindgen::AINPUT_SOURCE_CLASS_BUTTON,
+ Pointer = input_bindgen::AINPUT_SOURCE_CLASS_POINTER,
+ Navigation = input_bindgen::AINPUT_SOURCE_CLASS_NAVIGATION,
+ Position = input_bindgen::AINPUT_SOURCE_CLASS_POSITION,
+ Joystick = input_bindgen::AINPUT_SOURCE_CLASS_JOYSTICK,
+}
+
+bitflags! {
+ /// Source of the input device or input events.
+ pub struct Source: u32 {
+ /// SOURCE_UNKNOWN
+ const Unknown = input_bindgen::AINPUT_SOURCE_UNKNOWN;
+ /// SOURCE_KEYBOARD
+ const Keyboard = input_bindgen::AINPUT_SOURCE_KEYBOARD;
+ /// SOURCE_DPAD
+ const Dpad = input_bindgen::AINPUT_SOURCE_DPAD;
+ /// SOURCE_GAMEPAD
+ const Gamepad = input_bindgen::AINPUT_SOURCE_GAMEPAD;
+ /// SOURCE_TOUCHSCREEN
+ const Touchscreen = input_bindgen::AINPUT_SOURCE_TOUCHSCREEN;
+ /// SOURCE_MOUSE
+ const Mouse = input_bindgen::AINPUT_SOURCE_MOUSE;
+ /// SOURCE_STYLUS
+ const Stylus = input_bindgen::AINPUT_SOURCE_STYLUS;
+ /// SOURCE_BLUETOOTH_STYLUS
+ const BluetoothStylus = input_bindgen::AINPUT_SOURCE_BLUETOOTH_STYLUS;
+ /// SOURCE_TRACKBALL
+ const Trackball = input_bindgen::AINPUT_SOURCE_TRACKBALL;
+ /// SOURCE_MOUSE_RELATIVE
+ const MouseRelative = input_bindgen::AINPUT_SOURCE_MOUSE_RELATIVE;
+ /// SOURCE_TOUCHPAD
+ const Touchpad = input_bindgen::AINPUT_SOURCE_TOUCHPAD;
+ /// SOURCE_TOUCH_NAVIGATION
+ const TouchNavigation = input_bindgen::AINPUT_SOURCE_TOUCH_NAVIGATION;
+ /// SOURCE_JOYSTICK
+ const Joystick = input_bindgen::AINPUT_SOURCE_JOYSTICK;
+ /// SOURCE_HDMI
+ const HDMI = input_bindgen::AINPUT_SOURCE_HDMI;
+ /// SOURCE_SENSOR
+ const Sensor = input_bindgen::AINPUT_SOURCE_SENSOR;
+ /// SOURCE_ROTARY_ENCODER
+ const RotaryEncoder = input_bindgen::AINPUT_SOURCE_ROTARY_ENCODER;
+ }
+}
+
/// A rust enum representation of a MotionEvent action.
#[repr(u32)]
pub enum MotionAction {
@@ -134,3 +182,11 @@
const NO_FOCUS_CHANGE = input_bindgen::AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE;
}
}
+
+impl Source {
+ /// Return true if this source is from the provided class
+ pub fn is_from_class(&self, source_class: SourceClass) -> bool {
+ let class_bits = source_class as u32;
+ self.bits() & class_bits == class_bits
+ }
+}
diff --git a/libs/input/rust/input_verifier.rs b/libs/input/rust/input_verifier.rs
index 64c0466..2d94e70 100644
--- a/libs/input/rust/input_verifier.rs
+++ b/libs/input/rust/input_verifier.rs
@@ -17,7 +17,7 @@
//! Contains the InputVerifier, used to validate a stream of input events.
use crate::ffi::RustPointerProperties;
-use crate::input::{DeviceId, MotionAction, MotionFlags};
+use crate::input::{DeviceId, MotionAction, MotionFlags, Source, SourceClass};
use log::info;
use std::collections::HashMap;
use std::collections::HashSet;
@@ -51,10 +51,15 @@
pub fn process_movement(
&mut self,
device_id: DeviceId,
+ source: Source,
action: u32,
pointer_properties: &[RustPointerProperties],
flags: MotionFlags,
) -> Result<(), String> {
+ if !source.is_from_class(SourceClass::Pointer) {
+ // Skip non-pointer sources like MOUSE_RELATIVE for now
+ return Ok(());
+ }
if self.should_log {
info!(
"Processing {} for device {:?} ({} pointer{}) on {}",
@@ -68,6 +73,13 @@
match action.into() {
MotionAction::Down => {
+ if pointer_properties.len() != 1 {
+ return Err(format!(
+ "{}: Invalid DOWN event: there are {} pointers in the event",
+ self.name,
+ pointer_properties.len()
+ ));
+ }
let it = self
.touching_pointer_ids_by_device
.entry(device_id)
@@ -90,10 +102,19 @@
));
}
let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
+ if it.len() != pointer_properties.len() - 1 {
+ return Err(format!(
+ "{}: There are currently {} touching pointers, but the incoming \
+ POINTER_DOWN event has {}",
+ self.name,
+ it.len(),
+ pointer_properties.len()
+ ));
+ }
let pointer_id = pointer_properties[action_index].id;
if it.contains(&pointer_id) {
return Err(format!(
- "{}: Pointer with id={} not found in the properties",
+ "{}: Pointer with id={} already present found in the properties",
self.name, pointer_id
));
}
@@ -108,11 +129,10 @@
}
}
MotionAction::PointerUp { action_index } => {
- if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
+ if !self.ensure_touching_pointers_match(device_id, pointer_properties) {
return Err(format!(
- "{}: Received POINTER_UP but no pointers are currently down for device \
- {:?}",
- self.name, device_id
+ "{}: ACTION_POINTER_UP touching pointers don't match",
+ self.name
));
}
let it = self.touching_pointer_ids_by_device.get_mut(&device_id).unwrap();
@@ -120,6 +140,13 @@
it.remove(&pointer_id);
}
MotionAction::Up => {
+ if pointer_properties.len() != 1 {
+ return Err(format!(
+ "{}: Invalid UP event: there are {} pointers in the event",
+ self.name,
+ pointer_properties.len()
+ ));
+ }
if !self.touching_pointer_ids_by_device.contains_key(&device_id) {
return Err(format!(
"{} Received ACTION_UP but no pointers are currently down for device {:?}",
@@ -246,6 +273,7 @@
use crate::DeviceId;
use crate::MotionFlags;
use crate::RustPointerProperties;
+ use crate::Source;
#[test]
fn single_pointer_stream() {
let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
@@ -253,6 +281,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -261,6 +290,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -269,6 +299,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
&pointer_properties,
MotionFlags::empty(),
@@ -283,6 +314,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -291,6 +323,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -299,6 +332,7 @@
assert!(verifier
.process_movement(
DeviceId(2),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -307,6 +341,7 @@
assert!(verifier
.process_movement(
DeviceId(2),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -315,6 +350,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
&pointer_properties,
MotionFlags::empty(),
@@ -329,6 +365,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -337,6 +374,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
&pointer_properties,
MotionFlags::CANCELED,
@@ -351,6 +389,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_DOWN,
&pointer_properties,
MotionFlags::empty(),
@@ -359,6 +398,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_CANCEL,
&pointer_properties,
MotionFlags::empty(), // forgot to set FLAG_CANCELED
@@ -373,6 +413,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_UP,
&pointer_properties,
MotionFlags::empty(),
@@ -387,6 +428,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
@@ -396,6 +438,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_MOVE,
&pointer_properties,
MotionFlags::empty(),
@@ -405,6 +448,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_EXIT,
&pointer_properties,
MotionFlags::empty(),
@@ -414,6 +458,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
@@ -428,6 +473,7 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
@@ -437,10 +483,28 @@
assert!(verifier
.process_movement(
DeviceId(1),
+ Source::Touchscreen,
input_bindgen::AMOTION_EVENT_ACTION_HOVER_ENTER,
&pointer_properties,
MotionFlags::empty(),
)
.is_err());
}
+
+ // Send a MOVE without a preceding DOWN event. This is OK because it's from source
+ // MOUSE_RELATIVE, which is used during pointer capture. The verifier should allow such event.
+ #[test]
+ fn relative_mouse_move() {
+ let mut verifier = InputVerifier::new("Test", /*should_log*/ false);
+ let pointer_properties = Vec::from([RustPointerProperties { id: 0 }]);
+ assert!(verifier
+ .process_movement(
+ DeviceId(2),
+ Source::MouseRelative,
+ input_bindgen::AMOTION_EVENT_ACTION_MOVE,
+ &pointer_properties,
+ MotionFlags::empty(),
+ )
+ .is_ok());
+ }
}
diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs
index 1d3c434..01d9599 100644
--- a/libs/input/rust/lib.rs
+++ b/libs/input/rust/lib.rs
@@ -19,7 +19,7 @@
mod input;
mod input_verifier;
-pub use input::{DeviceId, MotionAction, MotionFlags};
+pub use input::{DeviceId, MotionAction, MotionFlags, Source};
pub use input_verifier::InputVerifier;
#[cxx::bridge(namespace = "android::input")]
@@ -51,6 +51,7 @@
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
+ source: u32,
action: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
@@ -73,12 +74,14 @@
fn process_movement(
verifier: &mut InputVerifier,
device_id: i32,
+ source: u32,
action: u32,
pointer_properties: &[RustPointerProperties],
flags: u32,
) -> String {
let result = verifier.process_movement(
DeviceId(device_id),
+ Source::from_bits(source).unwrap(),
action,
pointer_properties,
MotionFlags::from_bits(flags).unwrap(),
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
index 655de80..106d78a 100644
--- a/libs/input/tests/TouchResampling_test.cpp
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -31,6 +31,7 @@
int32_t id;
float x;
float y;
+ ToolType toolType = ToolType::FINGER;
bool isResampled = false;
};
@@ -99,7 +100,7 @@
properties.push_back({});
properties.back().clear();
properties.back().id = pointer.id;
- properties.back().toolType = ToolType::FINGER;
+ properties.back().toolType = pointer.toolType;
coords.push_back({});
coords.back().clear();
@@ -292,6 +293,48 @@
}
/**
+ * Stylus pointer coordinates are not resampled, but an event is still generated for the batch with
+ * a resampled timestamp and should be marked as such.
+ */
+TEST_F(TouchResamplingTest, StylusCoordinatesNotResampledFor) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30, .toolType = ToolType::STYLUS}}, AMOTION_EVENT_ACTION_MOVE},
+ // A resampled event is generated, but the stylus coordinates are not resampled.
+ {25ms,
+ {{0, 30, 30, .toolType = ToolType::STYLUS, .isResampled = true}},
+ AMOTION_EVENT_ACTION_MOVE},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
* Event should not be resampled when sample time is equal to event time.
*/
TEST_F(TouchResamplingTest, SampleTimeEqualsEventTime) {
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index 8d8a2bc..342f5de 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -73,6 +73,8 @@
"libGLESv2",
],
+ static_libs: ["libguiflags"],
+
export_header_lib_headers: ["jni_headers"],
header_libs: [
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index 0f119f3..32fb350 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -19,6 +19,7 @@
#include <android/hardware_buffer.h>
#include <gui/BufferQueueDefs.h>
#include <gui/ConsumerBase.h>
+#include <gui/Flags.h>
#include <gui/IGraphicBufferProducer.h>
#include <sys/cdefs.h>
#include <system/graphics.h>
@@ -290,6 +291,20 @@
*/
void releaseConsumerOwnership();
+ /**
+ * Interface for SurfaceTexture callback(s).
+ */
+ struct SurfaceTextureListener : public RefBase {
+ virtual void onFrameAvailable(const BufferItem& item) = 0;
+ virtual void onSetFrameRate(float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy) = 0;
+ };
+
+ /**
+ * setSurfaceTextureListener registers a SurfaceTextureListener.
+ */
+ void setSurfaceTextureListener(const sp<SurfaceTextureListener>&);
+
protected:
/**
* abandonLocked overrides the ConsumerBase method to clear
@@ -335,6 +350,14 @@
void computeCurrentTransformMatrixLocked();
/**
+ * onSetFrameRate Notifies the consumer of a setFrameRate call from the producer side.
+ */
+#if FLAG_BQ_SET_FRAME_RATE
+ void onSetFrameRate(float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy) override;
+#endif
+
+ /**
* The default consumer usage flags that SurfaceTexture always sets on its
* BufferQueue instance; these will be OR:d with any additional flags passed
* from the SurfaceTexture user. In particular, SurfaceTexture will always
@@ -465,8 +488,30 @@
*/
ImageConsumer mImageConsumer;
+ /**
+ * mSurfaceTextureListener holds the registered SurfaceTextureListener.
+ * Note that SurfaceTexture holds the lister with an sp<>, which means that the listener
+ * must only hold a wp<> to SurfaceTexture and not an sp<>.
+ */
+ sp<SurfaceTextureListener> mSurfaceTextureListener;
+
friend class ImageConsumer;
friend class EGLConsumer;
+
+private:
+ // Proxy listener to avoid having SurfaceTexture directly implement FrameAvailableListener as it
+ // is extending ConsumerBase which also implements FrameAvailableListener.
+ class FrameAvailableListenerProxy : public ConsumerBase::FrameAvailableListener {
+ public:
+ FrameAvailableListenerProxy(const wp<SurfaceTextureListener>& listener)
+ : mSurfaceTextureListener(listener) {}
+
+ private:
+ void onFrameAvailable(const BufferItem& item) override;
+
+ const wp<SurfaceTextureListener> mSurfaceTextureListener;
+ };
+ sp<FrameAvailableListenerProxy> mFrameAvailableListenerProxy;
};
// ----------------------------------------------------------------------------
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index 9f610e1..c2535e0 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -23,6 +23,8 @@
#include <system/window.h>
#include <utils/Trace.h>
+#include <com_android_graphics_libgui_flags.h>
+
namespace android {
// Macros for including the SurfaceTexture name in log messages
@@ -491,4 +493,42 @@
return buffer;
}
+void SurfaceTexture::setSurfaceTextureListener(
+ const sp<android::SurfaceTexture::SurfaceTextureListener>& listener) {
+ SFT_LOGV("setSurfaceTextureListener");
+
+ Mutex::Autolock _l(mMutex);
+ mSurfaceTextureListener = listener;
+ if (mSurfaceTextureListener != nullptr) {
+ mFrameAvailableListenerProxy =
+ sp<FrameAvailableListenerProxy>::make(mSurfaceTextureListener);
+ setFrameAvailableListener(mFrameAvailableListenerProxy);
+ } else {
+ mFrameAvailableListenerProxy.clear();
+ }
+}
+
+void SurfaceTexture::FrameAvailableListenerProxy::onFrameAvailable(const BufferItem& item) {
+ const auto listener = mSurfaceTextureListener.promote();
+ if (listener) {
+ listener->onFrameAvailable(item);
+ }
+}
+
+#if FLAG_BQ_SET_FRAME_RATE
+void SurfaceTexture::onSetFrameRate(float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy) {
+ SFT_LOGV("onSetFrameRate: %.2f", frameRate);
+
+ auto listener = [&] {
+ Mutex::Autolock _l(mMutex);
+ return mSurfaceTextureListener;
+ }();
+
+ if (listener) {
+ listener->onSetFrameRate(frameRate, compatibility, changeFrameRateStrategy);
+ }
+}
+#endif
+
} // namespace android
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index f889de5..0f62324 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -18,6 +18,7 @@
#include "UnwantedInteractionBlocker.h"
#include <android-base/stringprintf.h>
+#include <com_android_input_flags.h>
#include <ftl/enum.h>
#include <input/PrintTools.h>
#include <inttypes.h>
@@ -28,6 +29,8 @@
#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter.h"
#include "ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.h"
+namespace input_flags = com::android::input::flags;
+
using android::base::StringPrintf;
/**
@@ -344,10 +347,14 @@
ALOGD_IF(DEBUG_INBOUND_MOTION, "%s: %s", __func__, args.dump().c_str());
{ // acquire lock
std::scoped_lock lock(mLock);
- const std::vector<NotifyMotionArgs> processedArgs =
- mPreferStylusOverTouchBlocker.processMotion(args);
- for (const NotifyMotionArgs& loopArgs : processedArgs) {
- notifyMotionLocked(loopArgs);
+ if (input_flags::enable_multi_device_input()) {
+ notifyMotionLocked(args);
+ } else {
+ const std::vector<NotifyMotionArgs> processedArgs =
+ mPreferStylusOverTouchBlocker.processMotion(args);
+ for (const NotifyMotionArgs& loopArgs : processedArgs) {
+ notifyMotionLocked(loopArgs);
+ }
}
} // release lock
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 9cd1e09..5158220 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1293,7 +1293,7 @@
}
std::vector<InputTarget> InputDispatcher::findOutsideTargetsLocked(
- int32_t displayId, const sp<WindowInfoHandle>& touchedWindow) const {
+ int32_t displayId, const sp<WindowInfoHandle>& touchedWindow, int32_t pointerId) const {
if (touchedWindow == nullptr) {
return {};
}
@@ -1309,9 +1309,10 @@
const WindowInfo& info = *windowHandle->getInfo();
if (info.inputConfig.test(WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH)) {
- addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE,
- /*pointerIds=*/{}, /*firstDownTimeInTarget=*/std::nullopt,
- outsideTargets);
+ std::bitset<MAX_POINTER_ID + 1> pointerIds;
+ pointerIds.set(pointerId);
+ addWindowTargetLocked(windowHandle, InputTarget::Flags::DISPATCH_AS_OUTSIDE, pointerIds,
+ /*firstDownTimeInTarget=*/std::nullopt, outsideTargets);
}
}
return outsideTargets;
@@ -2333,6 +2334,7 @@
/* Case 1: New splittable pointer going down, or need target for hover or scroll. */
const auto [x, y] = resolveTouchedPosition(entry);
const int32_t pointerIndex = MotionEvent::getActionIndex(action);
+ const int32_t pointerId = entry.pointerProperties[pointerIndex].id;
// Outside targets should be added upon first dispatched DOWN event. That means, this should
// be a pointer that would generate ACTION_DOWN, *and* touch should not already be down.
const bool isStylus = isPointerFromStylus(entry, pointerIndex);
@@ -2340,7 +2342,7 @@
findTouchedWindowAtLocked(displayId, x, y, isStylus);
if (isDown) {
- targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle);
+ targets += findOutsideTargetsLocked(displayId, newTouchedWindowHandle, pointerId);
}
// Handle the case where we did not find a window.
if (newTouchedWindowHandle == nullptr) {
@@ -2398,7 +2400,6 @@
if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- const int32_t pointerId = entry.pointerProperties[0].id;
// The "windowHandle" is the target of this hovering pointer.
tempTouchState.addHoveringPointerToWindow(windowHandle, entry.deviceId, pointerId);
}
@@ -2423,7 +2424,7 @@
// Update the temporary touch state.
std::bitset<MAX_POINTER_ID + 1> pointerIds;
if (!isHoverAction) {
- pointerIds.set(entry.pointerProperties[pointerIndex].id);
+ pointerIds.set(pointerId);
}
const bool isDownOrPointerDown = maskedAction == AMOTION_EVENT_ACTION_DOWN ||
@@ -2467,7 +2468,6 @@
// If a window is already pilfering some pointers, give it this new pointer as well and
// make it pilfering. This will prevent other non-spy windows from getting this pointer,
// which is a specific behaviour that we want.
- const int32_t pointerId = entry.pointerProperties[pointerIndex].id;
for (TouchedWindow& touchedWindow : tempTouchState.windows) {
if (touchedWindow.hasTouchingPointer(entry.deviceId, pointerId) &&
touchedWindow.hasPilferingPointers(entry.deviceId)) {
@@ -4324,9 +4324,9 @@
mVerifiersByDisplay.try_emplace(args.displayId,
StringPrintf("display %" PRId32, args.displayId));
Result<void> result =
- it->second.processMovement(args.deviceId, args.action, args.getPointerCount(),
- args.pointerProperties.data(), args.pointerCoords.data(),
- args.flags);
+ it->second.processMovement(args.deviceId, args.source, args.action,
+ args.getPointerCount(), args.pointerProperties.data(),
+ args.pointerCoords.data(), args.flags);
if (!result.ok()) {
LOG(FATAL) << "Bad stream: " << result.error() << " caused by " << args.dump();
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 4d145c6..67705b9 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -242,8 +242,8 @@
int32_t displayId, float x, float y, bool isStylus = false,
bool ignoreDragWindow = false) const REQUIRES(mLock);
std::vector<InputTarget> findOutsideTargetsLocked(
- int32_t displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow) const
- REQUIRES(mLock);
+ int32_t displayId, const sp<android::gui::WindowInfoHandle>& touchedWindow,
+ int32_t pointerId) const REQUIRES(mLock);
std::vector<sp<android::gui::WindowInfoHandle>> findTouchedSpyWindowsAtLocked(
int32_t displayId, float x, float y, bool isStylus) const REQUIRES(mLock);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a73c511..5890050 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -3183,8 +3183,7 @@
} else {
// release sideband stream if it exists and a non null buffer is being set
if (mDrawingState.sidebandStream != nullptr) {
- mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
- mDrawingState.sidebandStream = nullptr;
+ setSidebandStream(nullptr, info, postTime);
}
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index c5870d4..dcef54d 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -944,6 +944,11 @@
return VK_ERROR_SURFACE_LOST_KHR;
}
+ // Additional buffer count over min_undequeued_buffers in vulkan came from 2 total
+ // being technically enough for fifo (although a poor experience) vs 3 being the
+ // absolute minimum for mailbox to be useful. So min_undequeued_buffers + 2 is sensible
+ static constexpr int default_additional_buffers = 2;
+
if(pPresentMode != nullptr) {
switch (pPresentMode->presentMode) {
case VK_PRESENT_MODE_IMMEDIATE_KHR:
@@ -951,8 +956,8 @@
break;
case VK_PRESENT_MODE_MAILBOX_KHR:
case VK_PRESENT_MODE_FIFO_KHR:
- capabilities->minImageCount =
- std::min(max_buffer_count, min_undequeued_buffers + 2);
+ capabilities->minImageCount = std::min(max_buffer_count,
+ min_undequeued_buffers + default_additional_buffers);
capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
break;
case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
@@ -971,7 +976,8 @@
break;
}
} else {
- capabilities->minImageCount = std::min(max_buffer_count, min_undequeued_buffers + 2);
+ capabilities->minImageCount = std::min(max_buffer_count,
+ min_undequeued_buffers + default_additional_buffers);
capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
}
}