Merge changes I355dea76,I63d21c22
* changes:
SF: Simplify per-display refresh rate selection
SF: Deduplicate FakeDisplayInjector
diff --git a/cmds/installd/otapreopt.rc b/cmds/installd/otapreopt.rc
index 059ae75..0bad0c5 100644
--- a/cmds/installd/otapreopt.rc
+++ b/cmds/installd/otapreopt.rc
@@ -5,4 +5,4 @@
# The dalvik-cache was not moved itself, so as to restrict the rights of otapreopt_slot.
# But now the relabeling is annoying as there is no force option available here. So
# explicitly list all the ISAs we know.
- restorecon_recursive /data/dalvik-cache/arm /data/dalvik-cache/arm64 /data/dalvik-cache/mips /data/dalvik-cache/mips64 /data/dalvik-cache/x86 /data/dalvik-cache/x86_64
+ restorecon_recursive /data/dalvik-cache/arm /data/dalvik-cache/arm64 /data/dalvik-cache/riscv64 /data/dalvik-cache/x86 /data/dalvik-cache/x86_64
diff --git a/include/android/surface_control_jni.h b/include/android/surface_control_jni.h
index 67e3a9f..a0a1fdb 100644
--- a/include/android/surface_control_jni.h
+++ b/include/android/surface_control_jni.h
@@ -36,14 +36,15 @@
/**
* Return the ASurfaceControl wrapped by a Java SurfaceControl object.
*
- * This method does not acquire any additional reference to the ASurfaceControl
- * that is returned. To keep the ASurfaceControl alive after the Java
- * SurfaceControl object is closed, explicitly or by the garbage collector, be
- * sure to use ASurfaceControl_acquire() to acquire an additional reference.
+ * The caller takes ownership of the returned ASurfaceControl returned and must
+ * release it * using ASurfaceControl_release.
+ *
+ * surfaceControlObj must be a non-null instance of android.view.SurfaceControl
+ * and isValid() must be true.
*
* Available since API level 34.
*/
-ASurfaceControl* _Nullable ASurfaceControl_fromSurfaceControl(JNIEnv* _Nonnull env,
+ASurfaceControl* _Nonnull ASurfaceControl_fromSurfaceControl(JNIEnv* _Nonnull env,
jobject _Nonnull surfaceControlObj) __INTRODUCED_IN(__ANDROID_API_U__);
/**
@@ -52,11 +53,13 @@
* The returned ASurfaceTransaction is still owned by the Java Transaction object is only
* valid while the Java Transaction object is alive. In particular, the returned transaction
* must NOT be deleted with ASurfaceTransaction_delete.
- * May return nullptr on error.
+ *
+ * transactionObj must be a non-null instance of
+ * android.view.SurfaceControl.Transaction and close() must not already be called.
*
* Available since API level 34.
*/
-ASurfaceTransaction* _Nullable ASurfaceTransaction_fromTransaction(JNIEnv* _Nonnull env,
+ASurfaceTransaction* _Nonnull ASurfaceTransaction_fromTransaction(JNIEnv* _Nonnull env,
jobject _Nonnull transactionObj) __INTRODUCED_IN(__ANDROID_API_U__);
__END_DECLS
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 0026e82..f4a1523 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -280,6 +280,9 @@
std::vector<InputDeviceLightInfo> getLights();
+ inline void setSupportsUsi(bool supportsUsi) { mSupportsUsi = supportsUsi; }
+ inline bool supportsUsi() const { return mSupportsUsi; }
+
private:
int32_t mId;
int32_t mGeneration;
@@ -292,6 +295,8 @@
uint32_t mSources;
int32_t mKeyboardType;
std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
+ // Whether this device supports the Universal Stylus Initiative (USI) protocol for styluses.
+ bool mSupportsUsi;
bool mHasVibrator;
bool mHasBattery;
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 29e02cf..34ef7b4 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -89,7 +89,6 @@
shared_libs: [
"libutils",
"libbinder",
- "libui",
],
static_libs: [
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 3fe03c7..4751a7d 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -182,6 +182,7 @@
mSources(other.mSources),
mKeyboardType(other.mKeyboardType),
mKeyCharacterMap(other.mKeyCharacterMap),
+ mSupportsUsi(other.mSupportsUsi),
mHasVibrator(other.mHasVibrator),
mHasBattery(other.mHasBattery),
mHasButtonUnderPad(other.mHasButtonUnderPad),
@@ -210,6 +211,7 @@
mHasBattery = false;
mHasButtonUnderPad = false;
mHasSensor = false;
+ mSupportsUsi = false;
mMotionRanges.clear();
mSensors.clear();
mLights.clear();
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index c53811a..5aae37d 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -10,6 +10,7 @@
cc_test {
name: "libinput_tests",
+ host_supported: true,
srcs: [
"IdGenerator_test.cpp",
"InputChannel_test.cpp",
@@ -24,6 +25,7 @@
static_libs: [
"libgui_window_info_static",
"libinput",
+ "libui-types",
],
cflags: [
"-Wall",
@@ -35,11 +37,13 @@
"libbinder",
"libcutils",
"liblog",
- "libui",
"libutils",
"libvintf",
],
data: ["data/*"],
+ test_options: {
+ unit_test: true,
+ },
test_suites: ["device-tests"],
}
@@ -60,7 +64,6 @@
"libcutils",
"libutils",
"libbinder",
- "libui",
"libbase",
],
}
diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp
index e872fa4..2344463 100644
--- a/libs/input/tests/InputDevice_test.cpp
+++ b/libs/input/tests/InputDevice_test.cpp
@@ -65,6 +65,9 @@
}
void SetUp() override {
+#if !defined(__ANDROID__)
+ GTEST_SKIP() << "b/253299089 Generic files are currently read directly from device.";
+#endif
loadKeyLayout("Generic");
loadKeyCharacterMap("Generic");
}
@@ -131,6 +134,9 @@
}
TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) {
+#if !defined(__ANDROID__)
+ GTEST_SKIP() << "Can't check kernel configs on host";
+#endif
std::string klPath = base::GetExecutableDirectory() + "/data/kl_with_required_fake_config.kl";
base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath;
@@ -139,6 +145,9 @@
}
TEST(InputDeviceKeyLayoutTest, LoadsWhenRequiredKernelConfigIsPresent) {
+#if !defined(__ANDROID__)
+ GTEST_SKIP() << "Can't check kernel configs on host";
+#endif
std::string klPath = base::GetExecutableDirectory() + "/data/kl_with_required_real_config.kl";
base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
ASSERT_TRUE(ret.ok()) << "Cannot load KeyLayout at " << klPath;
diff --git a/libs/jpegrecoverymap/OWNERS b/libs/jpegrecoverymap/OWNERS
index 6ace354..133af5b 100644
--- a/libs/jpegrecoverymap/OWNERS
+++ b/libs/jpegrecoverymap/OWNERS
@@ -1,3 +1,4 @@
arifdikici@google.com
+deakin@google.com
dichenzhang@google.com
kyslov@google.com
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
index c5f8e9a..6949f85 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
@@ -16,61 +16,100 @@
namespace android::recoverymap {
+/*
+ * Holds information for uncompressed image or recovery map.
+ */
+struct jpeg_r_uncompressed_struct {
+ // Pointer to the data location.
+ void* data;
+ // Width of the recovery map or image in pixels.
+ int width;
+ // Height of the recovery map or image in pixels.
+ int height;
+};
+
+/*
+ * Holds information for compressed image or recovery map.
+ */
+struct jpeg_r_compressed_struct {
+ // Pointer to the data location.
+ void* data;
+ // Data length;
+ int length;
+};
+
+typedef struct jpeg_r_uncompressed_struct* j_r_uncompressed_ptr;
+typedef struct jpeg_r_compressed_struct* j_r_compressed_ptr;
+
class RecoveryMap {
public:
/*
* This method is called in the decoding pipeline. It will decode the recovery map.
*
- * input: compressed recovery map
- * output: uncompressed recovery map
+ * @param compressed_recovery_map compressed recovery map
+ * @param dest decoded recover map
+ * @return true if decoding succeeds
*/
- void* decodeRecoveryMap(void* compressed_recovery_map);
+ bool decodeRecoveryMap(j_r_compressed_ptr compressed_recovery_map,
+ j_r_uncompressed_ptr dest);
/*
* This method is called in the encoding pipeline. It will encode the recovery map.
*
- * input: uncompressed recovery map
- * output: compressed recovery map
+ * @param uncompressed_recovery_map uncompressed recovery map
+ * @param dest encoded recover map
+ * @return true if encoding succeeds
*/
- void* encodeRecoveryMap(void* uncompressed_recovery_map);
+ bool encodeRecoveryMap(j_r_uncompressed_ptr uncompressed_recovery_map,
+ j_r_compressed_ptr dest);
/*
* This method is called in the encoding pipeline. It will take the uncompressed 8-bit and
* 10-bit yuv images as input, and calculate the uncompressed recovery map.
*
- * input: uncompressed yuv_420 image, uncompressed p010 image
- * output: uncompressed recovery map
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+ * @param dest recover map
+ * @return true if calculation succeeds
*/
- void* generateRecoveryMap(void* uncompressed_yuv_420_image, void* uncompressed_p010_image);
+ bool generateRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+ j_r_uncompressed_ptr uncompressed_p010_image,
+ j_r_uncompressed_ptr dest);
/*
* This method is called in the decoding pipeline. It will take the uncompressed (decoded)
- * 8-bit yuv image and the uncompressed(decoded) recovery map as input, and calculate the
+ * 8-bit yuv image and the uncompressed (decoded) recovery map as input, and calculate the
* 10-bit recovered image (in p010 color format).
*
- * input: uncompressed yuv_420 image, uncompressed recovery map
- * output: uncompress p010 image
+ * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+ * @param uncompressed_recovery_map uncompressed recovery map
+ * @param dest reconstructed HDR image
+ * @return true if calculation succeeds
*/
- void* applyRecoveryMap(void* uncompressed_yuv_420_image, void* uncompressed_recovery_map);
+ bool applyRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+ j_r_uncompressed_ptr uncompressed_recovery_map,
+ j_r_uncompressed_ptr dest);
/*
* This method is called in the decoding pipeline. It will read XMP metadata to find the start
* position of the compressed recovery map, and will extract the compressed recovery map.
*
- * input: compressed JPEG-G image (8-bit JPEG + compressed recovery map)
- * output: compressed recovery map
+ * @param compressed_jpeg_r_image compressed JPEG_R image
+ * @return compressed recovery map
*/
- void* extractRecoveryMap(void* compressed_jpeg_g_image);
+ j_r_compressed_ptr extractRecoveryMap(void* compressed_jpeg_r_image);
/*
* This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image
* and the compressed recovery map as input, and update the XMP metadata with the end of JPEG
* marker, and append the compressed gian map after the JPEG.
*
- * input: compressed 8-bit JPEG image (standard JPEG), compressed recovery map
- * output: compressed JPEG-G image (8-bit JPEG + compressed recovery map)
+ * @param compressed_jpeg_image compressed 8-bit JPEG image
+ * @param compress_recovery_map compressed recover map
+ * @return compressed JPEG_R image
*/
- void* appendRecoveryMap(void* compressed_jpeg_image, void* compressed_recovery_map);
+ void* appendRecoveryMap(void* compressed_jpeg_image,
+ j_r_compressed_ptr compressed_recovery_map);
};
-} // namespace android::recoverymap
\ No newline at end of file
+} // namespace android::recoverymap
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 3e95a31..bd92652 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -18,8 +18,54 @@
namespace android::recoverymap {
-void* RecoveryMap::decodeRecoveryMap(void* compressed_recovery_map) {
- if (compressed_recovery_map == nullptr) {
+bool RecoveryMap::decodeRecoveryMap(j_r_compressed_ptr compressed_recovery_map,
+ j_r_uncompressed_ptr dest) {
+ if (compressed_recovery_map == nullptr || dest == nullptr) {
+ return false;
+ }
+
+ // TBD
+ return true;
+}
+
+bool RecoveryMap::encodeRecoveryMap(j_r_uncompressed_ptr uncompressed_recovery_map,
+ j_r_compressed_ptr dest) {
+ if (uncompressed_recovery_map == nullptr || dest == nullptr) {
+ return false;
+ }
+
+ // TBD
+ return true;
+}
+
+bool RecoveryMap::generateRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+ j_r_uncompressed_ptr uncompressed_p010_image,
+ j_r_uncompressed_ptr dest) {
+ if (uncompressed_yuv_420_image == nullptr
+ || uncompressed_p010_image == nullptr
+ || dest == nullptr) {
+ return false;
+ }
+
+ // TBD
+ return true;
+}
+
+bool RecoveryMap::applyRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+ j_r_uncompressed_ptr uncompressed_recovery_map,
+ j_r_uncompressed_ptr dest) {
+ if (uncompressed_yuv_420_image == nullptr
+ || uncompressed_recovery_map == nullptr
+ || dest == nullptr) {
+ return false;
+ }
+
+ // TBD
+ return true;
+}
+
+j_r_compressed_ptr RecoveryMap::extractRecoveryMap(void* compressed_jpeg_r_image) {
+ if (compressed_jpeg_r_image == nullptr) {
return nullptr;
}
@@ -27,45 +73,8 @@
return nullptr;
}
-void* RecoveryMap::encodeRecoveryMap(void* uncompressed_recovery_map) {
- if (uncompressed_recovery_map == nullptr) {
- return nullptr;
- }
-
- // TBD
- return nullptr;
-}
-
-void* RecoveryMap::generateRecoveryMap(
- void* uncompressed_yuv_420_image, void* uncompressed_p010_image) {
- if (uncompressed_yuv_420_image == nullptr || uncompressed_p010_image == nullptr) {
- return nullptr;
- }
-
- // TBD
- return nullptr;
-}
-
-void* RecoveryMap::applyRecoveryMap(
- void* uncompressed_yuv_420_image, void* uncompressed_recovery_map) {
- if (uncompressed_yuv_420_image == nullptr || uncompressed_recovery_map == nullptr) {
- return nullptr;
- }
-
- // TBD
- return nullptr;
-}
-
-void* RecoveryMap::extractRecoveryMap(void* compressed_jpeg_g_image) {
- if (compressed_jpeg_g_image == nullptr) {
- return nullptr;
- }
-
- // TBD
- return nullptr;
-}
-
-void* RecoveryMap::appendRecoveryMap(void* compressed_jpeg_image, void* compressed_recovery_map) {
+void* RecoveryMap::appendRecoveryMap(void* compressed_jpeg_image,
+ j_r_compressed_ptr compressed_recovery_map) {
if (compressed_jpeg_image == nullptr || compressed_recovery_map == nullptr) {
return nullptr;
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index da58efd..18a73ea 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -189,73 +189,74 @@
void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
InputMapper::populateDeviceInfo(info);
- if (mDeviceMode != DeviceMode::DISABLED) {
- info->addMotionRange(mOrientedRanges.x);
- info->addMotionRange(mOrientedRanges.y);
- info->addMotionRange(mOrientedRanges.pressure);
-
- if (mDeviceMode == DeviceMode::UNSCALED && mSource == AINPUT_SOURCE_TOUCHPAD) {
- // Populate RELATIVE_X and RELATIVE_Y motion ranges for touchpad capture mode.
- //
- // RELATIVE_X and RELATIVE_Y motion ranges should be the largest possible relative
- // motion, i.e. the hardware dimensions, as the finger could move completely across the
- // touchpad in one sample cycle.
- const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
- const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
- info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -x.max, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -y.max, y.max, y.flat,
- y.fuzz, y.resolution);
- }
-
- if (mOrientedRanges.size) {
- info->addMotionRange(*mOrientedRanges.size);
- }
-
- if (mOrientedRanges.touchMajor) {
- info->addMotionRange(*mOrientedRanges.touchMajor);
- info->addMotionRange(*mOrientedRanges.touchMinor);
- }
-
- if (mOrientedRanges.toolMajor) {
- info->addMotionRange(*mOrientedRanges.toolMajor);
- info->addMotionRange(*mOrientedRanges.toolMinor);
- }
-
- if (mOrientedRanges.orientation) {
- info->addMotionRange(*mOrientedRanges.orientation);
- }
-
- if (mOrientedRanges.distance) {
- info->addMotionRange(*mOrientedRanges.distance);
- }
-
- if (mOrientedRanges.tilt) {
- info->addMotionRange(*mOrientedRanges.tilt);
- }
-
- if (mCursorScrollAccumulator.haveRelativeVWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
- }
- if (mCursorScrollAccumulator.haveRelativeHWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
- }
- if (mCalibration.coverageCalibration == Calibration::CoverageCalibration::BOX) {
- const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
- const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
- y.fuzz, y.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
- y.fuzz, y.resolution);
- }
- info->setButtonUnderPad(mParameters.hasButtonUnderPad);
+ if (mDeviceMode == DeviceMode::DISABLED) {
+ return;
}
+
+ info->addMotionRange(mOrientedRanges.x);
+ info->addMotionRange(mOrientedRanges.y);
+ info->addMotionRange(mOrientedRanges.pressure);
+
+ if (mDeviceMode == DeviceMode::UNSCALED && mSource == AINPUT_SOURCE_TOUCHPAD) {
+ // Populate RELATIVE_X and RELATIVE_Y motion ranges for touchpad capture mode.
+ //
+ // RELATIVE_X and RELATIVE_Y motion ranges should be the largest possible relative
+ // motion, i.e. the hardware dimensions, as the finger could move completely across the
+ // touchpad in one sample cycle.
+ const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
+ const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
+ info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_X, mSource, -x.max, x.max, x.flat, x.fuzz,
+ x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_RELATIVE_Y, mSource, -y.max, y.max, y.flat, y.fuzz,
+ y.resolution);
+ }
+
+ if (mOrientedRanges.size) {
+ info->addMotionRange(*mOrientedRanges.size);
+ }
+
+ if (mOrientedRanges.touchMajor) {
+ info->addMotionRange(*mOrientedRanges.touchMajor);
+ info->addMotionRange(*mOrientedRanges.touchMinor);
+ }
+
+ if (mOrientedRanges.toolMajor) {
+ info->addMotionRange(*mOrientedRanges.toolMajor);
+ info->addMotionRange(*mOrientedRanges.toolMinor);
+ }
+
+ if (mOrientedRanges.orientation) {
+ info->addMotionRange(*mOrientedRanges.orientation);
+ }
+
+ if (mOrientedRanges.distance) {
+ info->addMotionRange(*mOrientedRanges.distance);
+ }
+
+ if (mOrientedRanges.tilt) {
+ info->addMotionRange(*mOrientedRanges.tilt);
+ }
+
+ if (mCursorScrollAccumulator.haveRelativeVWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ if (mCursorScrollAccumulator.haveRelativeHWheel()) {
+ info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
+ }
+ if (mCalibration.coverageCalibration == Calibration::CoverageCalibration::BOX) {
+ const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
+ const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat, x.fuzz,
+ x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat, y.fuzz,
+ y.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat, x.fuzz,
+ x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat, y.fuzz,
+ y.resolution);
+ }
+ info->setButtonUnderPad(mParameters.hasButtonUnderPad);
+ info->setSupportsUsi(mParameters.supportsUsi);
}
void TouchInputMapper::dump(std::string& dump) {
@@ -395,13 +396,11 @@
}
if (changes && resetNeeded) {
- // If the device needs to be reset, cancel any ongoing gestures and reset the state.
- out += cancelTouch(when, when);
out += reset(when);
// Send reset, unless this is the first time the device has been configured,
// in which case the reader will call reset itself after all mappers are ready.
- out.push_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
+ out.emplace_back(NotifyDeviceResetArgs(getContext()->getNextId(), when, getDeviceId()));
}
return out;
}
@@ -507,6 +506,10 @@
// up in your pocket but you can enable it using the input device configuration.
mParameters.wake = getDeviceContext().isExternal();
getDeviceContext().getConfiguration().tryGetProperty("touch.wake", mParameters.wake);
+
+ mParameters.supportsUsi = false;
+ getDeviceContext().getConfiguration().tryGetProperty("touch.supportsUsi",
+ mParameters.supportsUsi);
}
void TouchInputMapper::dumpParameters(std::string& dump) {
@@ -523,6 +526,7 @@
mParameters.uniqueDisplayId.c_str());
dump += StringPrintf(INDENT4 "OrientationAware: %s\n", toString(mParameters.orientationAware));
dump += INDENT4 "Orientation: " + ftl::enum_string(mParameters.orientation) + "\n";
+ dump += StringPrintf(INDENT4 "SupportsUsi: %s\n", toString(mParameters.supportsUsi));
}
void TouchInputMapper::configureRawPointerAxes() {
@@ -1440,6 +1444,9 @@
}
std::list<NotifyArgs> TouchInputMapper::reset(nsecs_t when) {
+ std::list<NotifyArgs> out = cancelTouch(when, when);
+ updateTouchSpots();
+
mCursorButtonAccumulator.reset(getDeviceContext());
mCursorScrollAccumulator.reset(getDeviceContext());
mTouchButtonAccumulator.reset(getDeviceContext());
@@ -1470,7 +1477,7 @@
mPointerController->clearSpots();
}
- return InputMapper::reset(when);
+ return out += InputMapper::reset(when);
}
void TouchInputMapper::resetExternalStylus() {
@@ -1554,10 +1561,7 @@
std::list<NotifyArgs> TouchInputMapper::processRawTouches(bool timeout) {
std::list<NotifyArgs> out;
if (mDeviceMode == DeviceMode::DISABLED) {
- // Drop all input if the device is disabled.
- out += cancelTouch(mCurrentRawState.when, mCurrentRawState.readTime);
- mCurrentCookedState.clear();
- updateTouchSpots();
+ // Do not process raw event while the device is disabled.
return out;
}
@@ -1976,8 +1980,8 @@
int32_t metaState = getContext()->getGlobalMetaState();
int32_t buttonState = mCurrentCookedState.buttonState;
out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits,
@@ -2617,8 +2621,9 @@
BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
if (!dispatchedGestureIdBits.isEmpty()) {
if (cancelPreviousGesture) {
+ const uint32_t cancelFlags = flags | AMOTION_EVENT_FLAG_CANCELED;
out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, flags, metaState,
+ AMOTION_EVENT_ACTION_CANCEL, 0, cancelFlags, metaState,
buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords,
@@ -2754,8 +2759,8 @@
int32_t metaState = getContext()->getGlobalMetaState();
int32_t buttonState = mCurrentRawState.buttonState;
out.push_back(dispatchMotion(when, readTime, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, 0, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
+ metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords,
mPointerGesture.lastGestureIdToIndex,
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 50f30c8..7b0327e 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -232,6 +232,9 @@
GestureMode gestureMode;
bool wake;
+
+ // Whether the device supports the Universal Stylus Initiative (USI) protocol for styluses.
+ bool supportsUsi;
} mParameters;
// Immutable calibration parameters in parsed form.
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index dded6a1..8ac8dfc 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -3112,6 +3112,15 @@
return processArgList;
}
+ void resetMapper(InputMapper& mapper, nsecs_t when) {
+ const auto resetArgs = mapper.reset(when);
+ for (const auto args : resetArgs) {
+ mFakeListener->notify(args);
+ }
+ // Loop the reader to flush the input listener queue.
+ mReader->loopOnce();
+ }
+
static void assertMotionRange(const InputDeviceInfo& info,
int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) {
const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source);
@@ -6864,6 +6873,28 @@
toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
}
+TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareButtons();
+ prepareAxes(POSITION | PRESSURE);
+ SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+
+ // Touch down.
+ processDown(mapper, 100, 200);
+ processPressure(mapper, 1);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
+
+ // Reset the mapper. This should cancel the ongoing gesture.
+ resetMapper(mapper, ARBITRARY_TIME);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+}
+
TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
@@ -6878,8 +6909,9 @@
mFakeEventHub->setScanCodeState(EVENTHUB_ID, BTN_TOUCH, 1);
// Reset the mapper. When the mapper is reset, we expect it to attempt to recreate the touch
- // state by reading the current axis values.
- std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
+ // state by reading the current axis values. Since there was no ongoing gesture, calling reset
+ // does not generate any events.
+ resetMapper(mapper, ARBITRARY_TIME);
// Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
// the recreated touch state to generate a down event.
@@ -9530,9 +9562,10 @@
mFakeListener->assertNotifyMotionWasCalled(WithMotionAction(ACTION_POINTER_1_DOWN)));
// Reset the mapper. When the mapper is reset, we expect the current multi-touch state to be
- // preserved. Resetting should not generate any events.
- std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+ // preserved. Resetting should cancel the ongoing gesture.
+ resetMapper(mapper, ARBITRARY_TIME);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_CANCEL)));
// Send a sync to simulate an empty touch frame where nothing changes. The mapper should use
// the existing touch state to generate a down event.
@@ -9566,7 +9599,7 @@
// Reset the mapper. When the mapper is reset, we expect it to restore the latest
// raw state where no pointers are down.
- std::list<NotifyArgs> unused = mapper.reset(ARBITRARY_TIME);
+ resetMapper(mapper, ARBITRARY_TIME);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
// Send an empty sync frame. Since there are no pointers, no events are generated.
diff --git a/services/inputflinger/tests/TestInputListenerMatchers.h b/services/inputflinger/tests/TestInputListenerMatchers.h
index 2580405..ff7455b 100644
--- a/services/inputflinger/tests/TestInputListenerMatchers.h
+++ b/services/inputflinger/tests/TestInputListenerMatchers.h
@@ -23,13 +23,19 @@
namespace android {
MATCHER_P(WithMotionAction, action, "InputEvent with specified action") {
- if (action == AMOTION_EVENT_ACTION_CANCEL) {
- *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
- return (arg.flags & AMOTION_EVENT_FLAG_CANCELED) != 0;
+ bool matches = action == arg.action;
+ if (!matches) {
+ *result_listener << "expected action " << MotionEvent::actionToString(action)
+ << ", but got " << MotionEvent::actionToString(arg.action);
}
- *result_listener << "expected action " << MotionEvent::actionToString(action) << ", but got "
- << MotionEvent::actionToString(arg.action);
- return action == arg.action;
+ if (action == AMOTION_EVENT_ACTION_CANCEL) {
+ if (!matches) {
+ *result_listener << "; ";
+ }
+ *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set";
+ matches &= (arg.flags & AMOTION_EVENT_FLAG_CANCELED) != 0;
+ }
+ return matches;
}
MATCHER_P(WithSource, source, "InputEvent with specified source") {