Merge "SF: trace the render rate of an app" into main
diff --git a/data/etc/android.hardware.telephony.satellite.xml b/data/etc/android.hardware.telephony.satellite.xml
new file mode 100644
index 0000000..945e720
--- /dev/null
+++ b/data/etc/android.hardware.telephony.satellite.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<!-- This is the standard set of features for devices to support Telephony Satellite API. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.satellite" />
+</permissions>
\ No newline at end of file
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 47c2889..a76271d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -879,7 +879,7 @@
class ScopedSyntheticEventTracer {
public:
ScopedSyntheticEventTracer(std::unique_ptr<trace::InputTracerInterface>& tracer)
- : mTracer(tracer) {
+ : mTracer(tracer), mProcessingTimestamp(now()) {
if (mTracer) {
mEventTracker = mTracer->createTrackerForSyntheticEvent();
}
@@ -887,7 +887,7 @@
~ScopedSyntheticEventTracer() {
if (mTracer) {
- mTracer->eventProcessingComplete(*mEventTracker);
+ mTracer->eventProcessingComplete(*mEventTracker, mProcessingTimestamp);
}
}
@@ -896,8 +896,9 @@
}
private:
- std::unique_ptr<trace::InputTracerInterface>& mTracer;
+ const std::unique_ptr<trace::InputTracerInterface>& mTracer;
std::unique_ptr<trace::EventTrackerInterface> mEventTracker;
+ const nsecs_t mProcessingTimestamp;
};
} // namespace
@@ -1263,7 +1264,7 @@
if (mTracer) {
if (auto& traceTracker = getTraceTracker(*mPendingEvent); traceTracker != nullptr) {
- mTracer->eventProcessingComplete(*traceTracker);
+ mTracer->eventProcessingComplete(*traceTracker, currentTime);
}
}
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 46e7e8b..dfbe02f 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -499,67 +499,53 @@
nsecs_t currentTime) {
std::vector<std::unique_ptr<MotionEntry>> events;
std::vector<uint32_t> canceledPointerIndices;
- std::vector<PointerProperties> pointerProperties(MAX_POINTERS);
- std::vector<PointerCoords> pointerCoords(MAX_POINTERS);
+
for (uint32_t pointerIdx = 0; pointerIdx < memento.getPointerCount(); pointerIdx++) {
uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
- pointerProperties[pointerIdx] = memento.pointerProperties[pointerIdx];
- pointerCoords[pointerIdx] = memento.pointerCoords[pointerIdx];
if (pointerIds.test(pointerId)) {
canceledPointerIndices.push_back(pointerIdx);
}
}
if (canceledPointerIndices.size() == memento.getPointerCount()) {
- const int32_t action =
- memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
- int32_t flags = memento.flags;
- if (action == AMOTION_EVENT_ACTION_CANCEL) {
- flags |= AMOTION_EVENT_FLAG_CANCELED;
+ // We are cancelling all pointers.
+ events.emplace_back(createCancelEntryForMemento(memento, currentTime));
+ return events;
+ }
+
+ // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
+ // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
+ // previously canceled pointers from PointerProperties and PointerCoords, and update
+ // pointerCount appropriately. For convenience, sort the canceled pointer indices in
+ // descending order so that we can just slide the remaining pointers to the beginning of
+ // the array when a pointer is canceled.
+ std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
+ std::greater<uint32_t>());
+
+ std::vector<PointerProperties> pointerProperties = memento.pointerProperties;
+ std::vector<PointerCoords> pointerCoords = memento.pointerCoords;
+ for (const uint32_t pointerIdx : canceledPointerIndices) {
+ if (pointerProperties.size() <= 1) {
+ LOG(FATAL) << "Unexpected code path for canceling all pointers!";
}
+ const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
+ (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
events.push_back(
std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
currentTime, memento.deviceId, memento.source,
memento.displayId, memento.policyFlags, action,
- /*actionButton=*/0, flags, AMETA_NONE,
- /*buttonState=*/0, MotionClassification::NONE,
+ /*actionButton=*/0,
+ memento.flags | AMOTION_EVENT_FLAG_CANCELED,
+ AMETA_NONE, /*buttonState=*/0,
+ MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
- memento.pointerProperties, memento.pointerCoords));
- } else {
- // If we aren't canceling all pointers, we need to generate ACTION_POINTER_UP with
- // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
- // previously canceled pointers from PointerProperties and PointerCoords, and update
- // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
- // can just slide the remaining pointers to the beginning of the array when a pointer is
- // canceled.
- std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
- std::greater<uint32_t>());
+ pointerProperties, pointerCoords));
- uint32_t pointerCount = memento.getPointerCount();
- for (const uint32_t pointerIdx : canceledPointerIndices) {
- const int32_t action = pointerCount == 1 ? AMOTION_EVENT_ACTION_CANCEL
- : AMOTION_EVENT_ACTION_POINTER_UP |
- (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- events.push_back(
- std::make_unique<MotionEntry>(mIdGenerator.nextId(), /*injectionState=*/nullptr,
- currentTime, memento.deviceId, memento.source,
- memento.displayId, memento.policyFlags, action,
- /*actionButton=*/0,
- memento.flags | AMOTION_EVENT_FLAG_CANCELED,
- AMETA_NONE, /*buttonState=*/0,
- MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
- memento.yPrecision, memento.xCursorPosition,
- memento.yCursorPosition, memento.downTime,
- pointerProperties, pointerCoords));
-
- // Cleanup pointer information
- pointerProperties.erase(pointerProperties.begin() + pointerIdx);
- pointerCoords.erase(pointerCoords.begin() + pointerIdx);
- pointerCount--;
- }
+ // Cleanup pointer information
+ pointerProperties.erase(pointerProperties.begin() + pointerIdx);
+ pointerCoords.erase(pointerCoords.begin() + pointerIdx);
}
return events;
}
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.cpp b/services/inputflinger/dispatcher/trace/InputTracer.cpp
index a1a87af..5d2b854 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracer.cpp
@@ -145,7 +145,8 @@
eventState->metadata.isSecure |= targetInfo.isSecureWindow;
}
-void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
+void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie,
+ nsecs_t processingTimestamp) {
if (isDerivedCookie(cookie)) {
LOG(FATAL) << "Event processing cannot be set from a derived cookie.";
}
@@ -154,7 +155,7 @@
LOG(FATAL) << "Traced event was already logged. "
"eventProcessingComplete() was likely called more than once.";
}
- eventState->onEventProcessingComplete();
+ eventState->onEventProcessingComplete(processingTimestamp);
}
std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(
@@ -242,7 +243,8 @@
// --- InputTracer::EventState ---
-void InputTracer::EventState::onEventProcessingComplete() {
+void InputTracer::EventState::onEventProcessingComplete(nsecs_t processingTimestamp) {
+ metadata.processingTimestamp = processingTimestamp;
metadata.isImeConnectionActive = tracer.mIsImeConnectionActive;
// Write all of the events known so far to the trace.
@@ -277,7 +279,7 @@
// We should never end up here in normal operation. However, in tests, it's possible that we
// stop and destroy InputDispatcher without waiting for it to finish processing events, at
// which point an event (and thus its EventState) may be destroyed before processing finishes.
- onEventProcessingComplete();
+ onEventProcessingComplete(systemTime(CLOCK_MONOTONIC));
}
} // namespace android::inputdispatcher::trace::impl
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.h b/services/inputflinger/dispatcher/trace/InputTracer.h
index ab175be..cb525a4 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.h
+++ b/services/inputflinger/dispatcher/trace/InputTracer.h
@@ -44,7 +44,8 @@
std::unique_ptr<EventTrackerInterface> traceInboundEvent(const EventEntry&) override;
std::unique_ptr<EventTrackerInterface> createTrackerForSyntheticEvent() override;
void dispatchToTargetHint(const EventTrackerInterface&, const InputTarget&) override;
- void eventProcessingComplete(const EventTrackerInterface&) override;
+ void eventProcessingComplete(const EventTrackerInterface&,
+ nsecs_t processingTimestamp) override;
std::unique_ptr<EventTrackerInterface> traceDerivedEvent(const EventEntry&,
const EventTrackerInterface&) override;
void traceEventDispatch(const DispatchEntry&, const EventTrackerInterface&) override;
@@ -61,7 +62,7 @@
explicit inline EventState(InputTracer& tracer) : tracer(tracer){};
~EventState();
- void onEventProcessingComplete();
+ void onEventProcessingComplete(nsecs_t processingTimestamp);
InputTracer& tracer;
std::vector<const TracedEvent> events;
diff --git a/services/inputflinger/dispatcher/trace/InputTracerInterface.h b/services/inputflinger/dispatcher/trace/InputTracerInterface.h
index af6eefb..f5e4e59 100644
--- a/services/inputflinger/dispatcher/trace/InputTracerInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracerInterface.h
@@ -81,7 +81,8 @@
* outside of our control, such as how long apps take to respond, so we don't want to depend on
* that.
*/
- virtual void eventProcessingComplete(const EventTrackerInterface&) = 0;
+ virtual void eventProcessingComplete(const EventTrackerInterface&,
+ nsecs_t processingTimestamp) = 0;
/**
* Trace an input event that is derived from another event. This is used in cases where an event
diff --git a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
index 25099c3..761d619 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
@@ -99,6 +99,8 @@
std::set<gui::Uid> targets;
// True if the there was an active input method connection while this event was processed.
bool isImeConnectionActive;
+ // The timestamp for when the dispatching decisions were made for the event by the system.
+ nsecs_t processingTimestamp;
};
/** Additional information about an input event being dispatched to a window. */
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
index 3d30ad6..77b5c2e 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
@@ -231,6 +231,8 @@
}
const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
auto tracePacket = ctx.NewTracePacket();
+ tracePacket->set_timestamp(metadata.processingTimestamp);
+ tracePacket->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
auto* winscopeExtensions = static_cast<perfetto::protos::pbzero::WinscopeExtensionsImpl*>(
tracePacket->set_winscope_extensions());
auto* inputEvent = winscopeExtensions->set_android_input_event();
@@ -257,6 +259,8 @@
}
const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
auto tracePacket = ctx.NewTracePacket();
+ tracePacket->set_timestamp(metadata.processingTimestamp);
+ tracePacket->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
auto* winscopeExtensions = static_cast<perfetto::protos::pbzero::WinscopeExtensionsImpl*>(
tracePacket->set_winscope_extensions());
auto* inputEvent = winscopeExtensions->set_android_input_event();
@@ -283,6 +287,8 @@
}
const bool isRedacted = traceLevel == TraceLevel::TRACE_LEVEL_REDACTED;
auto tracePacket = ctx.NewTracePacket();
+ tracePacket->set_timestamp(dispatchArgs.deliveryTime);
+ tracePacket->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
auto* winscopeExtensions = static_cast<perfetto::protos::pbzero::WinscopeExtensionsImpl*>(
tracePacket->set_winscope_extensions());
auto* inputEvent = winscopeExtensions->set_android_input_event();
diff --git a/services/inputflinger/tests/FakeWindows.h b/services/inputflinger/tests/FakeWindows.h
index 36a8f00..ee65d3a 100644
--- a/services/inputflinger/tests/FakeWindows.h
+++ b/services/inputflinger/tests/FakeWindows.h
@@ -304,15 +304,11 @@
WithFlags(expectedFlags)));
}
- inline void consumeMotionPointerUp(
- int32_t pointerIdx,
- ui::LogicalDisplayId expectedDisplayId = ui::LogicalDisplayId::DEFAULT,
- int32_t expectedFlags = 0) {
+ inline void consumeMotionPointerUp(int32_t pointerIdx,
+ const ::testing::Matcher<MotionEvent>& matcher) {
const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |
(pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- consumeMotionEvent(testing::AllOf(WithMotionAction(action),
- WithDisplayId(expectedDisplayId),
- WithFlags(expectedFlags)));
+ consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
}
inline void consumeMotionUp(
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index aa1462a..5eab6be 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1282,9 +1282,11 @@
injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
InputEventInjectionSync::WAIT_FOR_RESULT))
<< "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- foregroundWindow->consumeMotionPointerUp(0);
- wallpaperWindow->consumeMotionPointerUp(0, ui::LogicalDisplayId::DEFAULT,
- EXPECTED_WALLPAPER_FLAGS);
+ foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
+ WithDisplayId(ui::LogicalDisplayId::DEFAULT));
+ wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
+ AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
+ WithFlags(EXPECTED_WALLPAPER_FLAGS)));
ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
injectMotionEvent(*mDispatcher,
@@ -6220,8 +6222,10 @@
{touchPoint, touchPoint}));
// The first window gets nothing and the second gets pointer up
firstWindow->assertNoEvents();
- secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
- AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
+ AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
+ WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
+ WithPointerCount(2)));
// Send up event to the second window
mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
@@ -6363,8 +6367,10 @@
{pointInFirst, pointInSecond}));
// The first window gets nothing and the second gets pointer up
firstWindow->assertNoEvents();
- secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
- AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
+ secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
+ AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
+ WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
+ WithPointerCount(2)));
// Send up event to the second window
mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
@@ -12881,10 +12887,14 @@
// Spy window pilfers the pointers.
EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
- window->consumeMotionPointerUp(/*idx=*/2, ui::LogicalDisplayId::DEFAULT,
- AMOTION_EVENT_FLAG_CANCELED);
- window->consumeMotionPointerUp(/*idx=*/1, ui::LogicalDisplayId::DEFAULT,
- AMOTION_EVENT_FLAG_CANCELED);
+ window->consumeMotionPointerUp(/*pointerIdx=*/2,
+ AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
+ WithFlags(AMOTION_EVENT_FLAG_CANCELED),
+ WithPointerCount(3)));
+ window->consumeMotionPointerUp(/*pointerIdx=*/1,
+ AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
+ WithFlags(AMOTION_EVENT_FLAG_CANCELED),
+ WithPointerCount(2)));
spy->assertNoEvents();
window->assertNoEvents();
diff --git a/services/inputflinger/tests/InputTraceSession.cpp b/services/inputflinger/tests/InputTraceSession.cpp
index a9d370a..db4e761 100644
--- a/services/inputflinger/tests/InputTraceSession.cpp
+++ b/services/inputflinger/tests/InputTraceSession.cpp
@@ -103,6 +103,11 @@
continue;
}
+ EXPECT_TRUE(packet.has_timestamp());
+ EXPECT_TRUE(packet.has_timestamp_clock_id());
+ EXPECT_EQ(packet.timestamp_clock_id(),
+ static_cast<uint32_t>(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC));
+
AndroidInputEvent::Decoder event{field.as_bytes()};
if (event.has_dispatcher_motion_event()) {
tracedMotions.emplace_back(event.dispatcher_motion_event(),