diff options
18 files changed, 269 insertions, 52 deletions
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 0a63c1564e..33bb343c9d 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -75,6 +75,7 @@ filegroup { "android/gui/IWindowInfosListener.aidl", "android/gui/IWindowInfosReportedListener.aidl", "android/gui/WindowInfo.aidl", + "android/gui/WindowInfosUpdate.aidl", ], } @@ -90,9 +91,11 @@ cc_library_static { "android/gui/InputApplicationInfo.aidl", "android/gui/IWindowInfosListener.aidl", "android/gui/IWindowInfosReportedListener.aidl", + "android/gui/WindowInfosUpdate.aidl", "android/gui/WindowInfo.aidl", "DisplayInfo.cpp", "WindowInfo.cpp", + "WindowInfosUpdate.cpp", ], shared_libs: [ diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp index 2b34a0fc47..76e7b6e162 100644 --- a/libs/gui/WindowInfosListenerReporter.cpp +++ b/libs/gui/WindowInfosListenerReporter.cpp @@ -17,6 +17,7 @@ #include <android/gui/ISurfaceComposer.h> #include <gui/AidlStatusUtil.h> #include <gui/WindowInfosListenerReporter.h> +#include "gui/WindowInfosUpdate.h" namespace android { @@ -84,7 +85,7 @@ status_t WindowInfosListenerReporter::removeWindowInfosListener( } binder::Status WindowInfosListenerReporter::onWindowInfosChanged( - const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos, + const gui::WindowInfosUpdate& update, const sp<IWindowInfosReportedListener>& windowInfosReportedListener) { std::unordered_set<sp<WindowInfosListener>, gui::SpHash<WindowInfosListener>> windowInfosListeners; @@ -95,12 +96,12 @@ binder::Status WindowInfosListenerReporter::onWindowInfosChanged( windowInfosListeners.insert(listener); } - mLastWindowInfos = windowInfos; - mLastDisplayInfos = displayInfos; + mLastWindowInfos = update.windowInfos; + mLastDisplayInfos = update.displayInfos; } for (auto listener : windowInfosListeners) { - listener->onWindowInfosChanged(windowInfos, displayInfos); + listener->onWindowInfosChanged(update); } if (windowInfosReportedListener) { diff --git a/libs/gui/WindowInfosUpdate.cpp b/libs/gui/WindowInfosUpdate.cpp new file mode 100644 index 0000000000..38ae5ef102 --- /dev/null +++ b/libs/gui/WindowInfosUpdate.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2023 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 <gui/WindowInfosUpdate.h> +#include <private/gui/ParcelUtils.h> + +namespace android::gui { + +status_t WindowInfosUpdate::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + + uint32_t size; + + SAFE_PARCEL(parcel->readUint32, &size); + windowInfos.reserve(size); + for (uint32_t i = 0; i < size; i++) { + windowInfos.push_back({}); + SAFE_PARCEL(windowInfos.back().readFromParcel, parcel); + } + + SAFE_PARCEL(parcel->readUint32, &size); + displayInfos.reserve(size); + for (uint32_t i = 0; i < size; i++) { + displayInfos.push_back({}); + SAFE_PARCEL(displayInfos.back().readFromParcel, parcel); + } + + SAFE_PARCEL(parcel->readInt64, &vsyncId); + SAFE_PARCEL(parcel->readInt64, ×tamp); + + return OK; +} + +status_t WindowInfosUpdate::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(windowInfos.size())); + for (auto& windowInfo : windowInfos) { + SAFE_PARCEL(windowInfo.writeToParcel, parcel); + } + + SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(displayInfos.size())); + for (auto& displayInfo : displayInfos) { + SAFE_PARCEL(displayInfo.writeToParcel, parcel); + } + + SAFE_PARCEL(parcel->writeInt64, vsyncId); + SAFE_PARCEL(parcel->writeInt64, timestamp); + + return OK; +} + +} // namespace android::gui diff --git a/libs/gui/android/gui/IWindowInfosListener.aidl b/libs/gui/android/gui/IWindowInfosListener.aidl index a5b2762318..400229d99f 100644 --- a/libs/gui/android/gui/IWindowInfosListener.aidl +++ b/libs/gui/android/gui/IWindowInfosListener.aidl @@ -16,12 +16,11 @@ package android.gui; -import android.gui.DisplayInfo; import android.gui.IWindowInfosReportedListener; -import android.gui.WindowInfo; +import android.gui.WindowInfosUpdate; /** @hide */ -oneway interface IWindowInfosListener -{ - void onWindowInfosChanged(in WindowInfo[] windowInfos, in DisplayInfo[] displayInfos, in @nullable IWindowInfosReportedListener windowInfosReportedListener); +oneway interface IWindowInfosListener { + void onWindowInfosChanged( + in WindowInfosUpdate update, in @nullable IWindowInfosReportedListener windowInfosReportedListener); } diff --git a/libs/gui/android/gui/WindowInfosUpdate.aidl b/libs/gui/android/gui/WindowInfosUpdate.aidl new file mode 100644 index 0000000000..0c6109da8f --- /dev/null +++ b/libs/gui/android/gui/WindowInfosUpdate.aidl @@ -0,0 +1,22 @@ +/* +** Copyright 2023, 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. +*/ + +package android.gui; + +import android.gui.DisplayInfo; +import android.gui.WindowInfo; + +parcelable WindowInfosUpdate cpp_header "gui/WindowInfosUpdate.h"; diff --git a/libs/gui/include/gui/WindowInfosListener.h b/libs/gui/include/gui/WindowInfosListener.h index a18a498c5e..02c8eb5ef3 100644 --- a/libs/gui/include/gui/WindowInfosListener.h +++ b/libs/gui/include/gui/WindowInfosListener.h @@ -16,15 +16,13 @@ #pragma once -#include <gui/DisplayInfo.h> -#include <gui/WindowInfo.h> +#include <gui/WindowInfosUpdate.h> #include <utils/RefBase.h> namespace android::gui { class WindowInfosListener : public virtual RefBase { public: - virtual void onWindowInfosChanged(const std::vector<WindowInfo>&, - const std::vector<DisplayInfo>&) = 0; + virtual void onWindowInfosChanged(const WindowInfosUpdate& update) = 0; }; -} // namespace android::gui
\ No newline at end of file +} // namespace android::gui diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h index 2754442a95..38cb108912 100644 --- a/libs/gui/include/gui/WindowInfosListenerReporter.h +++ b/libs/gui/include/gui/WindowInfosListenerReporter.h @@ -22,6 +22,7 @@ #include <binder/IBinder.h> #include <gui/SpHash.h> #include <gui/WindowInfosListener.h> +#include <gui/WindowInfosUpdate.h> #include <unordered_set> namespace android { @@ -29,8 +30,7 @@ namespace android { class WindowInfosListenerReporter : public gui::BnWindowInfosListener { public: static sp<WindowInfosListenerReporter> getInstance(); - binder::Status onWindowInfosChanged(const std::vector<gui::WindowInfo>&, - const std::vector<gui::DisplayInfo>&, + binder::Status onWindowInfosChanged(const gui::WindowInfosUpdate& update, const sp<gui::IWindowInfosReportedListener>&) override; status_t addWindowInfosListener( const sp<gui::WindowInfosListener>& windowInfosListener, diff --git a/libs/gui/include/gui/WindowInfosUpdate.h b/libs/gui/include/gui/WindowInfosUpdate.h new file mode 100644 index 0000000000..2ca59fb497 --- /dev/null +++ b/libs/gui/include/gui/WindowInfosUpdate.h @@ -0,0 +1,44 @@ +/* + * Copyright 2023 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 <binder/Parcelable.h> +#include <gui/DisplayInfo.h> +#include <gui/WindowInfo.h> + +namespace android::gui { + +struct WindowInfosUpdate : public Parcelable { + WindowInfosUpdate() {} + + WindowInfosUpdate(std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, + int64_t vsyncId, int64_t timestamp) + : windowInfos(std::move(windowInfos)), + displayInfos(std::move(displayInfos)), + vsyncId(vsyncId), + timestamp(timestamp) {} + + std::vector<WindowInfo> windowInfos; + std::vector<DisplayInfo> displayInfos; + int64_t vsyncId; + int64_t timestamp; + + status_t writeToParcel(android::Parcel*) const override; + status_t readFromParcel(const android::Parcel*) override; +}; + +} // namespace android::gui diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index f852001679..becf70a369 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -343,8 +343,10 @@ static void benchmarkOnWindowInfosChanged(benchmark::State& state) { std::vector<gui::DisplayInfo> displayInfos{info}; for (auto _ : state) { - dispatcher.onWindowInfosChanged(windowInfos, displayInfos); - dispatcher.onWindowInfosChanged(/*windowInfos=*/{}, /*displayInfos=*/{}); + dispatcher.onWindowInfosChanged( + {windowInfos, displayInfos, /*vsyncId=*/0, /*timestamp=*/0}); + dispatcher.onWindowInfosChanged( + {/*windowInfos=*/{}, /*displayInfos=*/{}, /*vsyncId=*/{}, /*timestamp=*/0}); } dispatcher.stop(); } diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 8c08ef25e3..bf5250288a 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -5572,6 +5572,14 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { } else { dump += INDENT "Displays: <none>\n"; } + dump += INDENT "Window Infos:\n"; + dump += StringPrintf(INDENT2 "vsync id: %" PRId64 "\n", mWindowInfosVsyncId); + dump += StringPrintf(INDENT2 "timestamp (ns): %" PRId64 "\n", mWindowInfosTimestamp); + dump += "\n"; + dump += StringPrintf(INDENT2 "max update delay (ns): %" PRId64 "\n", mMaxWindowInfosDelay); + dump += StringPrintf(INDENT2 "max update delay vsync id: %" PRId64 "\n", + mMaxWindowInfosDelayVsyncId); + dump += "\n"; if (!mGlobalMonitorsByDisplay.empty()) { for (const auto& [displayId, monitors] : mGlobalMonitorsByDisplay) { @@ -6580,12 +6588,11 @@ void InputDispatcher::displayRemoved(int32_t displayId) { mLooper->wake(); } -void InputDispatcher::onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos, - const std::vector<DisplayInfo>& displayInfos) { +void InputDispatcher::onWindowInfosChanged(const gui::WindowInfosUpdate& update) { // The listener sends the windows as a flattened array. Separate the windows by display for // more convenient parsing. std::unordered_map<int32_t, std::vector<sp<WindowInfoHandle>>> handlesPerDisplay; - for (const auto& info : windowInfos) { + for (const auto& info : update.windowInfos) { handlesPerDisplay.emplace(info.displayId, std::vector<sp<WindowInfoHandle>>()); handlesPerDisplay[info.displayId].push_back(sp<WindowInfoHandle>::make(info)); } @@ -6600,13 +6607,22 @@ void InputDispatcher::onWindowInfosChanged(const std::vector<WindowInfo>& window } mDisplayInfos.clear(); - for (const auto& displayInfo : displayInfos) { + for (const auto& displayInfo : update.displayInfos) { mDisplayInfos.emplace(displayInfo.displayId, displayInfo); } for (const auto& [displayId, handles] : handlesPerDisplay) { setInputWindowsLocked(handles, displayId); } + + mWindowInfosVsyncId = update.vsyncId; + mWindowInfosTimestamp = update.timestamp; + + int64_t delay = systemTime() - update.timestamp; + if (delay > mMaxWindowInfosDelay) { + mMaxWindowInfosDelay = delay; + mMaxWindowInfosDelayVsyncId = update.vsyncId; + } } // Wake up poll loop since it may need to make new input dispatching choices. mLooper->wake(); @@ -6629,9 +6645,8 @@ bool InputDispatcher::shouldDropInput( } void InputDispatcher::DispatcherWindowListener::onWindowInfosChanged( - const std::vector<gui::WindowInfo>& windowInfos, - const std::vector<DisplayInfo>& displayInfos) { - mDispatcher.onWindowInfosChanged(windowInfos, displayInfos); + const gui::WindowInfosUpdate& update) { + mDispatcher.onWindowInfosChanged(update); } void InputDispatcher::cancelCurrentTouch() { diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index dd7f7fe2b0..791dd63077 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -36,7 +36,7 @@ #include <attestation/HmacKeyManager.h> #include <gui/InputApplication.h> -#include <gui/WindowInfo.h> +#include <gui/WindowInfosUpdate.h> #include <input/Input.h> #include <input/InputTransport.h> #include <limits.h> @@ -144,8 +144,7 @@ public: void displayRemoved(int32_t displayId) override; // Public because it's also used by tests to simulate the WindowInfosListener callback - void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos, - const std::vector<android::gui::DisplayInfo>& displayInfos); + void onWindowInfosChanged(const gui::WindowInfosUpdate&); void cancelCurrentTouch() override; @@ -205,6 +204,11 @@ private: const IdGenerator mIdGenerator; + int64_t mWindowInfosVsyncId GUARDED_BY(mLock); + int64_t mWindowInfosTimestamp GUARDED_BY(mLock); + int64_t mMaxWindowInfosDelay GUARDED_BY(mLock) = -1; + int64_t mMaxWindowInfosDelayVsyncId GUARDED_BY(mLock) = -1; + // With each iteration, InputDispatcher nominally processes one queued event, // a timeout, or a response from an input consumer. // This method should only be called on the input dispatcher's own thread. @@ -356,9 +360,7 @@ private: class DispatcherWindowListener : public gui::WindowInfosListener { public: explicit DispatcherWindowListener(InputDispatcher& dispatcher) : mDispatcher(dispatcher){}; - void onWindowInfosChanged( - const std::vector<android::gui::WindowInfo>& windowInfos, - const std::vector<android::gui::DisplayInfo>& displayInfos) override; + void onWindowInfosChanged(const gui::WindowInfosUpdate&) override; private: InputDispatcher& mDispatcher; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index b3c509595b..c0bc68c292 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -3771,7 +3771,7 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { "Fake Window", ADISPLAY_ID_DEFAULT); window->setFocusable(true); - mDispatcher->onWindowInfosChanged({*window->getInfo()}, {}); + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); setFocusedWindow(window); window->consumeFocusEvent(true); @@ -3785,7 +3785,7 @@ TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) { window->consumeKeyUp(ADISPLAY_ID_DEFAULT); // All windows are removed from the display. Ensure that we can no longer dispatch to it. - mDispatcher->onWindowInfosChanged({}, {}); + mDispatcher->onWindowInfosChanged({{}, {}, 0, 0}); window->consumeFocusEvent(false); @@ -3801,7 +3801,7 @@ TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) { // Ensure window is non-split and have some transform. window->setPreventSplitting(true); window->setWindowOffset(20, 40); - mDispatcher->onWindowInfosChanged({*window->getInfo()}, {}); + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, @@ -3848,12 +3848,12 @@ public: info.displayId = displayId; info.transform = transform; mDisplayInfos.push_back(std::move(info)); - mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos); + mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0}); } void addWindow(const sp<WindowInfoHandle>& windowHandle) { mWindowInfos.push_back(*windowHandle->getInfo()); - mDispatcher->onWindowInfosChanged(mWindowInfos, mDisplayInfos); + mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0}); } void removeAllWindowsAndDisplays() { @@ -4952,7 +4952,7 @@ TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) { displayInfo.displayId = ADISPLAY_ID_DEFAULT; displayInfo.transform = transform; - mDispatcher->onWindowInfosChanged({*window->getInfo()}, {displayInfo}); + mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0}); const NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, @@ -5722,7 +5722,7 @@ TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) displayInfos[1].displayId = SECOND_DISPLAY_ID; displayInfos[1].transform = secondDisplayTransform; - mDispatcher->onWindowInfosChanged({}, displayInfos); + mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0}); // Enable InputFilter mDispatcher->setInputFilterEnabled(true); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d406afff1f..0e3c47b682 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2533,7 +2533,7 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe } updateCursorAsync(); - updateInputFlinger(); + updateInputFlinger(vsyncId); if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) { // This will block and tracing should only be enabled for debugging. @@ -3718,7 +3718,7 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { doCommitTransactions(); } -void SurfaceFlinger::updateInputFlinger() { +void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId) { if (!mInputFlinger || (!mUpdateInputInfo && mInputWindowCommands.empty())) { return; } @@ -3730,6 +3730,8 @@ void SurfaceFlinger::updateInputFlinger() { if (mUpdateInputInfo) { mUpdateInputInfo = false; updateWindowInfo = true; + mLastInputFlingerUpdateVsyncId = vsyncId; + mLastInputFlingerUpdateTimestamp = systemTime(); buildWindowInfos(windowInfos, displayInfos); } @@ -3759,7 +3761,9 @@ void SurfaceFlinger::updateInputFlinger() { std::move( inputWindowCommands.windowInfosReportedListeners), /* forceImmediateCall= */ visibleWindowsChanged || - !inputWindowCommands.focusRequests.empty()); + !inputWindowCommands.focusRequests.empty(), + mLastInputFlingerUpdateVsyncId, + mLastInputFlingerUpdateTimestamp); } else { // If there are listeners but no changes to input windows, call the listeners // immediately. @@ -6105,6 +6109,29 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp result.append(mTimeStats->miniDump()); result.append("\n"); + + result.append("Window Infos:\n"); + StringAppendF(&result, " input flinger update vsync id: %" PRId64 "\n", + mLastInputFlingerUpdateVsyncId.value); + StringAppendF(&result, " input flinger update timestamp (ns): %" PRId64 "\n", + mLastInputFlingerUpdateTimestamp); + result.append("\n"); + + if (int64_t unsentVsyncId = mWindowInfosListenerInvoker->getUnsentMessageVsyncId().value; + unsentVsyncId != -1) { + StringAppendF(&result, " unsent input flinger update vsync id: %" PRId64 "\n", + unsentVsyncId); + StringAppendF(&result, " unsent input flinger update timestamp (ns): %" PRId64 "\n", + mWindowInfosListenerInvoker->getUnsentMessageTimestamp()); + result.append("\n"); + } + + if (uint32_t pendingMessages = mWindowInfosListenerInvoker->getPendingMessageCount(); + pendingMessages != 0) { + StringAppendF(&result, " pending input flinger calls: %" PRIu32 "\n", + mWindowInfosListenerInvoker->getPendingMessageCount()); + result.append("\n"); + } } mat4 SurfaceFlinger::calculateColorMatrix(float saturation) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index cd7659bc0b..8eaa1c7f09 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -717,7 +717,7 @@ private: void updateLayerHistory(const frontend::LayerSnapshot& snapshot); frontend::Update flushLifecycleUpdates() REQUIRES(kMainThreadContext); - void updateInputFlinger(); + void updateInputFlinger(VsyncId); void persistDisplayBrightness(bool needsComposite) REQUIRES(kMainThreadContext); void buildWindowInfos(std::vector<gui::WindowInfo>& outWindowInfos, std::vector<gui::DisplayInfo>& outDisplayInfos); @@ -1248,6 +1248,9 @@ private: VsyncId mLastCommittedVsyncId; + VsyncId mLastInputFlingerUpdateVsyncId; + nsecs_t mLastInputFlingerUpdateTimestamp; + // If blurs should be enabled on this device. bool mSupportsBlur = false; std::atomic<uint32_t> mFrameMissedCount = 0; diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index 856fbbbf33..2b62638c61 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -16,6 +16,7 @@ #include <ftl/small_vector.h> #include <gui/ISurfaceComposer.h> +#include <gui/WindowInfosUpdate.h> #include "WindowInfosListenerInvoker.h" @@ -86,11 +87,12 @@ void WindowInfosListenerInvoker::binderDied(const wp<IBinder>& who) { void WindowInfosListenerInvoker::windowInfosChanged( std::vector<WindowInfo> windowInfos, std::vector<DisplayInfo> displayInfos, - WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall) { + WindowInfosReportedListenerSet reportedListeners, bool forceImmediateCall, VsyncId vsyncId, + nsecs_t timestamp) { reportedListeners.insert(sp<WindowInfosListenerInvoker>::fromExisting(this)); auto callListeners = [this, windowInfos = std::move(windowInfos), - displayInfos = std::move(displayInfos)]( - WindowInfosReportedListenerSet reportedListeners) mutable { + displayInfos = std::move(displayInfos), vsyncId, + timestamp](WindowInfosReportedListenerSet reportedListeners) mutable { WindowInfosListenerVector windowInfosListeners; { std::scoped_lock lock(mListenersMutex); @@ -103,6 +105,9 @@ void WindowInfosListenerInvoker::windowInfosChanged( sp<WindowInfosReportedListenerInvoker>::make(windowInfosListeners, std::move(reportedListeners)); + gui::WindowInfosUpdate update(std::move(windowInfos), std::move(displayInfos), + vsyncId.value, timestamp); + for (const auto& listener : windowInfosListeners) { sp<IBinder> asBinder = IInterface::asBinder(listener); @@ -111,8 +116,7 @@ void WindowInfosListenerInvoker::windowInfosChanged( // calling onWindowInfosReported. asBinder->linkToDeath(reportedInvoker); - auto status = - listener->onWindowInfosChanged(windowInfos, displayInfos, reportedInvoker); + auto status = listener->onWindowInfosChanged(update, reportedInvoker); if (!status.isOk()) { reportedInvoker->onWindowInfosReported(); } @@ -129,11 +133,15 @@ void WindowInfosListenerInvoker::windowInfosChanged( // to reduce the amount of binder memory used. if (mActiveMessageCount > 0 && !forceImmediateCall) { mWindowInfosChangedDelayed = std::move(callListeners); + mUnsentVsyncId = vsyncId; + mUnsentTimestamp = timestamp; mReportedListenersDelayed.merge(reportedListeners); return; } mWindowInfosChangedDelayed = nullptr; + mUnsentVsyncId = {-1}; + mUnsentTimestamp = -1; reportedListeners.merge(mReportedListenersDelayed); mActiveMessageCount++; } @@ -154,6 +162,8 @@ binder::Status WindowInfosListenerInvoker::onWindowInfosReported() { mActiveMessageCount++; callListeners = std::move(mWindowInfosChangedDelayed); mWindowInfosChangedDelayed = nullptr; + mUnsentVsyncId = {-1}; + mUnsentTimestamp = -1; reportedListeners = std::move(mReportedListenersDelayed); mReportedListenersDelayed.clear(); } diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h index 4da98282a9..e35d0564b5 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.h +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -26,6 +26,8 @@ #include <gui/SpHash.h> #include <utils/Mutex.h> +#include "scheduler/VsyncId.h" + namespace android { using WindowInfosReportedListenerSet = @@ -40,10 +42,25 @@ public: void windowInfosChanged(std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>, WindowInfosReportedListenerSet windowInfosReportedListeners, - bool forceImmediateCall); + bool forceImmediateCall, VsyncId vsyncId, nsecs_t timestamp); binder::Status onWindowInfosReported() override; + VsyncId getUnsentMessageVsyncId() { + std::scoped_lock lock(mMessagesMutex); + return mUnsentVsyncId; + } + + nsecs_t getUnsentMessageTimestamp() { + std::scoped_lock lock(mMessagesMutex); + return mUnsentTimestamp; + } + + uint32_t getPendingMessageCount() { + std::scoped_lock lock(mMessagesMutex); + return mActiveMessageCount; + } + protected: void binderDied(const wp<IBinder>& who) override; @@ -58,6 +75,8 @@ private: uint32_t mActiveMessageCount GUARDED_BY(mMessagesMutex) = 0; std::function<void(WindowInfosReportedListenerSet)> mWindowInfosChangedDelayed GUARDED_BY(mMessagesMutex); + VsyncId mUnsentVsyncId GUARDED_BY(mMessagesMutex) = {-1}; + nsecs_t mUnsentTimestamp GUARDED_BY(mMessagesMutex) = -1; WindowInfosReportedListenerSet mReportedListenersDelayed; }; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index c1bab0e89b..4d13aca5bb 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -590,7 +590,7 @@ public: mFlinger->binderDied(display); mFlinger->onFirstRef(); - mFlinger->updateInputFlinger(); + mFlinger->updateInputFlinger(VsyncId{0}); mFlinger->updateCursorAsync(); mutableScheduler().setVsyncConfig({.sfOffset = mFdp.ConsumeIntegral<nsecs_t>(), diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp index f4a8f038d7..3f27360cb7 100644 --- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp +++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp @@ -16,6 +16,7 @@ #include <gtest/gtest.h> #include <gui/SurfaceComposerClient.h> +#include <gui/WindowInfosUpdate.h> #include <private/android_filesystem_config.h> #include <cstdint> #include <future> @@ -41,9 +42,8 @@ protected: WindowInfosListener(WindowInfosPredicate predicate, std::promise<void>& promise) : mPredicate(std::move(predicate)), mPromise(promise) {} - void onWindowInfosChanged(const std::vector<WindowInfo>& windowInfos, - const std::vector<DisplayInfo>&) override { - if (mPredicate(windowInfos)) { + void onWindowInfosChanged(const gui::WindowInfosUpdate& update) override { + if (mPredicate(update.windowInfos)) { mPromise.set_value(); } } |