Merge changes Id0c3cf19,Id089db27,Ia4c0cbb8
* changes:
Ensure returned event is non-null
Stricter validation of motion events in dispatcher
Add test for hover events over spy window
diff --git a/include/ftl/optional.h b/include/ftl/optional.h
index 7b02bac..a818128 100644
--- a/include/ftl/optional.h
+++ b/include/ftl/optional.h
@@ -95,6 +95,14 @@
if (has_value()) return std::invoke(std::forward<F>(f), std::move(value()));
return R();
}
+
+ // Delete new for this class. Its base doesn't have a virtual destructor, and
+ // if it got deleted via base class pointer, it would cause undefined
+ // behavior. There's not a good reason to allocate this object on the heap
+ // anyway.
+ static void* operator new(size_t) = delete;
+ static void* operator new[](size_t) = delete;
+
};
template <typename T, typename U>
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index 98a18c9..7457496 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -21,6 +21,7 @@
#include <ftl/string.h>
#include <gui/constants.h>
#include <input/Input.h>
+#include <ui/Rotation.h>
#include <cinttypes>
#include <optional>
@@ -29,13 +30,6 @@
namespace android {
-enum {
- DISPLAY_ORIENTATION_0 = 0,
- DISPLAY_ORIENTATION_90 = 1,
- DISPLAY_ORIENTATION_180 = 2,
- DISPLAY_ORIENTATION_270 = 3
-};
-
/**
* Describes the different type of viewports supported by input flinger.
* Keep in sync with values in InputManagerService.java.
@@ -54,7 +48,7 @@
*/
struct DisplayViewport {
int32_t displayId; // -1 if invalid
- int32_t orientation;
+ ui::Rotation orientation;
int32_t logicalLeft;
int32_t logicalTop;
int32_t logicalRight;
@@ -74,7 +68,7 @@
DisplayViewport()
: displayId(ADISPLAY_ID_NONE),
- orientation(DISPLAY_ORIENTATION_0),
+ orientation(ui::ROTATION_0),
logicalLeft(0),
logicalTop(0),
logicalRight(0),
@@ -111,7 +105,7 @@
void setNonDisplayViewport(int32_t width, int32_t height) {
displayId = ADISPLAY_ID_NONE;
- orientation = DISPLAY_ORIENTATION_0;
+ orientation = ui::ROTATION_0;
logicalLeft = 0;
logicalTop = 0;
logicalRight = width;
diff --git a/include/input/Input.h b/include/input/Input.h
index d298d81..015efdd 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -577,7 +577,7 @@
inline const ui::Transform& getTransform() const { return mTransform; }
- int getSurfaceRotation() const;
+ std::optional<ui::Rotation> getSurfaceRotation() const;
inline float getXPrecision() const { return mXPrecision; }
diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h
index a616a95..1e4f6e7 100644
--- a/include/input/TouchVideoFrame.h
+++ b/include/input/TouchVideoFrame.h
@@ -16,6 +16,8 @@
#pragma once
+#include <ui/Rotation.h>
+
#include <stdint.h>
#include <sys/time.h>
#include <vector>
@@ -58,7 +60,7 @@
* Rotate the video frame.
* The rotation value is an enum from ui/Rotation.h
*/
- void rotate(int32_t orientation);
+ void rotate(ui::Rotation orientation);
private:
uint32_t mHeight;
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
index 6a25db2..2a00736 100644
--- a/libs/binder/ndk/include_cpp/android/binder_to_string.h
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -160,7 +160,7 @@
template <typename _T>
std::string ToString(const _T& t) {
if constexpr (details::ToEmptyString<_T>::value) {
- return "";
+ return "<unimplemented>";
} else if constexpr (std::is_same_v<bool, _T>) {
return t ? "true" : "false";
} else if constexpr (std::is_same_v<char16_t, _T>) {
@@ -176,9 +176,11 @@
return t;
#ifdef HAS_NDK_INTERFACE
} else if constexpr (std::is_same_v<::ndk::SpAIBinder, _T>) {
- return (t.get() == nullptr) ? "(null)" : "";
+ std::stringstream ss;
+ ss << "binder:" << std::hex << t.get();
+ return ss.str();
} else if constexpr (std::is_same_v<::ndk::ScopedFileDescriptor, _T>) {
- return (t.get() == -1) ? "(null)" : "";
+ return "fd:" + std::to_string(t.get());
#endif
#ifdef HAS_STRING16
} else if constexpr (std::is_same_v<String16, _T>) {
diff --git a/libs/binder/rust/tests/parcel_fuzzer/read_utils.rs b/libs/binder/rust/tests/parcel_fuzzer/read_utils.rs
index d2bfde1..a2d48b6 100644
--- a/libs/binder/rust/tests/parcel_fuzzer/read_utils.rs
+++ b/libs/binder/rust/tests/parcel_fuzzer/read_utils.rs
@@ -16,9 +16,9 @@
use binder::binder_impl::BorrowedParcel;
use binder::{ParcelFileDescriptor, Parcelable, SpIBinder};
-use binderReadParcelIface::aidl::EmptyParcelable::EmptyParcelable;
-use binderReadParcelIface::aidl::GenericDataParcelable::GenericDataParcelable;
-use binderReadParcelIface::aidl::SingleDataParcelable::SingleDataParcelable;
+use binderReadParcelIface::aidl::parcelables::EmptyParcelable::EmptyParcelable;
+use binderReadParcelIface::aidl::parcelables::GenericDataParcelable::GenericDataParcelable;
+use binderReadParcelIface::aidl::parcelables::SingleDataParcelable::SingleDataParcelable;
macro_rules! read_parcel_interface {
($data_type:ty) => {
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index 61a2412..35866ad 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -12,13 +12,14 @@
host_supported: true,
unstable: true,
srcs: [
- "EmptyParcelable.aidl",
- "SingleDataParcelable.aidl",
- "GenericDataParcelable.aidl",
+ "parcelables/EmptyParcelable.aidl",
+ "parcelables/SingleDataParcelable.aidl",
+ "parcelables/GenericDataParcelable.aidl",
],
backend: {
java: {
- enabled: false,
+ enabled: true,
+ platform_apis: true,
},
rust: {
enabled: true,
diff --git a/libs/binder/tests/parcel_fuzzer/EmptyParcelable.aidl b/libs/binder/tests/parcel_fuzzer/EmptyParcelable.aidl
deleted file mode 100644
index 96d6223..0000000
--- a/libs/binder/tests/parcel_fuzzer/EmptyParcelable.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-parcelable EmptyParcelable{
-}
\ No newline at end of file
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 9dac2c9..768fbe1 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -16,9 +16,9 @@
#define FUZZ_LOG_TAG "binder"
#include "binder.h"
-#include "EmptyParcelable.h"
-#include "GenericDataParcelable.h"
-#include "SingleDataParcelable.h"
+#include "parcelables/EmptyParcelable.h"
+#include "parcelables/GenericDataParcelable.h"
+#include "parcelables/SingleDataParcelable.h"
#include "util.h"
#include <android-base/hex.h>
@@ -359,19 +359,19 @@
},
[] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to call readFromParcel() with status for EmptyParcelable";
- EmptyParcelable emptyParcelable{};
+ parcelables::EmptyParcelable emptyParcelable{};
status_t status = emptyParcelable.readFromParcel(&p);
FUZZ_LOG() << " status: " << status;
},
[] (const ::android::Parcel& p , FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to call readFromParcel() with status for SingleDataParcelable";
- SingleDataParcelable singleDataParcelable;
+ parcelables::SingleDataParcelable singleDataParcelable;
status_t status = singleDataParcelable.readFromParcel(&p);
FUZZ_LOG() <<" status: " << status;
},
[] (const ::android::Parcel& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to call readFromParcel() with status for GenericDataParcelable";
- GenericDataParcelable genericDataParcelable;
+ parcelables::GenericDataParcelable genericDataParcelable;
status_t status = genericDataParcelable.readFromParcel(&p);
FUZZ_LOG() <<" status: " << status;
},
diff --git a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
index af773a0..53e7de4 100644
--- a/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
@@ -16,9 +16,9 @@
#define FUZZ_LOG_TAG "binder_ndk"
#include "binder_ndk.h"
-#include "aidl/EmptyParcelable.h"
-#include "aidl/GenericDataParcelable.h"
-#include "aidl/SingleDataParcelable.h"
+#include "aidl/parcelables/EmptyParcelable.h"
+#include "aidl/parcelables/GenericDataParcelable.h"
+#include "aidl/parcelables/SingleDataParcelable.h"
#include <android/binder_parcel_utils.h>
#include <android/binder_parcelable_utils.h>
@@ -183,19 +183,19 @@
[](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read parcel using readFromParcel for EmptyParcelable";
- aidl::EmptyParcelable emptyParcelable;
+ aidl::parcelables::EmptyParcelable emptyParcelable;
binder_status_t status = emptyParcelable.readFromParcel(p.aParcel());
FUZZ_LOG() << "status: " << status;
},
[](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read parcel using readFromParcel for SingleDataParcelable";
- aidl::SingleDataParcelable singleDataParcelable;
+ aidl::parcelables::SingleDataParcelable singleDataParcelable;
binder_status_t status = singleDataParcelable.readFromParcel(p.aParcel());
FUZZ_LOG() << "status: " << status;
},
[](const NdkParcelAdapter& p, FuzzedDataProvider& /*provider*/) {
FUZZ_LOG() << "about to read parcel using readFromParcel for GenericDataParcelable";
- aidl::GenericDataParcelable genericDataParcelable;
+ aidl::parcelables::GenericDataParcelable genericDataParcelable;
binder_status_t status = genericDataParcelable.readFromParcel(p.aParcel());
FUZZ_LOG() << "status: " << status;
},
diff --git a/libs/binder/tests/parcel_fuzzer/SingleDataParcelable.aidl b/libs/binder/tests/parcel_fuzzer/parcelables/EmptyParcelable.aidl
similarity index 92%
copy from libs/binder/tests/parcel_fuzzer/SingleDataParcelable.aidl
copy to libs/binder/tests/parcel_fuzzer/parcelables/EmptyParcelable.aidl
index d62891b..1216250 100644
--- a/libs/binder/tests/parcel_fuzzer/SingleDataParcelable.aidl
+++ b/libs/binder/tests/parcel_fuzzer/parcelables/EmptyParcelable.aidl
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-parcelable SingleDataParcelable{
- int data;
+package parcelables;
+parcelable EmptyParcelable {
}
\ No newline at end of file
diff --git a/libs/binder/tests/parcel_fuzzer/GenericDataParcelable.aidl b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
similarity index 97%
rename from libs/binder/tests/parcel_fuzzer/GenericDataParcelable.aidl
rename to libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
index fc2542b..f1079e9 100644
--- a/libs/binder/tests/parcel_fuzzer/GenericDataParcelable.aidl
+++ b/libs/binder/tests/parcel_fuzzer/parcelables/GenericDataParcelable.aidl
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package parcelables;
parcelable GenericDataParcelable {
int data;
diff --git a/libs/binder/tests/parcel_fuzzer/SingleDataParcelable.aidl b/libs/binder/tests/parcel_fuzzer/parcelables/SingleDataParcelable.aidl
similarity index 96%
rename from libs/binder/tests/parcel_fuzzer/SingleDataParcelable.aidl
rename to libs/binder/tests/parcel_fuzzer/parcelables/SingleDataParcelable.aidl
index d62891b..0187168 100644
--- a/libs/binder/tests/parcel_fuzzer/SingleDataParcelable.aidl
+++ b/libs/binder/tests/parcel_fuzzer/parcelables/SingleDataParcelable.aidl
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package parcelables;
parcelable SingleDataParcelable{
int data;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1e43700..aaa2102 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2330,6 +2330,9 @@
outMode.sfVsyncOffset = mode.sfVsyncOffset;
outMode.presentationDeadline = mode.presentationDeadline;
outMode.group = mode.group;
+ std::transform(mode.supportedHdrTypes.begin(), mode.supportedHdrTypes.end(),
+ std::back_inserter(outMode.supportedHdrTypes),
+ [](const int32_t& value) { return static_cast<ui::Hdr>(value); });
outInfo->supportedDisplayModes.push_back(outMode);
}
diff --git a/libs/gui/aidl/android/gui/DisplayMode.aidl b/libs/gui/aidl/android/gui/DisplayMode.aidl
index 3cd77f8..ce30426 100644
--- a/libs/gui/aidl/android/gui/DisplayMode.aidl
+++ b/libs/gui/aidl/android/gui/DisplayMode.aidl
@@ -27,6 +27,7 @@
Size resolution;
float xDpi = 0.0f;
float yDpi = 0.0f;
+ int[] supportedHdrTypes;
float refreshRate = 0.0f;
long appVsyncOffset = 0;
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 3685f54..9e8ebf3 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -21,6 +21,7 @@
#include <cutils/compiler.h>
#include <inttypes.h>
#include <string.h>
+#include <optional>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -552,21 +553,21 @@
&pointerCoords[getPointerCount()]);
}
-int MotionEvent::getSurfaceRotation() const {
+std::optional<ui::Rotation> MotionEvent::getSurfaceRotation() const {
// The surface rotation is the rotation from the window's coordinate space to that of the
// display. Since the event's transform takes display space coordinates to window space, the
// returned surface rotation is the inverse of the rotation for the surface.
switch (mTransform.getOrientation()) {
case ui::Transform::ROT_0:
- return DISPLAY_ORIENTATION_0;
+ return ui::ROTATION_0;
case ui::Transform::ROT_90:
- return DISPLAY_ORIENTATION_270;
+ return ui::ROTATION_270;
case ui::Transform::ROT_180:
- return DISPLAY_ORIENTATION_180;
+ return ui::ROTATION_180;
case ui::Transform::ROT_270:
- return DISPLAY_ORIENTATION_90;
+ return ui::ROTATION_90;
default:
- return -1;
+ return std::nullopt;
}
}
diff --git a/libs/input/TouchVideoFrame.cpp b/libs/input/TouchVideoFrame.cpp
index c62e098..c9393f4 100644
--- a/libs/input/TouchVideoFrame.cpp
+++ b/libs/input/TouchVideoFrame.cpp
@@ -40,17 +40,20 @@
const struct timeval& TouchVideoFrame::getTimestamp() const { return mTimestamp; }
-void TouchVideoFrame::rotate(int32_t orientation) {
+void TouchVideoFrame::rotate(ui::Rotation orientation) {
switch (orientation) {
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
rotateQuarterTurn(false /*clockwise*/);
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
rotate180();
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
rotateQuarterTurn(true /*clockwise*/);
break;
+ case ui::ROTATION_0:
+ // No need to rotate if there's no rotation.
+ break;
}
}
diff --git a/libs/input/tests/TouchVideoFrame_test.cpp b/libs/input/tests/TouchVideoFrame_test.cpp
index 654b236..081a995 100644
--- a/libs/input/tests/TouchVideoFrame_test.cpp
+++ b/libs/input/tests/TouchVideoFrame_test.cpp
@@ -73,38 +73,38 @@
TEST(TouchVideoFrame, Rotate90_0x0) {
TouchVideoFrame frame(0, 0, {}, TIMESTAMP);
TouchVideoFrame frameRotated(0, 0, {}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_90);
+ frame.rotate(ui::ROTATION_90);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate90_1x1) {
TouchVideoFrame frame(1, 1, {1}, TIMESTAMP);
TouchVideoFrame frameRotated(1, 1, {1}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_90);
+ frame.rotate(ui::ROTATION_90);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate90_2x2) {
TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
TouchVideoFrame frameRotated(2, 2, {2, 4, 1, 3}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_90);
+ frame.rotate(ui::ROTATION_90);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate90_3x2) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
TouchVideoFrame frameRotated(2, 3, {2, 4, 6, 1, 3, 5}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_90);
+ frame.rotate(ui::ROTATION_90);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate90_3x2_4times) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
TouchVideoFrame frameOriginal(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_90);
- frame.rotate(DISPLAY_ORIENTATION_90);
- frame.rotate(DISPLAY_ORIENTATION_90);
- frame.rotate(DISPLAY_ORIENTATION_90);
+ frame.rotate(ui::ROTATION_90);
+ frame.rotate(ui::ROTATION_90);
+ frame.rotate(ui::ROTATION_90);
+ frame.rotate(ui::ROTATION_90);
ASSERT_EQ(frame, frameOriginal);
}
@@ -113,43 +113,43 @@
TEST(TouchVideoFrame, Rotate180_0x0) {
TouchVideoFrame frame(0, 0, {}, TIMESTAMP);
TouchVideoFrame frameRotated(0, 0, {}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_180);
+ frame.rotate(ui::ROTATION_180);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate180_1x1) {
TouchVideoFrame frame(1, 1, {1}, TIMESTAMP);
TouchVideoFrame frameRotated(1, 1, {1}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_180);
+ frame.rotate(ui::ROTATION_180);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate180_2x2) {
TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
TouchVideoFrame frameRotated(2, 2, {4, 3, 2, 1}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_180);
+ frame.rotate(ui::ROTATION_180);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate180_3x2) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
TouchVideoFrame frameRotated(3, 2, {6, 5, 4, 3, 2, 1}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_180);
+ frame.rotate(ui::ROTATION_180);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate180_3x2_2times) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
TouchVideoFrame frameOriginal(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_180);
- frame.rotate(DISPLAY_ORIENTATION_180);
+ frame.rotate(ui::ROTATION_180);
+ frame.rotate(ui::ROTATION_180);
ASSERT_EQ(frame, frameOriginal);
}
TEST(TouchVideoFrame, Rotate180_3x3) {
TouchVideoFrame frame(3, 3, {1, 2, 3, 4, 5, 6, 7, 8, 9}, TIMESTAMP);
TouchVideoFrame frameRotated(3, 3, {9, 8, 7, 6, 5, 4, 3, 2, 1}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_180);
+ frame.rotate(ui::ROTATION_180);
ASSERT_EQ(frame, frameRotated);
}
@@ -158,38 +158,38 @@
TEST(TouchVideoFrame, Rotate270_0x0) {
TouchVideoFrame frame(0, 0, {}, TIMESTAMP);
TouchVideoFrame frameRotated(0, 0, {}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_270);
+ frame.rotate(ui::ROTATION_270);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate270_1x1) {
TouchVideoFrame frame(1, 1, {1}, TIMESTAMP);
TouchVideoFrame frameRotated(1, 1, {1}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_270);
+ frame.rotate(ui::ROTATION_270);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate270_2x2) {
TouchVideoFrame frame(2, 2, {1, 2, 3, 4}, TIMESTAMP);
TouchVideoFrame frameRotated(2, 2, {3, 1, 4, 2}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_270);
+ frame.rotate(ui::ROTATION_270);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate270_3x2) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
TouchVideoFrame frameRotated(2, 3, {5, 3, 1, 6, 4, 2}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_270);
+ frame.rotate(ui::ROTATION_270);
ASSERT_EQ(frame, frameRotated);
}
TEST(TouchVideoFrame, Rotate270_3x2_4times) {
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
TouchVideoFrame frameOriginal(3, 2, {1, 2, 3, 4, 5, 6}, TIMESTAMP);
- frame.rotate(DISPLAY_ORIENTATION_270);
- frame.rotate(DISPLAY_ORIENTATION_270);
- frame.rotate(DISPLAY_ORIENTATION_270);
- frame.rotate(DISPLAY_ORIENTATION_270);
+ frame.rotate(ui::ROTATION_270);
+ frame.rotate(ui::ROTATION_270);
+ frame.rotate(ui::ROTATION_270);
+ frame.rotate(ui::ROTATION_270);
ASSERT_EQ(frame, frameOriginal);
}
diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h
index a2791a6..65a8769 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -19,6 +19,7 @@
#include <cstdint>
#include <type_traits>
+#include <ui/GraphicTypes.h>
#include <ui/Size.h>
#include <utils/Flattenable.h>
#include <utils/Timers.h>
@@ -34,6 +35,7 @@
ui::Size resolution;
float xDpi = 0;
float yDpi = 0;
+ std::vector<ui::Hdr> supportedHdrTypes;
float refreshRate = 0;
nsecs_t appVsyncOffset = 0;
diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h
index 8661c36..1775d39 100644
--- a/libs/ui/include/ui/GraphicTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -20,6 +20,7 @@
#include <aidl/android/hardware/graphics/common/ChromaSiting.h>
#include <aidl/android/hardware/graphics/common/Compression.h>
#include <aidl/android/hardware/graphics/common/Cta861_3.h>
+#include <aidl/android/hardware/graphics/common/Hdr.h>
#include <aidl/android/hardware/graphics/common/Interlaced.h>
#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
#include <aidl/android/hardware/graphics/common/Smpte2086.h>
@@ -42,7 +43,6 @@
using android::hardware::graphics::common::V1_1::RenderIntent;
using android::hardware::graphics::common::V1_2::ColorMode;
using android::hardware::graphics::common::V1_2::Dataspace;
-using android::hardware::graphics::common::V1_2::Hdr;
using android::hardware::graphics::common::V1_2::PixelFormat;
/**
@@ -50,6 +50,7 @@
*/
using aidl::android::hardware::graphics::common::BlendMode;
using aidl::android::hardware::graphics::common::Cta861_3;
+using aidl::android::hardware::graphics::common::Hdr;
using aidl::android::hardware::graphics::common::PlaneLayout;
using aidl::android::hardware::graphics::common::Smpte2086;
diff --git a/libs/ui/include/ui/Rotation.h b/libs/ui/include/ui/Rotation.h
index 83d431d..c1d60f4 100644
--- a/libs/ui/include/ui/Rotation.h
+++ b/libs/ui/include/ui/Rotation.h
@@ -20,7 +20,14 @@
namespace android::ui {
-enum class Rotation { Rotation0 = 0, Rotation90 = 1, Rotation180 = 2, Rotation270 = 3 };
+enum class Rotation {
+ Rotation0 = 0,
+ Rotation90 = 1,
+ Rotation180 = 2,
+ Rotation270 = 3,
+
+ ftl_last = Rotation270
+};
// Equivalent to Surface.java constants.
constexpr auto ROTATION_0 = Rotation::Rotation0;
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 3b0f2ac..6d6cefb 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -23,6 +23,7 @@
#include <input/VelocityControl.h>
#include <input/VelocityTracker.h>
#include <stddef.h>
+#include <ui/Rotation.h>
#include <unistd.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -395,7 +396,7 @@
/* Gets the affine calibration associated with the specified device. */
virtual TouchAffineTransformation getTouchAffineTransformation(
- const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
+ const std::string& inputDeviceDescriptor, ui::Rotation surfaceRotation) = 0;
/* Notifies the input reader policy that a stylus gesture has started. */
virtual void notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) = 0;
};
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 46e86de..f5ac8de 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -51,6 +51,7 @@
"mapper/SingleTouchInputMapper.cpp",
"mapper/SwitchInputMapper.cpp",
"mapper/TouchInputMapper.cpp",
+ "mapper/TouchpadInputMapper.cpp",
"mapper/VibratorInputMapper.cpp",
"mapper/accumulator/CursorButtonAccumulator.cpp",
"mapper/accumulator/CursorScrollAccumulator.cpp",
@@ -131,6 +132,7 @@
// This should consist only of dependencies from inputflinger. Other dependencies should be
// in cc_defaults so that they are included in the tests.
"libinputflinger_base",
+ "libjsoncpp",
],
export_header_lib_headers: [
"libinputreader_headers",
@@ -145,5 +147,6 @@
},
static_libs: [
"libc++fs",
+ "libchrome-gestures",
],
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 0aaef53..f2ea90c 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -2215,6 +2215,10 @@
// a touch screen.
if (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);
+ if (device->propBitmask.test(INPUT_PROP_POINTER) &&
+ !device->keyBitmask.any(BTN_TOOL_PEN, BTN_TOOL_FINGER) && !haveStylusButtons) {
+ device->classes |= InputDeviceClass::TOUCHPAD;
+ }
}
// Is this an old style single-touch driver?
} else if (device->keyBitmask.test(BTN_TOUCH) && device->absBitmask.test(ABS_X) &&
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index e6ab872..150a8aa 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -33,6 +33,7 @@
#include "SensorInputMapper.h"
#include "SingleTouchInputMapper.h"
#include "SwitchInputMapper.h"
+#include "TouchpadInputMapper.h"
#include "VibratorInputMapper.h"
using android::hardware::input::InputDeviceCountryCode;
@@ -208,7 +209,12 @@
}
// Touchscreens and touchpad devices.
- if (classes.test(InputDeviceClass::TOUCH_MT)) {
+ // TODO(b/251196347): replace this with a proper flag.
+ constexpr bool ENABLE_NEW_TOUCHPAD_STACK = false;
+ if (ENABLE_NEW_TOUCHPAD_STACK && classes.test(InputDeviceClass::TOUCHPAD) &&
+ classes.test(InputDeviceClass::TOUCH_MT)) {
+ mappers.push_back(std::make_unique<TouchpadInputMapper>(*contextPtr));
+ } else if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
} else if (classes.test(InputDeviceClass::TOUCH)) {
mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 8e5f15f..42ca482 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -94,7 +94,7 @@
/* The input device is a cursor device such as a trackball or mouse. */
CURSOR = 0x00000008,
- /* The input device is a multi-touch touchscreen. */
+ /* The input device is a multi-touch touchscreen or touchpad. */
TOUCH_MT = 0x00000010,
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
@@ -130,6 +130,9 @@
/* The input device has sysfs controllable lights */
LIGHT = 0x00008000,
+ /* The input device is a touchpad, requiring an on-screen cursor. */
+ TOUCHPAD = 0x00010000,
+
/* The input device is virtual (not a real device, not part of UI configuration). */
VIRTUAL = 0x40000000,
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index a1a2af9..13e4d0c 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -227,7 +227,7 @@
mDisplayId = mPointerController->getDisplayId();
}
- mOrientation = DISPLAY_ORIENTATION_0;
+ mOrientation = ui::ROTATION_0;
const bool isOrientedDevice =
(mParameters.orientationAware && mParameters.hasAssociatedDisplay);
// InputReader works in the un-rotated display coordinate space, so we don't need to do
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 20746e5..939cceb 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -22,6 +22,7 @@
#include <PointerControllerInterface.h>
#include <input/VelocityControl.h>
+#include <ui/Rotation.h>
namespace android {
@@ -115,7 +116,7 @@
// ADISPLAY_ID_NONE to target the focused display. If there is no display target (i.e.
// std::nullopt), all events will be ignored.
std::optional<int32_t> mDisplayId;
- int32_t mOrientation;
+ ui::Rotation mOrientation;
std::shared_ptr<PointerControllerInterface> mPointerController;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index da9413e..44f0dfe 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -20,11 +20,13 @@
#include "KeyboardInputMapper.h"
+#include <ui/Rotation.h>
+
namespace android {
// --- Static Definitions ---
-static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
+static int32_t rotateKeyCode(int32_t keyCode, ui::Rotation orientation) {
static constexpr int32_t KEYCODE_ROTATION_MAP[][4] = {
// key codes enumerated counter-clockwise with the original (unrotated) key first
// no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
@@ -42,11 +44,10 @@
AKEYCODE_SYSTEM_NAVIGATION_RIGHT, AKEYCODE_SYSTEM_NAVIGATION_UP},
};
- LOG_ALWAYS_FATAL_IF(orientation < 0 || orientation > 3, "Invalid orientation: %d", orientation);
- if (orientation != DISPLAY_ORIENTATION_0) {
+ if (orientation != ui::ROTATION_0) {
for (const auto& rotation : KEYCODE_ROTATION_MAP) {
- if (rotation[DISPLAY_ORIENTATION_0] == keyCode) {
- return rotation[orientation];
+ if (rotation[static_cast<size_t>(ui::ROTATION_0)] == keyCode) {
+ return rotation[static_cast<size_t>(orientation)];
}
}
}
@@ -100,11 +101,11 @@
return mSource;
}
-int32_t KeyboardInputMapper::getOrientation() {
+ui::Rotation KeyboardInputMapper::getOrientation() {
if (mViewport) {
return mViewport->orientation;
}
- return DISPLAY_ORIENTATION_0;
+ return ui::ROTATION_0;
}
int32_t KeyboardInputMapper::getDisplayId() {
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 11d5ad2..0526fd8 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -82,7 +82,7 @@
void configureParameters();
void dumpParameters(std::string& dump) const;
- int32_t getOrientation();
+ ui::Rotation getOrientation();
int32_t getDisplayId();
[[nodiscard]] std::list<NotifyArgs> processKey(nsecs_t when, nsecs_t readTime, bool down,
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index 06d4dc3..19a79d7 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -25,7 +25,7 @@
namespace android {
RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDeviceContext& deviceContext)
- : InputMapper(deviceContext), mOrientation(DISPLAY_ORIENTATION_0) {
+ : InputMapper(deviceContext), mOrientation(ui::ROTATION_0) {
mSource = AINPUT_SOURCE_ROTARY_ENCODER;
}
@@ -73,7 +73,7 @@
if (internalViewport) {
mOrientation = internalViewport->orientation;
} else {
- mOrientation = DISPLAY_ORIENTATION_0;
+ mOrientation = ui::ROTATION_0;
}
}
return out;
@@ -107,7 +107,7 @@
// This is not a pointer, so it's not associated with a display.
int32_t displayId = ADISPLAY_ID_NONE;
- if (mOrientation == DISPLAY_ORIENTATION_180) {
+ if (mOrientation == ui::ROTATION_180) {
scroll = -scroll;
}
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
index f4352e7..cb5fd88 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h
@@ -16,6 +16,8 @@
#pragma once
+#include <ui/Rotation.h>
+
#include "CursorScrollAccumulator.h"
#include "InputMapper.h"
@@ -40,7 +42,7 @@
int32_t mSource;
float mScalingFactor;
- int32_t mOrientation;
+ ui::Rotation mOrientation;
[[nodiscard]] std::list<NotifyArgs> sync(nsecs_t when, nsecs_t readTime);
};
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
index d8a4d34..1c3ca97 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -18,6 +18,7 @@
#include <input/DisplayViewport.h>
#include <stdint.h>
+#include <ui/Rotation.h>
#include "EventHub.h"
#include "InputListener.h"
@@ -27,32 +28,32 @@
// --- Static Definitions ---
-static int32_t getInverseRotation(int32_t orientation) {
+static ui::Rotation getInverseRotation(ui::Rotation orientation) {
switch (orientation) {
- case DISPLAY_ORIENTATION_90:
- return DISPLAY_ORIENTATION_270;
- case DISPLAY_ORIENTATION_270:
- return DISPLAY_ORIENTATION_90;
+ case ui::ROTATION_90:
+ return ui::ROTATION_270;
+ case ui::ROTATION_270:
+ return ui::ROTATION_90;
default:
return orientation;
}
}
-static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
+static void rotateDelta(ui::Rotation orientation, float* deltaX, float* deltaY) {
float temp;
switch (orientation) {
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
temp = *deltaX;
*deltaX = *deltaY;
*deltaY = -temp;
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
*deltaX = -*deltaX;
*deltaY = -*deltaY;
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
temp = *deltaX;
*deltaX = -*deltaY;
*deltaY = temp;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 5631a10..cefc44e 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -27,6 +27,7 @@
#include "CursorScrollAccumulator.h"
#include "TouchButtonAccumulator.h"
#include "TouchCursorInputMapperCommon.h"
+#include "ui/Rotation.h"
namespace android {
@@ -81,16 +82,14 @@
}
static std::tuple<ui::Size /*displayBounds*/, Rect /*physicalFrame*/> getNaturalDisplayInfo(
- const DisplayViewport& viewport, int32_t naturalOrientation) {
- const auto rotation = ui::toRotation(naturalOrientation);
-
+ const DisplayViewport& viewport, ui::Rotation naturalOrientation) {
ui::Size rotatedDisplaySize{viewport.deviceWidth, viewport.deviceHeight};
- if (rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270) {
+ if (naturalOrientation == ui::ROTATION_90 || naturalOrientation == ui::ROTATION_270) {
std::swap(rotatedDisplaySize.width, rotatedDisplaySize.height);
}
- ui::Transform rotate(ui::Transform::toRotationFlags(rotation), rotatedDisplaySize.width,
- rotatedDisplaySize.height);
+ ui::Transform rotate(ui::Transform::toRotationFlags(naturalOrientation),
+ rotatedDisplaySize.width, rotatedDisplaySize.height);
Rect physicalFrame{viewport.physicalLeft, viewport.physicalTop, viewport.physicalRight,
viewport.physicalBottom};
@@ -133,7 +132,7 @@
mTouchButtonAccumulator(deviceContext),
mSource(0),
mDeviceMode(DeviceMode::DISABLED),
- mInputDeviceOrientation(DISPLAY_ORIENTATION_0) {}
+ mInputDeviceOrientation(ui::ROTATION_0) {}
TouchInputMapper::~TouchInputMapper() {}
@@ -424,18 +423,18 @@
getDeviceContext().getConfiguration().tryGetProperty("touch.orientationAware",
mParameters.orientationAware);
- mParameters.orientation = Parameters::Orientation::ORIENTATION_0;
+ mParameters.orientation = ui::ROTATION_0;
std::string orientationString;
if (getDeviceContext().getConfiguration().tryGetProperty("touch.orientation",
orientationString)) {
if (mParameters.deviceType != Parameters::DeviceType::TOUCH_SCREEN) {
ALOGW("The configuration 'touch.orientation' is only supported for touchscreens.");
} else if (orientationString == "ORIENTATION_90") {
- mParameters.orientation = Parameters::Orientation::ORIENTATION_90;
+ mParameters.orientation = ui::ROTATION_90;
} else if (orientationString == "ORIENTATION_180") {
- mParameters.orientation = Parameters::Orientation::ORIENTATION_180;
+ mParameters.orientation = ui::ROTATION_180;
} else if (orientationString == "ORIENTATION_270") {
- mParameters.orientation = Parameters::Orientation::ORIENTATION_270;
+ mParameters.orientation = ui::ROTATION_270;
} else if (orientationString != "ORIENTATION_0") {
ALOGW("Invalid value for touch.orientation: '%s'", orientationString.c_str());
}
@@ -812,8 +811,8 @@
// Note that the maximum value reported is an inclusive maximum value so it is one
// unit less than the total width or height of the display.
switch (mInputDeviceOrientation) {
- case DISPLAY_ORIENTATION_90:
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_90:
+ case ui::ROTATION_270:
mOrientedXPrecision = mYPrecision;
mOrientedYPrecision = mXPrecision;
@@ -923,8 +922,8 @@
// Apply the inverse of the input device orientation so that the input device is
// configured in the same orientation as the viewport. The input device orientation will
// be re-applied by mInputDeviceOrientation.
- const int32_t naturalDeviceOrientation =
- (mViewport.orientation - static_cast<int32_t>(mParameters.orientation) + 4) % 4;
+ const ui::Rotation naturalDeviceOrientation =
+ mViewport.orientation - mParameters.orientation;
std::tie(mDisplayBounds, mPhysicalFrameInDisplay) =
getNaturalDisplayInfo(mViewport, naturalDeviceOrientation);
@@ -935,7 +934,7 @@
// when the display rotation is applied later as a part of the per-window transform, we
// get the expected screen coordinates.
mInputDeviceOrientation = mParameters.orientationAware
- ? DISPLAY_ORIENTATION_0
+ ? ui::ROTATION_0
: getInverseRotation(mViewport.orientation);
// For orientation-aware devices that work in the un-rotated coordinate space, the
// viewport update should be skipped if it is only a change in the orientation.
@@ -943,12 +942,11 @@
mDisplayBounds == oldDisplayBounds && viewportOrientationChanged;
// Apply the input device orientation for the device.
- mInputDeviceOrientation =
- (mInputDeviceOrientation + static_cast<int32_t>(mParameters.orientation)) % 4;
+ mInputDeviceOrientation = mInputDeviceOrientation + mParameters.orientation;
} else {
mDisplayBounds = rawSize;
mPhysicalFrameInDisplay = Rect{mDisplayBounds};
- mInputDeviceOrientation = DISPLAY_ORIENTATION_0;
+ mInputDeviceOrientation = ui::ROTATION_0;
}
}
@@ -2349,7 +2347,7 @@
float left, top, right, bottom;
switch (mInputDeviceOrientation) {
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale;
right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale;
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
@@ -2360,7 +2358,7 @@
(mOrientedRanges.orientation->max - mOrientedRanges.orientation->min);
}
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
@@ -2371,7 +2369,7 @@
(mOrientedRanges.orientation->max - mOrientedRanges.orientation->min);
}
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale;
@@ -3805,19 +3803,19 @@
// 180 - reverse x, y.
// 270 - swap x/y and reverse x.
switch (mInputDeviceOrientation) {
- case DISPLAY_ORIENTATION_0:
+ case ui::ROTATION_0:
x = xScaled;
y = yScaled;
break;
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
y = xScaledMax;
x = yScaled;
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
x = xScaledMax;
y = yScaledMax;
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
y = xScaled;
x = yScaledMax;
break;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 3962b2a..34ba625 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -17,6 +17,7 @@
#pragma once
#include <stdint.h>
+#include <ui/Rotation.h>
#include "CursorButtonAccumulator.h"
#include "CursorScrollAccumulator.h"
@@ -218,15 +219,7 @@
bool associatedDisplayIsExternal;
bool orientationAware;
- enum class Orientation : int32_t {
- ORIENTATION_0 = DISPLAY_ORIENTATION_0,
- ORIENTATION_90 = DISPLAY_ORIENTATION_90,
- ORIENTATION_180 = DISPLAY_ORIENTATION_180,
- ORIENTATION_270 = DISPLAY_ORIENTATION_270,
-
- ftl_last = ORIENTATION_270
- };
- Orientation orientation;
+ ui::Rotation orientation;
bool hasButtonUnderPad;
std::string uniqueDisplayId;
@@ -424,7 +417,7 @@
// The orientation of the input device relative to that of the display panel. It specifies
// the rotation of the input device coordinates required to produce the display panel
// orientation, so it will depend on whether the device is orientation aware.
- int32_t mInputDeviceOrientation;
+ ui::Rotation mInputDeviceOrientation;
// Translation and scaling factors, orientation-independent.
float mXScale;
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
new file mode 100644
index 0000000..8c5bce7
--- /dev/null
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2022 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 "../Macros.h"
+
+#include <log/log_main.h>
+#include <chrono>
+#include "TouchpadInputMapper.h"
+
+namespace android {
+
+namespace {
+
+short getMaxTouchCount(const InputDeviceContext& context) {
+ if (context.hasKeyCode(BTN_TOOL_QUINTTAP)) return 5;
+ if (context.hasKeyCode(BTN_TOOL_QUADTAP)) return 4;
+ if (context.hasKeyCode(BTN_TOOL_TRIPLETAP)) return 3;
+ if (context.hasKeyCode(BTN_TOOL_DOUBLETAP)) return 2;
+ if (context.hasKeyCode(BTN_TOOL_FINGER)) return 1;
+ return 0;
+}
+
+HardwareProperties createHardwareProperties(const InputDeviceContext& context) {
+ HardwareProperties props;
+ RawAbsoluteAxisInfo absMtPositionX;
+ context.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &absMtPositionX);
+ props.left = absMtPositionX.minValue;
+ props.right = absMtPositionX.maxValue;
+ props.res_x = absMtPositionX.resolution;
+
+ RawAbsoluteAxisInfo absMtPositionY;
+ context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &absMtPositionY);
+ props.top = absMtPositionY.minValue;
+ props.bottom = absMtPositionY.maxValue;
+ props.res_y = absMtPositionY.resolution;
+
+ RawAbsoluteAxisInfo absMtOrientation;
+ context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &absMtOrientation);
+ props.orientation_minimum = absMtOrientation.minValue;
+ props.orientation_maximum = absMtOrientation.maxValue;
+
+ RawAbsoluteAxisInfo absMtSlot;
+ context.getAbsoluteAxisInfo(ABS_MT_SLOT, &absMtSlot);
+ props.max_finger_cnt = absMtSlot.maxValue - absMtSlot.minValue + 1;
+ props.max_touch_cnt = getMaxTouchCount(context);
+
+ // T5R2 ("Track 5, Report 2") is a feature of some old Synaptics touchpads that could track 5
+ // fingers but only report the coordinates of 2 of them. We don't know of any external touchpads
+ // that did this, so assume false.
+ props.supports_t5r2 = false;
+
+ props.support_semi_mt = context.hasInputProperty(INPUT_PROP_SEMI_MT);
+ props.is_button_pad = context.hasInputProperty(INPUT_PROP_BUTTONPAD);
+
+ // Mouse-only properties, which will always be false.
+ props.has_wheel = false;
+ props.wheel_is_hi_res = false;
+
+ // Linux Kernel haptic touchpad support isn't merged yet, so for now assume that no touchpads
+ // are haptic.
+ props.is_haptic_pad = false;
+ return props;
+}
+
+void gestureInterpreterCallback(void* clientData, const struct Gesture* gesture) {
+ // TODO(b/251196347): turn the gesture into a NotifyArgs and dispatch it.
+ ALOGD("Gesture ready: %s", gesture->String().c_str());
+}
+
+} // namespace
+
+TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext)
+ : InputMapper(deviceContext),
+ mGestureInterpreter(NewGestureInterpreter(), DeleteGestureInterpreter),
+ mTouchButtonAccumulator(deviceContext) {
+ mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD);
+ mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext));
+ mGestureInterpreter->SetCallback(gestureInterpreterCallback, nullptr);
+ // TODO(b/251196347): set a property provider, so we can change gesture properties.
+ // TODO(b/251196347): set a timer provider, so the library can use timers.
+
+ RawAbsoluteAxisInfo slotAxisInfo;
+ getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo);
+ if (!slotAxisInfo.valid || slotAxisInfo.maxValue <= 0) {
+ ALOGW("Touchpad \"%s\" doesn't have a valid ABS_MT_SLOT axis, and probably won't work "
+ "properly.",
+ getDeviceName().c_str());
+ }
+ mMotionAccumulator.configure(getDeviceContext(), slotAxisInfo.maxValue + 1, true);
+ mTouchButtonAccumulator.configure();
+}
+
+uint32_t TouchpadInputMapper::getSources() const {
+ return AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_TOUCHPAD;
+}
+
+std::list<NotifyArgs> TouchpadInputMapper::reset(nsecs_t when) {
+ mCursorButtonAccumulator.reset(getDeviceContext());
+ mTouchButtonAccumulator.reset();
+ mMscTimestamp = 0;
+ return InputMapper::reset(when);
+}
+
+std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent* rawEvent) {
+ if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+ sync(rawEvent->when);
+ }
+ if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
+ mMscTimestamp = rawEvent->value;
+ }
+ mCursorButtonAccumulator.process(rawEvent);
+ mMotionAccumulator.process(rawEvent);
+ mTouchButtonAccumulator.process(rawEvent);
+ return {};
+}
+
+void TouchpadInputMapper::sync(nsecs_t when) {
+ HardwareState hwState;
+ // The gestures library uses doubles to represent timestamps in seconds.
+ hwState.timestamp = std::chrono::duration<stime_t>(std::chrono::nanoseconds(when)).count();
+ hwState.msc_timestamp =
+ std::chrono::duration<stime_t>(std::chrono::microseconds(mMscTimestamp)).count();
+
+ hwState.buttons_down = 0;
+ if (mCursorButtonAccumulator.isLeftPressed()) {
+ hwState.buttons_down |= GESTURES_BUTTON_LEFT;
+ }
+ if (mCursorButtonAccumulator.isMiddlePressed()) {
+ hwState.buttons_down |= GESTURES_BUTTON_MIDDLE;
+ }
+ if (mCursorButtonAccumulator.isRightPressed()) {
+ hwState.buttons_down |= GESTURES_BUTTON_RIGHT;
+ }
+ if (mCursorButtonAccumulator.isBackPressed() || mCursorButtonAccumulator.isSidePressed()) {
+ hwState.buttons_down |= GESTURES_BUTTON_BACK;
+ }
+ if (mCursorButtonAccumulator.isForwardPressed() || mCursorButtonAccumulator.isExtraPressed()) {
+ hwState.buttons_down |= GESTURES_BUTTON_FORWARD;
+ }
+
+ std::vector<FingerState> fingers;
+ for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) {
+ MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i);
+ if (slot.isInUse()) {
+ FingerState& fingerState = fingers.emplace_back();
+ fingerState = {};
+ fingerState.touch_major = slot.getTouchMajor();
+ fingerState.touch_minor = slot.getTouchMinor();
+ fingerState.width_major = slot.getToolMajor();
+ fingerState.width_minor = slot.getToolMinor();
+ fingerState.pressure = slot.getPressure();
+ fingerState.orientation = slot.getOrientation();
+ fingerState.position_x = slot.getX();
+ fingerState.position_y = slot.getY();
+ fingerState.tracking_id = slot.getTrackingId();
+ }
+ }
+ hwState.fingers = fingers.data();
+ hwState.finger_cnt = fingers.size();
+ hwState.touch_cnt = mTouchButtonAccumulator.getTouchCount();
+
+ mGestureInterpreter->PushHardwareState(&hwState);
+ mMotionAccumulator.finishSync();
+ mMscTimestamp = 0;
+}
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
new file mode 100644
index 0000000..9d3a4b3
--- /dev/null
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "EventHub.h"
+#include "InputDevice.h"
+#include "InputMapper.h"
+#include "NotifyArgs.h"
+#include "accumulator/CursorButtonAccumulator.h"
+#include "accumulator/MultiTouchMotionAccumulator.h"
+#include "accumulator/TouchButtonAccumulator.h"
+
+#include "include/gestures.h"
+
+namespace android {
+
+class TouchpadInputMapper : public InputMapper {
+public:
+ explicit TouchpadInputMapper(InputDeviceContext& deviceContext);
+
+ uint32_t getSources() const override;
+ [[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
+ [[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+
+private:
+ void sync(nsecs_t when);
+
+ std::unique_ptr<gestures::GestureInterpreter, void (*)(gestures::GestureInterpreter*)>
+ mGestureInterpreter;
+
+ CursorButtonAccumulator mCursorButtonAccumulator;
+ MultiTouchMotionAccumulator mMotionAccumulator;
+ TouchButtonAccumulator mTouchButtonAccumulator;
+ int32_t mMscTimestamp = 0;
+};
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
index ed4c789..1380604 100644
--- a/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/CursorButtonAccumulator.h
@@ -32,6 +32,14 @@
void process(const RawEvent* rawEvent);
uint32_t getButtonState() const;
+ inline bool isLeftPressed() const { return mBtnLeft; }
+ inline bool isRightPressed() const { return mBtnRight; }
+ inline bool isMiddlePressed() const { return mBtnMiddle; }
+ inline bool isBackPressed() const { return mBtnBack; }
+ inline bool isSidePressed() const { return mBtnSide; }
+ inline bool isForwardPressed() const { return mBtnForward; }
+ inline bool isExtraPressed() const { return mBtnExtra; }
+ inline bool isTaskPressed() const { return mBtnTask; }
private:
bool mBtnLeft;
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
index bc23a8e..6601702 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.cpp
@@ -48,6 +48,7 @@
mBtnToolDoubleTap = mDeviceContext.isKeyPressed(BTN_TOOL_DOUBLETAP);
mBtnToolTripleTap = mDeviceContext.isKeyPressed(BTN_TOOL_TRIPLETAP);
mBtnToolQuadTap = mDeviceContext.isKeyPressed(BTN_TOOL_QUADTAP);
+ mBtnToolQuintTap = mDeviceContext.isKeyPressed(BTN_TOOL_QUINTTAP);
mHidUsageAccumulator.reset();
}
@@ -100,6 +101,9 @@
case BTN_TOOL_QUADTAP:
mBtnToolQuadTap = rawEvent->value;
break;
+ case BTN_TOOL_QUINTTAP:
+ mBtnToolQuintTap = rawEvent->value;
+ break;
default:
processMappedKey(rawEvent->code, rawEvent->value);
}
@@ -147,7 +151,8 @@
if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
return AMOTION_EVENT_TOOL_TYPE_STYLUS;
}
- if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
+ if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap ||
+ mBtnToolQuintTap) {
return AMOTION_EVENT_TOOL_TYPE_FINGER;
}
return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
@@ -156,7 +161,7 @@
bool TouchButtonAccumulator::isToolActive() const {
return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber || mBtnToolBrush ||
mBtnToolPencil || mBtnToolAirbrush || mBtnToolMouse || mBtnToolLens ||
- mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
+ mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap || mBtnToolQuintTap;
}
bool TouchButtonAccumulator::isHovering() const {
@@ -171,4 +176,15 @@
return mHaveBtnTouch;
}
+int TouchButtonAccumulator::getTouchCount() const {
+ if (mBtnTouch) {
+ if (mBtnToolQuintTap) return 5;
+ if (mBtnToolQuadTap) return 4;
+ if (mBtnToolTripleTap) return 3;
+ if (mBtnToolDoubleTap) return 2;
+ if (mBtnToolFinger) return 1;
+ }
+ return 0;
+}
+
} // namespace android
diff --git a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
index c2de23c..2e70e2e 100644
--- a/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
+++ b/services/inputflinger/reader/mapper/accumulator/TouchButtonAccumulator.h
@@ -41,6 +41,7 @@
bool isHovering() const;
bool hasStylus() const;
bool hasButtonTouch() const;
+ int getTouchCount() const;
private:
bool mHaveBtnTouch{};
@@ -60,6 +61,7 @@
bool mBtnToolDoubleTap{};
bool mBtnToolTripleTap{};
bool mBtnToolQuadTap{};
+ bool mBtnToolQuintTap{};
HidUsageAccumulator mHidUsageAccumulator{};
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 2e5bec9..53d821f 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -44,10 +44,12 @@
"FakeInputReaderPolicy.cpp",
"FakePointerController.cpp",
"FocusResolver_test.cpp",
+ "InputMapperTest.cpp",
"InputProcessor_test.cpp",
"InputProcessorConverter_test.cpp",
"InputDispatcher_test.cpp",
"InputReader_test.cpp",
+ "InstrumentedInputReader.cpp",
"LatencyTracker_test.cpp",
"NotifyArgs_test.cpp",
"PreferStylusOverTouch_test.cpp",
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
index 5c6a1b8..3af4298 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp
@@ -20,6 +20,7 @@
#include <gtest/gtest.h>
#include "TestConstants.h"
+#include "ui/Rotation.h"
namespace android {
@@ -76,12 +77,11 @@
}
void FakeInputReaderPolicy::addDisplayViewport(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, bool isActive,
+ ui::Rotation orientation, bool isActive,
const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
ViewportType type) {
- const bool isRotated =
- (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
+ const bool isRotated = orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270;
DisplayViewport v;
v.displayId = displayId;
v.orientation = orientation;
@@ -153,7 +153,7 @@
}
TouchAffineTransformation FakeInputReaderPolicy::getTouchAffineTransformation(
- const std::string& inputDeviceDescriptor, int32_t surfaceRotation) {
+ const std::string& inputDeviceDescriptor, ui::Rotation surfaceRotation) {
return transform;
}
diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.h b/services/inputflinger/tests/FakeInputReaderPolicy.h
index 65fe08f..c16cda4 100644
--- a/services/inputflinger/tests/FakeInputReaderPolicy.h
+++ b/services/inputflinger/tests/FakeInputReaderPolicy.h
@@ -49,8 +49,8 @@
std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const;
void addDisplayViewport(DisplayViewport viewport);
- void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
- bool isActive, const std::string& uniqueId,
+ void addDisplayViewport(int32_t displayId, int32_t width, int32_t height,
+ ui::Rotation orientation, bool isActive, const std::string& uniqueId,
std::optional<uint8_t> physicalPort, ViewportType type);
bool updateViewport(const DisplayViewport& viewport);
void addExcludedDeviceName(const std::string& deviceName);
@@ -63,7 +63,7 @@
const InputReaderConfiguration* getReaderConfiguration() const;
const std::vector<InputDeviceInfo>& getInputDevices() const;
TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
- int32_t surfaceRotation);
+ ui::Rotation surfaceRotation);
void setTouchAffineTransformation(const TouchAffineTransformation t);
PointerCaptureRequest setPointerCapture(bool enabled);
void setShowTouches(bool enabled);
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
new file mode 100644
index 0000000..3cd7c1b
--- /dev/null
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2022 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 "InputMapperTest.h"
+
+#include <InputReaderBase.h>
+#include <gtest/gtest.h>
+#include <ui/Rotation.h>
+
+namespace android {
+
+const char* InputMapperTest::DEVICE_NAME = "device";
+const char* InputMapperTest::DEVICE_LOCATION = "USB1";
+const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
+ ftl::Flags<InputDeviceClass>(0); // not needed for current tests
+
+void InputMapperTest::SetUp(ftl::Flags<InputDeviceClass> classes, int bus) {
+ mFakeEventHub = std::make_unique<FakeEventHub>();
+ mFakePolicy = sp<FakeInputReaderPolicy>::make();
+ mFakeListener = std::make_unique<TestInputListener>();
+ mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy, *mFakeListener);
+ mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes, bus);
+ // Consume the device reset notification generated when adding a new device.
+ mFakeListener->assertNotifyDeviceResetWasCalled();
+}
+
+void InputMapperTest::SetUp() {
+ SetUp(DEVICE_CLASSES);
+}
+
+void InputMapperTest::TearDown() {
+ mFakeListener.reset();
+ mFakePolicy.clear();
+}
+
+void InputMapperTest::addConfigurationProperty(const char* key, const char* value) {
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, key, value);
+}
+
+std::list<NotifyArgs> InputMapperTest::configureDevice(uint32_t changes) {
+ if (!changes ||
+ (changes &
+ (InputReaderConfiguration::CHANGE_DISPLAY_INFO |
+ InputReaderConfiguration::CHANGE_POINTER_CAPTURE))) {
+ mReader->requestRefreshConfiguration(changes);
+ mReader->loopOnce();
+ }
+ std::list<NotifyArgs> out =
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
+ // Loop the reader to flush the input listener queue.
+ for (const NotifyArgs& args : out) {
+ mFakeListener->notify(args);
+ }
+ mReader->loopOnce();
+ return out;
+}
+
+std::shared_ptr<InputDevice> InputMapperTest::newDevice(int32_t deviceId, const std::string& name,
+ const std::string& location,
+ int32_t eventHubId,
+ ftl::Flags<InputDeviceClass> classes,
+ int bus) {
+ InputDeviceIdentifier identifier;
+ identifier.name = name;
+ identifier.location = location;
+ identifier.bus = bus;
+ std::shared_ptr<InputDevice> device =
+ std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
+ identifier);
+ mReader->pushNextDevice(device);
+ mFakeEventHub->addDevice(eventHubId, name, classes, bus);
+ mReader->loopOnce();
+ return device;
+}
+
+void InputMapperTest::setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+ ui::Rotation orientation,
+ const std::string& uniqueId,
+ std::optional<uint8_t> physicalPort,
+ ViewportType viewportType) {
+ mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /* isActive= */ true,
+ uniqueId, physicalPort, viewportType);
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+}
+
+void InputMapperTest::clearViewports() {
+ mFakePolicy->clearViewports();
+}
+
+std::list<NotifyArgs> InputMapperTest::process(InputMapper& mapper, nsecs_t when, nsecs_t readTime,
+ int32_t type, int32_t code, int32_t value) {
+ RawEvent event;
+ event.when = when;
+ event.readTime = readTime;
+ event.deviceId = mapper.getDeviceContext().getEventHubId();
+ event.type = type;
+ event.code = code;
+ event.value = value;
+ std::list<NotifyArgs> processArgList = mapper.process(&event);
+ for (const NotifyArgs& args : processArgList) {
+ mFakeListener->notify(args);
+ }
+ // Loop the reader to flush the input listener queue.
+ mReader->loopOnce();
+ return processArgList;
+}
+
+void InputMapperTest::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();
+}
+
+std::list<NotifyArgs> InputMapperTest::handleTimeout(InputMapper& mapper, nsecs_t when) {
+ std::list<NotifyArgs> generatedArgs = mapper.timeoutExpired(when);
+ for (const NotifyArgs& args : generatedArgs) {
+ mFakeListener->notify(args);
+ }
+ // Loop the reader to flush the input listener queue.
+ mReader->loopOnce();
+ return generatedArgs;
+}
+
+void InputMapperTest::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);
+ ASSERT_TRUE(range != nullptr) << "Axis: " << axis << " Source: " << source;
+ ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source;
+ ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source;
+ ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source;
+ ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source;
+ ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source;
+ ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source;
+}
+
+void InputMapperTest::assertPointerCoords(const PointerCoords& coords, float x, float y,
+ float pressure, float size, float touchMajor,
+ float touchMinor, float toolMajor, float toolMinor,
+ float orientation, float distance,
+ float scaledAxisEpsilon) {
+ ASSERT_NEAR(x, coords.getAxisValue(AMOTION_EVENT_AXIS_X), scaledAxisEpsilon);
+ ASSERT_NEAR(y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y), scaledAxisEpsilon);
+ ASSERT_NEAR(pressure, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), EPSILON);
+ ASSERT_NEAR(size, coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE), EPSILON);
+ ASSERT_NEAR(touchMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), scaledAxisEpsilon);
+ ASSERT_NEAR(touchMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), scaledAxisEpsilon);
+ ASSERT_NEAR(toolMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), scaledAxisEpsilon);
+ ASSERT_NEAR(toolMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), scaledAxisEpsilon);
+ ASSERT_NEAR(orientation, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), EPSILON);
+ ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON);
+}
+
+void InputMapperTest::assertPosition(const FakePointerController& controller, float x, float y) {
+ float actualX, actualY;
+ controller.getPosition(&actualX, &actualY);
+ ASSERT_NEAR(x, actualX, 1);
+ ASSERT_NEAR(y, actualY, 1);
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h
new file mode 100644
index 0000000..b3401c3
--- /dev/null
+++ b/services/inputflinger/tests/InputMapperTest.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <list>
+#include <memory>
+
+#include <InputDevice.h>
+#include <InputMapper.h>
+#include <NotifyArgs.h>
+#include <ftl/flags.h>
+#include <utils/StrongPointer.h>
+
+#include "FakeEventHub.h"
+#include "FakeInputReaderPolicy.h"
+#include "InstrumentedInputReader.h"
+#include "TestConstants.h"
+#include "TestInputListener.h"
+
+namespace android {
+
+class InputMapperTest : public testing::Test {
+protected:
+ static const char* DEVICE_NAME;
+ static const char* DEVICE_LOCATION;
+ static constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
+ static constexpr int32_t DEVICE_GENERATION = 2;
+ static constexpr int32_t DEVICE_CONTROLLER_NUMBER = 0;
+ static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
+ static constexpr int32_t EVENTHUB_ID = 1;
+
+ std::shared_ptr<FakeEventHub> mFakeEventHub;
+ sp<FakeInputReaderPolicy> mFakePolicy;
+ std::unique_ptr<TestInputListener> mFakeListener;
+ std::unique_ptr<InstrumentedInputReader> mReader;
+ std::shared_ptr<InputDevice> mDevice;
+
+ virtual void SetUp(ftl::Flags<InputDeviceClass> classes, int bus = 0);
+ void SetUp() override;
+ void TearDown() override;
+
+ void addConfigurationProperty(const char* key, const char* value);
+ std::list<NotifyArgs> configureDevice(uint32_t changes);
+ std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+ const std::string& location, int32_t eventHubId,
+ ftl::Flags<InputDeviceClass> classes, int bus = 0);
+ template <class T, typename... Args>
+ T& addMapperAndConfigure(Args... args) {
+ T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
+ configureDevice(0);
+ std::list<NotifyArgs> resetArgList = mDevice->reset(ARBITRARY_TIME);
+ resetArgList += mapper.reset(ARBITRARY_TIME);
+ // Loop the reader to flush the input listener queue.
+ for (const NotifyArgs& loopArgs : resetArgList) {
+ mFakeListener->notify(loopArgs);
+ }
+ mReader->loopOnce();
+ return mapper;
+ }
+
+ void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
+ ui::Rotation orientation, const std::string& uniqueId,
+ std::optional<uint8_t> physicalPort,
+ ViewportType viewportType);
+ void clearViewports();
+ std::list<NotifyArgs> process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type,
+ int32_t code, int32_t value);
+ void resetMapper(InputMapper& mapper, nsecs_t when);
+
+ std::list<NotifyArgs> handleTimeout(InputMapper& mapper, nsecs_t when);
+
+ static void assertMotionRange(const InputDeviceInfo& info, int32_t axis, uint32_t source,
+ float min, float max, float flat, float fuzz);
+ static void assertPointerCoords(const PointerCoords& coords, float x, float y, float pressure,
+ float size, float touchMajor, float touchMinor, float toolMajor,
+ float toolMinor, float orientation, float distance,
+ float scaledAxisEpsilon = 1.f);
+ static void assertPosition(const FakePointerController& controller, float x, float y);
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index c72d01f..eef5690 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -36,13 +36,17 @@
#include <UinputDevice.h>
#include <VibratorInputMapper.h>
#include <android-base/thread_annotations.h>
+#include <ftl/enum.h>
#include <gtest/gtest.h>
#include <gui/constants.h>
+#include <ui/Rotation.h>
#include <thread>
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
#include "FakePointerController.h"
+#include "InputMapperTest.h"
+#include "InstrumentedInputReader.h"
#include "TestConstants.h"
#include "android/hardware/input/InputDeviceCountryCode.h"
#include "input/DisplayViewport.h"
@@ -89,9 +93,6 @@
static constexpr int32_t ACTION_POINTER_1_UP =
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
-// Error tolerance for floating point assertions.
-static const float EPSILON = 0.001f;
-
// Minimum timestamp separation between subsequent input events from a Bluetooth device.
static constexpr nsecs_t MIN_BLUETOOTH_TIMESTAMP_DELTA = ms2ns(4);
// Maximum smoothing time delta so that we don't generate events too far into the future.
@@ -111,12 +112,12 @@
{"green", LightColor::GREEN},
{"blue", LightColor::BLUE}};
-static int32_t getInverseRotation(int32_t orientation) {
+static ui::Rotation getInverseRotation(ui::Rotation orientation) {
switch (orientation) {
- case DISPLAY_ORIENTATION_90:
- return DISPLAY_ORIENTATION_270;
- case DISPLAY_ORIENTATION_270:
- return DISPLAY_ORIENTATION_90;
+ case ui::ROTATION_90:
+ return ui::ROTATION_270;
+ case ui::ROTATION_270:
+ return ui::ROTATION_90;
default:
return orientation;
}
@@ -343,117 +344,6 @@
}
};
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
- std::queue<std::shared_ptr<InputDevice>> mNextDevices;
-
-public:
- InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- InputListenerInterface& listener)
- : InputReader(eventHub, policy, listener), mFakeContext(this) {}
-
- virtual ~InstrumentedInputReader() {}
-
- void pushNextDevice(std::shared_ptr<InputDevice> device) { mNextDevices.push(device); }
-
- std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
- const std::string& location = "") {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- identifier.location = location;
- int32_t generation = deviceId + 1;
- return std::make_shared<InputDevice>(&mFakeContext, deviceId, generation, identifier);
- }
-
- // Make the protected loopOnce method accessible to tests.
- using InputReader::loopOnce;
-
-protected:
- virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t eventHubId,
- const InputDeviceIdentifier& identifier)
- REQUIRES(mLock) {
- if (!mNextDevices.empty()) {
- std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
- mNextDevices.pop();
- return device;
- }
- return InputReader::createDeviceLocked(eventHubId, identifier);
- }
-
- // --- FakeInputReaderContext ---
- class FakeInputReaderContext : public ContextImpl {
- int32_t mGlobalMetaState;
- bool mUpdateGlobalMetaStateWasCalled;
- int32_t mGeneration;
- std::optional<nsecs_t> mRequestedTimeout;
- std::vector<InputDeviceInfo> mExternalStylusDevices;
-
- public:
- FakeInputReaderContext(InputReader* reader)
- : ContextImpl(reader),
- mGlobalMetaState(0),
- mUpdateGlobalMetaStateWasCalled(false),
- mGeneration(1) {}
-
- virtual ~FakeInputReaderContext() {}
-
- void assertUpdateGlobalMetaStateWasCalled() {
- ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
- << "Expected updateGlobalMetaState() to have been called.";
- mUpdateGlobalMetaStateWasCalled = false;
- }
-
- void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
-
- uint32_t getGeneration() { return mGeneration; }
-
- void updateGlobalMetaState() override {
- mUpdateGlobalMetaStateWasCalled = true;
- ContextImpl::updateGlobalMetaState();
- }
-
- int32_t getGlobalMetaState() override {
- return mGlobalMetaState | ContextImpl::getGlobalMetaState();
- }
-
- int32_t bumpGeneration() override {
- mGeneration = ContextImpl::bumpGeneration();
- return mGeneration;
- }
-
- void requestTimeoutAtTime(nsecs_t when) override { mRequestedTimeout = when; }
-
- void assertTimeoutWasRequested(nsecs_t when) {
- ASSERT_TRUE(mRequestedTimeout) << "Expected timeout at time " << when
- << " but there was no timeout requested.";
- ASSERT_EQ(when, *mRequestedTimeout);
- mRequestedTimeout.reset();
- }
-
- void assertTimeoutWasNotRequested() {
- ASSERT_FALSE(mRequestedTimeout) << "Expected no timeout to have been requested,"
- " but one was requested at time "
- << *mRequestedTimeout;
- }
-
- void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {
- outDevices = mExternalStylusDevices;
- }
-
- void setExternalStylusDevices(std::vector<InputDeviceInfo>&& devices) {
- mExternalStylusDevices = devices;
- }
- } mFakeContext;
-
- friend class InputReaderTest;
-
-public:
- FakeInputReaderContext* getContext() { return &mFakeContext; }
-};
-
// --- InputReaderPolicyTest ---
class InputReaderPolicyTest : public testing::Test {
protected:
@@ -479,9 +369,8 @@
ASSERT_FALSE(internalViewport);
// Add an internal viewport, then clear it
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId, NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, uniqueId, NO_PORT, ViewportType::INTERNAL);
// Check matching by uniqueId
internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId);
@@ -510,21 +399,21 @@
constexpr int32_t virtualDisplayId2 = 3;
// Add an internal viewport
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, internalUniqueId,
- NO_PORT, ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, internalUniqueId, NO_PORT,
+ ViewportType::INTERNAL);
// Add an external viewport
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, externalUniqueId,
- NO_PORT, ViewportType::EXTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, externalUniqueId, NO_PORT,
+ ViewportType::EXTERNAL);
// Add an virtual viewport
mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, virtualUniqueId1,
- NO_PORT, ViewportType::VIRTUAL);
+ ui::ROTATION_0, true /*isActive*/, virtualUniqueId1, NO_PORT,
+ ViewportType::VIRTUAL);
// Add another virtual viewport
mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, virtualUniqueId2,
- NO_PORT, ViewportType::VIRTUAL);
+ ui::ROTATION_0, true /*isActive*/, virtualUniqueId2, NO_PORT,
+ ViewportType::VIRTUAL);
// Check matching by type for internal
std::optional<DisplayViewport> internalViewport =
@@ -572,13 +461,11 @@
for (const ViewportType& type : types) {
mFakePolicy->clearViewports();
// Add a viewport
- mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1,
- NO_PORT, type);
+ mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, uniqueId1, NO_PORT, type);
// Add another viewport
- mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2,
- NO_PORT, type);
+ mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, uniqueId2, NO_PORT, type);
// Check that correct display viewport was returned by comparing the display IDs.
std::optional<DisplayViewport> viewport1 =
@@ -618,10 +505,10 @@
// Add the default display first and ensure it gets returned.
mFakePolicy->clearViewports();
mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1, NO_PORT,
+ ui::ROTATION_0, true /*isActive*/, uniqueId1, NO_PORT,
ViewportType::INTERNAL);
mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2, NO_PORT,
+ ui::ROTATION_0, true /*isActive*/, uniqueId2, NO_PORT,
ViewportType::INTERNAL);
std::optional<DisplayViewport> viewport =
@@ -633,10 +520,10 @@
// Add the default display second to make sure order doesn't matter.
mFakePolicy->clearViewports();
mFakePolicy->addDisplayViewport(nonDefaultDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2, NO_PORT,
+ ui::ROTATION_0, true /*isActive*/, uniqueId2, NO_PORT,
ViewportType::INTERNAL);
mFakePolicy->addDisplayViewport(ADISPLAY_ID_DEFAULT, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1, NO_PORT,
+ ui::ROTATION_0, true /*isActive*/, uniqueId1, NO_PORT,
ViewportType::INTERNAL);
viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
@@ -660,13 +547,11 @@
mFakePolicy->clearViewports();
// Add a viewport that's associated with some display port that's not of interest.
- mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId1, hdmi3,
- type);
+ mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, uniqueId1, hdmi3, type);
// Add another viewport, connected to HDMI1 port
- mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, uniqueId2, hdmi1,
- type);
+ mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, uniqueId2, hdmi1, type);
// Check that correct display viewport was returned by comparing the display ports.
std::optional<DisplayViewport> hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1);
@@ -1119,11 +1004,10 @@
// Add default and second display.
mFakePolicy->clearViewports();
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, "local:0", NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, "local:0", NO_PORT, ViewportType::INTERNAL);
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, "local:1", hdmi1,
+ ui::ROTATION_0, true /*isActive*/, "local:1", hdmi1,
ViewportType::EXTERNAL);
mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
mReader->loopOnce();
@@ -1582,9 +1466,8 @@
#endif
InputReaderIntegrationTest::SetUp();
// At least add an internal display.
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, UNIQUE_ID, NO_PORT,
- ViewportType::INTERNAL);
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
mDevice = createUinputDevice<UinputTouchScreen>(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT));
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
@@ -1595,7 +1478,7 @@
}
void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const std::string& uniqueId,
+ ui::Rotation orientation, const std::string& uniqueId,
std::optional<uint8_t> physicalPort,
ViewportType viewportType) {
mFakePolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
@@ -2533,7 +2416,7 @@
// Prepare displays.
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, hdmi,
+ ui::ROTATION_0, true /*isActive*/, UNIQUE_ID, hdmi,
ViewportType::INTERNAL);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
@@ -2568,7 +2451,7 @@
// Device should be enabled when a display is found.
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
+ ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
NO_PORT, ViewportType::INTERNAL);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
@@ -2594,7 +2477,7 @@
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
+ ui::ROTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
NO_PORT, ViewportType::INTERNAL);
unused += mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
@@ -2622,194 +2505,6 @@
ASSERT_EQ(DEVICE_BLUETOOTH_ADDRESS, *address);
}
-// --- InputMapperTest ---
-
-class InputMapperTest : public testing::Test {
-protected:
- static const char* DEVICE_NAME;
- static const char* DEVICE_LOCATION;
- static const int32_t DEVICE_ID;
- static const int32_t DEVICE_GENERATION;
- static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
- static const int32_t EVENTHUB_ID;
-
- std::shared_ptr<FakeEventHub> mFakeEventHub;
- sp<FakeInputReaderPolicy> mFakePolicy;
- std::unique_ptr<TestInputListener> mFakeListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
- std::shared_ptr<InputDevice> mDevice;
-
- virtual void SetUp(ftl::Flags<InputDeviceClass> classes, int bus = 0) {
- mFakeEventHub = std::make_unique<FakeEventHub>();
- mFakePolicy = sp<FakeInputReaderPolicy>::make();
- mFakeListener = std::make_unique<TestInputListener>();
- mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
- *mFakeListener);
- mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes, bus);
- // Consume the device reset notification generated when adding a new device.
- mFakeListener->assertNotifyDeviceResetWasCalled();
- }
-
- void SetUp() override {
- SetUp(DEVICE_CLASSES);
- }
-
- void TearDown() override {
- mFakeListener.reset();
- mFakePolicy.clear();
- }
-
- void addConfigurationProperty(const char* key, const char* value) {
- mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, key, value);
- }
-
- std::list<NotifyArgs> configureDevice(uint32_t changes) {
- if (!changes ||
- (changes &
- (InputReaderConfiguration::CHANGE_DISPLAY_INFO |
- InputReaderConfiguration::CHANGE_POINTER_CAPTURE))) {
- mReader->requestRefreshConfiguration(changes);
- mReader->loopOnce();
- }
- std::list<NotifyArgs> out =
- mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
- // Loop the reader to flush the input listener queue.
- for (const NotifyArgs& args : out) {
- mFakeListener->notify(args);
- }
- mReader->loopOnce();
- return out;
- }
-
- std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
- const std::string& location, int32_t eventHubId,
- ftl::Flags<InputDeviceClass> classes, int bus = 0) {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- identifier.location = location;
- identifier.bus = bus;
- std::shared_ptr<InputDevice> device =
- std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
- identifier);
- mReader->pushNextDevice(device);
- mFakeEventHub->addDevice(eventHubId, name, classes, bus);
- mReader->loopOnce();
- return device;
- }
-
- template <class T, typename... Args>
- T& addMapperAndConfigure(Args... args) {
- T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
- configureDevice(0);
- std::list<NotifyArgs> resetArgList = mDevice->reset(ARBITRARY_TIME);
- resetArgList += mapper.reset(ARBITRARY_TIME);
- // Loop the reader to flush the input listener queue.
- for (const NotifyArgs& loopArgs : resetArgList) {
- mFakeListener->notify(loopArgs);
- }
- mReader->loopOnce();
- return mapper;
- }
-
- void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType viewportType) {
- mFakePolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
- uniqueId, physicalPort, viewportType);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- }
-
- void clearViewports() {
- mFakePolicy->clearViewports();
- }
-
- std::list<NotifyArgs> process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type,
- int32_t code, int32_t value) {
- RawEvent event;
- event.when = when;
- event.readTime = readTime;
- event.deviceId = mapper.getDeviceContext().getEventHubId();
- event.type = type;
- event.code = code;
- event.value = value;
- std::list<NotifyArgs> processArgList = mapper.process(&event);
- for (const NotifyArgs& args : processArgList) {
- mFakeListener->notify(args);
- }
- // Loop the reader to flush the input listener queue.
- mReader->loopOnce();
- 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();
- }
-
- std::list<NotifyArgs> handleTimeout(InputMapper& mapper, nsecs_t when) {
- std::list<NotifyArgs> generatedArgs = mapper.timeoutExpired(when);
- for (const NotifyArgs& args : generatedArgs) {
- mFakeListener->notify(args);
- }
- // Loop the reader to flush the input listener queue.
- mReader->loopOnce();
- return generatedArgs;
- }
-
- 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);
- ASSERT_TRUE(range != nullptr) << "Axis: " << axis << " Source: " << source;
- ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source;
- ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source;
- }
-
- static void assertPointerCoords(const PointerCoords& coords, float x, float y, float pressure,
- float size, float touchMajor, float touchMinor, float toolMajor,
- float toolMinor, float orientation, float distance,
- float scaledAxisEpsilon = 1.f) {
- ASSERT_NEAR(x, coords.getAxisValue(AMOTION_EVENT_AXIS_X), scaledAxisEpsilon);
- ASSERT_NEAR(y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y), scaledAxisEpsilon);
- ASSERT_NEAR(pressure, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), EPSILON);
- ASSERT_NEAR(size, coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE), EPSILON);
- ASSERT_NEAR(touchMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- scaledAxisEpsilon);
- ASSERT_NEAR(touchMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- scaledAxisEpsilon);
- ASSERT_NEAR(toolMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- scaledAxisEpsilon);
- ASSERT_NEAR(toolMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- scaledAxisEpsilon);
- ASSERT_NEAR(orientation, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), EPSILON);
- ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON);
- }
-
- static void assertPosition(const FakePointerController& controller, float x, float y) {
- float actualX, actualY;
- controller.getPosition(&actualX, &actualY);
- ASSERT_NEAR(x, actualX, 1);
- ASSERT_NEAR(y, actualY, 1);
- }
-};
-
-const char* InputMapperTest::DEVICE_NAME = "device";
-const char* InputMapperTest::DEVICE_LOCATION = "USB1";
-const int32_t InputMapperTest::DEVICE_ID = END_RESERVED_ID + 1000;
-const int32_t InputMapperTest::DEVICE_GENERATION = 2;
-const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0;
-const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
- ftl::Flags<InputDeviceClass>(0); // not needed for current tests
-const int32_t InputMapperTest::EVENTHUB_ID = 1;
-
// --- SwitchInputMapperTest ---
class SwitchInputMapperTest : public InputMapperTest {
@@ -3069,7 +2764,7 @@
protected:
const std::string UNIQUE_ID = "local:0";
- void prepareDisplay(int32_t orientation);
+ void prepareDisplay(ui::Rotation orientation);
void testDPadKeyRotation(KeyboardInputMapper& mapper, int32_t originalScanCode,
int32_t originalKeyCode, int32_t rotatedKeyCode,
@@ -3079,7 +2774,7 @@
/* Similar to setDisplayInfoAndReconfigure, but pre-populates all parameters except for the
* orientation.
*/
-void KeyboardInputMapperTest::prepareDisplay(int32_t orientation) {
+void KeyboardInputMapperTest::prepareDisplay(ui::Rotation orientation) {
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
NO_PORT, ViewportType::INTERNAL);
}
@@ -3291,7 +2986,7 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
@@ -3313,7 +3008,7 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
ASSERT_NO_FATAL_FAILURE(
testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP, DISPLAY_ID));
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
@@ -3324,7 +3019,7 @@
AKEYCODE_DPAD_LEFT, DISPLAY_ID));
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
ASSERT_NO_FATAL_FAILURE(
testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, DISPLAY_ID));
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
@@ -3335,7 +3030,7 @@
AKEYCODE_DPAD_DOWN, DISPLAY_ID));
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_180);
+ prepareDisplay(ui::ROTATION_180);
ASSERT_NO_FATAL_FAILURE(
testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN, DISPLAY_ID));
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
@@ -3346,7 +3041,7 @@
AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_270);
+ prepareDisplay(ui::ROTATION_270);
ASSERT_NO_FATAL_FAILURE(
testDPadKeyRotation(mapper, KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT, DISPLAY_ID));
ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper, KEY_RIGHT, AKEYCODE_DPAD_RIGHT,
@@ -3360,7 +3055,7 @@
// in the key up as we did in the key down.
NotifyKeyArgs args;
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_270);
+ prepareDisplay(ui::ROTATION_270);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
@@ -3368,7 +3063,7 @@
ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_180);
+ prepareDisplay(ui::ROTATION_180);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
@@ -3393,7 +3088,7 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
ASSERT_EQ(ADISPLAY_ID_NONE, args.displayId);
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 0);
@@ -3415,7 +3110,7 @@
// Display id should be ADISPLAY_ID_NONE without any display configuration.
// ^--- already checked by the previous test
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
@@ -3425,7 +3120,7 @@
constexpr int32_t newDisplayId = 2;
clearViewports();
- setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
+ setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_KEY, KEY_UP, 1);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
@@ -3635,9 +3330,9 @@
// Prepare second display.
constexpr int32_t newDisplayId = 2;
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
UNIQUE_ID, hdmi1, ViewportType::INTERNAL);
- setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0,
+ setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
SECONDARY_UNIQUE_ID, hdmi2, ViewportType::EXTERNAL);
// Default device will reconfigure above, need additional reconfiguration for another device.
unused += device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
@@ -3968,14 +3663,14 @@
void testMotionRotation(CursorInputMapper& mapper, int32_t originalX, int32_t originalY,
int32_t rotatedX, int32_t rotatedY);
- void prepareDisplay(int32_t orientation) {
+ void prepareDisplay(ui::Rotation orientation) {
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation,
DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
}
void prepareSecondaryDisplay() {
setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, SECONDARY_DISPLAY_UNIQUE_ID, NO_PORT,
+ ui::ROTATION_0, SECONDARY_DISPLAY_UNIQUE_ID, NO_PORT,
ViewportType::EXTERNAL);
}
@@ -4260,7 +3955,7 @@
addConfigurationProperty("cursor.orientationAware", "1");
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
@@ -4279,7 +3974,7 @@
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
@@ -4290,7 +3985,7 @@
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1));
@@ -4301,7 +3996,7 @@
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1));
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_180);
+ prepareDisplay(ui::ROTATION_180);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, -1, 0));
@@ -4312,7 +4007,7 @@
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1));
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_270);
+ prepareDisplay(ui::ROTATION_270);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1));
@@ -4776,7 +4471,7 @@
ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
// Ensure the display is rotated.
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
NotifyMotionArgs args;
@@ -4812,7 +4507,7 @@
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
// Set up the default display.
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
// Set up the secondary display as the display on which the pointer should be shown.
// The InputDevice is not associated with any display.
@@ -4839,7 +4534,7 @@
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
// Set up the default display.
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
// Set up the secondary display as the display on which the pointer should be shown,
// and associate the InputDevice with the secondary display.
@@ -4866,7 +4561,7 @@
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
// Set up the default display as the display on which the pointer should be shown.
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
// Associate the InputDevice with the secondary display.
@@ -5033,9 +4728,9 @@
TOOL_TYPE = 1 << 10,
};
- void prepareDisplay(int32_t orientation, std::optional<uint8_t> port = NO_PORT);
+ void prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port = NO_PORT);
void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port = NO_PORT);
- void prepareVirtualDisplay(int32_t orientation);
+ void prepareVirtualDisplay(ui::Rotation orientation);
void prepareVirtualKeys();
void prepareLocationCalibration();
int32_t toRawX(float displayX);
@@ -5089,17 +4784,17 @@
{ KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
};
-void TouchInputMapperTest::prepareDisplay(int32_t orientation, std::optional<uint8_t> port) {
+void TouchInputMapperTest::prepareDisplay(ui::Rotation orientation, std::optional<uint8_t> port) {
setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, UNIQUE_ID,
port, ViewportType::INTERNAL);
}
void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> port) {
setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, SECONDARY_UNIQUE_ID, port, type);
+ ui::ROTATION_0, SECONDARY_UNIQUE_ID, port, type);
}
-void TouchInputMapperTest::prepareVirtualDisplay(int32_t orientation) {
+void TouchInputMapperTest::prepareVirtualDisplay(ui::Rotation orientation) {
setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT,
orientation, VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT,
ViewportType::VIRTUAL);
@@ -5266,7 +4961,7 @@
TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5294,7 +4989,7 @@
TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5322,7 +5017,7 @@
TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5337,7 +5032,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5387,7 +5082,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5508,7 +5203,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5583,7 +5278,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.displayId", VIRTUAL_DISPLAY_UNIQUE_ID);
- prepareVirtualDisplay(DISPLAY_ORIENTATION_0);
+ prepareVirtualDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5679,7 +5374,7 @@
TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
prepareVirtualKeys();
@@ -5778,7 +5473,7 @@
NotifyMotionArgs args;
// Rotation 90.
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
processDown(mapper, toRawX(50), toRawY(75));
processSync(mapper);
@@ -5804,7 +5499,7 @@
// Rotation 0.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
processDown(mapper, toRawX(50), toRawY(75));
processSync(mapper);
@@ -5818,7 +5513,7 @@
// Rotation 90.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN);
processSync(mapper);
@@ -5832,7 +5527,7 @@
// Rotation 180.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_180);
+ prepareDisplay(ui::ROTATION_180);
processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
processSync(mapper);
@@ -5846,7 +5541,7 @@
// Rotation 270.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_270);
+ prepareDisplay(ui::ROTATION_270);
processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50));
processSync(mapper);
@@ -5866,7 +5561,7 @@
addConfigurationProperty("touch.orientationAware", "1");
addConfigurationProperty("touch.orientation", "ORIENTATION_0");
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5890,7 +5585,7 @@
addConfigurationProperty("touch.orientationAware", "1");
addConfigurationProperty("touch.orientation", "ORIENTATION_90");
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5914,7 +5609,7 @@
addConfigurationProperty("touch.orientationAware", "1");
addConfigurationProperty("touch.orientation", "ORIENTATION_180");
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5938,7 +5633,7 @@
addConfigurationProperty("touch.orientationAware", "1");
addConfigurationProperty("touch.orientation", "ORIENTATION_270");
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
NotifyMotionArgs args;
@@ -5969,7 +5664,7 @@
// Orientation 90, Rotation 0.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
processDown(mapper, RAW_X_MAX - toRotatedRawX(75) + RAW_X_MIN, toRotatedRawY(50));
processSync(mapper);
@@ -5983,7 +5678,7 @@
// Orientation 90, Rotation 90.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
processDown(mapper, toRotatedRawX(50), toRotatedRawY(75));
processSync(mapper);
@@ -5997,7 +5692,7 @@
// Orientation 90, Rotation 180.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_180);
+ prepareDisplay(ui::ROTATION_180);
processDown(mapper, toRotatedRawX(75), RAW_Y_MAX - toRotatedRawY(50) + RAW_Y_MIN);
processSync(mapper);
@@ -6011,7 +5706,7 @@
// Orientation 90, Rotation 270.
clearViewports();
- prepareDisplay(DISPLAY_ORIENTATION_270);
+ prepareDisplay(ui::ROTATION_270);
processDown(mapper, RAW_X_MAX - toRotatedRawX(50) + RAW_X_MIN,
RAW_Y_MAX - toRotatedRawY(75) + RAW_Y_MIN);
processSync(mapper);
@@ -6027,7 +5722,7 @@
TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6071,7 +5766,7 @@
TEST_F(SingleTouchInputMapperTest, Process_XYAxes_AffineCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareLocationCalibration();
prepareButtons();
prepareAxes(POSITION);
@@ -6094,7 +5789,7 @@
TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6337,7 +6032,7 @@
TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6472,7 +6167,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
@@ -6544,7 +6239,7 @@
TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6615,7 +6310,7 @@
TEST_F(SingleTouchInputMapperTest, Reset_CancelsOngoingGesture) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6637,7 +6332,7 @@
TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION | PRESSURE);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6665,7 +6360,7 @@
TEST_F(SingleTouchInputMapperTest,
Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6693,7 +6388,7 @@
TEST_F(SingleTouchInputMapperTest,
Process_WhenViewportActiveStatusChanged_TouchIsCanceledAndDeviceIsReset) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6753,7 +6448,7 @@
TEST_F(SingleTouchInputMapperTest, ButtonIsReleasedOnTouchUp) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -6796,27 +6491,25 @@
// The values inside DisplayViewport are expected to be pre-rotated. This updates the current
// DisplayViewport to pre-rotate the values. The viewport's physical display will be set to the
// rotated equivalent of the given un-rotated physical display bounds.
- void configurePhysicalDisplay(int32_t orientation, Rect naturalPhysicalDisplay) {
+ void configurePhysicalDisplay(ui::Rotation orientation, Rect naturalPhysicalDisplay) {
uint32_t inverseRotationFlags;
auto width = DISPLAY_WIDTH;
auto height = DISPLAY_HEIGHT;
switch (orientation) {
- case DISPLAY_ORIENTATION_90:
+ case ui::ROTATION_90:
inverseRotationFlags = ui::Transform::ROT_270;
std::swap(width, height);
break;
- case DISPLAY_ORIENTATION_180:
+ case ui::ROTATION_180:
inverseRotationFlags = ui::Transform::ROT_180;
break;
- case DISPLAY_ORIENTATION_270:
+ case ui::ROTATION_270:
inverseRotationFlags = ui::Transform::ROT_90;
std::swap(width, height);
break;
- case DISPLAY_ORIENTATION_0:
+ case ui::ROTATION_0:
inverseRotationFlags = ui::Transform::ROT_0;
break;
- default:
- FAIL() << "Invalid orientation: " << orientation;
}
const ui::Transform rotation(inverseRotationFlags, width, height);
@@ -6860,7 +6553,7 @@
TEST_F(TouchDisplayProjectionTest, IgnoresTouchesOutsidePhysicalDisplay) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
@@ -6875,8 +6568,7 @@
static const std::array<Point, 6> kPointsOutsidePhysicalDisplay{
{{-10, -10}, {0, 0}, {5, 100}, {50, 15}, {75, 100}, {50, 165}}};
- for (auto orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90, DISPLAY_ORIENTATION_180,
- DISPLAY_ORIENTATION_270}) {
+ for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
configurePhysicalDisplay(orientation, kPhysicalDisplay);
// Touches outside the physical display should be ignored, and should not generate any
@@ -6896,7 +6588,7 @@
TEST_F(TouchDisplayProjectionTest, EmitsTouchDownAfterEnteringPhysicalDisplay) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
@@ -6909,8 +6601,7 @@
// points (10, 20) and (70, 160) inside the display space, which is of the size 400 x 800.
static const Rect kPhysicalDisplay{10, 20, 70, 160};
- for (auto orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90, DISPLAY_ORIENTATION_180,
- DISPLAY_ORIENTATION_270}) {
+ for (auto orientation : {ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180, ui::ROTATION_270}) {
configurePhysicalDisplay(orientation, kPhysicalDisplay);
// Touches that start outside the physical display should be ignored until it enters the
@@ -6961,7 +6652,7 @@
public:
SingleTouchInputMapper& initializeInputMapperWithExternalStylus() {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareButtons();
prepareAxes(POSITION);
auto& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -7450,7 +7141,7 @@
TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
prepareVirtualKeys();
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -7722,7 +7413,7 @@
TEST_F(MultiTouchInputMapperTest, AxisResolution_IsPopulated) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
/*fuzz*/ 0, /*resolution*/ 10);
@@ -7752,7 +7443,7 @@
TEST_F(MultiTouchInputMapperTest, TouchMajorAndMinorAxes_DoNotAppearIfNotSupported) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, /*flat*/ 0,
/*fuzz*/ 0, /*resolution*/ 10);
@@ -7773,7 +7464,7 @@
TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID);
prepareVirtualKeys();
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -7944,7 +7635,7 @@
TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
prepareVirtualKeys();
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8110,7 +7801,7 @@
TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8159,7 +7850,7 @@
TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL | MINOR);
addConfigurationProperty("touch.size.calibration", "geometric");
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8196,7 +7887,7 @@
TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL);
addConfigurationProperty("touch.size.calibration", "diameter");
addConfigurationProperty("touch.size.scale", "10");
@@ -8247,7 +7938,7 @@
TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | TOUCH | TOOL);
addConfigurationProperty("touch.size.calibration", "area");
addConfigurationProperty("touch.size.scale", "43");
@@ -8280,7 +7971,7 @@
TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | PRESSURE);
addConfigurationProperty("touch.pressure.calibration", "amplitude");
addConfigurationProperty("touch.pressure.scale", "0.01");
@@ -8314,7 +8005,7 @@
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8557,7 +8248,7 @@
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleMappedStylusButtons) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8614,7 +8305,7 @@
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8764,7 +8455,7 @@
TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8835,7 +8526,7 @@
TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -8935,7 +8626,7 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
// Add viewport for display 1 on hdmi1
- prepareDisplay(DISPLAY_ORIENTATION_0, hdmi1);
+ prepareDisplay(ui::ROTATION_0, hdmi1);
// Send a touch event again
processPosition(mapper, 100, 100);
processSync(mapper);
@@ -8952,8 +8643,8 @@
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareVirtualDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
+ prepareVirtualDisplay(ui::ROTATION_0);
// Send a touch event
processPosition(mapper, 100, 100);
@@ -8976,7 +8667,7 @@
mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
prepareSecondaryDisplay(ViewportType::EXTERNAL);
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9000,7 +8691,7 @@
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
process(mapper, 10, 11 /*readTime*/, EV_ABS, ABS_MT_TRACKING_ID, 1);
process(mapper, 15, 16 /*readTime*/, EV_ABS, ABS_MT_POSITION_X, 100);
process(mapper, 20, 21 /*readTime*/, EV_ABS, ABS_MT_POSITION_Y, 100);
@@ -9025,9 +8716,8 @@
TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreDropped) {
addConfigurationProperty("touch.deviceType", "touchScreen");
// Don't set touch.enableForInactiveViewport to verify the default behavior.
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, false /*isActive*/, UNIQUE_ID, NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ false /*isActive*/, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9046,9 +8736,8 @@
TEST_F(MultiTouchInputMapperTest, WhenViewportIsNotActive_TouchesAreProcessed) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "1");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, false /*isActive*/, UNIQUE_ID, NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ false /*isActive*/, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
prepareAxes(POSITION);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9064,9 +8753,8 @@
TEST_F(MultiTouchInputMapperTest, Process_DeactivateViewport_AbortTouches) {
addConfigurationProperty("touch.deviceType", "touchScreen");
addConfigurationProperty("touch.enableForInactiveViewport", "0");
- mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, NO_PORT,
- ViewportType::INTERNAL);
+ mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, ui::ROTATION_0,
+ true /*isActive*/, UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
std::optional<DisplayViewport> optionalDisplayViewport =
mFakePolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
ASSERT_TRUE(optionalDisplayViewport.has_value());
@@ -9160,7 +8848,7 @@
mFakePolicy->setShowTouches(true);
// Create displays.
- prepareDisplay(DISPLAY_ORIENTATION_0, hdmi1);
+ prepareDisplay(ui::ROTATION_0, hdmi1);
prepareSecondaryDisplay(ViewportType::EXTERNAL, hdmi2);
// Default device will reconfigure above, need additional reconfiguration for another device.
@@ -9205,7 +8893,7 @@
TEST_F(MultiTouchInputMapperTest, VideoFrames_ReceivedByListener) {
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -9236,8 +8924,7 @@
NotifyMotionArgs motionArgs;
// Test all 4 orientations
- for (int32_t orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90,
- DISPLAY_ORIENTATION_180, DISPLAY_ORIENTATION_270}) {
+ for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
SCOPED_TRACE("Orientation " + StringPrintf("%i", orientation));
clearViewports();
prepareDisplay(orientation);
@@ -9262,8 +8949,7 @@
NotifyMotionArgs motionArgs;
// Test all 4 orientations
- for (int32_t orientation : {DISPLAY_ORIENTATION_0, DISPLAY_ORIENTATION_90,
- DISPLAY_ORIENTATION_180, DISPLAY_ORIENTATION_270}) {
+ for (ui::Rotation orientation : ftl::enum_range<ui::Rotation>()) {
SCOPED_TRACE("Orientation " + StringPrintf("%i", orientation));
clearViewports();
prepareDisplay(orientation);
@@ -9297,7 +8983,7 @@
std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
NotifyMotionArgs motionArgs;
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
processPosition(mapper, 100, 200);
processSync(mapper);
@@ -9320,7 +9006,7 @@
std::vector<TouchVideoFrame> frames{frame1, frame2, frame3};
NotifyMotionArgs motionArgs;
- prepareDisplay(DISPLAY_ORIENTATION_90);
+ prepareDisplay(ui::ROTATION_90);
mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
processPosition(mapper, 100, 200);
processSync(mapper);
@@ -9330,7 +9016,7 @@
// compared to the display. This is so that when the window transform (which contains the
// display rotation) is applied later by InputDispatcher, the coordinates end up in the
// window's coordinate space.
- frame.rotate(getInverseRotation(DISPLAY_ORIENTATION_90));
+ frame.rotate(getInverseRotation(ui::ROTATION_90));
});
ASSERT_EQ(frames, motionArgs.videoFrames);
}
@@ -9367,7 +9053,7 @@
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9412,7 +9098,7 @@
*/
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_SinglePointer) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9460,7 +9146,7 @@
*/
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_TwoPointers) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9535,7 +9221,7 @@
*/
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_ShouldCancelWhenAllTouchIsPalm) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9633,7 +9319,7 @@
*/
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType_KeepFirstPointer) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9705,7 +9391,7 @@
*/
TEST_F(MultiTouchInputMapperTest, Process_MultiTouch_WithInvalidTrackingId) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9762,7 +9448,7 @@
TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9803,7 +9489,7 @@
TEST_F(MultiTouchInputMapperTest, Reset_PreservesLastTouchState_NoPointersDown) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -9831,7 +9517,7 @@
TEST_F(MultiTouchInputMapperTest, StylusSourceIsAddedDynamicallyFromToolType) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE | TOOL_TYPE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
@@ -9890,7 +9576,7 @@
TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
prepareAxes(POSITION);
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
@@ -9921,7 +9607,7 @@
fakePointerController->setButtonState(0);
// prepare device and capture
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
@@ -10071,7 +9757,7 @@
fakePointerController->setButtonState(0);
// prepare device and capture
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
@@ -10112,7 +9798,7 @@
std::shared_ptr<FakePointerController> fakePointerController =
std::make_shared<FakePointerController>();
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT);
mFakeEventHub->addKey(EVENTHUB_ID, BTN_LEFT, 0, AKEYCODE_UNKNOWN, 0);
mFakePolicy->setPointerController(fakePointerController);
@@ -10139,7 +9825,7 @@
TEST_F(BluetoothMultiTouchInputMapperTest, TimestampSmoothening) {
addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION | ID | SLOT | PRESSURE);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
@@ -10189,7 +9875,7 @@
fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
fakePointerController->setPosition(0, 0);
fakePointerController->setButtonState(0);
- prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareDisplay(ui::ROTATION_0);
prepareAxes(POSITION);
prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
@@ -10549,7 +10235,7 @@
process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
}
- void prepareVirtualDisplay(int32_t orientation) {
+ void prepareVirtualDisplay(ui::Rotation orientation) {
setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID,
NO_PORT, ViewportType::VIRTUAL);
@@ -10567,7 +10253,7 @@
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, VIRTUAL_DISPLAY_UNIQUE_ID);
- prepareVirtualDisplay(DISPLAY_ORIENTATION_0);
+ prepareVirtualDisplay(ui::ROTATION_0);
// Send an axis event
processAxis(mapper, ABS_X, 100);
diff --git a/services/inputflinger/tests/InstrumentedInputReader.cpp b/services/inputflinger/tests/InstrumentedInputReader.cpp
new file mode 100644
index 0000000..1f8cd12
--- /dev/null
+++ b/services/inputflinger/tests/InstrumentedInputReader.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 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 "InstrumentedInputReader.h"
+
+namespace android {
+
+InstrumentedInputReader::InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ InputListenerInterface& listener)
+ : InputReader(eventHub, policy, listener), mFakeContext(this) {}
+
+void InstrumentedInputReader::pushNextDevice(std::shared_ptr<InputDevice> device) {
+ mNextDevices.push(device);
+}
+
+std::shared_ptr<InputDevice> InstrumentedInputReader::newDevice(int32_t deviceId,
+ const std::string& name,
+ const std::string& location) {
+ InputDeviceIdentifier identifier;
+ identifier.name = name;
+ identifier.location = location;
+ int32_t generation = deviceId + 1;
+ return std::make_shared<InputDevice>(&mFakeContext, deviceId, generation, identifier);
+}
+
+std::shared_ptr<InputDevice> InstrumentedInputReader::createDeviceLocked(
+ int32_t eventHubId, const InputDeviceIdentifier& identifier) REQUIRES(mLock) {
+ if (!mNextDevices.empty()) {
+ std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
+ mNextDevices.pop();
+ return device;
+ }
+ return InputReader::createDeviceLocked(eventHubId, identifier);
+}
+
+} // namespace android
diff --git a/services/inputflinger/tests/InstrumentedInputReader.h b/services/inputflinger/tests/InstrumentedInputReader.h
new file mode 100644
index 0000000..7f8d556
--- /dev/null
+++ b/services/inputflinger/tests/InstrumentedInputReader.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2022 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <queue>
+#include <string>
+
+#include <InputDevice.h>
+#include <InputReader.h>
+#include <gtest/gtest.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class InstrumentedInputReader : public InputReader {
+public:
+ InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ InputListenerInterface& listener);
+ virtual ~InstrumentedInputReader() {}
+
+ void pushNextDevice(std::shared_ptr<InputDevice> device);
+
+ std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+ const std::string& location = "");
+
+ // Make the protected loopOnce method accessible to tests.
+ using InputReader::loopOnce;
+
+protected:
+ virtual std::shared_ptr<InputDevice> createDeviceLocked(
+ int32_t eventHubId, const InputDeviceIdentifier& identifier);
+
+ class FakeInputReaderContext : public ContextImpl {
+ public:
+ FakeInputReaderContext(InputReader* reader)
+ : ContextImpl(reader),
+ mGlobalMetaState(0),
+ mUpdateGlobalMetaStateWasCalled(false),
+ mGeneration(1) {}
+
+ virtual ~FakeInputReaderContext() {}
+
+ void assertUpdateGlobalMetaStateWasCalled() {
+ ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
+ << "Expected updateGlobalMetaState() to have been called.";
+ mUpdateGlobalMetaStateWasCalled = false;
+ }
+
+ void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
+
+ uint32_t getGeneration() { return mGeneration; }
+
+ void updateGlobalMetaState() override {
+ mUpdateGlobalMetaStateWasCalled = true;
+ ContextImpl::updateGlobalMetaState();
+ }
+
+ int32_t getGlobalMetaState() override {
+ return mGlobalMetaState | ContextImpl::getGlobalMetaState();
+ }
+
+ int32_t bumpGeneration() override {
+ mGeneration = ContextImpl::bumpGeneration();
+ return mGeneration;
+ }
+
+ void requestTimeoutAtTime(nsecs_t when) override { mRequestedTimeout = when; }
+
+ void assertTimeoutWasRequested(nsecs_t when) {
+ ASSERT_TRUE(mRequestedTimeout) << "Expected timeout at time " << when
+ << " but there was no timeout requested.";
+ ASSERT_EQ(when, *mRequestedTimeout);
+ mRequestedTimeout.reset();
+ }
+
+ void assertTimeoutWasNotRequested() {
+ ASSERT_FALSE(mRequestedTimeout) << "Expected no timeout to have been requested,"
+ " but one was requested at time "
+ << *mRequestedTimeout;
+ }
+
+ void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override {
+ outDevices = mExternalStylusDevices;
+ }
+
+ void setExternalStylusDevices(std::vector<InputDeviceInfo>&& devices) {
+ mExternalStylusDevices = devices;
+ }
+
+ private:
+ int32_t mGlobalMetaState;
+ bool mUpdateGlobalMetaStateWasCalled;
+ int32_t mGeneration;
+ std::optional<nsecs_t> mRequestedTimeout;
+ std::vector<InputDeviceInfo> mExternalStylusDevices;
+ } mFakeContext;
+
+ friend class InputReaderTest;
+
+public:
+ FakeInputReaderContext* getContext() { return &mFakeContext; }
+
+private:
+ std::queue<std::shared_ptr<InputDevice>> mNextDevices;
+};
+
+} // namespace android
diff --git a/services/inputflinger/tests/TestConstants.h b/services/inputflinger/tests/TestConstants.h
index 8dc9d71..27881f6 100644
--- a/services/inputflinger/tests/TestConstants.h
+++ b/services/inputflinger/tests/TestConstants.h
@@ -27,4 +27,7 @@
static constexpr nsecs_t ARBITRARY_TIME = 1234;
static constexpr nsecs_t READ_TIME = 4321;
+// Error tolerance for floating point assertions.
+static const float EPSILON = 0.001f;
+
} // namespace android
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 64316ba..445ed18 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -311,7 +311,7 @@
return mFdp->ConsumeRandomLengthString(32);
}
TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
- int32_t surfaceRotation) override {
+ ui::Rotation surfaceRotation) override {
return mTransform;
}
void setTouchAffineTransformation(const TouchAffineTransformation t) { mTransform = t; }
diff --git a/services/sensorservice/aidl/SensorManager.cpp b/services/sensorservice/aidl/SensorManager.cpp
index 6d8d574..9b03344 100644
--- a/services/sensorservice/aidl/SensorManager.cpp
+++ b/services/sensorservice/aidl/SensorManager.cpp
@@ -201,7 +201,7 @@
// if thread not initialized, start thread
mStopThread = false;
std::thread pollThread{[&stopThread = mStopThread, looper = mLooper, javaVm = mJavaVm] {
- struct sched_param p = {0};
+ struct sched_param p = {};
p.sched_priority = 10;
if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
LOG(ERROR) << "Could not use SCHED_FIFO for looper thread: " << strerror(errno);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 269a5ea..46b857b 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -203,7 +203,7 @@
mRefreshRateSelector->setActiveMode(modeId, renderFps);
if (mRefreshRateOverlay) {
- mRefreshRateOverlay->changeRefreshRate(displayFps);
+ mRefreshRateOverlay->changeRefreshRate(displayFps, renderFps);
}
}
@@ -410,26 +410,35 @@
capabilities.getDesiredMinLuminance());
}
-void DisplayDevice::enableRefreshRateOverlay(bool enable, bool showSpinnner) {
+void DisplayDevice::enableRefreshRateOverlay(bool enable, bool showSpinner, bool showRenderRate) {
if (!enable) {
mRefreshRateOverlay.reset();
return;
}
+ ftl::Flags<RefreshRateOverlay::Features> features;
+ if (showSpinner) {
+ features |= RefreshRateOverlay::Features::Spinner;
+ }
+
+ if (showRenderRate) {
+ features |= RefreshRateOverlay::Features::RenderRate;
+ }
+
const auto fpsRange = mRefreshRateSelector->getSupportedRefreshRateRange();
- mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, showSpinnner);
+ mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, features);
mRefreshRateOverlay->setLayerStack(getLayerStack());
mRefreshRateOverlay->setViewport(getSize());
- mRefreshRateOverlay->changeRefreshRate(getActiveMode().modePtr->getFps());
+ mRefreshRateOverlay->changeRefreshRate(getActiveMode().modePtr->getFps(), getActiveMode().fps);
}
bool DisplayDevice::onKernelTimerChanged(std::optional<DisplayModeId> desiredModeId,
bool timerExpired) {
if (mRefreshRateSelector && mRefreshRateOverlay) {
- const auto newRefreshRate =
+ const auto newMode =
mRefreshRateSelector->onKernelTimerChanged(desiredModeId, timerExpired);
- if (newRefreshRate) {
- mRefreshRateOverlay->changeRefreshRate(*newRefreshRate);
+ if (newMode) {
+ mRefreshRateOverlay->changeRefreshRate(newMode->modePtr->getFps(), newMode->fps);
return true;
}
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 852a8a2..8f9b2a1 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -236,7 +236,8 @@
}
// Enables an overlay to be displayed with the current refresh rate
- void enableRefreshRateOverlay(bool enable, bool showSpinner) REQUIRES(kMainThreadContext);
+ void enableRefreshRateOverlay(bool enable, bool showSpinner, bool showRenderRate)
+ REQUIRES(kMainThreadContext);
bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; }
bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
void animateRefreshRateOverlay();
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 3782c6c..800e36d 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -535,7 +535,7 @@
return static_cast<Error>(status.getServiceSpecificError());
}
- *outTypes = translate<Hdr>(capabilities.types);
+ *outTypes = capabilities.types;
*outMaxLuminance = capabilities.maxLuminance;
*outMaxAverageLuminance = capabilities.maxAverageLuminance;
*outMinLuminance = capabilities.minLuminance;
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index d84efe7..2a043fd 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -104,7 +104,7 @@
Error getDozeSupport(Display display, bool* outSupport) override;
Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
- Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
+ Error getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance) override;
Error getOverlaySupport(OverlayProperties* outProperties) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index a9bf282..ec23935 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -66,7 +66,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Config;
@@ -84,6 +83,7 @@
using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey;
using PerFrameMetadataBlob = IComposerClient::PerFrameMetadataBlob;
using AidlTransform = ::aidl::android::hardware::graphics::common::Transform;
+using aidl::android::hardware::graphics::common::Hdr;
class Composer {
public:
@@ -140,7 +140,7 @@
virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
virtual Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) = 0;
- virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
+ virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e264570..d0126d0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -320,17 +320,17 @@
float maxLuminance = -1.0f;
float maxAverageLuminance = -1.0f;
float minLuminance = -1.0f;
- std::vector<Hwc2::Hdr> types;
- auto intError = mComposer.getHdrCapabilities(mId, &types,
- &maxLuminance, &maxAverageLuminance, &minLuminance);
+ std::vector<Hwc2::Hdr> hdrTypes;
+ auto intError = mComposer.getHdrCapabilities(mId, &hdrTypes, &maxLuminance,
+ &maxAverageLuminance, &minLuminance);
auto error = static_cast<HWC2::Error>(intError);
if (error != Error::NONE) {
return error;
}
- *outCapabilities = HdrCapabilities(std::move(types),
- maxLuminance, maxAverageLuminance, minLuminance);
+ *outCapabilities =
+ HdrCapabilities(std::move(hdrTypes), maxLuminance, maxAverageLuminance, minLuminance);
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 8238828..537d545 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -20,6 +20,7 @@
#include <android/hardware/graphics/composer/2.4/IComposer.h>
#include <android/hardware/graphics/composer/2.4/IComposerClient.h>
+#include <aidl/android/hardware/graphics/common/Hdr.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
@@ -39,7 +40,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Error;
@@ -69,6 +69,7 @@
using PowerMode = IComposerClient::PowerMode;
using Vsync = IComposerClient::Vsync;
using VsyncPeriodChangeConstraints = IComposerClient::VsyncPeriodChangeConstraints;
+using Hdr = aidl::android::hardware::graphics::common::Hdr;
} // namespace hardware::graphics::composer::hal
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index f8522e2..b607df0 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -496,13 +496,13 @@
"OptionalFeature::KernelIdleTimer is not supported on HIDL");
}
-Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
+Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) {
Error error = kDefaultError;
if (mClient_2_3) {
mClient_2_3->getHdrCapabilities_2_3(display,
- [&](const auto& tmpError, const auto& tmpTypes,
+ [&](const auto& tmpError, const auto& tmpHdrTypes,
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
@@ -510,15 +510,15 @@
if (error != Error::NONE) {
return;
}
+ *outHdrTypes = translate<ui::Hdr>(tmpHdrTypes);
- *outTypes = tmpTypes;
*outMaxLuminance = tmpMaxLuminance;
*outMaxAverageLuminance = tmpMaxAverageLuminance;
*outMinLuminance = tmpMinLuminance;
});
} else {
mClient->getHdrCapabilities(display,
- [&](const auto& tmpError, const auto& tmpTypes,
+ [&](const auto& tmpError, const auto& tmpHdrTypes,
const auto& tmpMaxLuminance,
const auto& tmpMaxAverageLuminance,
const auto& tmpMinLuminance) {
@@ -526,11 +526,7 @@
if (error != Error::NONE) {
return;
}
-
- outTypes->clear();
- for (auto type : tmpTypes) {
- outTypes->push_back(static_cast<Hdr>(type));
- }
+ *outHdrTypes = translate<ui::Hdr>(tmpHdrTypes);
*outMaxLuminance = tmpMaxLuminance;
*outMaxAverageLuminance = tmpMaxAverageLuminance;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 48b720c..3602bbb 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -56,7 +56,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Config;
@@ -209,7 +208,7 @@
Error getDozeSupport(Display display, bool* outSupport) override;
Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
- Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
+ Error getHdrCapabilities(Display display, std::vector<Hdr>* outHdrTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance) override;
Error getOverlaySupport(aidl::android::hardware::graphics::composer3::OverlayProperties*
outProperties) override;
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 9b19afb..7aa7e17 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -42,8 +42,8 @@
constexpr int kDigitHeight = 100;
constexpr int kDigitSpace = 16;
-// Layout is digit, space, digit, space, digit, space, spinner.
-constexpr int kBufferWidth = 4 * kDigitWidth + 3 * kDigitSpace;
+constexpr int kMaxDigits = /*displayFps*/ 3 + /*renderFps*/ 3 + /*spinner*/ 1;
+constexpr int kBufferWidth = kMaxDigits * kDigitWidth + (kMaxDigits - 1) * kDigitSpace;
constexpr int kBufferHeight = kDigitHeight;
SurfaceComposerClient::Transaction createTransaction(const sp<SurfaceControl>& surface) {
@@ -121,16 +121,10 @@
drawSegment(Segment::Bottom, left, color, canvas);
}
-auto RefreshRateOverlay::SevenSegmentDrawer::draw(int number, SkColor color,
+auto RefreshRateOverlay::SevenSegmentDrawer::draw(int displayFps, int renderFps, SkColor color,
ui::Transform::RotationFlags rotation,
- bool showSpinner) -> Buffers {
- if (number < 0 || number > 1000) return {};
-
- const auto hundreds = number / 100;
- const auto tens = (number / 10) % 10;
- const auto ones = number % 10;
-
- const size_t loopCount = showSpinner ? 6 : 1;
+ ftl::Flags<Features> features) -> Buffers {
+ const size_t loopCount = features.test(Features::Spinner) ? 6 : 1;
Buffers buffers;
buffers.reserve(loopCount);
@@ -169,20 +163,9 @@
canvas->setMatrix(canvasTransform);
int left = 0;
- if (hundreds != 0) {
- drawDigit(hundreds, left, color, *canvas);
- }
- left += kDigitWidth + kDigitSpace;
-
- if (tens != 0) {
- drawDigit(tens, left, color, *canvas);
- }
- left += kDigitWidth + kDigitSpace;
-
- drawDigit(ones, left, color, *canvas);
- left += kDigitWidth + kDigitSpace;
-
- if (showSpinner) {
+ drawNumber(displayFps, left, color, *canvas);
+ left += 3 * (kDigitWidth + kDigitSpace);
+ if (features.test(Features::Spinner)) {
switch (i) {
case 0:
drawSegment(Segment::Upper, left, color, *canvas);
@@ -205,6 +188,13 @@
}
}
+ left += kDigitWidth + kDigitSpace;
+
+ if (features.test(Features::RenderRate)) {
+ drawNumber(renderFps, left, color, *canvas);
+ }
+ left += 3 * (kDigitWidth + kDigitSpace);
+
void* pixels = nullptr;
buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
@@ -219,6 +209,23 @@
return buffers;
}
+void RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number, int left, SkColor color,
+ SkCanvas& canvas) {
+ if (number < 0 || number >= 1000) return;
+
+ if (number >= 100) {
+ drawDigit(number / 100, left, color, canvas);
+ }
+ left += kDigitWidth + kDigitSpace;
+
+ if (number >= 10) {
+ drawDigit((number / 10) % 10, left, color, canvas);
+ }
+ left += kDigitWidth + kDigitSpace;
+
+ drawDigit(number % 10, left, color, canvas);
+}
+
std::unique_ptr<SurfaceControlHolder> createSurfaceControlHolder() {
sp<SurfaceControl> surfaceControl =
SurfaceComposerClient::getDefault()
@@ -228,10 +235,8 @@
return std::make_unique<SurfaceControlHolder>(std::move(surfaceControl));
}
-RefreshRateOverlay::RefreshRateOverlay(FpsRange fpsRange, bool showSpinner)
- : mFpsRange(fpsRange),
- mShowSpinner(showSpinner),
- mSurfaceControl(createSurfaceControlHolder()) {
+RefreshRateOverlay::RefreshRateOverlay(FpsRange fpsRange, ftl::Flags<Features> features)
+ : mFpsRange(fpsRange), mFeatures(features), mSurfaceControl(createSurfaceControlHolder()) {
if (!mSurfaceControl) {
ALOGE("%s: Failed to create buffer state layer", __func__);
return;
@@ -243,10 +248,15 @@
.apply();
}
-auto RefreshRateOverlay::getOrCreateBuffers(Fps fps) -> const Buffers& {
+auto RefreshRateOverlay::getOrCreateBuffers(Fps displayFps, Fps renderFps) -> const Buffers& {
static const Buffers kNoBuffers;
if (!mSurfaceControl) return kNoBuffers;
+ // avoid caching different render rates if RenderRate is anyway not visible
+ if (!mFeatures.test(Features::RenderRate)) {
+ renderFps = 0_Hz;
+ }
+
const auto transformHint =
static_cast<ui::Transform::RotationFlags>(mSurfaceControl->get()->getTransformHint());
@@ -266,17 +276,20 @@
.setTransform(mSurfaceControl->get(), transform)
.apply();
- BufferCache::const_iterator it = mBufferCache.find({fps.getIntValue(), transformHint});
+ BufferCache::const_iterator it =
+ mBufferCache.find({displayFps.getIntValue(), renderFps.getIntValue(), transformHint});
if (it == mBufferCache.end()) {
const int minFps = mFpsRange.min.getIntValue();
const int maxFps = mFpsRange.max.getIntValue();
- // Clamp to the range. The current fps may be outside of this range if the display has
- // changed its set of supported refresh rates.
- const int intFps = std::clamp(fps.getIntValue(), minFps, maxFps);
+ // Clamp to the range. The current displayFps may be outside of this range if the display
+ // has changed its set of supported refresh rates.
+ const int displayIntFps = std::clamp(displayFps.getIntValue(), minFps, maxFps);
+ const int renderIntFps = renderFps.getIntValue();
// Ensure non-zero range to avoid division by zero.
- const float fpsScale = static_cast<float>(intFps - minFps) / std::max(1, maxFps - minFps);
+ const float fpsScale =
+ static_cast<float>(displayIntFps - minFps) / std::max(1, maxFps - minFps);
constexpr SkColor kMinFpsColor = SK_ColorRED;
constexpr SkColor kMaxFpsColor = SK_ColorGREEN;
@@ -292,8 +305,11 @@
const SkColor color = colorBase.toSkColor();
- auto buffers = SevenSegmentDrawer::draw(intFps, color, transformHint, mShowSpinner);
- it = mBufferCache.try_emplace({intFps, transformHint}, std::move(buffers)).first;
+ auto buffers = SevenSegmentDrawer::draw(displayIntFps, renderIntFps, color, transformHint,
+ mFeatures);
+ it = mBufferCache
+ .try_emplace({displayIntFps, renderIntFps, transformHint}, std::move(buffers))
+ .first;
}
return it->second;
@@ -303,7 +319,7 @@
constexpr int32_t kMaxWidth = 1000;
const auto width = std::min({kMaxWidth, viewport.width, viewport.height});
const auto height = 2 * width;
- Rect frame((3 * width) >> 4, height >> 5);
+ Rect frame((5 * width) >> 4, height >> 5);
frame.offsetBy(width >> 5, height >> 4);
createTransaction(mSurfaceControl->get())
@@ -317,16 +333,17 @@
createTransaction(mSurfaceControl->get()).setLayerStack(mSurfaceControl->get(), stack).apply();
}
-void RefreshRateOverlay::changeRefreshRate(Fps fps) {
- mCurrentFps = fps;
- const auto buffer = getOrCreateBuffers(fps)[mFrame];
+void RefreshRateOverlay::changeRefreshRate(Fps displayFps, Fps renderFps) {
+ mDisplayFps = displayFps;
+ mRenderFps = renderFps;
+ const auto buffer = getOrCreateBuffers(displayFps, renderFps)[mFrame];
createTransaction(mSurfaceControl->get()).setBuffer(mSurfaceControl->get(), buffer).apply();
}
void RefreshRateOverlay::animate() {
- if (!mShowSpinner || !mCurrentFps) return;
+ if (!mFeatures.test(Features::Spinner) || !mDisplayFps) return;
- const auto& buffers = getOrCreateBuffers(*mCurrentFps);
+ const auto& buffers = getOrCreateBuffers(*mDisplayFps, *mRenderFps);
mFrame = (mFrame + 1) % buffers.size();
const auto buffer = buffers[mFrame];
createTransaction(mSurfaceControl->get()).setBuffer(mSurfaceControl->get(), buffer).apply();
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index a2966e6..d6f828f 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -19,6 +19,7 @@
#include <SkColor.h>
#include <vector>
+#include <ftl/flags.h>
#include <ftl/small_map.h>
#include <ui/LayerStack.h>
#include <ui/Size.h>
@@ -50,11 +51,16 @@
class RefreshRateOverlay {
public:
- RefreshRateOverlay(FpsRange, bool showSpinner);
+ enum class Features {
+ Spinner = 1 << 0,
+ RenderRate = 1 << 1,
+ };
+
+ RefreshRateOverlay(FpsRange, ftl::Flags<Features>);
void setLayerStack(ui::LayerStack);
void setViewport(ui::Size);
- void changeRefreshRate(Fps);
+ void changeRefreshRate(Fps, Fps);
void animate();
private:
@@ -62,32 +68,39 @@
class SevenSegmentDrawer {
public:
- static Buffers draw(int number, SkColor, ui::Transform::RotationFlags, bool showSpinner);
+ static Buffers draw(int displayFps, int renderFps, SkColor, ui::Transform::RotationFlags,
+ ftl::Flags<Features>);
private:
enum class Segment { Upper, UpperLeft, UpperRight, Middle, LowerLeft, LowerRight, Bottom };
static void drawSegment(Segment, int left, SkColor, SkCanvas&);
static void drawDigit(int digit, int left, SkColor, SkCanvas&);
+ static void drawNumber(int number, int left, SkColor, SkCanvas&);
};
- const Buffers& getOrCreateBuffers(Fps);
+ const Buffers& getOrCreateBuffers(Fps, Fps);
struct Key {
- int fps;
+ int displayFps;
+ int renderFps;
ui::Transform::RotationFlags flags;
- bool operator==(Key other) const { return fps == other.fps && flags == other.flags; }
+ bool operator==(Key other) const {
+ return displayFps == other.displayFps && renderFps == other.renderFps &&
+ flags == other.flags;
+ }
};
using BufferCache = ftl::SmallMap<Key, Buffers, 9>;
BufferCache mBufferCache;
- std::optional<Fps> mCurrentFps;
+ std::optional<Fps> mDisplayFps;
+ std::optional<Fps> mRenderFps;
size_t mFrame = 0;
const FpsRange mFpsRange; // For color interpolation.
- const bool mShowSpinner;
+ const ftl::Flags<Features> mFeatures;
const std::unique_ptr<SurfaceControlHolder> mSurfaceControl;
};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index 4be1ac7..a05d3df 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -107,7 +107,8 @@
}
using fps_approx_ops::operator/;
- const auto start = std::max(1u, fps / range.max - 1);
+ // use signed type as `fps / range.max` might be 0
+ const auto start = std::max(1, static_cast<int>(fps / range.max) - 1);
const auto end = fps /
std::max(range.min, RefreshRateSelector::kMinSupportedFrameRate,
fps_approx_ops::operator<);
@@ -836,21 +837,25 @@
return frameRateOverrides;
}
-std::optional<Fps> RefreshRateSelector::onKernelTimerChanged(
+ftl::Optional<FrameRateMode> RefreshRateSelector::onKernelTimerChanged(
std::optional<DisplayModeId> desiredActiveModeId, bool timerExpired) const {
std::lock_guard lock(mLock);
- const DisplayModePtr& current = desiredActiveModeId
- ? mDisplayModes.get(*desiredActiveModeId)->get()
- : getActiveModeLocked().modePtr.get();
+ const auto current = [&]() REQUIRES(mLock) -> FrameRateMode {
+ if (desiredActiveModeId) {
+ const auto& modePtr = mDisplayModes.get(*desiredActiveModeId)->get();
+ return FrameRateMode{modePtr->getFps(), ftl::as_non_null(modePtr)};
+ }
+
+ return getActiveModeLocked();
+ }();
const DisplayModePtr& min = mMinRefreshRateModeIt->second;
- if (current == min) {
+ if (current.modePtr->getId() == min->getId()) {
return {};
}
- const auto& mode = timerExpired ? min : current;
- return mode->getFps();
+ return timerExpired ? FrameRateMode{min->getFps(), ftl::as_non_null(min)} : current;
}
const DisplayModePtr& RefreshRateSelector::getMinRefreshRateByPolicyLocked() const {
@@ -1053,8 +1058,12 @@
const auto& primaryRanges = policy.primaryRanges;
const auto& appRequestRanges = policy.appRequestRanges;
ALOGE_IF(!appRequestRanges.physical.includes(primaryRanges.physical),
- "Physical range is invalid");
- ALOGE_IF(!appRequestRanges.render.includes(primaryRanges.render), "Render range is invalid");
+ "Physical range is invalid: primary: %s appRequest: %s",
+ to_string(primaryRanges.physical).c_str(),
+ to_string(appRequestRanges.physical).c_str());
+ ALOGE_IF(!appRequestRanges.render.includes(primaryRanges.render),
+ "Render range is invalid: primary: %s appRequest: %s",
+ to_string(primaryRanges.render).c_str(), to_string(appRequestRanges.render).c_str());
return primaryRanges.valid() && appRequestRanges.valid();
}
@@ -1156,8 +1165,8 @@
const auto frameRateModes = createFrameRateModes(filterModes, ranges.render);
LOG_ALWAYS_FATAL_IF(frameRateModes.empty(),
- "No matching frame rate modes for %s physicalRange %s", rangeName,
- to_string(ranges.physical).c_str());
+ "No matching frame rate modes for %s range. policy: %s", rangeName,
+ policy->toString().c_str());
const auto stringifyModes = [&] {
std::string str;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index 1ed16c6..4f5842a 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -240,8 +240,9 @@
return {mMinRefreshRateModeIt->second->getFps(), mMaxRefreshRateModeIt->second->getFps()};
}
- std::optional<Fps> onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveModeId,
- bool timerExpired) const EXCLUDES(mLock);
+ ftl::Optional<FrameRateMode> onKernelTimerChanged(
+ std::optional<DisplayModeId> desiredActiveModeId, bool timerExpired) const
+ EXCLUDES(mLock);
void setActiveMode(DisplayModeId, Fps renderFrameRate) EXCLUDES(mLock);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 365ffb7..bd3c0f1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -198,6 +198,9 @@
namespace {
+static constexpr int FOUR_K_WIDTH = 3840;
+static constexpr int FOUR_K_HEIGHT = 2160;
+
// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
@@ -245,6 +248,44 @@
return displaySupportKernelIdleTimer || sysprop::support_kernel_idle_timer(false);
}
+bool isAbove4k30(const ui::DisplayMode& outMode) {
+ using fps_approx_ops::operator>;
+ Fps refreshRate = Fps::fromValue(outMode.refreshRate);
+ return outMode.resolution.getWidth() >= FOUR_K_WIDTH &&
+ outMode.resolution.getHeight() >= FOUR_K_HEIGHT && refreshRate > 30_Hz;
+}
+
+void excludeDolbyVisionIf4k30Present(const std::vector<ui::Hdr>& displayHdrTypes,
+ ui::DisplayMode& outMode) {
+ if (isAbove4k30(outMode) &&
+ std::any_of(displayHdrTypes.begin(), displayHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::DOLBY_VISION_4K30; })) {
+ for (ui::Hdr type : displayHdrTypes) {
+ if (type != ui::Hdr::DOLBY_VISION_4K30 && type != ui::Hdr::DOLBY_VISION) {
+ outMode.supportedHdrTypes.push_back(type);
+ }
+ }
+ } else {
+ for (ui::Hdr type : displayHdrTypes) {
+ if (type != ui::Hdr::DOLBY_VISION_4K30) {
+ outMode.supportedHdrTypes.push_back(type);
+ }
+ }
+ }
+}
+
+HdrCapabilities filterOut4k30(const HdrCapabilities& displayHdrCapabilities) {
+ std::vector<ui::Hdr> hdrTypes;
+ for (ui::Hdr type : displayHdrCapabilities.getSupportedHdrTypes()) {
+ if (type != ui::Hdr::DOLBY_VISION_4K30) {
+ hdrTypes.push_back(type);
+ }
+ }
+ return {hdrTypes, displayHdrCapabilities.getDesiredMaxLuminance(),
+ displayHdrCapabilities.getDesiredMaxAverageLuminance(),
+ displayHdrCapabilities.getDesiredMinLuminance()};
+}
+
} // namespace anonymous
// ---------------------------------------------------------------------------
@@ -422,7 +463,9 @@
android::hardware::details::setTrebleTestingOverride(true);
}
- mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
+ mRefreshRateOverlaySpinner = property_get_bool("debug.sf.show_refresh_rate_overlay_spinner", 0);
+ mRefreshRateOverlayRenderRate =
+ property_get_bool("debug.sf.show_refresh_rate_overlay_render_rate", 0);
if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
mTransactionTracing.emplace();
@@ -1031,7 +1074,8 @@
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
outMode.presentationDeadline = period - outMode.sfVsyncOffset + 1000000;
-
+ excludeDolbyVisionIf4k30Present(display->getHdrCapabilities().getSupportedHdrTypes(),
+ outMode);
info->supportedDisplayModes.push_back(outMode);
}
@@ -1042,7 +1086,7 @@
info->activeDisplayModeId =
display->refreshRateSelector().getActiveMode().modePtr->getId().value();
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
- info->hdrCapabilities = display->getHdrCapabilities();
+ info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities());
info->autoLowLatencyModeSupported =
getHwComposer().hasDisplayCapability(displayId,
@@ -2830,7 +2874,7 @@
return Config::FrameRateOverride::AppOverrideNativeRefreshRates;
}
- if (!base::GetBoolProperty("debug.sf.frame_rate_override_global"s, false)) {
+ if (!sysprop::frame_rate_override_global(false)) {
return Config::FrameRateOverride::AppOverride;
}
@@ -6882,7 +6926,8 @@
for (const auto& [id, display] : mPhysicalDisplays) {
if (display.snapshot().connectionType() == ui::DisplayConnectionType::Internal) {
if (const auto device = getDisplayDeviceLocked(id)) {
- device->enableRefreshRateOverlay(enable, mRefreshRateOverlaySpinner);
+ device->enableRefreshRateOverlay(enable, mRefreshRateOverlaySpinner,
+ mRefreshRateOverlayRenderRate);
}
}
}
@@ -7352,6 +7397,10 @@
outMode.sfVsyncOffset = mode.sfVsyncOffset;
outMode.presentationDeadline = mode.presentationDeadline;
outMode.group = mode.group;
+ std::transform(mode.supportedHdrTypes.begin(), mode.supportedHdrTypes.end(),
+ std::back_inserter(outMode.supportedHdrTypes),
+ [](const ui::Hdr& value) { return static_cast<int32_t>(value); });
+
outInfo->supportedDisplayModes.push_back(outMode);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e3217a3..b9903a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -639,6 +639,8 @@
bool mKernelIdleTimerEnabled = false;
// Show spinner with refresh rate overlay
bool mRefreshRateOverlaySpinner = false;
+ // Show render rate with refresh rate overlay
+ bool mRefreshRateOverlayRenderRate = false;
void setDesiredActiveMode(display::DisplayModeRequest&&) REQUIRES(mStateLock);
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index c8c71df..5b73030 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -371,6 +371,10 @@
return SurfaceFlingerProperties::frame_rate_override_for_native_rates().value_or(defaultValue);
}
+bool frame_rate_override_global(bool defaultValue) {
+ return SurfaceFlingerProperties::frame_rate_override_global().value_or(defaultValue);
+}
+
bool enable_layer_caching(bool defaultValue) {
return SurfaceFlingerProperties::enable_layer_caching().value_or(defaultValue);
}
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 5e316cf..09629cf 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -98,6 +98,8 @@
bool frame_rate_override_for_native_rates(bool defaultValue);
+bool frame_rate_override_global(bool defaultValue);
+
bool enable_layer_caching(bool defaultValue);
bool enable_sdr_dimming(bool defaultValue);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index dbfce78..c0a6bdb 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -81,7 +81,6 @@
using types::V1_1::RenderIntent;
using types::V1_2::ColorMode;
using types::V1_2::Dataspace;
-using types::V1_2::Hdr;
using types::V1_2::PixelFormat;
using V2_1::Config;
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index 28da81f..8540c3d 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -447,8 +447,8 @@
# Limits the frame rate override feature (enable_frame_rate_override) to override the refresh rate
# to native display refresh rates only. Before introducing this flag, native display refresh rates
-# was the default behvaiour. With this flag we can control which behaviour we want explicitly.
-# This flag is intoruduced as a fail-safe machanism and planned to be defaulted to false.
+# was the default behaviour. With this flag we can control which behaviour we want explicitly.
+# This flag is introduced as a fail-safe mechanism and planned to be defaulted to false.
prop {
api_name: "frame_rate_override_for_native_rates"
type: Boolean
@@ -457,6 +457,16 @@
prop_name: "ro.surface_flinger.frame_rate_override_for_native_rates"
}
+# Enables the frame rate override feature (enable_frame_rate_override) to
+# override the frame rate globally instead of only for individual apps.
+prop {
+ api_name: "frame_rate_override_global"
+ type: Boolean
+ scope: Public
+ access: Readonly
+ prop_name: "ro.surface_flinger.frame_rate_override_global"
+}
+
# Enables Layer Caching
prop {
api_name: "enable_layer_caching"
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index 0dfb80e..9338133 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -65,6 +65,10 @@
prop_name: "ro.surface_flinger.frame_rate_override_for_native_rates"
}
prop {
+ api_name: "frame_rate_override_global"
+ prop_name: "ro.surface_flinger.frame_rate_override_global"
+ }
+ prop {
api_name: "has_HDR_display"
prop_name: "ro.surface_flinger.has_HDR_display"
}
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 0114577..8b0cd78 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -111,6 +111,7 @@
"SurfaceFlinger_SetPowerModeInternalTest.cpp",
"SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
"SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp",
+ "SurfaceFlinger_ExcludeDolbyVisionTest.cpp",
"SchedulerTest.cpp",
"SetFrameRateTest.cpp",
"RefreshRateSelectorTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index fdf2ffe..a3b3c4c 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -2943,5 +2943,18 @@
EXPECT_EQ(kModeId35, selector.getBestFrameRateMode({}, {.idle = true})->getId());
}
+TEST_P(RefreshRateSelectorTest, policyCanBeInfinity) {
+ auto selector = createSelector(kModes_60_120, kModeId120);
+
+ constexpr Fps inf = Fps::fromValue(std::numeric_limits<float>::infinity());
+
+ using namespace fps_approx_ops;
+ selector.setDisplayManagerPolicy({kModeId60, {0_Hz, inf}});
+
+ // With no layers, idle should still be lower priority than touch boost.
+ EXPECT_EQ(kMode120, selector.getMaxRefreshRateByPolicy());
+ EXPECT_EQ(kMode60, selector.getMinRefreshRateByPolicy());
+}
+
} // namespace
} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_ExcludeDolbyVisionTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ExcludeDolbyVisionTest.cpp
new file mode 100644
index 0000000..11e734a
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ExcludeDolbyVisionTest.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include "DisplayTransactionTestHelpers.h"
+
+namespace android {
+namespace {
+
+using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
+
+class ExcludeDolbyVisionTest : public DisplayTransactionTest {
+public:
+ void injectDisplayModes(std::vector<DisplayModePtr> displayModePtrs) {
+ DisplayModes modes;
+ for (DisplayModePtr displayMode : displayModePtrs) {
+ modes.try_emplace(displayMode->getId(), displayMode);
+ }
+
+ mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
+ .setDisplayModes(std::move(modes), displayModePtrs[0]->getId())
+ .inject();
+ mDisplay->overrideHdrTypes(types);
+ }
+
+protected:
+ sp<DisplayDevice> mDisplay;
+
+ static constexpr DisplayModeId modeId1080p60{0};
+ static constexpr DisplayModeId modeId4k30{1};
+ static constexpr DisplayModeId modeId4k60{2};
+
+ static inline const DisplayModePtr mode1080p60 =
+ createDisplayMode(modeId1080p60, 60_Hz, 0, ui::Size(1920, 1080));
+ static inline const DisplayModePtr mode4k30 =
+ createDisplayMode(modeId4k30, 30_Hz, 1, ui::Size(3840, 2160));
+ static inline const DisplayModePtr mode4k30NonStandard =
+ createDisplayMode(modeId4k30, 30.1_Hz, 1, ui::Size(3840, 2160));
+ static inline const DisplayModePtr mode4k60 =
+ createDisplayMode(modeId4k60, 60_Hz, 2, ui::Size(3840, 2160));
+
+ const std::vector<ui::Hdr> types = {ui::Hdr::DOLBY_VISION, ui::Hdr::DOLBY_VISION_4K30,
+ ui::Hdr::HDR10_PLUS};
+};
+
+TEST_F(ExcludeDolbyVisionTest, excludesDolbyVisionOnModesHigherThan4k30) {
+ injectDisplayModes({mode4k60});
+ ui::DynamicDisplayInfo info;
+ mFlinger.getDynamicDisplayInfo(mDisplay->getDisplayToken().promote(), &info);
+
+ std::vector<ui::DisplayMode> displayModes = info.supportedDisplayModes;
+
+ ASSERT_EQ(1, displayModes.size());
+ ASSERT_TRUE(std::any_of(displayModes[0].supportedHdrTypes.begin(),
+ displayModes[0].supportedHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::HDR10_PLUS; }));
+ ASSERT_TRUE(displayModes[0].supportedHdrTypes.size() == 1);
+}
+
+TEST_F(ExcludeDolbyVisionTest, includesDolbyVisionOnModesLowerThanOrEqualTo4k30) {
+ injectDisplayModes({mode1080p60, mode4k30, mode4k30NonStandard});
+ ui::DynamicDisplayInfo info;
+ mFlinger.getDynamicDisplayInfo(mDisplay->getDisplayToken().promote(), &info);
+
+ std::vector<ui::DisplayMode> displayModes = info.supportedDisplayModes;
+
+ ASSERT_EQ(2, displayModes.size());
+ for (size_t i = 0; i < displayModes.size(); i++) {
+ ASSERT_TRUE(std::any_of(displayModes[i].supportedHdrTypes.begin(),
+ displayModes[i].supportedHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::HDR10_PLUS; }));
+ ASSERT_TRUE(std::any_of(displayModes[i].supportedHdrTypes.begin(),
+ displayModes[i].supportedHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::DOLBY_VISION; }));
+ ASSERT_TRUE(displayModes[i].supportedHdrTypes.size() == 2);
+ }
+}
+
+TEST_F(ExcludeDolbyVisionTest, 4k30IsNotReportedAsAValidHdrType) {
+ injectDisplayModes({mode4k60});
+ ui::DynamicDisplayInfo info;
+ mFlinger.getDynamicDisplayInfo(mDisplay->getDisplayToken().promote(), &info);
+
+ std::vector<ui::Hdr> displayHdrTypes = info.hdrCapabilities.getSupportedHdrTypes();
+
+ ASSERT_EQ(2, displayHdrTypes.size());
+ ASSERT_TRUE(std::any_of(displayHdrTypes.begin(), displayHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::HDR10_PLUS; }));
+ ASSERT_TRUE(std::any_of(displayHdrTypes.begin(), displayHdrTypes.end(),
+ [](ui::Hdr type) { return type == ui::Hdr::DOLBY_VISION; }));
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index e29dd67..c8362ee 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -30,6 +30,7 @@
#include <ftl/fake_guard.h>
#include <gui/ScreenCaptureResults.h>
+#include <ui/DynamicDisplayInfo.h>
#include "DisplayDevice.h"
#include "FakeVsyncConfiguration.h"
#include "FrameTracer/FrameTracer.h"
@@ -486,6 +487,11 @@
void updateLayerMetadataSnapshot() { mFlinger->updateLayerMetadataSnapshot(); }
+ void getDynamicDisplayInfo(const sp<IBinder>& displayToken,
+ ui::DynamicDisplayInfo* dynamicDisplayInfo) {
+ mFlinger->getDynamicDisplayInfo(displayToken, dynamicDisplayInfo);
+ }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/
@@ -643,7 +649,6 @@
// is much longer lived.
auto display = std::make_unique<HWC2Display>(*composer, *mCapabilities, mHwcDisplayId,
mHwcDisplayType);
-
display->mutableIsConnected() = true;
display->setPowerMode(mPowerMode);
flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
@@ -652,7 +657,6 @@
.WillRepeatedly(
DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
Return(hal::Error::NONE)));
-
EXPECT_CALL(*composer,
getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
.WillRepeatedly(DoAll(SetArgPointee<3>(mResolution.getWidth()),
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 5ee38ec..836e3a4 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -32,7 +32,6 @@
using android::hardware::graphics::common::V1_1::RenderIntent;
using android::hardware::graphics::common::V1_2::ColorMode;
using android::hardware::graphics::common::V1_2::Dataspace;
-using android::hardware::graphics::common::V1_2::Hdr;
using android::hardware::graphics::common::V1_2::PixelFormat;
using android::hardware::graphics::composer::V2_1::Config;
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 4927150..a99355f 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -1027,8 +1027,11 @@
}
}
-bool GetAndroidNativeBufferSpecVersion9Support(
- VkPhysicalDevice physicalDevice) {
+VkResult GetAndroidNativeBufferSpecVersion9Support(
+ VkPhysicalDevice physicalDevice,
+ bool& support) {
+ support = false;
+
const InstanceData& data = GetData(physicalDevice);
// Call to get propertyCount
@@ -1038,6 +1041,10 @@
physicalDevice, nullptr, &propertyCount, nullptr);
ATRACE_END();
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+ return result;
+ }
+
// Call to enumerate properties
std::vector<VkExtensionProperties> properties(propertyCount);
ATRACE_BEGIN("driver.EnumerateDeviceExtensionProperties");
@@ -1045,6 +1052,10 @@
physicalDevice, nullptr, &propertyCount, properties.data());
ATRACE_END();
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+ return result;
+ }
+
for (uint32_t i = 0; i < propertyCount; i++) {
auto& prop = properties[i];
@@ -1053,11 +1064,12 @@
continue;
if (prop.specVersion >= 9) {
- return true;
+ support = true;
+ return result;
}
}
- return false;
+ return result;
}
VkResult EnumerateDeviceExtensionProperties(
@@ -1101,18 +1113,30 @@
swapchainCompFeats.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT;
swapchainCompFeats.pNext = nullptr;
+ swapchainCompFeats.imageCompressionControlSwapchain = false;
VkPhysicalDeviceImageCompressionControlFeaturesEXT imageCompFeats = {};
imageCompFeats.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT;
imageCompFeats.pNext = &swapchainCompFeats;
+ imageCompFeats.imageCompressionControl = false;
VkPhysicalDeviceFeatures2 feats2 = {};
feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
feats2.pNext = &imageCompFeats;
- GetPhysicalDeviceFeatures2(physicalDevice, &feats2);
+ const auto& driver = GetData(physicalDevice).driver;
+ if (driver.GetPhysicalDeviceFeatures2 ||
+ driver.GetPhysicalDeviceFeatures2KHR) {
+ GetPhysicalDeviceFeatures2(physicalDevice, &feats2);
+ }
- bool anb9 = GetAndroidNativeBufferSpecVersion9Support(physicalDevice);
+ bool anb9 = false;
+ VkResult result =
+ GetAndroidNativeBufferSpecVersion9Support(physicalDevice, anb9);
+
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+ return result;
+ }
if (anb9 && imageCompFeats.imageCompressionControl) {
loader_extensions.push_back(
@@ -1142,7 +1166,7 @@
}
ATRACE_BEGIN("driver.EnumerateDeviceExtensionProperties");
- VkResult result = data.driver.EnumerateDeviceExtensionProperties(
+ result = data.driver.EnumerateDeviceExtensionProperties(
physicalDevice, pLayerName, pPropertyCount, pProperties);
ATRACE_END();
@@ -1532,6 +1556,11 @@
} break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN_FEATURES_EXT: {
+ VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT*
+ compressionFeat = reinterpret_cast<
+ VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT*>(
+ pFeats);
+ compressionFeat->imageCompressionControlSwapchain = false;
imageCompressionControlSwapchainInChain = true;
} break;
@@ -1551,6 +1580,7 @@
imageCompFeats.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_COMPRESSION_CONTROL_FEATURES_EXT;
imageCompFeats.pNext = nullptr;
+ imageCompFeats.imageCompressionControl = false;
VkPhysicalDeviceFeatures2 feats2 = {};
feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 475bc40..759149d 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -930,27 +930,36 @@
return GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice,
pSurfaceInfo->surface,
pSurfaceFormatCount, nullptr);
- } else {
- // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
- // after the call.
- std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount);
- VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
- physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
- surface_formats.data());
+ }
- if (result == VK_SUCCESS || result == VK_INCOMPLETE) {
- const auto& driver = GetData(physicalDevice).driver;
+ // temp vector for forwarding; we'll marshal it into the pSurfaceFormats
+ // after the call.
+ std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount);
+ VkResult result = GetPhysicalDeviceSurfaceFormatsKHR(
+ physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount,
+ surface_formats.data());
- // marshal results individually due to stride difference.
- uint32_t formats_to_marshal = *pSurfaceFormatCount;
- for (uint32_t i = 0u; i < formats_to_marshal; i++) {
- pSurfaceFormats[i].surfaceFormat = surface_formats[i];
+ if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+ return result;
+ }
- // Query the compression properties for the surface format
- if (pSurfaceFormats[i].pNext) {
+ const auto& driver = GetData(physicalDevice).driver;
+
+ // marshal results individually due to stride difference.
+ uint32_t formats_to_marshal = *pSurfaceFormatCount;
+ for (uint32_t i = 0u; i < formats_to_marshal; i++) {
+ pSurfaceFormats[i].surfaceFormat = surface_formats[i];
+
+ // Query the compression properties for the surface format
+ VkSurfaceFormat2KHR* pSurfaceFormat = &pSurfaceFormats[i];
+ while (pSurfaceFormat->pNext) {
+ pSurfaceFormat =
+ reinterpret_cast<VkSurfaceFormat2KHR*>(pSurfaceFormat->pNext);
+ switch (pSurfaceFormat->sType) {
+ case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_PROPERTIES_EXT: {
VkImageCompressionPropertiesEXT* surfaceCompressionProps =
reinterpret_cast<VkImageCompressionPropertiesEXT*>(
- pSurfaceFormats[i].pNext);
+ pSurfaceFormat);
if (surfaceCompressionProps &&
driver.GetPhysicalDeviceImageFormatProperties2KHR) {
@@ -992,12 +1001,16 @@
return compressionRes;
}
}
- }
+ } break;
+
+ default:
+ // Ignore all other extension structs
+ break;
}
}
-
- return result;
}
+
+ return result;
}
VKAPI_ATTR