Merge changes from topic "gestures-lib-sysprop"
* changes:
Use a sysprop to enable `TouchpadInputMapper`
Add gestures library to whole_static_libs for input reader
diff --git a/Android.bp b/Android.bp
index 615a7a8..3992f82 100644
--- a/Android.bp
+++ b/Android.bp
@@ -56,7 +56,8 @@
cc_library_headers {
name: "libandroid_sensor_headers",
- vendor: true,
+ vendor_available: true,
+ host_supported: true,
export_include_dirs: ["include_sensor"],
}
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/binder/trusty/include/log/log.h b/libs/binder/trusty/include/log/log.h
index d88d18a..de84617 100644
--- a/libs/binder/trusty/include/log/log.h
+++ b/libs/binder/trusty/include/log/log.h
@@ -121,6 +121,8 @@
TLOGE("android_errorWriteLog: tag:%x subTag:%s\n", tag, subTag); \
} while (0)
-extern "C" inline void __assert(const char* file, int line, const char* str) {
- LOG_ALWAYS_FATAL("%s:%d: assertion \"%s\" failed", file, line, str);
-}
+// Override the definition of __assert from binder_status.h
+#ifndef __BIONIC__
+#undef __assert
+#define __assert(file, line, str) LOG_ALWAYS_FATAL("%s:%d: %s", file, line, str)
+#endif // __BIONIC__
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index aaa2102..325c294 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2337,6 +2337,7 @@
}
outInfo->activeDisplayModeId = ginfo.activeDisplayModeId;
+ outInfo->renderFrameRate = ginfo.renderFrameRate;
outInfo->supportedColorModes.clear();
outInfo->supportedColorModes.reserve(ginfo.supportedColorModes.size());
diff --git a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
index 57e6081..3114929 100644
--- a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
+++ b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
@@ -27,6 +27,7 @@
List<DisplayMode> supportedDisplayModes;
int activeDisplayModeId;
+ float renderFrameRate;
int[] supportedColorModes;
int activeColorMode;
diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h
index 8c9fe4c..0b77754 100644
--- a/libs/ui/include/ui/DynamicDisplayInfo.h
+++ b/libs/ui/include/ui/DynamicDisplayInfo.h
@@ -35,6 +35,7 @@
// we can't use size_t because it may have different width
// in the client process.
ui::DisplayModeId activeDisplayModeId;
+ float renderFrameRate;
std::vector<ui::ColorMode> supportedColorModes;
ui::ColorMode activeColorMode;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 466c51e..4aac377 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -148,21 +148,23 @@
}
bool isValidMotionAction(int32_t action, int32_t actionButton, int32_t pointerCount) {
- switch (action & AMOTION_EVENT_ACTION_MASK) {
+ switch (MotionEvent::getActionMasked(action)) {
case AMOTION_EVENT_ACTION_DOWN:
case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
+ return pointerCount == 1;
case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_OUTSIDE:
case AMOTION_EVENT_ACTION_HOVER_ENTER:
case AMOTION_EVENT_ACTION_HOVER_MOVE:
case AMOTION_EVENT_ACTION_HOVER_EXIT:
+ return pointerCount >= 1;
+ case AMOTION_EVENT_ACTION_CANCEL:
+ case AMOTION_EVENT_ACTION_OUTSIDE:
case AMOTION_EVENT_ACTION_SCROLL:
return true;
case AMOTION_EVENT_ACTION_POINTER_DOWN:
case AMOTION_EVENT_ACTION_POINTER_UP: {
- int32_t index = getMotionEventActionPointerIndex(action);
- return index >= 0 && index < pointerCount;
+ const int32_t index = MotionEvent::getActionIndex(action);
+ return index >= 0 && index < pointerCount && pointerCount > 1;
}
case AMOTION_EVENT_ACTION_BUTTON_PRESS:
case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
@@ -2096,7 +2098,7 @@
bool isSplit = shouldSplitTouch(tempTouchState, entry);
const bool switchedDevice = (oldState != nullptr) &&
- (tempTouchState.deviceId != entry.deviceId || tempTouchState.source != entry.source);
+ (oldState->deviceId != entry.deviceId || oldState->source != entry.source);
const bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE ||
maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
@@ -2104,6 +2106,7 @@
const bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN ||
maskedAction == AMOTION_EVENT_ACTION_SCROLL || isHoverAction);
const bool isFromMouse = isFromSource(entry.source, AINPUT_SOURCE_MOUSE);
+
if (newGesture) {
bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
if (switchedDevice && tempTouchState.isDown() && !down && !isHoverAction) {
@@ -2995,6 +2998,8 @@
connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
+ LOG_ALWAYS_FATAL_IF(!inputTarget.flags.any(InputTarget::DISPATCH_MASK),
+ "No dispatch flags are set for %s", eventEntry->getDescription().c_str());
const bool wasEmpty = connection->outboundQueue.empty();
@@ -4053,10 +4058,9 @@
args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
}
}
- if (!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
- args->pointerProperties)) {
- return;
- }
+ LOG_ALWAYS_FATAL_IF(!validateMotionEvent(args->action, args->actionButton, args->pointerCount,
+ args->pointerProperties),
+ "Invalid event: %s", args->dump().c_str());
uint32_t policyFlags = args->policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
@@ -4981,10 +4985,6 @@
}
}
}
-
- if (DEBUG_FOCUS) {
- logDispatchStateLocked();
- }
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
@@ -5015,10 +5015,6 @@
} else {
changed = false;
}
-
- if (DEBUG_FOCUS) {
- logDispatchStateLocked();
- }
} // release lock
if (changed) {
@@ -5193,10 +5189,6 @@
synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection);
}
-
- if (DEBUG_FOCUS) {
- logDispatchStateLocked();
- }
} // release lock
// Wake up poll loop since it may need to make new input dispatching choices.
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 114e0bf..c21af9e 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -34,8 +34,7 @@
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle,
ftl::Flags<InputTarget::Flags> targetFlags, BitSet32 pointerIds,
std::optional<nsecs_t> eventTime) {
- for (size_t i = 0; i < windows.size(); i++) {
- TouchedWindow& touchedWindow = windows[i];
+ for (TouchedWindow& touchedWindow : windows) {
if (touchedWindow.windowHandle == windowHandle) {
touchedWindow.targetFlags |= targetFlags;
if (targetFlags.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 2a8b359..53d821f 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -44,6 +44,7 @@
"FakeInputReaderPolicy.cpp",
"FakePointerController.cpp",
"FocusResolver_test.cpp",
+ "InputMapperTest.cpp",
"InputProcessor_test.cpp",
"InputProcessorConverter_test.cpp",
"InputDispatcher_test.cpp",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index f3239ca..41c174a 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -110,6 +110,13 @@
*result_listener << "expected action " << MotionEvent::actionToString(action)
<< ", but got " << MotionEvent::actionToString(arg.getAction());
}
+ if (action == AMOTION_EVENT_ACTION_DOWN) {
+ if (!matches) {
+ *result_listener << "; ";
+ }
+ *result_listener << "downTime should match eventTime for ACTION_DOWN events";
+ matches &= arg.getDownTime() == arg.getEventTime();
+ }
if (action == AMOTION_EVENT_ACTION_CANCEL) {
if (!matches) {
*result_listener << "; ";
@@ -120,6 +127,10 @@
return matches;
}
+MATCHER_P(WithDownTime, downTime, "InputEvent with specified downTime") {
+ return arg.getDownTime() == downTime;
+}
+
MATCHER_P(WithSource, source, "InputEvent with specified source") {
*result_listener << "expected source " << inputEventSourceToString(source) << ", but got "
<< inputEventSourceToString(arg.getSource());
@@ -1210,6 +1221,7 @@
void consumeMotionOutsideWithZeroedCoords(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
int32_t expectedFlags = 0) {
InputEvent* event = consume();
+ ASSERT_NE(nullptr, event);
ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
const MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
EXPECT_EQ(AMOTION_EVENT_ACTION_OUTSIDE, motionEvent.getActionMasked());
@@ -1231,7 +1243,7 @@
void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
MotionEvent* motionEvent = consumeMotion();
- ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event";
+ ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event, but expected " << matcher;
ASSERT_THAT(*motionEvent, matcher);
}
@@ -2056,6 +2068,7 @@
mDispatcher->waitForIdle();
InputEvent* inputEvent1 = window1->consume();
+ ASSERT_NE(inputEvent1, nullptr);
window2->assertNoEvents();
MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
@@ -2065,6 +2078,7 @@
mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
mDispatcher->waitForIdle();
InputEvent* inputEvent2 = window2->consume();
+ ASSERT_NE(inputEvent2, nullptr);
MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
@@ -2074,17 +2088,13 @@
mDispatcher->notifyMotion(
&(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
mDispatcher->waitForIdle();
- InputEvent* inputEvent3 = window2->consume();
- MotionEvent& motionEvent3 = static_cast<MotionEvent&>(*inputEvent3);
- ASSERT_EQ(motionEvent3.getDownTime(), downTimeForWindow2);
+ window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
// Now add new touch down on the second window
mDispatcher->notifyMotion(
&(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
mDispatcher->waitForIdle();
- InputEvent* inputEvent4 = window2->consume();
- MotionEvent& motionEvent4 = static_cast<MotionEvent&>(*inputEvent4);
- ASSERT_EQ(motionEvent4.getDownTime(), downTimeForWindow2);
+ window2->consumeMotionEvent(WithDownTime(downTimeForWindow2));
// TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
window1->consumeMotionMove();
@@ -2094,16 +2104,12 @@
mDispatcher->notifyMotion(
&(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
mDispatcher->waitForIdle();
- InputEvent* inputEvent5 = window1->consume();
- MotionEvent& motionEvent5 = static_cast<MotionEvent&>(*inputEvent5);
- ASSERT_EQ(motionEvent5.getDownTime(), downTimeForWindow1);
+ window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
mDispatcher->notifyMotion(&(
args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
mDispatcher->waitForIdle();
- InputEvent* inputEvent6 = window1->consume();
- MotionEvent& motionEvent6 = static_cast<MotionEvent&>(*inputEvent6);
- ASSERT_EQ(motionEvent6.getDownTime(), downTimeForWindow1);
+ window1->consumeMotionEvent(WithDownTime(downTimeForWindow1));
}
TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
@@ -2128,10 +2134,8 @@
.x(900)
.y(400))
.build()));
- windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
- windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+ windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
// Move cursor into left window
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -2142,12 +2146,9 @@
.x(300)
.y(400))
.build()));
- windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
- windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
- windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
+ windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+ windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
// Inject a series of mouse events for a mouse click
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -2170,8 +2171,7 @@
.x(300)
.y(400))
.build()));
- windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(mDispatcher,
@@ -2183,8 +2183,7 @@
.x(300)
.y(400))
.build()));
- windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(mDispatcher,
@@ -2205,12 +2204,47 @@
.x(900)
.y(400))
.build()));
- windowLeft->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
- windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
- windowRight->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
+ windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+ windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
+
+ // No more events
+ windowLeft->assertNoEvents();
+ windowRight->assertNoEvents();
+}
+
+TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+
+ sp<FakeWindowHandle> spyWindow =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
+ spyWindow->setFrame(Rect(0, 0, 600, 800));
+ spyWindow->setTrustedOverlay(true);
+ spyWindow->setSpy(true);
+ sp<FakeWindowHandle> window =
+ sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT);
+ window->setFrame(Rect(0, 0, 600, 800));
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spyWindow, window}}});
+
+ // Send mouse cursor to the window
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher,
+ MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
+ AINPUT_SOURCE_MOUSE)
+ .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE)
+ .x(100)
+ .y(100))
+ .build()));
+
+ window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
+ WithSource(AINPUT_SOURCE_MOUSE)));
+ spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
+ WithSource(AINPUT_SOURCE_MOUSE)));
+
+ window->assertNoEvents();
+ spyWindow->assertNoEvents();
}
// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
@@ -2233,8 +2267,7 @@
.x(300)
.y(400))
.build()));
- window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
// Inject a series of mouse events for a mouse click
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
@@ -2257,8 +2290,7 @@
.x(300)
.y(400))
.build()));
- window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_PRESS,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(mDispatcher,
@@ -2270,8 +2302,7 @@
.x(300)
.y(400))
.build()));
- window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_BUTTON_RELEASE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(mDispatcher,
@@ -2291,8 +2322,7 @@
.x(300)
.y(400))
.build()));
- window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_EXIT,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
}
/**
@@ -2362,14 +2392,13 @@
.x(300)
.y(600))
.build()));
- windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
- windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
+ windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE));
// Remove all windows in secondary display and check that no event happens on window in
// primary display.
- mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}});
+ mDispatcher->setInputWindows(
+ {{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, {SECOND_DISPLAY_ID, {}}});
windowDefaultDisplay->assertNoEvents();
// Move cursor position in window in default display and check that only hover move
@@ -2385,8 +2414,9 @@
.x(400)
.y(700))
.build()));
- windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE,
- ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */);
+ windowDefaultDisplay->consumeMotionEvent(
+ AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
+ WithSource(AINPUT_SOURCE_MOUSE)));
windowDefaultDisplay->assertNoEvents();
}
@@ -4669,6 +4699,7 @@
const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
assertMotionAction(expectedAction, motionEvent.getAction());
+ ASSERT_EQ(points.size(), motionEvent.getPointerCount());
for (size_t i = 0; i < points.size(); i++) {
float expectedX = points[i].x;
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 58f1e1e..eef5690 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -45,6 +45,7 @@
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
#include "FakePointerController.h"
+#include "InputMapperTest.h"
#include "InstrumentedInputReader.h"
#include "TestConstants.h"
#include "android/hardware/input/InputDeviceCountryCode.h"
@@ -92,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.
@@ -2507,195 +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,
- ui::Rotation 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 {
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/sensorservice/aidl/utils.cpp b/services/sensorservice/aidl/utils.cpp
index 26bcdc5..beb38b9 100644
--- a/services/sensorservice/aidl/utils.cpp
+++ b/services/sensorservice/aidl/utils.cpp
@@ -58,7 +58,7 @@
::aidl::android::hardware::sensors::Event convertEvent(const ::ASensorEvent& src) {
::aidl::android::hardware::sensors::Event dst;
::android::hardware::sensors::implementation::
- convertFromSensorEvent(reinterpret_cast<const sensors_event_t&>(src), &dst);
+ convertFromASensorEvent(src, &dst);
return dst;
}
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
index 2f9e922..5fa594d 100644
--- a/services/sensorservice/hidl/utils.cpp
+++ b/services/sensorservice/hidl/utils.cpp
@@ -76,8 +76,8 @@
::android::hardware::sensors::V1_0::Event convertEvent(const ::ASensorEvent& src) {
::android::hardware::sensors::V1_0::Event dst;
- ::android::hardware::sensors::V1_0::implementation::convertFromSensorEvent(
- reinterpret_cast<const sensors_event_t&>(src), &dst);
+ ::android::hardware::sensors::V1_0::implementation::convertFromASensorEvent(
+ src, &dst);
return dst;
}
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 1acf15a..008d8c4 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -124,12 +124,12 @@
return event;
}
-DisplayEventReceiver::Event makeModeChanged(DisplayModePtr mode) {
+DisplayEventReceiver::Event makeModeChanged(const scheduler::FrameRateMode& mode) {
DisplayEventReceiver::Event event;
- event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, mode->getPhysicalDisplayId(),
- systemTime()};
- event.modeChange.modeId = mode->getId().value();
- event.modeChange.vsyncPeriod = mode->getVsyncPeriod();
+ event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
+ mode.modePtr->getPhysicalDisplayId(), systemTime()};
+ event.modeChange.modeId = mode.modePtr->getId().value();
+ event.modeChange.vsyncPeriod = mode.fps.getPeriodNsecs();
return event;
}
@@ -405,7 +405,7 @@
mCondition.notify_all();
}
-void EventThread::onModeChanged(DisplayModePtr mode) {
+void EventThread::onModeChanged(const scheduler::FrameRateMode& mode) {
std::lock_guard<std::mutex> lock(mMutex);
mPendingEvents.push_back(makeModeChanged(mode));
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 7a5a348..43c3598 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include <scheduler/FrameRateMode.h>
#include <condition_variable>
#include <cstdint>
#include <deque>
@@ -134,7 +135,7 @@
virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
// called when SF changes the active mode and apps needs to be notified about the change
- virtual void onModeChanged(DisplayModePtr) = 0;
+ virtual void onModeChanged(const scheduler::FrameRateMode&) = 0;
// called when SF updates the Frame Rate Override list
virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
@@ -185,7 +186,7 @@
void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
- void onModeChanged(DisplayModePtr) override;
+ void onModeChanged(const scheduler::FrameRateMode&) override;
void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 7f8f600..34f8df2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -330,7 +330,7 @@
RETURN_IF_INVALID_HANDLE(handle);
thread = mConnections[handle].thread.get();
}
- thread->onModeChanged(mode.modePtr.get());
+ thread->onModeChanged(mode);
}
size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bd3c0f1..cc4e082 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1083,8 +1083,9 @@
const PhysicalDisplayId displayId = snapshot.displayId();
- info->activeDisplayModeId =
- display->refreshRateSelector().getActiveMode().modePtr->getId().value();
+ const auto mode = display->refreshRateSelector().getActiveMode();
+ info->activeDisplayModeId = mode.modePtr->getId().value();
+ info->renderFrameRate = mode.fps.getValue();
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
info->hdrCapabilities = filterOut4k30(display->getHdrCapabilities());
@@ -1127,8 +1128,8 @@
return;
}
- const Fps renderFps = request.mode.fps;
- const Fps displayFps = request.mode.modePtr->getFps();
+ const auto mode = request.mode;
+ const bool emitEvent = request.emitEvent;
switch (display->setDesiredActiveMode(DisplayDevice::ActiveModeInfo(std::move(request)))) {
case DisplayDevice::DesiredActiveModeAction::InitiateDisplayModeSwitch:
@@ -1136,21 +1137,22 @@
// Start receiving vsync samples now, so that we can detect a period
// switch.
- mScheduler->resyncToHardwareVsync(true, displayFps);
+ mScheduler->resyncToHardwareVsync(true, mode.modePtr->getFps());
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// VsyncController model is locked.
modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
- updatePhaseConfiguration(renderFps);
+ updatePhaseConfiguration(mode.fps);
mScheduler->setModeChangePending(true);
break;
case DisplayDevice::DesiredActiveModeAction::InitiateRenderRateSwitch:
- mScheduler->setRenderRate(renderFps);
- updatePhaseConfiguration(renderFps);
- mRefreshRateStats->setRefreshRate(renderFps);
+ mScheduler->setRenderRate(mode.fps);
+ updatePhaseConfiguration(mode.fps);
+ mRefreshRateStats->setRefreshRate(mode.fps);
+ if (display->getPhysicalId() == mActiveDisplayId && emitEvent) {
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, mode);
+ }
- // TODO(b/259740021): send event to display manager about
- // the render rate change
break;
case DisplayDevice::DesiredActiveModeAction::None:
break;
@@ -7405,6 +7407,7 @@
}
outInfo->activeDisplayModeId = info.activeDisplayModeId;
+ outInfo->renderFrameRate = info.renderFrameRate;
outInfo->supportedColorModes.clear();
outInfo->supportedColorModes.reserve(info.supportedColorModes.size());
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index a5beaba..dd87f9d 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -633,9 +633,10 @@
.setId(DisplayModeId(7))
.setVsyncPeriod(16666666)
.build();
+ const Fps fps = mode->getFps() / 2;
- mThread->onModeChanged(mode);
- expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, 16666666);
+ mThread->onModeChanged({fps, ftl::as_non_null(mode)});
+ expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, fps.getPeriodNsecs());
}
TEST_F(EventThreadTest, postConfigChangedExternal) {
@@ -644,9 +645,10 @@
.setId(DisplayModeId(5))
.setVsyncPeriod(16666666)
.build();
+ const Fps fps = mode->getFps() / 2;
- mThread->onModeChanged(mode);
- expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, 16666666);
+ mThread->onModeChanged({fps, ftl::as_non_null(mode)});
+ expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, fps.getPeriodNsecs());
}
TEST_F(EventThreadTest, postConfigChangedPrimary64bit) {
@@ -655,8 +657,9 @@
.setId(DisplayModeId(7))
.setVsyncPeriod(16666666)
.build();
- mThread->onModeChanged(mode);
- expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, 16666666);
+ const Fps fps = mode->getFps() / 2;
+ mThread->onModeChanged({fps, ftl::as_non_null(mode)});
+ expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, fps.getPeriodNsecs());
}
TEST_F(EventThreadTest, suppressConfigChanged) {
@@ -669,9 +672,10 @@
.setId(DisplayModeId(9))
.setVsyncPeriod(16666666)
.build();
+ const Fps fps = mode->getFps() / 2;
- mThread->onModeChanged(mode);
- expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666);
+ mThread->onModeChanged({fps, ftl::as_non_null(mode)});
+ expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, fps.getPeriodNsecs());
auto args = suppressConnectionEventRecorder.waitForCall();
ASSERT_FALSE(args.has_value());
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index b81693a..074bf8c 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -144,7 +144,8 @@
// Verify that the next commit will complete the mode change and send
// a onModeChanged event to the framework.
- EXPECT_CALL(*mAppEventThread, onModeChanged(kMode90));
+ EXPECT_CALL(*mAppEventThread,
+ onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)}));
mFlinger.commit();
Mock::VerifyAndClearExpectations(mAppEventThread);
@@ -175,7 +176,8 @@
hal::HWConfigId(kModeId90.value()), _, _))
.WillOnce(DoAll(SetArgPointee<3>(timeline), Return(Error::NONE)));
- EXPECT_CALL(*mAppEventThread, onModeChanged(kMode90));
+ EXPECT_CALL(*mAppEventThread,
+ onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)}));
mFlinger.commit();
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index ded6806..f8567bd 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -34,7 +34,7 @@
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
- MOCK_METHOD1(onModeChanged, void(DisplayModePtr));
+ MOCK_METHOD1(onModeChanged, void(const scheduler::FrameRateMode &));
MOCK_METHOD2(onFrameRateOverridesChanged,
void(PhysicalDisplayId, std::vector<FrameRateOverride>));
MOCK_CONST_METHOD1(dump, void(std::string&));
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