From 0b150b7c6319e4445a757f0b1b73e7785ab7abfe Mon Sep 17 00:00:00 2001 From: RuXin Jiang Date: Thu, 14 Sep 2023 20:54:42 +0800 Subject: [PATCH 001/530] Remove the WCG check from switch Color Modes For devices that doesn't support Wide Color Gamut, color modes can't be switched due to WCG check condition within populateColorModes. Remove WCG check from populateColorModes,so that color mode can be switched correctly. Bug: 304471085 Test: CtsDisplayTestCases Test: CtsGraphicsTestCases Test: CtsMediaV2TestCases Test: many more CTS modules Test: manual-switch color modes Test: manual-check white balance Test: manualuse commands to check if renderintent value is correct Iffy-tests-added-by: Snild Dolkow Change-Id: I91ddf9cb6ffd1fb7accf2985f006720f4d02c65b --- .../src/DisplayColorProfile.cpp | 14 ++---- .../tests/DisplayColorProfileTest.cpp | 50 +++++++++++++++++-- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp index a7c45129b1..98c25ba051 100644 --- a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp +++ b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp @@ -271,10 +271,6 @@ const HdrCapabilities& DisplayColorProfile::getHdrCapabilities() const { void DisplayColorProfile::populateColorModes( const DisplayColorProfileCreationArgs::HwcColorModes& hwcColorModes) { - if (!hasWideColorGamut()) { - return; - } - // collect all known SDR render intents std::unordered_set sdrRenderIntents(sSdrRenderIntents.begin(), sSdrRenderIntents.end()); @@ -363,13 +359,9 @@ void DisplayColorProfile::getBestColorMode(Dataspace dataspace, RenderIntent int *outMode = iter->second.colorMode; *outIntent = iter->second.renderIntent; } else { - // this is unexpected on a WCG display - if (hasWideColorGamut()) { - ALOGE("map unknown (%s)/(%s) to default color mode", - dataspaceDetails(static_cast(dataspace)).c_str(), - decodeRenderIntent(intent).c_str()); - } - + ALOGI("map unknown (%s)/(%s) to default color mode", + dataspaceDetails(static_cast(dataspace)).c_str(), + decodeRenderIntent(intent).c_str()); *outDataspace = Dataspace::UNKNOWN; *outMode = ColorMode::NATIVE; *outIntent = RenderIntent::COLORIMETRIC; diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp index 21b9aa93ea..518081a83d 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp @@ -123,10 +123,10 @@ public: .build(); } - static impl::DisplayColorProfile createProfileWithSRGBColorModeSupport() { + static impl::DisplayColorProfile createProfileWithSRGBColorModeSupport(bool wcg = true) { return ProfileFactory() - .setHasWideColorGamut(true) .addHdrType(Hdr::HDR10) + .setHasWideColorGamut(wcg) .addColorModeRenderIntent(ColorMode::SRGB, RenderIntent::COLORIMETRIC) .addColorModeRenderIntent(ColorMode::SRGB, RenderIntent::ENHANCE) .addColorModeRenderIntent(ColorMode::SRGB, VendorRenderIntent) @@ -322,7 +322,7 @@ TEST_F(DisplayColorProfileTest, ctorSignalsHdrSupportForAnyWideColorGamutDevice) TEST_F(DisplayColorProfileTest, hasRenderIntentReturnsExpectedValueWhenOutputHasNoSupport) { auto profile = ProfileFactory::createProfileWithNoColorModeSupport(); - EXPECT_FALSE(profile.hasRenderIntent(RenderIntent::COLORIMETRIC)); + EXPECT_TRUE(profile.hasRenderIntent(RenderIntent::COLORIMETRIC)); EXPECT_FALSE(profile.hasRenderIntent(RenderIntent::ENHANCE)); EXPECT_FALSE(profile.hasRenderIntent(RenderIntent::TONE_MAP_COLORIMETRIC)); EXPECT_FALSE(profile.hasRenderIntent(RenderIntent::TONE_MAP_ENHANCE)); @@ -339,6 +339,16 @@ TEST_F(DisplayColorProfileTest, hasRenderIntentReturnsExpectedValueWhenOutputHas EXPECT_FALSE(profile.hasRenderIntent(VendorRenderIntent)); } +TEST_F(DisplayColorProfileTest, hasRenderIntentReturnsExpectedValueWhenOutputHasSRGBSupport_NoWCG) { + auto profile = ProfileFactory::createProfileWithSRGBColorModeSupport(false); + + EXPECT_TRUE(profile.hasRenderIntent(RenderIntent::COLORIMETRIC)); + EXPECT_TRUE(profile.hasRenderIntent(RenderIntent::ENHANCE)); + EXPECT_FALSE(profile.hasRenderIntent(RenderIntent::TONE_MAP_COLORIMETRIC)); + EXPECT_FALSE(profile.hasRenderIntent(RenderIntent::TONE_MAP_ENHANCE)); + EXPECT_TRUE(profile.hasRenderIntent(VendorRenderIntent)); +} + TEST_F(DisplayColorProfileTest, hasRenderIntentReturnsExpectedValueWhenOutputHasSRGBSupport) { auto profile = ProfileFactory::createProfileWithSRGBColorModeSupport(); @@ -509,6 +519,40 @@ TEST_F(DisplayColorProfileTest, getBestColorModeReturnsExpectedModesWhenOutputHa checkGetBestColorMode(profile, expectedResults); } +TEST_F(DisplayColorProfileTest, + getBestColorModeReturnsExpectedModesWhenOutputHasSRGBSupport_NoWCG) { + auto profile = ProfileFactory::createProfileWithSRGBColorModeSupport(false); + + // Note: This table of expected values goes with the table of arguments + // used in checkGetBestColorMode. + using Result = std::tuple; + std::array expectedResults = { + /* clang-format off */ + /* 0 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 1 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::ENHANCE}, + /* 2 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, VendorRenderIntent}, + + /* 3 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 4 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::ENHANCE}, + /* 5 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, VendorRenderIntent}, + + /* 6 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 7 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::ENHANCE}, + /* 8 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, VendorRenderIntent}, + + /* 9 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 10 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 11 */ Result{Dataspace::UNKNOWN, ColorMode::NATIVE, RenderIntent::COLORIMETRIC}, + + /* 12 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 13 */ Result{Dataspace::V0_SRGB, ColorMode::SRGB, RenderIntent::COLORIMETRIC}, + /* 14 */ Result{Dataspace::UNKNOWN, ColorMode::NATIVE, RenderIntent::COLORIMETRIC}, + /* clang-format on */ + }; + + checkGetBestColorMode(profile, expectedResults); +} + TEST_F(DisplayColorProfileTest, getBestColorModeReturnsExpectedModesWhenOutputHasSRGBSupport) { auto profile = ProfileFactory::createProfileWithSRGBColorModeSupport(); -- GitLab From 263507f9e3709bb4fff70ddd8e26c5dff46152ac Mon Sep 17 00:00:00 2001 From: Frederick Mayle Date: Thu, 30 May 2024 14:54:27 -0700 Subject: [PATCH 002/530] binder: remove mutex from transaction processing loop atomic ops are enough for the various count fields, we don't need a completely consistent view of them. Bug: 333946800 Test: atest --test-mapping frameworks/native/libs/binder/TEST_MAPPING Change-Id: I01f55a36f7421e4955e2b0d3a6500b183573d765 --- libs/binder/IPCThreadState.cpp | 76 +++++++++++------------ libs/binder/ProcessState.cpp | 30 ++++----- libs/binder/include/binder/ProcessState.h | 22 +++---- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index ef96f803c3..ad20cfa11e 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -613,16 +613,20 @@ bool IPCThreadState::flushIfNeeded() void IPCThreadState::blockUntilThreadAvailable() { - pthread_mutex_lock(&mProcess->mThreadCountLock); - mProcess->mWaitingForThreads++; - while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) { - ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n", - static_cast(mProcess->mExecutingThreadsCount), - static_cast(mProcess->mMaxThreads)); - pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock); - } - mProcess->mWaitingForThreads--; - pthread_mutex_unlock(&mProcess->mThreadCountLock); + std::unique_lock lock_guard_(mProcess->mOnThreadAvailableLock); + mProcess->mOnThreadAvailableWaiting++; + mProcess->mOnThreadAvailableCondVar.wait(lock_guard_, [&] { + size_t max = mProcess->mMaxThreads; + size_t cur = mProcess->mExecutingThreadsCount; + if (cur < max) { + return true; + } + ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%" PRId64 + " mMaxThreads=%" PRId64 "\n", + cur, max); + return false; + }); + mProcess->mOnThreadAvailableWaiting--; } status_t IPCThreadState::getAndExecuteCommand() @@ -642,34 +646,33 @@ status_t IPCThreadState::getAndExecuteCommand() ALOGI("%s", message.c_str()); } - pthread_mutex_lock(&mProcess->mThreadCountLock); - mProcess->mExecutingThreadsCount++; - if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads && - mProcess->mStarvationStartTimeMs == 0) { - mProcess->mStarvationStartTimeMs = uptimeMillis(); + size_t newThreadsCount = mProcess->mExecutingThreadsCount.fetch_add(1) + 1; + if (newThreadsCount >= mProcess->mMaxThreads) { + int64_t expected = 0; + mProcess->mStarvationStartTimeMs.compare_exchange_strong(expected, uptimeMillis()); } - pthread_mutex_unlock(&mProcess->mThreadCountLock); result = executeCommand(cmd); - pthread_mutex_lock(&mProcess->mThreadCountLock); - mProcess->mExecutingThreadsCount--; - if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads && - mProcess->mStarvationStartTimeMs != 0) { - int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs; - if (starvationTimeMs > 100) { - ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms", - mProcess->mMaxThreads, starvationTimeMs); + size_t maxThreads = mProcess->mMaxThreads; + newThreadsCount = mProcess->mExecutingThreadsCount.fetch_sub(1) - 1; + if (newThreadsCount < maxThreads) { + size_t starvationStartTimeMs = mProcess->mStarvationStartTimeMs.exchange(0); + if (starvationStartTimeMs != 0) { + int64_t starvationTimeMs = uptimeMillis() - starvationStartTimeMs; + if (starvationTimeMs > 100) { + ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms", maxThreads, + starvationTimeMs); + } } - mProcess->mStarvationStartTimeMs = 0; } // Cond broadcast can be expensive, so don't send it every time a binder // call is processed. b/168806193 - if (mProcess->mWaitingForThreads > 0) { - pthread_cond_broadcast(&mProcess->mThreadCountDecrement); + if (mProcess->mOnThreadAvailableWaiting > 0) { + std::lock_guard lock_guard_(mProcess->mOnThreadAvailableLock); + mProcess->mOnThreadAvailableCondVar.notify_all(); } - pthread_mutex_unlock(&mProcess->mThreadCountLock); } return result; @@ -727,10 +730,9 @@ void IPCThreadState::processPostWriteDerefs() void IPCThreadState::joinThreadPool(bool isMain) { - LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); - pthread_mutex_lock(&mProcess->mThreadCountLock); + LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), + getpid()); mProcess->mCurrentThreads++; - pthread_mutex_unlock(&mProcess->mThreadCountLock); mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); mIsLooper = true; @@ -758,13 +760,11 @@ void IPCThreadState::joinThreadPool(bool isMain) mOut.writeInt32(BC_EXIT_LOOPER); mIsLooper = false; talkWithDriver(false); - pthread_mutex_lock(&mProcess->mThreadCountLock); - LOG_ALWAYS_FATAL_IF(mProcess->mCurrentThreads == 0, - "Threadpool thread count = 0. Thread cannot exist and exit in empty " - "threadpool\n" + size_t oldCount = mProcess->mCurrentThreads.fetch_sub(1); + LOG_ALWAYS_FATAL_IF(oldCount == 0, + "Threadpool thread count underflowed. Thread cannot exist and exit in " + "empty threadpool\n" "Misconfiguration. Increase threadpool max threads configuration\n"); - mProcess->mCurrentThreads--; - pthread_mutex_unlock(&mProcess->mThreadCountLock); } status_t IPCThreadState::setupPolling(int* fd) @@ -776,9 +776,7 @@ status_t IPCThreadState::setupPolling(int* fd) mOut.writeInt32(BC_ENTER_LOOPER); flushCommands(); *fd = mProcess->mDriverFD; - pthread_mutex_lock(&mProcess->mThreadCountLock); mProcess->mCurrentThreads++; - pthread_mutex_unlock(&mProcess->mThreadCountLock); return 0; } diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index fb2781be59..4f7cbad885 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -407,9 +407,7 @@ void ProcessState::spawnPooledThread(bool isMain) ALOGV("Spawning new pooled thread, name=%s\n", name.c_str()); sp t = sp::make(isMain); t->run(name.c_str()); - pthread_mutex_lock(&mThreadCountLock); mKernelStartedThreads++; - pthread_mutex_unlock(&mThreadCountLock); } // TODO: if startThreadPool is called on another thread after the process // starts up, the kernel might think that it already requested those @@ -432,19 +430,19 @@ status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) { } size_t ProcessState::getThreadPoolMaxTotalThreadCount() const { - pthread_mutex_lock(&mThreadCountLock); - auto detachGuard = make_scope_guard([&]() { pthread_mutex_unlock(&mThreadCountLock); }); - if (mThreadPoolStarted) { - LOG_ALWAYS_FATAL_IF(mKernelStartedThreads > mMaxThreads + 1, - "too many kernel-started threads: %zu > %zu + 1", mKernelStartedThreads, - mMaxThreads); + size_t kernelStarted = mKernelStartedThreads; + size_t max = mMaxThreads; + size_t current = mCurrentThreads; + + LOG_ALWAYS_FATAL_IF(kernelStarted > max + 1, + "too many kernel-started threads: %zu > %zu + 1", kernelStarted, max); // calling startThreadPool starts a thread size_t threads = 1; // the kernel is configured to start up to mMaxThreads more threads - threads += mMaxThreads; + threads += max; // Users may call IPCThreadState::joinThreadPool directly. We don't // currently have a way to count this directly (it could be added by @@ -454,8 +452,8 @@ size_t ProcessState::getThreadPoolMaxTotalThreadCount() const { // in IPCThreadState, temporarily forget about the extra join threads. // This is okay, because most callers of this method only care about // having 0, 1, or more threads. - if (mCurrentThreads > mKernelStartedThreads) { - threads += mCurrentThreads - mKernelStartedThreads; + if (current > kernelStarted) { + threads += current - kernelStarted; } return threads; @@ -463,10 +461,9 @@ size_t ProcessState::getThreadPoolMaxTotalThreadCount() const { // must not be initialized or maybe has poll thread setup, we // currently don't track this in libbinder - LOG_ALWAYS_FATAL_IF(mKernelStartedThreads != 0, - "Expecting 0 kernel started threads but have" - " %zu", - mKernelStartedThreads); + size_t kernelStarted = mKernelStartedThreads; + LOG_ALWAYS_FATAL_IF(kernelStarted != 0, "Expecting 0 kernel started threads but have %zu", + kernelStarted); return mCurrentThreads; } @@ -553,10 +550,7 @@ ProcessState::ProcessState(const char* driver) : mDriverName(String8(driver)), mDriverFD(-1), mVMStart(MAP_FAILED), - mThreadCountLock(PTHREAD_MUTEX_INITIALIZER), - mThreadCountDecrement(PTHREAD_COND_INITIALIZER), mExecutingThreadsCount(0), - mWaitingForThreads(0), mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mCurrentThreads(0), mKernelStartedThreads(0), diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index a46663867c..11898a0515 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -23,6 +23,7 @@ #include +#include #include // --------------------------------------------------------------------------- @@ -162,22 +163,21 @@ private: int mDriverFD; void* mVMStart; - // Protects thread count and wait variables below. - mutable pthread_mutex_t mThreadCountLock; - // Broadcast whenever mWaitingForThreads > 0 - pthread_cond_t mThreadCountDecrement; + mutable std::mutex mOnThreadAvailableLock; + std::condition_variable mOnThreadAvailableCondVar; + // Number of threads waiting on `mOnThreadAvailableCondVar`. + std::atomic_int64_t mOnThreadAvailableWaiting = 0; + // Number of binder threads current executing a command. - size_t mExecutingThreadsCount; - // Number of threads calling IPCThreadState::blockUntilThreadAvailable() - size_t mWaitingForThreads; + std::atomic_size_t mExecutingThreadsCount; // Maximum number of lazy threads to be started in the threadpool by the kernel. - size_t mMaxThreads; + std::atomic_size_t mMaxThreads; // Current number of threads inside the thread pool. - size_t mCurrentThreads; + std::atomic_size_t mCurrentThreads; // Current number of pooled threads inside the thread pool. - size_t mKernelStartedThreads; + std::atomic_size_t mKernelStartedThreads; // Time when thread pool was emptied - int64_t mStarvationStartTimeMs; + std::atomic_int64_t mStarvationStartTimeMs; mutable std::mutex mLock; // protects everything below. -- GitLab From 983c460931129619842e0fb3fffefbbdd1bcf945 Mon Sep 17 00:00:00 2001 From: Daniele Di Proietto Date: Mon, 15 Apr 2024 18:18:01 +0000 Subject: [PATCH 003/530] atrace: New --prefer_sdk flag The flag sets a new property `debug.atrace.prefer_sdk`, which is a bitmap of the categories that are supposed to prefer the perfetto sdk over legacy atrace. Bug: 303199244 Change-Id: I8ad73e415e0a2713ebf9b51b6702fd4f9961f1e7 --- cmds/atrace/atrace.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index cd4926ad50..4160a72e83 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -68,6 +68,7 @@ using std::string; const char* k_traceTagsProperty = "debug.atrace.tags.enableflags"; const char* k_userInitiatedTraceProperty = "debug.atrace.user_initiated"; +const char* k_tracePreferSdkProperty = "debug.atrace.prefer_sdk"; const char* k_traceAppsNumberProperty = "debug.atrace.app_number"; const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d"; const char* k_coreServiceCategory = "core_services"; @@ -600,6 +601,17 @@ static void clearAppProperties() } } +// Set the property that's read by userspace to prefer the perfetto SDK. +static bool setPreferSdkProperty(uint64_t tags) +{ + std::string value = android::base::StringPrintf("%#" PRIx64, tags); + if (!android::base::SetProperty(k_tracePreferSdkProperty, value)) { + fprintf(stderr, "error setting prefer_sdk system property\n"); + return false; + } + return true; +} + // Set the system property that indicates which apps should perform // application-level tracing. static bool setAppCmdlineProperty(char* cmdline) @@ -918,6 +930,17 @@ static void stopTrace() setTracingEnabled(false); } +static bool preferSdkCategories() { + uint64_t tags = 0; + for (size_t i = 0; i < arraysize(k_categories); i++) { + if (g_categoryEnables[i]) { + const TracingCategory& c = k_categories[i]; + tags |= c.tags; + } + } + return setPreferSdkProperty(tags); +} + // Read data from the tracing pipe and forward to stdout static void streamTrace() { @@ -1108,6 +1131,9 @@ static void showHelp(const char *cmd) " CPU performance, like pagecache usage.\n" " --list_categories\n" " list the available tracing categories\n" + " --prefer_sdk\n" + " prefer the perfetto sdk over legacy atrace for\n" + " categories and exits immediately\n" " -o filename write the trace to the specified file instead\n" " of stdout.\n" ); @@ -1252,6 +1278,7 @@ int main(int argc, char **argv) bool traceStop = true; bool traceDump = true; bool traceStream = false; + bool preferSdk = false; bool onlyUserspace = false; if (argc == 2 && 0 == strcmp(argv[1], "--help")) { @@ -1276,6 +1303,7 @@ int main(int argc, char **argv) {"only_userspace", no_argument, nullptr, 0 }, {"list_categories", no_argument, nullptr, 0 }, {"stream", no_argument, nullptr, 0 }, + {"prefer_sdk", no_argument, nullptr, 0 }, {nullptr, 0, nullptr, 0 } }; @@ -1348,6 +1376,8 @@ int main(int argc, char **argv) } else if (!strcmp(long_options[option_index].name, "stream")) { traceStream = true; traceDump = false; + } else if (!strcmp(long_options[option_index].name, "prefer_sdk")) { + preferSdk = true; } else if (!strcmp(long_options[option_index].name, "list_categories")) { listSupportedCategories(); exit(0); @@ -1362,6 +1392,11 @@ int main(int argc, char **argv) } } + if (preferSdk) { + bool res = preferSdkCategories(); + exit(res ? 0 : 1); + } + if (onlyUserspace) { if (!async || !(traceStart || traceStop)) { fprintf(stderr, "--only_userspace can only be used with " -- GitLab From e283631bb407d6cd7b0d8578f4ac2dfd1706f398 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Thu, 9 May 2024 14:36:19 -0700 Subject: [PATCH 004/530] Implement binder_sdk*_test(s) These tests attempt to build binder_sdk snapshot in controlled environment outside of Android build tree. Bug: 302718225 Test: atest binder_sdk_test Test: atest binder_sdk_docker_test_clang Test: atest binder_sdk_docker_test_gcc Test: atest binder_sdk_docker_test_gnumake Test: cd frameworks/native/libs/binder/tests/binder_sdk ./binder_sdk_docker_test.sh clang.Dockerfile Change-Id: I11fdd05428726884541fbb61dea34e4e82389f4f --- libs/binder/Android.bp | 15 +++- libs/binder/tests/binder_sdk/Android.bp | 84 +++++++++++++++++++ .../binder_sdk/binder_sdk_docker_test.sh | 70 ++++++++++++++++ .../tests/binder_sdk/binder_sdk_test.sh | 40 +++++++++ libs/binder/tests/binder_sdk/clang.Dockerfile | 32 +++++++ libs/binder/tests/binder_sdk/gcc.Dockerfile | 32 +++++++ .../tests/binder_sdk/gnumake.Dockerfile | 30 +++++++ 7 files changed, 300 insertions(+), 3 deletions(-) create mode 100644 libs/binder/tests/binder_sdk/Android.bp create mode 100755 libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh create mode 100644 libs/binder/tests/binder_sdk/binder_sdk_test.sh create mode 100644 libs/binder/tests/binder_sdk/clang.Dockerfile create mode 100644 libs/binder/tests/binder_sdk/gcc.Dockerfile create mode 100644 libs/binder/tests/binder_sdk/gnumake.Dockerfile diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index cb1d1143bc..9a4644860c 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -19,6 +19,7 @@ package { // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 default_applicable_licenses: ["frameworks_native_license"], + default_team: "trendy_team_virtualization", } cc_library_headers { @@ -90,7 +91,11 @@ cc_cmake_snapshot { "libbinder_sdk", "libbinder_sdk_single_threaded", "libbinder_ndk_sdk", + "googletest_cmake", + "binderRpcTestNoKernel", + "binderRpcTestSingleThreadedNoKernel", + "binderRpcWireProtocolTest", ], prebuilts: [ // to enable arm64 host support, build with musl - e.g. on aosp_cf_arm64_phone @@ -133,12 +138,16 @@ cc_cmake_snapshot { { android_name: "libgtest", mapped_name: "GTest::gtest", - package_system: "GTest", + package_pregenerated: "external/googletest", }, { android_name: "libgtest_main", - mapped_name: "GTest::gtest", - package_system: "GTest", + mapped_name: "GTest::gtest_main", + package_pregenerated: "external/googletest", + }, + { + android_name: "googletest_cmake", + package_pregenerated: "external/googletest", }, // use libbinder_sdk and friends instead of full Android's libbinder diff --git a/libs/binder/tests/binder_sdk/Android.bp b/libs/binder/tests/binder_sdk/Android.bp new file mode 100644 index 0000000000..4e884ad319 --- /dev/null +++ b/libs/binder/tests/binder_sdk/Android.bp @@ -0,0 +1,84 @@ +// +// 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. +// + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + +sh_test_host { + name: "binder_sdk_test", + src: "binder_sdk_test.sh", + test_suites: ["general-tests"], + test_options: { + unit_test: false, + }, + + data: [ + ":binder_sdk", + ":cmake_root", + ], + data_bins: [ + "cmake", + "ctest", + ], +} + +sh_test_host { + name: "binder_sdk_docker_test_gcc", + src: "binder_sdk_docker_test.sh", + test_suites: ["general-tests"], + test_options: { + unit_test: false, + }, + + data: [ + ":binder_sdk", + "gcc.Dockerfile", + ], +} + +sh_test_host { + name: "binder_sdk_docker_test_clang", + src: "binder_sdk_docker_test.sh", + test_suites: ["general-tests"], + test_options: { + unit_test: false, + }, + + data: [ + ":binder_sdk", + "clang.Dockerfile", + ], +} + +sh_test_host { + name: "binder_sdk_docker_test_gnumake", + src: "binder_sdk_docker_test.sh", + test_suites: ["general-tests"], + test_options: { + unit_test: false, + }, + + data: [ + ":binder_sdk", + "gnumake.Dockerfile", + ], +} diff --git a/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh b/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh new file mode 100755 index 0000000000..0eca84607e --- /dev/null +++ b/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# +# 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. +# + +set -ex + +TEST_NAME="$(basename "$0")" +DOCKER_TAG="${TEST_NAME}-${RANDOM}${RANDOM}" +DOCKER_FILE=*.Dockerfile +DOCKER_RUN_FLAGS= + +# Guess if we're running as an Android test or directly +if [ "$(ls -1 ${DOCKER_FILE} | wc -l)" == "1" ]; then + # likely running as `atest binder_sdk_docker_test_XYZ` + DOCKER_PATH="$(dirname $(readlink --canonicalize --no-newline binder_sdk.zip))" +else + # likely running directly as `./binder_sdk_docker_test.sh` - provide mode for easy testing + RED='\033[1;31m' + NO_COLOR='\033[0m' + + if ! modinfo vsock_loopback &>/dev/null ; then + echo -e "${RED}Module vsock_loopback is not installed.${NO_COLOR}" + exit 1 + fi + if modprobe --dry-run --first-time vsock_loopback &>/dev/null ; then + echo "Module vsock_loopback is not loaded. Attempting to load..." + if ! sudo modprobe vsock_loopback ; then + echo -e "${RED}Module vsock_loopback is not loaded and attempt to load failed.${NO_COLOR}" + exit 1 + fi + fi + + DOCKER_RUN_FLAGS="--interactive --tty" + + DOCKER_FILE="$1" + if [ ! -f "${DOCKER_FILE}" ]; then + echo -e "${RED}Docker file '${DOCKER_FILE}' doesn't exist. Please provide one as an argument.${NO_COLOR}" + exit 1 + fi + + if [ ! -d "${ANDROID_BUILD_TOP}" ]; then + echo -e "${RED}ANDROID_BUILD_TOP doesn't exist. Please lunch some target.${NO_COLOR}" + exit 1 + fi + ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode binder_sdk + BINDER_SDK_ZIP="${ANDROID_BUILD_TOP}/out/soong/.intermediates/frameworks/native/libs/binder/binder_sdk/linux_glibc_x86_64/*/binder_sdk.zip" + DOCKER_PATH="$(dirname $(ls -1 ${BINDER_SDK_ZIP} | head --lines=1))" +fi + +function cleanup { + docker rmi --force "${DOCKER_TAG}" 2>/dev/null || true +} +trap cleanup EXIT + +docker build --force-rm --tag "${DOCKER_TAG}" --file ${DOCKER_FILE} ${DOCKER_PATH} +docker run ${DOCKER_RUN_FLAGS} --rm "${DOCKER_TAG}" diff --git a/libs/binder/tests/binder_sdk/binder_sdk_test.sh b/libs/binder/tests/binder_sdk/binder_sdk_test.sh new file mode 100644 index 0000000000..1881acef5e --- /dev/null +++ b/libs/binder/tests/binder_sdk/binder_sdk_test.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# +# 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. +# + +set -ex + +RED='\033[1;31m' +NO_COLOR='\033[0m' + +if [ ! -f "binder_sdk.zip" ]; then + echo -e "${RED}binder_sdk.zip doesn't exist. Are you running this test through 'atest binder_sdk_test'?${NO_COLOR}" + exit 1 +fi + +mkdir -p bin +cp `pwd`/cmake bin/cmake +cp `pwd`/ctest bin/ctest +export PATH="`pwd`/bin:$PATH" + +WORKDIR=workdir_$RANDOM$RANDOM$RANDOM +unzip -q -d $WORKDIR binder_sdk.zip +cd $WORKDIR + +cmake . +make -j +make test ARGS="--parallel 32 --output-on-failure" diff --git a/libs/binder/tests/binder_sdk/clang.Dockerfile b/libs/binder/tests/binder_sdk/clang.Dockerfile new file mode 100644 index 0000000000..aa1fec2d3c --- /dev/null +++ b/libs/binder/tests/binder_sdk/clang.Dockerfile @@ -0,0 +1,32 @@ +# +# 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. +# + +FROM debian:bookworm + +RUN echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list && \ + apt-get update -y && \ + apt-get install -y clang cmake ninja-build unzip + +ADD binder_sdk.zip / +RUN unzip -q -d binder_sdk binder_sdk.zip + +WORKDIR /binder_sdk +RUN CC=clang CXX=clang++ cmake -G Ninja -B build . +RUN cmake --build build + +WORKDIR /binder_sdk/build +# Alternatively: `ninja test`, but it won't pass parallel argument +ENTRYPOINT [ "ctest", "--parallel", "32", "--output-on-failure" ] diff --git a/libs/binder/tests/binder_sdk/gcc.Dockerfile b/libs/binder/tests/binder_sdk/gcc.Dockerfile new file mode 100644 index 0000000000..fb2ee2ce7d --- /dev/null +++ b/libs/binder/tests/binder_sdk/gcc.Dockerfile @@ -0,0 +1,32 @@ +# +# 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. +# + +FROM gcc:9 + +RUN echo 'deb http://deb.debian.org/debian bullseye-backports main' >> /etc/apt/sources.list && \ + apt-get update -y && \ + apt-get install -y cmake ninja-build + +ADD binder_sdk.zip / +RUN unzip -q -d binder_sdk binder_sdk.zip + +WORKDIR /binder_sdk +RUN CC=gcc CXX=g++ cmake -G Ninja -B build . +RUN cmake --build build + +WORKDIR /binder_sdk/build +# Alternatively: `ninja test`, but it won't pass parallel argument +ENTRYPOINT [ "ctest", "--parallel", "32", "--output-on-failure" ] diff --git a/libs/binder/tests/binder_sdk/gnumake.Dockerfile b/libs/binder/tests/binder_sdk/gnumake.Dockerfile new file mode 100644 index 0000000000..abe12fb9d1 --- /dev/null +++ b/libs/binder/tests/binder_sdk/gnumake.Dockerfile @@ -0,0 +1,30 @@ +# +# 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. +# + +FROM gcc:9 + +RUN echo 'deb http://deb.debian.org/debian bullseye-backports main' >> /etc/apt/sources.list && \ + apt-get update -y && \ + apt-get install -y cmake + +ADD binder_sdk.zip / +RUN unzip -q -d binder_sdk binder_sdk.zip + +WORKDIR /binder_sdk +RUN cmake . +RUN make -j + +ENTRYPOINT make test ARGS="--parallel 32 --output-on-failure" -- GitLab From 27613c3cdced0d63e5981fbd55197f052a323b43 Mon Sep 17 00:00:00 2001 From: Nergi Rahardi Date: Thu, 23 May 2024 06:57:02 +0000 Subject: [PATCH 005/530] Revert^2 "Set Change::Metadata on LayerMetadata update" This reverts commit 10fbacda6dc007baca753d19ccfd148cd8a8eab9. Reason for revert: Change::Metadata no longer sent on BLAST dequeueTime update ag/27478127 Change-Id: I9889ac6cfcd03103fcc9ede13f4b05a3bf8fcdb3 --- libs/gui/include/gui/LayerMetadata.h | 1 + .../FrontEnd/LayerSnapshotBuilder.cpp | 10 ++-- .../FrontEnd/RequestedLayerState.cpp | 1 + .../tests/unittests/LayerSnapshotTest.cpp | 46 ++++++++++++++++++- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h index 9cf62bc7d6..7ee291df4c 100644 --- a/libs/gui/include/gui/LayerMetadata.h +++ b/libs/gui/include/gui/LayerMetadata.h @@ -74,6 +74,7 @@ enum class GameMode : int32_t { } // namespace android::gui using android::gui::METADATA_ACCESSIBILITY_ID; +using android::gui::METADATA_CALLING_UID; using android::gui::METADATA_DEQUEUE_TIME; using android::gui::METADATA_GAME_MODE; using android::gui::METADATA_MOUSE_CURSOR; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index ca53a0dfa6..2d424372f0 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -801,10 +801,12 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a } } - if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::GameMode)) { - snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) - ? requested.gameMode - : parentSnapshot.gameMode; + if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::Metadata)) { + if (snapshot.changes.test(RequestedLayerState::Changes::GameMode)) { + snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) + ? requested.gameMode + : parentSnapshot.gameMode; + } updateMetadata(snapshot, requested, args); if (args.includeMetadata) { snapshot.layerMetadata = parentSnapshot.layerMetadata; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 3e8d74094d..c3c299964a 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -328,6 +328,7 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta changes |= RequestedLayerState::Changes::GameMode; } } + changes |= RequestedLayerState::Changes::Metadata; } if (clientState.what & layer_state_t::eFrameRateChanged) { const auto compatibility = diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index dedb292b34..081bf4a089 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -291,13 +291,57 @@ TEST_F(LayerSnapshotTest, GameMode) { transactions.back().states.front().layerId = 1; transactions.back().states.front().state.layerId = static_cast(1); mLifecycleManager.applyTransactions(transactions); - EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::GameMode); + EXPECT_EQ(mLifecycleManager.getGlobalChanges(), + RequestedLayerState::Changes::GameMode | RequestedLayerState::Changes::Metadata); UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER); EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eMetadataChanged); EXPECT_EQ(static_cast(getSnapshot(1)->gameMode), 42); EXPECT_EQ(static_cast(getSnapshot(11)->gameMode), 42); } +TEST_F(LayerSnapshotTest, UpdateMetadata) { + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + transactions.back().states.front().state.what = layer_state_t::eMetadataChanged; + // This test focuses on metadata used by ARC++ to ensure LayerMetadata is updated correctly, + // and not using stale data. + transactions.back().states.front().state.metadata = LayerMetadata(); + transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_UID, 123); + transactions.back().states.front().state.metadata.setInt32(METADATA_WINDOW_TYPE, 234); + transactions.back().states.front().state.metadata.setInt32(METADATA_TASK_ID, 345); + transactions.back().states.front().state.metadata.setInt32(METADATA_MOUSE_CURSOR, 456); + transactions.back().states.front().state.metadata.setInt32(METADATA_ACCESSIBILITY_ID, 567); + transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_PID, 678); + transactions.back().states.front().state.metadata.setInt32(METADATA_CALLING_UID, 789); + + transactions.back().states.front().layerId = 1; + transactions.back().states.front().state.layerId = static_cast(1); + + mLifecycleManager.applyTransactions(transactions); + EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::Metadata); + + // Setting includeMetadata=true to ensure metadata update is applied to LayerSnapshot + LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(), + .layerLifecycleManager = mLifecycleManager, + .includeMetadata = true, + .displays = mFrontEndDisplayInfos, + .globalShadowSettings = globalShadowSettings, + .supportsBlur = true, + .supportedLayerGenericMetadata = {}, + .genericLayerMetadataKeyMap = {}}; + update(mSnapshotBuilder, args); + + EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eMetadataChanged); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_UID, -1), 123); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_WINDOW_TYPE, -1), 234); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_TASK_ID, -1), 345); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_MOUSE_CURSOR, -1), 456); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_ACCESSIBILITY_ID, -1), 567); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_PID, -1), 678); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_CALLING_UID, -1), 789); +} + TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) { // ROOT // ├── 1 -- GitLab From 0dfc096b0816f584bc4aa7e81d658df3847a34be Mon Sep 17 00:00:00 2001 From: Nergi Rahardi Date: Thu, 23 May 2024 06:57:36 +0000 Subject: [PATCH 006/530] Revert^2 "SF: Update metadata of unvisible layers to backend" This reverts commit ad34a68198c65bea568bac779fd8ad2937ba8087. Reason for revert: Change::Metadata no longer sent on BLAST dequeueTime update ag/27478127 Change-Id: I912d50938089edfb56154561b53d365024ce15ed --- .../FrontEnd/LayerSnapshotBuilder.cpp | 40 +++++++++---- .../FrontEnd/LayerSnapshotBuilder.h | 5 ++ services/surfaceflinger/SurfaceFlinger.cpp | 10 +++- .../tests/unittests/LayerSnapshotTest.cpp | 60 +++++++++++++++++++ 4 files changed, 104 insertions(+), 11 deletions(-) diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 2d424372f0..a4ffd51d43 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -317,6 +317,21 @@ void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requeste } } +void updateMetadataAndGameMode(LayerSnapshot& snapshot, const RequestedLayerState& requested, + const LayerSnapshotBuilder::Args& args, + const LayerSnapshot& parentSnapshot) { + if (snapshot.changes.test(RequestedLayerState::Changes::GameMode)) { + snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) + ? requested.gameMode + : parentSnapshot.gameMode; + } + updateMetadata(snapshot, requested, args); + if (args.includeMetadata) { + snapshot.layerMetadata = parentSnapshot.layerMetadata; + snapshot.layerMetadata.merge(requested.metadata); + } +} + void clearChanges(LayerSnapshot& snapshot) { snapshot.changes.clear(); snapshot.clientChanges = 0; @@ -762,6 +777,11 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a RequestedLayerState::Changes::Input)) { updateInput(snapshot, requested, parentSnapshot, path, args); } + if (forceUpdate || + (args.includeMetadata && + snapshot.changes.test(RequestedLayerState::Changes::Metadata))) { + updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot); + } return; } @@ -802,16 +822,7 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a } if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::Metadata)) { - if (snapshot.changes.test(RequestedLayerState::Changes::GameMode)) { - snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE) - ? requested.gameMode - : parentSnapshot.gameMode; - } - updateMetadata(snapshot, requested, args); - if (args.includeMetadata) { - snapshot.layerMetadata = parentSnapshot.layerMetadata; - snapshot.layerMetadata.merge(requested.metadata); - } + updateMetadataAndGameMode(snapshot, requested, args, parentSnapshot); } if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged || @@ -1180,6 +1191,15 @@ void LayerSnapshotBuilder::forEachVisibleSnapshot(const Visitor& visitor) { } } +void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor, + const ConstPredicate& predicate) { + for (int i = 0; i < mNumInterestingSnapshots; i++) { + std::unique_ptr& snapshot = mSnapshots.at((size_t)i); + if (!predicate(*snapshot)) continue; + visitor(snapshot); + } +} + void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const { for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) { LayerSnapshot& snapshot = *mSnapshots[(size_t)i]; diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h index 1cec0183b9..dbbad7664a 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h @@ -86,6 +86,11 @@ public: // Visit each visible snapshot in z-order and move the snapshot if needed void forEachVisibleSnapshot(const Visitor& visitor); + typedef std::function ConstPredicate; + // Visit each snapshot that satisfies the predicate and move the snapshot if needed with visible + // snapshots in z-order + void forEachSnapshot(const Visitor& visitor, const ConstPredicate& predicate); + // Visit each snapshot interesting to input reverse z-order void forEachInputSnapshot(const ConstVisitor& visitor) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 694f147ea0..53ed489b58 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -9315,7 +9315,9 @@ std::vector> SurfaceFlinger::moveSnapshotsToComposit std::vector> layers; if (mLayerLifecycleManagerEnabled) { nsecs_t currentTime = systemTime(); - mLayerSnapshotBuilder.forEachVisibleSnapshot( + const bool needsMetadata = mCompositionEngine->getFeatureFlags().test( + compositionengine::Feature::kSnapshotLayerMetadata); + mLayerSnapshotBuilder.forEachSnapshot( [&](std::unique_ptr& snapshot) FTL_FAKE_GUARD( kMainThreadContext) { if (cursorOnly && @@ -9338,6 +9340,12 @@ std::vector> SurfaceFlinger::moveSnapshotsToComposit layerFE->mSnapshot = std::move(snapshot); refreshArgs.layers.push_back(layerFE); layers.emplace_back(legacyLayer.get(), layerFE.get()); + }, + [needsMetadata](const frontend::LayerSnapshot& snapshot) { + return snapshot.isVisible || + (needsMetadata && + snapshot.changes.test( + frontend::RequestedLayerState::Changes::Metadata)); }); } if (!mLayerLifecycleManagerEnabled) { diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp index 081bf4a089..4641f78d69 100644 --- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp @@ -342,6 +342,55 @@ TEST_F(LayerSnapshotTest, UpdateMetadata) { EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_CALLING_UID, -1), 789); } +TEST_F(LayerSnapshotTest, UpdateMetadataOfHiddenLayers) { + hideLayer(1); + + std::vector transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + transactions.back().states.front().state.what = layer_state_t::eMetadataChanged; + // This test focuses on metadata used by ARC++ to ensure LayerMetadata is updated correctly, + // and not using stale data. + transactions.back().states.front().state.metadata = LayerMetadata(); + transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_UID, 123); + transactions.back().states.front().state.metadata.setInt32(METADATA_WINDOW_TYPE, 234); + transactions.back().states.front().state.metadata.setInt32(METADATA_TASK_ID, 345); + transactions.back().states.front().state.metadata.setInt32(METADATA_MOUSE_CURSOR, 456); + transactions.back().states.front().state.metadata.setInt32(METADATA_ACCESSIBILITY_ID, 567); + transactions.back().states.front().state.metadata.setInt32(METADATA_OWNER_PID, 678); + transactions.back().states.front().state.metadata.setInt32(METADATA_CALLING_UID, 789); + + transactions.back().states.front().layerId = 1; + transactions.back().states.front().state.layerId = static_cast(1); + + mLifecycleManager.applyTransactions(transactions); + EXPECT_EQ(mLifecycleManager.getGlobalChanges(), + RequestedLayerState::Changes::Metadata | RequestedLayerState::Changes::Visibility | + RequestedLayerState::Changes::VisibleRegion | + RequestedLayerState::Changes::AffectsChildren); + + // Setting includeMetadata=true to ensure metadata update is applied to LayerSnapshot + LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(), + .layerLifecycleManager = mLifecycleManager, + .includeMetadata = true, + .displays = mFrontEndDisplayInfos, + .globalShadowSettings = globalShadowSettings, + .supportsBlur = true, + .supportedLayerGenericMetadata = {}, + .genericLayerMetadataKeyMap = {}}; + update(mSnapshotBuilder, args); + + EXPECT_EQ(static_cast(getSnapshot(1)->clientChanges), + layer_state_t::eMetadataChanged | layer_state_t::eFlagsChanged); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_UID, -1), 123); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_WINDOW_TYPE, -1), 234); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_TASK_ID, -1), 345); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_MOUSE_CURSOR, -1), 456); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_ACCESSIBILITY_ID, -1), 567); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_OWNER_PID, -1), 678); + EXPECT_EQ(getSnapshot(1)->layerMetadata.getInt32(METADATA_CALLING_UID, -1), 789); +} + TEST_F(LayerSnapshotTest, NoLayerVoteForParentWithChildVotes) { // ROOT // ├── 1 @@ -1338,6 +1387,17 @@ TEST_F(LayerSnapshotTest, NonVisibleLayerWithInput) { EXPECT_TRUE(foundInputLayer); } +TEST_F(LayerSnapshotTest, ForEachSnapshotsWithPredicate) { + std::vector visitedUniqueSequences; + mSnapshotBuilder.forEachSnapshot( + [&](const std::unique_ptr& snapshot) { + visitedUniqueSequences.push_back(snapshot->uniqueSequence); + }, + [](const frontend::LayerSnapshot& snapshot) { return snapshot.uniqueSequence == 111; }); + EXPECT_EQ(visitedUniqueSequences.size(), 1u); + EXPECT_EQ(visitedUniqueSequences[0], 111u); +} + TEST_F(LayerSnapshotTest, canOccludePresentation) { setFlags(12, layer_state_t::eCanOccludePresentation, layer_state_t::eCanOccludePresentation); LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(), -- GitLab From e35071d1328a9803712019a16d2d0fd06411464a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 13 Jun 2024 11:47:49 +0000 Subject: [PATCH 007/530] libc++fs is part of libc++ now. Change-Id: I2a8455c6da5d6fc537f0201aeaaf2837be50d26f --- cmds/dumpstate/Android.bp | 1 - 1 file changed, 1 deletion(-) diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index 4a77967bb2..59770b8b58 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -158,7 +158,6 @@ cc_test { "tests/dumpstate_test.cpp", ], static_libs: [ - "libc++fs", "libgmock", ], test_config: "dumpstate_test.xml", -- GitLab From a8359fccae2082d864f1df08c4eb7028d59f3c4b Mon Sep 17 00:00:00 2001 From: Vaibhav Devmurari Date: Mon, 10 Jun 2024 20:01:25 +0000 Subject: [PATCH 008/530] Add support for pre-classifying devices Bring in blocklist from CrOS as initial config (https://source.chromium.org/chromium/chromium/src/+/main:ui/events/ozone/evdev/event_device_info.cc;drc=1bbf8ac9caa7e57a52a71deec56bf1b6f683c6bd;l=31) Test: atest --host libinput_rust_test Bug: 263559234 Flag: com.android.input.flags.enable_keyboard_classifier Change-Id: I8ffd3d6268cd96de9dfa0addb4653768fed5732c --- .../rust/keyboard_classification_config.rs | 127 ++++++++++++++++++ libs/input/rust/keyboard_classifier.rs | 38 ++++++ libs/input/rust/lib.rs | 1 + 3 files changed, 166 insertions(+) create mode 100644 libs/input/rust/keyboard_classification_config.rs diff --git a/libs/input/rust/keyboard_classification_config.rs b/libs/input/rust/keyboard_classification_config.rs new file mode 100644 index 0000000000..ab74efb674 --- /dev/null +++ b/libs/input/rust/keyboard_classification_config.rs @@ -0,0 +1,127 @@ +/* + * Copyright 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. + */ + +use crate::input::KeyboardType; + +// TODO(b/263559234): Categorize some of these to KeyboardType::None based on ability to produce +// key events at all. (Requires setup allowing InputDevice to dynamically add/remove +// KeyboardInputMapper based on blocklist and KeyEvents in case a KeyboardType::None device ends +// up producing a key event) +pub static CLASSIFIED_DEVICES: &[( + /* vendorId */ u16, + /* productId */ u16, + KeyboardType, + /* is_finalized */ bool, +)] = &[ + // HP X4000 Wireless Mouse + (0x03f0, 0xa407, KeyboardType::NonAlphabetic, true), + // Microsoft Wireless Mobile Mouse 6000 + (0x045e, 0x0745, KeyboardType::NonAlphabetic, true), + // Microsoft Surface Precision Mouse + (0x045e, 0x0821, KeyboardType::NonAlphabetic, true), + // Microsoft Pro IntelliMouse + (0x045e, 0x082a, KeyboardType::NonAlphabetic, true), + // Microsoft Bluetooth Mouse + (0x045e, 0x082f, KeyboardType::NonAlphabetic, true), + // Xbox One Elite Series 2 gamepad + (0x045e, 0x0b05, KeyboardType::NonAlphabetic, true), + // Logitech T400 + (0x046d, 0x4026, KeyboardType::NonAlphabetic, true), + // Logitech M720 Triathlon (Unifying) + (0x046d, 0x405e, KeyboardType::NonAlphabetic, true), + // Logitech MX Master 2S (Unifying) + (0x046d, 0x4069, KeyboardType::NonAlphabetic, true), + // Logitech M585 (Unifying) + (0x046d, 0x406b, KeyboardType::NonAlphabetic, true), + // Logitech MX Anywhere 2 (Unifying) + (0x046d, 0x4072, KeyboardType::NonAlphabetic, true), + // Logitech Pebble M350 + (0x046d, 0x4080, KeyboardType::NonAlphabetic, true), + // Logitech T630 Ultrathin + (0x046d, 0xb00d, KeyboardType::NonAlphabetic, true), + // Logitech M558 + (0x046d, 0xb011, KeyboardType::NonAlphabetic, true), + // Logitech MX Master (Bluetooth) + (0x046d, 0xb012, KeyboardType::NonAlphabetic, true), + // Logitech MX Anywhere 2 (Bluetooth) + (0x046d, 0xb013, KeyboardType::NonAlphabetic, true), + // Logitech M720 Triathlon (Bluetooth) + (0x046d, 0xb015, KeyboardType::NonAlphabetic, true), + // Logitech M535 + (0x046d, 0xb016, KeyboardType::NonAlphabetic, true), + // Logitech MX Master / Anywhere 2 (Bluetooth) + (0x046d, 0xb017, KeyboardType::NonAlphabetic, true), + // Logitech MX Master 2S (Bluetooth) + (0x046d, 0xb019, KeyboardType::NonAlphabetic, true), + // Logitech MX Anywhere 2S (Bluetooth) + (0x046d, 0xb01a, KeyboardType::NonAlphabetic, true), + // Logitech M585/M590 (Bluetooth) + (0x046d, 0xb01b, KeyboardType::NonAlphabetic, true), + // Logitech G603 Lightspeed Gaming Mouse (Bluetooth) + (0x046d, 0xb01c, KeyboardType::NonAlphabetic, true), + // Logitech MX Master (Bluetooth) + (0x046d, 0xb01e, KeyboardType::NonAlphabetic, true), + // Logitech MX Anywhere 2 (Bluetooth) + (0x046d, 0xb01f, KeyboardType::NonAlphabetic, true), + // Logitech MX Master 3 (Bluetooth) + (0x046d, 0xb023, KeyboardType::NonAlphabetic, true), + // Logitech G604 Lightspeed Gaming Mouse (Bluetooth) + (0x046d, 0xb024, KeyboardType::NonAlphabetic, true), + // Logitech Spotlight Presentation Remote (Bluetooth) + (0x046d, 0xb503, KeyboardType::NonAlphabetic, true), + // Logitech R500 (Bluetooth) + (0x046d, 0xb505, KeyboardType::NonAlphabetic, true), + // Logitech M500s + (0x046d, 0xc093, KeyboardType::NonAlphabetic, true), + // Logitech Spotlight Presentation Remote (USB dongle) + (0x046d, 0xc53e, KeyboardType::NonAlphabetic, true), + // Elecom Enelo IR LED Mouse 350 + (0x056e, 0x0134, KeyboardType::NonAlphabetic, true), + // Elecom EPRIM Blue LED 5 button mouse 228 + (0x056e, 0x0141, KeyboardType::NonAlphabetic, true), + // Elecom Blue LED Mouse 203 + (0x056e, 0x0159, KeyboardType::NonAlphabetic, true), + // Zebra LS2208 barcode scanner + (0x05e0, 0x1200, KeyboardType::NonAlphabetic, true), + // RDing FootSwitch1F1 + (0x0c45, 0x7403, KeyboardType::NonAlphabetic, true), + // SteelSeries Sensei RAW Frost Blue + (0x1038, 0x1369, KeyboardType::NonAlphabetic, true), + // SteelSeries Rival 3 Wired + (0x1038, 0x1824, KeyboardType::NonAlphabetic, true), + // SteelSeries Rival 3 Wireless (USB dongle) + (0x1038, 0x1830, KeyboardType::NonAlphabetic, true), + // Yubico.com Yubikey + (0x1050, 0x0010, KeyboardType::NonAlphabetic, true), + // Yubico.com Yubikey 4 OTP+U2F+CCID + (0x1050, 0x0407, KeyboardType::NonAlphabetic, true), + // Lenovo USB-C Wired Compact Mouse + (0x17ef, 0x6123, KeyboardType::NonAlphabetic, true), + // Corsair Katar Pro Wireless (USB dongle) + (0x1b1c, 0x1b94, KeyboardType::NonAlphabetic, true), + // Corsair Katar Pro Wireless (Bluetooth) + (0x1bae, 0x1b1c, KeyboardType::NonAlphabetic, true), + // Kensington Pro Fit Full-size + (0x1bcf, 0x08a0, KeyboardType::NonAlphabetic, true), + // Huion HS64 + (0x256c, 0x006d, KeyboardType::NonAlphabetic, true), + // XP-Pen Star G640 + (0x28bd, 0x0914, KeyboardType::NonAlphabetic, true), + // XP-Pen Artist 12 Pro + (0x28bd, 0x091f, KeyboardType::NonAlphabetic, true), + // XP-Pen Deco mini7W + (0x28bd, 0x0928, KeyboardType::NonAlphabetic, true), +]; diff --git a/libs/input/rust/keyboard_classifier.rs b/libs/input/rust/keyboard_classifier.rs index 1063fac664..8721ef7687 100644 --- a/libs/input/rust/keyboard_classifier.rs +++ b/libs/input/rust/keyboard_classifier.rs @@ -35,6 +35,7 @@ //! TODO(b/263559234): Data store implementation to store information about past classification use crate::input::{DeviceId, InputDevice, KeyboardType}; +use crate::keyboard_classification_config::CLASSIFIED_DEVICES; use crate::{DeviceClass, ModifierState}; use std::collections::HashMap; @@ -126,6 +127,14 @@ impl KeyboardClassifier { (KeyboardType::NonAlphabetic, true) }; } + + // Check in known device list for classification + for data in CLASSIFIED_DEVICES.iter() { + if device.identifier.vendor == data.0 && device.identifier.product == data.1 { + return (data.2, data.3); + } + } + // Any composite device with multiple device classes should be categorized as non-alphabetic // keyboard initially if device.classes.contains(DeviceClass::Touch) @@ -169,6 +178,7 @@ impl KeyboardClassifier { #[cfg(test)] mod tests { use crate::input::{DeviceId, InputDevice, KeyboardType}; + use crate::keyboard_classification_config::CLASSIFIED_DEVICES; use crate::keyboard_classifier::KeyboardClassifier; use crate::{DeviceClass, ModifierState, RustInputDeviceIdentifier}; @@ -326,6 +336,17 @@ mod tests { assert!(!classifier.is_finalized(DEVICE_ID)); } + #[test] + fn classify_known_devices() { + let mut classifier = KeyboardClassifier::new(); + for device in CLASSIFIED_DEVICES.iter() { + classifier + .notify_keyboard_changed(create_device_with_vendor_product_ids(device.0, device.1)); + assert_eq!(classifier.get_keyboard_type(DEVICE_ID), device.2); + assert_eq!(classifier.is_finalized(DEVICE_ID), device.3); + } + } + fn create_device(classes: DeviceClass) -> InputDevice { InputDevice { device_id: DEVICE_ID, @@ -342,4 +363,21 @@ mod tests { classes, } } + + fn create_device_with_vendor_product_ids(vendor: u16, product: u16) -> InputDevice { + InputDevice { + device_id: DEVICE_ID, + identifier: RustInputDeviceIdentifier { + name: "test_device".to_string(), + location: "location".to_string(), + unique_id: "unique_id".to_string(), + bus: 123, + vendor, + product, + version: 567, + descriptor: "descriptor".to_string(), + }, + classes: DeviceClass::Keyboard | DeviceClass::AlphabeticKey | DeviceClass::External, + } + } } diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs index 5010475334..af8f889cb5 100644 --- a/libs/input/rust/lib.rs +++ b/libs/input/rust/lib.rs @@ -18,6 +18,7 @@ mod input; mod input_verifier; +mod keyboard_classification_config; mod keyboard_classifier; pub use input::{ -- GitLab From 7b1bc2c59dc6f3c69d1c8861e26edb0e498f6042 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 14 Jun 2024 13:22:01 +0000 Subject: [PATCH 009/530] Use PLOG() for failed system calls, so we see errno. Bug: http://b/346961364 Change-Id: Id9e204160ab9fa55a42495a3e96dfca354abc276 --- libs/adbd_auth/adbd_auth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp index ebc74fb3d8..78896ed553 100644 --- a/libs/adbd_auth/adbd_auth.cpp +++ b/libs/adbd_auth/adbd_auth.cpp @@ -365,7 +365,7 @@ public: if (event.events & EPOLLIN) { int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf))); if (rc == -1) { - LOG(FATAL) << "adbd_auth: failed to read from framework fd"; + PLOG(FATAL) << "adbd_auth: failed to read from framework fd"; } else if (rc == 0) { LOG(INFO) << "adbd_auth: hit EOF on framework fd"; std::lock_guard lock(mutex_); -- GitLab From c04759244f3f6d419502f2f1bf3ff6ddbd597151 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 13 Jun 2024 15:27:17 -0700 Subject: [PATCH 010/530] SF/CE: Fix startup race in HwcAsyncWorker If a HwcAsyncWorker is created, and shortly after `HwcAsyncWorker::send` is called to queue up a task to run, there is a chance that the thread that is created to run the tasks hasn't gotten to waiting on the internal condition variable before the `notify_one` call is made to wake up any waiting threads. The result is that the HwcAsyncWorker thread doesn't get notified, and goes to sleep. Meanwhile the SurfaceFlinger main thread waits forever for the task to complete. Eventually the System Services start timing out as SurfaceFlinger isn't processing requests. The fix is simple -- switch to the two argument (predicate) form of `std::condition_variable::wait()`, with the predicate checking for a task (and the done flag). The predicate is checked before actually waiting on the condition variable. Additionally a unit test is added to verify this and a few other edge conditions. The test fails (times out) without the implementation fix when run with `atest`, and passes/completes with it. Note that this is normally an uncommon error particularly on most devices as HwcAsyncWorkers are only created when new outputs (virtual or physical displays) are created, and there is usually a big gap between when the HwcAsyncWorker is created and when it is actually used. It ended up being more of a problem on Chromebooks as we create outputs for every new app window, which happens much more frequently, and with a much shorter delay between creation and use. Flag: EXEMPT bugfix Bug: 333824019 Test: atest libcompositionengine_test Test: Smoke test of running DOTA Underlords on a Trogdor Chromebook (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:e0b2747abd28f4595a6f18f3f9fbe8aa15ae7000) Merged-In: If3ad46a1297a0448dbdb505957081329f4cd2aca Change-Id: If3ad46a1297a0448dbdb505957081329f4cd2aca --- .../CompositionEngine/Android.bp | 1 + .../CompositionEngine/src/HwcAsyncWorker.cpp | 3 +- .../tests/HwcAsyncWorkerTest.cpp | 71 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 7fa58dfef8..610b10f32d 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -148,6 +148,7 @@ cc_test { "tests/CompositionEngineTest.cpp", "tests/DisplayColorProfileTest.cpp", "tests/DisplayTest.cpp", + "tests/HwcAsyncWorkerTest.cpp", "tests/HwcBufferCacheTest.cpp", "tests/MockHWC2.cpp", "tests/MockHWComposer.cpp", diff --git a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp index 6086f0be3f..91385b4ff3 100644 --- a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp +++ b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace android::compositionengine::impl { @@ -60,7 +61,7 @@ void HwcAsyncWorker::run() { std::unique_lock lock(mMutex); android::base::ScopedLockAssertion assumeLock(mMutex); while (!mDone) { - mCv.wait(lock); + mCv.wait(lock, [this]() FTL_FAKE_GUARD(mMutex) { return mTaskRequested || mDone; }); if (mTaskRequested && mTask.valid()) { mTask(); mTaskRequested = false; diff --git a/services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp new file mode 100644 index 0000000000..dd04df6d6b --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 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. + */ + +#include + +#include +#include + +namespace android::compositionengine { +namespace { + +using namespace std::chrono_literals; + +// For the edge case tests below, how much real time should be spent trying to reproduce edge cases +// problems in a loop. +// +// Larger values mean problems are more likely to be detected, at the cost of making the unit test +// run slower. +// +// As we expect the tests to be run continuously, even a short loop will eventually catch +// problems, though not necessarily from changes in the same build that introduce them. +constexpr auto kWallTimeForEdgeCaseTests = 5ms; + +TEST(HwcAsyncWorker, continuousTasksEdgeCase) { + // Ensures that a single worker that is given multiple tasks in short succession will run them. + + impl::HwcAsyncWorker worker; + const auto endTime = std::chrono::steady_clock::now() + kWallTimeForEdgeCaseTests; + while (std::chrono::steady_clock::now() < endTime) { + auto f1 = worker.send([] { return false; }); + EXPECT_FALSE(f1.get()); + auto f2 = worker.send([] { return true; }); + EXPECT_TRUE(f2.get()); + } +} + +TEST(HwcAsyncWorker, constructAndDestroyEdgeCase) { + // Ensures that newly created HwcAsyncWorkers can be immediately destroyed. + + const auto endTime = std::chrono::steady_clock::now() + kWallTimeForEdgeCaseTests; + while (std::chrono::steady_clock::now() < endTime) { + impl::HwcAsyncWorker worker; + } +} + +TEST(HwcAsyncWorker, newlyCreatedRunsTasksEdgeCase) { + // Ensures that newly created HwcAsyncWorkers will run a task if given one immediately. + + const auto endTime = std::chrono::steady_clock::now() + kWallTimeForEdgeCaseTests; + while (std::chrono::steady_clock::now() < endTime) { + impl::HwcAsyncWorker worker; + auto f = worker.send([] { return true; }); + f.get(); + } +} + +} // namespace +} // namespace android::compositionengine -- GitLab From 2a2f7145decd6f57f214bd4a5d56595830de4875 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Mon, 17 Jun 2024 14:09:22 +0900 Subject: [PATCH 011/530] libbinder_ndk: V APIs are guarded with V Using __ANDROID_API_FUTURE__ for V symbols was a workaround because __builtin_available(android __ANDROID_API_V__,*) didn't work when V is still a preview. It's fixed now in clang and we can use __ANDROID_API_V__ when gaurding V symbols. The guard evaluates to true if the platform SDK version is V or higher or it's a preview. Bug: 322384429 Test: presubmit Change-Id: If35077330d0b002091cf191c2de31dc93e09178d --- .../ndk/include_cpp/android/persistable_bundle_aidl.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h index d570eab976..cf7dc1a510 100644 --- a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h +++ b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h @@ -26,13 +26,10 @@ #if defined(__ANDROID_VENDOR__) #include #else // __ANDROID_VENDOR__ -#if defined(API_LEVEL_AT_LEAST) -// Redefine API_LEVEL_AT_LEAST here to replace the version to __ANDROID_API_FUTURE__ as a workaround -#undef API_LEVEL_AT_LEAST -#endif -// TODO(b/322384429) switch this __ANDROID_API_FUTURE__ to sdk_api_level when V is finalized +#if !defined(API_LEVEL_AT_LEAST) #define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \ - (__builtin_available(android __ANDROID_API_FUTURE__, *)) + (__builtin_available(android sdk_api_level, *)) +#endif #endif // __ANDROID_VENDOR__ namespace aidl::android::os { -- GitLab From 4f61be28eaf5297057b2c4f9b65b47018655bbb1 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Mon, 17 Jun 2024 13:29:11 +0900 Subject: [PATCH 012/530] libui: use __ANDROID_API_V__ __builtin_available() now works with preview SDK version (V in this case). No need to use __ANDROID_API_FUTURE__ which was a workaround. __builtin_available(andorid 35, *) evaluates to true if - the platform SDK version is 35 or higher - or, the platform is a preview (not REL) Bug: 322384429 Test: CF loads mapper from vapex Change-Id: I264cf444a0fb163e445471920930b6be3930dd03 --- libs/ui/Gralloc5.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp index 303043a35a..c4157abe5d 100644 --- a/libs/ui/Gralloc5.cpp +++ b/libs/ui/Gralloc5.cpp @@ -90,8 +90,7 @@ static void *loadIMapperLibrary() { } void* so = nullptr; - // TODO(b/322384429) switch this to __ANDROID_API_V__ when V is finalized - if API_LEVEL_AT_LEAST(__ANDROID_API_FUTURE__, 202404) { + if API_LEVEL_AT_LEAST (__ANDROID_API_V__, 202404) { so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(), RTLD_LOCAL | RTLD_NOW); } else { -- GitLab From 5ade9f1ab181f61da17a562e9c6d7bc2306ee58c Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Sun, 19 May 2024 13:02:07 +0000 Subject: [PATCH 013/530] Add perfetto traces to ServiceManager Bug: 342101947 Test: run external/perfetto/tools/record_android_trace -c config.pbtx Add the following to the config.pbtx: data_sources { config { name: "track_event" track_event_config { disabled_categories:"*" enabled_categories: "servicemanager" } } } Change-Id: Ida65d96241899f9f50a48f4b2f12ec1f7a5dc978 --- cmds/servicemanager/Android.bp | 9 ++++- cmds/servicemanager/ServiceManager.cpp | 53 +++++++++++++++++++++++++- cmds/servicemanager/ServiceManager.h | 9 +++++ cmds/servicemanager/main.cpp | 24 ++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp index 3897197bd5..e5d7b7456b 100644 --- a/cmds/servicemanager/Android.bp +++ b/cmds/servicemanager/Android.bp @@ -29,6 +29,7 @@ cc_defaults { "liblog", "libutils", "libselinux", + "libperfetto_c", ], target: { @@ -48,7 +49,13 @@ cc_defaults { enabled: false, }, vendor: { - exclude_shared_libs: ["libvintf"], + exclude_shared_libs: [ + "libvintf", + "libperfetto_c", + ], + }, + recovery: { + exclude_shared_libs: ["libperfetto_c"], }, }, } diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 95a05cdcde..1333599bf2 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,11 @@ #include #include +#if !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) +#include "perfetto/public/te_category_macros.h" +#include "perfetto/public/te_macros.h" +#endif // !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + #ifndef VENDORSERVICEMANAGER #include #ifdef __ANDROID_RECOVERY__ @@ -42,6 +48,17 @@ using ::android::internal::Stability; namespace android { +#if defined(VENDORSERVICEMANAGER) || defined(__ANDROID_RECOVERY__) +#define SM_PERFETTO_TRACE_FUNC(...) +#else + +PERFETTO_TE_CATEGORIES_DEFINE(PERFETTO_SM_CATEGORIES); + +#define SM_PERFETTO_TRACE_FUNC(...) \ + PERFETTO_TE_SCOPED(servicemanager, PERFETTO_TE_SLICE_BEGIN(__func__) __VA_OPT__(, ) __VA_ARGS__) + +#endif // !(defined(VENDORSERVICEMANAGER) || defined(__ANDROID_RECOVERY__)) + bool is_multiuser_uid_isolated(uid_t uid) { uid_t appid = multiuser_get_app_id(uid); return appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; @@ -348,18 +365,24 @@ ServiceManager::~ServiceManager() { } Status ServiceManager::getService(const std::string& name, sp* outBinder) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + *outBinder = tryGetService(name, true); // returns ok regardless of result for legacy reasons return Status::ok(); } Status ServiceManager::checkService(const std::string& name, sp* outBinder) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + *outBinder = tryGetService(name, false); // returns ok regardless of result for legacy reasons return Status::ok(); } sp ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); sp out; @@ -398,6 +421,8 @@ sp ServiceManager::tryGetService(const std::string& name, bool startIfN } bool isValidServiceName(const std::string& name) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + if (name.size() == 0) return false; if (name.size() > 127) return false; @@ -413,6 +438,8 @@ bool isValidServiceName(const std::string& name) { } Status ServiceManager::addService(const std::string& name, const sp& binder, bool allowIsolated, int32_t dumpPriority) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); if (multiuser_get_app_id(ctx.uid) >= AID_APP) { @@ -505,6 +532,8 @@ Status ServiceManager::addService(const std::string& name, const sp& bi } Status ServiceManager::listServices(int32_t dumpPriority, std::vector* outList) { + SM_PERFETTO_TRACE_FUNC(); + if (!mAccess->canList(mAccess->getCallingContext())) { return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied."); } @@ -532,6 +561,8 @@ Status ServiceManager::listServices(int32_t dumpPriority, std::vector& callback) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { @@ -578,6 +609,8 @@ Status ServiceManager::registerForNotifications( } Status ServiceManager::unregisterForNotifications( const std::string& name, const sp& callback) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { @@ -601,6 +634,8 @@ Status ServiceManager::unregisterForNotifications( } Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { @@ -616,6 +651,8 @@ Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) { } binder::Status ServiceManager::getDeclaredInstances(const std::string& interface, std::vector* outReturn) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("interface", interface.c_str())); + auto ctx = mAccess->getCallingContext(); std::vector allInstances; @@ -640,6 +677,8 @@ binder::Status ServiceManager::getDeclaredInstances(const std::string& interface Status ServiceManager::updatableViaApex(const std::string& name, std::optional* outReturn) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { @@ -656,6 +695,8 @@ Status ServiceManager::updatableViaApex(const std::string& name, Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& apexName, std::vector* outReturn) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("apexName", apexName.c_str())); + auto ctx = mAccess->getCallingContext(); std::vector apexUpdatableNames; @@ -674,12 +715,13 @@ Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& ape if (outReturn->size() == 0 && apexUpdatableNames.size() != 0) { return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied."); } - return Status::ok(); } Status ServiceManager::getConnectionInfo(const std::string& name, std::optional* outReturn) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + auto ctx = mAccess->getCallingContext(); if (!mAccess->canFind(ctx, name)) { @@ -697,6 +739,8 @@ Status ServiceManager::getConnectionInfo(const std::string& name, void ServiceManager::removeRegistrationCallback(const wp& who, ServiceCallbackMap::iterator* it, bool* found) { + SM_PERFETTO_TRACE_FUNC(); + std::vector>& listeners = (*it)->second; for (auto lit = listeners.begin(); lit != listeners.end();) { @@ -716,6 +760,8 @@ void ServiceManager::removeRegistrationCallback(const wp& who, } void ServiceManager::binderDied(const wp& who) { + SM_PERFETTO_TRACE_FUNC(); + for (auto it = mNameToService.begin(); it != mNameToService.end();) { if (who == it->second.binder) { // TODO: currently, this entry contains the state also @@ -758,6 +804,8 @@ void ServiceManager::tryStartService(const Access::CallingContext& ctx, const st Status ServiceManager::registerClientCallback(const std::string& name, const sp& service, const sp& cb) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + if (cb == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Callback null."); } @@ -918,6 +966,8 @@ void ServiceManager::sendClientCallbackNotifications(const std::string& serviceN } Status ServiceManager::tryUnregisterService(const std::string& name, const sp& binder) { + SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str())); + if (binder == nullptr) { return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null service."); } @@ -983,6 +1033,7 @@ Status ServiceManager::tryUnregisterService(const std::string& name, const sp* outReturn) { + SM_PERFETTO_TRACE_FUNC(); if (!mAccess->canList(mAccess->getCallingContext())) { return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied."); } diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h index 3b925a48cb..1536014f0a 100644 --- a/cmds/servicemanager/ServiceManager.h +++ b/cmds/servicemanager/ServiceManager.h @@ -20,6 +20,10 @@ #include #include +#if !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) +#include "perfetto/public/te_category_macros.h" +#endif // !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + #include "Access.h" namespace android { @@ -29,6 +33,11 @@ using os::IClientCallback; using os::IServiceCallback; using os::ServiceDebugInfo; +#if !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) +#define PERFETTO_SM_CATEGORIES(C) C(servicemanager, "servicemanager", "Service Manager category") +PERFETTO_TE_CATEGORIES_DECLARE(PERFETTO_SM_CATEGORIES); +#endif // !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient { public: ServiceManager(std::unique_ptr&& access); diff --git a/cmds/servicemanager/main.cpp b/cmds/servicemanager/main.cpp index 07908ba5b3..c126e91373 100644 --- a/cmds/servicemanager/main.cpp +++ b/cmds/servicemanager/main.cpp @@ -26,6 +26,26 @@ #include "Access.h" #include "ServiceManager.h" +#if !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + +#include +#include +#include +#include + +namespace android { + +static void register_perfetto_te_categories() { + struct PerfettoProducerInitArgs perfetto_args = PERFETTO_PRODUCER_INIT_ARGS_INIT(); + perfetto_args.backends = PERFETTO_BACKEND_SYSTEM; + PerfettoProducerInit(perfetto_args); + PerfettoTeInit(); + PERFETTO_TE_REGISTER_CATEGORIES(PERFETTO_SM_CATEGORIES); +} +} // namespace android + +#endif // !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + using ::android::Access; using ::android::IPCThreadState; using ::android::Looper; @@ -132,6 +152,10 @@ int main(int argc, char** argv) { const char* driver = argc == 2 ? argv[1] : "/dev/binder"; +#if !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + android::register_perfetto_te_categories(); +#endif // !defined(VENDORSERVICEMANAGER) && !defined(__ANDROID_RECOVERY__) + LOG(INFO) << "Starting sm instance on " << driver; sp ps = ProcessState::initWithDriver(driver); -- GitLab From 6c9ce49b66b937abb84e52008e49a4035aea0150 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Wed, 12 Jun 2024 11:41:14 +1200 Subject: [PATCH 014/530] Tidy up dispatch to GPDIFP2 in swapchain Bug: b/346650750 Test: n/a Change-Id: I22eba5cffcd86b671b69097ba087b795ad1732b2 --- vulkan/libvulkan/swapchain.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 9e67725b58..00e987fb2e 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -1473,23 +1473,14 @@ static VkResult getProducerUsage(const VkDevice& device, image_format_properties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; image_format_properties.pNext = &ahb_usage; - if (instance_dispatch.GetPhysicalDeviceImageFormatProperties2) { - VkResult result = instance_dispatch.GetPhysicalDeviceImageFormatProperties2( - pdev, &image_format_info, &image_format_properties); - if (result != VK_SUCCESS) { - ALOGE("VkGetPhysicalDeviceImageFormatProperties2 for AHB usage failed: %d", result); - return VK_ERROR_SURFACE_LOST_KHR; - } - } - else { - VkResult result = instance_dispatch.GetPhysicalDeviceImageFormatProperties2KHR( - pdev, &image_format_info, - &image_format_properties); - if (result != VK_SUCCESS) { - ALOGE("VkGetPhysicalDeviceImageFormatProperties2KHR for AHB usage failed: %d", - result); - return VK_ERROR_SURFACE_LOST_KHR; - } + VkResult result = GetPhysicalDeviceImageFormatProperties2( + pdev, &image_format_info, &image_format_properties); + if (result != VK_SUCCESS) { + ALOGE( + "VkGetPhysicalDeviceImageFormatProperties2 for AHB usage " + "failed: %d", + result); + return VK_ERROR_SURFACE_LOST_KHR; } // Determine if USAGE_FRONT_BUFFER is needed. -- GitLab From 3ff44c7e852f5614514a15dcec78ba7857e5d010 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 17 Jun 2024 11:03:30 -0400 Subject: [PATCH 015/530] SF: Fix pacesetter promotion for folded mirroring The pacesetter display is demoted/promoted in response to a hotplug. On foldables, the promoted display was hard-coded to the inner display, so a hotplug while folded would incorrectly use that powered-off display as the pacesetter, causing system-wide jank until the next fold/unfold. Fixes: 347248313 Flag: EXEMPT bugfix Test: Connect and disconnect external display while folded. Test: Fold and unfold while external display is connected. Test: Pacesetter is still correct on folded/unfolded boot. Change-Id: Id5cb29c3cbaa8ed455a15d8be3a32e79a470cce5 --- .../surfaceflinger/Scheduler/Scheduler.cpp | 17 ++++++++----- services/surfaceflinger/Scheduler/Scheduler.h | 16 +++++++++--- services/surfaceflinger/SurfaceFlinger.cpp | 8 +++--- .../tests/unittests/SchedulerTest.cpp | 25 ++++++++++++------- .../tests/unittests/TestableScheduler.h | 16 ++++++------ .../tests/unittests/TestableSurfaceFlinger.h | 4 +-- 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 60681a2bc8..26e11e5693 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -123,19 +123,22 @@ void Scheduler::setPacesetterDisplay(std::optional pacesetter promotePacesetterDisplay(pacesetterIdOpt); } -void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { +void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, + PhysicalDisplayId activeDisplayId) { auto schedulePtr = std::make_shared(selectorPtr->getActiveMode().modePtr, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }); - registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr)); + registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr), + activeDisplayId); } void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, - VsyncSchedulePtr schedulePtr) { + VsyncSchedulePtr schedulePtr, + PhysicalDisplayId activeDisplayId) { demotePacesetterDisplay(); auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) { @@ -145,7 +148,7 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, std::move(schedulePtr), mFeatures) .second; - return std::make_pair(promotePacesetterDisplayLocked(), isNew); + return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId), isNew); }(); applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); @@ -158,7 +161,9 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, dispatchHotplug(displayId, Hotplug::Connected); } -void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { +void Scheduler::unregisterDisplay(PhysicalDisplayId displayId, PhysicalDisplayId activeDisplayId) { + LOG_ALWAYS_FATAL_IF(displayId == activeDisplayId, "Cannot unregister the active display!"); + dispatchHotplug(displayId, Hotplug::Disconnected); demotePacesetterDisplay(); @@ -173,7 +178,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { // headless virtual display.) LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!"); - pacesetterVsyncSchedule = promotePacesetterDisplayLocked(); + pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId); } applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index ccaa05f970..1a4aa79818 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -101,9 +101,16 @@ public: using ConstVsyncSchedulePtr = std::shared_ptr; using VsyncSchedulePtr = std::shared_ptr; - void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr) REQUIRES(kMainThreadContext) + // After registration/unregistration, `activeDisplayId` is promoted to pacesetter. Note that the + // active display is never unregistered, since hotplug disconnect never happens for activatable + // displays, i.e. a foldable's internal displays or otherwise the (internal or external) primary + // display. + // TODO: b/255635821 - Remove active display parameters. + void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr, + PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); - void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); + void unregisterDisplay(PhysicalDisplayId, PhysicalDisplayId activeDisplayId) + REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void run(); @@ -390,8 +397,9 @@ private: // the caller on the main thread to avoid deadlock, since the timer thread locks it before exit. void demotePacesetterDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock); - void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr) - REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); + void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr, + PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) + EXCLUDES(mDisplayLock); struct Policy; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 596ec12d9e..5fa6d26dfe 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3855,7 +3855,8 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, ftl::FakeGuard guard(kMainThreadContext); // For hotplug reconnect, renew the registration since display modes have been reloaded. - mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); + mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), + mActiveDisplayId); } if (display->isVirtual()) { @@ -3894,7 +3895,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp& displayToken) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { - mScheduler->unregisterDisplay(display->getPhysicalId()); + mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId); } } @@ -4506,7 +4507,8 @@ void SurfaceFlinger::initScheduler(const sp& display) { getFactory(), activeRefreshRate, *mTimeStats); // The pacesetter must be registered before EventThread creation below. - mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); + mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), + mActiveDisplayId); if (FlagManager::getInstance().vrr_config()) { mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps, /*applyImmediately*/ true); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 4fb06907d0..fc54a8b74f 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -343,12 +343,15 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) { } TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { + constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared(kDisplay1Modes, - kDisplay1Mode60->getId())); + kDisplay1Mode60->getId()), + kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared(kDisplay2Modes, - kDisplay2Mode60->getId())); + kDisplay2Mode60->getId()), + kActiveDisplayId); mScheduler->setDisplayPowerMode(kDisplayId1, hal::PowerMode::ON); mScheduler->setDisplayPowerMode(kDisplayId2, hal::PowerMode::ON); @@ -411,10 +414,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { { // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz. - mScheduler - ->registerDisplay(kDisplayId3, - std::make_shared(kDisplay3Modes, - kDisplay3Mode60->getId())); + mScheduler->registerDisplay(kDisplayId3, + std::make_shared(kDisplay3Modes, + kDisplay3Mode60->getId()), + kActiveDisplayId); mScheduler->setDisplayPowerMode(kDisplayId3, hal::PowerMode::ON); const GlobalSignals globalSignals = {.touch = true}; @@ -457,12 +460,15 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { } TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) { + constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared(kDisplay1Modes, - kDisplay1Mode60->getId())); + kDisplay1Mode60->getId()), + kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared(kDisplay2Modes, - kDisplay2Mode60->getId())); + kDisplay2Mode60->getId()), + kActiveDisplayId); using VsyncIds = std::vector>; @@ -585,7 +591,8 @@ TEST_F(SchedulerTest, nextFrameIntervalTest) { mFlinger.getTimeStats(), mSchedulerCallback}; - scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker); + scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt, + vrrTracker); vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate); scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate, /*applyImmediately*/ false); vrrTracker->addVsyncTimestamp(0); diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 198a5def8c..f0638094c7 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -53,7 +53,7 @@ public: factory, selectorPtr->getActiveMode().fps, timeStats) { const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId(); registerDisplay(displayId, std::move(selectorPtr), std::move(controller), - std::move(tracker)); + std::move(tracker), displayId); ON_CALL(*this, postMessage).WillByDefault([](sp&& handler) { // Execute task to prevent broken promise exception on destruction. @@ -85,14 +85,16 @@ public: void registerDisplay( PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, + std::optional activeDisplayIdOpt = {}, std::shared_ptr vsyncTracker = std::make_shared()) { registerDisplay(displayId, std::move(selectorPtr), - std::make_unique(), vsyncTracker); + std::make_unique(), vsyncTracker, + activeDisplayIdOpt.value_or(displayId)); } void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::unique_ptr controller, - std::shared_ptr tracker) { + std::shared_ptr tracker, PhysicalDisplayId activeDisplayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::registerDisplayInternal(displayId, std::move(selectorPtr), std::shared_ptr( @@ -101,16 +103,12 @@ public: mock::VSyncDispatch>(), std::move(controller), mockRequestHardwareVsync - .AsStdFunction()))); + .AsStdFunction())), + activeDisplayId); } testing::MockFunction mockRequestHardwareVsync; - void unregisterDisplay(PhysicalDisplayId displayId) { - ftl::FakeGuard guard(kMainThreadContext); - Scheduler::unregisterDisplay(displayId); - } - void setDisplayPowerMode(PhysicalDisplayId displayId, hal::PowerMode powerMode) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::setDisplayPowerMode(displayId, powerMode); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 007383b3d9..4197cbd271 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -1118,8 +1118,8 @@ public: if (mFlinger.scheduler() && mSchedulerRegistration) { mFlinger.scheduler()->registerDisplay(*physicalId, mCreationArgs.refreshRateSelector, - std::move(controller), - std::move(tracker)); + std::move(controller), std::move(tracker), + mFlinger.mutableActiveDisplayId()); } } -- GitLab From 548f4497df58f43f85f5e0c4e9e0a41bd6b8bae7 Mon Sep 17 00:00:00 2001 From: ramindani Date: Thu, 13 Jun 2024 10:29:04 -0700 Subject: [PATCH 016/530] SF: Update vsync timeline validUntil to be exact vsync time. Introduce Timeline::isWithin function that puts sourced vsync time source into Unique, Shared and Outside categories. BUG: 343603085 Test: atest VSyncPredictorTest Flag: com.android.graphics.surfaceflinger.flags.vrr_bugfix_24q4 Change-Id: I99094e64c8403455158a6e794bd4d2ce32429f93 --- .../Scheduler/VSyncPredictor.cpp | 35 ++++++++++++++----- .../surfaceflinger/Scheduler/VSyncPredictor.h | 18 ++++++++++ .../tests/unittests/VSyncPredictorTest.cpp | 30 ++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index dd3c4b074c..0644acaee2 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -360,7 +360,11 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) { purgeTimelines(now); for (auto& timeline : mTimelines) { - if (timeline.validUntil() && timeline.validUntil()->ns() > vsync) { + const bool isVsyncValid = FlagManager::getInstance().vrr_bugfix_24q4() + ? timeline.isWithin(TimePoint::fromNs(vsync)) == + VsyncTimeline::VsyncOnTimeline::Unique + : timeline.validUntil() && timeline.validUntil()->ns() > vsync; + if (isVsyncValid) { return timeline.isVSyncInPhase(model, vsync, frameRate); } } @@ -395,8 +399,14 @@ void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) { mLastCommittedVsync = TimePoint::fromNs(0); } else { - mTimelines.back().freeze( - TimePoint::fromNs(mLastCommittedVsync.ns() + mIdealPeriod.ns() / 2)); + if (FlagManager::getInstance().vrr_bugfix_24q4()) { + // We need to freeze the timeline at the committed vsync so that we don't + // overshoot the deadline. + mTimelines.back().freeze(mLastCommittedVsync); + } else { + mTimelines.back().freeze( + TimePoint::fromNs(mLastCommittedVsync.ns() + mIdealPeriod.ns() / 2)); + } } mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, renderRate); purgeTimelines(TimePoint::fromNs(mClock->now())); @@ -611,7 +621,10 @@ void VSyncPredictor::purgeTimelines(android::TimePoint now) { while (mTimelines.size() > 1) { const auto validUntilOpt = mTimelines.front().validUntil(); - if (validUntilOpt && *validUntilOpt < now) { + const bool isTimelineOutDated = FlagManager::getInstance().vrr_bugfix_24q4() + ? mTimelines.front().isWithin(now) == VsyncTimeline::VsyncOnTimeline::Outside + : validUntilOpt && *validUntilOpt < now; + if (isTimelineOutDated) { mTimelines.pop_front(); } else { break; @@ -660,9 +673,12 @@ std::optional VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTime vsyncTime += missedVsync.fixup.ns(); ATRACE_FORMAT_INSTANT("lastFrameMissed"); } else if (mightBackpressure && lastVsyncOpt) { - // lastVsyncOpt is based on the old timeline before we shifted it. we should correct it - // first before trying to use it. - lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt); + if (!FlagManager::getInstance().vrr_bugfix_24q4()) { + // lastVsyncOpt does not need to be corrected with the new rate, and + // it should be used as is to avoid skipping a frame when changing rates are + // aligned at vsync time. + lastVsyncOpt = snapToVsyncAlignedWithRenderRate(model, *lastVsyncOpt); + } const auto vsyncDiff = vsyncTime - *lastVsyncOpt; if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) { // avoid a duplicate vsync @@ -681,7 +697,10 @@ std::optional VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTime } ATRACE_FORMAT_INSTANT("vsync in %.2fms", float(vsyncTime - TimePoint::now().ns()) / 1e6f); - if (mValidUntil && vsyncTime > mValidUntil->ns()) { + const bool isVsyncInvalid = FlagManager::getInstance().vrr_bugfix_24q4() + ? isWithin(TimePoint::fromNs(vsyncTime)) == VsyncOnTimeline::Outside + : mValidUntil && vsyncTime > mValidUntil->ns(); + if (isVsyncInvalid) { ATRACE_FORMAT_INSTANT("no longer valid for vsync in %.2f", static_cast(vsyncTime - TimePoint::now().ns()) / 1e6f); return std::nullopt; diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h index 8ce61d86c6..66a7d71435 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.h +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h @@ -106,6 +106,24 @@ private: void shiftVsyncSequence(Duration phase); void setRenderRate(std::optional renderRateOpt) { mRenderRateOpt = renderRateOpt; } + enum class VsyncOnTimeline { + Unique, // Within timeline, not shared with next timeline. + Shared, // Within timeline, shared with next timeline. + Outside, // Outside of the timeline. + }; + VsyncOnTimeline isWithin(TimePoint vsync) { + const auto threshold = mIdealPeriod.ns() / 2; + if (!mValidUntil || vsync.ns() < mValidUntil->ns() - threshold) { + // if mValidUntil is absent then timeline is not frozen and + // vsync should be unique to that timeline. + return VsyncOnTimeline::Unique; + } + if (vsync.ns() > mValidUntil->ns() + threshold) { + return VsyncOnTimeline::Outside; + } + return VsyncOnTimeline::Shared; + } + private: nsecs_t snapToVsyncAlignedWithRenderRate(Model model, nsecs_t vsync); VsyncSequence getVsyncSequenceLocked(Model, nsecs_t vsync); diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index 5109ea6793..f36a8a6fd7 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -673,6 +673,36 @@ TEST_F(VSyncPredictorTest, setRenderRateIsIgnoredIfNotDivisor) { EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 5100), Eq(mNow + 6 * mPeriod)); } +TEST_F(VSyncPredictorTest, setRenderRateWhenRenderRateGoesDown) { + SET_FLAG_FOR_TEST(flags::vrr_config, true); + SET_FLAG_FOR_TEST(flags::vrr_bugfix_24q4, true); + + const int32_t kGroup = 0; + const auto kResolution = ui::Size(1920, 1080); + const auto vsyncRate = Fps::fromPeriodNsecs(500); + const auto minFrameRate = Fps::fromPeriodNsecs(1000); + hal::VrrConfig vrrConfig; + vrrConfig.minFrameIntervalNs = minFrameRate.getPeriodNsecs(); + const ftl::NonNull kMode = + ftl::as_non_null(createDisplayModeBuilder(DisplayModeId(0), vsyncRate, kGroup, + kResolution, DEFAULT_DISPLAY_ID) + .setVrrConfig(std::move(vrrConfig)) + .build()); + + VSyncPredictor vrrTracker{std::make_unique(mClock), kMode, kHistorySize, + kMinimumSamplesForPrediction, kOutlierTolerancePercent}; + + Fps frameRate = Fps::fromPeriodNsecs(1000); + vrrTracker.setRenderRate(frameRate, /*applyImmediately*/ false); + vrrTracker.addVsyncTimestamp(0); + EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700)); + EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000, 1000)); + + frameRate = Fps::fromPeriodNsecs(3000); + vrrTracker.setRenderRate(frameRate, /*applyImmediately*/ false); + EXPECT_TRUE(vrrTracker.isVSyncInPhase(2000, frameRate)); +} + TEST_F(VSyncPredictorTest, setRenderRateHighIsAppliedImmediately) { SET_FLAG_FOR_TEST(flags::vrr_config, true); -- GitLab From 29814f26deb640f5d42678fc31aa4b50c76c3190 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Tue, 18 Jun 2024 14:53:10 +0000 Subject: [PATCH 017/530] Define MotionEventFlag as an AIDL enum This allows us to loop through all enum values defined in AIDL in native code in a unit test to verify that they are all redefined in various languages. This will help catch missed flag redefinitions in presubmit rather than as runtime crashes. Bug: 346613247 Test: libinput_rust_test Flag: NONE no behavior change Change-Id: I48c5119e28a91315c3bbc561616eb48750bfb804 --- include/input/Input.h | 23 ++-- libs/input/Android.bp | 1 + libs/input/android/os/IInputConstants.aidl | 120 +--------------- libs/input/android/os/MotionEventFlag.aidl | 152 +++++++++++++++++++++ libs/input/rust/input.rs | 42 ++++-- 5 files changed, 203 insertions(+), 135 deletions(-) create mode 100644 libs/input/android/os/MotionEventFlag.aidl diff --git a/include/input/Input.h b/include/input/Input.h index ec08cdd163..456977bb34 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -25,6 +25,7 @@ #include #ifdef __linux__ #include +#include #endif #include #include @@ -69,15 +70,17 @@ enum { * actual intent. */ AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED = - android::os::IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED, + static_cast(android::os::MotionEventFlag::WINDOW_IS_PARTIALLY_OBSCURED), + AMOTION_EVENT_FLAG_HOVER_EXIT_PENDING = - android::os::IInputConstants::MOTION_EVENT_FLAG_HOVER_EXIT_PENDING, + static_cast(android::os::MotionEventFlag::HOVER_EXIT_PENDING), + /** * This flag indicates that the event has been generated by a gesture generator. It * provides a hint to the GestureDetector to not apply any touch slop. */ AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE = - android::os::IInputConstants::MOTION_EVENT_FLAG_IS_GENERATED_GESTURE, + static_cast(android::os::MotionEventFlag::IS_GENERATED_GESTURE), /** * This flag indicates that the event will not cause a focus change if it is directed to an @@ -86,27 +89,27 @@ enum { * into focus. */ AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE = - android::os::IInputConstants::MOTION_EVENT_FLAG_NO_FOCUS_CHANGE, + static_cast(android::os::MotionEventFlag::NO_FOCUS_CHANGE), /** * This event was generated or modified by accessibility service. */ AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = - android::os::IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, + static_cast(android::os::MotionEventFlag::IS_ACCESSIBILITY_EVENT), AMOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS = - android::os::IInputConstants::MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS, + static_cast(android::os::MotionEventFlag::TARGET_ACCESSIBILITY_FOCUS), /* Motion event is inconsistent with previously sent motion events. */ - AMOTION_EVENT_FLAG_TAINTED = android::os::IInputConstants::INPUT_EVENT_FLAG_TAINTED, + AMOTION_EVENT_FLAG_TAINTED = static_cast(android::os::MotionEventFlag::TAINTED), /** Private flag, not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION = - android::os::IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION, + static_cast(android::os::MotionEventFlag::PRIVATE_FLAG_SUPPORTS_ORIENTATION), /** Private flag, not used in Java. */ - AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = android::os::IInputConstants:: - MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION, + AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = static_cast( + android::os::MotionEventFlag::PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION), /** Mask for all private flags that are not used in Java. */ AMOTION_EVENT_PRIVATE_FLAG_MASK = AMOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION | diff --git a/libs/input/Android.bp b/libs/input/Android.bp index d782f42071..c2a7ebb614 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -30,6 +30,7 @@ filegroup { "android/os/InputEventInjectionResult.aidl", "android/os/InputEventInjectionSync.aidl", "android/os/InputConfig.aidl", + "android/os/MotionEventFlag.aidl", "android/os/PointerIconType.aidl", ], } diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl index a77dfa59fe..e23fc94c5e 100644 --- a/libs/input/android/os/IInputConstants.aidl +++ b/libs/input/android/os/IInputConstants.aidl @@ -49,130 +49,24 @@ interface IInputConstants const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000; /** - * This flag indicates that the window that received this motion event is partly - * or wholly obscured by another visible window above it and the event directly passed through - * the obscured area. - * - * A security sensitive application can check this flag to identify situations in which - * a malicious application may have covered up part of its content for the purpose - * of misleading the user or hijacking touches. An appropriate response might be - * to drop the suspect touches or to take additional precautions to confirm the user's - * actual intent. - */ - const int MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED = 0x1; - - /** - * This flag indicates that the window that received this motion event is partly - * or wholly obscured by another visible window above it and the event did not directly pass - * through the obscured area. - * - * A security sensitive application can check this flag to identify situations in which - * a malicious application may have covered up part of its content for the purpose - * of misleading the user or hijacking touches. An appropriate response might be - * to drop the suspect touches or to take additional precautions to confirm the user's - * actual intent. - * - * Unlike FLAG_WINDOW_IS_OBSCURED, this is only true if the window that received this event is - * obstructed in areas other than the touched location. - */ - const int MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 0x2; - - /** - * This private flag is only set on {@link #ACTION_HOVER_MOVE} events and indicates that - * this event will be immediately followed by a {@link #ACTION_HOVER_EXIT}. It is used to - * prevent generating redundant {@link #ACTION_HOVER_ENTER} events. - * @hide - */ - const int MOTION_EVENT_FLAG_HOVER_EXIT_PENDING = 0x4; - - /** - * This flag indicates that the event has been generated by a gesture generator. It - * provides a hint to the GestureDetector to not apply any touch slop. - * - * @hide - */ - const int MOTION_EVENT_FLAG_IS_GENERATED_GESTURE = 0x8; - - /** - * This flag is only set for events with {@link #ACTION_POINTER_UP} and {@link #ACTION_CANCEL}. - * It indicates that the pointer going up was an unintentional user touch. When FLAG_CANCELED - * is set, the typical actions that occur in response for a pointer going up (such as click - * handlers, end of drawing) should be aborted. This flag is typically set when the user was - * accidentally touching the screen, such as by gripping the device, or placing the palm on the - * screen. - * - * @see #ACTION_POINTER_UP - * @see #ACTION_CANCEL + * Common input event flag used for both motion and key events for a gesture or pointer being + * canceled. */ const int INPUT_EVENT_FLAG_CANCELED = 0x20; /** - * This flag indicates that the event will not cause a focus change if it is directed to an - * unfocused window, even if it an {@link #ACTION_DOWN}. This is typically used with pointer - * gestures to allow the user to direct gestures to an unfocused window without bringing the - * window into focus. - * @hide - */ - const int MOTION_EVENT_FLAG_NO_FOCUS_CHANGE = 0x40; - - /** - * This flag indicates that the event has a valid value for AXIS_ORIENTATION. - * - * This is a private flag that is not used in Java. - * @hide - */ - const int MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION = 0x80; - - /** - * This flag indicates that the pointers' AXIS_ORIENTATION can be used to precisely determine - * the direction in which the tool is pointing. The value of the orientation axis will be in - * the range [-pi, pi], which represents a full circle. This is usually supported by devices - * like styluses. - * - * Conversely, AXIS_ORIENTATION cannot be used to tell which direction the tool is pointing - * when this flag is not set. In this case, the axis value will have a range of [-pi/2, pi/2], - * which represents half a circle. This is usually the case for devices like touchscreens and - * touchpads, for which it is difficult to tell which direction along the major axis of the - * touch ellipse the finger is pointing. - * - * This is a private flag that is not used in Java. - * @hide - */ - const int MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = 0x100; - - /** - * The input event was generated or modified by accessibility service. - * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either - * set of flags, including in input/Input.h and in android/input.h. + * Common input event flag used for both motion and key events, indicating that the event + * was generated or modified by accessibility service. */ const int INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT = 0x800; /** - * Private flag that indicates when the system has detected that this motion event - * may be inconsistent with respect to the sequence of previously delivered motion events, - * such as when a pointer move event is sent but the pointer is not down. - * - * @hide - * @see #isTainted - * @see #setTainted + * Common input event flag used for both motion and key events, indicating that the system has + * detected this event may be inconsistent with the current event sequence or gesture, such as + * when a pointer move event is sent but the pointer is not down. */ const int INPUT_EVENT_FLAG_TAINTED = 0x80000000; - /** - * Private flag indicating that this event was synthesized by the system and should be delivered - * to the accessibility focused view first. When being dispatched such an event is not handled - * by predecessors of the accessibility focused view and after the event reaches that view the - * flag is cleared and normal event dispatch is performed. This ensures that the platform can - * click on any view that has accessibility focus which is semantically equivalent to asking the - * view to perform a click accessibility action but more generic as views not implementing click - * action correctly can still be activated. - * - * @hide - * @see #isTargetAccessibilityFocus() - * @see #setTargetAccessibilityFocus(boolean) - */ - const int MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS = 0x40000000; - /* The default pointer acceleration value. */ const int DEFAULT_POINTER_ACCELERATION = 3; diff --git a/libs/input/android/os/MotionEventFlag.aidl b/libs/input/android/os/MotionEventFlag.aidl new file mode 100644 index 0000000000..2093b0636a --- /dev/null +++ b/libs/input/android/os/MotionEventFlag.aidl @@ -0,0 +1,152 @@ +/** + * Copyright 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. + */ + +package android.os; + +import android.os.IInputConstants; + +/** + * Flag definitions for MotionEvents. + * @hide + */ +@Backing(type="int") +enum MotionEventFlag { + + /** + * This flag indicates that the window that received this motion event is partly + * or wholly obscured by another visible window above it and the event directly passed through + * the obscured area. + * + * A security sensitive application can check this flag to identify situations in which + * a malicious application may have covered up part of its content for the purpose + * of misleading the user or hijacking touches. An appropriate response might be + * to drop the suspect touches or to take additional precautions to confirm the user's + * actual intent. + */ + WINDOW_IS_OBSCURED = 0x1, + + /** + * This flag indicates that the window that received this motion event is partly + * or wholly obscured by another visible window above it and the event did not directly pass + * through the obscured area. + * + * A security sensitive application can check this flag to identify situations in which + * a malicious application may have covered up part of its content for the purpose + * of misleading the user or hijacking touches. An appropriate response might be + * to drop the suspect touches or to take additional precautions to confirm the user's + * actual intent. + * + * Unlike FLAG_WINDOW_IS_OBSCURED, this is only true if the window that received this event is + * obstructed in areas other than the touched location. + */ + WINDOW_IS_PARTIALLY_OBSCURED = 0x2, + + /** + * This private flag is only set on {@link #ACTION_HOVER_MOVE} events and indicates that + * this event will be immediately followed by a {@link #ACTION_HOVER_EXIT}. It is used to + * prevent generating redundant {@link #ACTION_HOVER_ENTER} events. + * @hide + */ + HOVER_EXIT_PENDING = 0x4, + + /** + * This flag indicates that the event has been generated by a gesture generator. It + * provides a hint to the GestureDetector to not apply any touch slop. + * + * @hide + */ + IS_GENERATED_GESTURE = 0x8, + + /** + * This flag is only set for events with {@link #ACTION_POINTER_UP} and {@link #ACTION_CANCEL}. + * It indicates that the pointer going up was an unintentional user touch. When FLAG_CANCELED + * is set, the typical actions that occur in response for a pointer going up (such as click + * handlers, end of drawing) should be aborted. This flag is typically set when the user was + * accidentally touching the screen, such as by gripping the device, or placing the palm on the + * screen. + * + * @see #ACTION_POINTER_UP + * @see #ACTION_CANCEL + */ + CANCELED = IInputConstants.INPUT_EVENT_FLAG_CANCELED, + + /** + * This flag indicates that the event will not cause a focus change if it is directed to an + * unfocused window, even if it an {@link #ACTION_DOWN}. This is typically used with pointer + * gestures to allow the user to direct gestures to an unfocused window without bringing the + * window into focus. + * @hide + */ + NO_FOCUS_CHANGE = 0x40, + + /** + * This flag indicates that the event has a valid value for AXIS_ORIENTATION. + * + * This is a private flag that is not used in Java. + * @hide + */ + PRIVATE_FLAG_SUPPORTS_ORIENTATION = 0x80, + + /** + * This flag indicates that the pointers' AXIS_ORIENTATION can be used to precisely determine + * the direction in which the tool is pointing. The value of the orientation axis will be in + * the range [-pi, pi], which represents a full circle. This is usually supported by devices + * like styluses. + * + * Conversely, AXIS_ORIENTATION cannot be used to tell which direction the tool is pointing + * when this flag is not set. In this case, the axis value will have a range of [-pi/2, pi/2], + * which represents half a circle. This is usually the case for devices like touchscreens and + * touchpads, for which it is difficult to tell which direction along the major axis of the + * touch ellipse the finger is pointing. + * + * This is a private flag that is not used in Java. + * @hide + */ + PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = 0x100, + + /** + * The input event was generated or modified by accessibility service. + * Shared by both KeyEvent and MotionEvent flags, so this value should not overlap with either + * set of flags, including in input/Input.h and in android/input.h. + */ + IS_ACCESSIBILITY_EVENT = IInputConstants.INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT, + + /** + * Private flag that indicates when the system has detected that this motion event + * may be inconsistent with respect to the sequence of previously delivered motion events, + * such as when a pointer move event is sent but the pointer is not down. + * + * @hide + * @see #isTainted + * @see #setTainted + */ + TAINTED = IInputConstants.INPUT_EVENT_FLAG_TAINTED, + + /** + * Private flag indicating that this event was synthesized by the system and should be delivered + * to the accessibility focused view first. When being dispatched such an event is not handled + * by predecessors of the accessibility focused view and after the event reaches that view the + * flag is cleared and normal event dispatch is performed. This ensures that the platform can + * click on any view that has accessibility focus which is semantically equivalent to asking the + * view to perform a click accessibility action but more generic as views not implementing click + * action correctly can still be activated. + * + * @hide + * @see #isTargetAccessibilityFocus() + * @see #setTargetAccessibilityFocus(boolean) + */ + TARGET_ACCESSIBILITY_FOCUS = 0x40000000, +} diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs index 564d94dbb4..c46b7bb85c 100644 --- a/libs/input/rust/input.rs +++ b/libs/input/rust/input.rs @@ -19,6 +19,7 @@ use crate::ffi::RustInputDeviceIdentifier; use bitflags::bitflags; use inputconstants::aidl::android::os::IInputConstants; +use inputconstants::aidl::android::os::MotionEventFlag::MotionEventFlag; use std::fmt; /// The InputDevice ID. @@ -193,31 +194,34 @@ impl MotionAction { bitflags! { /// MotionEvent flags. + /// The source of truth for the flag definitions are the MotionEventFlag AIDL enum. + /// The flag values are redefined here as a bitflags API. #[derive(Debug)] pub struct MotionFlags: u32 { /// FLAG_WINDOW_IS_OBSCURED - const WINDOW_IS_OBSCURED = IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_OBSCURED as u32; + const WINDOW_IS_OBSCURED = MotionEventFlag::WINDOW_IS_OBSCURED.0 as u32; /// FLAG_WINDOW_IS_PARTIALLY_OBSCURED - const WINDOW_IS_PARTIALLY_OBSCURED = IInputConstants::MOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED as u32; + const WINDOW_IS_PARTIALLY_OBSCURED = MotionEventFlag::WINDOW_IS_PARTIALLY_OBSCURED.0 as u32; /// FLAG_HOVER_EXIT_PENDING - const HOVER_EXIT_PENDING = IInputConstants::MOTION_EVENT_FLAG_HOVER_EXIT_PENDING as u32; + const HOVER_EXIT_PENDING = MotionEventFlag::HOVER_EXIT_PENDING.0 as u32; /// FLAG_IS_GENERATED_GESTURE - const IS_GENERATED_GESTURE = IInputConstants::MOTION_EVENT_FLAG_IS_GENERATED_GESTURE as u32; + const IS_GENERATED_GESTURE = MotionEventFlag::IS_GENERATED_GESTURE.0 as u32; /// FLAG_CANCELED - const CANCELED = IInputConstants::INPUT_EVENT_FLAG_CANCELED as u32; + const CANCELED = MotionEventFlag::CANCELED.0 as u32; /// FLAG_NO_FOCUS_CHANGE - const NO_FOCUS_CHANGE = IInputConstants::MOTION_EVENT_FLAG_NO_FOCUS_CHANGE as u32; + const NO_FOCUS_CHANGE = MotionEventFlag::NO_FOCUS_CHANGE.0 as u32; /// PRIVATE_FLAG_SUPPORTS_ORIENTATION - const PRIVATE_SUPPORTS_ORIENTATION = IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_ORIENTATION as u32; + const PRIVATE_FLAG_SUPPORTS_ORIENTATION = + MotionEventFlag::PRIVATE_FLAG_SUPPORTS_ORIENTATION.0 as u32; /// PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION - const PRIVATE_SUPPORTS_DIRECTIONAL_ORIENTATION = - IInputConstants::MOTION_EVENT_PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION as u32; + const PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION = + MotionEventFlag::PRIVATE_FLAG_SUPPORTS_DIRECTIONAL_ORIENTATION.0 as u32; /// FLAG_IS_ACCESSIBILITY_EVENT - const IS_ACCESSIBILITY_EVENT = IInputConstants::INPUT_EVENT_FLAG_IS_ACCESSIBILITY_EVENT as u32; + const IS_ACCESSIBILITY_EVENT = MotionEventFlag::IS_ACCESSIBILITY_EVENT.0 as u32; /// FLAG_TAINTED - const TAINTED = IInputConstants::INPUT_EVENT_FLAG_TAINTED as u32; + const TAINTED = MotionEventFlag::TAINTED.0 as u32; /// FLAG_TARGET_ACCESSIBILITY_FOCUS - const TARGET_ACCESSIBILITY_FOCUS = IInputConstants::MOTION_EVENT_FLAG_TARGET_ACCESSIBILITY_FOCUS as u32; + const TARGET_ACCESSIBILITY_FOCUS = MotionEventFlag::TARGET_ACCESSIBILITY_FOCUS.0 as u32; } } @@ -333,10 +337,24 @@ pub enum KeyboardType { #[cfg(test)] mod tests { use crate::input::SourceClass; + use crate::MotionFlags; use crate::Source; + use inputconstants::aidl::android::os::MotionEventFlag::MotionEventFlag; + #[test] fn convert_source_class_pointer() { let source = Source::from_bits(input_bindgen::AINPUT_SOURCE_CLASS_POINTER).unwrap(); assert!(source.is_from_class(SourceClass::Pointer)); } + + /// Ensure all MotionEventFlag constants are re-defined in rust. + #[test] + fn all_motion_event_flags_defined() { + for flag in MotionEventFlag::enum_values() { + assert!( + MotionFlags::from_bits(flag.0 as u32).is_some(), + "MotionEventFlag value {flag:?} is not redefined as a rust MotionFlags" + ); + } + } } -- GitLab From 39be47b981c93b4366c7fdd341c064e7f47bfb94 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 17 Jun 2024 11:03:30 -0400 Subject: [PATCH 018/530] SF: Fix pacesetter promotion for folded mirroring The pacesetter display is demoted/promoted in response to a hotplug. On foldables, the promoted display was hard-coded to the inner display, so a hotplug while folded would incorrectly use that powered-off display as the pacesetter, causing system-wide jank until the next fold/unfold. Bug: 347248313 Flag: EXEMPT bugfix Test: Connect and disconnect external display while folded. Test: Fold and unfold while external display is connected. Test: Pacesetter is still correct on folded/unfolded boot. (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:3ff44c7e852f5614514a15dcec78ba7857e5d010) Merged-In: Id5cb29c3cbaa8ed455a15d8be3a32e79a470cce5 Change-Id: Id0a32686c1271163e88a8c586482ee37d42a5bdf --- .../surfaceflinger/Scheduler/Scheduler.cpp | 17 ++++++++----- services/surfaceflinger/Scheduler/Scheduler.h | 16 +++++++++--- services/surfaceflinger/SurfaceFlinger.cpp | 8 +++--- .../tests/unittests/SchedulerTest.cpp | 25 ++++++++++++------- .../tests/unittests/TestableScheduler.h | 16 ++++++------ .../tests/unittests/TestableSurfaceFlinger.h | 4 +-- 6 files changed, 53 insertions(+), 33 deletions(-) diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 819b952074..4cd4c6d638 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -123,19 +123,22 @@ void Scheduler::setPacesetterDisplay(std::optional pacesetter promotePacesetterDisplay(pacesetterIdOpt); } -void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) { +void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, + PhysicalDisplayId activeDisplayId) { auto schedulePtr = std::make_shared(selectorPtr->getActiveMode().modePtr, mFeatures, [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); }); - registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr)); + registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr), + activeDisplayId); } void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, - VsyncSchedulePtr schedulePtr) { + VsyncSchedulePtr schedulePtr, + PhysicalDisplayId activeDisplayId) { demotePacesetterDisplay(); auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) { @@ -145,7 +148,7 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, std::move(schedulePtr), mFeatures) .second; - return std::make_pair(promotePacesetterDisplayLocked(), isNew); + return std::make_pair(promotePacesetterDisplayLocked(activeDisplayId), isNew); }(); applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); @@ -158,7 +161,9 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId, dispatchHotplug(displayId, Hotplug::Connected); } -void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { +void Scheduler::unregisterDisplay(PhysicalDisplayId displayId, PhysicalDisplayId activeDisplayId) { + LOG_ALWAYS_FATAL_IF(displayId == activeDisplayId, "Cannot unregister the active display!"); + dispatchHotplug(displayId, Hotplug::Disconnected); demotePacesetterDisplay(); @@ -173,7 +178,7 @@ void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) { // headless virtual display.) LOG_ALWAYS_FATAL_IF(mDisplays.empty(), "Cannot unregister all displays!"); - pacesetterVsyncSchedule = promotePacesetterDisplayLocked(); + pacesetterVsyncSchedule = promotePacesetterDisplayLocked(activeDisplayId); } applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule)); } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index fc935cd3c4..7a3007945b 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -101,9 +101,16 @@ public: using ConstVsyncSchedulePtr = std::shared_ptr; using VsyncSchedulePtr = std::shared_ptr; - void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr) REQUIRES(kMainThreadContext) + // After registration/unregistration, `activeDisplayId` is promoted to pacesetter. Note that the + // active display is never unregistered, since hotplug disconnect never happens for activatable + // displays, i.e. a foldable's internal displays or otherwise the (internal or external) primary + // display. + // TODO: b/255635821 - Remove active display parameters. + void registerDisplay(PhysicalDisplayId, RefreshRateSelectorPtr, + PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); - void unregisterDisplay(PhysicalDisplayId) REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); + void unregisterDisplay(PhysicalDisplayId, PhysicalDisplayId activeDisplayId) + REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); void run(); @@ -388,8 +395,9 @@ private: // the caller on the main thread to avoid deadlock, since the timer thread locks it before exit. void demotePacesetterDisplay() REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock, mPolicyLock); - void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr) - REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock); + void registerDisplayInternal(PhysicalDisplayId, RefreshRateSelectorPtr, VsyncSchedulePtr, + PhysicalDisplayId activeDisplayId) REQUIRES(kMainThreadContext) + EXCLUDES(mDisplayLock); struct Policy; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cf5f55d7bd..b75be37119 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3717,7 +3717,8 @@ void SurfaceFlinger::processDisplayAdded(const wp& displayToken, ftl::FakeGuard guard(kMainThreadContext); // For hotplug reconnect, renew the registration since display modes have been reloaded. - mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); + mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), + mActiveDisplayId); } if (display->isVirtual()) { @@ -3756,7 +3757,7 @@ void SurfaceFlinger::processDisplayRemoved(const wp& displayToken) { if (display->isVirtual()) { releaseVirtualDisplay(display->getVirtualId()); } else { - mScheduler->unregisterDisplay(display->getPhysicalId()); + mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId); } } @@ -4376,7 +4377,8 @@ void SurfaceFlinger::initScheduler(const sp& display) { getFactory(), activeRefreshRate, *mTimeStats); // The pacesetter must be registered before EventThread creation below. - mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); + mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector(), + mActiveDisplayId); if (FlagManager::getInstance().vrr_config()) { mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps); } diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 03c12d6f73..be3fce669f 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -337,12 +337,15 @@ TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) { } TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { + constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared(kDisplay1Modes, - kDisplay1Mode60->getId())); + kDisplay1Mode60->getId()), + kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared(kDisplay2Modes, - kDisplay2Mode60->getId())); + kDisplay2Mode60->getId()), + kActiveDisplayId); using DisplayModeChoice = TestableScheduler::DisplayModeChoice; TestableScheduler::DisplayModeChoiceMap expectedChoices; @@ -402,10 +405,10 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { { // The kDisplayId3 does not support 120Hz, The pacesetter display rate is chosen to be 120 // Hz. In this case only the display kDisplayId3 choose 60Hz as it does not support 120Hz. - mScheduler - ->registerDisplay(kDisplayId3, - std::make_shared(kDisplay3Modes, - kDisplay3Mode60->getId())); + mScheduler->registerDisplay(kDisplayId3, + std::make_shared(kDisplay3Modes, + kDisplay3Mode60->getId()), + kActiveDisplayId); const GlobalSignals globalSignals = {.touch = true}; mScheduler->replaceTouchTimer(10); @@ -447,12 +450,15 @@ TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) { } TEST_F(SchedulerTest, onFrameSignalMultipleDisplays) { + constexpr PhysicalDisplayId kActiveDisplayId = kDisplayId1; mScheduler->registerDisplay(kDisplayId1, std::make_shared(kDisplay1Modes, - kDisplay1Mode60->getId())); + kDisplay1Mode60->getId()), + kActiveDisplayId); mScheduler->registerDisplay(kDisplayId2, std::make_shared(kDisplay2Modes, - kDisplay2Mode60->getId())); + kDisplay2Mode60->getId()), + kActiveDisplayId); using VsyncIds = std::vector>; @@ -574,7 +580,8 @@ TEST_F(SchedulerTest, nextFrameIntervalTest) { mFlinger.getTimeStats(), mSchedulerCallback}; - scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, vrrTracker); + scheduler.registerDisplay(kMode->getPhysicalDisplayId(), vrrSelectorPtr, std::nullopt, + vrrTracker); vrrSelectorPtr->setActiveMode(kMode->getId(), frameRate); scheduler.setRenderRate(kMode->getPhysicalDisplayId(), frameRate); vrrTracker->addVsyncTimestamp(0); diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 1472ebf009..e436273c9e 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -53,7 +53,7 @@ public: factory, selectorPtr->getActiveMode().fps, timeStats) { const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId(); registerDisplay(displayId, std::move(selectorPtr), std::move(controller), - std::move(tracker)); + std::move(tracker), displayId); ON_CALL(*this, postMessage).WillByDefault([](sp&& handler) { // Execute task to prevent broken promise exception on destruction. @@ -85,14 +85,16 @@ public: void registerDisplay( PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, + std::optional activeDisplayIdOpt = {}, std::shared_ptr vsyncTracker = std::make_shared()) { registerDisplay(displayId, std::move(selectorPtr), - std::make_unique(), vsyncTracker); + std::make_unique(), vsyncTracker, + activeDisplayIdOpt.value_or(displayId)); } void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::unique_ptr controller, - std::shared_ptr tracker) { + std::shared_ptr tracker, PhysicalDisplayId activeDisplayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::registerDisplayInternal(displayId, std::move(selectorPtr), std::shared_ptr( @@ -101,16 +103,12 @@ public: mock::VSyncDispatch>(), std::move(controller), mockRequestHardwareVsync - .AsStdFunction()))); + .AsStdFunction())), + activeDisplayId); } testing::MockFunction mockRequestHardwareVsync; - void unregisterDisplay(PhysicalDisplayId displayId) { - ftl::FakeGuard guard(kMainThreadContext); - Scheduler::unregisterDisplay(displayId); - } - std::optional pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS { return mPacesetterDisplayId; } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index bce7729d80..99223f0aa3 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -1079,8 +1079,8 @@ public: if (mFlinger.scheduler() && mRegisterDisplay) { mFlinger.scheduler()->registerDisplay(physicalId, display->holdRefreshRateSelector(), - std::move(controller), - std::move(tracker)); + std::move(controller), std::move(tracker), + mFlinger.mutableActiveDisplayId()); } display->setActiveMode(activeModeId, fps, fps); -- GitLab From 99490acc7a6139a80fecc2029aeb0eb388c1917c Mon Sep 17 00:00:00 2001 From: Frederick Mayle Date: Tue, 18 Jun 2024 12:21:18 -0700 Subject: [PATCH 019/530] binder: fix printf warning introduced in https://r.android.com/3107366 Bug: 333946800 Test: m Change-Id: I432c5364b5a444d5b5c4c56b6d7a80f0303609a6 --- libs/binder/IPCThreadState.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 8b65d630ec..c3bbdbadaa 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -621,9 +621,8 @@ void IPCThreadState::blockUntilThreadAvailable() if (cur < max) { return true; } - ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%" PRId64 - " mMaxThreads=%" PRId64 "\n", - cur, max); + ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%zu mMaxThreads=%zu\n", cur, + max); return false; }); mProcess->mOnThreadAvailableWaiting--; -- GitLab From 56a0471ed60e551925dfc8d76cb061ffa8d10122 Mon Sep 17 00:00:00 2001 From: Parth Sane Date: Mon, 22 Apr 2024 14:21:07 +0000 Subject: [PATCH 020/530] Add a BackendUnifiedServiceManager wrapper This can be directly used by java and rust ffi Test: atest aidl_integration_test Bug: 333854840 Flag: EXEMPT refactor Change-Id: I12c3730a89422bf08ab723a82888431f291bd7b3 --- libs/binder/Android.bp | 3 +- libs/binder/BackendUnifiedServiceManager.cpp | 119 ++++++++++++++++++ libs/binder/BackendUnifiedServiceManager.h | 68 ++++++++++ libs/binder/IServiceManager.cpp | 70 ++++------- libs/binder/IServiceManagerFFI.cpp | 27 ++++ .../include/binder/IServiceManagerFFI.h | 25 ++++ 6 files changed, 265 insertions(+), 47 deletions(-) create mode 100644 libs/binder/BackendUnifiedServiceManager.cpp create mode 100644 libs/binder/BackendUnifiedServiceManager.h create mode 100644 libs/binder/IServiceManagerFFI.cpp create mode 100644 libs/binder/include/binder/IServiceManagerFFI.h diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index f31f8d3993..1abde5cb92 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -442,8 +442,10 @@ cc_defaults { name: "libbinder_kernel_defaults", srcs: [ "BufferedTextOutput.cpp", + "BackendUnifiedServiceManager.cpp", "IPCThreadState.cpp", "IServiceManager.cpp", + "IServiceManagerFFI.cpp", "ProcessState.cpp", "Static.cpp", ":libbinder_aidl", @@ -519,7 +521,6 @@ cc_library { "ParcelableHolder.cpp", "PersistableBundle.cpp", ], - target: { android: { // NOT static to keep the wire protocol unfrozen diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp new file mode 100644 index 0000000000..496c5ef788 --- /dev/null +++ b/libs/binder/BackendUnifiedServiceManager.cpp @@ -0,0 +1,119 @@ +/* + * 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. + */ +#include "BackendUnifiedServiceManager.h" + +namespace android { + +using AidlServiceManager = android::os::IServiceManager; + +BackendUnifiedServiceManager::BackendUnifiedServiceManager(const sp& impl) + : mTheRealServiceManager(impl) {} + +sp BackendUnifiedServiceManager::getImpl() { + return mTheRealServiceManager; +} +binder::Status BackendUnifiedServiceManager::getService(const ::std::string& name, + sp* _aidl_return) { + return mTheRealServiceManager->getService(name, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name, + sp* _aidl_return) { + return mTheRealServiceManager->checkService(name, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::addService(const ::std::string& name, + const sp& service, + bool allowIsolated, int32_t dumpPriority) { + return mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority); +} +binder::Status BackendUnifiedServiceManager::listServices( + int32_t dumpPriority, ::std::vector<::std::string>* _aidl_return) { + return mTheRealServiceManager->listServices(dumpPriority, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::registerForNotifications( + const ::std::string& name, const sp& callback) { + return mTheRealServiceManager->registerForNotifications(name, callback); +} +binder::Status BackendUnifiedServiceManager::unregisterForNotifications( + const ::std::string& name, const sp& callback) { + return mTheRealServiceManager->unregisterForNotifications(name, callback); +} +binder::Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name, + bool* _aidl_return) { + return mTheRealServiceManager->isDeclared(name, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::getDeclaredInstances( + const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) { + return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::updatableViaApex( + const ::std::string& name, ::std::optional<::std::string>* _aidl_return) { + return mTheRealServiceManager->updatableViaApex(name, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::getUpdatableNames( + const ::std::string& apexName, ::std::vector<::std::string>* _aidl_return) { + return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::getConnectionInfo( + const ::std::string& name, ::std::optional* _aidl_return) { + return mTheRealServiceManager->getConnectionInfo(name, _aidl_return); +} +binder::Status BackendUnifiedServiceManager::registerClientCallback( + const ::std::string& name, const sp& service, + const sp& callback) { + return mTheRealServiceManager->registerClientCallback(name, service, callback); +} +binder::Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name, + const sp& service) { + return mTheRealServiceManager->tryUnregisterService(name, service); +} +binder::Status BackendUnifiedServiceManager::getServiceDebugInfo( + ::std::vector* _aidl_return) { + return mTheRealServiceManager->getServiceDebugInfo(_aidl_return); +} + +[[clang::no_destroy]] static std::once_flag gUSmOnce; +[[clang::no_destroy]] static sp gUnifiedServiceManager; + +sp getBackendUnifiedServiceManager() { + std::call_once(gUSmOnce, []() { +#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__) + /* wait for service manager */ { + using std::literals::chrono_literals::operator""s; + using android::base::WaitForProperty; + while (!WaitForProperty("servicemanager.ready", "true", 1s)) { + ALOGE("Waited for servicemanager.ready for a second, waiting another..."); + } + } +#endif + + sp sm = nullptr; + while (sm == nullptr) { + sm = interface_cast( + ProcessState::self()->getContextObject(nullptr)); + if (sm == nullptr) { + ALOGE("Waiting 1s on context object on %s.", + ProcessState::self()->getDriverName().c_str()); + sleep(1); + } + } + + gUnifiedServiceManager = sp::make(sm); + }); + + return gUnifiedServiceManager; +} + +} // namespace android \ No newline at end of file diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h new file mode 100644 index 0000000000..a67d5bae2d --- /dev/null +++ b/libs/binder/BackendUnifiedServiceManager.h @@ -0,0 +1,68 @@ +/* + * 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. + */ +#pragma once + +#include +#include +#include +#include + +namespace android { + +class BackendUnifiedServiceManager : public android::os::BnServiceManager { +public: + explicit BackendUnifiedServiceManager(const sp& impl); + + sp getImpl(); + binder::Status getService(const ::std::string& name, sp* _aidl_return) override; + binder::Status checkService(const ::std::string& name, sp* _aidl_return) override; + binder::Status addService(const ::std::string& name, const sp& service, + bool allowIsolated, int32_t dumpPriority) override; + binder::Status listServices(int32_t dumpPriority, + ::std::vector<::std::string>* _aidl_return) override; + binder::Status registerForNotifications(const ::std::string& name, + const sp& callback) override; + binder::Status unregisterForNotifications(const ::std::string& name, + const sp& callback) override; + binder::Status isDeclared(const ::std::string& name, bool* _aidl_return) override; + binder::Status getDeclaredInstances(const ::std::string& iface, + ::std::vector<::std::string>* _aidl_return) override; + binder::Status updatableViaApex(const ::std::string& name, + ::std::optional<::std::string>* _aidl_return) override; + binder::Status getUpdatableNames(const ::std::string& apexName, + ::std::vector<::std::string>* _aidl_return) override; + binder::Status getConnectionInfo(const ::std::string& name, + ::std::optional* _aidl_return) override; + binder::Status registerClientCallback(const ::std::string& name, const sp& service, + const sp& callback) override; + binder::Status tryUnregisterService(const ::std::string& name, + const sp& service) override; + binder::Status getServiceDebugInfo(::std::vector* _aidl_return) override; + + // for legacy ABI + const String16& getInterfaceDescriptor() const override { + return mTheRealServiceManager->getInterfaceDescriptor(); + } + + IBinder* onAsBinder() override { return IInterface::asBinder(mTheRealServiceManager).get(); } + +private: + sp mTheRealServiceManager; +}; + +sp getBackendUnifiedServiceManager(); + +} // namespace android \ No newline at end of file diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index fbcf823045..5844c85d21 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "ServiceManagerCppClient" +#include #include #include @@ -111,14 +112,12 @@ public: std::vector getServiceDebugInfo() override; // for legacy ABI const String16& getInterfaceDescriptor() const override { - return mTheRealServiceManager->getInterfaceDescriptor(); - } - IBinder* onAsBinder() override { - return IInterface::asBinder(mTheRealServiceManager).get(); + return mUnifiedServiceManager->getInterfaceDescriptor(); } + IBinder* onAsBinder() override { return IInterface::asBinder(mUnifiedServiceManager).get(); } protected: - sp mTheRealServiceManager; + sp mUnifiedServiceManager; // AidlRegistrationCallback -> services that its been registered for // notifications. using LocalRegistrationAndWaiter = @@ -136,9 +135,9 @@ protected: // will still have the 5s delay that is expected by a large amount of Android code. // // When implementing ServiceManagerShim, use realGetService instead of - // mTheRealServiceManager->getService so that it can be overridden in ServiceManagerHostShim. + // mUnifiedServiceManager->getService so that it can be overridden in ServiceManagerHostShim. virtual Status realGetService(const std::string& name, sp* _aidl_return) { - return mTheRealServiceManager->getService(name, _aidl_return); + return mUnifiedServiceManager->getService(name, _aidl_return); } }; @@ -148,26 +147,7 @@ protected: sp defaultServiceManager() { std::call_once(gSmOnce, []() { -#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__) - /* wait for service manager */ { - using std::literals::chrono_literals::operator""s; - using android::base::WaitForProperty; - while (!WaitForProperty("servicemanager.ready", "true", 1s)) { - ALOGE("Waited for servicemanager.ready for a second, waiting another..."); - } - } -#endif - - sp sm = nullptr; - while (sm == nullptr) { - sm = interface_cast(ProcessState::self()->getContextObject(nullptr)); - if (sm == nullptr) { - ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str()); - sleep(1); - } - } - - gDefaultServiceManager = sp::make(sm); + gDefaultServiceManager = sp::make(getBackendUnifiedServiceManager()); }); return gDefaultServiceManager; @@ -290,9 +270,9 @@ void* openDeclaredPassthroughHal(const String16& interface, const String16& inst // ---------------------------------------------------------------------- -ServiceManagerShim::ServiceManagerShim(const sp& impl) - : mTheRealServiceManager(impl) -{} +ServiceManagerShim::ServiceManagerShim(const sp& impl) { + mUnifiedServiceManager = sp::make(impl); +} // This implementation could be simplified and made more efficient by delegating // to waitForService. However, this changes the threading structure in some @@ -345,7 +325,7 @@ sp ServiceManagerShim::getService(const String16& name) const sp ServiceManagerShim::checkService(const String16& name) const { sp ret; - if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { + if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { return nullptr; } return ret; @@ -354,15 +334,15 @@ sp ServiceManagerShim::checkService(const String16& name) const status_t ServiceManagerShim::addService(const String16& name, const sp& service, bool allowIsolated, int dumpsysPriority) { - Status status = mTheRealServiceManager->addService( - String8(name).c_str(), service, allowIsolated, dumpsysPriority); + Status status = mUnifiedServiceManager->addService(String8(name).c_str(), service, + allowIsolated, dumpsysPriority); return status.exceptionCode(); } Vector ServiceManagerShim::listServices(int dumpsysPriority) { std::vector ret; - if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) { + if (!mUnifiedServiceManager->listServices(dumpsysPriority, &ret).isOk()) { return {}; } @@ -420,15 +400,13 @@ sp ServiceManagerShim::waitForService(const String16& name16) if (out != nullptr) return out; sp waiter = sp::make(); - if (Status status = mTheRealServiceManager->registerForNotifications(name, waiter); + if (Status status = mUnifiedServiceManager->registerForNotifications(name, waiter); !status.isOk()) { ALOGW("Failed to registerForNotifications in waitForService for %s: %s", name.c_str(), status.toString8().c_str()); return nullptr; } - Defer unregister ([&] { - mTheRealServiceManager->unregisterForNotifications(name, waiter); - }); + Defer unregister([&] { mUnifiedServiceManager->unregisterForNotifications(name, waiter); }); while(true) { { @@ -469,7 +447,7 @@ sp ServiceManagerShim::waitForService(const String16& name16) bool ServiceManagerShim::isDeclared(const String16& name) { bool declared; - if (Status status = mTheRealServiceManager->isDeclared(String8(name).c_str(), &declared); + if (Status status = mUnifiedServiceManager->isDeclared(String8(name).c_str(), &declared); !status.isOk()) { ALOGW("Failed to get isDeclared for %s: %s", String8(name).c_str(), status.toString8().c_str()); @@ -481,7 +459,7 @@ bool ServiceManagerShim::isDeclared(const String16& name) { Vector ServiceManagerShim::getDeclaredInstances(const String16& interface) { std::vector out; if (Status status = - mTheRealServiceManager->getDeclaredInstances(String8(interface).c_str(), &out); + mUnifiedServiceManager->getDeclaredInstances(String8(interface).c_str(), &out); !status.isOk()) { ALOGW("Failed to getDeclaredInstances for %s: %s", String8(interface).c_str(), status.toString8().c_str()); @@ -498,7 +476,7 @@ Vector ServiceManagerShim::getDeclaredInstances(const String16& interf std::optional ServiceManagerShim::updatableViaApex(const String16& name) { std::optional declared; - if (Status status = mTheRealServiceManager->updatableViaApex(String8(name).c_str(), &declared); + if (Status status = mUnifiedServiceManager->updatableViaApex(String8(name).c_str(), &declared); !status.isOk()) { ALOGW("Failed to get updatableViaApex for %s: %s", String8(name).c_str(), status.toString8().c_str()); @@ -509,7 +487,7 @@ std::optional ServiceManagerShim::updatableViaApex(const String16& nam Vector ServiceManagerShim::getUpdatableNames(const String16& apexName) { std::vector out; - if (Status status = mTheRealServiceManager->getUpdatableNames(String8(apexName).c_str(), &out); + if (Status status = mUnifiedServiceManager->getUpdatableNames(String8(apexName).c_str(), &out); !status.isOk()) { ALOGW("Failed to getUpdatableNames for %s: %s", String8(apexName).c_str(), status.toString8().c_str()); @@ -528,7 +506,7 @@ std::optional ServiceManagerShim::getConnection const String16& name) { std::optional connectionInfo; if (Status status = - mTheRealServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo); + mUnifiedServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo); !status.isOk()) { ALOGW("Failed to get ConnectionInfo for %s: %s", String8(name).c_str(), status.toString8().c_str()); @@ -549,7 +527,7 @@ status_t ServiceManagerShim::registerForNotifications(const String16& name, sp registrationWaiter = sp::make(cb); std::lock_guard lock(mNameToRegistrationLock); if (Status status = - mTheRealServiceManager->registerForNotifications(nameStr, registrationWaiter); + mUnifiedServiceManager->registerForNotifications(nameStr, registrationWaiter); !status.isOk()) { ALOGW("Failed to registerForNotifications for %s: %s", nameStr.c_str(), status.toString8().c_str()); @@ -600,7 +578,7 @@ status_t ServiceManagerShim::unregisterForNotifications(const String16& name, ALOGE("%s Callback passed wasn't used to register for notifications", __FUNCTION__); return BAD_VALUE; } - if (Status status = mTheRealServiceManager->unregisterForNotifications(String8(name).c_str(), + if (Status status = mUnifiedServiceManager->unregisterForNotifications(String8(name).c_str(), registrationWaiter); !status.isOk()) { ALOGW("Failed to get service manager to unregisterForNotifications for %s: %s", @@ -613,7 +591,7 @@ status_t ServiceManagerShim::unregisterForNotifications(const String16& name, std::vector ServiceManagerShim::getServiceDebugInfo() { std::vector serviceDebugInfos; std::vector ret; - if (Status status = mTheRealServiceManager->getServiceDebugInfo(&serviceDebugInfos); + if (Status status = mUnifiedServiceManager->getServiceDebugInfo(&serviceDebugInfos); !status.isOk()) { ALOGW("%s Failed to get ServiceDebugInfo", __FUNCTION__); return ret; diff --git a/libs/binder/IServiceManagerFFI.cpp b/libs/binder/IServiceManagerFFI.cpp new file mode 100644 index 0000000000..7d4d7dc063 --- /dev/null +++ b/libs/binder/IServiceManagerFFI.cpp @@ -0,0 +1,27 @@ +/* + * 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. + */ +#include + +#include +#include + +namespace android::impl { +sp +getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed() { + return getBackendUnifiedServiceManager(); +} + +} // namespace android::impl diff --git a/libs/binder/include/binder/IServiceManagerFFI.h b/libs/binder/include/binder/IServiceManagerFFI.h new file mode 100644 index 0000000000..753735506c --- /dev/null +++ b/libs/binder/include/binder/IServiceManagerFFI.h @@ -0,0 +1,25 @@ +/* + * 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. + */ +#pragma once + +#include + +namespace android::impl { + +LIBBINDER_EXPORTED sp +getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed(); + +} // namespace android::impl -- GitLab From 9cf8f32cc33028e43362e79c60437c42dfc9c7d6 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Tue, 18 Jun 2024 20:22:42 +0000 Subject: [PATCH 021/530] Include SOURCE_TOUCHPAD for Virtual Navigation Touchpad In addition to the existing SOURCE_TOUCH_NAVIGATION, this change includes SOURCE_TOUCHPAD to the InputDevice and the events for a Virtual Navigation Touchpad. Navigation touchpad events should not be affected by the geometry of the window that receives the events, since they are focus events (as opposed to pointer events). Adding SOURCE_TOUCHPAD will also add SOURCE_CLASS_POSITION, which will make the event ignore any local transforms. Bug: 343963635 Test: atest inputflinger_tests Flag: NONE bug fix Change-Id: I8faefbce0a50377f9e46dbfa419900a00473c262 --- services/inputflinger/reader/mapper/TouchInputMapper.cpp | 2 +- services/inputflinger/tests/InputReader_test.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index a3834908a7..81ec24e094 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -931,7 +931,7 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) mSource |= AINPUT_SOURCE_STYLUS; } } else if (mParameters.deviceType == Parameters::DeviceType::TOUCH_NAVIGATION) { - mSource = AINPUT_SOURCE_TOUCH_NAVIGATION; + mSource = AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD; mDeviceMode = DeviceMode::NAVIGATION; } else { ALOGW("Touch device '%s' has invalid parameters or configuration. The device will be " diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index fe238f3087..fa9d263406 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -6245,7 +6245,7 @@ TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsSetToTouchNavigation_setsCorr SingleTouchInputMapper& mapper = constructAndAddMapper(); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled()); - ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mapper.getSources()); + ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mapper.getSources()); } TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) { @@ -6268,7 +6268,7 @@ TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_upda InputReaderConfiguration::Change::DEVICE_TYPE /*changes*/); // Check whether device type update was successful. - ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources()); + ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION | AINPUT_SOURCE_TOUCHPAD, mDevice->getSources()); } TEST_F(SingleTouchInputMapperTest, HoverEventsOutsidePhysicalFrameAreIgnored) { -- GitLab From 1a25e4ec80a1e48ad552ce6659d187dd1a3aa4b4 Mon Sep 17 00:00:00 2001 From: Kaylee Lubick Date: Thu, 20 Jun 2024 17:35:57 +0000 Subject: [PATCH 022/530] [native] Update deprecated GrVk type names These are just aliases for the GPU-backend agnostic type name, so we should just use them. This also deletes seemingly unnecessary #includes. Change-Id: I6d7cb04671fa67c9b59144583a6a296e7acd7b84 Bug: b/309785258 Flag: EXEMPT refactor --- libs/renderengine/skia/SkiaVkRenderEngine.cpp | 1 - libs/renderengine/skia/SkiaVkRenderEngine.h | 2 -- libs/renderengine/skia/VulkanInterface.cpp | 33 ++++++------------- libs/renderengine/skia/VulkanInterface.h | 11 +++---- .../skia/compat/GaneshGpuContext.cpp | 6 ++-- .../renderengine/skia/compat/SkiaGpuContext.h | 5 ++- 6 files changed, 19 insertions(+), 39 deletions(-) diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp index bd501073d7..a1f917dc03 100644 --- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h index 0a2f9b2228..d2bb3d53cf 100644 --- a/libs/renderengine/skia/SkiaVkRenderEngine.h +++ b/libs/renderengine/skia/SkiaVkRenderEngine.h @@ -17,8 +17,6 @@ #ifndef SF_SKIAVKRENDERENGINE_H_ #define SF_SKIAVKRENDERENGINE_H_ -#include - #include "SkiaRenderEngine.h" #include "VulkanInterface.h" #include "compat/SkiaGpuContext.h" diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp index 5e756b03ed..37b69f6590 100644 --- a/libs/renderengine/skia/VulkanInterface.cpp +++ b/libs/renderengine/skia/VulkanInterface.cpp @@ -32,21 +32,8 @@ namespace android { namespace renderengine { namespace skia { -GrVkBackendContext VulkanInterface::getGaneshBackendContext() { - GrVkBackendContext backendContext; - backendContext.fInstance = mInstance; - backendContext.fPhysicalDevice = mPhysicalDevice; - backendContext.fDevice = mDevice; - backendContext.fQueue = mQueue; - backendContext.fGraphicsQueueIndex = mQueueIndex; - backendContext.fMaxAPIVersion = mApiVersion; - backendContext.fVkExtensions = &mGrExtensions; - backendContext.fDeviceFeatures2 = mPhysicalDeviceFeatures2; - backendContext.fGetProc = mGrGetProc; - backendContext.fProtectedContext = mIsProtected ? Protected::kYes : Protected::kNo; - backendContext.fDeviceLostContext = this; // VulkanInterface is long-lived - backendContext.fDeviceLostProc = onVkDeviceFault; - return backendContext; +VulkanBackendContext VulkanInterface::getGaneshBackendContext() { + return this->getGraphiteBackendContext(); }; VulkanBackendContext VulkanInterface::getGraphiteBackendContext() { @@ -57,7 +44,7 @@ VulkanBackendContext VulkanInterface::getGraphiteBackendContext() { backendContext.fQueue = mQueue; backendContext.fGraphicsQueueIndex = mQueueIndex; backendContext.fMaxAPIVersion = mApiVersion; - backendContext.fVkExtensions = &mGrExtensions; + backendContext.fVkExtensions = &mVulkanExtensions; backendContext.fDeviceFeatures2 = mPhysicalDeviceFeatures2; backendContext.fGetProc = mGrGetProc; backendContext.fProtectedContext = mIsProtected ? Protected::kYes : Protected::kNo; @@ -429,11 +416,11 @@ void VulkanInterface::init(bool protectedContent) { mDeviceExtensionNames.push_back(devExt.extensionName); } - mGrExtensions.init(sGetProc, instance, physicalDevice, enabledInstanceExtensionNames.size(), - enabledInstanceExtensionNames.data(), enabledDeviceExtensionNames.size(), - enabledDeviceExtensionNames.data()); + mVulkanExtensions.init(sGetProc, instance, physicalDevice, enabledInstanceExtensionNames.size(), + enabledInstanceExtensionNames.data(), enabledDeviceExtensionNames.size(), + enabledDeviceExtensionNames.data()); - if (!mGrExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) { + if (!mVulkanExtensions.hasExtension(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, 1)) { BAIL("Vulkan driver doesn't support external semaphore fd"); } @@ -458,7 +445,7 @@ void VulkanInterface::init(bool protectedContent) { tailPnext = &mProtectedMemoryFeatures->pNext; } - if (mGrExtensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) { + if (mVulkanExtensions.hasExtension(VK_EXT_DEVICE_FAULT_EXTENSION_NAME, 1)) { mDeviceFaultFeatures = new VkPhysicalDeviceFaultFeaturesEXT; mDeviceFaultFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT; mDeviceFaultFeatures->pNext = nullptr; @@ -484,7 +471,7 @@ void VulkanInterface::init(bool protectedContent) { queuePriority, }; - if (mGrExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) { + if (mVulkanExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) { queueNextPtr = &queuePriorityCreateInfo; } @@ -606,7 +593,7 @@ void VulkanInterface::teardown() { mQueue = VK_NULL_HANDLE; // Implicitly destroyed by destroying mDevice. mQueueIndex = 0; mApiVersion = 0; - mGrExtensions = skgpu::VulkanExtensions(); + mVulkanExtensions = skgpu::VulkanExtensions(); mGrGetProc = nullptr; mIsProtected = false; mIsRealtimePriority = false; diff --git a/libs/renderengine/skia/VulkanInterface.h b/libs/renderengine/skia/VulkanInterface.h index f20b00251b..d0fe4d1544 100644 --- a/libs/renderengine/skia/VulkanInterface.h +++ b/libs/renderengine/skia/VulkanInterface.h @@ -16,7 +16,7 @@ #pragma once -#include +#include #include #include @@ -24,10 +24,6 @@ using namespace skgpu; -namespace skgpu { -struct VulkanBackendContext; -} // namespace skgpu - namespace android { namespace renderengine { namespace skia { @@ -48,7 +44,8 @@ public: bool takeOwnership(); void teardown(); - GrVkBackendContext getGaneshBackendContext(); + // TODO(b/309785258) Combine these into one now that they are the same implementation. + VulkanBackendContext getGaneshBackendContext(); VulkanBackendContext getGraphiteBackendContext(); VkSemaphore createExportableSemaphore(); VkSemaphore importSemaphoreFromSyncFd(int syncFd); @@ -86,7 +83,7 @@ private: VkQueue mQueue = VK_NULL_HANDLE; int mQueueIndex = 0; uint32_t mApiVersion = 0; - skgpu::VulkanExtensions mGrExtensions; + skgpu::VulkanExtensions mVulkanExtensions; VkPhysicalDeviceFeatures2* mPhysicalDeviceFeatures2 = nullptr; VkPhysicalDeviceSamplerYcbcrConversionFeatures* mSamplerYcbcrConversionFeatures = nullptr; VkPhysicalDeviceProtectedMemoryFeatures* mProtectedMemoryFeatures = nullptr; diff --git a/libs/renderengine/skia/compat/GaneshGpuContext.cpp b/libs/renderengine/skia/compat/GaneshGpuContext.cpp index b2eae009ed..b121fe83eb 100644 --- a/libs/renderengine/skia/compat/GaneshGpuContext.cpp +++ b/libs/renderengine/skia/compat/GaneshGpuContext.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "../AutoBackendTexture.h" #include "GaneshBackendTexture.h" @@ -56,10 +56,10 @@ std::unique_ptr SkiaGpuContext::MakeGL_Ganesh( } std::unique_ptr SkiaGpuContext::MakeVulkan_Ganesh( - const GrVkBackendContext& grVkBackendContext, + const skgpu::VulkanBackendContext& vkBackendContext, GrContextOptions::PersistentCache& skSLCacheMonitor) { return std::make_unique( - GrDirectContexts::MakeVulkan(grVkBackendContext, ganeshOptions(skSLCacheMonitor))); + GrDirectContexts::MakeVulkan(vkBackendContext, ganeshOptions(skSLCacheMonitor))); } GaneshGpuContext::GaneshGpuContext(sk_sp grContext) : mGrContext(grContext) { diff --git a/libs/renderengine/skia/compat/SkiaGpuContext.h b/libs/renderengine/skia/compat/SkiaGpuContext.h index 282dfe7abe..9fa6fb8521 100644 --- a/libs/renderengine/skia/compat/SkiaGpuContext.h +++ b/libs/renderengine/skia/compat/SkiaGpuContext.h @@ -23,7 +23,6 @@ #include #include #include -#include #include "include/gpu/vk/VulkanBackendContext.h" #include "SkiaBackendTexture.h" @@ -52,10 +51,10 @@ public: GrContextOptions::PersistentCache& skSLCacheMonitor); /** - * grVkBackendContext must remain valid until after SkiaGpuContext is destroyed. + * vkBackendContext must remain valid until after SkiaGpuContext is destroyed. */ static std::unique_ptr MakeVulkan_Ganesh( - const GrVkBackendContext& grVkBackendContext, + const skgpu::VulkanBackendContext& vkBackendContext, GrContextOptions::PersistentCache& skSLCacheMonitor); // TODO: b/293371537 - Need shader / pipeline monitoring support in Graphite. -- GitLab From 6781d33a5f1f65031907dba71cbaf404a18459df Mon Sep 17 00:00:00 2001 From: Frederick Mayle Date: Tue, 21 May 2024 14:12:40 -0700 Subject: [PATCH 023/530] libbinder: export fewer symbols for bionic builds https://r.android.com/3087749 added these new options. This commit enables them for bionic builds. See that commit for details. Bug: 338458975 Test: TH Change-Id: Ib0a3bc28ab53931a673be5d85a3c760c318ead7e --- libs/binder/Android.bp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index f31f8d3993..bd6a08e09b 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -268,6 +268,21 @@ cc_defaults { "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", ], + + target: { + bionic: { + // Hide symbols by default and set the BUILDING_LIBBINDER macro so that + // the code knows to export them. + // + // Only enabled on bionic builds, where RTTI is disabled, because + // it is failing to export required typeinfo symbols. + // TODO: b/341341056 - Find a solution for non-bionic builds. + cflags: [ + "-fvisibility=hidden", + "-DBUILDING_LIBBINDER", + ], + }, + }, } cc_defaults { -- GitLab From a3be80cbc647821cf8dce0ce55a30dfe5e7f9f49 Mon Sep 17 00:00:00 2001 From: ramindani Date: Thu, 20 Jun 2024 14:08:37 -0700 Subject: [PATCH 024/530] SF: Add a flag vrr_bugfix_dropped_frame BUG: 343603085 Test: atest libsurfaceflinger_unittest Flag: com.android.graphics.surfaceflinger.flags.vrr_bugfix_dropped_frame Change-Id: Ib53b48a704e7752773800018a579a1d641badde6 --- services/surfaceflinger/common/FlagManager.cpp | 2 ++ .../common/include/common/FlagManager.h | 1 + .../surfaceflinger/surfaceflinger_flags_new.aconfig | 11 +++++++++++ 3 files changed, 14 insertions(+) diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index b7ec6e0b26..9b4677911e 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -135,6 +135,7 @@ void FlagManager::dump(std::string& result) const { DUMP_READ_ONLY_FLAG(vulkan_renderengine); DUMP_READ_ONLY_FLAG(renderable_buffer_usage); DUMP_READ_ONLY_FLAG(vrr_bugfix_24q4); + DUMP_READ_ONLY_FLAG(vrr_bugfix_dropped_frame); DUMP_READ_ONLY_FLAG(restore_blur_step); DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro); DUMP_READ_ONLY_FLAG(protected_if_client); @@ -239,6 +240,7 @@ FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_ FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "") FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "") FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, ""); +FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "") FLAG_MANAGER_READ_ONLY_FLAG(ce_fence_promise, ""); FLAG_MANAGER_READ_ONLY_FLAG(graphite_renderengine, "debug.renderengine.graphite") FLAG_MANAGER_READ_ONLY_FLAG(latch_unsignaled_with_auto_refresh_changed, ""); diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index 8f98ed3777..1601fa5c08 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -73,6 +73,7 @@ public: bool screenshot_fence_preservation() const; bool vulkan_renderengine() const; bool vrr_bugfix_24q4() const; + bool vrr_bugfix_dropped_frame() const; bool renderable_buffer_usage() const; bool restore_blur_step() const; bool dont_skip_on_early_ro() const; diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig index ee12325705..9619f6874d 100644 --- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig @@ -125,4 +125,15 @@ flag { } } # vrr_bugfix_24q4 +flag { + name: "vrr_bugfix_dropped_frame" + namespace: "core_graphics" + description: "bug fix for VRR dropped frame" + bug: "343603085" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} # vrr_bugfix_dropped_frame + # IMPORTANT - please keep alphabetize to reduce merge conflicts -- GitLab From f2f40f4de6991c1acd091bc486894863518ae285 Mon Sep 17 00:00:00 2001 From: ramindani Date: Tue, 18 Jun 2024 16:48:28 -0700 Subject: [PATCH 025/530] SF: Update the sequence of operation for frame rate override This change will freeze the timeline with the new rate generated through the requestDisplayMode before updating the render rate for frameRateOverride BUG: 343603085 Test: atest libsurfaceflinger_unittest Flag: com.android.graphics.surfaceflinger.flags.vrr_bugfix_dropped_frame Change-Id: I4d1c8febe1203de11046f6b6f4a92dc5f29cfbb3 --- services/surfaceflinger/Scheduler/Scheduler.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 60681a2bc8..4ce6cca765 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -1113,8 +1113,10 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals .emitEvent = !choice.consideredSignals.idle}); } - frameRateOverridesChanged = updateFrameRateOverridesLocked(consideredSignals, modeOpt->fps); - + if (!FlagManager::getInstance().vrr_bugfix_dropped_frame()) { + frameRateOverridesChanged = + updateFrameRateOverridesLocked(consideredSignals, modeOpt->fps); + } if (mPolicy.modeOpt != modeOpt) { mPolicy.modeOpt = modeOpt; refreshRateChanged = true; @@ -1129,6 +1131,12 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals if (refreshRateChanged) { mSchedulerCallback.requestDisplayModes(std::move(modeRequests)); } + + if (FlagManager::getInstance().vrr_bugfix_dropped_frame()) { + std::scoped_lock lock(mPolicyLock); + frameRateOverridesChanged = + updateFrameRateOverridesLocked(consideredSignals, mPolicy.modeOpt->fps); + } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); } -- GitLab From 71df3978e38f97a5365ab7bdba6050929386a557 Mon Sep 17 00:00:00 2001 From: Rocky Fang Date: Tue, 4 Jun 2024 17:49:33 +0000 Subject: [PATCH 026/530] Add trace for sensor event Test: collect trace for system server, see expected trace Bug: 333132224 Flag: com.android.hardware.libsensor.flags.sensor_event_queue_report_sensor_usage_in_tracing Change-Id: I066a150cdc85060e2530c3fc4ea4fa13c56af298 --- libs/sensor/Android.bp | 2 + libs/sensor/SensorEventQueue.cpp | 53 +++++++++++++------ libs/sensor/SensorManager.cpp | 37 ++++++++++++- libs/sensor/include/sensor/SensorEventQueue.h | 5 +- libs/sensor/include/sensor/SensorManager.h | 20 +++---- services/sensorservice/aidl/fuzzer/Android.bp | 5 ++ 6 files changed, 96 insertions(+), 26 deletions(-) diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp index 7fa47b45f0..659666d6b6 100644 --- a/libs/sensor/Android.bp +++ b/libs/sensor/Android.bp @@ -63,6 +63,8 @@ cc_library { "libhardware", "libpermission", "android.companion.virtual.virtualdevice_aidl-cpp", + "libaconfig_storage_read_api_cc", + "server_configurable_flags", ], static_libs: [ diff --git a/libs/sensor/SensorEventQueue.cpp b/libs/sensor/SensorEventQueue.cpp index 4438d454c0..84852eabec 100644 --- a/libs/sensor/SensorEventQueue.cpp +++ b/libs/sensor/SensorEventQueue.cpp @@ -15,31 +15,40 @@ */ #define LOG_TAG "Sensors" +#define ATRACE_TAG ATRACE_TAG_SYSTEM_SERVER +#include +#include +#include +#include +#include +#include +#include #include - -#include +#include #include - -#include #include +#include -#include -#include -#include - -#include -#include +#include +#include +#include using std::min; +namespace libsensor_flags = com::android::hardware::libsensor::flags; // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- -SensorEventQueue::SensorEventQueue(const sp& connection) - : mSensorEventConnection(connection), mRecBuffer(nullptr), mAvailable(0), mConsumed(0), - mNumAcksToSend(0) { +SensorEventQueue::SensorEventQueue(const sp& connection, + SensorManager& sensorManager) + : mSensorEventConnection(connection), + mRecBuffer(nullptr), + mSensorManager(sensorManager), + mAvailable(0), + mConsumed(0), + mNumAcksToSend(0) { mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT]; } @@ -65,8 +74,8 @@ ssize_t SensorEventQueue::write(const sp& tube, ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { if (mAvailable == 0) { - ssize_t err = BitTube::recvObjects(mSensorChannel, - mRecBuffer, MAX_RECEIVE_BUFFER_EVENT_COUNT); + ssize_t err = + BitTube::recvObjects(mSensorChannel, mRecBuffer, MAX_RECEIVE_BUFFER_EVENT_COUNT); if (err < 0) { return err; } @@ -75,6 +84,20 @@ ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { } size_t count = min(numEvents, mAvailable); memcpy(events, mRecBuffer + mConsumed, count * sizeof(ASensorEvent)); + + if (CC_UNLIKELY(ATRACE_ENABLED()) && + libsensor_flags::sensor_event_queue_report_sensor_usage_in_tracing()) { + for (size_t i = 0; i < count; i++) { + std::optional sensorName = + mSensorManager.getSensorNameByHandle(events->sensor); + if (sensorName.has_value()) { + char buffer[UINT8_MAX]; + std::snprintf(buffer, sizeof(buffer), "Sensor event from %s", + sensorName.value().data()); + ATRACE_INSTANT_FOR_TRACK(LOG_TAG, buffer); + } + } + } mAvailable -= count; mConsumed += count; return static_cast(count); diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp index 9411e204e9..3ca6f0f904 100644 --- a/libs/sensor/SensorManager.cpp +++ b/libs/sensor/SensorManager.cpp @@ -38,6 +38,7 @@ #include #include +namespace libsensor_flags = com::android::hardware::libsensor::flags; // ---------------------------------------------------------------------------- namespace android { @@ -78,6 +79,21 @@ int getDeviceIdForUid(uid_t uid) { return DEVICE_ID_DEFAULT; } +bool findSensorNameInList(int32_t handle, const Vector& sensorList, + std::string* outString) { + for (auto& sensor : sensorList) { + if (sensor.getHandle() == handle) { + std::ostringstream oss; + oss << sensor.getStringType() << ":" << sensor.getName(); + if (outString) { + *outString = std::move(oss.str()); + } + return true; + } + } + return false; +} + } // namespace Mutex SensorManager::sLock; @@ -355,6 +371,25 @@ Sensor const* SensorManager::getDefaultSensor(int type) return nullptr; } +std::optional SensorManager::getSensorNameByHandle(int32_t handle) { + std::lock_guard lock(mSensorHandleToNameMutex); + auto iterator = mSensorHandleToName.find(handle); + if (iterator != mSensorHandleToName.end()) { + return iterator->second; + } + + std::string sensorName; + if (!findSensorNameInList(handle, mSensors, &sensorName) && + !findSensorNameInList(handle, mDynamicSensors, &sensorName)) { + ALOGW("Cannot find sensor with handle %d", handle); + return std::nullopt; + } + + mSensorHandleToName[handle] = std::move(sensorName); + + return mSensorHandleToName[handle]; +} + sp SensorManager::createEventQueue( String8 packageName, int mode, String16 attributionTag) { sp queue; @@ -368,7 +403,7 @@ sp SensorManager::createEventQueue( ALOGE("createEventQueue: connection is NULL."); return nullptr; } - queue = new SensorEventQueue(connection); + queue = new SensorEventQueue(connection, *this); break; } return queue; diff --git a/libs/sensor/include/sensor/SensorEventQueue.h b/libs/sensor/include/sensor/SensorEventQueue.h index 8c3fde0fa1..0bcaadc7c0 100644 --- a/libs/sensor/include/sensor/SensorEventQueue.h +++ b/libs/sensor/include/sensor/SensorEventQueue.h @@ -42,6 +42,7 @@ namespace android { // ---------------------------------------------------------------------------- class ISensorEventConnection; +class SensorManager; class Sensor; class Looper; @@ -65,7 +66,8 @@ public: // Default sensor sample period static constexpr int32_t SENSOR_DELAY_NORMAL = 200000; - explicit SensorEventQueue(const sp& connection); + explicit SensorEventQueue(const sp& connection, + SensorManager& sensorManager); virtual ~SensorEventQueue(); virtual void onFirstRef(); @@ -107,6 +109,7 @@ private: mutable Mutex mLock; mutable sp mLooper; ASensorEvent* mRecBuffer; + SensorManager& mSensorManager; size_t mAvailable; size_t mConsumed; uint32_t mNumAcksToSend; diff --git a/libs/sensor/include/sensor/SensorManager.h b/libs/sensor/include/sensor/SensorManager.h index 49f050a0ac..8d7237d548 100644 --- a/libs/sensor/include/sensor/SensorManager.h +++ b/libs/sensor/include/sensor/SensorManager.h @@ -17,22 +17,20 @@ #ifndef ANDROID_GUI_SENSOR_MANAGER_H #define ANDROID_GUI_SENSOR_MANAGER_H -#include -#include - -#include -#include - #include #include #include - +#include +#include +#include #include +#include #include #include -#include -#include +#include +#include +#include // ---------------------------------------------------------------------------- // Concrete types for the NDK @@ -66,6 +64,7 @@ public: sp createEventQueue( String8 packageName = String8(""), int mode = 0, String16 attributionTag = String16("")); bool isDataInjectionEnabled(); + std::optional getSensorNameByHandle(int32_t handle); bool isReplayDataInjectionEnabled(); bool isHalBypassReplayDataInjectionEnabled(); int createDirectChannel(size_t size, int channelType, const native_handle_t *channelData); @@ -97,6 +96,9 @@ private: const String16 mOpPackageName; const int mDeviceId; std::unordered_map> mDirectConnection; + + std::mutex mSensorHandleToNameMutex; + std::unordered_map mSensorHandleToName; int32_t mDirectConnectionHandle; }; diff --git a/services/sensorservice/aidl/fuzzer/Android.bp b/services/sensorservice/aidl/fuzzer/Android.bp index f6f104ee88..b2dc89bfd0 100644 --- a/services/sensorservice/aidl/fuzzer/Android.bp +++ b/services/sensorservice/aidl/fuzzer/Android.bp @@ -26,6 +26,11 @@ cc_fuzz { "libfakeservicemanager", "libcutils", "liblog", + "libsensor_flags_c_lib", + ], + shared_libs: [ + "libaconfig_storage_read_api_cc", + "server_configurable_flags", ], srcs: [ "fuzzer.cpp", -- GitLab From 42a145f0ebd2b22898a2972e92cd2983f321f519 Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Tue, 18 Jun 2024 15:30:25 +0000 Subject: [PATCH 027/530] Increase wait timeout for InputReader tests Current timeout is not sufficient for some events on cuttlefish devices. Increase the timeout and account for hardware multiplier to reduce flakiness. Test: atest inputflinger_tests:TouchIntegrationTest --rerun-until-failure 1000 Bug: 303677628 Flag: TEST_ONLY Change-Id: I72a8b2e6884492192842bf9f6b192573cd408084 --- .../inputflinger/tests/FakeInputReaderPolicy.cpp | 15 ++++++++++++--- services/inputflinger/tests/TestConstants.h | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/services/inputflinger/tests/FakeInputReaderPolicy.cpp b/services/inputflinger/tests/FakeInputReaderPolicy.cpp index d2cb0ac3df..6099c91daf 100644 --- a/services/inputflinger/tests/FakeInputReaderPolicy.cpp +++ b/services/inputflinger/tests/FakeInputReaderPolicy.cpp @@ -16,6 +16,7 @@ #include "FakeInputReaderPolicy.h" +#include #include #include @@ -24,6 +25,12 @@ namespace android { +namespace { + +static const int HW_TIMEOUT_MULTIPLIER = base::GetIntProperty("ro.hw_timeout_multiplier", 1); + +} // namespace + void FakeInputReaderPolicy::assertInputDevicesChanged() { waitForInputDevices([](bool devicesChanged) { if (!devicesChanged) { @@ -241,9 +248,11 @@ void FakeInputReaderPolicy::waitForInputDevices(std::function proces base::ScopedLockAssertion assumeLocked(mLock); const bool devicesChanged = - mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) { - return mInputDevicesChanged; - }); + mDevicesChangedCondition.wait_for(lock, + ADD_INPUT_DEVICE_TIMEOUT * HW_TIMEOUT_MULTIPLIER, + [this]() REQUIRES(mLock) { + return mInputDevicesChanged; + }); ASSERT_NO_FATAL_FAILURE(processDevicesChanged(devicesChanged)); mInputDevicesChanged = false; } diff --git a/services/inputflinger/tests/TestConstants.h b/services/inputflinger/tests/TestConstants.h index ad48b0fbe0..082bbb8136 100644 --- a/services/inputflinger/tests/TestConstants.h +++ b/services/inputflinger/tests/TestConstants.h @@ -24,6 +24,9 @@ namespace android { using std::chrono_literals::operator""ms; +// Timeout for waiting for an input device to be added and processed +static constexpr std::chrono::duration ADD_INPUT_DEVICE_TIMEOUT = 500ms; + // Timeout for waiting for an expected event static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms; -- GitLab From e190327cfddff093aef4134482a868b91d38f519 Mon Sep 17 00:00:00 2001 From: Victor Khimenko Date: Fri, 21 Jun 2024 10:44:34 +0000 Subject: [PATCH 028/530] Add emulated_apit_checker for Vulkan We are auto-generating data-structures autotmatically and then are comparing layout of what we have generated to calculated one. We also compare layout for structures provided by hwvulkan_headers, but only on host. This CL closes the loop and makes it possible to do such comparison on gues, too. Bug: 330393812 Test: m berberis_all Change-Id: I80143ccd6a21c6c9cd8a0365427bf95f035fbc2a --- vulkan/Android.bp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vulkan/Android.bp b/vulkan/Android.bp index 2bf905c654..0da9cc00a9 100644 --- a/vulkan/Android.bp +++ b/vulkan/Android.bp @@ -26,6 +26,8 @@ package { cc_library_headers { name: "hwvulkan_headers", + host_supported: true, // Used for verification in Berberis. + native_bridge_supported: true, // Used for verification in Berberis. vendor_available: true, header_libs: [ "libcutils_headers", -- GitLab From c099400b0138d705d7d3b341970e60e397f1bb45 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Wed, 22 May 2024 16:34:52 -0400 Subject: [PATCH 029/530] Output::presentFrameAndReleaseLayers: flush pending commands for OFF displays Most work from this method can be skipped if the display is not enabled. However, uncaching buffers should still occur. If the display is disabled and there are buffers to uncache, still flush pending commands. They should only contain commands that are meaningful for a disabled display, like bufferSlotsToClear. Bug: 330806421 Test: libcompositionengine_test Flag: flush_buffer_slots_to_uncache Change-Id: I7baa3e76af86329fb266395e63e92a0ba38967f4 (cherry picked from commit a3ba7fa4665a1df144ba777a37dbb979bab0d390) Merged-In: I7baa3e76af86329fb266395e63e92a0ba38967f4 --- .../include/compositionengine/Output.h | 3 +- .../include/compositionengine/impl/Display.h | 1 + .../include/compositionengine/impl/Output.h | 6 +- .../include/compositionengine/mock/Output.h | 3 +- .../CompositionEngine/src/Display.cpp | 9 + .../CompositionEngine/src/Output.cpp | 19 ++- .../CompositionEngine/tests/DisplayTest.cpp | 4 +- .../CompositionEngine/tests/MockHWComposer.h | 1 + .../CompositionEngine/tests/OutputTest.cpp | 157 +++++++++++++++--- .../DisplayHardware/HWComposer.cpp | 7 + .../DisplayHardware/HWComposer.h | 4 + .../surfaceflinger/common/FlagManager.cpp | 4 + .../common/include/common/FlagManager.h | 1 + .../surfaceflinger_flags_new.aconfig | 11 ++ 14 files changed, 196 insertions(+), 34 deletions(-) diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index f1d6f52eb8..a46ec4f066 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -306,7 +306,7 @@ protected: virtual void finishFrame(GpuCompositionResult&&) = 0; virtual std::optional composeSurfaces( const Region&, std::shared_ptr, base::unique_fd&) = 0; - virtual void presentFrameAndReleaseLayers() = 0; + virtual void presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) = 0; virtual void renderCachedSets(const CompositionRefreshArgs&) = 0; virtual bool chooseCompositionStrategy( std::optional*) = 0; @@ -314,6 +314,7 @@ protected: const std::optional& changes) = 0; virtual bool getSkipColorTransform() const = 0; virtual FrameFences presentFrame() = 0; + virtual void executeCommands() = 0; virtual std::vector generateClientCompositionRequests( bool supportsProtectedContent, ui::Dataspace outputDataspace, std::vector &outLayerRef) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 2dc9a1a49a..f942f90aad 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -60,6 +60,7 @@ public: void applyCompositionStrategy(const std::optional&) override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentFrame() override; + void executeCommands() override; void setExpensiveRenderingExpected(bool) override; void finishFrame(GpuCompositionResult&&) override; bool supportsOffloadPresent() const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 911d67b5ed..eafb383ccc 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -104,7 +104,7 @@ public: std::optional composeSurfaces(const Region&, std::shared_ptr, base::unique_fd&) override; - void presentFrameAndReleaseLayers() override; + void presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) override; void renderCachedSets(const CompositionRefreshArgs&) override; void cacheClientCompositionRequests(uint32_t) override; bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override; @@ -123,7 +123,8 @@ public: virtual std::future chooseCompositionStrategyAsync( std::optional*); virtual void resetCompositionStrategy(); - virtual ftl::Future presentFrameAndReleaseLayersAsync(); + virtual ftl::Future presentFrameAndReleaseLayersAsync( + bool flushEvenWhenDisabled); protected: std::unique_ptr createOutputLayer(const sp&) const; @@ -137,6 +138,7 @@ protected: void applyCompositionStrategy(const std::optional&) override{}; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentFrame() override; + void executeCommands() override {} virtual renderengine::DisplaySettings generateClientCompositionDisplaySettings( const std::shared_ptr& buffer) const; std::vector generateClientCompositionRequests( diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index 95ea3a4ed7..5c086d4736 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -121,9 +121,10 @@ public: base::unique_fd&)); MOCK_CONST_METHOD0(getSkipColorTransform, bool()); - MOCK_METHOD0(presentFrameAndReleaseLayers, void()); + MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled)); MOCK_METHOD1(renderCachedSets, void(const CompositionRefreshArgs&)); MOCK_METHOD0(presentFrame, compositionengine::Output::FrameFences()); + MOCK_METHOD(void, executeCommands, ()); MOCK_METHOD3(generateClientCompositionRequests, std::vector(bool, ui::Dataspace, std::vector&)); diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 6428d089a7..6931983137 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -365,6 +365,15 @@ void Display::applyClientTargetRequests(const ClientTargetProperty& clientTarget static_cast(clientTargetProperty.clientTargetProperty.pixelFormat)); } +void Display::executeCommands() { + const auto halDisplayIdOpt = HalDisplayId::tryCast(mId); + if (mIsDisconnected || !halDisplayIdOpt) { + return; + } + + getCompositionEngine().getHwComposer().executeCommands(*halDisplayIdOpt); +} + compositionengine::Output::FrameFences Display::presentFrame() { auto fences = impl::Output::presentFrame(); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 921e05dfb2..ce48945701 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -474,8 +474,9 @@ ftl::Future Output::present( devOptRepaintFlash(refreshArgs); finishFrame(std::move(result)); ftl::Future future; + const bool flushEvenWhenDisabled = !refreshArgs.bufferIdsToUncache.empty(); if (mOffloadPresent) { - future = presentFrameAndReleaseLayersAsync(); + future = presentFrameAndReleaseLayersAsync(flushEvenWhenDisabled); // Only offload for this frame. The next frame will determine whether it // needs to be offloaded. Leave the HwcAsyncWorker in place. For one thing, @@ -483,7 +484,7 @@ ftl::Future Output::present( // we don't want to churn. mOffloadPresent = false; } else { - presentFrameAndReleaseLayers(); + presentFrameAndReleaseLayers(flushEvenWhenDisabled); future = ftl::yield({}); } renderCachedSets(refreshArgs); @@ -1133,9 +1134,9 @@ void Output::prepareFrame() { finishPrepareFrame(); } -ftl::Future Output::presentFrameAndReleaseLayersAsync() { +ftl::Future Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) { return ftl::Future(std::move(mHwComposerAsyncWorker->send([&]() { - presentFrameAndReleaseLayers(); + presentFrameAndReleaseLayers(flushEvenWhenDisabled); return true; }))) .then([](bool) { return std::monostate{}; }); @@ -1210,7 +1211,8 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& } } - presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = false; + presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay); @@ -1584,11 +1586,16 @@ bool Output::isPowerHintSessionEnabled() { return false; } -void Output::presentFrameAndReleaseLayers() { +void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str()); ALOGV(__FUNCTION__); if (!getState().isEnabled) { + if (flushEvenWhenDisabled && FlagManager::getInstance().flush_buffer_slots_to_uncache()) { + // Some commands, like clearing buffer slots, should still be executed + // even if the display is not enabled. + executeCommands(); + } return; } diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index a95a5c62fd..39163ea60f 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -1067,8 +1067,8 @@ TEST_F(DisplayFunctionalTest, presentFrameAndReleaseLayersCriticalCallsAreOrdere EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(_, _)); EXPECT_CALL(*mDisplaySurface, onFrameCommitted()); - - mDisplay->presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = false; + mDisplay->presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } } // namespace diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index 575a30e522..fb4fe5f0e9 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -63,6 +63,7 @@ public: (override)); MOCK_METHOD2(presentAndGetReleaseFences, status_t(HalDisplayId, std::optional)); + MOCK_METHOD(status_t, executeCommands, (HalDisplayId)); MOCK_METHOD2(setPowerMode, status_t(PhysicalDisplayId, hal::PowerMode)); MOCK_METHOD2(setActiveConfig, status_t(HalDisplayId, size_t)); MOCK_METHOD2(setColorTransform, status_t(HalDisplayId, const mat4&)); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 799c7edebd..1f2028faf8 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -2014,7 +2014,7 @@ struct OutputPresentTest : public testing::Test { MOCK_METHOD0(prepareFrameAsync, GpuCompositionResult()); MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD1(finishFrame, void(GpuCompositionResult&&)); - MOCK_METHOD0(presentFrameAndReleaseLayers, void()); + MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override)); MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&)); }; @@ -2036,7 +2036,7 @@ TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) { EXPECT_CALL(mOutput, prepareFrame()); EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args))); EXPECT_CALL(mOutput, finishFrame(_)); - EXPECT_CALL(mOutput, presentFrameAndReleaseLayers()); + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(false)); EXPECT_CALL(mOutput, renderCachedSets(Ref(args))); mOutput.present(args); @@ -2056,7 +2056,7 @@ TEST_F(OutputPresentTest, predictingCompositionStrategyInvokesPrepareFrameAsync) EXPECT_CALL(mOutput, prepareFrameAsync()); EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args))); EXPECT_CALL(mOutput, finishFrame(_)); - EXPECT_CALL(mOutput, presentFrameAndReleaseLayers()); + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(false)); EXPECT_CALL(mOutput, renderCachedSets(Ref(args))); mOutput.present(args); @@ -2902,7 +2902,7 @@ struct OutputDevOptRepaintFlashTest : public testing::Test { std::optional(const Region&, std::shared_ptr, base::unique_fd&)); - MOCK_METHOD0(presentFrameAndReleaseLayers, void()); + MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled)); MOCK_METHOD0(prepareFrame, void()); MOCK_METHOD0(updateProtectedContentState, void()); MOCK_METHOD2(dequeueRenderBuffer, @@ -2939,7 +2939,8 @@ TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) { mOutput.mState.isEnabled = false; InSequence seq; - EXPECT_CALL(mOutput, presentFrameAndReleaseLayers()); + constexpr bool kFlushEvenWhenDisabled = false; + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)); EXPECT_CALL(mOutput, prepareFrame()); mOutput.devOptRepaintFlash(mRefreshArgs); @@ -2951,7 +2952,8 @@ TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfEnabled) { InSequence seq; EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kEmptyRegion)); - EXPECT_CALL(mOutput, presentFrameAndReleaseLayers()); + constexpr bool kFlushEvenWhenDisabled = false; + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)); EXPECT_CALL(mOutput, prepareFrame()); mOutput.devOptRepaintFlash(mRefreshArgs); @@ -2967,7 +2969,8 @@ TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)); EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), _, _)); EXPECT_CALL(*mRenderSurface, queueBuffer(_, 1.f)); - EXPECT_CALL(mOutput, presentFrameAndReleaseLayers()); + constexpr bool kFlushEvenWhenDisabled = false; + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)); EXPECT_CALL(mOutput, prepareFrame()); mOutput.devOptRepaintFlash(mRefreshArgs); @@ -2985,7 +2988,7 @@ struct OutputFinishFrameTest : public testing::Test { std::optional(const Region&, std::shared_ptr, base::unique_fd&)); - MOCK_METHOD0(presentFrameAndReleaseLayers, void()); + MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override)); MOCK_METHOD0(updateProtectedContentState, void()); MOCK_METHOD2(dequeueRenderBuffer, bool(base::unique_fd*, std::shared_ptr*)); @@ -3102,7 +3105,8 @@ struct OutputPostFramebufferTest : public testing::Test { struct OutputPartialMock : public OutputPartialMockBase { // Sets up the helper functions called by the function under test to use // mock implementations. - MOCK_METHOD0(presentFrame, compositionengine::Output::FrameFences()); + MOCK_METHOD(compositionengine::Output::FrameFences, presentFrame, ()); + MOCK_METHOD(void, executeCommands, ()); }; struct Layer { @@ -3140,9 +3144,67 @@ struct OutputPostFramebufferTest : public testing::Test { }; TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) { + SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache, + true); mOutput.mState.isEnabled = false; + EXPECT_CALL(mOutput, executeCommands()).Times(0); + EXPECT_CALL(mOutput, presentFrame()).Times(0); - mOutput.presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = false; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); +} + +TEST_F(OutputPostFramebufferTest, ifNotEnabledExecutesCommandsIfFlush) { + SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache, + true); + mOutput.mState.isEnabled = false; + EXPECT_CALL(mOutput, executeCommands()); + EXPECT_CALL(mOutput, presentFrame()).Times(0); + + constexpr bool kFlushEvenWhenDisabled = true; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); +} + +TEST_F(OutputPostFramebufferTest, ifEnabledDoNotExecuteCommands) { + SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache, + true); + mOutput.mState.isEnabled = true; + + compositionengine::Output::FrameFences frameFences; + + EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u)); + + // This should only be called for disabled outputs. This test's goal is to verify this line; + // the other expectations help satisfy the StrictMocks. + EXPECT_CALL(mOutput, executeCommands()).Times(0); + + EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); + EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); + + constexpr bool kFlushEvenWhenDisabled = true; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); +} + +TEST_F(OutputPostFramebufferTest, ifEnabledDoNotExecuteCommands2) { + // Same test as ifEnabledDoNotExecuteCommands, but with this variable set to false. + constexpr bool kFlushEvenWhenDisabled = false; + + SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache, + true); + mOutput.mState.isEnabled = true; + + compositionengine::Output::FrameFences frameFences; + + EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u)); + + // This should only be called for disabled outputs. This test's goal is to verify this line; + // the other expectations help satisfy the StrictMocks. + EXPECT_CALL(mOutput, executeCommands()).Times(0); + + EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); + EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); + + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) { @@ -3160,7 +3222,8 @@ TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCom EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); - mOutput.presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = true; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { @@ -3202,7 +3265,8 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get()); }); - mOutput.presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = false; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) { @@ -3225,7 +3289,8 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); - mOutput.presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = false; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { @@ -3270,7 +3335,8 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); - mOutput.presentFrameAndReleaseLayers(); + constexpr bool kFlushEvenWhenDisabled = false; + mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); // After the call the list of released layers should have been cleared. EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty()); @@ -5057,8 +5123,9 @@ struct OutputPresentFrameAndReleaseLayersAsyncTest : public ::testing::Test { struct OutputPartialMock : public OutputPrepareFrameAsyncTest::OutputPartialMock { // Set up the helper functions called by the function under test to use // mock implementations. - MOCK_METHOD0(presentFrameAndReleaseLayers, void()); - MOCK_METHOD0(presentFrameAndReleaseLayersAsync, ftl::Future()); + MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled)); + MOCK_METHOD(ftl::Future, presentFrameAndReleaseLayersAsync, + (bool flushEvenWhenDisabled)); }; OutputPresentFrameAndReleaseLayersAsyncTest() { mOutput->setDisplayColorProfileForTest( @@ -5075,16 +5142,16 @@ struct OutputPresentFrameAndReleaseLayersAsyncTest : public ::testing::Test { }; TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, notCalledWhenNotRequested) { - EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync()).Times(0); - EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(1); + EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(_)).Times(0); + EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(_)).Times(1); mOutput->present(mRefreshArgs); } TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledWhenRequested) { - EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync()) + EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(false)) .WillOnce(Return(ftl::yield({}))); - EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(0); + EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(_)).Times(0); mOutput->offloadPresentNextFrame(); mOutput->present(mRefreshArgs); @@ -5092,9 +5159,10 @@ TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledWhenRequested) { TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledForOneFrame) { ::testing::InSequence inseq; - EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync()) + constexpr bool kFlushEvenWhenDisabled = false; + EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(kFlushEvenWhenDisabled)) .WillOnce(Return(ftl::yield({}))); - EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(1); + EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)).Times(1); mOutput->offloadPresentNextFrame(); mOutput->present(mRefreshArgs); @@ -5175,5 +5243,50 @@ TEST_F(OutputUpdateProtectedContentStateTest, ifProtectedContentLayerComposeByCl mOutput.updateProtectedContentState(); } +struct OutputPresentFrameAndReleaseLayersTest : public testing::Test { + struct OutputPartialMock : public OutputPartialMockBase { + // Sets up the helper functions called by the function under test (and functions we can + // ignore) to use mock implementations. + MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD1(updateCompositionState, + void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD0(planComposition, void()); + MOCK_METHOD1(writeCompositionState, void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD0(beginFrame, void()); + MOCK_METHOD0(prepareFrame, void()); + MOCK_METHOD0(prepareFrameAsync, GpuCompositionResult()); + MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD1(finishFrame, void(GpuCompositionResult&&)); + MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override)); + MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&)); + }; + + NiceMock mOutput; +}; + +TEST_F(OutputPresentFrameAndReleaseLayersTest, noBuffersToUncache) { + CompositionRefreshArgs args; + ASSERT_TRUE(args.bufferIdsToUncache.empty()); + mOutput.editState().isEnabled = false; + + constexpr bool kFlushEvenWhenDisabled = false; + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)); + + mOutput.present(args); +} + +TEST_F(OutputPresentFrameAndReleaseLayersTest, buffersToUncache) { + CompositionRefreshArgs args; + args.bufferIdsToUncache.push_back(1); + mOutput.editState().isEnabled = false; + + constexpr bool kFlushEvenWhenDisabled = true; + EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)); + + mOutput.present(args); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 776bcd3e32..3e16e7c1ec 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -602,6 +602,13 @@ status_t HWComposer::presentAndGetReleaseFences( return NO_ERROR; } +status_t HWComposer::executeCommands(HalDisplayId displayId) { + auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; + auto error = static_cast(mComposer->executeCommands(hwcDisplay->getId())); + RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR); + return NO_ERROR; +} + status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 7fbbb1a672..f21f1d8108 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -160,6 +160,8 @@ public: HalDisplayId, std::optional earliestPresentTime) = 0; + virtual status_t executeCommands(HalDisplayId) = 0; + // set power mode virtual status_t setPowerMode(PhysicalDisplayId, hal::PowerMode) = 0; @@ -359,6 +361,8 @@ public: HalDisplayId, std::optional earliestPresentTime) override; + status_t executeCommands(HalDisplayId) override; + // set power mode status_t setPowerMode(PhysicalDisplayId, hal::PowerMode mode) override; diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp index b7f06a992e..393fab5e84 100644 --- a/services/surfaceflinger/common/FlagManager.cpp +++ b/services/surfaceflinger/common/FlagManager.cpp @@ -132,6 +132,8 @@ void FlagManager::dump(std::string& result) const { DUMP_READ_ONLY_FLAG(restore_blur_step); DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro); DUMP_READ_ONLY_FLAG(protected_if_client); + DUMP_READ_ONLY_FLAG(flush_buffer_slots_to_uncache); + #undef DUMP_READ_ONLY_FLAG #undef DUMP_SERVER_FLAG #undef DUMP_FLAG_INTERVAL @@ -212,6 +214,8 @@ FLAG_MANAGER_READ_ONLY_FLAG(renderable_buffer_usage, "") FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step") FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "") FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "") +FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, + "debug.sf.flush_buffer_slots_to_uncache"); /// Trunk stable server flags /// FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "") diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h index 241c814780..16f6a9996e 100644 --- a/services/surfaceflinger/common/include/common/FlagManager.h +++ b/services/surfaceflinger/common/include/common/FlagManager.h @@ -72,6 +72,7 @@ public: bool restore_blur_step() const; bool dont_skip_on_early_ro() const; bool protected_if_client() const; + bool flush_buffer_slots_to_uncache() const; protected: // overridden for unit tests diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig index 5451752d91..e3dceb68a8 100644 --- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig +++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig @@ -10,4 +10,15 @@ flag { bug: "273702768" } # dont_skip_on_early_ro2 +flag { + name: "flush_buffer_slots_to_uncache" + namespace: "core_graphics" + description: "Flush DisplayCommands for disabled displays in order to uncache requested buffers." + bug: "330806421" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} # flush_buffer_slots_to_uncache + # IMPORTANT - please keep alphabetize to reduce merge conflicts -- GitLab From 207674d8c5d67d077b74a66dc3c941c878ba5016 Mon Sep 17 00:00:00 2001 From: Harry Cutts Date: Thu, 6 Jun 2024 18:53:41 +0000 Subject: [PATCH 030/530] Return a std::optional from EventHub::getAbsoluteAxisInfo InputDevice::getAbsoluteAxisInfo will be refactored similarly in a follow-up. Test: atest inputflinger_tests Test: m checkinput Test: build and run inputflinger_multitouch_input_fuzzer for a while Bug: 245989146 Flag: EXEMPT refactor Change-Id: I57de645c889de53c8be0f9f8744a62e92fafdadb --- services/inputflinger/reader/EventHub.cpp | 13 ++++------ .../inputflinger/reader/include/EventHub.h | 9 ++++--- .../inputflinger/reader/include/InputDevice.h | 11 ++++---- services/inputflinger/tests/FakeEventHub.cpp | 12 ++++----- services/inputflinger/tests/FakeEventHub.h | 4 +-- .../tests/HardwareProperties_test.cpp | 26 ++++++++----------- .../inputflinger/tests/InputMapperTest.cpp | 20 +++++++------- services/inputflinger/tests/InterfaceMocks.h | 4 +-- .../tests/fuzzers/MapperHelpers.h | 21 +++++++++++---- 9 files changed, 63 insertions(+), 57 deletions(-) diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index fe70a51b81..7052c61a37 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -998,26 +998,23 @@ std::optional EventHub::getConfiguration(int32_t deviceId) const { return *device->configuration; } -status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const { - outAxisInfo->clear(); +std::optional EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis) const { if (axis < 0 || axis > ABS_MAX) { - return NAME_NOT_FOUND; + return std::nullopt; } std::scoped_lock _l(mLock); const Device* device = getDeviceLocked(deviceId); if (device == nullptr) { - return NAME_NOT_FOUND; + return std::nullopt; } // We can read the RawAbsoluteAxisInfo even if the device is disabled and doesn't have a valid // fd, because the info is populated once when the device is first opened, and it doesn't change // throughout the device lifecycle. auto it = device->absState.find(axis); if (it == device->absState.end()) { - return NAME_NOT_FOUND; + return std::nullopt; } - *outAxisInfo = it->second.info; - return OK; + return it->second.info; } bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const { diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 7cf584df78..0ae57e3f2a 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -278,8 +279,8 @@ public: */ virtual std::optional getConfiguration(int32_t deviceId) const = 0; - virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const = 0; + virtual std::optional getAbsoluteAxisInfo(int32_t deviceId, + int axis) const = 0; virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0; @@ -511,8 +512,8 @@ public: std::optional getConfiguration(int32_t deviceId) const override final; - status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const override final; + std::optional getAbsoluteAxisInfo(int32_t deviceId, + int axis) const override final; bool hasRelativeAxis(int32_t deviceId, int axis) const override final; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 2a7e262bf5..37c7e5c8d0 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -306,9 +306,11 @@ public: return mEventHub->getDeviceControllerNumber(mId); } inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const { - if (const auto status = mEventHub->getAbsoluteAxisInfo(mId, code, axisInfo); status != OK) { - return status; + std::optional info = mEventHub->getAbsoluteAxisInfo(mId, code); + if (!info.has_value()) { + return NAME_NOT_FOUND; } + *axisInfo = *info; // Validate axis info for InputDevice. if (axisInfo->valid && axisInfo->minValue == axisInfo->maxValue) { @@ -432,9 +434,8 @@ public: } inline bool hasAbsoluteAxis(int32_t code) const { - RawAbsoluteAxisInfo info; - mEventHub->getAbsoluteAxisInfo(mId, code, &info); - return info.valid; + std::optional info = mEventHub->getAbsoluteAxisInfo(mId, code); + return info.has_value() && info->valid; } inline bool isKeyPressed(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode) == AKEY_STATE_DOWN; diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index daa000f2ce..1e9be0eb4f 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -16,6 +16,8 @@ #include "FakeEventHub.h" +#include + #include #include #include @@ -263,18 +265,16 @@ std::optional FakeEventHub::getConfiguration(int32_t deviceId) cons return device->configuration; } -status_t FakeEventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const { +std::optional FakeEventHub::getAbsoluteAxisInfo(int32_t deviceId, + int axis) const { Device* device = getDevice(deviceId); if (device) { ssize_t index = device->absoluteAxes.indexOfKey(axis); if (index >= 0) { - *outAxisInfo = device->absoluteAxes.valueAt(index); - return OK; + return device->absoluteAxes.valueAt(index); } } - outAxisInfo->clear(); - return -1; + return std::nullopt; } bool FakeEventHub::hasRelativeAxis(int32_t deviceId, int axis) const { diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index f07b3441c2..37bcc405c4 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -168,8 +168,8 @@ private: InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override; int32_t getDeviceControllerNumber(int32_t) const override; std::optional getConfiguration(int32_t deviceId) const override; - status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const override; + std::optional getAbsoluteAxisInfo(int32_t deviceId, + int axis) const override; bool hasRelativeAxis(int32_t deviceId, int axis) const override; bool hasInputProperty(int32_t, int) const override; bool hasMscEvent(int32_t deviceId, int mscEvent) const override final; diff --git a/services/inputflinger/tests/HardwareProperties_test.cpp b/services/inputflinger/tests/HardwareProperties_test.cpp index 8dfa8c8e0c..643fab6d44 100644 --- a/services/inputflinger/tests/HardwareProperties_test.cpp +++ b/services/inputflinger/tests/HardwareProperties_test.cpp @@ -48,24 +48,20 @@ protected: static constexpr int32_t EVENTHUB_ID = 1; void setupValidAxis(int axis, int32_t min, int32_t max, int32_t resolution) { - EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_)) - .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) { - outAxisInfo->valid = true; - outAxisInfo->minValue = min; - outAxisInfo->maxValue = max; - outAxisInfo->flat = 0; - outAxisInfo->fuzz = 0; - outAxisInfo->resolution = resolution; - return OK; - }); + EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) + .WillRepeatedly(Return(std::optional{{ + .valid = true, + .minValue = min, + .maxValue = max, + .flat = 0, + .fuzz = 0, + .resolution = resolution, + }})); } void setupInvalidAxis(int axis) { - EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, testing::_)) - .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) { - outAxisInfo->valid = false; - return -1; - }); + EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) + .WillRepeatedly(Return(std::nullopt)); } void setProperty(int property, bool value) { diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index b5c9232a78..19bc5bef66 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -57,16 +57,16 @@ void InputMapperUnitTest::createDevice() { void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution) { - EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis, _)) - .WillRepeatedly([=](int32_t, int32_t, RawAbsoluteAxisInfo* outAxisInfo) { - outAxisInfo->valid = valid; - outAxisInfo->minValue = min; - outAxisInfo->maxValue = max; - outAxisInfo->flat = 0; - outAxisInfo->fuzz = 0; - outAxisInfo->resolution = resolution; - return valid ? OK : -1; - }); + EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) + .WillRepeatedly(Return(valid ? std::optional{{ + .valid = true, + .minValue = min, + .maxValue = max, + .flat = 0, + .fuzz = 0, + .resolution = resolution, + }} + : std::nullopt)); } void InputMapperUnitTest::expectScanCodes(bool present, std::set scanCodes) { diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index 16d3193908..a7a0833aec 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -91,8 +91,8 @@ public: MOCK_METHOD(InputDeviceIdentifier, getDeviceIdentifier, (int32_t deviceId), (const)); MOCK_METHOD(int32_t, getDeviceControllerNumber, (int32_t deviceId), (const)); MOCK_METHOD(std::optional, getConfiguration, (int32_t deviceId), (const)); - MOCK_METHOD(status_t, getAbsoluteAxisInfo, - (int32_t deviceId, int axis, RawAbsoluteAxisInfo* outAxisInfo), (const)); + MOCK_METHOD(std::optional, getAbsoluteAxisInfo, + (int32_t deviceId, int axis), (const)); MOCK_METHOD(bool, hasRelativeAxis, (int32_t deviceId, int axis), (const)); MOCK_METHOD(bool, hasInputProperty, (int32_t deviceId, int property), (const)); MOCK_METHOD(bool, hasMscEvent, (int32_t deviceId, int mscEvent), (const)); diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index ff425ddfb7..50fbf4b995 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -119,16 +120,26 @@ public: void setAbsoluteAxisInfo(int32_t deviceId, int axis, const RawAbsoluteAxisInfo& axisInfo) { mAxes[deviceId][axis] = axisInfo; } - status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, - RawAbsoluteAxisInfo* outAxisInfo) const override { + std::optional getAbsoluteAxisInfo(int32_t deviceId, + int axis) const override { if (auto deviceAxesIt = mAxes.find(deviceId); deviceAxesIt != mAxes.end()) { const std::map& deviceAxes = deviceAxesIt->second; if (auto axisInfoIt = deviceAxes.find(axis); axisInfoIt != deviceAxes.end()) { - *outAxisInfo = axisInfoIt->second; - return OK; + return axisInfoIt->second; } } - return mFdp->ConsumeIntegral(); + if (mFdp->ConsumeBool()) { + return std::optional({ + .valid = mFdp->ConsumeBool(), + .minValue = mFdp->ConsumeIntegral(), + .maxValue = mFdp->ConsumeIntegral(), + .flat = mFdp->ConsumeIntegral(), + .fuzz = mFdp->ConsumeIntegral(), + .resolution = mFdp->ConsumeIntegral(), + }); + } else { + return std::nullopt; + } } bool hasRelativeAxis(int32_t deviceId, int axis) const override { return mFdp->ConsumeBool(); } bool hasInputProperty(int32_t deviceId, int property) const override { -- GitLab From e2c5e20e5297118618bda915909e2f710495f05e Mon Sep 17 00:00:00 2001 From: Harry Cutts Date: Fri, 21 Jun 2024 17:08:48 +0000 Subject: [PATCH 031/530] Return std::optional from getAbsoluteAxisValue This makes the methods nicer to use, and forces callers to clearly handle the case where there's no value to return. Test: m checkinput Test: atest inputflinger_tests Test: build and run inputflinger_multitouch_input_fuzzer for a while Bug: 245989146 Flag: EXEMPT refactor Change-Id: I51c750d21d8a95ef631d93365ee76d18ebf71d43 --- services/inputflinger/reader/EventHub.cpp | 12 +++++------- services/inputflinger/reader/include/EventHub.h | 7 +++---- services/inputflinger/reader/include/InputDevice.h | 9 ++------- .../accumulator/MultiTouchMotionAccumulator.cpp | 10 ++++------ .../accumulator/SingleTouchMotionAccumulator.cpp | 14 +++++++------- services/inputflinger/tests/FakeEventHub.cpp | 9 +++------ services/inputflinger/tests/FakeEventHub.h | 2 +- services/inputflinger/tests/InterfaceMocks.h | 2 +- .../tests/MultiTouchInputMapper_test.cpp | 14 ++++---------- .../tests/TouchpadInputMapper_test.cpp | 7 ++----- .../inputflinger/tests/fuzzers/MapperHelpers.h | 9 ++++++--- 11 files changed, 38 insertions(+), 57 deletions(-) diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 7052c61a37..65583e95bf 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -1127,22 +1127,20 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const { return device->swState.test(sw) ? AKEY_STATE_DOWN : AKEY_STATE_UP; } -status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const { - *outValue = 0; +std::optional EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const { if (axis < 0 || axis > ABS_MAX) { - return NAME_NOT_FOUND; + return std::nullopt; } std::scoped_lock _l(mLock); const Device* device = getDeviceLocked(deviceId); if (device == nullptr || !device->hasValidFd()) { - return NAME_NOT_FOUND; + return std::nullopt; } const auto it = device->absState.find(axis); if (it == device->absState.end()) { - return NAME_NOT_FOUND; + return std::nullopt; } - *outValue = it->second.value; - return OK; + return it->second.value; } base::Result> EventHub::getMtSlotValues(int32_t deviceId, int32_t axis, diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 0ae57e3f2a..2a4346694a 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -340,8 +340,7 @@ public: virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0; virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0; virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0; - virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, - int32_t* outValue) const = 0; + virtual std::optional getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const = 0; /* Query Multi-Touch slot values for an axis. Returns error or an 1 indexed array of size * (slotCount + 1). The value at the 0 index is set to queried axis. */ virtual base::Result> getMtSlotValues(int32_t deviceId, int32_t axis, @@ -560,8 +559,8 @@ public: int32_t getSwitchState(int32_t deviceId, int32_t sw) const override final; int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override final; - status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, - int32_t* outValue) const override final; + std::optional getAbsoluteAxisValue(int32_t deviceId, + int32_t axis) const override final; base::Result> getMtSlotValues(int32_t deviceId, int32_t axis, size_t slotCount) const override final; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 37c7e5c8d0..7fd55973c7 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -381,8 +381,8 @@ public: return mEventHub->getKeyCodeForKeyLocation(mId, locationKeyCode); } inline int32_t getSwitchState(int32_t sw) const { return mEventHub->getSwitchState(mId, sw); } - inline status_t getAbsoluteAxisValue(int32_t code, int32_t* outValue) const { - return mEventHub->getAbsoluteAxisValue(mId, code, outValue); + inline std::optional getAbsoluteAxisValue(int32_t code) const { + return mEventHub->getAbsoluteAxisValue(mId, code); } inline base::Result> getMtSlotValues(int32_t axis, size_t slotCount) const { @@ -443,11 +443,6 @@ public: inline bool isKeyCodePressed(int32_t keyCode) const { return mEventHub->getKeyCodeState(mId, keyCode) == AKEY_STATE_DOWN; } - inline int32_t getAbsoluteAxisValue(int32_t code) const { - int32_t value; - mEventHub->getAbsoluteAxisValue(mId, code, &value); - return value; - } inline bool isDeviceEnabled() { return mEventHub->isDeviceEnabled(mId); } inline status_t enableDevice() { return mEventHub->enableDevice(mId); } inline status_t disableDevice() { return mEventHub->disableDevice(mId); } diff --git a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp index 4919068201..8dc6e4d397 100644 --- a/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/MultiTouchMotionAccumulator.cpp @@ -139,13 +139,11 @@ void MultiTouchMotionAccumulator::populateCurrentSlot( if (!mUsingSlotsProtocol) { return; } - int32_t initialSlot; - if (const auto status = deviceContext.getAbsoluteAxisValue(ABS_MT_SLOT, &initialSlot); - status == OK) { - mCurrentSlot = initialSlot; + if (const std::optional initialSlot = deviceContext.getAbsoluteAxisValue(ABS_MT_SLOT); + initialSlot.has_value()) { + mCurrentSlot = initialSlot.value(); } else { - ALOGE("Could not retrieve current multi-touch slot index. status=%s", - statusToString(status).c_str()); + ALOGE("Could not retrieve current multi-touch slot index"); } } diff --git a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp index 2b82ddf33d..4cf9243653 100644 --- a/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp +++ b/services/inputflinger/reader/mapper/accumulator/SingleTouchMotionAccumulator.cpp @@ -26,13 +26,13 @@ SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() { } void SingleTouchMotionAccumulator::reset(InputDeviceContext& deviceContext) { - mAbsX = deviceContext.getAbsoluteAxisValue(ABS_X); - mAbsY = deviceContext.getAbsoluteAxisValue(ABS_Y); - mAbsPressure = deviceContext.getAbsoluteAxisValue(ABS_PRESSURE); - mAbsToolWidth = deviceContext.getAbsoluteAxisValue(ABS_TOOL_WIDTH); - mAbsDistance = deviceContext.getAbsoluteAxisValue(ABS_DISTANCE); - mAbsTiltX = deviceContext.getAbsoluteAxisValue(ABS_TILT_X); - mAbsTiltY = deviceContext.getAbsoluteAxisValue(ABS_TILT_Y); + mAbsX = deviceContext.getAbsoluteAxisValue(ABS_X).value_or(0); + mAbsY = deviceContext.getAbsoluteAxisValue(ABS_Y).value_or(0); + mAbsPressure = deviceContext.getAbsoluteAxisValue(ABS_PRESSURE).value_or(0); + mAbsToolWidth = deviceContext.getAbsoluteAxisValue(ABS_TOOL_WIDTH).value_or(0); + mAbsDistance = deviceContext.getAbsoluteAxisValue(ABS_DISTANCE).value_or(0); + mAbsTiltX = deviceContext.getAbsoluteAxisValue(ABS_TILT_X).value_or(0); + mAbsTiltY = deviceContext.getAbsoluteAxisValue(ABS_TILT_Y).value_or(0); } void SingleTouchMotionAccumulator::clearAbsoluteAxes() { diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index 1e9be0eb4f..12736c8cc0 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -417,18 +417,15 @@ int32_t FakeEventHub::getSwitchState(int32_t deviceId, int32_t sw) const { return AKEY_STATE_UNKNOWN; } -status_t FakeEventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, - int32_t* outValue) const { +std::optional FakeEventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const { Device* device = getDevice(deviceId); if (device) { ssize_t index = device->absoluteAxisValue.indexOfKey(axis); if (index >= 0) { - *outValue = device->absoluteAxisValue.valueAt(index); - return OK; + return device->absoluteAxisValue.valueAt(index); } } - *outValue = 0; - return -1; + return std::nullopt; } void FakeEventHub::setMtSlotValues(int32_t deviceId, int32_t axis, diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index 37bcc405c4..c2c875f518 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -187,7 +187,7 @@ private: std::optional getRawLayoutInfo(int32_t deviceId) const override; int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override; int32_t getSwitchState(int32_t deviceId, int32_t sw) const override; - status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const override; + std::optional getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const override; int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override; // Return true if the device has non-empty key layout. diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index a7a0833aec..bacc6d432e 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -131,7 +131,7 @@ public: MOCK_METHOD(int32_t, getKeyCodeState, (int32_t deviceId, int32_t keyCode), (const, override)); MOCK_METHOD(int32_t, getSwitchState, (int32_t deviceId, int32_t sw), (const, override)); - MOCK_METHOD(status_t, getAbsoluteAxisValue, (int32_t deviceId, int32_t axis, int32_t* outValue), + MOCK_METHOD(std::optional, getAbsoluteAxisValue, (int32_t deviceId, int32_t axis), (const, override)); MOCK_METHOD(base::Result>, getMtSlotValues, (int32_t deviceId, int32_t axis, size_t slotCount), (const, override)); diff --git a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp index b5f897154b..d4d3c3857f 100644 --- a/services/inputflinger/tests/MultiTouchInputMapper_test.cpp +++ b/services/inputflinger/tests/MultiTouchInputMapper_test.cpp @@ -99,11 +99,8 @@ protected: setupAxis(ABS_MT_TOOL_TYPE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0); // reset current slot at the beginning - EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, _)) - .WillRepeatedly([](int32_t, int32_t, int32_t* outValue) { - *outValue = 0; - return OK; - }); + EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT)) + .WillRepeatedly(Return(0)); // mark all slots not in use mockSlotValues({}); @@ -211,11 +208,8 @@ TEST_F(MultiTouchInputMapperUnitTest, MultiFingerGestureWithUnexpectedReset) { const auto pointerCoordsBeforeReset = std::get(args.back()).pointerCoords; // On buffer overflow mapper will be reset and MT slots data will be repopulated - EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, _)) - .WillRepeatedly([=](int32_t, int32_t, int32_t* outValue) { - *outValue = 1; - return OK; - }); + EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT)) + .WillRepeatedly(Return(1)); mockSlotValues( {{1, {Point{x1, y1}, FIRST_TRACKING_ID}}, {2, {Point{x2, y2}, SECOND_TRACKING_ID}}}); diff --git a/services/inputflinger/tests/TouchpadInputMapper_test.cpp b/services/inputflinger/tests/TouchpadInputMapper_test.cpp index 2b62dd13ef..1afb4f090a 100644 --- a/services/inputflinger/tests/TouchpadInputMapper_test.cpp +++ b/services/inputflinger/tests/TouchpadInputMapper_test.cpp @@ -103,11 +103,8 @@ protected: setupAxis(ABS_MT_DISTANCE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0); setupAxis(ABS_MT_TOOL_TYPE, /*valid=*/false, /*min=*/0, /*max=*/0, /*resolution=*/0); - EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, testing::_)) - .WillRepeatedly([](int32_t eventHubId, int32_t, int32_t* outValue) { - *outValue = 0; - return OK; - }); + EXPECT_CALL(mMockEventHub, getAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT)) + .WillRepeatedly(Return(0)); EXPECT_CALL(mMockEventHub, getMtSlotValues(EVENTHUB_ID, testing::_, testing::_)) .WillRepeatedly([]() -> base::Result> { return base::ResultError("Axis not supported", NAME_NOT_FOUND); diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index 50fbf4b995..6dea540e9c 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -208,9 +208,12 @@ public: int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const override { return mFdp->ConsumeIntegral(); } - status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, - int32_t* outValue) const override { - return mFdp->ConsumeIntegral(); + std::optional getAbsoluteAxisValue(int32_t deviceId, int32_t axis) const override { + if (mFdp->ConsumeBool()) { + return mFdp->ConsumeIntegral(); + } else { + return std::nullopt; + } } base::Result> getMtSlotValues(int32_t deviceId, int32_t axis, size_t slotCount) const override { -- GitLab From 11db98694208cefcdd06fdaad2a63514b168d27f Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 21 Jun 2024 22:06:14 +0000 Subject: [PATCH 032/530] Get window info debug data without holding the statelock Avoids a deadlock with mStateLock when calling dumpsys SurfaceFlinger. Deadlock happens because we make a blocking call into the background thread holding the mStateLock. Background thread may try to hold the mStateLock when destroying a layer handle which can result in a deadlock. Flag: EXEMPT bugfix Test: presubmit, run dumpsys Fixes: 347142017 Change-Id: Icda6d4ee0ead70a4d76a4f6fe766fdf40bae6d2c --- services/surfaceflinger/SurfaceFlinger.cpp | 23 +++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d7727808a4..5b40acf030 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6391,15 +6391,23 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { return NO_ERROR; } - // Traversal of drawing state must happen on the main thread. - // Otherwise, SortedVector may have shared ownership during concurrent - // traversals, which can result in use-after-frees. + // Collect debug data from main thread std::string compositionLayers; mScheduler ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { dumpVisibleFrontEnd(compositionLayers); }) .get(); + // get window info listener data without the state lock + auto windowInfosDebug = mWindowInfosListenerInvoker->getDebugInfo(); + compositionLayers.append("Window Infos:\n"); + StringAppendF(&compositionLayers, " max send vsync id: %" PRId64 "\n", + ftl::to_underlying(windowInfosDebug.maxSendDelayVsyncId)); + StringAppendF(&compositionLayers, " max send delay (ns): %" PRId64 " ns\n", + windowInfosDebug.maxSendDelayDuration); + StringAppendF(&compositionLayers, " unsent messages: %zu\n", + windowInfosDebug.pendingMessageCount); + compositionLayers.append("\n"); dumpAll(args, compositionLayers, result); write(fd, result.c_str(), result.size()); return NO_ERROR; @@ -6982,15 +6990,6 @@ void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositio result.append(mTimeStats->miniDump()); result.append("\n"); - - result.append("Window Infos:\n"); - auto windowInfosDebug = mWindowInfosListenerInvoker->getDebugInfo(); - StringAppendF(&result, " max send vsync id: %" PRId64 "\n", - ftl::to_underlying(windowInfosDebug.maxSendDelayVsyncId)); - StringAppendF(&result, " max send delay (ns): %" PRId64 " ns\n", - windowInfosDebug.maxSendDelayDuration); - StringAppendF(&result, " unsent messages: %zu\n", windowInfosDebug.pendingMessageCount); - result.append("\n"); } mat4 SurfaceFlinger::calculateColorMatrix(float saturation) { -- GitLab From 4780eb455bfa3d43a5e5439b004847fc1e576839 Mon Sep 17 00:00:00 2001 From: Justin Yun Date: Mon, 24 Jun 2024 18:21:57 +0900 Subject: [PATCH 033/530] Define prebuilt xml files as prebuilt_etc modules These files were installed with PRODUCT_COPY_FILES. Instead of using the PRODUCT_COPY_FILES define them as prebuilt_etc modules and install them. Different from the other modules in this directory, these new modules are for system files. Bug: 314933937 Test: m aosp_cf_system_x86_64 Change-Id: I3a8fb0046bbadcd5fcd5c2ded4d3b745b71e0f47 --- data/etc/Android.bp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/data/etc/Android.bp b/data/etc/Android.bp index 707b9982ab..b63d14b2cb 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -412,6 +412,14 @@ prebuilt_etc { defaults: ["frameworks_native_data_etc_defaults"], } +// installed in system +prebuilt_etc { + name: "android.software.preview_sdk.prebuilt.xml", + relative_install_path: "permissions", + src: "android.software.preview_sdk.xml", + filename_from_src: true, +} + prebuilt_etc { name: "android.software.sip.voip.prebuilt.xml", src: "android.software.sip.voip.xml", @@ -454,6 +462,22 @@ prebuilt_etc { defaults: ["frameworks_native_data_etc_defaults"], } +// installed in system +prebuilt_etc { + name: "android.software.webview.prebuilt.xml", + relative_install_path: "permissions", + src: "android.software.webview.xml", + filename_from_src: true, +} + +// installed in system +prebuilt_etc { + name: "android.software.window_magnification.prebuilt.xml", + relative_install_path: "permissions", + src: "android.software.window_magnification.xml", + filename_from_src: true, +} + prebuilt_etc { name: "aosp_excluded_hardware.prebuilt.xml", src: "aosp_excluded_hardware.xml", -- GitLab From 7cbcabf503e7b184d1c7115a24f11c8502e8b78d Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 24 Jun 2024 12:25:40 +0000 Subject: [PATCH 034/530] Fix ASystemFont docs. Looks like the docs weren't updated as the API changed during API review. Bug: https://github.com/android/ndk/issues/2034 Change-Id: I2eaeba50672efe42de95aa7adcf77f1a7a141432 --- include/android/system_fonts.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h index 94484eaf54..2d3a2148ae 100644 --- a/include/android/system_fonts.h +++ b/include/android/system_fonts.h @@ -31,27 +31,27 @@ * * \code{.cpp} * ASystemFontIterator* iterator = ASystemFontIterator_open(); - * ASystemFont* font = NULL; + * AFont* font = NULL; * * while ((font = ASystemFontIterator_next(iterator)) != nullptr) { * // Look if the font is your desired one. - * if (ASystemFont_getWeight(font) == 400 && !ASystemFont_isItalic(font) - * && ASystemFont_getLocale(font) == NULL) { + * if (AFont_getWeight(font) == 400 && !AFont_isItalic(font) + * && AFont_getLocale(font) == NULL) { * break; * } - * ASystemFont_close(font); + * AFont_close(font); * } * ASystemFontIterator_close(iterator); * - * int fd = open(ASystemFont_getFontFilePath(font), O_RDONLY); - * int collectionIndex = ASystemFont_getCollectionINdex(font); + * int fd = open(AFont_getFontFilePath(font), O_RDONLY | O_CLOEXEC); + * int collectionIndex = AFont_getCollectionIndex(font); * std::vector> variationSettings; - * for (size_t i = 0; i < ASystemFont_getAxisCount(font); ++i) { + * for (size_t i = 0; i < AFont_getAxisCount(font); ++i) { * variationSettings.push_back(std::make_pair( - * ASystemFont_getAxisTag(font, i), - * ASystemFont_getAxisValue(font, i))); + * AFont_getAxisTag(font, i), + * AFont_getAxisValue(font, i))); * } - * ASystemFont_close(font); + * AFont_close(font); * * // Use this font for your text rendering engine. * @@ -99,7 +99,7 @@ typedef struct ASystemFontIterator ASystemFontIterator; /** * Create a system font iterator. * - * Use ASystemFont_close() to close the iterator. + * Use ASystemFontIterator_close() to close the iterator. * * Available since API level 29. * @@ -123,7 +123,7 @@ void ASystemFontIterator_close(ASystemFontIterator* _Nullable iterator) __INTROD * * \param iterator an iterator for the system fonts. Passing NULL is not allowed. * \return a font. If no more font is available, returns nullptr. You need to release the returned - * font by ASystemFont_close when it is no longer needed. + * font with AFont_close() when it is no longer needed. */ AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29); -- GitLab From 1972557dca9614dfd1c32fe34dd901d9edbf7fa9 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Mon, 24 Jun 2024 10:44:13 -0400 Subject: [PATCH 035/530] Fix lambda in presentFrameAndReleaseLayersAsync Follow on to I7baa3e76af86329fb266395e63e92a0ba38967f4, which made a lambda use a variable it did not capture correctly. Fix that capture. Bug: 330806421 Bug: 347659752 Test: manual Flag: EXEMPT bug fix Change-Id: I3a8dd1670113111e01de3471b8061ff24dd0a115 --- services/surfaceflinger/CompositionEngine/src/Output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 5b9a10252e..b40aea4210 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1102,7 +1102,7 @@ void Output::prepareFrame() { } ftl::Future Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) { - return ftl::Future(std::move(mHwComposerAsyncWorker->send([&]() { + return ftl::Future(std::move(mHwComposerAsyncWorker->send([this, flushEvenWhenDisabled]() { presentFrameAndReleaseLayers(flushEvenWhenDisabled); return true; }))) -- GitLab From e188462f7a04eb69ebb57f4cd4880e867f259027 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III Date: Mon, 24 Jun 2024 10:44:13 -0400 Subject: [PATCH 036/530] Fix lambda in presentFrameAndReleaseLayersAsync Follow on to I7baa3e76af86329fb266395e63e92a0ba38967f4, which made a lambda use a variable it did not capture correctly. Fix that capture. Bug: 330806421 Bug: 347659752 Test: manual Flag: EXEMPT bug fix Change-Id: I3a8dd1670113111e01de3471b8061ff24dd0a115 (cherry picked from commit 1972557dca9614dfd1c32fe34dd901d9edbf7fa9) --- services/surfaceflinger/CompositionEngine/src/Output.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index ce48945701..894c791ed7 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1135,7 +1135,7 @@ void Output::prepareFrame() { } ftl::Future Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) { - return ftl::Future(std::move(mHwComposerAsyncWorker->send([&]() { + return ftl::Future(std::move(mHwComposerAsyncWorker->send([this, flushEvenWhenDisabled]() { presentFrameAndReleaseLayers(flushEvenWhenDisabled); return true; }))) -- GitLab From 714b1bd40e547eddc4a24a13b0c737db2f92d08a Mon Sep 17 00:00:00 2001 From: Rachel Lee Date: Mon, 24 Jun 2024 11:22:15 -0700 Subject: [PATCH 037/530] Set LOW category to 48 fps Based on UX. Bug: 343775394 Test: libsurfaceflinger_unittest Flag: EXEMPT bugfix Change-Id: I493152d82e96b3a1a7397fcf6a19077392cf4c23 --- .../Scheduler/RefreshRateSelector.cpp | 2 +- .../unittests/RefreshRateSelectorTest.cpp | 81 +++++++++++++++++-- 2 files changed, 77 insertions(+), 6 deletions(-) diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index 2c664928ee..76fbef0bc0 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -1636,7 +1636,7 @@ FpsRange RefreshRateSelector::getFrameRateCategoryRange(FrameRateCategory catego case FrameRateCategory::Normal: return FpsRange{60_Hz, 120_Hz}; case FrameRateCategory::Low: - return FpsRange{30_Hz, 120_Hz}; + return FpsRange{48_Hz, 120_Hz}; case FrameRateCategory::HighHint: case FrameRateCategory::NoPreference: case FrameRateCategory::Default: diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp index cf9a7d3e69..06c4e30989 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp @@ -1562,7 +1562,7 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60 // When frame rates get an equal score, the lower is chosen, unless there are Max votes. {0_Hz, FrameRateCategory::High, 90_Hz}, {0_Hz, FrameRateCategory::Normal, 60_Hz}, - {0_Hz, FrameRateCategory::Low, 30_Hz}, + {0_Hz, FrameRateCategory::Low, 60_Hz}, {0_Hz, FrameRateCategory::NoPreference, 60_Hz}, // Cases that have both desired frame rate and frame rate category requirements. @@ -1609,6 +1609,77 @@ TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_30_60 } } +TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategory_120_vrr) { + if (GetParam() != Config::FrameRateOverride::Enabled) { + return; + } + + SET_FLAG_FOR_TEST(flags::vrr_config, true); + // Device with VRR config mode + auto selector = createSelector(kVrrMode_120, kModeId120); + + struct Case { + // Params + Fps desiredFrameRate = 0_Hz; + FrameRateCategory frameRateCategory = FrameRateCategory::Default; + + // Expected result + Fps expectedFrameRate = 0_Hz; + }; + + // Prepare a table with the vote and the expected refresh rate + const std::initializer_list testCases = { + // Cases that only have frame rate category requirements, but no desired frame rate. + // When frame rates get an equal score, the lower is chosen, unless there are Max votes. + {0_Hz, FrameRateCategory::High, 120_Hz}, + {0_Hz, FrameRateCategory::Normal, 60_Hz}, + {0_Hz, FrameRateCategory::Low, 48_Hz}, + {0_Hz, FrameRateCategory::NoPreference, 120_Hz}, + + // Cases that have both desired frame rate and frame rate category requirements. + {24_Hz, FrameRateCategory::High, 120_Hz}, + {30_Hz, FrameRateCategory::High, 120_Hz}, + {12_Hz, FrameRateCategory::Normal, 60_Hz}, + {24_Hz, FrameRateCategory::Low, 48_Hz}, + {30_Hz, FrameRateCategory::NoPreference, 30_Hz}, + + // Cases that only have desired frame rate. + {30_Hz, FrameRateCategory::Default, 30_Hz}, + }; + + for (auto testCase : testCases) { + std::vector layers; + ALOGI("**** %s: Testing desiredFrameRate=%s, frameRateCategory=%s", __func__, + to_string(testCase.desiredFrameRate).c_str(), + ftl::enum_string(testCase.frameRateCategory).c_str()); + + if (testCase.desiredFrameRate.isValid()) { + std::stringstream ss; + ss << to_string(testCase.desiredFrameRate) << "ExplicitDefault"; + LayerRequirement layer = {.name = ss.str(), + .vote = LayerVoteType::ExplicitDefault, + .desiredRefreshRate = testCase.desiredFrameRate, + .weight = 1.f}; + layers.push_back(layer); + } + + if (testCase.frameRateCategory != FrameRateCategory::Default) { + std::stringstream ss; + ss << "ExplicitCategory (" << ftl::enum_string(testCase.frameRateCategory) << ")"; + LayerRequirement layer = {.name = ss.str(), + .vote = LayerVoteType::ExplicitCategory, + .frameRateCategory = testCase.frameRateCategory, + .weight = 1.f}; + layers.push_back(layer); + } + + EXPECT_EQ(testCase.expectedFrameRate, selector.getBestFrameRateMode(layers).fps) + << "Did not get expected frame rate for frameRate=" + << to_string(testCase.desiredFrameRate) + << " category=" << ftl::enum_string(testCase.frameRateCategory); + } +} + TEST_P(RefreshRateSelectorTest, getBestFrameRateMode_withFrameRateCategoryMultiLayers_30_60_90_120) { auto selector = createSelector(makeModes(kMode30, kMode60, kMode90, kMode120), kModeId60); @@ -2140,14 +2211,14 @@ TEST_P(RefreshRateSelectorTest, // These layers may switch modes because smoothSwitchOnly=false. {FrameRateCategory::Default, false, 120_Hz, kModeId120}, {FrameRateCategory::NoPreference, false, 120_Hz, kModeId120}, - {FrameRateCategory::Low, false, 30_Hz, kModeId60}, + {FrameRateCategory::Low, false, 60_Hz, kModeId60}, {FrameRateCategory::Normal, false, 60_Hz, kModeId60}, {FrameRateCategory::High, false, 120_Hz, kModeId120}, // These layers cannot change mode due to smoothSwitchOnly, and will definitely use // active mode (120Hz). {FrameRateCategory::NoPreference, true, 120_Hz, kModeId120}, - {FrameRateCategory::Low, true, 40_Hz, kModeId120}, + {FrameRateCategory::Low, true, 120_Hz, kModeId120}, {FrameRateCategory::Normal, true, 120_Hz, kModeId120}, {FrameRateCategory::High, true, 120_Hz, kModeId120}, }; @@ -2207,13 +2278,13 @@ TEST_P(RefreshRateSelectorTest, {FrameRateCategory::Default, false, 120_Hz}, // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate. {FrameRateCategory::NoPreference, false, 120_Hz}, - {FrameRateCategory::Low, false, 30_Hz}, + {FrameRateCategory::Low, false, 48_Hz}, {FrameRateCategory::Normal, false, 60_Hz}, {FrameRateCategory::High, false, 120_Hz}, {FrameRateCategory::Default, true, 120_Hz}, // TODO(b/266481656): Once this bug is fixed, NoPreference should be a lower frame rate. {FrameRateCategory::NoPreference, true, 120_Hz}, - {FrameRateCategory::Low, true, 30_Hz}, + {FrameRateCategory::Low, true, 48_Hz}, {FrameRateCategory::Normal, true, 60_Hz}, {FrameRateCategory::High, true, 120_Hz}, }; -- GitLab From 9d84eae592f9760b1985e628a59dc40a424717b4 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Wed, 12 Jun 2024 12:06:28 +1200 Subject: [PATCH 038/530] Unbitrot libvulkan's code generator The generator py scripts were broken when VKSC was released. Fix them and submit the updated autogenerated code. Bug: b/346650750 Flag: EXEMPT bugfix Test: ran the script after fixes Change-Id: I44352b052e5d018b91b327f1c8b3763146ed8fbe --- vulkan/libvulkan/api_gen.cpp | 11 ++-- vulkan/scripts/generator_common.py | 89 ++++++++++++++++++------------ vulkan/scripts/null_generator.py | 2 + 3 files changed, 64 insertions(+), 38 deletions(-) diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp index a9706bc871..a3fe33e67e 100644 --- a/vulkan/libvulkan/api_gen.cpp +++ b/vulkan/libvulkan/api_gen.cpp @@ -178,7 +178,7 @@ bool InitDispatchTable( INIT_PROC(false, instance, GetPhysicalDeviceExternalSemaphoreProperties); INIT_PROC(false, instance, GetPhysicalDeviceExternalFenceProperties); INIT_PROC(false, instance, EnumeratePhysicalDeviceGroups); - INIT_PROC_EXT(KHR_swapchain, false, instance, GetPhysicalDevicePresentRectanglesKHR); + INIT_PROC_EXT(KHR_swapchain, true, instance, GetPhysicalDevicePresentRectanglesKHR); INIT_PROC(false, instance, GetPhysicalDeviceToolProperties); // clang-format on @@ -325,9 +325,9 @@ bool InitDispatchTable( INIT_PROC(false, dev, BindBufferMemory2); INIT_PROC(false, dev, BindImageMemory2); INIT_PROC(false, dev, CmdSetDeviceMask); - INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupPresentCapabilitiesKHR); - INIT_PROC_EXT(KHR_swapchain, false, dev, GetDeviceGroupSurfacePresentModesKHR); - INIT_PROC_EXT(KHR_swapchain, false, dev, AcquireNextImage2KHR); + INIT_PROC_EXT(KHR_swapchain, true, dev, GetDeviceGroupPresentCapabilitiesKHR); + INIT_PROC_EXT(KHR_swapchain, true, dev, GetDeviceGroupSurfacePresentModesKHR); + INIT_PROC_EXT(KHR_swapchain, true, dev, AcquireNextImage2KHR); INIT_PROC(false, dev, CmdDispatchBase); INIT_PROC(false, dev, CreateDescriptorUpdateTemplate); INIT_PROC(false, dev, DestroyDescriptorUpdateTemplate); @@ -659,6 +659,8 @@ VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pNa "vkGetDrmDisplayEXT", "vkGetInstanceProcAddr", "vkGetPhysicalDeviceCalibrateableTimeDomainsEXT", + "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR", + "vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR", "vkGetPhysicalDeviceDisplayPlaneProperties2KHR", "vkGetPhysicalDeviceDisplayProperties2KHR", "vkGetPhysicalDeviceExternalBufferProperties", @@ -703,6 +705,7 @@ VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pNa "vkGetPhysicalDeviceToolProperties", "vkGetPhysicalDeviceToolPropertiesEXT", "vkGetPhysicalDeviceVideoCapabilitiesKHR", + "vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR", "vkGetPhysicalDeviceVideoFormatPropertiesKHR", "vkSubmitDebugUtilsMessageEXT", }; diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py index 866c1b7b75..6b4cbad2e2 100644 --- a/vulkan/scripts/generator_common.py +++ b/vulkan/scripts/generator_common.py @@ -351,9 +351,50 @@ def parse_vulkan_registry(): 'external', 'vulkan-headers', 'registry', 'vk.xml') tree = element_tree.parse(registry) root = tree.getroot() + + for exts in root.iter('extensions'): + for extension in exts.iter('extension'): + if 'vulkan' not in extension.get('supported').split(','): + # ANDROID_native_buffer is a weird special case -- it's declared in vk.xml as + # disabled but we _do_ want to generate plumbing for it in the Android loader. + if extension.get('name') != 'VK_ANDROID_native_buffer': + print('skip extension disabled or not for vulkan: ' + extension.get('name')) + continue + + apiversion = 'VK_VERSION_1_0' + if extension.tag == 'extension': + extname = extension.get('name') + if (extension.get('type') == 'instance' and + extension.get('promotedto') is not None): + promoted_inst_ext_dict[extname] = \ + version_2_api_version(extension.get('promotedto')) + for req in extension.iter('require'): + if req.get('feature') is not None: + apiversion = req.get('feature') + for commands in req: + if commands.tag == 'command': + cmd_name = commands.get('name') + if cmd_name not in extension_dict: + extension_dict[cmd_name] = extname + version_dict[cmd_name] = apiversion + + for feature in root.iter('feature'): + if 'vulkan' not in feature.get('api').split(','): + continue + + apiversion = feature.get('name') + for req in feature.iter('require'): + for command in req: + if command.tag == 'command': + cmd_name = command.get('name') + version_dict[cmd_name] = apiversion + for commands in root.iter('commands'): for command in commands: if command.tag == 'command': + if command.get('api') == 'vulkansc': + continue + parameter_list = [] protoset = False cmd_name = '' @@ -361,12 +402,18 @@ def parse_vulkan_registry(): if command.get('alias') is not None: alias = command.get('alias') cmd_name = command.get('name') - alias_dict[cmd_name] = alias - command_list.append(cmd_name) - param_dict[cmd_name] = param_dict[alias].copy() - return_type_dict[cmd_name] = return_type_dict[alias] + # At this stage all valid commands have been added to the version + # dict so we can use it to filter valid commands + if cmd_name in version_dict: + alias_dict[cmd_name] = alias + command_list.append(cmd_name) + param_dict[cmd_name] = param_dict[alias].copy() + return_type_dict[cmd_name] = return_type_dict[alias] for params in command: if params.tag == 'param': + if params.get('api') == 'vulkansc': + # skip SC-only param variant + continue param_type = '' if params.text is not None and params.text.strip(): param_type = params.text.strip() + ' ' @@ -387,39 +434,13 @@ def parse_vulkan_registry(): cmd_type = c.text if c.tag == 'name': cmd_name = c.text - protoset = True - command_list.append(cmd_name) - return_type_dict[cmd_name] = cmd_type + if cmd_name in version_dict: + protoset = True + command_list.append(cmd_name) + return_type_dict[cmd_name] = cmd_type if protoset: param_dict[cmd_name] = parameter_list.copy() - for exts in root.iter('extensions'): - for extension in exts: - apiversion = 'VK_VERSION_1_0' - if extension.tag == 'extension': - extname = extension.get('name') - if (extension.get('type') == 'instance' and - extension.get('promotedto') is not None): - promoted_inst_ext_dict[extname] = \ - version_2_api_version(extension.get('promotedto')) - for req in extension: - if req.get('feature') is not None: - apiversion = req.get('feature') - for commands in req: - if commands.tag == 'command': - cmd_name = commands.get('name') - if cmd_name not in extension_dict: - extension_dict[cmd_name] = extname - version_dict[cmd_name] = apiversion - - for feature in root.iter('feature'): - apiversion = feature.get('name') - for req in feature: - for command in req: - if command.tag == 'command': - cmd_name = command.get('name') - if cmd_name in command_list: - version_dict[cmd_name] = apiversion version_code_set = set() for version in version_dict.values(): diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py index e9faef663b..3624c1d032 100644 --- a/vulkan/scripts/null_generator.py +++ b/vulkan/scripts/null_generator.py @@ -89,6 +89,8 @@ def gen_cpp(): f.write(gencom.copyright_and_warning(2015)) f.write("""\ +#include + #include #include "null_driver_gen.h" -- GitLab From 290b072d6fd85a35675cfd26d225296fb2e2a2c6 Mon Sep 17 00:00:00 2001 From: Harry Cutts Date: Tue, 25 Jun 2024 15:20:07 +0000 Subject: [PATCH 039/530] InputDevice: clear absolute axis info if not found In change I57de645c889de53c8be0f9f8744a62e92fafdadb, getAbsoluteAxisInfo was modified to handle EventHub::getAbsoluteAxisInfo returning an optional. However, the old form of EventHub::getAbsoluteAxisInfo had the side effect of clearing the RawAbsoluteAxisInfo struct that it was passed a pointer to if the axis isn't present, crucially setting valid to false. To avoid a behaviour change due to the refactor, mimic that in InputDevice::getAbsoluteAxisInfo. Test: atest inputflinger_tests Test: m checkinput Bug: 245989146 Flag: EXEMPT refactor Change-Id: If32272f983139c2e9d5f1e548fb209c21d191180 --- services/inputflinger/reader/include/InputDevice.h | 1 + 1 file changed, 1 insertion(+) diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 7fd55973c7..086c26f5e2 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -308,6 +308,7 @@ public: inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const { std::optional info = mEventHub->getAbsoluteAxisInfo(mId, code); if (!info.has_value()) { + axisInfo->clear(); return NAME_NOT_FOUND; } *axisInfo = *info; -- GitLab From dd438e2a4b541fbe88b85346b450a1106b799109 Mon Sep 17 00:00:00 2001 From: Vladimir Komsiyski Date: Tue, 13 Feb 2024 11:47:54 +0100 Subject: [PATCH 040/530] Virtual rotary encoder native support - detect rotary encoder input devices if they have a single scroll axis and nothing else - make the rotary mapper display-aware as the virtual rotary is constrained to a single virtual display, just like the other virtual input devices Fix: 320328752 Test: atest inputflinger_tests Test: see CTS in topic Flag: android.companion.virtualdevice.flags.virtual_rotary Change-Id: I5581013d06708cbcc2c3ac8a622cd259aea8a9b4 --- include/input/VirtualInputDevice.h | 7 + libs/input/VirtualInputDevice.cpp | 11 ++ services/inputflinger/reader/Android.bp | 1 + services/inputflinger/reader/EventHub.cpp | 10 ++ .../mapper/RotaryEncoderInputMapper.cpp | 20 ++- .../reader/mapper/RotaryEncoderInputMapper.h | 1 + services/inputflinger/tests/Android.bp | 1 + .../tests/RotaryEncoderInputMapper_test.cpp | 169 ++++++++++++++++++ 8 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp diff --git a/include/input/VirtualInputDevice.h b/include/input/VirtualInputDevice.h index 222dac8557..9bbaa0c5ec 100644 --- a/include/input/VirtualInputDevice.h +++ b/include/input/VirtualInputDevice.h @@ -122,4 +122,11 @@ private: bool handleStylusUp(uint16_t tool, std::chrono::nanoseconds eventTime); }; +class VirtualRotaryEncoder : public VirtualInputDevice { +public: + VirtualRotaryEncoder(android::base::unique_fd fd); + virtual ~VirtualRotaryEncoder() override; + bool writeScrollEvent(float scrollAmount, std::chrono::nanoseconds eventTime); +}; + } // namespace android diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp index eea06f1720..b73ee65504 100644 --- a/libs/input/VirtualInputDevice.cpp +++ b/libs/input/VirtualInputDevice.cpp @@ -509,4 +509,15 @@ bool VirtualStylus::handleStylusUp(uint16_t tool, std::chrono::nanoseconds event return true; } +// --- VirtualRotaryEncoder --- +VirtualRotaryEncoder::VirtualRotaryEncoder(unique_fd fd) : VirtualInputDevice(std::move(fd)) {} + +VirtualRotaryEncoder::~VirtualRotaryEncoder() {} + +bool VirtualRotaryEncoder::writeScrollEvent(float scrollAmount, + std::chrono::nanoseconds eventTime) { + return writeInputEvent(EV_REL, REL_WHEEL, static_cast(scrollAmount), eventTime) && + writeInputEvent(EV_SYN, SYN_REPORT, 0, eventTime); +} + } // namespace android diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index e76b648ce5..b2f15b400d 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -78,6 +78,7 @@ cc_defaults { name: "libinputreader_defaults", srcs: [":libinputreader_sources"], shared_libs: [ + "android.companion.virtualdevice.flags-aconfig-cc-host", "libbase", "libcap", "libcrypto", diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index fe70a51b81..540f55d75d 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -33,6 +33,8 @@ #include #include +#include + #define LOG_TAG "EventHub" // #define LOG_NDEBUG 0 @@ -68,6 +70,8 @@ using android::base::StringPrintf; namespace android { +namespace vd_flags = android::companion::virtualdevice::flags; + using namespace ftl::flag_operators; static const char* DEVICE_INPUT_PATH = "/dev/input"; @@ -2503,6 +2507,12 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { } } + // See if the device is a rotary encoder with a single scroll axis and nothing else. + if (vd_flags::virtual_rotary() && device->classes == ftl::Flags(0) && + device->relBitmask.test(REL_WHEEL) && !device->relBitmask.test(REL_HWHEEL)) { + device->classes |= InputDeviceClass::ROTARY_ENCODER; + } + // If the device isn't recognized as something we handle, don't monitor it. if (device->classes == ftl::Flags(0)) { ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(), diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp index 27ff52fa65..20fd3598f7 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp @@ -84,12 +84,18 @@ std::list RotaryEncoderInputMapper::reconfigure(nsecs_t when, } } if (!changes.any() || changes.test(InputReaderConfiguration::Change::DISPLAY_INFO)) { - std::optional internalViewport = - config.getDisplayViewportByType(ViewportType::INTERNAL); - if (internalViewport) { - mOrientation = internalViewport->orientation; + if (getDeviceContext().getAssociatedViewport()) { + mDisplayId = getDeviceContext().getAssociatedViewport()->displayId; + mOrientation = getDeviceContext().getAssociatedViewport()->orientation; } else { - mOrientation = ui::ROTATION_0; + mDisplayId = ui::LogicalDisplayId::INVALID; + std::optional internalViewport = + config.getDisplayViewportByType(ViewportType::INTERNAL); + if (internalViewport) { + mOrientation = internalViewport->orientation; + } else { + mOrientation = ui::ROTATION_0; + } } } return out; @@ -124,8 +130,6 @@ std::list RotaryEncoderInputMapper::sync(nsecs_t when, nsecs_t readT // Send motion event. if (scrolled) { int32_t metaState = getContext()->getGlobalMetaState(); - // This is not a pointer, so it's not associated with a display. - ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID; if (mOrientation == ui::ROTATION_180) { scroll = -scroll; @@ -147,7 +151,7 @@ std::list RotaryEncoderInputMapper::sync(nsecs_t when, nsecs_t readT out.push_back( NotifyMotionArgs(getContext()->getNextId(), when, readTime, getDeviceId(), mSource, - displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, + mDisplayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /*buttonState=*/0, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION, diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h index 14c540bf6e..7e804150b1 100644 --- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h +++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.h @@ -47,6 +47,7 @@ private: int32_t mSource; float mScalingFactor; ui::Rotation mOrientation; + ui::LogicalDisplayId mDisplayId = ui::LogicalDisplayId::INVALID; std::unique_ptr mSlopController; explicit RotaryEncoderInputMapper(InputDeviceContext& deviceContext, diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index cf0d46a75d..bddf43e344 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -76,6 +76,7 @@ cc_test { "PointerChoreographer_test.cpp", "PreferStylusOverTouch_test.cpp", "PropertyProvider_test.cpp", + "RotaryEncoderInputMapper_test.cpp", "SlopController_test.cpp", "SyncQueue_test.cpp", "TimerProvider_test.cpp", diff --git a/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp new file mode 100644 index 0000000000..94cfc3274b --- /dev/null +++ b/services/inputflinger/tests/RotaryEncoderInputMapper_test.cpp @@ -0,0 +1,169 @@ +/* + * Copyright 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. + */ + +#include "RotaryEncoderInputMapper.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "InputMapperTest.h" +#include "InputReaderBase.h" +#include "InterfaceMocks.h" +#include "NotifyArgs.h" +#include "TestEventMatchers.h" +#include "ui/Rotation.h" + +#define TAG "RotaryEncoderInputMapper_test" + +namespace android { + +using testing::AllOf; +using testing::Return; +using testing::VariantWith; +constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT; +constexpr ui::LogicalDisplayId SECONDARY_DISPLAY_ID = ui::LogicalDisplayId{DISPLAY_ID.val() + 1}; +constexpr int32_t DISPLAY_WIDTH = 480; +constexpr int32_t DISPLAY_HEIGHT = 800; + +namespace { + +DisplayViewport createViewport() { + DisplayViewport v; + v.orientation = ui::Rotation::Rotation0; + v.logicalRight = DISPLAY_HEIGHT; + v.logicalBottom = DISPLAY_WIDTH; + v.physicalRight = DISPLAY_HEIGHT; + v.physicalBottom = DISPLAY_WIDTH; + v.deviceWidth = DISPLAY_HEIGHT; + v.deviceHeight = DISPLAY_WIDTH; + v.isActive = true; + return v; +} + +DisplayViewport createPrimaryViewport() { + DisplayViewport v = createViewport(); + v.displayId = DISPLAY_ID; + v.uniqueId = "local:1"; + return v; +} + +DisplayViewport createSecondaryViewport() { + DisplayViewport v = createViewport(); + v.displayId = SECONDARY_DISPLAY_ID; + v.uniqueId = "local:2"; + v.type = ViewportType::EXTERNAL; + return v; +} + +/** + * A fake InputDeviceContext that allows the associated viewport to be specified for the mapper. + * + * This is currently necessary because InputMapperUnitTest doesn't register the mappers it creates + * with the InputDevice object, meaning that InputDevice::isIgnored becomes true, and the input + * device doesn't set its associated viewport when it's configured. + * + * TODO(b/319217713): work out a way to avoid this fake. + */ +class ViewportFakingInputDeviceContext : public InputDeviceContext { +public: + ViewportFakingInputDeviceContext(InputDevice& device, int32_t eventHubId, + std::optional viewport) + : InputDeviceContext(device, eventHubId), mAssociatedViewport(viewport) {} + + ViewportFakingInputDeviceContext(InputDevice& device, int32_t eventHubId) + : ViewportFakingInputDeviceContext(device, eventHubId, createPrimaryViewport()) {} + + std::optional getAssociatedViewport() const override { + return mAssociatedViewport; + } + + void setViewport(const std::optional& viewport) { + mAssociatedViewport = viewport; + } + +private: + std::optional mAssociatedViewport; +}; + +} // namespace + +/** + * Unit tests for RotaryEncoderInputMapper. + */ +class RotaryEncoderInputMapperTest : public InputMapperUnitTest { +protected: + void SetUp() override { SetUpWithBus(BUS_USB); } + void SetUpWithBus(int bus) override { + InputMapperUnitTest::SetUpWithBus(bus); + + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_WHEEL)) + .WillRepeatedly(Return(true)); + EXPECT_CALL(mMockEventHub, hasRelativeAxis(EVENTHUB_ID, REL_HWHEEL)) + .WillRepeatedly(Return(false)); + } +}; + +TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdWithAssociatedViewport) { + DisplayViewport primaryViewport = createPrimaryViewport(); + DisplayViewport secondaryViewport = createSecondaryViewport(); + mReaderConfiguration.setDisplayViewports({primaryViewport, secondaryViewport}); + + // Set up the secondary display as the associated viewport of the mapper. + createDevice(); + ViewportFakingInputDeviceContext deviceContext(*mDevice, EVENTHUB_ID, secondaryViewport); + mMapper = createInputMapper(deviceContext, mReaderConfiguration); + + std::list args; + // Ensure input events are generated for the secondary display. + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + EXPECT_THAT(args, + ElementsAre(VariantWith( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithSource(AINPUT_SOURCE_ROTARY_ENCODER), + WithDisplayId(SECONDARY_DISPLAY_ID))))); +} + +TEST_F(RotaryEncoderInputMapperTest, ConfigureDisplayIdNoAssociatedViewport) { + // Set up the default display. + mFakePolicy->clearViewports(); + mFakePolicy->addDisplayViewport(createPrimaryViewport()); + + // Set up the mapper with no associated viewport. + createDevice(); + mMapper = createInputMapper(*mDeviceContext, mReaderConfiguration); + + // Ensure input events are generated without display ID + std::list args; + args += process(ARBITRARY_TIME, EV_REL, REL_WHEEL, 1); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + EXPECT_THAT(args, + ElementsAre(VariantWith( + AllOf(WithMotionAction(AMOTION_EVENT_ACTION_SCROLL), + WithSource(AINPUT_SOURCE_ROTARY_ENCODER), + WithDisplayId(ui::LogicalDisplayId::INVALID))))); +} + +} // namespace android \ No newline at end of file -- GitLab From b6ddf525be3c2abbde59ae1533494b18a7961087 Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Mon, 24 Jun 2024 18:56:08 -0500 Subject: [PATCH 041/530] Fix DisplayState sanitization. Bug: 347307756 Flag: EXEMPT bugfix Test: CredentialsTest Change-Id: I500ff9a5bd356845e2d0be4d1430448f448c4e8a --- libs/gui/ISurfaceComposer.cpp | 2 +- libs/gui/SurfaceComposerClient.cpp | 3 +- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../surfaceflinger/tests/Credentials_test.cpp | 53 ++++++++++++++++++- .../tests/unittests/TestableSurfaceFlinger.h | 2 +- 8 files changed, 61 insertions(+), 9 deletions(-) diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ff6b558d41..269936858a 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -62,7 +62,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index af91bb3ae2..5db539497c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1059,7 +1059,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.token = BufferCache::getInstance().getToken(); uncacheBuffer.id = cacheId; Vector composerStates; - status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {}, + Vector displayStates; + status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates, ISurfaceComposer::eOneWay, Transaction::getDefaultApplyToken(), {}, systemTime(), true, {uncacheBuffer}, false, {}, generateId(), {}); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index eb4a802c17..1ecc216dff 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -112,7 +112,7 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 43cd0f8a7f..5e91088378 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -636,7 +636,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& /*frameTimelineInfo*/, Vector& /*state*/, - const Vector& /*displays*/, uint32_t /*flags*/, + Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/, int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const std::vector& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 596ec12d9e..f9262a0a9c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5167,7 +5167,7 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t nu status_t SurfaceFlinger::setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, @@ -5182,7 +5182,7 @@ status_t SurfaceFlinger::setTransactionState( composerState.state.sanitize(permissions); } - for (DisplayState display : displays) { + for (DisplayState& display : displays) { display.sanitize(permissions); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ee541c4364..7762bbea9f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -559,7 +559,7 @@ private: sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const; status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index ebe11fb0f3..d355e720d1 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -276,7 +277,7 @@ TEST_F(CredentialsTest, CreateDisplayTest) { TEST_F(CredentialsTest, CaptureLayersTest) { setupBackgroundSurface(); sp outBuffer; - std::function condition = [=]() { + std::function condition = [=, this]() { LayerCaptureArgs captureArgs; captureArgs.layerHandle = mBGSurfaceControl->getHandle(); captureArgs.sourceCrop = {0, 0, 1, 1}; @@ -396,6 +397,56 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { } } +TEST_F(CredentialsTest, DisplayTransactionPermissionTest) { + const auto display = getFirstDisplayToken(); + + ui::DisplayState displayState; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + const ui::Rotation initialOrientation = displayState.orientation; + + // Set display orientation from an untrusted process. This should fail silently. + { + UIDFaker f{AID_BIN}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did not change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); + + // Set display orientation from a trusted process. + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation + ui::ROTATION_90, displayState.orientation); + + // Reset orientation + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation, layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 007383b3d9..7d1ec253c4 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -528,7 +528,7 @@ public: auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, std::vector& listenerCallbacks, -- GitLab From 77c511c4d546227e768d7594840a4845b11e7756 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Mon, 24 Jun 2024 21:55:46 +0000 Subject: [PATCH 042/530] Support per-layer color transforms when local tonemapping * Preserve alpha channel when tonemapping * Don't tonemap when a layer is entirely SDR Bug: 329464641 Flag: com.android.graphics.surfaceflinger.flags.local_tonemap_screenshots Test: adb shell cmd color_display set-layer-saturation 0 com.google.android.apps.wellbeing com.google.android.youtube Change-Id: I363475caac5af83f2ef30bc073cf8c5aa6e313d4 --- libs/renderengine/skia/SkiaRenderEngine.cpp | 44 ++++++++++++--------- libs/renderengine/skia/filters/MouriMap.cpp | 4 +- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index e62640eb85..c39da958e8 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -514,7 +514,7 @@ sk_sp SkiaRenderEngine::createRuntimeEffectShader( auto shader = parameters.shader; if (stretchEffect.hasEffect()) { const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; - if (graphicBuffer && parameters.shader) { + if (graphicBuffer && shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); } } @@ -525,21 +525,25 @@ sk_sp SkiaRenderEngine::createRuntimeEffectShader( static_cast(targetBuffer->getPixelFormat())) : std::nullopt; - if (parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local) { - // TODO: Handle color matrix transforms in linear space. - SkImage* image = parameters.shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr); - if (image) { - static MouriMap kMapper; - const float ratio = getHdrRenderType(parameters.layer.sourceDataspace, format) == - HdrRenderType::GENERIC_HDR - ? 1.0f - : parameters.layerDimmingRatio; - return kMapper.mouriMap(getActiveContext(), parameters.shader, ratio); - } + const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format); + + const auto usingLocalTonemap = + parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local && + hdrType != HdrRenderType::SDR && + shader->isAImage((SkMatrix*)nullptr, (SkTileMode*)nullptr); + + if (usingLocalTonemap) { + static MouriMap kMapper; + const float ratio = + hdrType == HdrRenderType::GENERIC_HDR ? 1.0f : parameters.layerDimmingRatio; + shader = kMapper.mouriMap(getActiveContext(), shader, ratio); } + // disable tonemapping if we already locally tonemapped + auto inputDataspace = + usingLocalTonemap ? parameters.outputDataSpace : parameters.layer.sourceDataspace; auto effect = - shaders::LinearEffect{.inputDataspace = parameters.layer.sourceDataspace, + shaders::LinearEffect{.inputDataspace = inputDataspace, .outputDataspace = parameters.outputDataSpace, .undoPremultipliedAlpha = parameters.undoPremultipliedAlpha, .fakeOutputDataspace = parameters.fakeOutputDataspace}; @@ -555,20 +559,22 @@ sk_sp SkiaRenderEngine::createRuntimeEffectShader( mat4 colorTransform = parameters.layer.colorTransform; - colorTransform *= - mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio, - parameters.layerDimmingRatio, 1.f)); + if (!usingLocalTonemap) { + colorTransform *= + mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio, + parameters.layerDimmingRatio, 1.f)); + } const auto targetBuffer = parameters.layer.source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; const auto hardwareBuffer = graphicBuffer ? graphicBuffer->toAHardwareBuffer() : nullptr; - return createLinearEffectShader(parameters.shader, effect, runtimeEffect, - std::move(colorTransform), parameters.display.maxLuminance, + return createLinearEffectShader(shader, effect, runtimeEffect, std::move(colorTransform), + parameters.display.maxLuminance, parameters.display.currentLuminanceNits, parameters.layer.source.buffer.maxLuminanceNits, hardwareBuffer, parameters.display.renderIntent); } - return parameters.shader; + return shader; } void SkiaRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) { diff --git a/libs/renderengine/skia/filters/MouriMap.cpp b/libs/renderengine/skia/filters/MouriMap.cpp index 7d8b8a5116..cc25fcc5b9 100644 --- a/libs/renderengine/skia/filters/MouriMap.cpp +++ b/libs/renderengine/skia/filters/MouriMap.cpp @@ -84,13 +84,13 @@ const SkString kTonemap(R"( float3 linear = toLinearSrgb(rgba.rgb) * hdrSdrRatio; if (localMax <= 1.0) { - return float4(fromLinearSrgb(linear), 1.0); + return float4(fromLinearSrgb(linear), rgba.a); } float maxRGB = max(linear.r, max(linear.g, linear.b)); localMax = max(localMax, maxRGB); float gain = (1 + maxRGB / (localMax * localMax)) / (1 + maxRGB); - return float4(fromLinearSrgb(linear * gain), 1.0); + return float4(fromLinearSrgb(linear * gain), rgba.a); } )"); -- GitLab From a32eadee7c1fd1612140c4148600eff2d61c6975 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 25 Jun 2024 23:20:51 +0000 Subject: [PATCH 043/530] Use dimming ratio when detecting hdr type for local TMO ...otherwise UltraHDR isn't counted as HDR, which then disables tonemapping to SDR. Bug: 329464641 Flag: com.android.graphics.surfaceflinger.flags.local_tonemap_screenshots Test: screenshot Chrome showing an HDR image Change-Id: I71febc9ef3477938deb4cb904a464f3ab4e598f9 --- libs/renderengine/skia/SkiaRenderEngine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index c39da958e8..5f37125d16 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -525,7 +525,8 @@ sk_sp SkiaRenderEngine::createRuntimeEffectShader( static_cast(targetBuffer->getPixelFormat())) : std::nullopt; - const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format); + const auto hdrType = getHdrRenderType(parameters.layer.sourceDataspace, format, + parameters.layerDimmingRatio); const auto usingLocalTonemap = parameters.display.tonemapStrategy == DisplaySettings::TonemapStrategy::Local && -- GitLab From 0d1a417b3909cb91c2642e7ec628ac358779b510 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 25 Jun 2024 23:41:14 +0000 Subject: [PATCH 044/530] Add tests that exercise MouriMap in RenderEngineTest Bug: 329464641 Flag: TEST_ONLY Test: librenderengine_test Change-Id: I9163ae0e7be239bfbcc8a6e4a277ea1dcd655995 --- libs/renderengine/tests/RenderEngineTest.cpp | 208 +++++++++++++++++++ 1 file changed, 208 insertions(+) diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index a8a98236e2..032413570a 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -3147,6 +3147,214 @@ TEST_P(RenderEngineTest, r8_respects_color_transform_when_device_handles) { expectBufferColor(Rect(0, 0, 1, 1), 0, 70, 0, 255); } +TEST_P(RenderEngineTest, localTonemap_preservesFullscreenSdr) { + if (!GetParam()->apiSupported()) { + GTEST_SKIP(); + } + + initializeRenderEngine(); + + mBuffer = std::make_shared< + renderengine::impl:: + ExternalTexture>(sp::make(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE, + "output"), + *mRE, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); + ASSERT_EQ(0, mBuffer->getBuffer()->initCheck()); + + const auto whiteBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(51, 51, 51, 255)); + + const auto rect = Rect(0, 0, 1, 1); + const renderengine::DisplaySettings display{ + .physicalDisplay = rect, + .clip = rect, + .outputDataspace = ui::Dataspace::SRGB, + .targetLuminanceNits = 40, + .tonemapStrategy = renderengine::DisplaySettings::TonemapStrategy::Local, + }; + + const renderengine::LayerSettings whiteLayer{ + .geometry.boundaries = rect.toFloatRect(), + .source = + renderengine::PixelSource{ + .buffer = + renderengine::Buffer{ + .buffer = whiteBuffer, + }, + }, + .alpha = 1.0f, + .sourceDataspace = ui::Dataspace::V0_SCRGB_LINEAR, + .whitePointNits = 200, + }; + + std::vector layers{whiteLayer}; + invokeDraw(display, layers); + + expectBufferColor(Rect(0, 0, 1, 1), 255, 255, 255, 255); +} + +TEST_P(RenderEngineTest, localTonemap_preservesFarawaySdrRegions) { + if (!GetParam()->apiSupported()) { + GTEST_SKIP(); + } + + initializeRenderEngine(); + + const auto blockWidth = 256; + const auto width = blockWidth * 4; + + const auto buffer = allocateSourceBuffer(width, 1); + + mBuffer = std::make_shared< + renderengine::impl:: + ExternalTexture>(sp::make(width, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE, + "output"), + *mRE, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); + + { + uint8_t* pixels; + buffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); + uint8_t* dst = pixels; + for (uint32_t i = 0; i < width; i++) { + uint8_t value = 0; + if (i < blockWidth) { + value = 51; + } else if (i >= blockWidth * 3) { + value = 255; + } + dst[0] = value; + dst[1] = value; + dst[2] = value; + dst[3] = 255; + dst += 4; + } + buffer->getBuffer()->unlock(); + } + + const auto rect = Rect(0, 0, width, 1); + const renderengine::DisplaySettings display{ + .physicalDisplay = rect, + .clip = rect, + .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, + .targetLuminanceNits = 40, + .tonemapStrategy = renderengine::DisplaySettings::TonemapStrategy::Local, + }; + + const renderengine::LayerSettings whiteLayer{ + .geometry.boundaries = rect.toFloatRect(), + .source = + renderengine::PixelSource{ + .buffer = + renderengine::Buffer{ + .buffer = buffer, + }, + }, + .alpha = 1.0f, + .sourceDataspace = ui::Dataspace::V0_SCRGB_LINEAR, + .whitePointNits = 200, + }; + + std::vector layers{whiteLayer}; + invokeDraw(display, layers); + + // SDR regions are boosted to preserve SDR detail. + expectBufferColor(Rect(0, 0, blockWidth, 1), 255, 255, 255, 255); + expectBufferColor(Rect(blockWidth, 0, blockWidth * 2, 1), 0, 0, 0, 255); + expectBufferColor(Rect(blockWidth * 2, 0, blockWidth * 3, 1), 0, 0, 0, 255); + expectBufferColor(Rect(blockWidth * 3, 0, blockWidth * 4, 1), 255, 255, 255, 255); +} + +TEST_P(RenderEngineTest, localTonemap_tonemapsNearbySdrRegions) { + if (!GetParam()->apiSupported()) { + GTEST_SKIP(); + } + + initializeRenderEngine(); + + const auto blockWidth = 2; + const auto width = blockWidth * 2; + + mBuffer = std::make_shared< + renderengine::impl:: + ExternalTexture>(sp::make(width, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE, + "output"), + *mRE, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); + + const auto buffer = allocateSourceBuffer(width, 1); + + { + uint8_t* pixels; + buffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); + uint8_t* dst = pixels; + for (uint32_t i = 0; i < width; i++) { + uint8_t value = 0; + if (i < blockWidth) { + value = 51; + } else if (i >= blockWidth) { + value = 255; + } + dst[0] = value; + dst[1] = value; + dst[2] = value; + dst[3] = 255; + dst += 4; + } + buffer->getBuffer()->unlock(); + } + + const auto rect = Rect(0, 0, width, 1); + const renderengine::DisplaySettings display{ + .physicalDisplay = rect, + .clip = rect, + .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, + .targetLuminanceNits = 40, + .tonemapStrategy = renderengine::DisplaySettings::TonemapStrategy::Local, + }; + + const renderengine::LayerSettings whiteLayer{ + .geometry.boundaries = rect.toFloatRect(), + .source = + renderengine::PixelSource{ + .buffer = + renderengine::Buffer{ + .buffer = buffer, + }, + }, + .alpha = 1.0f, + .sourceDataspace = ui::Dataspace::V0_SCRGB_LINEAR, + .whitePointNits = 200, + }; + + std::vector layers{whiteLayer}; + invokeDraw(display, layers); + + // SDR regions remain "dimmed", but preserve detail with a roll-off curve. + expectBufferColor(Rect(0, 0, blockWidth, 1), 132, 132, 132, 255, 2); + // HDR regions are not dimmed. + expectBufferColor(Rect(blockWidth, 0, blockWidth * 2, 1), 255, 255, 255, 255); +} + TEST_P(RenderEngineTest, primeShaderCache) { // TODO: b/331447071 - Fix in Graphite and re-enable. if (GetParam()->skiaBackend() == renderengine::RenderEngine::SkiaBackend::GRAPHITE) { -- GitLab From c0945310adf96d38a6c8d3319ff2180e3afd8442 Mon Sep 17 00:00:00 2001 From: Sam Dubey Date: Tue, 11 Jun 2024 14:42:12 +0000 Subject: [PATCH 045/530] Add inputflinger unit tests to device-platinum-tests suite Change-Id: Ia5de14f81e5050efe224a3bed5bfd2cb58f6af57 --- services/inputflinger/tests/Android.bp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index cf0d46a75d..bea457bcde 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -115,5 +115,8 @@ cc_test { test_options: { unit_test: true, }, - test_suites: ["device-tests"], + test_suites: [ + "device-tests", + "device-platinum-tests", + ], } -- GitLab From ba5fda62ea1a01dbf388dda63f9fcf2c4ea448bd Mon Sep 17 00:00:00 2001 From: Frederick Mayle Date: Fri, 3 May 2024 16:04:56 -0700 Subject: [PATCH 046/530] libbinder: simpler scope_guard implementation libbinder_on_trusty_mock size: 289,374 -> 286,533 bytes Bug: 338458975 Test: TH Change-Id: I9fc817ba09c8697fb8b5f566cec28f15b6e7ea5d --- libs/binder/include/binder/Functional.h | 35 ++++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/libs/binder/include/binder/Functional.h b/libs/binder/include/binder/Functional.h index 08e3b214da..bb0e5f4115 100644 --- a/libs/binder/include/binder/Functional.h +++ b/libs/binder/include/binder/Functional.h @@ -17,10 +17,37 @@ #pragma once #include -#include +#include namespace android::binder::impl { +template +class scope_guard; + +template +scope_guard make_scope_guard(F f); + +template +class scope_guard { +public: + inline ~scope_guard() { + if (f_.has_value()) std::move(f_.value())(); + } + inline void release() { f_.reset(); } + +private: + friend scope_guard android::binder::impl::make_scope_guard(F); + + inline scope_guard(F&& f) : f_(std::move(f)) {} + + std::optional f_; +}; + +template +inline scope_guard make_scope_guard(F f) { + return scope_guard(std::move(f)); +} + template constexpr void assert_small_callable() { // While this buffer (std::function::__func::__buf_) is an implementation detail generally not @@ -32,12 +59,6 @@ constexpr void assert_small_callable() { "Try using std::ref, but make sure lambda lives long enough to be called."); } -template -std::unique_ptr> make_scope_guard(F&& f) { - assert_small_callable(); - return {reinterpret_cast(true), std::bind(f)}; -} - template class SmallFunction : public std::function { public: -- GitLab From 4e8200dec484fd6e5873f2a89c0b314467034eef Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Wed, 26 Jun 2024 19:47:18 +0000 Subject: [PATCH 047/530] Fix DisplayState sanitization. Bug: 347307756 Flag: EXEMPT bugfix Test: CredentialsTest Change-Id: I500ff9a5bd356845e2d0be4d1430448f448c4e8a (cherry picked from commit b6ddf525be3c2abbde59ae1533494b18a7961087) Merged-In: I500ff9a5bd356845e2d0be4d1430448f448c4e8a --- libs/gui/ISurfaceComposer.cpp | 2 +- libs/gui/SurfaceComposerClient.cpp | 3 +- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 2 +- .../surfaceflinger/tests/Credentials_test.cpp | 51 +++++++++++++++++++ .../tests/unittests/TestableSurfaceFlinger.h | 2 +- 9 files changed, 61 insertions(+), 9 deletions(-) diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index b526a6c92c..fc619c32ed 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -61,7 +61,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0fda358b63..4c561cc26f 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1047,7 +1047,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.token = BufferCache::getInstance().getToken(); uncacheBuffer.id = cacheId; Vector composerStates; - status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {}, + Vector displayStates; + status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates, ISurfaceComposer::eOneWay, Transaction::getDefaultApplyToken(), {}, systemTime(), true, {uncacheBuffer}, false, {}, generateId(), {}); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3ff6735926..2790167191 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -113,7 +113,7 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 8d7cf07b96..d351e28ca9 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -697,7 +697,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& /*frameTimelineInfo*/, Vector& /*state*/, - const Vector& /*displays*/, uint32_t /*flags*/, + Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/, int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const std::vector& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d606788053..e90b66ec8d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4502,7 +4502,7 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const sp& layer, const layer_s status_t SurfaceFlinger::setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, @@ -4517,7 +4517,7 @@ status_t SurfaceFlinger::setTransactionState( composerState.state.sanitize(permissions); } - for (DisplayState display : displays) { + for (DisplayState& display : displays) { display.sanitize(permissions); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d4700a4e25..aa2f074191 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -517,7 +517,7 @@ private: sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const; status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 4d03be04b3..f05b9e6633 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -739,7 +739,7 @@ public: auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 2d18166da5..0599858f8e 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,56 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { } } +TEST_F(CredentialsTest, DisplayTransactionPermissionTest) { + const auto display = getFirstDisplayToken(); + + ui::DisplayState displayState; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + const ui::Rotation initialOrientation = displayState.orientation; + + // Set display orientation from an untrusted process. This should fail silently. + { + UIDFaker f{AID_BIN}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did not change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); + + // Set display orientation from a trusted process. + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation + ui::ROTATION_90, displayState.orientation); + + // Reset orientation + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation, layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 945e48842d..2464f53d95 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -468,7 +468,7 @@ public: auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, std::vector& listenerCallbacks, -- GitLab From 9c7a1f541f020b66dbf02e3de78cf04437572d2c Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Wed, 26 Jun 2024 19:50:41 +0000 Subject: [PATCH 048/530] Fix DisplayState sanitization. Bug: 347307756 Flag: EXEMPT bugfix Test: CredentialsTest Change-Id: I500ff9a5bd356845e2d0be4d1430448f448c4e8a (cherry picked from commit b6ddf525be3c2abbde59ae1533494b18a7961087) Merged-In: I500ff9a5bd356845e2d0be4d1430448f448c4e8a --- libs/gui/ISurfaceComposer.cpp | 2 +- libs/gui/SurfaceComposerClient.cpp | 3 +- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../fuzzer/surfaceflinger_fuzzers_utils.h | 2 +- .../surfaceflinger/tests/Credentials_test.cpp | 51 +++++++++++++++++++ .../tests/unittests/TestableSurfaceFlinger.h | 2 +- 9 files changed, 61 insertions(+), 9 deletions(-) diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ff6b558d41..269936858a 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -62,7 +62,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands commands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 861fdc40eb..b6dd6f701f 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1047,7 +1047,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.token = BufferCache::getInstance().getToken(); uncacheBuffer.id = cacheId; Vector composerStates; - status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, {}, + Vector displayStates; + status_t status = sf->setTransactionState(FrameTimelineInfo{}, composerStates, displayStates, ISurfaceComposer::eOneWay, Transaction::getDefaultApplyToken(), {}, systemTime(), true, {uncacheBuffer}, false, {}, generateId(), {}); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index a836f4642a..c46fa4dc10 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -113,7 +113,7 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 8cb07da91d..70b61d46ce 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -701,7 +701,7 @@ public: status_t setTransactionState( const FrameTimelineInfo& /*frameTimelineInfo*/, Vector& /*state*/, - const Vector& /*displays*/, uint32_t /*flags*/, + Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, InputWindowCommands /*inputWindowCommands*/, int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const std::vector& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5dbb39d855..047714347a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4498,7 +4498,7 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const sp& layer, const layer_s status_t SurfaceFlinger::setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, @@ -4513,7 +4513,7 @@ status_t SurfaceFlinger::setTransactionState( composerState.state.sanitize(permissions); } - for (DisplayState display : displays) { + for (DisplayState& display : displays) { display.sanitize(permissions); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index fd897b2d28..58966e6d57 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -523,7 +523,7 @@ private: sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const; status_t setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, InputWindowCommands inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 649df56e65..36a3e2eae8 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -743,7 +743,7 @@ public: auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 2d18166da5..0599858f8e 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,56 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { } } +TEST_F(CredentialsTest, DisplayTransactionPermissionTest) { + const auto display = getFirstDisplayToken(); + + ui::DisplayState displayState; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + const ui::Rotation initialOrientation = displayState.orientation; + + // Set display orientation from an untrusted process. This should fail silently. + { + UIDFaker f{AID_BIN}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did not change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); + + // Set display orientation from a trusted process. + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation + ui::ROTATION_90, + layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + + // Verify that the display orientation did change. + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation + ui::ROTATION_90, displayState.orientation); + + // Reset orientation + { + UIDFaker f{AID_SYSTEM}; + Transaction transaction; + Rect layerStackRect; + Rect displayRect; + transaction.setDisplayProjection(display, initialOrientation, layerStackRect, displayRect); + transaction.apply(/*synchronous=*/true); + } + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayState(display, &displayState)); + ASSERT_EQ(initialOrientation, displayState.orientation); +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 6b13c0ddaf..f233a2573f 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -503,7 +503,7 @@ public: auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, - const Vector& displays, uint32_t flags, const sp& applyToken, + Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, std::vector& listenerCallbacks, -- GitLab From 0c25e864701a6c408b90709493dd30de9b929e2e Mon Sep 17 00:00:00 2001 From: Paul Ramirez Date: Tue, 18 Jun 2024 21:33:33 +0000 Subject: [PATCH 049/530] Return message wrapped in Result from receiveMessage Changed receivedMessaged return type from status_t to android::base::Result<>. Enforces checking valid state before using the object. Flag: EXEMPT refactor Bug: 297226446 Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST Change-Id: Ic2285d38a2d0d2227c1fae92379270a5f52586c7 --- include/input/InputTransport.h | 2 +- libs/input/InputConsumer.cpp | 15 +++--- libs/input/InputConsumerNoResampling.cpp | 60 ++++++++++++------------ libs/input/InputTransport.cpp | 38 ++++++++------- libs/input/tests/InputChannel_test.cpp | 33 +++++++------ 5 files changed, 78 insertions(+), 70 deletions(-) diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 6548810ca8..b26a194a0e 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -275,7 +275,7 @@ public: * Return DEAD_OBJECT if the channel's peer has been closed. * Other errors probably indicate that the channel is broken. */ - status_t receiveMessage(InputMessage* msg); + android::base::Result receiveMessage(); /* Tells whether there is a message in the channel available to be received. * diff --git a/libs/input/InputConsumer.cpp b/libs/input/InputConsumer.cpp index fcf490d5f9..dce528f763 100644 --- a/libs/input/InputConsumer.cpp +++ b/libs/input/InputConsumer.cpp @@ -235,8 +235,9 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consum mMsgDeferred = false; } else { // Receive a fresh message. - status_t result = mChannel->receiveMessage(&mMsg); - if (result == OK) { + android::base::Result result = mChannel->receiveMessage(); + if (result.ok()) { + mMsg = std::move(result.value()); const auto [_, inserted] = mConsumeTimes.emplace(mMsg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC)); LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32, @@ -244,11 +245,11 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consum // Trace the event processing timeline - event was just read from the socket ATRACE_ASYNC_BEGIN(mProcessingTraceTag.c_str(), /*cookie=*/mMsg.header.seq); - } - if (result) { + } else { // Consume the next batched event unless batches are being held for later. - if (consumeBatches || result != WOULD_BLOCK) { - result = consumeBatch(factory, frameTime, outSeq, outEvent); + if (consumeBatches || result.error().code() != WOULD_BLOCK) { + result = android::base::Error( + consumeBatch(factory, frameTime, outSeq, outEvent)); if (*outEvent) { ALOGD_IF(DEBUG_TRANSPORT_CONSUMER, "channel '%s' consumer ~ consumed batch event, seq=%u", @@ -256,7 +257,7 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consum break; } } - return result; + return result.error().code(); } } diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp index 15d992f9f3..e193983d9a 100644 --- a/libs/input/InputConsumerNoResampling.cpp +++ b/libs/input/InputConsumerNoResampling.cpp @@ -362,36 +362,36 @@ void InputConsumerNoResampling::handleMessages(std::vector&& messa std::vector InputConsumerNoResampling::readAllMessages() { std::vector messages; while (true) { - InputMessage msg; - status_t result = mChannel->receiveMessage(&msg); - switch (result) { - case OK: { - const auto [_, inserted] = - mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC)); - LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32, - msg.header.seq); - - // Trace the event processing timeline - event was just read from the socket - // TODO(b/329777420): distinguish between multiple instances of InputConsumer - // in the same process. - ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq); - messages.push_back(msg); - break; - } - case WOULD_BLOCK: { - return messages; - } - case DEAD_OBJECT: { - LOG(FATAL) << "Got a dead object for " << mChannel->getName(); - break; - } - case BAD_VALUE: { - LOG(FATAL) << "Got a bad value for " << mChannel->getName(); - break; - } - default: { - LOG(FATAL) << "Unexpected error: " << result; - break; + android::base::Result result = mChannel->receiveMessage(); + if (result.ok()) { + const InputMessage& msg = *result; + const auto [_, inserted] = + mConsumeTimes.emplace(msg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC)); + LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32, + msg.header.seq); + + // Trace the event processing timeline - event was just read from the socket + // TODO(b/329777420): distinguish between multiple instances of InputConsumer + // in the same process. + ATRACE_ASYNC_BEGIN("InputConsumer processing", /*cookie=*/msg.header.seq); + messages.push_back(msg); + } else { // !result.ok() + switch (result.error().code()) { + case WOULD_BLOCK: { + return messages; + } + case DEAD_OBJECT: { + LOG(FATAL) << "Got a dead object for " << mChannel->getName(); + break; + } + case BAD_VALUE: { + LOG(FATAL) << "Got a bad value for " << mChannel->getName(); + break; + } + default: { + LOG(FATAL) << "Unexpected error: " << result.error().message(); + break; + } } } } diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 47b422857e..bac681df85 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -424,10 +424,11 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { return OK; } -status_t InputChannel::receiveMessage(InputMessage* msg) { +android::base::Result InputChannel::receiveMessage() { ssize_t nRead; + InputMessage msg; do { - nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT); + nRead = ::recv(getFd(), &msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { @@ -435,36 +436,36 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed, errno=%d", name.c_str(), errno); if (error == EAGAIN || error == EWOULDBLOCK) { - return WOULD_BLOCK; + return android::base::Error(WOULD_BLOCK); } if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) { - return DEAD_OBJECT; + return android::base::Error(DEAD_OBJECT); } - return -error; + return android::base::Error(-error); } if (nRead == 0) { // check for EOF ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed because peer was closed", name.c_str()); - return DEAD_OBJECT; + return android::base::Error(DEAD_OBJECT); } - if (!msg->isValid(nRead)) { + if (!msg.isValid(nRead)) { ALOGE("channel '%s' ~ received invalid message of size %zd", name.c_str(), nRead); - return BAD_VALUE; + return android::base::Error(BAD_VALUE); } ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", name.c_str(), - ftl::enum_string(msg->header.type).c_str()); + ftl::enum_string(msg.header.type).c_str()); if (ATRACE_ENABLED()) { // Add an additional trace point to include data about the received message. std::string message = StringPrintf("receiveMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=%s)", - name.c_str(), msg->header.seq, - ftl::enum_string(msg->header.type).c_str()); + name.c_str(), msg.header.seq, + ftl::enum_string(msg.header.type).c_str()); ATRACE_NAME(message.c_str()); } - return OK; + return msg; } bool InputChannel::probablyHasInput() const { @@ -729,15 +730,16 @@ status_t InputPublisher::publishTouchModeEvent(uint32_t seq, int32_t eventId, bo } android::base::Result InputPublisher::receiveConsumerResponse() { - InputMessage msg; - status_t result = mChannel->receiveMessage(&msg); - if (result) { - if (debugTransportPublisher() && result != WOULD_BLOCK) { + android::base::Result result = mChannel->receiveMessage(); + if (!result.ok()) { + if (debugTransportPublisher() && result.error().code() != WOULD_BLOCK) { LOG(INFO) << "channel '" << mChannel->getName() << "' publisher ~ " << __func__ << ": " - << strerror(result); + << result.error().message(); } - return android::base::Error(result); + return result.error(); } + + const InputMessage& msg = *result; if (msg.header.type == InputMessage::Type::FINISHED) { ALOGD_IF(debugTransportPublisher(), "channel '%s' publisher ~ %s: finished: seq=%u, handled=%s", diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index 02d4c07bfa..435bdcde2d 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -78,9 +78,10 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg)) << "server channel should be able to send message to client channel"; - InputMessage clientMsg; - EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg)) + android::base::Result clientMsgResult = clientChannel->receiveMessage(); + ASSERT_TRUE(clientMsgResult.ok()) << "client channel should be able to receive message from server channel"; + const InputMessage& clientMsg = *clientMsgResult; EXPECT_EQ(serverMsg.header.type, clientMsg.header.type) << "client channel should receive the correct message from server channel"; EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action) @@ -94,9 +95,10 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { EXPECT_EQ(OK, clientChannel->sendMessage(&clientReply)) << "client channel should be able to send message to server channel"; - InputMessage serverReply; - EXPECT_EQ(OK, serverChannel->receiveMessage(&serverReply)) + android::base::Result serverReplyResult = serverChannel->receiveMessage(); + ASSERT_TRUE(serverReplyResult.ok()) << "server channel should be able to receive message from client channel"; + const InputMessage& serverReply = *serverReplyResult; EXPECT_EQ(clientReply.header.type, serverReply.header.type) << "server channel should receive the correct message from client channel"; EXPECT_EQ(clientReply.header.seq, serverReply.header.seq) @@ -134,9 +136,10 @@ TEST_F(InputChannelTest, ProbablyHasInput) { << "client channel should observe that message is available before receiving it"; // Receive (consume) the message. - InputMessage clientMsg; - EXPECT_EQ(OK, receiverChannel->receiveMessage(&clientMsg)) + android::base::Result clientMsgResult = receiverChannel->receiveMessage(); + ASSERT_TRUE(clientMsgResult.ok()) << "client channel should be able to receive message from server channel"; + const InputMessage& clientMsg = *clientMsgResult; EXPECT_EQ(serverMsg.header.type, clientMsg.header.type) << "client channel should receive the correct message from server channel"; EXPECT_EQ(serverMsg.body.key.action, clientMsg.body.key.action) @@ -156,8 +159,8 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; - InputMessage msg; - EXPECT_EQ(WOULD_BLOCK, clientChannel->receiveMessage(&msg)) + android::base::Result msgResult = clientChannel->receiveMessage(); + EXPECT_EQ(WOULD_BLOCK, msgResult.error().code()) << "receiveMessage should have returned WOULD_BLOCK"; } @@ -172,8 +175,8 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { serverChannel.reset(); // close server channel - InputMessage msg; - EXPECT_EQ(DEAD_OBJECT, clientChannel->receiveMessage(&msg)) + android::base::Result msgResult = clientChannel->receiveMessage(); + EXPECT_EQ(DEAD_OBJECT, msgResult.error().code()) << "receiveMessage should have returned DEAD_OBJECT"; } @@ -207,7 +210,7 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { MotionClassification::DEEP_PRESS, }; - InputMessage serverMsg = {}, clientMsg; + InputMessage serverMsg = {}; serverMsg.header.type = InputMessage::Type::MOTION; serverMsg.header.seq = 1; serverMsg.body.motion.pointerCount = 1; @@ -218,11 +221,13 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { EXPECT_EQ(OK, serverChannel->sendMessage(&serverMsg)) << "server channel should be able to send message to client channel"; - EXPECT_EQ(OK, clientChannel->receiveMessage(&clientMsg)) + android::base::Result clientMsgResult = clientChannel->receiveMessage(); + ASSERT_TRUE(clientMsgResult.ok()) << "client channel should be able to receive message from server channel"; + const InputMessage& clientMsg = *clientMsgResult; EXPECT_EQ(serverMsg.header.type, clientMsg.header.type); - EXPECT_EQ(classification, clientMsg.body.motion.classification) << - "Expected to receive " << motionClassificationToString(classification); + EXPECT_EQ(classification, clientMsg.body.motion.classification) + << "Expected to receive " << motionClassificationToString(classification); } } -- GitLab From 5fe801b1e9c27ec11b06b19b3056a4fa7af7d66c Mon Sep 17 00:00:00 2001 From: Greg Kaiser Date: Thu, 27 Jun 2024 00:03:33 +0000 Subject: [PATCH 050/530] Revert "libbinder: export fewer symbols for bionic builds" This reverts commit 6781d33a5f1f65031907dba71cbaf404a18459df. Reason for revert: Causes b/349657329 Change-Id: Id87786ad46b1b48b0040b75edc4ec64f2d382e73 Test: Local build of device with this reverted no longer has b/349657329 --- libs/binder/Android.bp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index bd6a08e09b..f31f8d3993 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -268,21 +268,6 @@ cc_defaults { "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", ], - - target: { - bionic: { - // Hide symbols by default and set the BUILDING_LIBBINDER macro so that - // the code knows to export them. - // - // Only enabled on bionic builds, where RTTI is disabled, because - // it is failing to export required typeinfo symbols. - // TODO: b/341341056 - Find a solution for non-bionic builds. - cflags: [ - "-fvisibility=hidden", - "-DBUILDING_LIBBINDER", - ], - }, - }, } cc_defaults { -- GitLab From 871886eebe469fc21568ff363993bde9a6593837 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Wed, 26 Jun 2024 17:17:51 -0700 Subject: [PATCH 051/530] Fix region sampling for secure layers We were swapping a couple of boolean params when requesting screenshots for region sampling, breaking region sampling for secure layers in the process. Fix this by passing flags instead of booleans in a long list of arguments and add a test to verify the code path. FLAG: EXEMPT bugfix Fixes: 348944802 Test: presubmit Change-Id: I58f12e5cf81cb59115c1b9c500ac1e18a8ec72e5 --- libs/gui/tests/RegionSampling_test.cpp | 58 ++++++++++++++----- services/surfaceflinger/DisplayRenderArea.cpp | 16 +++-- services/surfaceflinger/DisplayRenderArea.h | 5 +- services/surfaceflinger/LayerRenderArea.cpp | 9 ++- services/surfaceflinger/LayerRenderArea.h | 4 +- .../surfaceflinger/RegionSamplingThread.cpp | 6 +- services/surfaceflinger/RenderArea.h | 24 +++++--- services/surfaceflinger/RenderAreaBuilder.h | 40 ++++--------- services/surfaceflinger/SurfaceFlinger.cpp | 24 +++++--- .../tests/unittests/CompositionTest.cpp | 8 ++- 10 files changed, 111 insertions(+), 83 deletions(-) diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp index b18b544257..223e4b6cbd 100644 --- a/libs/gui/tests/RegionSampling_test.cpp +++ b/libs/gui/tests/RegionSampling_test.cpp @@ -239,8 +239,9 @@ protected: float const luma_green = 0.7152; uint32_t const rgba_blue = 0xFFFF0000; float const luma_blue = 0.0722; - float const error_margin = 0.01; + float const error_margin = 0.1; float const luma_gray = 0.50; + static constexpr std::chrono::milliseconds EVENT_WAIT_TIME_MS = 5000ms; }; TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) { @@ -261,7 +262,7 @@ TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) { composer->removeRegionSamplingListener(listener); } -TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) { +TEST_F(RegionSamplingTest, CollectsLuma) { fill_render(rgba_green); sp composer = ComposerServiceAIDL::getComposerService(); @@ -273,7 +274,30 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) { sampleArea.bottom = 200; composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_green, error_margin); + + composer->removeRegionSamplingListener(listener); +} + +TEST_F(RegionSamplingTest, CollectsLumaForSecureLayer) { + fill_render(rgba_green); + SurfaceComposerClient::Transaction() + .setFlags(mContentLayer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) + .apply(/*synchronous=*/true); + + sp composer = ComposerServiceAIDL::getComposerService(); + sp listener = new Listener(); + gui::ARect sampleArea; + sampleArea.left = 100; + sampleArea.top = 100; + sampleArea.right = 200; + sampleArea.bottom = 200; + composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); + + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); composer->removeRegionSamplingListener(listener); @@ -291,13 +315,14 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsChangingLuma) { sampleArea.bottom = 200; composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); listener->reset(); fill_render(rgba_blue); - EXPECT_TRUE(listener->wait_event(300ms)) + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) << "timed out waiting for 2nd luma event to be received"; EXPECT_NEAR(listener->luma(), luma_blue, error_margin); @@ -323,10 +348,10 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromTwoRegions) { graySampleArea.bottom = 200; composer->addRegionSamplingListener(graySampleArea, mTopLayer->getHandle(), grayListener); - EXPECT_TRUE(grayListener->wait_event(300ms)) + EXPECT_TRUE(grayListener->wait_event(EVENT_WAIT_TIME_MS)) << "timed out waiting for luma event to be received"; EXPECT_NEAR(grayListener->luma(), luma_gray, error_margin); - EXPECT_TRUE(greenListener->wait_event(300ms)) + EXPECT_TRUE(greenListener->wait_event(EVENT_WAIT_TIME_MS)) << "timed out waiting for luma event to be received"; EXPECT_NEAR(greenListener->luma(), luma_green, error_margin); @@ -334,7 +359,7 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromTwoRegions) { composer->removeRegionSamplingListener(grayListener); } -TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) { +TEST_F(RegionSamplingTest, TestIfInvalidInputParameters) { sp composer = ComposerServiceAIDL::getComposerService(); sp listener = new Listener(); @@ -369,7 +394,7 @@ TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) { composer->removeRegionSamplingListener(listener); } -TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) { +TEST_F(RegionSamplingTest, TestCallbackAfterRemoveListener) { fill_render(rgba_green); sp composer = ComposerServiceAIDL::getComposerService(); sp listener = new Listener(); @@ -381,7 +406,8 @@ TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) { composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); fill_render(rgba_green); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); listener->reset(); @@ -404,11 +430,13 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) { // Test: listener in (100, 100). See layer before move, no layer after move. fill_render(rgba_blue); composer->addRegionSamplingListener(sampleAreaA, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_blue, error_margin); listener->reset(); SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply(); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_gray, error_margin); composer->removeRegionSamplingListener(listener); @@ -420,11 +448,13 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) { sampleAreaA.right = sampleArea.right; sampleAreaA.bottom = sampleArea.bottom; composer->addRegionSamplingListener(sampleAreaA, mTopLayer->getHandle(), listener); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_gray, error_margin); listener->reset(); SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply(); - EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_TRUE(listener->wait_event(EVENT_WAIT_TIME_MS)) + << "timed out waiting for luma event to be received"; EXPECT_NEAR(listener->luma(), luma_green, error_margin); composer->removeRegionSamplingListener(listener); } diff --git a/services/surfaceflinger/DisplayRenderArea.cpp b/services/surfaceflinger/DisplayRenderArea.cpp index 55b395b458..c63c738d34 100644 --- a/services/surfaceflinger/DisplayRenderArea.cpp +++ b/services/surfaceflinger/DisplayRenderArea.cpp @@ -22,22 +22,20 @@ namespace android { std::unique_ptr DisplayRenderArea::create(wp displayWeak, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace reqDataSpace, - bool hintForSeamlessTransition, - bool allowSecureLayers) { + ftl::Flags options) { if (auto display = displayWeak.promote()) { // Using new to access a private constructor. - return std::unique_ptr( - new DisplayRenderArea(std::move(display), sourceCrop, reqSize, reqDataSpace, - hintForSeamlessTransition, allowSecureLayers)); + return std::unique_ptr(new DisplayRenderArea(std::move(display), + sourceCrop, reqSize, + reqDataSpace, options)); } return nullptr; } DisplayRenderArea::DisplayRenderArea(sp display, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace reqDataSpace, - bool hintForSeamlessTransition, bool allowSecureLayers) - : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, hintForSeamlessTransition, - allowSecureLayers), + ftl::Flags options) + : RenderArea(reqSize, CaptureFill::OPAQUE, reqDataSpace, options), mDisplay(std::move(display)), mSourceCrop(sourceCrop) {} @@ -46,7 +44,7 @@ const ui::Transform& DisplayRenderArea::getTransform() const { } bool DisplayRenderArea::isSecure() const { - return mAllowSecureLayers && mDisplay->isSecure(); + return mOptions.test(Options::CAPTURE_SECURE_LAYERS) && mDisplay->isSecure(); } sp DisplayRenderArea::getDisplayDevice() const { diff --git a/services/surfaceflinger/DisplayRenderArea.h b/services/surfaceflinger/DisplayRenderArea.h index 4555a9ed66..677d01975a 100644 --- a/services/surfaceflinger/DisplayRenderArea.h +++ b/services/surfaceflinger/DisplayRenderArea.h @@ -29,8 +29,7 @@ class DisplayRenderArea : public RenderArea { public: static std::unique_ptr create(wp, const Rect& sourceCrop, ui::Size reqSize, ui::Dataspace, - bool hintForSeamlessTransition, - bool allowSecureLayers = true); + ftl::Flags options); const ui::Transform& getTransform() const override; bool isSecure() const override; @@ -39,7 +38,7 @@ public: private: DisplayRenderArea(sp, const Rect& sourceCrop, ui::Size reqSize, - ui::Dataspace, bool hintForSeamlessTransition, bool allowSecureLayers = true); + ui::Dataspace, ftl::Flags options); const sp mDisplay; const Rect mSourceCrop; diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp index f323ce7284..bfe6d2a956 100644 --- a/services/surfaceflinger/LayerRenderArea.cpp +++ b/services/surfaceflinger/LayerRenderArea.cpp @@ -27,10 +27,9 @@ namespace android { LayerRenderArea::LayerRenderArea(sp layer, frontend::LayerSnapshot layerSnapshot, const Rect& crop, ui::Size reqSize, ui::Dataspace reqDataSpace, - bool allowSecureLayers, const ui::Transform& layerTransform, - const Rect& layerBufferSize, bool hintForSeamlessTransition) - : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, hintForSeamlessTransition, - allowSecureLayers), + const ui::Transform& layerTransform, const Rect& layerBufferSize, + ftl::Flags options) + : RenderArea(reqSize, CaptureFill::CLEAR, reqDataSpace, options), mLayer(std::move(layer)), mLayerSnapshot(std::move(layerSnapshot)), mLayerBufferSize(layerBufferSize), @@ -42,7 +41,7 @@ const ui::Transform& LayerRenderArea::getTransform() const { } bool LayerRenderArea::isSecure() const { - return mAllowSecureLayers; + return mOptions.test(Options::CAPTURE_SECURE_LAYERS); } sp LayerRenderArea::getDisplayDevice() const { diff --git a/services/surfaceflinger/LayerRenderArea.h b/services/surfaceflinger/LayerRenderArea.h index a12bfca54a..f72c7c7715 100644 --- a/services/surfaceflinger/LayerRenderArea.h +++ b/services/surfaceflinger/LayerRenderArea.h @@ -33,9 +33,9 @@ class SurfaceFlinger; class LayerRenderArea : public RenderArea { public: LayerRenderArea(sp layer, frontend::LayerSnapshot layerSnapshot, const Rect& crop, - ui::Size reqSize, ui::Dataspace reqDataSpace, bool allowSecureLayers, + ui::Size reqSize, ui::Dataspace reqDataSpace, const ui::Transform& layerTransform, const Rect& layerBufferSize, - bool hintForSeamlessTransition); + ftl::Flags options); const ui::Transform& getTransform() const override; bool isSecure() const override; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 5add290e96..e579eb08a6 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -277,7 +277,6 @@ void RegionSamplingThread::captureSample() { } const Rect sampledBounds = sampleRegion.bounds(); - constexpr bool kHintForSeamlessTransition = false; std::unordered_set, SpHash> listeners; @@ -350,9 +349,8 @@ void RegionSamplingThread::captureSample() { SurfaceFlinger::RenderAreaBuilderVariant renderAreaBuilder(std::in_place_type, sampledBounds, - sampledBounds.getSize(), ui::Dataspace::V0_SRGB, - kHintForSeamlessTransition, true /* captureSecureLayers */, - displayWeak); + sampledBounds.getSize(), ui::Dataspace::V0_SRGB, displayWeak, + RenderArea::Options::CAPTURE_SECURE_LAYERS); FenceResult fenceResult; if (FlagManager::getInstance().single_hop_screenshot() && diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index e8d20af4ad..034e467be9 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -21,16 +21,23 @@ class DisplayDevice; class RenderArea { public: enum class CaptureFill {CLEAR, OPAQUE}; - + enum class Options { + // If not set, the secure layer would be blacked out or skipped + // when rendered to an insecure render area + CAPTURE_SECURE_LAYERS = 1 << 0, + + // If set, the render result may be used for system animations + // that must preserve the exact colors of the display + HINT_FOR_SEAMLESS_TRANSITION = 1 << 1, + }; static float getCaptureFillValue(CaptureFill captureFill); RenderArea(ui::Size reqSize, CaptureFill captureFill, ui::Dataspace reqDataSpace, - bool hintForSeamlessTransition, bool allowSecureLayers = false) - : mAllowSecureLayers(allowSecureLayers), + ftl::Flags options) + : mOptions(options), mReqSize(reqSize), mReqDataSpace(reqDataSpace), - mCaptureFill(captureFill), - mHintForSeamlessTransition(hintForSeamlessTransition) {} + mCaptureFill(captureFill) {} static std::function>>()> fromTraverseLayersLambda( std::function traverseLayers) { @@ -90,16 +97,17 @@ public: // Returns whether the render result may be used for system animations that // must preserve the exact colors of the display. - bool getHintForSeamlessTransition() const { return mHintForSeamlessTransition; } + bool getHintForSeamlessTransition() const { + return mOptions.test(Options::HINT_FOR_SEAMLESS_TRANSITION); + } protected: - const bool mAllowSecureLayers; + ftl::Flags mOptions; private: const ui::Size mReqSize; const ui::Dataspace mReqDataSpace; const CaptureFill mCaptureFill; - const bool mHintForSeamlessTransition; }; } // namespace android diff --git a/services/surfaceflinger/RenderAreaBuilder.h b/services/surfaceflinger/RenderAreaBuilder.h index a25c6e0b67..599fa7e102 100644 --- a/services/surfaceflinger/RenderAreaBuilder.h +++ b/services/surfaceflinger/RenderAreaBuilder.h @@ -36,50 +36,34 @@ struct RenderAreaBuilder { // Composition data space of the render area ui::Dataspace reqDataSpace; - // If true, the secure layer would be blacked out or skipped - // when rendered to an insecure render area - bool allowSecureLayers; - - // If true, the render result may be used for system animations - // that must preserve the exact colors of the display - bool hintForSeamlessTransition; - + ftl::Flags options; virtual std::unique_ptr build() const = 0; RenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace, - bool allowSecureLayers, bool hintForSeamlessTransition) - : crop(crop), - reqSize(reqSize), - reqDataSpace(reqDataSpace), - allowSecureLayers(allowSecureLayers), - hintForSeamlessTransition(hintForSeamlessTransition) {} + ftl::Flags options) + : crop(crop), reqSize(reqSize), reqDataSpace(reqDataSpace), options(options) {} virtual ~RenderAreaBuilder() = default; }; struct DisplayRenderAreaBuilder : RenderAreaBuilder { DisplayRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace, - bool allowSecureLayers, bool hintForSeamlessTransition, - wp displayWeak) - : RenderAreaBuilder(crop, reqSize, reqDataSpace, allowSecureLayers, - hintForSeamlessTransition), - displayWeak(displayWeak) {} + wp displayWeak, + ftl::Flags options) + : RenderAreaBuilder(crop, reqSize, reqDataSpace, options), displayWeak(displayWeak) {} // Display that render area will be on wp displayWeak; std::unique_ptr build() const override { - return DisplayRenderArea::create(displayWeak, crop, reqSize, reqDataSpace, - hintForSeamlessTransition, allowSecureLayers); + return DisplayRenderArea::create(displayWeak, crop, reqSize, reqDataSpace, options); } }; struct LayerRenderAreaBuilder : RenderAreaBuilder { - LayerRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace, - bool allowSecureLayers, bool hintForSeamlessTransition, sp layer, - bool childrenOnly) - : RenderAreaBuilder(crop, reqSize, reqDataSpace, allowSecureLayers, - hintForSeamlessTransition), + LayerRenderAreaBuilder(Rect crop, ui::Size reqSize, ui::Dataspace reqDataSpace, sp layer, + bool childrenOnly, ftl::Flags options) + : RenderAreaBuilder(crop, reqSize, reqDataSpace, options), layer(layer), childrenOnly(childrenOnly) {} @@ -110,8 +94,8 @@ struct LayerRenderAreaBuilder : RenderAreaBuilder { std::unique_ptr build() const override { return std::make_unique(layer, std::move(layerSnapshot), crop, reqSize, - reqDataSpace, allowSecureLayers, layerTransform, - layerBufferSize, hintForSeamlessTransition); + reqDataSpace, layerTransform, layerBufferSize, + options); } }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5b40acf030..13a1464594 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -7958,10 +7958,13 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, GetLayerSnapshotsFunction getLayerSnapshotsFn = getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); + ftl::Flags options; + if (args.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS; + if (args.hintForSeamlessTransition) + options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION; captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type, args.sourceCrop, reqSize, args.dataspace, - args.hintForSeamlessTransition, - args.captureSecureLayers, displayWeak), + displayWeak, options), getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); } @@ -8012,10 +8015,12 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args constexpr bool kAllowProtected = false; constexpr bool kGrayscale = false; + ftl::Flags options; + if (args.hintForSeamlessTransition) + options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION; captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type, - Rect(), size, args.dataspace, - args.hintForSeamlessTransition, - false /* captureSecureLayers */, displayWeak), + Rect(), size, args.dataspace, displayWeak, + options), getLayerSnapshotsFn, size, args.pixelFormat, kAllowProtected, kGrayscale, captureListener); } @@ -8114,10 +8119,13 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return; } + ftl::Flags options; + if (args.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS; + if (args.hintForSeamlessTransition) + options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION; captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type, crop, - reqSize, dataspace, args.captureSecureLayers, - args.hintForSeamlessTransition, parent, - args.childrenOnly), + reqSize, dataspace, parent, args.childrenOnly, + options), getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected, args.grayscale, captureListener); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 08973de195..cdd77fec95 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -70,6 +70,7 @@ using testing::SetArgPointee; using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; +using namespace ftl::flag_operators; constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID; constexpr hal::HWLayerId HWC_LAYER = 5000; @@ -197,8 +198,11 @@ void CompositionTest::captureScreenComposition() { const Rect sourceCrop(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT); constexpr bool regionSampling = false; - auto renderArea = DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(), - ui::Dataspace::V0_SRGB, true, true); + auto renderArea = + DisplayRenderArea::create(mDisplay, sourceCrop, sourceCrop.getSize(), + ui::Dataspace::V0_SRGB, + RenderArea::Options::CAPTURE_SECURE_LAYERS | + RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION); auto traverseLayers = [this](const LayerVector::Visitor& visitor) { return mFlinger.traverseLayersInLayerStack(mDisplay->getLayerStack(), -- GitLab From 5a93ccb90b8507c806417c160c7c30a62d6f1bc2 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Wed, 26 Jun 2024 00:38:32 +0000 Subject: [PATCH 052/530] Add trace slices to capture tasks important for latency monitoring Add a trace slices for: - for all post composition work on main thread - transaction callbacks - screenshot work on main thread Flag: EXEMPT adding trace slices + trivial refactor Bug: 333623207 Test: perfetto Change-Id: I6ca0a80941327edc0c78decf82176459d15d4595 --- .../surfaceflinger/RegionSamplingThread.cpp | 5 ++--- services/surfaceflinger/SurfaceFlinger.cpp | 8 ++++---- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../TransactionCallbackInvoker.cpp | 17 +++++++++++------ 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 5add290e96..86867d350f 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -358,9 +358,8 @@ void RegionSamplingThread::captureSample() { if (FlagManager::getInstance().single_hop_screenshot() && FlagManager::getInstance().ce_fence_promise()) { std::vector> layerFEs; - auto displayState = - mFlinger.getDisplayAndLayerSnapshotsFromMainThread(renderAreaBuilder, - getLayerSnapshotsFn, layerFEs); + auto displayState = mFlinger.getSnapshotsFromMainThread(renderAreaBuilder, + getLayerSnapshotsFn, layerFEs); fenceResult = mFlinger.captureScreenshot(renderAreaBuilder, buffer, kRegionSampling, kGrayscale, kIsProtected, nullptr, displayState, layerFEs) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5b40acf030..5d8c7283d8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2907,6 +2907,7 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( } } + ATRACE_NAME("postComposition"); mTimeStats->recordFrameDuration(pacesetterTarget.frameBeginTime().ns(), systemTime()); // Send a power hint after presentation is finished. @@ -8153,12 +8154,12 @@ bool SurfaceFlinger::layersHasProtectedLayer(const std::vector>& lay // Accessing display requires mStateLock, and contention for this lock // is reduced when grabbed from the main thread, thus also reducing // risk of deadlocks. -std::optional -SurfaceFlinger::getDisplayAndLayerSnapshotsFromMainThread( +std::optional SurfaceFlinger::getSnapshotsFromMainThread( RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn, std::vector>& layerFEs) { return mScheduler ->schedule([=, this, &renderAreaBuilder, &layerFEs]() REQUIRES(kMainThreadContext) { + ATRACE_NAME("getSnapshotsFromMainThread"); auto layers = getLayerSnapshotsFn(); for (auto& [layer, layerFE] : layers) { attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK); @@ -8188,8 +8189,7 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil FlagManager::getInstance().ce_fence_promise()) { std::vector> layerFEs; auto displayState = - getDisplayAndLayerSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, - layerFEs); + getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layerFEs); const bool supportsProtected = getRenderEngine().supportsProtectedContent(); bool hasProtectedLayer = false; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ee541c4364..34f48cd928 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -896,7 +896,7 @@ private: using OutputCompositionState = compositionengine::impl::OutputCompositionState; - std::optional getDisplayAndLayerSnapshotsFromMainThread( + std::optional getSnapshotsFromMainThread( RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn, std::vector>& layerFEs); diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 222ae30acb..8721538880 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -26,6 +26,7 @@ #include "TransactionCallbackInvoker.h" #include "BackgroundExecutor.h" #include "Utils/FenceUtils.h" +#include "utils/Trace.h" #include @@ -164,7 +165,7 @@ void TransactionCallbackInvoker::addPresentFence(sp presentFence) { void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // For each listener auto completedTransactionsItr = mCompletedTransactions.begin(); - BackgroundExecutor::Callbacks callbacks; + ftl::SmallVector listenerStatsToSend; while (completedTransactionsItr != mCompletedTransactions.end()) { auto& [listener, transactionStatsDeque] = *completedTransactionsItr; ListenerStats listenerStats; @@ -199,10 +200,7 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // keep it as an IBinder due to consistency reasons: if we // interface_cast at the IPC boundary when reading a Parcel, // we get pointers that compare unequal in the SF process. - callbacks.emplace_back([stats = std::move(listenerStats)]() { - interface_cast(stats.listener) - ->onTransactionCompleted(stats); - }); + listenerStatsToSend.emplace_back(std::move(listenerStats)); } } completedTransactionsItr++; @@ -212,7 +210,14 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { mPresentFence.clear(); } - BackgroundExecutor::getInstance().sendCallbacks(std::move(callbacks)); + BackgroundExecutor::getInstance().sendCallbacks( + {[listenerStatsToSend = std::move(listenerStatsToSend)]() { + ATRACE_NAME("TransactionCallbackInvoker::sendCallbacks"); + for (auto& stats : listenerStatsToSend) { + interface_cast(stats.listener) + ->onTransactionCompleted(stats); + } + }}); } // ----------------------------------------------------------------------- -- GitLab From cd3f6d8d422ef5d581807308117558787f2e1baa Mon Sep 17 00:00:00 2001 From: fengqian Date: Thu, 27 Jun 2024 16:14:09 +0800 Subject: [PATCH 053/530] SurfaceFlinger: define LOG_NDEBUG for debug. Bug: 349735052 Add LOG_NDEBUG define in LayerLifecycleManager for debug. Test: make & boot Change-Id: I160fcaa6527aa120b2ba300d6a3d3eb6be649a8c Signed-off-by: fengqian --- services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp index 0983e7c1ac..e864ff60f7 100644 --- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp +++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +// #define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG -- GitLab From 1d46f58320055b7aad551b92827bf3405258f25e Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Tue, 21 May 2024 15:06:29 -0700 Subject: [PATCH 054/530] Migrate from libutils SystemClock.h to std::chrono Bug: 341997808 Test: mma Change-Id: Ib4d60eeaaac73566cc79d473f6551e9abd20e69a --- libs/binder/ActivityManager.cpp | 13 +++++----- libs/binder/IPCThreadState.cpp | 20 +++++++++------ libs/binder/IServiceManager.cpp | 31 +++++++++++++---------- libs/binder/PermissionController.cpp | 12 ++++----- libs/binder/ProcessState.cpp | 2 +- libs/binder/Utils.h | 7 +++++ libs/binder/include/binder/ProcessState.h | 5 +++- 7 files changed, 54 insertions(+), 36 deletions(-) diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp index 526427663b..98349c6ab3 100644 --- a/libs/binder/ActivityManager.cpp +++ b/libs/binder/ActivityManager.cpp @@ -23,10 +23,10 @@ #include #include -#include - namespace android { +using namespace std::chrono_literals; + ActivityManager::ActivityManager() { } @@ -43,15 +43,16 @@ sp ActivityManager::getService() } } else { ALOGI("Thread pool not started. Polling for activity service."); - int64_t startTime = 0; + auto startTime = std::chrono::steady_clock::now().min(); while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) { sp binder = defaultServiceManager()->checkService(String16("activity")); if (binder == nullptr) { // Wait for the activity service to come back... - if (startTime == 0) { - startTime = uptimeMillis(); + if (startTime == startTime.min()) { + startTime = std::chrono::steady_clock::now(); ALOGI("Waiting for activity service"); - } else if ((uptimeMillis() - startTime) > 1000000) { + } else if (std::chrono::steady_clock::now() - startTime > 1000s) { + // TODO(b/342453147): timeout of 1000s = 16min and 40s doesn't seem intended ALOGW("Waiting too long for activity service, giving up"); service = nullptr; break; diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index c3bbdbadaa..61d0dbad31 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -38,6 +37,7 @@ #include #include +#include "Utils.h" #include "binder_module.h" #if LOG_NDEBUG @@ -65,6 +65,8 @@ namespace android { +using namespace std::chrono_literals; + // Static const and functions will be optimized out if not used, // when LOG_NDEBUG and references in IF_LOG_COMMANDS() are optimized out. static const char* kReturnStrings[] = { @@ -647,8 +649,9 @@ status_t IPCThreadState::getAndExecuteCommand() size_t newThreadsCount = mProcess->mExecutingThreadsCount.fetch_add(1) + 1; if (newThreadsCount >= mProcess->mMaxThreads) { - int64_t expected = 0; - mProcess->mStarvationStartTimeMs.compare_exchange_strong(expected, uptimeMillis()); + auto expected = ProcessState::never(); + mProcess->mStarvationStartTime + .compare_exchange_strong(expected, std::chrono::steady_clock::now()); } result = executeCommand(cmd); @@ -656,12 +659,13 @@ status_t IPCThreadState::getAndExecuteCommand() size_t maxThreads = mProcess->mMaxThreads; newThreadsCount = mProcess->mExecutingThreadsCount.fetch_sub(1) - 1; if (newThreadsCount < maxThreads) { - size_t starvationStartTimeMs = mProcess->mStarvationStartTimeMs.exchange(0); - if (starvationStartTimeMs != 0) { - int64_t starvationTimeMs = uptimeMillis() - starvationStartTimeMs; - if (starvationTimeMs > 100) { + auto starvationStartTime = + mProcess->mStarvationStartTime.exchange(ProcessState::never()); + if (starvationStartTime != ProcessState::never()) { + auto starvationTime = std::chrono::steady_clock::now() - starvationStartTime; + if (starvationTime > 100ms) { ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms", maxThreads, - starvationTimeMs); + to_ms(starvationTime)); } } } diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 5844c85d21..50d00ae2f2 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #ifndef __ANDROID_VNDK__ #include @@ -48,9 +48,12 @@ #endif #include "Static.h" +#include "Utils.h" namespace android { +using namespace std::chrono_literals; + using AidlRegistrationCallback = IServiceManager::LocalRegistrationCallback; using AidlServiceManager = android::os::IServiceManager; @@ -194,16 +197,16 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid, bool logP pc = gPermissionController; gPermissionControllerLock.unlock(); - int64_t startTime = 0; + auto startTime = std::chrono::steady_clock::now().min(); while (true) { if (pc != nullptr) { bool res = pc->checkPermission(permission, pid, uid); if (res) { - if (startTime != 0) { - ALOGI("Check passed after %d seconds for %s from uid=%d pid=%d", - (int)((uptimeMillis() - startTime) / 1000), String8(permission).c_str(), - uid, pid); + if (startTime != startTime.min()) { + const auto waitTime = std::chrono::steady_clock::now() - startTime; + ALOGI("Check passed after %" PRIu64 "ms for %s from uid=%d pid=%d", + to_ms(waitTime), String8(permission).c_str(), uid, pid); } return res; } @@ -229,8 +232,8 @@ bool checkPermission(const String16& permission, pid_t pid, uid_t uid, bool logP sp binder = defaultServiceManager()->checkService(_permission); if (binder == nullptr) { // Wait for the permission controller to come back... - if (startTime == 0) { - startTime = uptimeMillis(); + if (startTime == startTime.min()) { + startTime = std::chrono::steady_clock::now(); ALOGI("Waiting to check permission %s from uid=%d pid=%d", String8(permission).c_str(), uid, pid); } @@ -287,8 +290,8 @@ sp ServiceManagerShim::getService(const String16& name) const const bool isVendorService = strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; - constexpr int64_t timeout = 5000; - int64_t startTime = uptimeMillis(); + constexpr auto timeout = 5s; + const auto startTime = std::chrono::steady_clock::now(); // Vendor code can't access system properties if (!gSystemBootCompleted && !isVendorService) { #ifdef __ANDROID__ @@ -306,15 +309,16 @@ sp ServiceManagerShim::getService(const String16& name) const ProcessState::self()->getDriverName().c_str()); int n = 0; - while (uptimeMillis() - startTime < timeout) { + while (std::chrono::steady_clock::now() - startTime < timeout) { n++; usleep(1000*sleepTime); sp svc = checkService(name); if (svc != nullptr) { - ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIi64 "ms", + const auto waitTime = std::chrono::steady_clock::now() - startTime; + ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIu64 "ms", String8(name).c_str(), ProcessState::self()->getDriverName().c_str(), - uptimeMillis() - startTime); + to_ms(waitTime)); return svc; } } @@ -416,7 +420,6 @@ sp ServiceManagerShim::waitForService(const String16& name16) // that another thread serves the callback, and we never get a // command, so we hang indefinitely. std::unique_lock lock(waiter->mMutex); - using std::literals::chrono_literals::operator""s; waiter->mCv.wait_for(lock, 1s, [&] { return waiter->mBinder != nullptr; }); diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp index 0c8924503d..c11eb7df42 100644 --- a/libs/binder/PermissionController.cpp +++ b/libs/binder/PermissionController.cpp @@ -19,10 +19,10 @@ #include #include -#include - namespace android { +using namespace std::chrono_literals; + PermissionController::PermissionController() { } @@ -30,16 +30,16 @@ PermissionController::PermissionController() sp PermissionController::getService() { std::lock_guard scoped_lock(mLock); - int64_t startTime = 0; + auto startTime = std::chrono::steady_clock::now().min(); sp service = mService; while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) { sp binder = defaultServiceManager()->checkService(String16("permission")); if (binder == nullptr) { // Wait for the activity service to come back... - if (startTime == 0) { - startTime = uptimeMillis(); + if (startTime == startTime.min()) { + startTime = std::chrono::steady_clock::now(); ALOGI("Waiting for permission service"); - } else if ((uptimeMillis() - startTime) > 10000) { + } else if (std::chrono::steady_clock::now() - startTime > 10s) { ALOGW("Waiting too long for permission service, giving up"); service = nullptr; break; diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index ad5a6b32b6..5de152a42a 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -555,7 +555,7 @@ ProcessState::ProcessState(const char* driver) mMaxThreads(DEFAULT_MAX_BINDER_THREADS), mCurrentThreads(0), mKernelStartedThreads(0), - mStarvationStartTimeMs(0), + mStarvationStartTime(never()), mForked(false), mThreadPoolStarted(false), mThreadPoolSeq(1), diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h index df8a4ce1f1..5e1012af01 100644 --- a/libs/binder/Utils.h +++ b/libs/binder/Utils.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -114,4 +115,10 @@ struct Span { // Android is little-endian. LIBBINDER_INTERNAL_EXPORTED std::string HexString(const void* bytes, size_t len); +// Converts any std::chrono duration to the number of milliseconds +template +uint64_t to_ms(std::chrono::duration duration) { + return std::chrono::duration_cast(duration).count(); +} + } // namespace android diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index 11898a0515..8908cb8ae0 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -24,6 +24,7 @@ #include #include +#include #include // --------------------------------------------------------------------------- @@ -177,7 +178,9 @@ private: // Current number of pooled threads inside the thread pool. std::atomic_size_t mKernelStartedThreads; // Time when thread pool was emptied - std::atomic_int64_t mStarvationStartTimeMs; + std::atomic mStarvationStartTime; + + static constexpr auto never = &std::chrono::steady_clock::time_point::min; mutable std::mutex mLock; // protects everything below. -- GitLab From 022db680633b483ec5fab4f6b0722981482b3a02 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Mon, 17 Jun 2024 13:55:51 -0700 Subject: [PATCH 055/530] RpcServer: let system allocate vsock ports This greatly improves stability with concurrent test execution Bug: 285204695 Test: atest --host binder_sdk_test Change-Id: Ib7b76df693288033e55fa27786bf6efb21d0ebf0 --- libs/binder/RpcServer.cpp | 19 +++++++++-- libs/binder/include/binder/RpcServer.h | 7 ++-- .../tests/BinderRpcTestServerConfig.aidl | 1 - libs/binder/tests/binderRpcTest.cpp | 32 +++++++++---------- libs/binder/tests/binderRpcTestService.cpp | 4 +-- 5 files changed, 39 insertions(+), 24 deletions(-) diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index d9e926a9d5..b8742af1f9 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -71,8 +71,23 @@ status_t RpcServer::setupUnixDomainServer(const char* path) { return setupSocketServer(UnixSocketAddress(path)); } -status_t RpcServer::setupVsockServer(unsigned int bindCid, unsigned int port) { - return setupSocketServer(VsockSocketAddress(bindCid, port)); +status_t RpcServer::setupVsockServer(unsigned bindCid, unsigned port, unsigned* assignedPort) { + auto status = setupSocketServer(VsockSocketAddress(bindCid, port)); + if (status != OK) return status; + + if (assignedPort == nullptr) return OK; + sockaddr_vm addr; + socklen_t len = sizeof(addr); + if (0 != getsockname(mServer.fd.get(), reinterpret_cast(&addr), &len)) { + status = -errno; + ALOGE("setupVsockServer: Failed to getsockname: %s", strerror(-status)); + return status; + } + + LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu", + static_cast(len), sizeof(addr)); + *assignedPort = addr.svm_port; + return OK; } status_t RpcServer::setupInetServer(const char* address, unsigned int port, diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index abea0fb40c..c241d31623 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -85,9 +85,12 @@ public: /** * Creates an RPC server binding to the given CID at the given port. + * + * Set |port| to VMADDR_PORT_ANY to pick an ephemeral port. In this case, |assignedPort| + * will be set to the picked port number, if it is not null. */ - [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned int bindCid, - unsigned int port); + [[nodiscard]] LIBBINDER_EXPORTED status_t setupVsockServer(unsigned bindCid, unsigned port, + unsigned* assignedPort = nullptr); /** * Creates an RPC server at the current port using IPv4. diff --git a/libs/binder/tests/BinderRpcTestServerConfig.aidl b/libs/binder/tests/BinderRpcTestServerConfig.aidl index b2e0ef21c7..96550bca6b 100644 --- a/libs/binder/tests/BinderRpcTestServerConfig.aidl +++ b/libs/binder/tests/BinderRpcTestServerConfig.aidl @@ -20,7 +20,6 @@ parcelable BinderRpcTestServerConfig { int socketType; int rpcSecurity; int serverVersion; - int vsockPort; int socketFd; // Inherited from the parent process. @utf8InCpp String addr; } diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 19882ea1a9..9b1b64ae8c 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -141,11 +141,6 @@ static std::string allocateSocketAddress() { return ret; }; -static unsigned int allocateVsockPort() { - static unsigned int vsockPort = 34567; - return vsockPort++; -} - static unique_fd initUnixSocket(std::string addr) { auto socket_addr = UnixSocketAddress(addr.c_str()); unique_fd fd(TEMP_FAILURE_RETRY(socket(socket_addr.addr()->sa_family, SOCK_STREAM, AF_UNIX))); @@ -300,7 +295,6 @@ std::unique_ptr BinderRpc::createRpcTestSocketServerProcessEtc( serverConfig.socketType = static_cast(socketType); serverConfig.rpcSecurity = static_cast(rpcSecurity); serverConfig.serverVersion = serverVersion; - serverConfig.vsockPort = allocateVsockPort(); serverConfig.addr = addr; serverConfig.socketFd = socketFd.get(); for (auto mode : options.serverSupportedFileDescriptorTransportModes) { @@ -379,7 +373,7 @@ std::unique_ptr BinderRpc::createRpcTestSocketServerProcessEtc( unique_fd(dup(bootstrapClientFd.get()))); break; case SocketType::VSOCK: - status = session->setupVsockClient(VMADDR_CID_LOCAL, serverConfig.vsockPort); + status = session->setupVsockClient(VMADDR_CID_LOCAL, serverInfo.port); break; case SocketType::INET: status = session->setupInetClient("127.0.0.1", serverInfo.port); @@ -1152,8 +1146,6 @@ INSTANTIATE_TEST_SUITE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderR #else // BINDER_RPC_TO_TRUSTY_TEST bool testSupportVsockLoopback() { // We don't need to enable TLS to know if vsock is supported. - unsigned int vsockPort = allocateVsockPort(); - unique_fd serverFd( TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); @@ -1165,16 +1157,21 @@ bool testSupportVsockLoopback() { sockaddr_vm serverAddr{ .svm_family = AF_VSOCK, - .svm_port = vsockPort, + .svm_port = VMADDR_PORT_ANY, .svm_cid = VMADDR_CID_ANY, }; int ret = TEMP_FAILURE_RETRY( bind(serverFd.get(), reinterpret_cast(&serverAddr), sizeof(serverAddr))); - LOG_ALWAYS_FATAL_IF(0 != ret, "Could not bind socket to port %u: %s", vsockPort, + LOG_ALWAYS_FATAL_IF(0 != ret, "Could not bind socket to port VMADDR_PORT_ANY: %s", strerror(errno)); + socklen_t len = sizeof(serverAddr); + ret = getsockname(serverFd.get(), reinterpret_cast(&serverAddr), &len); + LOG_ALWAYS_FATAL_IF(0 != ret, "Failed to getsockname: %s", strerror(errno)); + LOG_ALWAYS_FATAL_IF(len < sizeof(serverAddr), "getsockname didn't read the full addr struct"); + ret = TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/)); - LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", vsockPort, + LOG_ALWAYS_FATAL_IF(0 != ret, "Could not listen socket on port %u: %s", serverAddr.svm_port, strerror(errno)); // Try to connect to the server using the VMADDR_CID_LOCAL cid @@ -1183,13 +1180,13 @@ bool testSupportVsockLoopback() { // and they return ETIMEDOUT after that. unique_fd connectFd( TEMP_FAILURE_RETRY(socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0))); - LOG_ALWAYS_FATAL_IF(!connectFd.ok(), "Could not create socket for port %u: %s", vsockPort, - strerror(errno)); + LOG_ALWAYS_FATAL_IF(!connectFd.ok(), "Could not create socket for port %u: %s", + serverAddr.svm_port, strerror(errno)); bool success = false; sockaddr_vm connectAddr{ .svm_family = AF_VSOCK, - .svm_port = vsockPort, + .svm_port = serverAddr.svm_port, .svm_cid = VMADDR_CID_LOCAL, }; ret = TEMP_FAILURE_RETRY(connect(connectFd.get(), reinterpret_cast(&connectAddr), @@ -1538,8 +1535,9 @@ public: }; } break; case SocketType::VSOCK: { - auto port = allocateVsockPort(); - auto status = rpcServer->setupVsockServer(VMADDR_CID_LOCAL, port); + unsigned port; + auto status = + rpcServer->setupVsockServer(VMADDR_CID_LOCAL, VMADDR_PORT_ANY, &port); if (status != OK) { return AssertionFailure() << "setupVsockServer: " << statusToString(status); } diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp index 28125f169c..aef946481f 100644 --- a/libs/binder/tests/binderRpcTestService.cpp +++ b/libs/binder/tests/binderRpcTestService.cpp @@ -143,8 +143,8 @@ int main(int argc, char* argv[]) { break; case SocketType::VSOCK: LOG_ALWAYS_FATAL_IF(OK != - server->setupVsockServer(VMADDR_CID_LOCAL, - serverConfig.vsockPort), + server->setupVsockServer(VMADDR_CID_LOCAL, VMADDR_PORT_ANY, + &outPort), "Need `sudo modprobe vsock_loopback`?"); break; case SocketType::INET: { -- GitLab From e1f9d9778f80c498b6c6747157006302224e652f Mon Sep 17 00:00:00 2001 From: Justin Yun Date: Fri, 28 Jun 2024 13:37:32 +0900 Subject: [PATCH 056/530] Define android.software.credentials.xml as prebuilt_etc Instead of using PRODUCT_COPY_FILES to copy a source file to install, define a prebuilt_etc module and add it to the PRODUCT_PACKAGES. android.software.credentials.xml is to be installed in system for GSI. Bug: 345373198 Test: See if android.software.credentials.xml is installed in system/etc/permissions Change-Id: Ib9f030e1e0ff6db55a6e07444943407f9ff1c1df --- data/etc/Android.bp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/data/etc/Android.bp b/data/etc/Android.bp index b63d14b2cb..ab09de102b 100644 --- a/data/etc/Android.bp +++ b/data/etc/Android.bp @@ -370,6 +370,14 @@ prebuilt_etc { defaults: ["frameworks_native_data_etc_defaults"], } +// installed in system for GSI +prebuilt_etc { + name: "android.software.credentials.prebuilt.xml", + relative_install_path: "permissions", + src: "android.software.credentials.xml", + filename_from_src: true, +} + prebuilt_etc { name: "android.software.device_id_attestation.prebuilt.xml", src: "android.software.device_id_attestation.xml", -- GitLab From 994989902a02e97f371a7ac86845d9a9eba48553 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Thu, 27 Jun 2024 22:46:40 -0700 Subject: [PATCH 057/530] libdumputils: avoid set A container of const T uses std::allocator, which was an undocumented libc++ extension that has been removed. See https://github.com/llvm/llvm-project/pull/96319. Bug: 349681543 Test: m libdumputils Change-Id: Ie673d1f16ebe25050e4f04a2fce797cb6a98f2d9 --- libs/dumputils/dump_utils.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index f4cf11edb6..a9bd11e41d 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ #include +#include #include #include @@ -115,7 +116,7 @@ static const std::vector aidl_interfaces_to_dump { /* list of extra hal interfaces to dump containing process during native dumps */ // This is filled when dumpstate is called. -static std::set extra_hal_interfaces_to_dump; +static std::set extra_hal_interfaces_to_dump; static void read_extra_hals_to_dump_from_property() { // extra hals to dump are already filled @@ -129,7 +130,7 @@ static void read_extra_hals_to_dump_from_property() { if (trimmed_token.length() == 0) { continue; } - extra_hal_interfaces_to_dump.insert(trimmed_token); + extra_hal_interfaces_to_dump.insert(std::move(trimmed_token)); } } -- GitLab From 40800e1b0eed45e30c3f05e0e9829be2f83a7fc4 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Thu, 27 Jun 2024 23:03:32 -0700 Subject: [PATCH 058/530] librenderengine: avoid vector A container of const T uses std::allocator, which was an undocumented libc++ extension that has been removed. See https://github.com/llvm/llvm-project/pull/96319. Bug: 349681543 Test: m librenderengine Change-Id: I4c0f5adb94415777f832217bc8115e04de6186c5 --- libs/renderengine/skia/Cache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index abe0d9b0a6..7b3b176d79 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -718,8 +718,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine, bool shouldPrimeUlt const auto externalTexture = std::make_shared(externalBuffer, *renderengine, impl::ExternalTexture::Usage::READABLE); - std::vector> textures = - {srcTexture, externalTexture}; + std::vector> textures = {srcTexture, externalTexture}; // Another external texture with a different pixel format triggers useIsOpaqueWorkaround. // It doesn't have to be f16, but it can't be the usual 8888. -- GitLab From 658fdc7dd6df246b6873d02cbbb94e0f79f5cc33 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Thu, 27 Jun 2024 23:23:21 -0700 Subject: [PATCH 059/530] libcompositionengine: avoid vector A container of const T uses std::allocator, which was an undocumented libc++ extension that has been removed. See https://github.com/llvm/llvm-project/pull/96319. Bug: 349681543 Test: m libcompositionengine Change-Id: I359350a298fc9a59c0ca925a36f753ac3fb3b64e --- .../include/compositionengine/impl/planner/Predictor.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h index 6be673597e..9c0e072f2e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h @@ -92,15 +92,15 @@ public: } private: - std::vector copyLayers(const std::vector& layers) { - std::vector copiedLayers; + std::vector copyLayers(const std::vector& layers) { + std::vector copiedLayers; copiedLayers.reserve(layers.size()); std::transform(layers.cbegin(), layers.cend(), std::back_inserter(copiedLayers), [](const LayerState* layerState) { return *layerState; }); return copiedLayers; } - std::vector mLayers; + std::vector mLayers; // TODO(b/180976743): Tune kMaxDifferingFields constexpr static int kMaxDifferingFields = 6; -- GitLab From d56514e908eb4b0738a56930a4d9e8e81a545bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20M=C3=BCtschard?= Date: Fri, 24 May 2024 17:37:13 +0200 Subject: [PATCH 060/530] Jank callback API refactor. Removes the old work-arounds for missing jank callbacks. Removes the jank data from the transaction completed callback. Adds new function to ISurfaceComposer to register jank listeners. With the new API, jank data is only sent over binder periodically (every ~50 frames) and on a background thread. It is also only tracked for layers where there is a listener registered. Test: manual, libsurfaceflinger_unittest Bug: http://b/336461947 Flag: EXEMPT refactor Change-Id: I3238ce604571832523525cf098832c7352879826 --- libs/gui/ITransactionCompletedListener.cpp | 48 +--- libs/gui/SurfaceComposerClient.cpp | 224 +++++++++++++----- libs/gui/aidl/android/gui/IJankListener.aidl | 29 +++ .../aidl/android/gui/ISurfaceComposer.aidl | 19 ++ libs/gui/aidl/android/gui/JankData.aidl | 35 +++ .../gui/ITransactionCompletedListener.h | 38 +-- libs/gui/include/gui/SurfaceComposerClient.h | 100 ++++++-- libs/gui/tests/Surface_test.cpp | 13 + services/surfaceflinger/Android.bp | 3 +- .../FrameTimeline/FrameTimeline.cpp | 9 + services/surfaceflinger/Jank/JankTracker.cpp | 206 ++++++++++++++++ services/surfaceflinger/Jank/JankTracker.h | 99 ++++++++ services/surfaceflinger/Layer.cpp | 66 +----- services/surfaceflinger/Layer.h | 10 - services/surfaceflinger/SurfaceFlinger.cpp | 37 ++- services/surfaceflinger/SurfaceFlinger.h | 6 + .../TransactionCallbackInvoker.cpp | 13 +- .../TransactionCallbackInvoker.h | 7 +- .../surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/FrameTimelineTest.cpp | 63 +++++ .../tests/unittests/JankTrackerTest.cpp | 216 +++++++++++++++++ .../unittests/TransactionSurfaceFrameTest.cpp | 91 +------ 22 files changed, 999 insertions(+), 334 deletions(-) create mode 100644 libs/gui/aidl/android/gui/IJankListener.aidl create mode 100644 libs/gui/aidl/android/gui/JankData.aidl create mode 100644 services/surfaceflinger/Jank/JankTracker.cpp create mode 100644 services/surfaceflinger/Jank/JankTracker.h create mode 100644 services/surfaceflinger/tests/unittests/JankTrackerTest.cpp diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index f5d19aac78..83fc827c5f 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -43,12 +43,6 @@ enum class Tag : uint32_t { } // Anonymous namespace -namespace { // Anonymous - -constexpr int32_t kSerializedCallbackTypeOnCompelteWithJankData = 2; - -} // Anonymous namespace - status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { status_t err = output->writeUint64(frameNumber); if (err != NO_ERROR) return err; @@ -119,23 +113,6 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } -JankData::JankData() - : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {} - -status_t JankData::writeToParcel(Parcel* output) const { - SAFE_PARCEL(output->writeInt64, frameVsyncId); - SAFE_PARCEL(output->writeInt32, jankType); - SAFE_PARCEL(output->writeInt64, frameIntervalNs); - return NO_ERROR; -} - -status_t JankData::readFromParcel(const Parcel* input) { - SAFE_PARCEL(input->readInt64, &frameVsyncId); - SAFE_PARCEL(input->readInt32, &jankType); - SAFE_PARCEL(input->readInt64, &frameIntervalNs); - return NO_ERROR; -} - status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, surfaceControl); if (const auto* acquireFence = std::get_if>(&acquireTimeOrFence)) { @@ -160,10 +137,6 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount); SAFE_PARCEL(output->writeParcelable, eventStats); - SAFE_PARCEL(output->writeInt32, static_cast(jankData.size())); - for (const auto& data : jankData) { - SAFE_PARCEL(output->writeParcelable, data); - } SAFE_PARCEL(output->writeParcelable, previousReleaseCallbackId); return NO_ERROR; } @@ -200,13 +173,6 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readUint32, ¤tMaxAcquiredBufferCount); SAFE_PARCEL(input->readParcelable, &eventStats); - int32_t jankData_size = 0; - SAFE_PARCEL_READ_SIZE(input->readInt32, &jankData_size, input->dataSize()); - for (int i = 0; i < jankData_size; i++) { - JankData data; - SAFE_PARCEL(input->readParcelable, &data); - jankData.push_back(data); - } SAFE_PARCEL(input->readParcelable, &previousReleaseCallbackId); return NO_ERROR; } @@ -371,11 +337,7 @@ ListenerCallbacks ListenerCallbacks::filter(CallbackId::Type type) const { status_t CallbackId::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, id); - if (type == Type::ON_COMPLETE && includeJankData) { - SAFE_PARCEL(output->writeInt32, kSerializedCallbackTypeOnCompelteWithJankData); - } else { - SAFE_PARCEL(output->writeInt32, static_cast(type)); - } + SAFE_PARCEL(output->writeInt32, static_cast(type)); return NO_ERROR; } @@ -383,13 +345,7 @@ status_t CallbackId::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readInt64, &id); int32_t typeAsInt; SAFE_PARCEL(input->readInt32, &typeAsInt); - if (typeAsInt == kSerializedCallbackTypeOnCompelteWithJankData) { - type = Type::ON_COMPLETE; - includeJankData = true; - } else { - type = static_cast(typeAsInt); - includeJankData = false; - } + type = static_cast(typeAsInt); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index af91bb3ae2..e2ac1d5de5 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -86,7 +86,8 @@ int64_t generateId() { return (((int64_t)getpid()) << 32) | ++idCounter; } -void emptyCallback(nsecs_t, const sp&, const std::vector&) {} +constexpr int64_t INVALID_VSYNC = -1; + } // namespace const std::string SurfaceComposerClient::kEmpty{}; @@ -207,9 +208,168 @@ sp SurfaceComposerClient::getDefault() { return DefaultComposerClient::getComposerClient(); } +// --------------------------------------------------------------------------- + JankDataListener::~JankDataListener() { } +status_t JankDataListener::flushJankData() { + if (mLayerId == -1) { + return INVALID_OPERATION; + } + + binder::Status status = ComposerServiceAIDL::getComposerService()->flushJankData(mLayerId); + return statusTFromBinderStatus(status); +} + +std::mutex JankDataListenerFanOut::sFanoutInstanceMutex; +std::unordered_map> JankDataListenerFanOut::sFanoutInstances; + +binder::Status JankDataListenerFanOut::onJankData(const std::vector& jankData) { + // Find the highest VSync ID. + int64_t lastVsync = jankData.empty() + ? 0 + : std::max_element(jankData.begin(), jankData.end(), + [](const gui::JankData& jd1, const gui::JankData& jd2) { + return jd1.frameVsyncId < jd2.frameVsyncId; + }) + ->frameVsyncId; + + // Fan out the jank data callback. + std::vector> listenersToRemove; + for (auto listener : getActiveListeners()) { + if (!listener->onJankDataAvailable(jankData) || + (listener->mRemoveAfter >= 0 && listener->mRemoveAfter <= lastVsync)) { + listenersToRemove.push_back(listener); + } + } + + return removeListeners(listenersToRemove) + ? binder::Status::ok() + : binder::Status::fromExceptionCode(binder::Status::EX_NULL_POINTER); +} + +status_t JankDataListenerFanOut::addListener(sp sc, sp listener) { + sp layer = sc->getHandle(); + if (layer == nullptr) { + return UNEXPECTED_NULL; + } + int32_t layerId = sc->getLayerId(); + + sFanoutInstanceMutex.lock(); + auto it = sFanoutInstances.find(layerId); + bool registerNeeded = it == sFanoutInstances.end(); + sp fanout; + if (registerNeeded) { + fanout = sp::make(layerId); + sFanoutInstances.insert({layerId, fanout}); + } else { + fanout = it->second; + } + + fanout->mMutex.lock(); + fanout->mListeners.insert(listener); + fanout->mMutex.unlock(); + + sFanoutInstanceMutex.unlock(); + + if (registerNeeded) { + binder::Status status = + ComposerServiceAIDL::getComposerService()->addJankListener(layer, fanout); + return statusTFromBinderStatus(status); + } + return OK; +} + +status_t JankDataListenerFanOut::removeListener(sp listener) { + int32_t layerId = listener->mLayerId; + if (layerId == -1) { + return INVALID_OPERATION; + } + + int64_t removeAfter = INVALID_VSYNC; + sp fanout; + + sFanoutInstanceMutex.lock(); + auto it = sFanoutInstances.find(layerId); + if (it != sFanoutInstances.end()) { + fanout = it->second; + removeAfter = fanout->updateAndGetRemovalVSync(); + } + + if (removeAfter != INVALID_VSYNC) { + // Remove this instance from the map, so that no new listeners are added + // while we're scheduled to be removed. + sFanoutInstances.erase(layerId); + } + sFanoutInstanceMutex.unlock(); + + if (removeAfter < 0) { + return OK; + } + + binder::Status status = + ComposerServiceAIDL::getComposerService()->removeJankListener(layerId, fanout, + removeAfter); + return statusTFromBinderStatus(status); +} + +std::vector> JankDataListenerFanOut::getActiveListeners() { + std::scoped_lock lock(mMutex); + + std::vector> listeners; + for (auto it = mListeners.begin(); it != mListeners.end();) { + auto listener = it->promote(); + if (!listener) { + it = mListeners.erase(it); + } else { + listeners.push_back(std::move(listener)); + it++; + } + } + return listeners; +} + +bool JankDataListenerFanOut::removeListeners(const std::vector>& listeners) { + std::scoped_lock fanoutLock(sFanoutInstanceMutex); + std::scoped_lock listenersLock(mMutex); + + for (auto listener : listeners) { + mListeners.erase(listener); + } + + if (mListeners.empty()) { + sFanoutInstances.erase(mLayerId); + return false; + } + return true; +} + +int64_t JankDataListenerFanOut::updateAndGetRemovalVSync() { + std::scoped_lock lock(mMutex); + if (mRemoveAfter >= 0) { + // We've already been scheduled to be removed. Don't schedule again. + return INVALID_VSYNC; + } + + int64_t removeAfter = 0; + for (auto it = mListeners.begin(); it != mListeners.end();) { + auto listener = it->promote(); + if (!listener) { + it = mListeners.erase(it); + } else if (listener->mRemoveAfter < 0) { + // We have at least one listener that's still interested. Don't remove. + return INVALID_VSYNC; + } else { + removeAfter = std::max(removeAfter, listener->mRemoveAfter); + it++; + } + } + + mRemoveAfter = removeAfter; + return removeAfter; +} + // --------------------------------------------------------------------------- // TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs @@ -256,14 +416,6 @@ CallbackId TransactionCompletedListener::addCallbackFunction( surfaceControls, CallbackId::Type callbackType) { std::lock_guard lock(mMutex); - return addCallbackFunctionLocked(callbackFunction, surfaceControls, callbackType); -} - -CallbackId TransactionCompletedListener::addCallbackFunctionLocked( - const TransactionCompletedCallback& callbackFunction, - const std::unordered_set, SurfaceComposerClient::SCHash>& - surfaceControls, - CallbackId::Type callbackType) { startListeningLocked(); CallbackId callbackId(getNextIdLocked(), callbackType); @@ -272,33 +424,11 @@ CallbackId TransactionCompletedListener::addCallbackFunctionLocked( for (const auto& surfaceControl : surfaceControls) { callbackSurfaceControls[surfaceControl->getHandle()] = surfaceControl; - - if (callbackType == CallbackId::Type::ON_COMPLETE && - mJankListeners.count(surfaceControl->getLayerId()) != 0) { - callbackId.includeJankData = true; - } } return callbackId; } -void TransactionCompletedListener::addJankListener(const sp& listener, - sp surfaceControl) { - std::lock_guard lock(mMutex); - mJankListeners.insert({surfaceControl->getLayerId(), listener}); -} - -void TransactionCompletedListener::removeJankListener(const sp& listener) { - std::lock_guard lock(mMutex); - for (auto it = mJankListeners.begin(); it != mJankListeners.end();) { - if (it->second == listener) { - it = mJankListeners.erase(it); - } else { - it++; - } - } -} - void TransactionCompletedListener::setReleaseBufferCallback(const ReleaseCallbackId& callbackId, ReleaseBufferCallback listener) { std::scoped_lock lock(mMutex); @@ -325,32 +455,20 @@ void TransactionCompletedListener::removeSurfaceStatsListener(void* context, voi } void TransactionCompletedListener::addSurfaceControlToCallbacks( - SurfaceComposerClient::CallbackInfo& callbackInfo, - const sp& surfaceControl) { + const sp& surfaceControl, + const std::unordered_set& callbackIds) { std::lock_guard lock(mMutex); - bool includingJankData = false; - for (auto callbackId : callbackInfo.callbackIds) { + for (auto callbackId : callbackIds) { mCallbacks[callbackId].surfaceControls.emplace(std::piecewise_construct, std::forward_as_tuple( surfaceControl->getHandle()), std::forward_as_tuple(surfaceControl)); - includingJankData = includingJankData || callbackId.includeJankData; - } - - // If no registered callback is requesting jank data, but there is a jank listener registered - // on the new surface control, add a synthetic callback that requests the jank data. - if (!includingJankData && mJankListeners.count(surfaceControl->getLayerId()) != 0) { - CallbackId callbackId = - addCallbackFunctionLocked(&emptyCallback, callbackInfo.surfaceControls, - CallbackId::Type::ON_COMPLETE); - callbackInfo.callbackIds.emplace(callbackId); } } void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map callbacksMap; - std::multimap> jankListenersMap; { std::lock_guard lock(mMutex); @@ -366,7 +484,6 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener * sp that could possibly exist for the callbacks. */ callbacksMap = mCallbacks; - jankListenersMap = mJankListeners; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); @@ -486,12 +603,6 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener transactionStats.presentFence, surfaceStats); } } - - if (surfaceStats.jankData.empty()) continue; - auto jankRange = jankListenersMap.equal_range(layerId); - for (auto it = jankRange.first; it != jankRange.second; it++) { - it->second->onJankDataAvailable(surfaceStats.jankData); - } } } } @@ -1004,8 +1115,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr // register all surface controls for all callbackIds for this listener that is merging for (const auto& surfaceControl : currentProcessCallbackInfo.surfaceControls) { - mTransactionCompletedListener->addSurfaceControlToCallbacks(currentProcessCallbackInfo, - surfaceControl); + mTransactionCompletedListener + ->addSurfaceControlToCallbacks(surfaceControl, + currentProcessCallbackInfo.callbackIds); } } @@ -1361,7 +1473,7 @@ void SurfaceComposerClient::Transaction::registerSurfaceControlForCallback( auto& callbackInfo = mListenerCallbacks[TransactionCompletedListener::getIInstance()]; callbackInfo.surfaceControls.insert(sc); - mTransactionCompletedListener->addSurfaceControlToCallbacks(callbackInfo, sc); + mTransactionCompletedListener->addSurfaceControlToCallbacks(sc, callbackInfo.callbackIds); } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition( diff --git a/libs/gui/aidl/android/gui/IJankListener.aidl b/libs/gui/aidl/android/gui/IJankListener.aidl new file mode 100644 index 0000000000..2bfd1af69d --- /dev/null +++ b/libs/gui/aidl/android/gui/IJankListener.aidl @@ -0,0 +1,29 @@ +/* + * Copyright 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. + */ + +package android.gui; + +import android.gui.JankData; + +/** @hide */ +interface IJankListener { + + /** + * Callback reporting jank data of the most recent frames. + * @See {@link ISurfaceComposer#addJankListener(IBinder, IJankListener)} + */ + void onJankData(in JankData[] data); +} diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index 6d018ea7ef..ac14138e8c 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -42,6 +42,7 @@ import android.gui.ISurfaceComposerClient; import android.gui.ITunnelModeEnabledListener; import android.gui.IWindowInfosListener; import android.gui.IWindowInfosPublisher; +import android.gui.IJankListener; import android.gui.LayerCaptureArgs; import android.gui.OverlayProperties; import android.gui.PullAtomData; @@ -580,4 +581,22 @@ interface ISurfaceComposer { * This method should not block the ShutdownThread therefore it's handled asynchronously. */ oneway void notifyShutdown(); + + /** + * Registers the jank listener on the given layer to receive jank data of future frames. + */ + void addJankListener(IBinder layer, IJankListener listener); + + /** + * Flushes any pending jank data on the given layer to any registered listeners on that layer. + */ + oneway void flushJankData(int layerId); + + /** + * Schedules the removal of the jank listener from the given layer after the VSync with the + * specified ID. Use a value <= 0 for afterVsync to remove the listener immediately. The given + * listener will not be removed before the given VSync, but may still receive data for frames + * past the provided VSync. + */ + oneway void removeJankListener(int layerId, IJankListener listener, long afterVsync); } diff --git a/libs/gui/aidl/android/gui/JankData.aidl b/libs/gui/aidl/android/gui/JankData.aidl new file mode 100644 index 0000000000..7ea9d22ecf --- /dev/null +++ b/libs/gui/aidl/android/gui/JankData.aidl @@ -0,0 +1,35 @@ +/* + * Copyright 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. + */ + + package android.gui; + + /** @hide */ +parcelable JankData { + /** + * Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId + */ + long frameVsyncId; + + /** + * Bitmask of jank types that occurred. + */ + int jankType; + + /** + * Expected duration in nanoseconds of this frame. + */ + long frameIntervalNs; +} diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index bc97cd0828..014029b257 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -16,8 +16,6 @@ #pragma once -#include "JankInfo.h" - #include #include #include @@ -40,15 +38,10 @@ class ListenerCallbacks; class CallbackId : public Parcelable { public: int64_t id; - enum class Type : int32_t { - ON_COMPLETE = 0, - ON_COMMIT = 1, - /*reserved for serialization = 2*/ - } type; - bool includeJankData; // Only respected for ON_COMPLETE callbacks. + enum class Type : int32_t { ON_COMPLETE = 0, ON_COMMIT = 1 } type; CallbackId() {} - CallbackId(int64_t id, Type type) : id(id), type(type), includeJankData(false) {} + CallbackId(int64_t id, Type type) : id(id), type(type) {} status_t writeToParcel(Parcel* output) const override; status_t readFromParcel(const Parcel* input) override; @@ -113,29 +106,6 @@ public: nsecs_t dequeueReadyTime; }; -/** - * Jank information representing SurfaceFlinger's jank classification about frames for a specific - * surface. - */ -class JankData : public Parcelable { -public: - status_t writeToParcel(Parcel* output) const override; - status_t readFromParcel(const Parcel* input) override; - - JankData(); - JankData(int64_t frameVsyncId, int32_t jankType, nsecs_t frameIntervalNs) - : frameVsyncId(frameVsyncId), jankType(jankType), frameIntervalNs(frameIntervalNs) {} - - // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId - int64_t frameVsyncId; - - // Bitmask of janks that occurred - int32_t jankType; - - // Expected duration of the frame - nsecs_t frameIntervalNs; -}; - class SurfaceStats : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; @@ -145,14 +115,13 @@ public: SurfaceStats(const sp& sc, std::variant> acquireTimeOrFence, const sp& prevReleaseFence, std::optional hint, uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats, - std::vector jankData, ReleaseCallbackId previousReleaseCallbackId) + ReleaseCallbackId previousReleaseCallbackId) : surfaceControl(sc), acquireTimeOrFence(std::move(acquireTimeOrFence)), previousReleaseFence(prevReleaseFence), transformHint(hint), currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount), eventStats(frameEventStats), - jankData(std::move(jankData)), previousReleaseCallbackId(previousReleaseCallbackId) {} sp surfaceControl; @@ -161,7 +130,6 @@ public: std::optional transformHint = 0; uint32_t currentMaxAcquiredBufferCount = 0; FrameEventHistoryStats eventStats; - std::vector jankData; ReleaseCallbackId previousReleaseCallbackId; }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 0862e03c44..88c0c53e12 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -864,12 +865,82 @@ public: // --------------------------------------------------------------------------- -class JankDataListener : public VirtualLightRefBase { +class JankDataListener; + +// Acts as a representative listener to the composer for a single layer and +// forwards any received jank data to multiple listeners. Will remove itself +// from the composer only once the last listener is removed. +class JankDataListenerFanOut : public gui::BnJankListener { public: - virtual ~JankDataListener() = 0; - virtual void onJankDataAvailable(const std::vector& jankData) = 0; + JankDataListenerFanOut(int32_t layerId) : mLayerId(layerId) {} + + binder::Status onJankData(const std::vector& jankData) override; + + static status_t addListener(sp sc, sp listener); + static status_t removeListener(sp listener); + +private: + std::vector> getActiveListeners(); + bool removeListeners(const std::vector>& listeners); + int64_t updateAndGetRemovalVSync(); + + struct WpJDLHash { + std::size_t operator()(const wp& listener) const { + return std::hash{}(listener.unsafe_get()); + } + }; + + std::mutex mMutex; + std::unordered_set, WpJDLHash> mListeners GUARDED_BY(mMutex); + int32_t mLayerId; + int64_t mRemoveAfter = -1; + + static std::mutex sFanoutInstanceMutex; + static std::unordered_map> sFanoutInstances; }; +// Base class for client listeners interested in jank classification data from +// the composer. Subclasses should override onJankDataAvailable and call the add +// and removal methods to receive jank data. +class JankDataListener : public virtual RefBase { +public: + JankDataListener() {} + virtual ~JankDataListener(); + + virtual bool onJankDataAvailable(const std::vector& jankData) = 0; + + status_t addListener(sp sc) { + if (mLayerId != -1) { + removeListener(0); + mLayerId = -1; + } + + int32_t layerId = sc->getLayerId(); + status_t status = + JankDataListenerFanOut::addListener(std::move(sc), + sp::fromExisting(this)); + if (status == OK) { + mLayerId = layerId; + } + return status; + } + + status_t removeListener(int64_t afterVsync) { + mRemoveAfter = std::max(static_cast(0), afterVsync); + return JankDataListenerFanOut::removeListener(sp::fromExisting(this)); + } + + status_t flushJankData(); + + friend class JankDataListenerFanOut; + +private: + int32_t mLayerId = -1; + int64_t mRemoveAfter = -1; +}; + +// --------------------------------------------------------------------------- + class TransactionCompletedListener : public BnTransactionCompletedListener { public: TransactionCompletedListener(); @@ -904,7 +975,6 @@ protected: std::unordered_map mCallbacks GUARDED_BY(mMutex); - std::multimap> mJankListeners GUARDED_BY(mMutex); std::unordered_map mReleaseBufferCallbacks GUARDED_BY(mMutex); @@ -927,14 +997,10 @@ public: const std::unordered_set, SurfaceComposerClient::SCHash>& surfaceControls, CallbackId::Type callbackType); - CallbackId addCallbackFunctionLocked( - const TransactionCompletedCallback& callbackFunction, - const std::unordered_set, SurfaceComposerClient::SCHash>& - surfaceControls, - CallbackId::Type callbackType) REQUIRES(mMutex); - void addSurfaceControlToCallbacks(SurfaceComposerClient::CallbackInfo& callbackInfo, - const sp& surfaceControl); + void addSurfaceControlToCallbacks( + const sp& surfaceControl, + const std::unordered_set& callbackIds); void addQueueStallListener(std::function stallListener, void* id); void removeQueueStallListener(void *id); @@ -943,18 +1009,6 @@ public: TrustedPresentationCallback tpc, int id, void* context); void clearTrustedPresentationCallback(int id); - /* - * Adds a jank listener to be informed about SurfaceFlinger's jank classification for a specific - * surface. Jank classifications arrive as part of the transaction callbacks about previous - * frames submitted to this Surface. - */ - void addJankListener(const sp& listener, sp surfaceControl); - - /** - * Removes a jank listener previously added to addJankCallback. - */ - void removeJankListener(const sp& listener); - void addSurfaceStatsListener(void* context, void* cookie, sp surfaceControl, SurfaceStatsCallback listener); void removeSurfaceStatsListener(void* context, void* cookie); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 43cd0f8a7f..ace442339d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -987,6 +987,19 @@ public: binder::Status notifyShutdown() override { return binder::Status::ok(); } + binder::Status addJankListener(const sp& /*layer*/, + const sp& /*listener*/) override { + return binder::Status::ok(); + } + + binder::Status flushJankData(int32_t /*layerId*/) override { return binder::Status::ok(); } + + binder::Status removeJankListener(int32_t /*layerId*/, + const sp& /*listener*/, + int64_t /*afterVsync*/) override { + return binder::Status::ok(); + } + protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 1b6c598372..a37433cead 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -85,7 +85,7 @@ cc_defaults { "libui", "libutils", "libSurfaceFlingerProp", - "libaconfig_storage_read_api_cc" + "libaconfig_storage_read_api_cc", ], static_libs: [ "iinputflinger_aidl_lib_static", @@ -187,6 +187,7 @@ filegroup { "FrameTracker.cpp", "HdrLayerInfoReporter.cpp", "HdrSdrRatioOverlay.cpp", + "Jank/JankTracker.cpp", "WindowInfosListenerInvoker.cpp", "Layer.cpp", "LayerFE.cpp", diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 2596a25d15..f671006149 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -30,6 +30,8 @@ #include #include +#include "../Jank/JankTracker.h" + namespace android::frametimeline { using base::StringAppendF; @@ -685,6 +687,13 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName, mGameMode, mJankType, displayDeadlineDelta, displayPresentDelta, deadlineDelta}); + + gui::JankData jd; + jd.frameVsyncId = mToken; + jd.jankType = mJankType; + jd.frameIntervalNs = + (mRenderRate ? *mRenderRate : mDisplayFrameRenderRate).getPeriodNsecs(); + JankTracker::onJankData(mLayerId, jd); } } diff --git a/services/surfaceflinger/Jank/JankTracker.cpp b/services/surfaceflinger/Jank/JankTracker.cpp new file mode 100644 index 0000000000..8e0e084cd2 --- /dev/null +++ b/services/surfaceflinger/Jank/JankTracker.cpp @@ -0,0 +1,206 @@ +/* + * Copyright 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. + */ + +#include "JankTracker.h" + +#include +#include "BackgroundExecutor.h" + +namespace android { + +namespace { + +constexpr size_t kJankDataBatchSize = 50; + +} // anonymous namespace + +std::atomic JankTracker::sListenerCount(0); +std::atomic JankTracker::sCollectAllJankDataForTesting(false); + +JankTracker::~JankTracker() {} + +void JankTracker::addJankListener(int32_t layerId, sp listener) { + // Increment right away, so that if an onJankData call comes in before the background thread has + // added this listener, it will not drop the data. + sListenerCount++; + + BackgroundExecutor::getLowPriorityInstance().sendCallbacks( + {[layerId, listener = std::move(listener)]() { + JankTracker& tracker = getInstance(); + const std::lock_guard _l(tracker.mLock); + tracker.addJankListenerLocked(layerId, listener); + }}); +} + +void JankTracker::flushJankData(int32_t layerId) { + BackgroundExecutor::getLowPriorityInstance().sendCallbacks( + {[layerId]() { getInstance().doFlushJankData(layerId); }}); +} + +void JankTracker::removeJankListener(int32_t layerId, sp listener, int64_t afterVsync) { + BackgroundExecutor::getLowPriorityInstance().sendCallbacks( + {[layerId, listener = std::move(listener), afterVsync]() { + JankTracker& tracker = getInstance(); + const std::lock_guard _l(tracker.mLock); + tracker.markJankListenerForRemovalLocked(layerId, listener, afterVsync); + }}); +} + +void JankTracker::onJankData(int32_t layerId, gui::JankData data) { + if (sListenerCount == 0) { + return; + } + + BackgroundExecutor::getLowPriorityInstance().sendCallbacks( + {[layerId, data = std::move(data)]() { + JankTracker& tracker = getInstance(); + + tracker.mLock.lock(); + bool hasListeners = tracker.mJankListeners.count(layerId) > 0; + tracker.mLock.unlock(); + + if (!hasListeners && !sCollectAllJankDataForTesting) { + return; + } + + tracker.mJankDataLock.lock(); + tracker.mJankData.emplace(layerId, data); + size_t count = tracker.mJankData.count(layerId); + tracker.mJankDataLock.unlock(); + + if (count >= kJankDataBatchSize && !sCollectAllJankDataForTesting) { + tracker.doFlushJankData(layerId); + } + }}); +} + +void JankTracker::addJankListenerLocked(int32_t layerId, sp listener) { + for (auto it = mJankListeners.find(layerId); it != mJankListeners.end(); it++) { + if (it->second.mListener == listener) { + // Undo the duplicate increment in addJankListener. + sListenerCount--; + return; + } + } + + mJankListeners.emplace(layerId, std::move(listener)); +} + +void JankTracker::doFlushJankData(int32_t layerId) { + std::vector jankData; + int64_t maxVsync = transferAvailableJankData(layerId, jankData); + + std::vector> toSend; + + mLock.lock(); + for (auto it = mJankListeners.find(layerId); it != mJankListeners.end();) { + if (!jankData.empty()) { + toSend.emplace_back(it->second.mListener); + } + + int64_t removeAfter = it->second.mRemoveAfter; + if (removeAfter != -1 && removeAfter <= maxVsync) { + it = mJankListeners.erase(it); + sListenerCount--; + } else { + it++; + } + } + mLock.unlock(); + + for (const auto& listener : toSend) { + binder::Status status = interface_cast(listener)->onJankData(jankData); + if (status.exceptionCode() == binder::Status::EX_NULL_POINTER) { + // Remove any listeners, where the App side has gone away, without + // deregistering. + dropJankListener(layerId, listener); + } + } +} + +void JankTracker::markJankListenerForRemovalLocked(int32_t layerId, sp listener, + int64_t afterVysnc) { + for (auto it = mJankListeners.find(layerId); it != mJankListeners.end(); it++) { + if (it->second.mListener == listener) { + it->second.mRemoveAfter = std::max(static_cast(0), afterVysnc); + return; + } + } +} + +int64_t JankTracker::transferAvailableJankData(int32_t layerId, + std::vector& outJankData) { + const std::lock_guard _l(mJankDataLock); + int64_t maxVsync = 0; + auto range = mJankData.equal_range(layerId); + for (auto it = range.first; it != range.second;) { + maxVsync = std::max(it->second.frameVsyncId, maxVsync); + outJankData.emplace_back(std::move(it->second)); + it = mJankData.erase(it); + } + return maxVsync; +} + +void JankTracker::dropJankListener(int32_t layerId, sp listener) { + const std::lock_guard _l(mLock); + for (auto it = mJankListeners.find(layerId); it != mJankListeners.end(); it++) { + if (it->second.mListener == listener) { + mJankListeners.erase(it); + sListenerCount--; + return; + } + } +} + +void JankTracker::clearAndStartCollectingAllJankDataForTesting() { + BackgroundExecutor::getLowPriorityInstance().flushQueue(); + + // Clear all past tracked jank data. + JankTracker& tracker = getInstance(); + const std::lock_guard _l(tracker.mJankDataLock); + tracker.mJankData.clear(); + + // Pretend there's at least one listener. + sListenerCount++; + sCollectAllJankDataForTesting = true; +} + +std::vector JankTracker::getCollectedJankDataForTesting(int32_t layerId) { + JankTracker& tracker = getInstance(); + const std::lock_guard _l(tracker.mJankDataLock); + + auto range = tracker.mJankData.equal_range(layerId); + std::vector result; + std::transform(range.first, range.second, std::back_inserter(result), + [](std::pair layerIdToJankData) { + return layerIdToJankData.second; + }); + + return result; +} + +void JankTracker::clearAndStopCollectingAllJankDataForTesting() { + // Undo startCollectingAllJankDataForTesting. + sListenerCount--; + sCollectAllJankDataForTesting = false; + + // Clear all tracked jank data. + JankTracker& tracker = getInstance(); + const std::lock_guard _l(tracker.mJankDataLock); + tracker.mJankData.clear(); +} + +} // namespace android diff --git a/services/surfaceflinger/Jank/JankTracker.h b/services/surfaceflinger/Jank/JankTracker.h new file mode 100644 index 0000000000..5917358797 --- /dev/null +++ b/services/surfaceflinger/Jank/JankTracker.h @@ -0,0 +1,99 @@ +/* + * Copyright 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. + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace android { +namespace frametimeline { +class FrameTimelineTest; +} + +/** + * JankTracker maintains a backlog of frame jank classification and manages and notififies any + * registered jank data listeners. + */ +class JankTracker { +public: + ~JankTracker(); + + static void addJankListener(int32_t layerId, sp listener); + static void flushJankData(int32_t layerId); + static void removeJankListener(int32_t layerId, sp listener, int64_t afterVysnc); + + static void onJankData(int32_t layerId, gui::JankData data); + +protected: + // The following methods can be used to force the tracker to collect all jank data and not + // flush it for a short time period and should *only* be used for testing. Every call to + // clearAndStartCollectingAllJankDataForTesting needs to be followed by a call to + // clearAndStopCollectingAllJankDataForTesting. + static void clearAndStartCollectingAllJankDataForTesting(); + static std::vector getCollectedJankDataForTesting(int32_t layerId); + static void clearAndStopCollectingAllJankDataForTesting(); + + friend class frametimeline::FrameTimelineTest; + +private: + JankTracker() {} + JankTracker(const JankTracker&) = delete; + JankTracker(JankTracker&&) = delete; + + JankTracker& operator=(const JankTracker&) = delete; + JankTracker& operator=(JankTracker&&) = delete; + + static JankTracker& getInstance() { + static JankTracker instance; + return instance; + } + + void addJankListenerLocked(int32_t layerId, sp listener) REQUIRES(mLock); + void doFlushJankData(int32_t layerId); + void markJankListenerForRemovalLocked(int32_t layerId, sp listener, int64_t afterVysnc) + REQUIRES(mLock); + + int64_t transferAvailableJankData(int32_t layerId, std::vector& jankData); + void dropJankListener(int32_t layerId, sp listener); + + struct Listener { + sp mListener; + int64_t mRemoveAfter; + + Listener(sp&& listener) : mListener(listener), mRemoveAfter(-1) {} + }; + + // We keep track of the current listener count, so that the onJankData call, which is on the + // main thread, can short-curcuit the scheduling on the background thread (which involves + // locking) if there are no listeners registered, which is the most common case. + static std::atomic sListenerCount; + static std::atomic sCollectAllJankDataForTesting; + + std::mutex mLock; + std::unordered_multimap mJankListeners GUARDED_BY(mLock); + std::mutex mJankDataLock; + std::unordered_multimap mJankData GUARDED_BY(mJankDataLock); + + friend class JankTrackerTest; +}; + +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d27bfd29ef..e758741afb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -767,41 +767,6 @@ bool Layer::isSecure() const { return (p != nullptr) ? p->isSecure() : false; } -void Layer::transferAvailableJankData(const std::deque>& handles, - std::vector& jankData) { - if (mPendingJankClassifications.empty() || - !mPendingJankClassifications.front()->getJankType()) { - return; - } - - bool includeJankData = false; - for (const auto& handle : handles) { - for (const auto& cb : handle->callbackIds) { - if (cb.includeJankData) { - includeJankData = true; - break; - } - } - - if (includeJankData) { - jankData.reserve(mPendingJankClassifications.size()); - break; - } - } - - while (!mPendingJankClassifications.empty() && - mPendingJankClassifications.front()->getJankType()) { - if (includeJankData) { - std::shared_ptr surfaceFrame = - mPendingJankClassifications.front(); - jankData.emplace_back(JankData(surfaceFrame->getToken(), - surfaceFrame->getJankType().value(), - surfaceFrame->getRenderRate().getPeriodNsecs())); - } - mPendingJankClassifications.pop_front(); - } -} - // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- @@ -1436,7 +1401,6 @@ std::shared_ptr Layer::createSurfaceFrameForTransac if (fps) { surfaceFrame->setRenderRate(*fps); } - onSurfaceFrameCreated(surfaceFrame); return surfaceFrame; } @@ -1453,7 +1417,6 @@ std::shared_ptr Layer::createSurfaceFrameForBuffer( if (fps) { surfaceFrame->setRenderRate(*fps); } - onSurfaceFrameCreated(surfaceFrame); return surfaceFrame; } @@ -1479,7 +1442,6 @@ void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info, if (fps) { surfaceFrame->setRenderRate(*fps); } - onSurfaceFrameCreated(surfaceFrame); addSurfaceFrameDroppedForBuffer(surfaceFrame, postTime); } @@ -2942,25 +2904,6 @@ void Layer::onLayerDisplayed(ftl::SharedFuture futureFenceResult, } } -void Layer::onSurfaceFrameCreated( - const std::shared_ptr& surfaceFrame) { - while (mPendingJankClassifications.size() >= kPendingClassificationMaxSurfaceFrames) { - // Too many SurfaceFrames pending classification. The front of the deque is probably not - // tracked by FrameTimeline and will never be presented. This will only result in a memory - // leak. - if (hasBufferOrSidebandStreamInDrawing()) { - // Only log for layers with a buffer, since we expect the jank data to be drained for - // these, while there may be no jank listeners for bufferless layers. - ALOGW("Removing the front of pending jank deque from layer - %s to prevent memory leak", - mName.c_str()); - std::string miniDump = mPendingJankClassifications.front()->miniDump(); - ALOGD("Head SurfaceFrame mini dump\n%s", miniDump.c_str()); - } - mPendingJankClassifications.pop_front(); - } - mPendingJankClassifications.emplace_back(surfaceFrame); -} - void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->transformHint = mTransformHint; @@ -2978,10 +2921,7 @@ void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { } } - std::vector jankData; - transferAvailableJankData(mDrawingState.callbackHandles, jankData); - mFlinger->getTransactionCallbackInvoker().addCallbackHandles(mDrawingState.callbackHandles, - jankData); + mFlinger->getTransactionCallbackInvoker().addCallbackHandles(mDrawingState.callbackHandles); mDrawingState.callbackHandles = {}; } @@ -3449,9 +3389,7 @@ bool Layer::setTransactionCompletedListeners(const std::vector jankData; - transferAvailableJankData(remainingHandles, jankData); - mFlinger->getTransactionCallbackInvoker().addCallbackHandles(remainingHandles, jankData); + mFlinger->getTransactionCallbackInvoker().addCallbackHandles(remainingHandles); } mReleasePreviousBuffer = false; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b9fcd5c333..d3b56f89d1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -980,7 +980,6 @@ protected: void preparePerFrameBufferCompositionState(); void preparePerFrameEffectsCompositionState(); void gatherBufferInfo(); - void onSurfaceFrameCreated(const std::shared_ptr&); bool isClonedFromAlive() { return getClonedFrom() != nullptr; } @@ -1195,11 +1194,6 @@ private: bool hasSomethingToDraw() const { return hasEffect() || hasBufferOrSidebandStream(); } - // Fills the provided vector with the currently available JankData and removes the processed - // JankData from the pending list. - void transferAvailableJankData(const std::deque>& handles, - std::vector& jankData); - bool shouldOverrideChildrenFrameRate() const { return getDrawingState().frameRateSelectionStrategy == FrameRateSelectionStrategy::OverrideChildren; @@ -1268,10 +1262,6 @@ private: // time. std::variant> mCallbackHandleAcquireTimeOrFence = -1; - std::deque> mPendingJankClassifications; - // An upper bound on the number of SurfaceFrames in the pending classifications deque. - static constexpr int kPendingClassificationMaxSurfaceFrames = 50; - const std::string mBlastTransactionName{"BufferTX - " + mName}; // This integer is incremented everytime a buffer arrives at the server for this layer, // and decremented when a buffer is dropped or latched. When changed the integer is exported diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5b40acf030..989020daeb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -143,6 +143,7 @@ #include "FrontEnd/LayerLog.h" #include "FrontEnd/LayerSnapshot.h" #include "HdrLayerInfoReporter.h" +#include "Jank/JankTracker.h" #include "Layer.h" #include "LayerProtoHelper.h" #include "LayerRenderArea.h" @@ -5507,10 +5508,8 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } if (layer == nullptr) { for (auto& [listener, callbackIds] : s.listeners) { - mTransactionCallbackInvoker.addCallbackHandle(sp::make(listener, - callbackIds, - s.surface), - std::vector()); + mTransactionCallbackInvoker.addCallbackHandle( + sp::make(listener, callbackIds, s.surface)); } return 0; } @@ -5868,10 +5867,8 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f } if (layer == nullptr) { for (auto& [listener, callbackIds] : s.listeners) { - mTransactionCallbackInvoker.addCallbackHandle(sp::make(listener, - callbackIds, - s.surface), - std::vector()); + mTransactionCallbackInvoker.addCallbackHandle( + sp::make(listener, callbackIds, s.surface)); } return 0; } @@ -6114,6 +6111,8 @@ void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp& layer, uint32 mTransactionHandler.onLayerDestroyed(layerId); } + JankTracker::flushJankData(layerId); + Mutex::Autolock lock(mStateLock); markLayerPendingRemovalLocked(layer); layer->onHandleDestroyed(); @@ -10463,6 +10462,28 @@ binder::Status SurfaceComposerAIDL::notifyShutdown() { return ::android::binder::Status::ok(); } +binder::Status SurfaceComposerAIDL::addJankListener(const sp& layerHandle, + const sp& listener) { + sp layer = LayerHandle::getLayer(layerHandle); + if (layer == nullptr) { + return binder::Status::fromExceptionCode(binder::Status::EX_NULL_POINTER); + } + JankTracker::addJankListener(layer->sequence, IInterface::asBinder(listener)); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::flushJankData(int32_t layerId) { + JankTracker::flushJankData(layerId); + return binder::Status::ok(); +} + +binder::Status SurfaceComposerAIDL::removeJankListener(int32_t layerId, + const sp& listener, + int64_t afterVsync) { + JankTracker::removeJankListener(layerId, IInterface::asBinder(listener), afterVsync); + return binder::Status::ok(); +} + status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) { if (!mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) { IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ee541c4364..6838994867 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1693,6 +1694,11 @@ public: int pid, std::optional* outInfo) override; binder::Status getSchedulingPolicy(gui::SchedulingPolicy* outPolicy) override; binder::Status notifyShutdown() override; + binder::Status addJankListener(const sp& layer, + const sp& listener) override; + binder::Status flushJankData(int32_t layerId) override; + binder::Status removeJankListener(int32_t layerId, const sp& listener, + int64_t afterVsync) override; private: static const constexpr bool kUsePermissionCache = true; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 222ae30acb..b9555c04a8 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -64,13 +64,12 @@ status_t TransactionCallbackInvoker::addOnCommitCallbackHandles( if (handles.empty()) { return NO_ERROR; } - const std::vector& jankData = std::vector(); for (const auto& handle : handles) { if (!containsOnCommitCallbacks(handle->callbackIds)) { outRemainingHandles.push_back(handle); continue; } - status_t err = addCallbackHandle(handle, jankData); + status_t err = addCallbackHandle(handle); if (err != NO_ERROR) { return err; } @@ -80,12 +79,12 @@ status_t TransactionCallbackInvoker::addOnCommitCallbackHandles( } status_t TransactionCallbackInvoker::addCallbackHandles( - const std::deque>& handles, const std::vector& jankData) { + const std::deque>& handles) { if (handles.empty()) { return NO_ERROR; } for (const auto& handle : handles) { - status_t err = addCallbackHandle(handle, jankData); + status_t err = addCallbackHandle(handle); if (err != NO_ERROR) { return err; } @@ -111,8 +110,7 @@ status_t TransactionCallbackInvoker::findOrCreateTransactionStats( return NO_ERROR; } -status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle, - const std::vector& jankData) { +status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle) { // If we can't find the transaction stats something has gone wrong. The client should call // startRegistration before trying to add a callback handle. TransactionStats* transactionStats; @@ -151,8 +149,7 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle->previousReleaseFence, handle->transformHint, handle->currentMaxAcquiredBufferCount, - eventStats, jankData, - handle->previousReleaseCallbackId); + eventStats, handle->previousReleaseCallbackId); } return NO_ERROR; } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index cb7150b943..7853a9f359 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -63,8 +63,7 @@ public: class TransactionCallbackInvoker { public: - status_t addCallbackHandles(const std::deque>& handles, - const std::vector& jankData); + status_t addCallbackHandles(const std::deque>& handles); status_t addOnCommitCallbackHandles(const std::deque>& handles, std::deque>& outRemainingHandles); @@ -77,9 +76,7 @@ public: mCompletedTransactions.clear(); } - status_t addCallbackHandle(const sp& handle, - const std::vector& jankData); - + status_t addCallbackHandle(const sp& handle); private: status_t findOrCreateTransactionStats(const sp& listener, diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 98d5754271..bc35639a00 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -84,6 +84,7 @@ cc_test { "FrameTimelineTest.cpp", "GameModeTest.cpp", "HWComposerTest.cpp", + "JankTrackerTest.cpp", "OneShotTimerTest.cpp", "LayerHistoryTest.cpp", "LayerHistoryIntegrationTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index dac9265b71..25437ca856 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -15,6 +15,8 @@ */ #include +#include "BackgroundExecutor.h" +#include "Jank/JankTracker.h" #include "com_android_graphics_surfaceflinger_flags.h" #include "gmock/gmock-spec-builders.h" #include "mock/MockTimeStats.h" @@ -90,8 +92,12 @@ public: mTraceCookieCounter = &mFrameTimeline->mTraceCookieCounter; maxDisplayFrames = &mFrameTimeline->mMaxDisplayFrames; maxTokens = mTokenManager->kMaxTokens; + + JankTracker::clearAndStartCollectingAllJankDataForTesting(); } + void TearDown() override { JankTracker::clearAndStopCollectingAllJankDataForTesting(); } + // Each tracing session can be used for a single block of Start -> Stop. static std::unique_ptr getTracingSessionForTest() { perfetto::TraceConfig cfg; @@ -175,6 +181,16 @@ public: [&](FrameTimelineDataSource::TraceContext ctx) { ctx.Flush(); }); } + std::vector getLayerOneJankData() { + BackgroundExecutor::getLowPriorityInstance().flushQueue(); + return JankTracker::getCollectedJankDataForTesting(sLayerIdOne); + } + + std::vector getLayerTwoJankData() { + BackgroundExecutor::getLowPriorityInstance().flushQueue(); + return JankTracker::getCollectedJankDataForTesting(sLayerIdTwo); + } + std::shared_ptr mTimeStats; std::unique_ptr mFrameTimeline; impl::TokenManager* mTokenManager; @@ -339,6 +355,9 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { EXPECT_NE(surfaceFrame1->getJankSeverityType(), std::nullopt); EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt); EXPECT_NE(surfaceFrame2->getJankSeverityType(), std::nullopt); + + EXPECT_EQ(getLayerOneJankData().size(), 1u); + EXPECT_EQ(getLayerTwoJankData().size(), 1u); } TEST_F(FrameTimelineTest, displayFrameSkippedComposition) { @@ -446,6 +465,8 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { // The window should have slided by 1 now and the previous 0th display frame // should have been removed from the deque EXPECT_EQ(compareTimelineItems(displayFrame0->getActuals(), TimelineItem(52, 57, 62)), true); + + EXPECT_EQ(getLayerOneJankData().size(), *maxDisplayFrames); } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) { @@ -575,6 +596,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_doesNotReportForInvalidTokens) { presentFence1->signalForTest(70); mFrameTimeline->setSfPresent(59, presentFence1); + + EXPECT_EQ(getLayerOneJankData().size(), 0u); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { @@ -603,6 +626,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { presentFence1->signalForTest(70); mFrameTimeline->setSfPresent(62, presentFence1); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::SurfaceFlingerCpuDeadlineMissed); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfGpu) { @@ -633,6 +660,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfGpu) { presentFence1->signalForTest(70); mFrameTimeline->setSfPresent(59, presentFence1, gpuFence1); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::SurfaceFlingerGpuDeadlineMissed); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { @@ -661,6 +692,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { mFrameTimeline->setSfPresent(56, presentFence1); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::DisplayHAL); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::DisplayHAL); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { @@ -691,6 +726,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Partial); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::AppDeadlineMissed); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) { @@ -721,6 +760,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfScheduling) { EXPECT_EQ(surfaceFrame1->getJankType(), JankType::SurfaceFlingerScheduling); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::SurfaceFlingerScheduling); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) { @@ -751,6 +794,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsSfPredictionError) { EXPECT_EQ(surfaceFrame1->getJankType(), JankType::PredictionError); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Partial); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::PredictionError); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { @@ -782,6 +829,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppBufferStuffing) { EXPECT_EQ(surfaceFrame1->getJankType(), JankType::BufferStuffing); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::BufferStuffing); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { @@ -814,6 +865,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) { EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::AppDeadlineMissed); } TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPresentsSurfaceFrame) { @@ -858,6 +913,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_displayFramePredictionExpiredPres EXPECT_EQ(surfaceFrame1->getActuals().presentTime, 90); EXPECT_EQ(surfaceFrame1->getJankType(), JankType::Unknown | JankType::AppDeadlineMissed); EXPECT_EQ(surfaceFrame1->getJankSeverityType(), JankSeverityType::Full); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::Unknown | JankType::AppDeadlineMissed); } /* @@ -1789,6 +1848,10 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::OnTimeFinish); EXPECT_EQ(displayFrame->getJankType(), JankType::None); EXPECT_EQ(displayFrame->getJankSeverityType(), JankSeverityType::None); + + auto jankData = getLayerOneJankData(); + EXPECT_EQ(jankData.size(), 1u); + EXPECT_EQ(jankData[0].jankType, JankType::None); } TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresent) { diff --git a/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp b/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp new file mode 100644 index 0000000000..2941a14ef9 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/JankTrackerTest.cpp @@ -0,0 +1,216 @@ +/* + * Copyright 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. + */ + +#include +#include +#include "BackgroundExecutor.h" +#include "Jank/JankTracker.h" + +#include +#include + +namespace android { + +namespace { + +using namespace testing; + +class MockJankListener : public gui::BnJankListener { +public: + MockJankListener() = default; + ~MockJankListener() override = default; + + MOCK_METHOD(binder::Status, onJankData, (const std::vector& jankData), + (override)); +}; + +} // anonymous namespace + +class JankTrackerTest : public Test { +public: + JankTrackerTest() {} + + void SetUp() override { mListener = sp>::make(); } + + void addJankListener(int32_t layerId) { + JankTracker::addJankListener(layerId, IInterface::asBinder(mListener)); + } + + void removeJankListener(int32_t layerId, int64_t after) { + JankTracker::removeJankListener(layerId, IInterface::asBinder(mListener), after); + } + + void addJankData(int32_t layerId, int jankType) { + gui::JankData data; + data.frameVsyncId = mVsyncId++; + data.jankType = jankType; + data.frameIntervalNs = 8333333; + JankTracker::onJankData(layerId, data); + } + + void flushBackgroundThread() { BackgroundExecutor::getLowPriorityInstance().flushQueue(); } + + size_t listenerCount() { return JankTracker::sListenerCount; } + + std::vector getCollectedJankData(int32_t layerId) { + return JankTracker::getCollectedJankDataForTesting(layerId); + } + + sp> mListener = nullptr; + int64_t mVsyncId = 1000; +}; + +TEST_F(JankTrackerTest, jankDataIsTrackedAndPropagated) { + ASSERT_EQ(listenerCount(), 0u); + + EXPECT_CALL(*mListener.get(), onJankData(SizeIs(3))) + .WillOnce([](const std::vector& jankData) { + EXPECT_EQ(jankData[0].frameVsyncId, 1000); + EXPECT_EQ(jankData[0].jankType, 1); + EXPECT_EQ(jankData[0].frameIntervalNs, 8333333); + + EXPECT_EQ(jankData[1].frameVsyncId, 1001); + EXPECT_EQ(jankData[1].jankType, 2); + EXPECT_EQ(jankData[1].frameIntervalNs, 8333333); + + EXPECT_EQ(jankData[2].frameVsyncId, 1002); + EXPECT_EQ(jankData[2].jankType, 3); + EXPECT_EQ(jankData[2].frameIntervalNs, 8333333); + return binder::Status::ok(); + }); + EXPECT_CALL(*mListener.get(), onJankData(SizeIs(2))) + .WillOnce([](const std::vector& jankData) { + EXPECT_EQ(jankData[0].frameVsyncId, 1003); + EXPECT_EQ(jankData[0].jankType, 4); + EXPECT_EQ(jankData[0].frameIntervalNs, 8333333); + + EXPECT_EQ(jankData[1].frameVsyncId, 1004); + EXPECT_EQ(jankData[1].jankType, 5); + EXPECT_EQ(jankData[1].frameIntervalNs, 8333333); + + return binder::Status::ok(); + }); + + addJankListener(123); + addJankData(123, 1); + addJankData(123, 2); + addJankData(123, 3); + JankTracker::flushJankData(123); + addJankData(123, 4); + removeJankListener(123, mVsyncId); + addJankData(123, 5); + JankTracker::flushJankData(123); + addJankData(123, 6); + JankTracker::flushJankData(123); + removeJankListener(123, 0); + + flushBackgroundThread(); +} + +TEST_F(JankTrackerTest, jankDataIsAutomaticallyFlushedInBatches) { + ASSERT_EQ(listenerCount(), 0u); + + // needs to be larger than kJankDataBatchSize in JankTracker.cpp. + constexpr size_t kNumberOfJankDataToSend = 234; + + size_t jankDataReceived = 0; + size_t numBatchesReceived = 0; + + EXPECT_CALL(*mListener.get(), onJankData(_)) + .WillRepeatedly([&](const std::vector& jankData) { + jankDataReceived += jankData.size(); + numBatchesReceived++; + return binder::Status::ok(); + }); + + addJankListener(123); + for (size_t i = 0; i < kNumberOfJankDataToSend; i++) { + addJankData(123, 0); + } + + flushBackgroundThread(); + // Check that we got some data, without explicitly flushing. + EXPECT_GT(jankDataReceived, 0u); + EXPECT_GT(numBatchesReceived, 0u); + EXPECT_LT(numBatchesReceived, jankDataReceived); // batches should be > size 1. + + removeJankListener(123, 0); + JankTracker::flushJankData(123); + flushBackgroundThread(); + EXPECT_EQ(jankDataReceived, kNumberOfJankDataToSend); +} + +TEST_F(JankTrackerTest, jankListenerIsRemovedWhenReturningNullError) { + ASSERT_EQ(listenerCount(), 0u); + + EXPECT_CALL(*mListener.get(), onJankData(SizeIs(3))) + .WillOnce(Return(binder::Status::fromExceptionCode(binder::Status::EX_NULL_POINTER))); + + addJankListener(123); + addJankData(123, 1); + addJankData(123, 2); + addJankData(123, 3); + JankTracker::flushJankData(123); + addJankData(123, 4); + addJankData(123, 5); + JankTracker::flushJankData(123); + flushBackgroundThread(); + + EXPECT_EQ(listenerCount(), 0u); +} + +TEST_F(JankTrackerTest, jankDataIsDroppedIfNobodyIsListening) { + ASSERT_EQ(listenerCount(), 0u); + + addJankData(123, 1); + addJankData(123, 2); + addJankData(123, 3); + flushBackgroundThread(); + + EXPECT_EQ(getCollectedJankData(123).size(), 0u); +} + +TEST_F(JankTrackerTest, listenerCountTracksRegistrations) { + ASSERT_EQ(listenerCount(), 0u); + + addJankListener(123); + addJankListener(456); + flushBackgroundThread(); + EXPECT_EQ(listenerCount(), 2u); + + removeJankListener(123, 0); + JankTracker::flushJankData(123); + removeJankListener(456, 0); + JankTracker::flushJankData(456); + flushBackgroundThread(); + EXPECT_EQ(listenerCount(), 0u); +} + +TEST_F(JankTrackerTest, listenerCountIsAccurateOnDuplicateRegistration) { + ASSERT_EQ(listenerCount(), 0u); + + addJankListener(123); + addJankListener(123); + flushBackgroundThread(); + EXPECT_EQ(listenerCount(), 1u); + + removeJankListener(123, 0); + JankTracker::flushJankData(123); + flushBackgroundThread(); + EXPECT_EQ(listenerCount(), 0u); +} + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 46733b9a83..0745f870e4 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -302,58 +302,6 @@ public: EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState()); } - void PendingSurfaceFramesRemovedAfterClassification() { - sp layer = createLayer(); - - sp fence1(sp::make()); - auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - BufferData bufferData; - bufferData.acquireFence = fence1; - bufferData.frameNumber = 1; - bufferData.flags |= BufferData::BufferDataChange::fenceChanged; - bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - std::shared_ptr externalTexture1 = std::make_shared< - renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, - 1ULL /* bufferId */, - HAL_PIXEL_FORMAT_RGBA_8888, - 0ULL /*usage*/); - FrameTimelineInfo ftInfo; - ftInfo.vsyncId = 1; - ftInfo.inputEventId = 0; - layer->setBuffer(externalTexture1, bufferData, 10, 20, false, ftInfo); - ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); - const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; - - sp fence2(sp::make()); - auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - bufferData.acquireFence = fence2; - bufferData.frameNumber = 1; - bufferData.flags |= BufferData::BufferDataChange::fenceChanged; - bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - std::shared_ptr externalTexture2 = std::make_shared< - renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, - 1ULL /* bufferId */, - HAL_PIXEL_FORMAT_RGBA_8888, - 0ULL /*usage*/); - layer->setBuffer(externalTexture2, bufferData, 10, 20, false, ftInfo); - acquireFence2->signalForTest(12); - - ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); - auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; - - commitTransaction(layer.get()); - layer->updateTexImage(15); - - // Both the droppedSurfaceFrame and presentedSurfaceFrame should be in - // pendingJankClassifications. - EXPECT_EQ(2u, layer->mPendingJankClassifications.size()); - presentedSurfaceFrame->onPresent(20, JankType::None, 90_Hz, 90_Hz, - /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); - layer->releasePendingBuffer(25); - - EXPECT_EQ(0u, layer->mPendingJankClassifications.size()); - } - void BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer() { sp layer = createLayer(); @@ -445,8 +393,7 @@ public: void MultipleCommitsBeforeLatch() { sp layer = createLayer(); - uint32_t surfaceFramesPendingClassification = 0; - std::vector> bufferlessSurfaceFrames; + std::vector> surfaceFrames; for (int i = 0; i < 10; i += 2) { sp fence(sp::make()); BufferData bufferData; @@ -469,51 +416,43 @@ public: layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo2, 10); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); - auto& bufferlessSurfaceFrame = - layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*vsyncId*/ 2); - bufferlessSurfaceFrames.push_back(bufferlessSurfaceFrame); + + surfaceFrames.push_back(layer->mDrawingState.bufferSurfaceFrameTX); + surfaceFrames.push_back( + layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*vsyncId*/ 2)); commitTransaction(layer.get()); - surfaceFramesPendingClassification += 2; - EXPECT_EQ(surfaceFramesPendingClassification, - layer->mPendingJankClassifications.size()); } auto presentedBufferSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; layer->updateTexImage(15); // BufferlessSurfaceFrames are immediately set to presented and added to the DisplayFrame. // Since we don't have access to DisplayFrame here, trigger an onPresent directly. - for (auto& surfaceFrame : bufferlessSurfaceFrames) { - surfaceFrame->onPresent(20, JankType::None, 90_Hz, 90_Hz, - /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); + // The odd indices are the bufferless frames. + for (uint32_t i = 1; i < 10; i += 2) { + surfaceFrames[i]->onPresent(20, JankType::None, 90_Hz, 90_Hz, + /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); } presentedBufferSurfaceFrame->onPresent(20, JankType::None, 90_Hz, 90_Hz, /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0); - // There should be 10 bufferlessSurfaceFrames and 1 bufferSurfaceFrame - ASSERT_EQ(10u, surfaceFramesPendingClassification); - ASSERT_EQ(surfaceFramesPendingClassification, layer->mPendingJankClassifications.size()); - // For the frames upto 8, the bufferSurfaceFrame should have been dropped while the // bufferlessSurfaceFrame presented for (uint32_t i = 0; i < 8; i += 2) { - auto& bufferSurfaceFrame = layer->mPendingJankClassifications[i]; - auto& bufferlessSurfaceFrame = layer->mPendingJankClassifications[i + 1]; + auto bufferSurfaceFrame = surfaceFrames[i]; + auto bufferlessSurfaceFrame = surfaceFrames[i + 1]; EXPECT_EQ(bufferSurfaceFrame->getPresentState(), PresentState::Dropped); EXPECT_EQ(bufferlessSurfaceFrame->getPresentState(), PresentState::Presented); } { - auto& bufferSurfaceFrame = layer->mPendingJankClassifications[8u]; - auto& bufferlessSurfaceFrame = layer->mPendingJankClassifications[9u]; + auto bufferSurfaceFrame = surfaceFrames[8]; + auto bufferlessSurfaceFrame = surfaceFrames[9]; EXPECT_EQ(bufferSurfaceFrame->getPresentState(), PresentState::Presented); EXPECT_EQ(bufferlessSurfaceFrame->getPresentState(), PresentState::Presented); } layer->releasePendingBuffer(25); - - // There shouldn't be any pending classifications. Everything should have been cleared. - EXPECT_EQ(0u, layer->mPendingJankClassifications.size()); } }; @@ -541,10 +480,6 @@ TEST_F(TransactionSurfaceFrameTest, MultipleSurfaceFramesPresentedTogether) { MultipleSurfaceFramesPresentedTogether(); } -TEST_F(TransactionSurfaceFrameTest, PendingSurfaceFramesRemovedAfterClassification) { - PendingSurfaceFramesRemovedAfterClassification(); -} - TEST_F(TransactionSurfaceFrameTest, BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer) { BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer(); -- GitLab From 67e1ae63301dc02f4d940b5f480b1f495b3b977e Mon Sep 17 00:00:00 2001 From: Harry Cutts Date: Wed, 26 Jun 2024 10:45:56 +0000 Subject: [PATCH 061/530] InputDevice: return std::optional from getAbsoluteAxisInfo This also allows us to remove the valid field from RawAbsoluteAxisInfo, since we can represent "invalid" axes (which usually just meant absent ones) using std::nullopt. Test: atest inputflinger_tests Test: m checkinput Test: Check "Raw Touch Axes" section of touch input mapper info in dumpsys input Bug: 245989146 Flag: EXEMPT refactor Change-Id: I045a2e0b61a84657f2f8171c1fee3cc3e331ac86 --- services/inputflinger/reader/EventHub.cpp | 9 +- .../inputflinger/reader/include/EventHub.h | 6 +- .../inputflinger/reader/include/InputDevice.h | 16 +-- .../mapper/CapturedTouchpadEventConverter.cpp | 61 +++++---- .../mapper/ExternalStylusInputMapper.cpp | 10 +- .../reader/mapper/ExternalStylusInputMapper.h | 4 +- .../reader/mapper/InputMapper.cpp | 8 +- .../inputflinger/reader/mapper/InputMapper.h | 7 +- .../reader/mapper/JoystickInputMapper.cpp | 7 +- .../reader/mapper/MultiTouchInputMapper.cpp | 34 ++--- .../reader/mapper/SensorInputMapper.cpp | 7 +- .../reader/mapper/SingleTouchInputMapper.cpp | 18 +-- .../reader/mapper/TouchInputMapper.cpp | 120 +++++++++--------- .../reader/mapper/TouchInputMapper.h | 22 ++-- .../reader/mapper/TouchpadInputMapper.cpp | 11 +- .../mapper/gestures/GestureConverter.cpp | 9 +- .../mapper/gestures/HardwareProperties.cpp | 36 ++++-- services/inputflinger/tests/FakeEventHub.cpp | 1 - .../tests/HardwareProperties_test.cpp | 1 - .../inputflinger/tests/InputMapperTest.cpp | 1 - .../tests/fuzzers/MapperHelpers.h | 1 - .../tests/fuzzers/TouchpadInputFuzzer.cpp | 1 - 22 files changed, 194 insertions(+), 196 deletions(-) diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 65583e95bf..7095928d5b 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -513,10 +513,10 @@ ftl::Flags getAbsAxisUsage(int32_t axis, // --- RawAbsoluteAxisInfo --- -std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info) { - if (info.valid) { - out << "min=" << info.minValue << ", max=" << info.maxValue << ", flat=" << info.flat - << ", fuzz=" << info.fuzz << ", resolution=" << info.resolution; +std::ostream& operator<<(std::ostream& out, const std::optional& info) { + if (info) { + out << "min=" << info->minValue << ", max=" << info->maxValue << ", flat=" << info->flat + << ", fuzz=" << info->fuzz << ", resolution=" << info->resolution; } else { out << "unknown range"; } @@ -645,7 +645,6 @@ void EventHub::Device::populateAbsoluteAxisStates() { continue; } auto& [axisInfo, value] = absState[axis]; - axisInfo.valid = true; axisInfo.minValue = info.minimum; axisInfo.maxValue = info.maximum; axisInfo.flat = info.flat; diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 2a4346694a..c647558c9f 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -71,18 +71,14 @@ struct RawEvent { /* Describes an absolute axis. */ struct RawAbsoluteAxisInfo { - bool valid{false}; // true if the information is valid, false otherwise - int32_t minValue{}; // minimum value int32_t maxValue{}; // maximum value int32_t flat{}; // center flat position, eg. flat == 8 means center is between -8 and 8 int32_t fuzz{}; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise int32_t resolution{}; // resolution in units per mm or radians per mm - - inline void clear() { *this = RawAbsoluteAxisInfo(); } }; -std::ostream& operator<<(std::ostream& out, const RawAbsoluteAxisInfo& info); +std::ostream& operator<<(std::ostream& out, const std::optional& info); /* * Input device classes. diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 086c26f5e2..f2fdc37047 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -305,22 +305,17 @@ public: inline int32_t getDeviceControllerNumber() const { return mEventHub->getDeviceControllerNumber(mId); } - inline status_t getAbsoluteAxisInfo(int32_t code, RawAbsoluteAxisInfo* axisInfo) const { + inline std::optional getAbsoluteAxisInfo(int32_t code) const { std::optional info = mEventHub->getAbsoluteAxisInfo(mId, code); - if (!info.has_value()) { - axisInfo->clear(); - return NAME_NOT_FOUND; - } - *axisInfo = *info; // Validate axis info for InputDevice. - if (axisInfo->valid && axisInfo->minValue == axisInfo->maxValue) { + if (info && info->minValue == info->maxValue) { // Historically, we deem axes with the same min and max values as invalid to avoid // dividing by zero when scaling by max - min. // TODO(b/291772515): Perform axis info validation on a per-axis basis when it is used. - axisInfo->valid = false; + return std::nullopt; } - return OK; + return info; } inline bool hasRelativeAxis(int32_t code) const { return mEventHub->hasRelativeAxis(mId, code); @@ -435,8 +430,7 @@ public: } inline bool hasAbsoluteAxis(int32_t code) const { - std::optional info = mEventHub->getAbsoluteAxisInfo(mId, code); - return info.has_value() && info->valid; + return mEventHub->getAbsoluteAxisInfo(mId, code).has_value(); } inline bool isKeyPressed(int32_t scanCode) const { return mEventHub->getScanCodeState(mId, scanCode) == AKEY_STATE_DOWN; diff --git a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp index 90685dec2b..c8e7790c86 100644 --- a/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp +++ b/services/inputflinger/reader/mapper/CapturedTouchpadEventConverter.cpp @@ -16,6 +16,7 @@ #include "CapturedTouchpadEventConverter.h" +#include #include #include @@ -53,32 +54,33 @@ CapturedTouchpadEventConverter::CapturedTouchpadEventConverter( mMotionAccumulator(motionAccumulator), mHasTouchMinor(deviceContext.hasAbsoluteAxis(ABS_MT_TOUCH_MINOR)), mHasToolMinor(deviceContext.hasAbsoluteAxis(ABS_MT_WIDTH_MINOR)) { - RawAbsoluteAxisInfo orientationInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &orientationInfo); - if (orientationInfo.valid) { - if (orientationInfo.maxValue > 0) { - mOrientationScale = M_PI_2 / orientationInfo.maxValue; - } else if (orientationInfo.minValue < 0) { - mOrientationScale = -M_PI_2 / orientationInfo.minValue; + if (std::optional orientation = + deviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + orientation) { + if (orientation->maxValue > 0) { + mOrientationScale = M_PI_2 / orientation->maxValue; + } else if (orientation->minValue < 0) { + mOrientationScale = -M_PI_2 / orientation->minValue; } } // TODO(b/275369880): support touch.pressure.calibration and .scale properties when captured. - RawAbsoluteAxisInfo pressureInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &pressureInfo); - if (pressureInfo.valid && pressureInfo.maxValue > 0) { - mPressureScale = 1.0 / pressureInfo.maxValue; + if (std::optional pressure = + deviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE); + pressure && pressure->maxValue > 0) { + mPressureScale = 1.0 / pressure->maxValue; } - RawAbsoluteAxisInfo touchMajorInfo, toolMajorInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &touchMajorInfo); - deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &toolMajorInfo); - mHasTouchMajor = touchMajorInfo.valid; - mHasToolMajor = toolMajorInfo.valid; - if (mHasTouchMajor && touchMajorInfo.maxValue != 0) { - mSizeScale = 1.0f / touchMajorInfo.maxValue; - } else if (mHasToolMajor && toolMajorInfo.maxValue != 0) { - mSizeScale = 1.0f / toolMajorInfo.maxValue; + std::optional touchMajor = + deviceContext.getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR); + std::optional toolMajor = + deviceContext.getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR); + mHasTouchMajor = touchMajor.has_value(); + mHasToolMajor = toolMajor.has_value(); + if (mHasTouchMajor && touchMajor->maxValue != 0) { + mSizeScale = 1.0f / touchMajor->maxValue; + } else if (mHasToolMajor && toolMajor->maxValue != 0) { + mSizeScale = 1.0f / toolMajor->maxValue; } } @@ -113,15 +115,13 @@ void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MAJOR, ABS_MT_WIDTH_MAJOR); tryAddRawMotionRange(/*byref*/ info, AMOTION_EVENT_AXIS_TOOL_MINOR, ABS_MT_WIDTH_MINOR); - RawAbsoluteAxisInfo pressureInfo; - mDeviceContext.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &pressureInfo); - if (pressureInfo.valid) { + if (mDeviceContext.hasAbsoluteAxis(ABS_MT_PRESSURE)) { info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, SOURCE, 0, 1, 0, 0, 0); } - RawAbsoluteAxisInfo orientationInfo; - mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &orientationInfo); - if (orientationInfo.valid && (orientationInfo.maxValue > 0 || orientationInfo.minValue < 0)) { + if (std::optional orientation = + mDeviceContext.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + orientation && (orientation->maxValue > 0 || orientation->minValue < 0)) { info.addMotionRange(AMOTION_EVENT_AXIS_ORIENTATION, SOURCE, -M_PI_2, M_PI_2, 0, 0, 0); } @@ -133,11 +133,10 @@ void CapturedTouchpadEventConverter::populateMotionRanges(InputDeviceInfo& info) void CapturedTouchpadEventConverter::tryAddRawMotionRange(InputDeviceInfo& deviceInfo, int32_t androidAxis, int32_t evdevAxis) const { - RawAbsoluteAxisInfo info; - mDeviceContext.getAbsoluteAxisInfo(evdevAxis, &info); - if (info.valid) { - deviceInfo.addMotionRange(androidAxis, SOURCE, info.minValue, info.maxValue, info.flat, - info.fuzz, info.resolution); + std::optional info = mDeviceContext.getAbsoluteAxisInfo(evdevAxis); + if (info) { + deviceInfo.addMotionRange(androidAxis, SOURCE, info->minValue, info->maxValue, info->flat, + info->fuzz, info->resolution); } } diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp index 3af1d04073..7cc8940379 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp @@ -33,7 +33,7 @@ uint32_t ExternalStylusInputMapper::getSources() const { void ExternalStylusInputMapper::populateDeviceInfo(InputDeviceInfo& info) { InputMapper::populateDeviceInfo(info); - if (mRawPressureAxis.valid) { + if (mRawPressureAxis) { info.addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, AINPUT_SOURCE_STYLUS, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); } @@ -50,7 +50,7 @@ void ExternalStylusInputMapper::dump(std::string& dump) { std::list ExternalStylusInputMapper::reconfigure(nsecs_t when, const InputReaderConfiguration& config, ConfigurationChanges changes) { - getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPressureAxis); + mRawPressureAxis = getAbsoluteAxisInfo(ABS_PRESSURE); mTouchButtonAccumulator.configure(); return {}; } @@ -82,10 +82,10 @@ std::list ExternalStylusInputMapper::sync(nsecs_t when) { mStylusState.toolType = ToolType::STYLUS; } - if (mRawPressureAxis.valid) { + if (mRawPressureAxis) { auto rawPressure = static_cast(mSingleTouchMotionAccumulator.getAbsolutePressure()); - mStylusState.pressure = (rawPressure - mRawPressureAxis.minValue) / - static_cast(mRawPressureAxis.maxValue - mRawPressureAxis.minValue); + mStylusState.pressure = (rawPressure - mRawPressureAxis->minValue) / + static_cast(mRawPressureAxis->maxValue - mRawPressureAxis->minValue); } else if (mTouchButtonAccumulator.hasButtonTouch()) { mStylusState.pressure = mTouchButtonAccumulator.isHovering() ? 0.0f : 1.0f; } diff --git a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h index c040a7b996..d48fd9b469 100644 --- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h +++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.h @@ -16,6 +16,8 @@ #pragma once +#include + #include "InputMapper.h" #include "SingleTouchMotionAccumulator.h" @@ -43,7 +45,7 @@ public: private: SingleTouchMotionAccumulator mSingleTouchMotionAccumulator; - RawAbsoluteAxisInfo mRawPressureAxis; + std::optional mRawPressureAxis; TouchButtonAccumulator mTouchButtonAccumulator; StylusState mStylusState; diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp index b6c5c9806c..c44c48c0bf 100644 --- a/services/inputflinger/reader/mapper/InputMapper.cpp +++ b/services/inputflinger/reader/mapper/InputMapper.cpp @@ -18,6 +18,7 @@ #include "InputMapper.h" +#include #include #include @@ -116,15 +117,16 @@ std::list InputMapper::updateExternalStylusState(const StylusState& return {}; } -status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) { - return getDeviceContext().getAbsoluteAxisInfo(axis, axisInfo); +std::optional InputMapper::getAbsoluteAxisInfo(int32_t axis) { + return getDeviceContext().getAbsoluteAxisInfo(axis); } void InputMapper::bumpGeneration() { getDeviceContext().bumpGeneration(); } -void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis, +void InputMapper::dumpRawAbsoluteAxisInfo(std::string& dump, + const std::optional& axis, const char* name) { std::stringstream out; out << INDENT4 << name << ": " << axis << "\n"; diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h index 2c51448b4e..e5afcc798e 100644 --- a/services/inputflinger/reader/mapper/InputMapper.h +++ b/services/inputflinger/reader/mapper/InputMapper.h @@ -16,6 +16,8 @@ #pragma once +#include + #include "EventHub.h" #include "InputDevice.h" #include "InputListener.h" @@ -126,10 +128,11 @@ protected: explicit InputMapper(InputDeviceContext& deviceContext, const InputReaderConfiguration& readerConfig); - status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo); + std::optional getAbsoluteAxisInfo(int32_t axis); void bumpGeneration(); - static void dumpRawAbsoluteAxisInfo(std::string& dump, const RawAbsoluteAxisInfo& axis, + static void dumpRawAbsoluteAxisInfo(std::string& dump, + const std::optional& axis, const char* name); static void dumpStylusState(std::string& dump, const StylusState& state); }; diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp index 41e018d392..3091714e00 100644 --- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp +++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp @@ -117,9 +117,8 @@ std::list JoystickInputMapper::reconfigure(nsecs_t when, continue; // axis must be claimed by a different device } - RawAbsoluteAxisInfo rawAxisInfo; - getAbsoluteAxisInfo(abs, &rawAxisInfo); - if (rawAxisInfo.valid) { + if (std::optional rawAxisInfo = getAbsoluteAxisInfo(abs); + rawAxisInfo) { // Map axis. AxisInfo axisInfo; const bool explicitlyMapped = !getDeviceContext().mapAxis(abs, &axisInfo); @@ -129,7 +128,7 @@ std::list JoystickInputMapper::reconfigure(nsecs_t when, axisInfo.mode = AxisInfo::MODE_NORMAL; axisInfo.axis = -1; } - mAxes.insert({abs, createAxis(axisInfo, rawAxisInfo, explicitlyMapped)}); + mAxes.insert({abs, createAxis(axisInfo, rawAxisInfo.value(), explicitlyMapped)}); } } diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index 1986fe286a..3ea3c20385 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -133,7 +133,7 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { bool isHovering = mTouchButtonAccumulator.getToolType() != ToolType::MOUSE && (mTouchButtonAccumulator.isHovering() || - (mRawPointerAxes.pressure.valid && inSlot.getPressure() <= 0)); + (mRawPointerAxes.pressure && inSlot.getPressure() <= 0)); outPointer.isHovering = isHovering; // Assign pointer id using tracking id if available. @@ -189,21 +189,23 @@ std::list MultiTouchInputMapper::reconfigure(nsecs_t when, void MultiTouchInputMapper::configureRawPointerAxes() { TouchInputMapper::configureRawPointerAxes(); - getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x); - getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y); - getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor); - getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor); - getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor); - getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor); - getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation); - getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure); - getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance); - getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId); - getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot); - - if (mRawPointerAxes.trackingId.valid && mRawPointerAxes.slot.valid && - mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) { - size_t slotCount = mRawPointerAxes.slot.maxValue + 1; + // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub won't + // classify a device as multitouch if they're not present. + mRawPointerAxes.x = getAbsoluteAxisInfo(ABS_MT_POSITION_X).value(); + mRawPointerAxes.y = getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value(); + mRawPointerAxes.touchMajor = getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR); + mRawPointerAxes.touchMinor = getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR); + mRawPointerAxes.toolMajor = getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR); + mRawPointerAxes.toolMinor = getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR); + mRawPointerAxes.orientation = getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + mRawPointerAxes.pressure = getAbsoluteAxisInfo(ABS_MT_PRESSURE); + mRawPointerAxes.distance = getAbsoluteAxisInfo(ABS_MT_DISTANCE); + mRawPointerAxes.trackingId = getAbsoluteAxisInfo(ABS_MT_TRACKING_ID); + mRawPointerAxes.slot = getAbsoluteAxisInfo(ABS_MT_SLOT); + + if (mRawPointerAxes.trackingId && mRawPointerAxes.slot && mRawPointerAxes.slot->minValue == 0 && + mRawPointerAxes.slot->maxValue > 0) { + size_t slotCount = mRawPointerAxes.slot->maxValue + 1; if (slotCount > MAX_SLOTS) { ALOGW("MultiTouch Device %s reported %zu slots but the framework " "only supports a maximum of %zu slots at this time.", diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp index d7f2993daa..4233f789d6 100644 --- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp @@ -133,9 +133,8 @@ std::list SensorInputMapper::reconfigure(nsecs_t when, .test(InputDeviceClass::SENSOR))) { continue; } - RawAbsoluteAxisInfo rawAxisInfo; - getAbsoluteAxisInfo(abs, &rawAxisInfo); - if (rawAxisInfo.valid) { + if (std::optional rawAxisInfo = getAbsoluteAxisInfo(abs); + rawAxisInfo) { AxisInfo axisInfo; // Axis doesn't need to be mapped, as sensor mapper doesn't generate any motion // input events @@ -146,7 +145,7 @@ std::list SensorInputMapper::reconfigure(nsecs_t when, if (ret.ok()) { InputDeviceSensorType sensorType = (*ret).first; int32_t sensorDataIndex = (*ret).second; - const Axis& axis = createAxis(axisInfo, rawAxisInfo); + const Axis& axis = createAxis(axisInfo, rawAxisInfo.value()); parseSensorConfiguration(sensorType, abs, sensorDataIndex, axis); mAxes.insert({abs, axis}); diff --git a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp index 140bb0c4ed..869feb4359 100644 --- a/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/SingleTouchInputMapper.cpp @@ -44,7 +44,7 @@ void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { bool isHovering = mTouchButtonAccumulator.getToolType() != ToolType::MOUSE && (mTouchButtonAccumulator.isHovering() || - (mRawPointerAxes.pressure.valid && + (mRawPointerAxes.pressure && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0)); outState->rawPointerData.markIdBit(0, isHovering); @@ -72,13 +72,15 @@ void SingleTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { void SingleTouchInputMapper::configureRawPointerAxes() { TouchInputMapper::configureRawPointerAxes(); - getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x); - getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y); - getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure); - getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor); - getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance); - getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX); - getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY); + // We can safely assume that ABS_X and _Y axes will be available, as EventHub won't classify a + // device as a touch device if they're not present. + mRawPointerAxes.x = getAbsoluteAxisInfo(ABS_X).value(); + mRawPointerAxes.y = getAbsoluteAxisInfo(ABS_Y).value(); + mRawPointerAxes.pressure = getAbsoluteAxisInfo(ABS_PRESSURE); + mRawPointerAxes.toolMajor = getAbsoluteAxisInfo(ABS_TOOL_WIDTH); + mRawPointerAxes.distance = getAbsoluteAxisInfo(ABS_DISTANCE); + mRawPointerAxes.tiltX = getAbsoluteAxisInfo(ABS_TILT_X); + mRawPointerAxes.tiltY = getAbsoluteAxisInfo(ABS_TILT_Y); } bool SingleTouchInputMapper::hasStylus() const { diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp index 81ec24e094..beba3b896f 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp @@ -600,10 +600,10 @@ void TouchInputMapper::initializeSizeRanges() { const float diagonalSize = hypotf(mDisplayBounds.width, mDisplayBounds.height); // Size factors. - if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.touchMajor.maxValue != 0) { - mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue; - } else if (mRawPointerAxes.toolMajor.valid && mRawPointerAxes.toolMajor.maxValue != 0) { - mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue; + if (mRawPointerAxes.touchMajor && mRawPointerAxes.touchMajor->maxValue != 0) { + mSizeScale = 1.0f / mRawPointerAxes.touchMajor->maxValue; + } else if (mRawPointerAxes.toolMajor && mRawPointerAxes.toolMajor->maxValue != 0) { + mSizeScale = 1.0f / mRawPointerAxes.toolMajor->maxValue; } else { mSizeScale = 0.0f; } @@ -618,18 +618,18 @@ void TouchInputMapper::initializeSizeRanges() { .resolution = 0, }; - if (mRawPointerAxes.touchMajor.valid) { - mRawPointerAxes.touchMajor.resolution = - clampResolution("touchMajor", mRawPointerAxes.touchMajor.resolution); - mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor.resolution; + if (mRawPointerAxes.touchMajor) { + mRawPointerAxes.touchMajor->resolution = + clampResolution("touchMajor", mRawPointerAxes.touchMajor->resolution); + mOrientedRanges.touchMajor->resolution = mRawPointerAxes.touchMajor->resolution; } mOrientedRanges.touchMinor = mOrientedRanges.touchMajor; mOrientedRanges.touchMinor->axis = AMOTION_EVENT_AXIS_TOUCH_MINOR; - if (mRawPointerAxes.touchMinor.valid) { - mRawPointerAxes.touchMinor.resolution = - clampResolution("touchMinor", mRawPointerAxes.touchMinor.resolution); - mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor.resolution; + if (mRawPointerAxes.touchMinor) { + mRawPointerAxes.touchMinor->resolution = + clampResolution("touchMinor", mRawPointerAxes.touchMinor->resolution); + mOrientedRanges.touchMinor->resolution = mRawPointerAxes.touchMinor->resolution; } mOrientedRanges.toolMajor = InputDeviceInfo::MotionRange{ @@ -641,18 +641,18 @@ void TouchInputMapper::initializeSizeRanges() { .fuzz = 0, .resolution = 0, }; - if (mRawPointerAxes.toolMajor.valid) { - mRawPointerAxes.toolMajor.resolution = - clampResolution("toolMajor", mRawPointerAxes.toolMajor.resolution); - mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor.resolution; + if (mRawPointerAxes.toolMajor) { + mRawPointerAxes.toolMajor->resolution = + clampResolution("toolMajor", mRawPointerAxes.toolMajor->resolution); + mOrientedRanges.toolMajor->resolution = mRawPointerAxes.toolMajor->resolution; } mOrientedRanges.toolMinor = mOrientedRanges.toolMajor; mOrientedRanges.toolMinor->axis = AMOTION_EVENT_AXIS_TOOL_MINOR; - if (mRawPointerAxes.toolMinor.valid) { - mRawPointerAxes.toolMinor.resolution = - clampResolution("toolMinor", mRawPointerAxes.toolMinor.resolution); - mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor.resolution; + if (mRawPointerAxes.toolMinor) { + mRawPointerAxes.toolMinor->resolution = + clampResolution("toolMinor", mRawPointerAxes.toolMinor->resolution); + mOrientedRanges.toolMinor->resolution = mRawPointerAxes.toolMinor->resolution; } if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) { @@ -704,9 +704,10 @@ void TouchInputMapper::initializeOrientedRanges() { mCalibration.pressureCalibration == Calibration::PressureCalibration::AMPLITUDE) { if (mCalibration.pressureScale) { mPressureScale = *mCalibration.pressureScale; - pressureMax = mPressureScale * mRawPointerAxes.pressure.maxValue; - } else if (mRawPointerAxes.pressure.valid && mRawPointerAxes.pressure.maxValue != 0) { - mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue; + pressureMax = mPressureScale * + (mRawPointerAxes.pressure ? mRawPointerAxes.pressure->maxValue : 0); + } else if (mRawPointerAxes.pressure && mRawPointerAxes.pressure->maxValue != 0) { + mPressureScale = 1.0f / mRawPointerAxes.pressure->maxValue; } } @@ -725,18 +726,18 @@ void TouchInputMapper::initializeOrientedRanges() { mTiltXScale = 0; mTiltYCenter = 0; mTiltYScale = 0; - mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid; + mHaveTilt = mRawPointerAxes.tiltX && mRawPointerAxes.tiltY; if (mHaveTilt) { - mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue, mRawPointerAxes.tiltX.maxValue); - mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue, mRawPointerAxes.tiltY.maxValue); + mTiltXCenter = avg(mRawPointerAxes.tiltX->minValue, mRawPointerAxes.tiltX->maxValue); + mTiltYCenter = avg(mRawPointerAxes.tiltY->minValue, mRawPointerAxes.tiltY->maxValue); mTiltXScale = M_PI / 180; mTiltYScale = M_PI / 180; - if (mRawPointerAxes.tiltX.resolution) { - mTiltXScale = 1.0 / mRawPointerAxes.tiltX.resolution; + if (mRawPointerAxes.tiltX->resolution) { + mTiltXScale = 1.0 / mRawPointerAxes.tiltX->resolution; } - if (mRawPointerAxes.tiltY.resolution) { - mTiltYScale = 1.0 / mRawPointerAxes.tiltY.resolution; + if (mRawPointerAxes.tiltY->resolution) { + mTiltYScale = 1.0 / mRawPointerAxes.tiltY->resolution; } mOrientedRanges.tilt = InputDeviceInfo::MotionRange{ @@ -766,11 +767,11 @@ void TouchInputMapper::initializeOrientedRanges() { } else if (mCalibration.orientationCalibration != Calibration::OrientationCalibration::NONE) { if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::INTERPOLATED) { - if (mRawPointerAxes.orientation.valid) { - if (mRawPointerAxes.orientation.maxValue > 0) { - mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue; - } else if (mRawPointerAxes.orientation.minValue < 0) { - mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue; + if (mRawPointerAxes.orientation) { + if (mRawPointerAxes.orientation->maxValue > 0) { + mOrientationScale = M_PI_2 / mRawPointerAxes.orientation->maxValue; + } else if (mRawPointerAxes.orientation->minValue < 0) { + mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation->minValue; } else { mOrientationScale = 0; } @@ -795,14 +796,14 @@ void TouchInputMapper::initializeOrientedRanges() { mDistanceScale = mCalibration.distanceScale.value_or(1.0f); } + const bool hasDistance = mRawPointerAxes.distance.has_value(); mOrientedRanges.distance = InputDeviceInfo::MotionRange{ - .axis = AMOTION_EVENT_AXIS_DISTANCE, .source = mSource, - .min = mRawPointerAxes.distance.minValue * mDistanceScale, - .max = mRawPointerAxes.distance.maxValue * mDistanceScale, + .min = hasDistance ? mRawPointerAxes.distance->minValue * mDistanceScale : 0, + .max = hasDistance ? mRawPointerAxes.distance->maxValue * mDistanceScale : 0, .flat = 0, - .fuzz = mRawPointerAxes.distance.fuzz * mDistanceScale, + .fuzz = hasDistance ? mRawPointerAxes.distance->fuzz * mDistanceScale : 0, .resolution = 0, }; } @@ -943,12 +944,7 @@ void TouchInputMapper::configureInputDevice(nsecs_t when, bool* outResetNeeded) const std::optional newViewportOpt = findViewport(); // Ensure the device is valid and can be used. - if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) { - ALOGW("Touch device '%s' did not report support for X or Y axis! " - "The device will be inoperable.", - getDeviceName().c_str()); - mDeviceMode = DeviceMode::DISABLED; - } else if (!newViewportOpt) { + if (!newViewportOpt) { ALOGI("Touch device '%s' could not query the properties of its associated " "display. The device will be inoperable until the display size " "becomes available.", @@ -1237,7 +1233,7 @@ void TouchInputMapper::parseCalibration() { void TouchInputMapper::resolveCalibration() { // Size - if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) { + if (mRawPointerAxes.touchMajor || mRawPointerAxes.toolMajor) { if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DEFAULT) { mCalibration.sizeCalibration = Calibration::SizeCalibration::GEOMETRIC; } @@ -1246,7 +1242,7 @@ void TouchInputMapper::resolveCalibration() { } // Pressure - if (mRawPointerAxes.pressure.valid) { + if (mRawPointerAxes.pressure) { if (mCalibration.pressureCalibration == Calibration::PressureCalibration::DEFAULT) { mCalibration.pressureCalibration = Calibration::PressureCalibration::PHYSICAL; } @@ -1255,7 +1251,7 @@ void TouchInputMapper::resolveCalibration() { } // Orientation - if (mRawPointerAxes.orientation.valid) { + if (mRawPointerAxes.orientation) { if (mCalibration.orientationCalibration == Calibration::OrientationCalibration::DEFAULT) { mCalibration.orientationCalibration = Calibration::OrientationCalibration::INTERPOLATED; } @@ -1264,7 +1260,7 @@ void TouchInputMapper::resolveCalibration() { } // Distance - if (mRawPointerAxes.distance.valid) { + if (mRawPointerAxes.distance) { if (mCalibration.distanceCalibration == Calibration::DistanceCalibration::DEFAULT) { mCalibration.distanceCalibration = Calibration::DistanceCalibration::SCALED; } @@ -2251,25 +2247,25 @@ void TouchInputMapper::cookPointerData() { case Calibration::SizeCalibration::DIAMETER: case Calibration::SizeCalibration::BOX: case Calibration::SizeCalibration::AREA: - if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) { + if (mRawPointerAxes.touchMajor && mRawPointerAxes.toolMajor) { touchMajor = in.touchMajor; - touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor; + touchMinor = mRawPointerAxes.touchMinor ? in.touchMinor : in.touchMajor; toolMajor = in.toolMajor; - toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor; - size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor) - : in.touchMajor; - } else if (mRawPointerAxes.touchMajor.valid) { + toolMinor = mRawPointerAxes.toolMinor ? in.toolMinor : in.toolMajor; + size = mRawPointerAxes.touchMinor ? avg(in.touchMajor, in.touchMinor) + : in.touchMajor; + } else if (mRawPointerAxes.touchMajor) { toolMajor = touchMajor = in.touchMajor; toolMinor = touchMinor = - mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor; - size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor) - : in.touchMajor; - } else if (mRawPointerAxes.toolMajor.valid) { + mRawPointerAxes.touchMinor ? in.touchMinor : in.touchMajor; + size = mRawPointerAxes.touchMinor ? avg(in.touchMajor, in.touchMinor) + : in.touchMajor; + } else if (mRawPointerAxes.toolMajor) { touchMajor = toolMajor = in.toolMajor; touchMinor = toolMinor = - mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor; - size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor) - : in.toolMajor; + mRawPointerAxes.toolMinor ? in.toolMinor : in.toolMajor; + size = mRawPointerAxes.toolMinor ? avg(in.toolMajor, in.toolMinor) + : in.toolMajor; } else { ALOG_ASSERT(false, "No touch or tool axes. " diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h index 30c58a59c5..beab6e7179 100644 --- a/services/inputflinger/reader/mapper/TouchInputMapper.h +++ b/services/inputflinger/reader/mapper/TouchInputMapper.h @@ -61,17 +61,17 @@ static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); struct RawPointerAxes { RawAbsoluteAxisInfo x{}; RawAbsoluteAxisInfo y{}; - RawAbsoluteAxisInfo pressure{}; - RawAbsoluteAxisInfo touchMajor{}; - RawAbsoluteAxisInfo touchMinor{}; - RawAbsoluteAxisInfo toolMajor{}; - RawAbsoluteAxisInfo toolMinor{}; - RawAbsoluteAxisInfo orientation{}; - RawAbsoluteAxisInfo distance{}; - RawAbsoluteAxisInfo tiltX{}; - RawAbsoluteAxisInfo tiltY{}; - RawAbsoluteAxisInfo trackingId{}; - RawAbsoluteAxisInfo slot{}; + std::optional pressure{}; + std::optional touchMajor{}; + std::optional touchMinor{}; + std::optional toolMajor{}; + std::optional toolMinor{}; + std::optional orientation{}; + std::optional distance{}; + std::optional tiltX{}; + std::optional tiltY{}; + std::optional trackingId{}; + std::optional slot{}; inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; } inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; } diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp index 24efae893e..daab636c59 100644 --- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp @@ -240,14 +240,15 @@ TouchpadInputMapper::TouchpadInputMapper(InputDeviceContext& deviceContext, mGestureConverter(*getContext(), deviceContext, getDeviceId()), mCapturedEventConverter(*getContext(), deviceContext, mMotionAccumulator, getDeviceId()), mMetricsId(metricsIdFromInputDeviceIdentifier(deviceContext.getDeviceIdentifier())) { - RawAbsoluteAxisInfo slotAxisInfo; - deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT, &slotAxisInfo); - if (!slotAxisInfo.valid || slotAxisInfo.maxValue < 0) { + if (std::optional slotAxis = + deviceContext.getAbsoluteAxisInfo(ABS_MT_SLOT); + slotAxis && slotAxis->maxValue >= 0) { + mMotionAccumulator.configure(deviceContext, slotAxis->maxValue + 1, true); + } else { LOG(WARNING) << "Touchpad " << deviceContext.getName() << " doesn't have a valid ABS_MT_SLOT axis, and probably won't work properly."; - slotAxisInfo.maxValue = 0; + mMotionAccumulator.configure(deviceContext, 1, true); } - mMotionAccumulator.configure(deviceContext, slotAxisInfo.maxValue + 1, true); mGestureInterpreter->Initialize(GESTURES_DEVCLASS_TOUCHPAD); mGestureInterpreter->SetHardwareProperties(createHardwareProperties(deviceContext)); diff --git a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp index e8e7376e92..9924d0d491 100644 --- a/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp +++ b/services/inputflinger/reader/mapper/gestures/GestureConverter.cpp @@ -66,10 +66,11 @@ GestureConverter::GestureConverter(InputReaderContext& readerContext, const InputDeviceContext& deviceContext, int32_t deviceId) : mDeviceId(deviceId), mReaderContext(readerContext), - mEnableFlingStop(input_flags::enable_touchpad_fling_stop()) { - deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mXAxisInfo); - deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mYAxisInfo); -} + mEnableFlingStop(input_flags::enable_touchpad_fling_stop()), + // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub + // won't classify a device as a touchpad if they're not present. + mXAxisInfo(deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_X).value()), + mYAxisInfo(deviceContext.getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value()) {} std::string GestureConverter::dump() const { std::stringstream out; diff --git a/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp b/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp index 04655dc439..d8a1f501d1 100644 --- a/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp +++ b/services/inputflinger/reader/mapper/gestures/HardwareProperties.cpp @@ -16,6 +16,8 @@ #include "HardwareProperties.h" +#include + namespace android { namespace { @@ -33,26 +35,34 @@ unsigned short getMaxTouchCount(const InputDeviceContext& context) { HardwareProperties createHardwareProperties(const InputDeviceContext& context) { HardwareProperties props; - RawAbsoluteAxisInfo absMtPositionX; - context.getAbsoluteAxisInfo(ABS_MT_POSITION_X, &absMtPositionX); + // We can safely assume that ABS_MT_POSITION_X and _Y axes will be available, as EventHub won't + // classify a device as a touchpad if they're not present. + RawAbsoluteAxisInfo absMtPositionX = context.getAbsoluteAxisInfo(ABS_MT_POSITION_X).value(); props.left = absMtPositionX.minValue; props.right = absMtPositionX.maxValue; props.res_x = absMtPositionX.resolution; - RawAbsoluteAxisInfo absMtPositionY; - context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &absMtPositionY); + RawAbsoluteAxisInfo absMtPositionY = context.getAbsoluteAxisInfo(ABS_MT_POSITION_Y).value(); props.top = absMtPositionY.minValue; props.bottom = absMtPositionY.maxValue; props.res_y = absMtPositionY.resolution; - RawAbsoluteAxisInfo absMtOrientation; - context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &absMtOrientation); - props.orientation_minimum = absMtOrientation.minValue; - props.orientation_maximum = absMtOrientation.maxValue; + if (std::optional absMtOrientation = + context.getAbsoluteAxisInfo(ABS_MT_ORIENTATION); + absMtOrientation) { + props.orientation_minimum = absMtOrientation->minValue; + props.orientation_maximum = absMtOrientation->maxValue; + } else { + props.orientation_minimum = 0; + props.orientation_maximum = 0; + } - RawAbsoluteAxisInfo absMtSlot; - context.getAbsoluteAxisInfo(ABS_MT_SLOT, &absMtSlot); - props.max_finger_cnt = absMtSlot.maxValue - absMtSlot.minValue + 1; + if (std::optional absMtSlot = context.getAbsoluteAxisInfo(ABS_MT_SLOT); + absMtSlot) { + props.max_finger_cnt = absMtSlot->maxValue - absMtSlot->minValue + 1; + } else { + props.max_finger_cnt = 1; + } props.max_touch_cnt = getMaxTouchCount(context); // T5R2 ("Track 5, Report 2") is a feature of some old Synaptics touchpads that could track 5 @@ -71,9 +81,7 @@ HardwareProperties createHardwareProperties(const InputDeviceContext& context) { // are haptic. props.is_haptic_pad = false; - RawAbsoluteAxisInfo absMtPressure; - context.getAbsoluteAxisInfo(ABS_MT_PRESSURE, &absMtPressure); - props.reports_pressure = absMtPressure.valid; + props.reports_pressure = context.hasAbsoluteAxis(ABS_MT_PRESSURE); return props; } diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index 12736c8cc0..7079278a90 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -105,7 +105,6 @@ void FakeEventHub::addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, Device* device = getDevice(deviceId); RawAbsoluteAxisInfo info; - info.valid = true; info.minValue = minValue; info.maxValue = maxValue; info.flat = flat; diff --git a/services/inputflinger/tests/HardwareProperties_test.cpp b/services/inputflinger/tests/HardwareProperties_test.cpp index 643fab6d44..e87f8228c8 100644 --- a/services/inputflinger/tests/HardwareProperties_test.cpp +++ b/services/inputflinger/tests/HardwareProperties_test.cpp @@ -50,7 +50,6 @@ protected: void setupValidAxis(int axis, int32_t min, int32_t max, int32_t resolution) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) .WillRepeatedly(Return(std::optional{{ - .valid = true, .minValue = min, .maxValue = max, .flat = 0, diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index 19bc5bef66..5722444f16 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -59,7 +59,6 @@ void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t m int32_t resolution) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) .WillRepeatedly(Return(valid ? std::optional{{ - .valid = true, .minValue = min, .maxValue = max, .flat = 0, diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index 6dea540e9c..969c03268e 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -130,7 +130,6 @@ public: } if (mFdp->ConsumeBool()) { return std::optional({ - .valid = mFdp->ConsumeBool(), .minValue = mFdp->ConsumeIntegral(), .maxValue = mFdp->ConsumeIntegral(), .flat = mFdp->ConsumeIntegral(), diff --git a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp index c620032eef..ebbb311512 100644 --- a/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/TouchpadInputFuzzer.cpp @@ -34,7 +34,6 @@ void setAxisInfo(ThreadSafeFuzzedDataProvider& fdp, FuzzEventHub& eventHub, int3 if (fdp.ConsumeBool()) { eventHub.setAbsoluteAxisInfo(id, axis, RawAbsoluteAxisInfo{ - .valid = fdp.ConsumeBool(), .minValue = fdp.ConsumeIntegral(), .maxValue = fdp.ConsumeIntegral(), .flat = fdp.ConsumeIntegral(), -- GitLab From fe25f12be72212333ab35ee3c62b155d2f557077 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Wed, 26 Jun 2024 12:45:57 -0700 Subject: [PATCH 062/530] BackendUnifiedServiceManager: tidy up includes This was breaking Linux Binder IPC (WIP) build. Bug: 341997808 Test: mma Change-Id: Ic3f25c9c49773d4f7c759e8318513f166ec2d995 --- libs/binder/BackendUnifiedServiceManager.cpp | 4 ++++ libs/binder/BackendUnifiedServiceManager.h | 1 - libs/binder/IServiceManager.cpp | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp index 496c5ef788..b0d3048c37 100644 --- a/libs/binder/BackendUnifiedServiceManager.cpp +++ b/libs/binder/BackendUnifiedServiceManager.cpp @@ -15,6 +15,10 @@ */ #include "BackendUnifiedServiceManager.h" +#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__) +#include +#endif + namespace android { using AidlServiceManager = android::os::IServiceManager; diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h index a67d5bae2d..d72b5bb94f 100644 --- a/libs/binder/BackendUnifiedServiceManager.h +++ b/libs/binder/BackendUnifiedServiceManager.h @@ -15,7 +15,6 @@ */ #pragma once -#include #include #include #include diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 50d00ae2f2..2095586528 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -16,8 +16,8 @@ #define LOG_TAG "ServiceManagerCppClient" -#include #include +#include "BackendUnifiedServiceManager.h" #include #include -- GitLab From d1603f4fab2b6700d28c55c724e3c12cea50674d Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Wed, 26 Jun 2024 14:05:42 -0700 Subject: [PATCH 063/530] Reformat BpBinder.h Bug: 341997808 Test: mma Change-Id: I052ed2841c02ddb170dcaab534c5326eeb09f411 --- libs/binder/include/binder/BpBinder.h | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index 8ac30ba02f..d7f74c4152 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -176,10 +176,10 @@ private: BpBinder(BinderHandle&& handle, int32_t trackedUid); explicit BpBinder(RpcHandle&& handle); - virtual ~BpBinder(); - virtual void onFirstRef(); - virtual void onLastStrongRef(const void* id); - virtual bool onIncStrongAttempted(uint32_t flags, const void* id); + virtual ~BpBinder(); + virtual void onFirstRef(); + virtual void onLastStrongRef(const void* id); + virtual bool onIncStrongAttempted(uint32_t flags, const void* id); friend ::android::internal::Stability; @@ -192,30 +192,30 @@ private: uint32_t flags; }; - void reportOneDeath(const Obituary& obit); - bool isDescriptorCached() const; - - mutable RpcMutex mLock; - volatile int32_t mAlive; - volatile int32_t mObitsSent; - Vector* mObituaries; - ObjectManager mObjects; - mutable String16 mDescriptorCache; - int32_t mTrackedUid; - - static RpcMutex sTrackingLock; - static std::unordered_map sTrackingMap; - static int sNumTrackedUids; - static std::atomic_bool sCountByUidEnabled; - static binder_proxy_limit_callback sLimitCallback; - static uint32_t sBinderProxyCountHighWatermark; - static uint32_t sBinderProxyCountLowWatermark; - static bool sBinderProxyThrottleCreate; - static std::unordered_map sLastLimitCallbackMap; - static std::atomic sBinderProxyCount; - static std::atomic sBinderProxyCountWarned; - static binder_proxy_warning_callback sWarningCallback; - static uint32_t sBinderProxyCountWarningWatermark; + void reportOneDeath(const Obituary& obit); + bool isDescriptorCached() const; + + mutable RpcMutex mLock; + volatile int32_t mAlive; + volatile int32_t mObitsSent; + Vector* mObituaries; + ObjectManager mObjects; + mutable String16 mDescriptorCache; + int32_t mTrackedUid; + + static RpcMutex sTrackingLock; + static std::unordered_map sTrackingMap; + static int sNumTrackedUids; + static std::atomic_bool sCountByUidEnabled; + static binder_proxy_limit_callback sLimitCallback; + static uint32_t sBinderProxyCountHighWatermark; + static uint32_t sBinderProxyCountLowWatermark; + static bool sBinderProxyThrottleCreate; + static std::unordered_map sLastLimitCallbackMap; + static std::atomic sBinderProxyCount; + static std::atomic sBinderProxyCountWarned; + static binder_proxy_warning_callback sWarningCallback; + static uint32_t sBinderProxyCountWarningWatermark; }; } // namespace android -- GitLab From 4532c9841559818896f7322fb13b85ed49bd177a Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Fri, 21 Jun 2024 15:10:58 -0700 Subject: [PATCH 064/530] Binder NDK tests: use std::mutex, not android::Mutex Bug: 341997808 Test: mma Change-Id: Ie485a31a895dcd7fa70134e2b16e4cfb682581bb --- libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index 966ec959b6..666b3af762 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -826,22 +826,22 @@ TEST(NdkBinder, GetAndVerifyScopedAIBinder_Weak) { class MyResultReceiver : public BnResultReceiver { public: - Mutex mMutex; - Condition mCondition; + std::mutex mMutex; + std::condition_variable mCondition; bool mHaveResult = false; int32_t mResult = 0; virtual void send(int32_t resultCode) { - AutoMutex _l(mMutex); + std::unique_lock _l(mMutex); mResult = resultCode; mHaveResult = true; - mCondition.signal(); + mCondition.notify_one(); } int32_t waitForResult() { - AutoMutex _l(mMutex); + std::unique_lock _l(mMutex); while (!mHaveResult) { - mCondition.wait(mMutex); + mCondition.wait(_l); } return mResult; } -- GitLab From be0ad90f195063f8a846b15cb435d71544e5db1f Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 27 Jun 2024 23:38:43 +0000 Subject: [PATCH 065/530] Create a wrapper for atrace macros Create a SF specific macro to call into atrace. This will make the switch to perfetto for capturing atrace tags easier. Flag: EXEMPT refactor Bug: 349905670 Test: perfetto Change-Id: I4d046d837f52ef78b08e3c97556f2eddb06232dd --- services/surfaceflinger/ClientCache.cpp | 2 +- .../src/CompositionEngine.cpp | 10 +- .../CompositionEngine/src/Display.cpp | 6 +- .../CompositionEngine/src/Output.cpp | 35 ++-- .../CompositionEngine/src/RenderSurface.cpp | 4 +- .../src/planner/CachedSet.cpp | 4 +- .../src/planner/Flattener.cpp | 31 ++- .../CompositionEngine/src/planner/Planner.cpp | 8 +- .../Display/DisplayModeController.cpp | 8 +- services/surfaceflinger/DisplayDevice.cpp | 5 +- .../DisplayHardware/AidlComposerHal.cpp | 9 +- .../DisplayHardware/HWComposer.cpp | 31 ++- .../DisplayHardware/HidlComposerHal.cpp | 8 +- .../DisplayHardware/PowerAdvisor.cpp | 34 ++-- .../FrameTimeline/FrameTimeline.cpp | 16 +- .../FrontEnd/LayerHierarchy.cpp | 6 +- .../FrontEnd/LayerSnapshotBuilder.cpp | 6 +- .../FrontEnd/RequestedLayerState.cpp | 14 +- .../FrontEnd/TransactionHandler.cpp | 8 +- .../surfaceflinger/HdrLayerInfoReporter.cpp | 6 +- services/surfaceflinger/Layer.cpp | 91 +++++---- services/surfaceflinger/LayerFE.cpp | 7 +- .../surfaceflinger/RegionSamplingThread.cpp | 14 +- .../surfaceflinger/Scheduler/EventThread.cpp | 7 +- .../surfaceflinger/Scheduler/LayerHistory.cpp | 44 ++--- .../surfaceflinger/Scheduler/LayerInfo.cpp | 36 ++-- .../surfaceflinger/Scheduler/MessageQueue.cpp | 6 +- .../Scheduler/RefreshRateSelector.cpp | 57 +++--- .../surfaceflinger/Scheduler/Scheduler.cpp | 34 ++-- .../Scheduler/VSyncDispatchTimerQueue.cpp | 36 ++-- .../Scheduler/VSyncPredictor.cpp | 101 +++++----- .../surfaceflinger/Scheduler/VSyncReactor.cpp | 23 ++- .../Scheduler/VsyncModulator.cpp | 10 +- .../Scheduler/VsyncSchedule.cpp | 6 +- .../Scheduler/src/FrameTargeter.cpp | 11 +- .../surfaceflinger/Scheduler/src/Timer.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 182 +++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 4 +- services/surfaceflinger/TimeStats/Android.bp | 1 + .../surfaceflinger/TimeStats/TimeStats.cpp | 54 +++--- services/surfaceflinger/TracedOrdinal.h | 10 +- .../surfaceflinger/Tracing/LayerTracing.cpp | 4 +- .../Tracing/TransactionRingBuffer.h | 5 +- .../TransactionCallbackInvoker.cpp | 6 +- .../WindowInfosListenerInvoker.cpp | 12 +- .../common/include/common/trace.h | 104 ++++++++++ 46 files changed, 606 insertions(+), 514 deletions(-) create mode 100644 services/surfaceflinger/common/include/common/trace.h diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index 09e41ffede..40ea8d387a 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include "ClientCache.h" diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 4c776879f0..5c5d0cd74d 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -23,7 +24,6 @@ #include #include -#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -128,7 +128,7 @@ void offloadOutputs(Outputs& outputs) { } // namespace void CompositionEngine::present(CompositionRefreshArgs& args) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); preComposition(args); @@ -155,7 +155,7 @@ void CompositionEngine::present(CompositionRefreshArgs& args) { } { - ATRACE_NAME("Waiting on HWC"); + SFTRACE_NAME("Waiting on HWC"); for (auto& future : presentFutures) { // TODO(b/185536303): Call ftl::Future::wait() once it exists, since // we do not need the return value of get(). @@ -177,7 +177,7 @@ void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) { } void CompositionEngine::preComposition(CompositionRefreshArgs& args) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); bool needsAnotherUpdate = false; @@ -199,7 +199,7 @@ void CompositionEngine::preComposition(CompositionRefreshArgs& args) { // promises for buffer releases are fulfilled at the end of composition. void CompositionEngine::postComposition(CompositionRefreshArgs& args) { if (FlagManager::getInstance().ce_fence_promise()) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); for (auto& layerFE : args.layers) { diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index c1617d787b..77b1940e23 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -25,9 +26,6 @@ #include #include #include -#include - -#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -235,7 +233,7 @@ void Display::beginFrame() { bool Display::chooseCompositionStrategy( std::optional* outChanges) { - ATRACE_FORMAT("%s for %s", __func__, getNamePlusId().c_str()); + SFTRACE_FORMAT("%s for %s", __func__, getNamePlusId().c_str()); ALOGV(__FUNCTION__); if (mIsDisconnected) { diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index b40aea4210..64cded8691 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include #include @@ -53,7 +53,6 @@ #include #include #include -#include #include "TracedOrdinal.h" @@ -424,7 +423,7 @@ void Output::setReleasedLayers(Output::ReleasedLayers&& layers) { void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs, LayerFESet& geomSnapshots) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); rebuildLayerStacks(refreshArgs, geomSnapshots); @@ -453,8 +452,8 @@ ftl::Future Output::present( }) .value(); }; - ATRACE_FORMAT("%s for %s%s", __func__, mNamePlusId.c_str(), - stringifyExpectedPresentTime().c_str()); + SFTRACE_FORMAT("%s for %s%s", __func__, mNamePlusId.c_str(), + stringifyExpectedPresentTime().c_str()); ALOGV(__FUNCTION__); updateColorProfile(refreshArgs); @@ -518,7 +517,7 @@ void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& if (!outputState.isEnabled || CC_LIKELY(!refreshArgs.updatingOutputGeometryThisFrame)) { return; } - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); // Process the layers to determine visibility and coverage @@ -804,7 +803,7 @@ void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) } void Output::updateCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); if (!getState().isEnabled) { @@ -831,14 +830,14 @@ void Output::planComposition() { return; } - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); mPlanner->plan(getOutputLayersOrderedByZ()); } void Output::writeCompositionState(const compositionengine::CompositionRefreshArgs& refreshArgs) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); if (!getState().isEnabled) { @@ -1081,7 +1080,7 @@ void Output::beginFrame() { } void Output::prepareFrame() { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); auto& outputState = editState(); @@ -1116,7 +1115,7 @@ std::future Output::chooseCompositionStrategyAsync( } GpuCompositionResult Output::prepareFrameAsync() { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); auto& state = editState(); const auto& previousChanges = state.previousDeviceRequestedChanges; @@ -1146,7 +1145,7 @@ GpuCompositionResult Output::prepareFrameAsync() { state.strategyPrediction = predictionSucceeded ? CompositionStrategyPredictionState::SUCCESS : CompositionStrategyPredictionState::FAIL; if (!predictionSucceeded) { - ATRACE_NAME("CompositionStrategyPredictionMiss"); + SFTRACE_NAME("CompositionStrategyPredictionMiss"); resetCompositionStrategy(); if (chooseCompositionSuccess) { applyCompositionStrategy(changes); @@ -1155,7 +1154,7 @@ GpuCompositionResult Output::prepareFrameAsync() { // Track the dequeued buffer to reuse so we don't need to dequeue another one. compositionResult.buffer = buffer; } else { - ATRACE_NAME("CompositionStrategyPredictionHit"); + SFTRACE_NAME("CompositionStrategyPredictionHit"); } state.previousDeviceRequestedChanges = std::move(changes); state.previousDeviceRequestedSuccess = chooseCompositionSuccess; @@ -1187,7 +1186,7 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& } void Output::finishFrame(GpuCompositionResult&& result) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); const auto& outputState = getState(); if (!outputState.isEnabled) { @@ -1276,7 +1275,7 @@ bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence, std::optional Output::composeSurfaces( const Region& debugRegion, std::shared_ptr tex, base::unique_fd& fd) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV(__FUNCTION__); const auto& outputState = getState(); @@ -1317,13 +1316,13 @@ std::optional Output::composeSurfaces( if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers)) { - ATRACE_NAME("ClientCompositionCacheHit"); + SFTRACE_NAME("ClientCompositionCacheHit"); outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); // b/239944175 pass the fence associated with the buffer. return base::unique_fd(std::move(fd)); } - ATRACE_NAME("ClientCompositionCacheMiss"); + SFTRACE_NAME("ClientCompositionCacheMiss"); mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1570,7 +1569,7 @@ bool Output::isPowerHintSessionGpuReportingEnabled() { } void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { - ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str()); + SFTRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str()); ALOGV(__FUNCTION__); if (!getState().isEnabled) { diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index c0b23d97d4..d6028bf4cf 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #include #include #include -#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -149,7 +149,7 @@ void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComp std::shared_ptr RenderSurface::dequeueBuffer( base::unique_fd* bufferFence) { - ATRACE_CALL(); + SFTRACE_CALL(); int fd = -1; ANativeWindowBuffer* buffer = nullptr; diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index ea9442da06..409a206ace 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include namespace android::compositionengine::impl::planner { @@ -160,7 +160,7 @@ void CachedSet::updateAge(std::chrono::steady_clock::time_point now) { void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& texturePool, const OutputCompositionState& outputState, bool deviceHandlesColorTransform) { - ATRACE_CALL(); + SFTRACE_CALL(); if (outputState.powerCallback) { outputState.powerCallback->notifyCpuLoadUp(); } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index 4bafed2c8e..783209c26a 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -21,11 +21,10 @@ #include #include +#include #include #include -#include - using time_point = std::chrono::steady_clock::time_point; using namespace std::chrono_literals; @@ -77,7 +76,7 @@ Flattener::Flattener(renderengine::RenderEngine& renderEngine, const Tunables& t NonBufferHash Flattener::flattenLayers(const std::vector& layers, NonBufferHash hash, time_point now) { - ATRACE_CALL(); + SFTRACE_CALL(); const size_t unflattenedDisplayCost = calculateDisplayCost(layers); mUnflattenedDisplayCost += unflattenedDisplayCost; @@ -113,7 +112,7 @@ void Flattener::renderCachedSets( const OutputCompositionState& outputState, std::optional renderDeadline, bool deviceHandlesColorTransform) { - ATRACE_CALL(); + SFTRACE_CALL(); if (!mNewCachedSet) { return; @@ -121,7 +120,7 @@ void Flattener::renderCachedSets( // Ensure that a cached set has a valid buffer first if (mNewCachedSet->hasRenderedBuffer()) { - ATRACE_NAME("mNewCachedSet->hasRenderedBuffer()"); + SFTRACE_NAME("mNewCachedSet->hasRenderedBuffer()"); return; } @@ -138,13 +137,13 @@ void Flattener::renderCachedSets( if (mNewCachedSet->getSkipCount() <= mTunables.mRenderScheduling->maxDeferRenderAttempts) { - ATRACE_FORMAT("DeadlinePassed: exceeded deadline by: %d us", - std::chrono::duration_cast( - estimatedRenderFinish - *renderDeadline) - .count()); + SFTRACE_FORMAT("DeadlinePassed: exceeded deadline by: %d us", + std::chrono::duration_cast( + estimatedRenderFinish - *renderDeadline) + .count()); return; } else { - ATRACE_NAME("DeadlinePassed: exceeded max skips"); + SFTRACE_NAME("DeadlinePassed: exceeded max skips"); } } } @@ -271,7 +270,7 @@ NonBufferHash Flattener::computeLayersHash() const{ // was already populated with these layers, i.e. on the second and following // calls with the same geometry. bool Flattener::mergeWithCachedSets(const std::vector& layers, time_point now) { - ATRACE_CALL(); + SFTRACE_CALL(); std::vector merged; if (mLayers.empty()) { @@ -415,7 +414,7 @@ bool Flattener::mergeWithCachedSets(const std::vector& layers } std::vector Flattener::findCandidateRuns(time_point now) const { - ATRACE_CALL(); + SFTRACE_CALL(); std::vector runs; bool isPartOfRun = false; Run::Builder builder; @@ -431,8 +430,8 @@ std::vector Flattener::findCandidateRuns(time_point now) const { if (!layerIsInactive && currentSet->getLayerCount() == kNumLayersFpsConsideration) { auto layerFps = currentSet->getFirstLayer().getState()->getFps(); if (layerFps > 0 && layerFps <= kFpsActiveThreshold) { - ATRACE_FORMAT("layer is considered inactive due to low FPS [%s] %f", - currentSet->getFirstLayer().getName().c_str(), layerFps); + SFTRACE_FORMAT("layer is considered inactive due to low FPS [%s] %f", + currentSet->getFirstLayer().getName().c_str(), layerFps); layerIsInactive = true; } } @@ -494,7 +493,7 @@ std::optional Flattener::findBestRun(std::vector } void Flattener::buildCachedSets(time_point now) { - ATRACE_CALL(); + SFTRACE_CALL(); if (mLayers.empty()) { ALOGV("[%s] No layers found, returning", __func__); return; @@ -508,7 +507,7 @@ void Flattener::buildCachedSets(time_point now) { for (const CachedSet& layer : mLayers) { // TODO (b/191997217): make it less aggressive, and sync with findCandidateRuns if (layer.hasProtectedLayers()) { - ATRACE_NAME("layer->hasProtectedLayers()"); + SFTRACE_NAME("layer->hasProtectedLayers()"); return; } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index 5e6cade56f..d114ff79a1 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -21,11 +21,11 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include +#include #include #include #include -#include #include namespace android::compositionengine::impl::planner { @@ -83,7 +83,7 @@ void Planner::setDisplaySize(ui::Size size) { void Planner::plan( compositionengine::Output::OutputLayersEnumerator&& layers) { - ATRACE_CALL(); + SFTRACE_CALL(); std::unordered_set removedLayers; removedLayers.reserve(mPreviousLayers.size()); @@ -165,7 +165,7 @@ void Planner::plan( void Planner::reportFinalPlan( compositionengine::Output::OutputLayersEnumerator&& layers) { - ATRACE_CALL(); + SFTRACE_CALL(); if (!mPredictorEnabled) { return; } @@ -204,7 +204,7 @@ void Planner::reportFinalPlan( void Planner::renderCachedSets(const OutputCompositionState& outputState, std::optional renderDeadline, bool deviceHandlesColorTransform) { - ATRACE_CALL(); + SFTRACE_CALL(); mFlattener.renderCachedSets(outputState, renderDeadline, deviceHandlesColorTransform); } diff --git a/services/surfaceflinger/Display/DisplayModeController.cpp b/services/surfaceflinger/Display/DisplayModeController.cpp index a6a9bec3c3..c43d585270 100644 --- a/services/surfaceflinger/Display/DisplayModeController.cpp +++ b/services/surfaceflinger/Display/DisplayModeController.cpp @@ -83,7 +83,7 @@ auto DisplayModeController::setDesiredMode(PhysicalDisplayId displayId, FTL_EXPECT(mDisplays.get(displayId).ok_or(DesiredModeAction::None)).get(); { - ATRACE_NAME(displayPtr->concatId(__func__).c_str()); + SFTRACE_NAME(displayPtr->concatId(__func__).c_str()); ALOGD("%s %s", displayPtr->concatId(__func__).c_str(), to_string(desiredMode).c_str()); std::scoped_lock lock(displayPtr->desiredModeLock); @@ -204,7 +204,7 @@ bool DisplayModeController::initiateModeChange(PhysicalDisplayId displayId, return false; } - ATRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue()); + SFTRACE_INT(displayPtr->pendingModeFpsTrace.c_str(), mode.getVsyncRate().getIntValue()); return true; } @@ -227,8 +227,8 @@ void DisplayModeController::setActiveModeLocked(PhysicalDisplayId displayId, Dis Fps vsyncRate, Fps renderFps) { const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get(); - ATRACE_INT(displayPtr->activeModeFpsTrace.c_str(), vsyncRate.getIntValue()); - ATRACE_INT(displayPtr->renderRateFpsTrace.c_str(), renderFps.getIntValue()); + SFTRACE_INT(displayPtr->activeModeFpsTrace.c_str(), vsyncRate.getIntValue()); + SFTRACE_INT(displayPtr->renderRateFpsTrace.c_str(), renderFps.getIntValue()); displayPtr->selectorPtr->setActiveMode(modeId, renderFps); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 27ea4a9865..8288b99864 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -24,6 +24,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include #include #include #include @@ -398,7 +399,7 @@ void DisplayDevice::enableHdrSdrRatioOverlay(bool enable) { } void DisplayDevice::updateHdrSdrRatioOverlayRatio(float currentHdrSdrRatio) { - ATRACE_CALL(); + SFTRACE_CALL(); mHdrSdrRatio = currentHdrSdrRatio; if (mHdrSdrRatioOverlay) { mHdrSdrRatioOverlay->changeHdrSdrRatio(currentHdrSdrRatio); @@ -440,7 +441,7 @@ void DisplayDevice::enableRefreshRateOverlay(bool enable, bool setByHwc, Fps ref } void DisplayDevice::updateRefreshRateOverlayRate(Fps refreshRate, Fps renderFps, bool setByHwc) { - ATRACE_CALL(); + SFTRACE_CALL(); if (mRefreshRateOverlay) { if (!mRefreshRateOverlay->isSetByHwc() || setByHwc) { if (mRefreshRateSelector->isVrrDevice() && !mRefreshRateOverlay->isSetByHwc()) { diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp index 362ab9c39e..d50a0bcec1 100644 --- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp @@ -25,9 +25,8 @@ #include #include #include -#include +#include #include -#include #include @@ -677,7 +676,7 @@ Error AidlComposer::getReleaseFences(Display display, std::vector* outLay Error AidlComposer::presentDisplay(Display display, int* outPresentFence) { const auto displayId = translate(display); - ATRACE_FORMAT("HwcPresentDisplay %" PRId64, displayId); + SFTRACE_FORMAT("HwcPresentDisplay %" PRId64, displayId); Error error = Error::NONE; mMutex.lock_shared(); @@ -810,7 +809,7 @@ Error AidlComposer::validateDisplay(Display display, nsecs_t expectedPresentTime int32_t frameIntervalNs, uint32_t* outNumTypes, uint32_t* outNumRequests) { const auto displayId = translate(display); - ATRACE_FORMAT("HwcValidateDisplay %" PRId64, displayId); + SFTRACE_FORMAT("HwcValidateDisplay %" PRId64, displayId); Error error = Error::NONE; mMutex.lock_shared(); @@ -840,7 +839,7 @@ Error AidlComposer::presentOrValidateDisplay(Display display, nsecs_t expectedPr uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) { const auto displayId = translate(display); - ATRACE_FORMAT("HwcPresentOrValidateDisplay %" PRId64, displayId); + SFTRACE_FORMAT("HwcPresentOrValidateDisplay %" PRId64, displayId); Error error = Error::NONE; mMutex.lock_shared(); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 3d285a84ef..73fa855c3c 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -28,16 +28,15 @@ #include "HWComposer.h" #include +#include #include #include #include #include -#include #include #include #include #include -#include #include "../Layer.h" // needed only for debugging #include "../SurfaceFlingerProperties.h" @@ -178,8 +177,8 @@ std::optional HWComposer::onVsync(hal::HWDisplayId hwcDisplay displayData.lastPresentTimestamp = timestamp; } - ATRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(), - displayData.vsyncTraceToggle); + SFTRACE_INT(ftl::Concat("HW_VSYNC_", displayIdOpt->value).c_str(), + displayData.vsyncTraceToggle); displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; return displayIdOpt; @@ -428,14 +427,14 @@ void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled return; } - ATRACE_CALL(); + SFTRACE_CALL(); auto error = displayData.hwcDisplay->setVsyncEnabled(enabled); RETURN_IF_HWC_ERROR(error, displayId); displayData.vsyncEnabled = enabled; - ATRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(), - enabled == hal::Vsync::ENABLE ? 1 : 0); + SFTRACE_INT(ftl::Concat("HW_VSYNC_ON_", displayId.value).c_str(), + enabled == hal::Vsync::ENABLE ? 1 : 0); } status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot, @@ -455,7 +454,7 @@ status_t HWComposer::getDeviceCompositionChanges( std::optional earliestPresentTime, nsecs_t expectedPresentTime, Fps frameInterval, std::optional* outChanges) { - ATRACE_CALL(); + SFTRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -493,7 +492,7 @@ status_t HWComposer::getDeviceCompositionChanges( }(); displayData.validateWasSkipped = false; - ATRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue()); + SFTRACE_FORMAT("NextFrameInterval %d_Hz", frameInterval.getIntValue()); if (canSkipValidate) { sp outPresentFence = Fence::NO_FENCE; uint32_t state = UINT32_MAX; @@ -568,7 +567,7 @@ sp HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* status_t HWComposer::presentAndGetReleaseFences( HalDisplayId displayId, std::optional earliestPresentTime) { - ATRACE_CALL(); + SFTRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -584,7 +583,7 @@ status_t HWComposer::presentAndGetReleaseFences( } if (earliestPresentTime) { - ATRACE_NAME("wait for earliest present time"); + SFTRACE_NAME("wait for earliest present time"); std::this_thread::sleep_until(*earliestPresentTime); } @@ -897,9 +896,9 @@ status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId status_t HWComposer::notifyExpectedPresent(PhysicalDisplayId displayId, TimePoint expectedPresentTime, Fps frameInterval) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - ATRACE_FORMAT("%s ExpectedPresentTime in %.2fms frameInterval %.2fms", __func__, - ticks(expectedPresentTime - TimePoint::now()), - ticks(Duration::fromNs(frameInterval.getPeriodNsecs()))); + SFTRACE_FORMAT("%s ExpectedPresentTime in %.2fms frameInterval %.2fms", __func__, + ticks(expectedPresentTime - TimePoint::now()), + ticks(Duration::fromNs(frameInterval.getPeriodNsecs()))); const auto error = mComposer->notifyExpectedPresent(mDisplayData[displayId].hwcDisplay->getId(), expectedPresentTime.ns(), frameInterval.getPeriodNsecs()); @@ -1149,7 +1148,7 @@ void HWComposer::loadHdrConversionCapabilities() { status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId, std::chrono::milliseconds timeout) { - ATRACE_CALL(); + SFTRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout); if (error == hal::Error::UNSUPPORTED) { @@ -1168,7 +1167,7 @@ bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) cons } Hwc2::AidlTransform HWComposer::getPhysicalDisplayOrientation(PhysicalDisplayId displayId) const { - ATRACE_CALL(); + SFTRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, Hwc2::AidlTransform::NONE); Hwc2::AidlTransform outTransform; const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay; diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp index 12ab2c284a..c5008d8dd5 100644 --- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp @@ -27,11 +27,11 @@ #include #include #include +#include #include #include #include #include -#include #include "HWC2.h" #include "Hal.h" @@ -588,7 +588,7 @@ Error HidlComposer::getReleaseFences(Display display, std::vector* outLay } Error HidlComposer::presentDisplay(Display display, int* outPresentFence) { - ATRACE_NAME("HwcPresentDisplay"); + SFTRACE_NAME("HwcPresentDisplay"); mWriter.selectDisplay(display); mWriter.presentDisplay(); @@ -676,7 +676,7 @@ Error HidlComposer::setClientTargetSlotCount(Display display) { Error HidlComposer::validateDisplay(Display display, nsecs_t /*expectedPresentTime*/, int32_t /*frameIntervalNs*/, uint32_t* outNumTypes, uint32_t* outNumRequests) { - ATRACE_NAME("HwcValidateDisplay"); + SFTRACE_NAME("HwcValidateDisplay"); mWriter.selectDisplay(display); mWriter.validateDisplay(); @@ -694,7 +694,7 @@ Error HidlComposer::presentOrValidateDisplay(Display display, nsecs_t /*expected int32_t /*frameIntervalNs*/, uint32_t* outNumTypes, uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) { - ATRACE_NAME("HwcPresentOrValidateDisplay"); + SFTRACE_NAME("HwcPresentOrValidateDisplay"); mWriter.selectDisplay(display); mWriter.presentOrvalidateDisplay(); diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index 6c1a81314d..da56014530 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -27,9 +27,9 @@ #include #include +#include #include #include -#include #include @@ -74,9 +74,9 @@ std::chrono::milliseconds getUpdateTimeout() { void traceExpensiveRendering(bool enabled) { if (enabled) { - ATRACE_ASYNC_BEGIN("ExpensiveRendering", 0); + SFTRACE_ASYNC_BEGIN("ExpensiveRendering", 0); } else { - ATRACE_ASYNC_END("ExpensiveRendering", 0); + SFTRACE_ASYNC_END("ExpensiveRendering", 0); } } @@ -210,7 +210,7 @@ void PowerAdvisor::sendHintSessionHint(SessionHint hint) { ALOGV("Power hint session is not enabled, skip sending session hint"); return; } - ATRACE_CALL(); + SFTRACE_CALL(); if (sTraceHintSessionData) ATRACE_INT("Session hint", static_cast(hint)); { std::scoped_lock lock(mHintSessionMutex); @@ -295,7 +295,7 @@ void PowerAdvisor::updateTargetWorkDuration(Duration targetDuration) { ALOGV("Power hint session is not enabled, skipping target update"); return; } - ATRACE_CALL(); + SFTRACE_CALL(); { mTargetDuration = targetDuration; if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDuration.ns()); @@ -324,7 +324,7 @@ void PowerAdvisor::reportActualWorkDuration() { ALOGV("Actual work duration power hint cannot be sent, skipping"); return; } - ATRACE_CALL(); + SFTRACE_CALL(); std::optional actualDuration = estimateWorkDuration(); if (!actualDuration.has_value() || actualDuration->durationNanos < 0) { ALOGV("Failed to send actual work duration, skipping"); @@ -332,16 +332,16 @@ void PowerAdvisor::reportActualWorkDuration() { } actualDuration->durationNanos += sTargetSafetyMargin.ns(); if (sTraceHintSessionData) { - ATRACE_INT64("Measured duration", actualDuration->durationNanos); - ATRACE_INT64("Target error term", actualDuration->durationNanos - mTargetDuration.ns()); - ATRACE_INT64("Reported duration", actualDuration->durationNanos); + SFTRACE_INT64("Measured duration", actualDuration->durationNanos); + SFTRACE_INT64("Target error term", actualDuration->durationNanos - mTargetDuration.ns()); + SFTRACE_INT64("Reported duration", actualDuration->durationNanos); if (supportsGpuReporting()) { - ATRACE_INT64("Reported cpu duration", actualDuration->cpuDurationNanos); - ATRACE_INT64("Reported gpu duration", actualDuration->gpuDurationNanos); + SFTRACE_INT64("Reported cpu duration", actualDuration->cpuDurationNanos); + SFTRACE_INT64("Reported gpu duration", actualDuration->gpuDurationNanos); } - ATRACE_INT64("Reported target", mLastTargetDurationSent.ns()); - ATRACE_INT64("Reported target error term", - actualDuration->durationNanos - mLastTargetDurationSent.ns()); + SFTRACE_INT64("Reported target", mLastTargetDurationSent.ns()); + SFTRACE_INT64("Reported target error term", + actualDuration->durationNanos - mLastTargetDurationSent.ns()); } ALOGV("Sending actual work duration of: %" PRId64 " with cpu: %" PRId64 " and gpu: %" PRId64 @@ -664,9 +664,9 @@ std::optional PowerAdvisor::estimateWorkDuration() { .gpuDurationNanos = supportsGpuReporting() ? estimatedGpuDuration.ns() : 0, }; if (sTraceHintSessionData) { - ATRACE_INT64("Idle duration", idleDuration.ns()); - ATRACE_INT64("Total duration", totalDuration.ns()); - ATRACE_INT64("Flinger duration", flingerDuration.ns()); + SFTRACE_INT64("Idle duration", idleDuration.ns()); + SFTRACE_INT64("Total duration", totalDuration.ns()); + SFTRACE_INT64("Flinger duration", flingerDuration.ns()); } return std::make_optional(duration); } diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index f671006149..55505650e3 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -22,8 +22,8 @@ #include #include +#include #include -#include #include #include @@ -829,7 +829,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) cons namespace impl { int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) { - ATRACE_CALL(); + SFTRACE_CALL(); std::scoped_lock lock(mMutex); while (mPredictions.size() >= kMaxTokens) { mPredictions.erase(mPredictions.begin()); @@ -875,7 +875,7 @@ void FrameTimeline::registerDataSource() { std::shared_ptr FrameTimeline::createSurfaceFrameForToken( const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, int32_t layerId, std::string layerName, std::string debugName, bool isBuffer, GameMode gameMode) { - ATRACE_CALL(); + SFTRACE_CALL(); if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, layerId, std::move(layerName), std::move(debugName), @@ -911,14 +911,14 @@ FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr timeStats, } void FrameTimeline::addSurfaceFrame(std::shared_ptr surfaceFrame) { - ATRACE_CALL(); + SFTRACE_CALL(); std::scoped_lock lock(mMutex); mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame); } void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate, Fps renderRate) { - ATRACE_CALL(); + SFTRACE_CALL(); std::scoped_lock lock(mMutex); mCurrentDisplayFrame->onSfWakeUp(token, refreshRate, renderRate, mTokenManager.getPredictionsForToken(token), wakeUpTime); @@ -927,7 +927,7 @@ void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRa void FrameTimeline::setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr& presentFence, const std::shared_ptr& gpuFence) { - ATRACE_CALL(); + SFTRACE_CALL(); std::scoped_lock lock(mMutex); mCurrentDisplayFrame->setActualEndTime(sfPresentTime); mCurrentDisplayFrame->setGpuFence(gpuFence); @@ -937,7 +937,7 @@ void FrameTimeline::setSfPresent(nsecs_t sfPresentTime, } void FrameTimeline::onCommitNotComposited() { - ATRACE_CALL(); + SFTRACE_CALL(); std::scoped_lock lock(mMutex); mCurrentDisplayFrame->onCommitNotComposited(); mCurrentDisplayFrame.reset(); @@ -1516,7 +1516,7 @@ void FrameTimeline::dumpJank(std::string& result) { } void FrameTimeline::parseArgs(const Vector& args, std::string& result) { - ATRACE_CALL(); + SFTRACE_CALL(); std::unordered_map argsMap; for (size_t i = 0; i < args.size(); i++) { argsMap[std::string(String8(args[i]).c_str())] = true; diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 39a6b777bb..f4335f36bc 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -413,11 +413,11 @@ void LayerHierarchyBuilder::doUpdate( void LayerHierarchyBuilder::update(LayerLifecycleManager& layerLifecycleManager) { if (!mInitialized) { - ATRACE_NAME("LayerHierarchyBuilder:init"); + SFTRACE_NAME("LayerHierarchyBuilder:init"); init(layerLifecycleManager.getLayers()); } else if (layerLifecycleManager.getGlobalChanges().test( RequestedLayerState::Changes::Hierarchy)) { - ATRACE_NAME("LayerHierarchyBuilder:update"); + SFTRACE_NAME("LayerHierarchyBuilder:update"); doUpdate(layerLifecycleManager.getLayers(), layerLifecycleManager.getDestroyedLayers()); } else { return; // nothing to do @@ -426,7 +426,7 @@ void LayerHierarchyBuilder::update(LayerLifecycleManager& layerLifecycleManager) uint32_t invalidRelativeRoot; bool hasRelZLoop = mRoot.hasRelZLoop(invalidRelativeRoot); while (hasRelZLoop) { - ATRACE_NAME("FixRelZLoop"); + SFTRACE_NAME("FixRelZLoop"); TransactionTraceWriter::getInstance().invoke("relz_loop_detected", /*overwrite=*/false); layerLifecycleManager.fixRelativeZLoop(invalidRelativeRoot); diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index a4ffd51d43..2b1b2c85b3 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -23,8 +23,8 @@ #include #include +#include #include -#include #include #include @@ -402,7 +402,7 @@ bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) { // There are only content changes which do not require any child layer snapshots to be updated. ALOGV("%s", __func__); - ATRACE_NAME("FastPath"); + SFTRACE_NAME("FastPath"); uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays); if (forceUpdate || args.displayChanges) { @@ -436,7 +436,7 @@ bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) { } void LayerSnapshotBuilder::updateSnapshots(const Args& args) { - ATRACE_NAME("UpdateSnapshots"); + SFTRACE_NAME("UpdateSnapshots"); LayerSnapshot rootSnapshot = args.rootSnapshot; if (args.parentCrop) { rootSnapshot.geomLayerBounds = *args.parentCrop; diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index c3c299964a..17d3f4bf38 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -19,7 +19,7 @@ #undef LOG_TAG #define LOG_TAG "SurfaceFlinger" -#include +#include #include #include #include @@ -581,8 +581,8 @@ bool RequestedLayerState::backpressureEnabled() const { bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const { static constexpr uint64_t requiredFlags = layer_state_t::eBufferChanged; if ((s.what & requiredFlags) != requiredFlags) { - ATRACE_FORMAT_INSTANT("%s: false [missing required flags 0x%" PRIx64 "]", __func__, - (s.what | requiredFlags) & ~s.what); + SFTRACE_FORMAT_INSTANT("%s: false [missing required flags 0x%" PRIx64 "]", __func__, + (s.what | requiredFlags) & ~s.what); return false; } @@ -594,8 +594,8 @@ bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const { ? 0 : (layer_state_t::eAutoRefreshChanged | layer_state_t::eFlagsChanged)); if (s.what & deniedFlags) { - ATRACE_FORMAT_INSTANT("%s: false [has denied flags 0x%" PRIx64 "]", __func__, - s.what & deniedFlags); + SFTRACE_FORMAT_INSTANT("%s: false [has denied flags 0x%" PRIx64 "]", __func__, + s.what & deniedFlags); return false; } @@ -616,8 +616,8 @@ bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const { ? layer_state_t::eFlagsChanged : 0); if (changedFlags & deniedChanges) { - ATRACE_FORMAT_INSTANT("%s: false [has denied changes flags 0x%" PRIx64 "]", __func__, - changedFlags & deniedChanges); + SFTRACE_FORMAT_INSTANT("%s: false [has denied changes flags 0x%" PRIx64 "]", __func__, + changedFlags & deniedChanges); return false; } diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp index d3d950974f..a1e8213132 100644 --- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp +++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp @@ -19,9 +19,9 @@ #define LOG_TAG "SurfaceFlinger" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include #include #include -#include #include "FrontEnd/LayerLog.h" #include "TransactionHandler.h" @@ -31,7 +31,7 @@ namespace android::surfaceflinger::frontend { void TransactionHandler::queueTransaction(TransactionState&& state) { mLocklessTransactionQueue.push(std::move(state)); mPendingTransactionCount.fetch_add(1); - ATRACE_INT("TransactionQueue", static_cast(mPendingTransactionCount.load())); + SFTRACE_INT("TransactionQueue", static_cast(mPendingTransactionCount.load())); } void TransactionHandler::collectTransactions() { @@ -71,7 +71,7 @@ std::vector TransactionHandler::flushTransactions() { applyUnsignaledBufferTransaction(transactions, flushState); mPendingTransactionCount.fetch_sub(transactions.size()); - ATRACE_INT("TransactionQueue", static_cast(mPendingTransactionCount.load())); + SFTRACE_INT("TransactionQueue", static_cast(mPendingTransactionCount.load())); return transactions; } @@ -83,7 +83,7 @@ void TransactionHandler::applyUnsignaledBufferTransaction( // only apply an unsignaled buffer transaction if it's the first one if (!transactions.empty()) { - ATRACE_NAME("fence unsignaled"); + SFTRACE_NAME("fence unsignaled"); return; } diff --git a/services/surfaceflinger/HdrLayerInfoReporter.cpp b/services/surfaceflinger/HdrLayerInfoReporter.cpp index 278833244c..85921bb72d 100644 --- a/services/surfaceflinger/HdrLayerInfoReporter.cpp +++ b/services/surfaceflinger/HdrLayerInfoReporter.cpp @@ -19,8 +19,8 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include +#include #include -#include #include "HdrLayerInfoReporter.h" @@ -29,7 +29,7 @@ namespace android { using base::StringAppendF; void HdrLayerInfoReporter::dispatchHdrLayerInfo(const HdrLayerInfo& info) { - ATRACE_CALL(); + SFTRACE_CALL(); if (mHdrInfoHistory.size() == 0 || mHdrInfoHistory.back().info != info) { mHdrInfoHistory.next() = EventHistoryEntry{info}; } @@ -47,7 +47,7 @@ void HdrLayerInfoReporter::dispatchHdrLayerInfo(const HdrLayerInfo& info) { } for (const auto& listener : toInvoke) { - ATRACE_NAME("invoking onHdrLayerInfoChanged"); + SFTRACE_NAME("invoking onHdrLayerInfoChanged"); listener->onHdrLayerInfoChanged(info.numberOfHdrLayers, info.maxW, info.maxH, info.flags, info.maxDesiredHdrSdrRatio); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e758741afb..86c7d165e8 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -58,7 +58,6 @@ #include #include #include -#include #include #include @@ -772,7 +771,7 @@ bool Layer::isSecure() const { // ---------------------------------------------------------------------------- uint32_t Layer::doTransaction(uint32_t flags) { - ATRACE_CALL(); + SFTRACE_CALL(); // TODO: This is unfortunate. mDrawingStateModified = mDrawingState.modified; @@ -2783,7 +2782,7 @@ void Layer::callReleaseBufferCallback(const sp& l if (!listener) { return; } - ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber); + SFTRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber); uint32_t currentMaxAcquiredBufferCount = mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid); listener->onReleaseBuffer({buffer->getId(), framenumber}, @@ -2910,8 +2909,8 @@ void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { handle->dequeueReadyTime = dequeueReadyTime; handle->currentMaxAcquiredBufferCount = mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid); - ATRACE_FORMAT_INSTANT("releasePendingBuffer %s - %" PRIu64, getDebugName(), - handle->previousReleaseCallbackId.framenumber); + SFTRACE_FORMAT_INSTANT("releasePendingBuffer %s - %" PRIu64, getDebugName(), + handle->previousReleaseCallbackId.framenumber); } for (auto& handle : mDrawingState.callbackHandles) { @@ -3090,13 +3089,13 @@ void Layer::resetDrawingStateBufferInfo() { bool Layer::setBuffer(std::shared_ptr& buffer, const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const FrameTimelineInfo& info) { - ATRACE_FORMAT("setBuffer %s - hasBuffer=%s", getDebugName(), (buffer ? "true" : "false")); + SFTRACE_FORMAT("setBuffer %s - hasBuffer=%s", getDebugName(), (buffer ? "true" : "false")); const bool frameNumberChanged = bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged); const uint64_t frameNumber = frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1; - ATRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber); + SFTRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber); if (mDrawingState.buffer) { releasePreviousBuffer(); @@ -3191,10 +3190,10 @@ void Layer::setDesiredPresentTime(nsecs_t desiredPresentTime, bool isAutoTimesta } void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerProps, nsecs_t now) { - ATRACE_CALL(); + SFTRACE_CALL(); const nsecs_t presentTime = [&] { if (!mDrawingState.isAutoTimestamp) { - ATRACE_FORMAT_INSTANT("desiredPresentTime"); + SFTRACE_FORMAT_INSTANT("desiredPresentTime"); return mDrawingState.desiredPresentTime; } @@ -3203,7 +3202,7 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro mFlinger->mFrameTimeline->getTokenManager()->getPredictionsForToken( mDrawingState.latchedVsyncId); if (prediction.has_value()) { - ATRACE_FORMAT_INSTANT("predictedPresentTime"); + SFTRACE_FORMAT_INSTANT("predictedPresentTime"); mMaxTimeForUseVsyncId = prediction->presentTime + scheduler::LayerHistory::kMaxPeriodForHistory.count(); return prediction->presentTime; @@ -3241,7 +3240,7 @@ void Layer::recordLayerHistoryBufferUpdate(const scheduler::LayerProps& layerPro if (ATRACE_ENABLED() && presentTime > 0) { const auto presentIn = TimePoint::fromNs(presentTime) - TimePoint::now(); - ATRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str()); + SFTRACE_FORMAT_INSTANT("presentIn %s", to_string(presentIn).c_str()); } mFlinger->mScheduler->recordLayerHistory(sequence, layerProps, presentTime, now, @@ -3565,12 +3564,12 @@ void Layer::gatherBufferInfo() { ui::Dataspace dataspace = ui::Dataspace::UNKNOWN; status_t err = OK; { - ATRACE_NAME("getDataspace"); + SFTRACE_NAME("getDataspace"); err = mapper.getDataspace(mBufferInfo.mBuffer->getBuffer()->handle, &dataspace); } if (err != OK || dataspace != mBufferInfo.mDataspace) { { - ATRACE_NAME("setDataspace"); + SFTRACE_NAME("setDataspace"); err = mapper.setDataspace(mBufferInfo.mBuffer->getBuffer()->handle, static_cast(mBufferInfo.mDataspace)); } @@ -3634,7 +3633,7 @@ void Layer::decrementPendingBufferCount() { } void Layer::tracePendingBufferCount(int32_t pendingBuffers) { - ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); + SFTRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); } /* @@ -3712,41 +3711,41 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const { : layer_state_t::eAutoRefreshChanged); if ((s.what & requiredFlags) != requiredFlags) { - ATRACE_FORMAT_INSTANT("%s: false [missing required flags 0x%" PRIx64 "]", __func__, - (s.what | requiredFlags) & ~s.what); + SFTRACE_FORMAT_INSTANT("%s: false [missing required flags 0x%" PRIx64 "]", __func__, + (s.what | requiredFlags) & ~s.what); return false; } if (s.what & deniedFlags) { - ATRACE_FORMAT_INSTANT("%s: false [has denied flags 0x%" PRIx64 "]", __func__, - s.what & deniedFlags); + SFTRACE_FORMAT_INSTANT("%s: false [has denied flags 0x%" PRIx64 "]", __func__, + s.what & deniedFlags); return false; } if (s.what & layer_state_t::ePositionChanged) { if (mRequestedTransform.tx() != s.x || mRequestedTransform.ty() != s.y) { - ATRACE_FORMAT_INSTANT("%s: false [ePositionChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [ePositionChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eAlphaChanged) { if (mDrawingState.color.a != s.color.a) { - ATRACE_FORMAT_INSTANT("%s: false [eAlphaChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eAlphaChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eColorTransformChanged) { if (mDrawingState.colorTransform != s.colorTransform) { - ATRACE_FORMAT_INSTANT("%s: false [eColorTransformChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eColorTransformChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eBackgroundColorChanged) { if (mDrawingState.bgColorLayer || s.bgColor.a != 0) { - ATRACE_FORMAT_INSTANT("%s: false [eBackgroundColorChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eBackgroundColorChanged changed]", __func__); return false; } } @@ -3756,92 +3755,92 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const { mRequestedTransform.dtdy() != s.matrix.dtdy || mRequestedTransform.dtdx() != s.matrix.dtdx || mRequestedTransform.dsdy() != s.matrix.dsdy) { - ATRACE_FORMAT_INSTANT("%s: false [eMatrixChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eMatrixChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eCornerRadiusChanged) { if (mDrawingState.cornerRadius != s.cornerRadius) { - ATRACE_FORMAT_INSTANT("%s: false [eCornerRadiusChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eCornerRadiusChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eBackgroundBlurRadiusChanged) { if (mDrawingState.backgroundBlurRadius != static_cast(s.backgroundBlurRadius)) { - ATRACE_FORMAT_INSTANT("%s: false [eBackgroundBlurRadiusChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eBackgroundBlurRadiusChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eBufferTransformChanged) { if (mDrawingState.bufferTransform != s.bufferTransform) { - ATRACE_FORMAT_INSTANT("%s: false [eBufferTransformChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eBufferTransformChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eTransformToDisplayInverseChanged) { if (mDrawingState.transformToDisplayInverse != s.transformToDisplayInverse) { - ATRACE_FORMAT_INSTANT("%s: false [eTransformToDisplayInverseChanged changed]", - __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eTransformToDisplayInverseChanged changed]", + __func__); return false; } } if (s.what & layer_state_t::eCropChanged) { if (mDrawingState.crop != s.crop) { - ATRACE_FORMAT_INSTANT("%s: false [eCropChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eCropChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eDataspaceChanged) { if (mDrawingState.dataspace != s.dataspace) { - ATRACE_FORMAT_INSTANT("%s: false [eDataspaceChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eDataspaceChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eHdrMetadataChanged) { if (mDrawingState.hdrMetadata != s.hdrMetadata) { - ATRACE_FORMAT_INSTANT("%s: false [eHdrMetadataChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eHdrMetadataChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eSidebandStreamChanged) { if (mDrawingState.sidebandStream != s.sidebandStream) { - ATRACE_FORMAT_INSTANT("%s: false [eSidebandStreamChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eSidebandStreamChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eColorSpaceAgnosticChanged) { if (mDrawingState.colorSpaceAgnostic != s.colorSpaceAgnostic) { - ATRACE_FORMAT_INSTANT("%s: false [eColorSpaceAgnosticChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eColorSpaceAgnosticChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eShadowRadiusChanged) { if (mDrawingState.shadowRadius != s.shadowRadius) { - ATRACE_FORMAT_INSTANT("%s: false [eShadowRadiusChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eShadowRadiusChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eFixedTransformHintChanged) { if (mDrawingState.fixedTransformHint != s.fixedTransformHint) { - ATRACE_FORMAT_INSTANT("%s: false [eFixedTransformHintChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eFixedTransformHintChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eTrustedOverlayChanged) { if (mDrawingState.isTrustedOverlay != (s.trustedOverlay == gui::TrustedOverlay::ENABLED)) { - ATRACE_FORMAT_INSTANT("%s: false [eTrustedOverlayChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eTrustedOverlayChanged changed]", __func__); return false; } } @@ -3850,28 +3849,28 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const { StretchEffect temp = s.stretchEffect; temp.sanitize(); if (mDrawingState.stretchEffect != temp) { - ATRACE_FORMAT_INSTANT("%s: false [eStretchChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eStretchChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eBufferCropChanged) { if (mDrawingState.bufferCrop != s.bufferCrop) { - ATRACE_FORMAT_INSTANT("%s: false [eBufferCropChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eBufferCropChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eDestinationFrameChanged) { if (mDrawingState.destinationFrame != s.destinationFrame) { - ATRACE_FORMAT_INSTANT("%s: false [eDestinationFrameChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eDestinationFrameChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eDimmingEnabledChanged) { if (mDrawingState.dimmingEnabled != s.dimmingEnabled) { - ATRACE_FORMAT_INSTANT("%s: false [eDimmingEnabledChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eDimmingEnabledChanged changed]", __func__); return false; } } @@ -3879,14 +3878,14 @@ bool Layer::isSimpleBufferUpdate(const layer_state_t& s) const { if (s.what & layer_state_t::eExtendedRangeBrightnessChanged) { if (mDrawingState.currentHdrSdrRatio != s.currentHdrSdrRatio || mDrawingState.desiredHdrSdrRatio != s.desiredHdrSdrRatio) { - ATRACE_FORMAT_INSTANT("%s: false [eExtendedRangeBrightnessChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eExtendedRangeBrightnessChanged changed]", __func__); return false; } } if (s.what & layer_state_t::eDesiredHdrHeadroomChanged) { if (mDrawingState.desiredHdrSdrRatio != s.desiredHdrSdrRatio) { - ATRACE_FORMAT_INSTANT("%s: false [eDesiredHdrHeadroomChanged changed]", __func__); + SFTRACE_FORMAT_INSTANT("%s: false [eDesiredHdrHeadroomChanged changed]", __func__); return false; } } @@ -4078,8 +4077,8 @@ bool Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { } bool Layer::latchBufferImpl(bool& recomputeVisibleRegions, nsecs_t latchTime, bool bgColorOnly) { - ATRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(), - getDrawingState().frameNumber); + SFTRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(), + getDrawingState().frameNumber); bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); @@ -4090,7 +4089,7 @@ bool Layer::latchBufferImpl(bool& recomputeVisibleRegions, nsecs_t latchTime, bo // If the head buffer's acquire fence hasn't signaled yet, return and // try again later if (!fenceHasSignaled()) { - ATRACE_NAME("!fenceHasSignaled()"); + SFTRACE_NAME("!fenceHasSignaled()"); mFlinger->onLayerUpdate(); return false; } diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index c2251a858b..8f819b25e0 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -19,11 +19,10 @@ #define LOG_TAG "SurfaceFlinger" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include #include -#include #include #include -#include #include "LayerFE.h" #include "SurfaceFlinger.h" @@ -122,7 +121,7 @@ std::optional LayerFE::prepareClientC std::optional LayerFE::prepareClientCompositionInternal( compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const { - ATRACE_CALL(); + SFTRACE_CALL(); compositionengine::LayerFE::LayerSettings layerSettings; layerSettings.geometry.boundaries = reduce(mSnapshot->geomLayerBounds, mSnapshot->transparentRegionHint); @@ -214,7 +213,7 @@ void LayerFE::prepareEffectsClientComposition( void LayerFE::prepareBufferStateClientComposition( compositionengine::LayerFE::LayerSettings& layerSettings, compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const { - ATRACE_CALL(); + SFTRACE_CALL(); if (CC_UNLIKELY(!mSnapshot->externalTexture)) { // If there is no buffer for the layer or we have sidebandstream where there is no // activeBuffer, then we need to return LayerSettings. diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 1eb865d600..06a4d00e48 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -26,6 +26,7 @@ #include "RegionSamplingThread.h" +#include #include #include #include @@ -34,7 +35,6 @@ #include #include #include -#include #include @@ -148,7 +148,7 @@ void RegionSamplingThread::checkForStaleLuma() { std::lock_guard lock(mThreadControlMutex); if (mSampleRequestTime.has_value()) { - ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::waitForSamplePhase)); + SFTRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::waitForSamplePhase)); mSampleRequestTime.reset(); mFlinger.scheduleSample(); } @@ -166,7 +166,7 @@ void RegionSamplingThread::doSample( if (mLastSampleTime + mTunables.mSamplingPeriod > now) { // content changed, but we sampled not too long ago, so we need to sample some time in the // future. - ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::idleTimerWaiting)); + SFTRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::idleTimerWaiting)); mSampleRequestTime = now; return; } @@ -175,13 +175,13 @@ void RegionSamplingThread::doSample( // until the next vsync deadline, defer this sampling work // to a later frame, when hopefully there will be more time. if (samplingDeadline.has_value() && now + mTunables.mSamplingDuration > *samplingDeadline) { - ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::waitForQuietFrame)); + SFTRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::waitForQuietFrame)); mSampleRequestTime = mSampleRequestTime.value_or(now); return; } } - ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::sample)); + SFTRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::sample)); mSampleRequestTime.reset(); mLastSampleTime = now; @@ -247,7 +247,7 @@ std::vector RegionSamplingThread::sampleBuffer( } void RegionSamplingThread::captureSample() { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mSamplingMutex); if (mDescriptors.empty()) { @@ -393,7 +393,7 @@ void RegionSamplingThread::captureSample() { } mCachedBuffer = buffer; - ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); + SFTRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); } // NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations. diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 6b654499a2..d31fceab7e 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -33,7 +33,7 @@ #include #include - +#include #include #include @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -226,14 +225,14 @@ binder::Status EventThreadConnection::setVsyncRate(int rate) { } binder::Status EventThreadConnection::requestNextVsync() { - ATRACE_CALL(); + SFTRACE_CALL(); mEventThread->requestNextVsync(sp::fromExisting(this)); return binder::Status::ok(); } binder::Status EventThreadConnection::getLatestVsyncEventData( ParcelableVsyncEventData* outVsyncEventData) { - ATRACE_CALL(); + SFTRACE_CALL(); outVsyncEventData->vsync = mEventThread->getLatestVsyncEventData(sp::fromExisting(this), systemTime()); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index a819b7979f..4fd4c0ecc3 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -21,8 +21,8 @@ #include "LayerHistory.h" #include +#include #include -#include #include #include @@ -72,7 +72,7 @@ bool useFrameRatePriority() { void trace(const LayerInfo& info, LayerHistory::LayerVoteType type, int fps) { const auto traceType = [&](LayerHistory::LayerVoteType checkedType, int value) { - ATRACE_INT(info.getTraceTag(checkedType), type == checkedType ? value : 0); + SFTRACE_INT(info.getTraceTag(checkedType), type == checkedType ? value : 0); }; traceType(LayerHistory::LayerVoteType::NoVote, 1); @@ -190,7 +190,7 @@ void LayerHistory::setLayerProperties(int32_t id, const LayerProps& properties) } auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) -> Summary { - ATRACE_CALL(); + SFTRACE_CALL(); Summary summary; std::lock_guard lock(mLock); @@ -204,7 +204,7 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority, layerFocused ? "" : "not"); - ATRACE_FORMAT("%s", info->getName().c_str()); + SFTRACE_FORMAT("%s", info->getName().c_str()); const auto votes = info->getRefreshRateVote(selector, now); for (LayerInfo::LayerVote vote : votes) { if (vote.isNoVote()) { @@ -222,8 +222,8 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - const std::string categoryString = vote.category == FrameRateCategory::Default ? "" : base::StringPrintf("category=%s", ftl::enum_string(vote.category).c_str()); - ATRACE_FORMAT_INSTANT("%s %s %s (%.2f)", ftl::enum_string(vote.type).c_str(), - to_string(vote.fps).c_str(), categoryString.c_str(), weight); + SFTRACE_FORMAT_INSTANT("%s %s %s (%.2f)", ftl::enum_string(vote.type).c_str(), + to_string(vote.fps).c_str(), categoryString.c_str(), weight); summary.push_back({info->getName(), info->getOwnerUid(), vote.type, vote.fps, vote.seamlessness, vote.category, vote.categorySmoothSwitchOnly, weight, layerFocused}); @@ -238,7 +238,7 @@ auto LayerHistory::summarize(const RefreshRateSelector& selector, nsecs_t now) - } void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) { - ATRACE_CALL(); + SFTRACE_CALL(); const nsecs_t threshold = getActiveLayerThreshold(now); // iterate over inactive map @@ -310,7 +310,7 @@ void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) { if (gameModeFrameRateOverride.isValid()) { info->setLayerVote({gameFrameRateOverrideVoteType, gameModeFrameRateOverride}); - ATRACE_FORMAT_INSTANT("GameModeFrameRateOverride"); + SFTRACE_FORMAT_INSTANT("GameModeFrameRateOverride"); if (CC_UNLIKELY(mTraceEnabled)) { trace(*info, gameFrameRateOverrideVoteType, gameModeFrameRateOverride.getIntValue()); @@ -326,19 +326,19 @@ void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) { } else if (gameDefaultFrameRateOverride.isValid()) { info->setLayerVote( {gameFrameRateOverrideVoteType, gameDefaultFrameRateOverride}); - ATRACE_FORMAT_INSTANT("GameDefaultFrameRateOverride"); + SFTRACE_FORMAT_INSTANT("GameDefaultFrameRateOverride"); if (CC_UNLIKELY(mTraceEnabled)) { trace(*info, gameFrameRateOverrideVoteType, gameDefaultFrameRateOverride.getIntValue()); } } else { if (frameRate.isValid() && !frameRate.isVoteValidForMrr(isVrrDevice)) { - ATRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s " - "%s %s", - info->getName().c_str(), - ftl::enum_string(frameRate.vote.type).c_str(), - to_string(frameRate.vote.rate).c_str(), - ftl::enum_string(frameRate.category).c_str()); + SFTRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s " + "%s %s", + info->getName().c_str(), + ftl::enum_string(frameRate.vote.type).c_str(), + to_string(frameRate.vote.rate).c_str(), + ftl::enum_string(frameRate.category).c_str()); } info->resetLayerVote(); } @@ -349,12 +349,12 @@ void LayerHistory::partitionLayers(nsecs_t now, bool isVrrDevice) { frameRate.vote.seamlessness, frameRate.category}); } else { if (!frameRate.isVoteValidForMrr(isVrrDevice)) { - ATRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s " - "%s %s", - info->getName().c_str(), - ftl::enum_string(frameRate.vote.type).c_str(), - to_string(frameRate.vote.rate).c_str(), - ftl::enum_string(frameRate.category).c_str()); + SFTRACE_FORMAT_INSTANT("Reset layer to ignore explicit vote on MRR %s: %s " + "%s %s", + info->getName().c_str(), + ftl::enum_string(frameRate.vote.type).c_str(), + to_string(frameRate.vote.rate).c_str(), + ftl::enum_string(frameRate.category).c_str()); } info->resetLayerVote(); } @@ -421,7 +421,7 @@ auto LayerHistory::findLayer(int32_t id) -> std::pair { bool LayerHistory::isSmallDirtyArea(uint32_t dirtyArea, float threshold) const { const float ratio = (float)dirtyArea / mDisplayArea; const bool isSmallDirty = ratio <= threshold; - ATRACE_FORMAT_INSTANT("small dirty=%s, ratio=%.3f", isSmallDirty ? "true" : "false", ratio); + SFTRACE_FORMAT_INSTANT("small dirty=%s, ratio=%.3f", isSmallDirty ? "true" : "false", ratio); return isSmallDirty; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 632f42ab36..a1a60e3e30 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -27,10 +27,10 @@ #include #include +#include #include #include #include -#include #include #undef LOG_TAG @@ -259,7 +259,7 @@ std::optional LayerInfo::calculateAverageFrameTime() const { } if (smallDirtyCount > 0) { - ATRACE_FORMAT_INSTANT("small dirty = %" PRIu32, smallDirtyCount); + SFTRACE_FORMAT_INSTANT("small dirty = %" PRIu32, smallDirtyCount); } if (numDeltas == 0) { @@ -272,7 +272,7 @@ std::optional LayerInfo::calculateAverageFrameTime() const { std::optional LayerInfo::calculateRefreshRateIfPossible(const RefreshRateSelector& selector, nsecs_t now) { - ATRACE_CALL(); + SFTRACE_CALL(); static constexpr float MARGIN = 1.0f; // 1Hz if (!hasEnoughDataForHeuristic()) { ALOGV("Not enough data"); @@ -307,7 +307,7 @@ std::optional LayerInfo::calculateRefreshRateIfPossible(const RefreshRateSe LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelector& selector, nsecs_t now) { - ATRACE_CALL(); + SFTRACE_CALL(); LayerInfo::RefreshRateVotes votes; if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { @@ -315,8 +315,8 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec const auto voteType = mLayerVote.type == LayerHistory::LayerVoteType::NoVote ? LayerHistory::LayerVoteType::NoVote : LayerHistory::LayerVoteType::ExplicitCategory; - ATRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(), - ftl::enum_string(mLayerVote.category).c_str()); + SFTRACE_FORMAT_INSTANT("Vote %s (category=%s)", ftl::enum_string(voteType).c_str(), + ftl::enum_string(mLayerVote.category).c_str()); ALOGV("%s voted %s with category: %s", mName.c_str(), ftl::enum_string(voteType).c_str(), ftl::enum_string(mLayerVote.category).c_str()); @@ -326,7 +326,7 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec if (mLayerVote.fps.isValid() || mLayerVote.type != LayerHistory::LayerVoteType::ExplicitDefault) { - ATRACE_FORMAT_INSTANT("Vote %s", ftl::enum_string(mLayerVote.type).c_str()); + SFTRACE_FORMAT_INSTANT("Vote %s", ftl::enum_string(mLayerVote.type).c_str()); ALOGV("%s voted %d", mName.c_str(), static_cast(mLayerVote.type)); votes.push_back({mLayerVote.type, mLayerVote.fps, mLayerVote.seamlessness, FrameRateCategory::Default, mLayerVote.categorySmoothSwitchOnly}); @@ -336,7 +336,7 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec } if (isAnimating(now)) { - ATRACE_FORMAT_INSTANT("animating"); + SFTRACE_FORMAT_INSTANT("animating"); ALOGV("%s is animating", mName.c_str()); mLastRefreshRate.animating = true; votes.push_back({LayerHistory::LayerVoteType::Max, Fps()}); @@ -345,7 +345,7 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec // Vote for max refresh rate whenever we're front-buffered. if (FlagManager::getInstance().vrr_config() && isFrontBuffered()) { - ATRACE_FORMAT_INSTANT("front buffered"); + SFTRACE_FORMAT_INSTANT("front buffered"); ALOGV("%s is front-buffered", mName.c_str()); votes.push_back({LayerHistory::LayerVoteType::Max, Fps()}); return votes; @@ -354,7 +354,7 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec const LayerInfo::Frequent frequent = isFrequent(now); mIsFrequencyConclusive = frequent.isConclusive; if (!frequent.isFrequent) { - ATRACE_FORMAT_INSTANT("infrequent"); + SFTRACE_FORMAT_INSTANT("infrequent"); ALOGV("%s is infrequent", mName.c_str()); mLastRefreshRate.infrequent = true; mLastSmallDirtyCount = 0; @@ -365,14 +365,14 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec } if (frequent.clearHistory) { - ATRACE_FORMAT_INSTANT("frequent.clearHistory"); + SFTRACE_FORMAT_INSTANT("frequent.clearHistory"); ALOGV("%s frequent.clearHistory", mName.c_str()); clearHistory(now); } // Return no vote if the recent frames are small dirty. if (frequent.isSmallDirty && !mLastRefreshRate.reported.isValid()) { - ATRACE_FORMAT_INSTANT("NoVote (small dirty)"); + SFTRACE_FORMAT_INSTANT("NoVote (small dirty)"); ALOGV("%s is small dirty", mName.c_str()); votes.push_back({LayerHistory::LayerVoteType::NoVote, Fps()}); return votes; @@ -380,13 +380,13 @@ LayerInfo::RefreshRateVotes LayerInfo::getRefreshRateVote(const RefreshRateSelec auto refreshRate = calculateRefreshRateIfPossible(selector, now); if (refreshRate.has_value()) { - ATRACE_FORMAT_INSTANT("calculated (%s)", to_string(*refreshRate).c_str()); + SFTRACE_FORMAT_INSTANT("calculated (%s)", to_string(*refreshRate).c_str()); ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str()); votes.push_back({LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}); return votes; } - ATRACE_FORMAT_INSTANT("Max (can't resolve refresh rate)"); + SFTRACE_FORMAT_INSTANT("Max (can't resolve refresh rate)"); ALOGV("%s Max (can't resolve refresh rate)", mName.c_str()); votes.push_back({LayerHistory::LayerVoteType::Max, Fps()}); return votes; @@ -452,7 +452,7 @@ Fps LayerInfo::RefreshRateHistory::add(Fps refreshRate, nsecs_t now, mHeuristicTraceTagData = makeHeuristicTraceTagData(); } - ATRACE_INT(mHeuristicTraceTagData->average.c_str(), refreshRate.getIntValue()); + SFTRACE_INT(mHeuristicTraceTagData->average.c_str(), refreshRate.getIntValue()); } return selectRefreshRate(selector); @@ -486,9 +486,9 @@ Fps LayerInfo::RefreshRateHistory::selectRefreshRate(const RefreshRateSelector& mHeuristicTraceTagData = makeHeuristicTraceTagData(); } - ATRACE_INT(mHeuristicTraceTagData->max.c_str(), max->refreshRate.getIntValue()); - ATRACE_INT(mHeuristicTraceTagData->min.c_str(), min->refreshRate.getIntValue()); - ATRACE_INT(mHeuristicTraceTagData->consistent.c_str(), consistent); + SFTRACE_INT(mHeuristicTraceTagData->max.c_str(), max->refreshRate.getIntValue()); + SFTRACE_INT(mHeuristicTraceTagData->min.c_str(), min->refreshRate.getIntValue()); + SFTRACE_INT(mHeuristicTraceTagData->consistent.c_str(), consistent); } return consistent ? maxClosestRate : Fps(); diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index ff88d71259..6a67ac5d42 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -57,7 +57,7 @@ MessageQueue::MessageQueue(ICompositor& compositor, sp handler) mHandler(std::move(handler)) {} void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) { - ATRACE_CALL(); + SFTRACE_CALL(); // Trace VSYNC-sf mVsync.value = (mVsync.value + 1) % 2; @@ -136,7 +136,7 @@ void MessageQueue::destroyVsync() { } void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mVsync.mutex); mVsync.workDuration = workDuration; mVsync.scheduledFrameTimeOpt = @@ -189,7 +189,7 @@ void MessageQueue::scheduleConfigure() { } void MessageQueue::scheduleFrame() { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mVsync.mutex); mVsync.scheduledFrameTimeOpt = diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp index be5ffbcb71..0b17c8495c 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp @@ -28,13 +28,12 @@ #include #include +#include #include #include #include #include -#include #include -#include #include "RefreshRateSelector.h" @@ -494,7 +493,7 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector RankedFrameRates { using namespace fps_approx_ops; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("%s: %zu layers", __func__, layers.size()); const auto& activeMode = *getActiveModeLocked().modePtr; @@ -508,8 +507,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vectorprimaryRangeIsSingleRate() && hasExplicitVoteLayers)) { ALOGV("Idle"); const auto ranking = rankFrameRates(activeMode.getGroup(), RefreshRateOrder::Ascending); - ATRACE_FORMAT_INSTANT("%s (Idle)", to_string(ranking.front().frameRateMode.fps).c_str()); + SFTRACE_FORMAT_INSTANT("%s (Idle)", to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, GlobalSignals{.idle = true}}; } if (layers.empty() || noVoteLayers == layers.size()) { ALOGV("No layers with votes"); const auto ranking = rankFrameRates(anchorGroup, RefreshRateOrder::Descending); - ATRACE_FORMAT_INSTANT("%s (No layers with votes)", - to_string(ranking.front().frameRateMode.fps).c_str()); + SFTRACE_FORMAT_INSTANT("%s (No layers with votes)", + to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals}; } @@ -637,8 +636,8 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vectorgetId() == activeModeId; }); - ATRACE_FORMAT_INSTANT("%s (All layers Min)", - to_string(ranking.front().frameRateMode.fps).c_str()); + SFTRACE_FORMAT_INSTANT("%s (All layers Min)", + to_string(ranking.front().frameRateMode.fps).c_str()); return {ranking, kNoSignals}; } @@ -847,13 +846,13 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector UidToFrameRateOverride { - ATRACE_CALL(); + SFTRACE_CALL(); if (mConfig.enableFrameRateOverride == Config::FrameRateOverride::Disabled) { return {}; } @@ -1064,12 +1063,12 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector #include #include +#include #include #include #include #include #include -#include #include #include #include @@ -250,8 +250,8 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId, const auto period = pacesetterPtr->targeterPtr->target().expectedFrameDuration(); const auto skipDuration = Duration::fromNs( static_cast(period.ns() * mPacesetterFrameDurationFractionToSkip)); - ATRACE_FORMAT("Injecting jank for %f%% of the frame (%" PRId64 " ns)", - mPacesetterFrameDurationFractionToSkip * 100, skipDuration.ns()); + SFTRACE_FORMAT("Injecting jank for %f%% of the frame (%" PRId64 " ns)", + mPacesetterFrameDurationFractionToSkip * 100, skipDuration.ns()); std::this_thread::sleep_for(skipDuration); mPacesetterFrameDurationFractionToSkip = 0.f; } @@ -282,7 +282,7 @@ bool Scheduler::isVsyncValid(TimePoint expectedVsyncTime, uid_t uid) const { return true; } - ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str()); + SFTRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str()); return getVsyncSchedule()->getTracker().isVSyncInPhase(expectedVsyncTime.ns(), *frameRate); } @@ -510,7 +510,7 @@ void Scheduler::disableHardwareVsync(PhysicalDisplayId id, bool disallow) { } void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) { - ATRACE_CALL(); + SFTRACE_CALL(); std::scoped_lock lock(mDisplayLock); ftl::FakeGuard guard(kMainThreadContext); @@ -544,12 +544,12 @@ void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEn void Scheduler::onHardwareVsyncRequest(PhysicalDisplayId id, bool enabled) { static const auto& whence = __func__; - ATRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str()); + SFTRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str()); // On main thread to serialize reads/writes of pending hardware VSYNC state. static_cast( schedule([=, this]() FTL_FAKE_GUARD(mDisplayLock) FTL_FAKE_GUARD(kMainThreadContext) { - ATRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str()); + SFTRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str()); if (const auto displayOpt = mDisplays.get(id)) { auto& display = displayOpt->get(); @@ -631,7 +631,7 @@ bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp, } void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr fence) { - ATRACE_NAME(ftl::Concat(__func__, ' ', id.value).c_str()); + SFTRACE_NAME(ftl::Concat(__func__, ' ', id.value).c_str()); const auto scheduleOpt = (ftl::FakeGuard(mDisplayLock), mDisplays.get(id)).and_then([](const Display& display) { return display.powerMode == hal::PowerMode::OFF @@ -694,7 +694,7 @@ void Scheduler::chooseRefreshRateForContent( const auto selectorPtr = pacesetterSelectorPtr(); if (!selectorPtr->canSwitch()) return; - ATRACE_CALL(); + SFTRACE_CALL(); LayerHistory::Summary summary = mLayerHistory.summarize(*selectorPtr, systemTime()); applyPolicy(&Policy::contentRequirements, std::move(summary)); @@ -779,7 +779,7 @@ auto Scheduler::getVsyncScheduleLocked(std::optional idOpt) c } void Scheduler::kernelIdleTimerCallback(TimerState state) { - ATRACE_INT("ExpiredKernelIdleTimer", static_cast(state)); + SFTRACE_INT("ExpiredKernelIdleTimer", static_cast(state)); // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number @@ -810,7 +810,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { void Scheduler::idleTimerCallback(TimerState state) { applyPolicy(&Policy::idleTimer, state); - ATRACE_INT("ExpiredIdleTimer", static_cast(state)); + SFTRACE_INT("ExpiredIdleTimer", static_cast(state)); } void Scheduler::touchTimerCallback(TimerState state) { @@ -822,12 +822,12 @@ void Scheduler::touchTimerCallback(TimerState state) { if (applyPolicy(&Policy::touch, touch).touch) { mLayerHistory.clear(); } - ATRACE_INT("TouchState", static_cast(touch)); + SFTRACE_INT("TouchState", static_cast(touch)); } void Scheduler::displayPowerTimerCallback(TimerState state) { applyPolicy(&Policy::displayPowerTimer, state); - ATRACE_INT("ExpiredDisplayPowerTimer", static_cast(state)); + SFTRACE_INT("ExpiredDisplayPowerTimer", static_cast(state)); } void Scheduler::dump(utils::Dumper& dumper) const { @@ -990,7 +990,7 @@ void Scheduler::updateAttachedChoreographersFrameRate( auto& layerChoreographers = choreographers->second; layerChoreographers.frameRate = fps; - ATRACE_FORMAT_INSTANT("%s: %s for %s", __func__, to_string(fps).c_str(), layer.name.c_str()); + SFTRACE_FORMAT_INSTANT("%s: %s for %s", __func__, to_string(fps).c_str(), layer.name.c_str()); ALOGV("%s: %s for %s", __func__, to_string(fps).c_str(), layer.name.c_str()); auto it = layerChoreographers.connections.begin(); @@ -1072,13 +1072,13 @@ int Scheduler::updateAttachedChoreographersInternal( void Scheduler::updateAttachedChoreographers( const surfaceflinger::frontend::LayerHierarchy& layerHierarchy, Fps displayRefreshRate) { - ATRACE_CALL(); + SFTRACE_CALL(); updateAttachedChoreographersInternal(layerHierarchy, displayRefreshRate, 0); } template auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals { - ATRACE_CALL(); + SFTRACE_CALL(); std::vector modeRequests; GlobalSignals consideredSignals; @@ -1149,7 +1149,7 @@ auto Scheduler::applyPolicy(S Policy::*statePtr, T&& newState) -> GlobalSignals } auto Scheduler::chooseDisplayModes() const -> DisplayModeChoiceMap { - ATRACE_CALL(); + SFTRACE_CALL(); DisplayModeChoiceMap modeChoices; const auto globalSignals = makeGlobalSignals(); diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp index 6d6b70d198..8dae3ca0a3 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp @@ -19,8 +19,8 @@ #include #include +#include #include -#include #include #include @@ -52,7 +52,7 @@ void traceEntry(const VSyncDispatchTimerQueueEntry& entry, nsecs_t now) { ftl::Concat trace(ftl::truncated<5>(entry.name()), " alarm in ", ns2us(*entry.wakeupTime() - now), "us; VSYNC in ", ns2us(*entry.targetVsync() - now), "us"); - ATRACE_FORMAT_INSTANT(trace.c_str()); + SFTRACE_FORMAT_INSTANT(trace.c_str()); } } // namespace @@ -98,7 +98,7 @@ std::optional VSyncDispatchTimerQueueEntry::targetVsync() const { ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTiming timing, VSyncTracker& tracker, nsecs_t now) { - ATRACE_NAME("VSyncDispatchTimerQueueEntry::schedule"); + SFTRACE_NAME("VSyncDispatchTimerQueueEntry::schedule"); auto nextVsyncTime = tracker.nextAnticipatedVSyncTimeFrom(std::max(timing.lastVsync, now + timing.workDuration + @@ -110,8 +110,8 @@ ScheduleResult VSyncDispatchTimerQueueEntry::schedule(VSyncDispatch::ScheduleTim mArmedInfo && (nextVsyncTime > (mArmedInfo->mActualVsyncTime + mMinVsyncDistance)); bool const wouldSkipAWakeup = mArmedInfo && ((nextWakeupTime > (mArmedInfo->mActualWakeupTime + mMinVsyncDistance))); - ATRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(), - wouldSkipAVsyncTarget, wouldSkipAWakeup); + SFTRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(), + wouldSkipAVsyncTarget, wouldSkipAWakeup); if (FlagManager::getInstance().dont_skip_on_early_ro()) { if (wouldSkipAVsyncTarget || wouldSkipAWakeup) { nextVsyncTime = mArmedInfo->mActualVsyncTime; @@ -154,13 +154,13 @@ nsecs_t VSyncDispatchTimerQueueEntry::adjustVsyncIfNeeded(VSyncTracker& tracker, bool const nextVsyncTooClose = mLastDispatchTime && (nextVsyncTime - *mLastDispatchTime + mMinVsyncDistance) <= currentPeriod; if (alreadyDispatchedForVsync) { - ATRACE_FORMAT_INSTANT("alreadyDispatchedForVsync"); + SFTRACE_FORMAT_INSTANT("alreadyDispatchedForVsync"); return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + mMinVsyncDistance, *mLastDispatchTime); } if (nextVsyncTooClose) { - ATRACE_FORMAT_INSTANT("nextVsyncTooClose"); + SFTRACE_FORMAT_INSTANT("nextVsyncTooClose"); return tracker.nextAnticipatedVSyncTimeFrom(*mLastDispatchTime + currentPeriod, *mLastDispatchTime + currentPeriod); } @@ -172,7 +172,7 @@ auto VSyncDispatchTimerQueueEntry::getArmedInfo(VSyncTracker& tracker, nsecs_t n VSyncDispatch::ScheduleTiming timing, std::optional armedInfo) const -> ArmingInfo { - ATRACE_NAME("VSyncDispatchTimerQueueEntry::getArmedInfo"); + SFTRACE_NAME("VSyncDispatchTimerQueueEntry::getArmedInfo"); const auto earliestReadyBy = now + timing.workDuration + timing.readyDuration; const auto earliestVsync = std::max(earliestReadyBy, timing.lastVsync); @@ -188,8 +188,8 @@ auto VSyncDispatchTimerQueueEntry::getArmedInfo(VSyncTracker& tracker, nsecs_t n armedInfo && (nextVsyncTime > (armedInfo->mActualVsyncTime + mMinVsyncDistance)); bool const wouldSkipAWakeup = armedInfo && (nextWakeupTime > (armedInfo->mActualWakeupTime + mMinVsyncDistance)); - ATRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(), - wouldSkipAVsyncTarget, wouldSkipAWakeup); + SFTRACE_FORMAT_INSTANT("%s: wouldSkipAVsyncTarget=%d wouldSkipAWakeup=%d", mName.c_str(), + wouldSkipAVsyncTarget, wouldSkipAWakeup); if (wouldSkipAVsyncTarget || wouldSkipAWakeup) { return *armedInfo; } @@ -199,7 +199,7 @@ auto VSyncDispatchTimerQueueEntry::getArmedInfo(VSyncTracker& tracker, nsecs_t n } void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) { - ATRACE_NAME("VSyncDispatchTimerQueueEntry::update"); + SFTRACE_NAME("VSyncDispatchTimerQueueEntry::update"); if (!mArmedInfo && !mWorkloadUpdateInfo) { return; } @@ -208,9 +208,9 @@ void VSyncDispatchTimerQueueEntry::update(VSyncTracker& tracker, nsecs_t now) { const auto workDelta = mWorkloadUpdateInfo->workDuration - mScheduleTiming.workDuration; const auto readyDelta = mWorkloadUpdateInfo->readyDuration - mScheduleTiming.readyDuration; const auto lastVsyncDelta = mWorkloadUpdateInfo->lastVsync - mScheduleTiming.lastVsync; - ATRACE_FORMAT_INSTANT("Workload updated workDelta=%" PRId64 " readyDelta=%" PRId64 - " lastVsyncDelta=%" PRId64, - workDelta, readyDelta, lastVsyncDelta); + SFTRACE_FORMAT_INSTANT("Workload updated workDelta=%" PRId64 " readyDelta=%" PRId64 + " lastVsyncDelta=%" PRId64, + workDelta, readyDelta, lastVsyncDelta); mScheduleTiming = *mWorkloadUpdateInfo; mWorkloadUpdateInfo.reset(); } @@ -310,7 +310,7 @@ void VSyncDispatchTimerQueue::rearmTimer(nsecs_t now) { void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor( nsecs_t now, CallbackMap::const_iterator skipUpdateIt) { - ATRACE_CALL(); + SFTRACE_CALL(); std::optional min; std::optional targetVsync; std::optional nextWakeupName; @@ -337,13 +337,13 @@ void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor( if (min && min < mIntendedWakeupTime) { setTimer(*min, now); } else { - ATRACE_NAME("cancel timer"); + SFTRACE_NAME("cancel timer"); cancelTimer(); } } void VSyncDispatchTimerQueue::timerCallback() { - ATRACE_CALL(); + SFTRACE_CALL(); struct Invocation { std::shared_ptr callback; nsecs_t vsyncTimestamp; @@ -383,7 +383,7 @@ void VSyncDispatchTimerQueue::timerCallback() { for (auto const& invocation : invocations) { ftl::Concat trace(ftl::truncated<5>(invocation.callback->name())); - ATRACE_FORMAT("%s: %s", __func__, trace.c_str()); + SFTRACE_FORMAT("%s: %s", __func__, trace.c_str()); invocation.callback->callback(invocation.vsyncTimestamp, invocation.wakeupTimestamp, invocation.deadlineTimestamp); } diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index 0644acaee2..16799bd32d 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -30,10 +30,10 @@ #include #include #include +#include #include #include #include -#include #include #include "RefreshRateSelector.h" @@ -77,7 +77,7 @@ inline void VSyncPredictor::traceInt64If(const char* name, int64_t value) const } inline void VSyncPredictor::traceInt64(const char* name, int64_t value) const { - ATRACE_INT64(ftl::Concat(ftl::truncated<14>(name), " ", mId.value).c_str(), value); + SFTRACE_INT64(ftl::Concat(ftl::truncated<14>(name), " ", mId.value).c_str(), value); } inline size_t VSyncPredictor::next(size_t i) const { @@ -98,7 +98,7 @@ bool VSyncPredictor::validate(nsecs_t timestamp) const { (timestamp - aValidTimestamp) % idealPeriod() * kMaxPercent / idealPeriod(); if (percent >= kOutlierTolerancePercent && percent <= (kMaxPercent - kOutlierTolerancePercent)) { - ATRACE_FORMAT_INSTANT("timestamp is not aligned with model"); + SFTRACE_FORMAT_INSTANT("timestamp is not aligned with model"); return false; } @@ -109,7 +109,7 @@ bool VSyncPredictor::validate(nsecs_t timestamp) const { const auto distancePercent = std::abs(*iter - timestamp) * kMaxPercent / idealPeriod(); if (distancePercent < kOutlierTolerancePercent) { // duplicate timestamp - ATRACE_FORMAT_INSTANT("duplicate timestamp"); + SFTRACE_FORMAT_INSTANT("duplicate timestamp"); return false; } return true; @@ -135,7 +135,7 @@ Period VSyncPredictor::minFramePeriodLocked() const { } bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); @@ -155,8 +155,8 @@ bool VSyncPredictor::addVsyncTimestamp(nsecs_t timestamp) { } else { mKnownTimestamp = timestamp; } - ATRACE_FORMAT_INSTANT("timestamp rejected. mKnownTimestamp was %.2fms ago", - (mClock->now() - *mKnownTimestamp) / 1e6f); + SFTRACE_FORMAT_INSTANT("timestamp rejected. mKnownTimestamp was %.2fms ago", + (mClock->now() - *mKnownTimestamp) / 1e6f); return false; } @@ -297,7 +297,7 @@ nsecs_t VSyncPredictor::snapToVsync(nsecs_t timePoint) const { nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint, std::optional lastVsyncOpt) { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); const auto now = TimePoint::fromNs(mClock->now()); @@ -330,8 +330,8 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint, if (*vsyncOpt > mLastCommittedVsync) { mLastCommittedVsync = *vsyncOpt; - ATRACE_FORMAT_INSTANT("mLastCommittedVsync in %.2fms", - float(mLastCommittedVsync.ns() - mClock->now()) / 1e6f); + SFTRACE_FORMAT_INSTANT("mLastCommittedVsync in %.2fms", + float(mLastCommittedVsync.ns() - mClock->now()) / 1e6f); } return vsyncOpt->ns(); @@ -374,7 +374,7 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) { } void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) { - ATRACE_FORMAT("%s %s", __func__, to_string(renderRate).c_str()); + SFTRACE_FORMAT("%s %s", __func__, to_string(renderRate).c_str()); ALOGV("%s %s: RenderRate %s ", __func__, to_string(mId).c_str(), to_string(renderRate).c_str()); std::lock_guard lock(mMutex); const auto prevRenderRate = mRenderRateOpt; @@ -382,7 +382,7 @@ void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) { const auto renderPeriodDelta = prevRenderRate ? prevRenderRate->getPeriodNsecs() - renderRate.getPeriodNsecs() : 0; if (applyImmediately) { - ATRACE_FORMAT_INSTANT("applyImmediately"); + SFTRACE_FORMAT_INSTANT("applyImmediately"); while (mTimelines.size() > 1) { mTimelines.pop_front(); } @@ -394,7 +394,7 @@ void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) { const bool newRenderRateIsHigher = renderPeriodDelta > renderRate.getPeriodNsecs() && mLastCommittedVsync.ns() - mClock->now() > 2 * renderRate.getPeriodNsecs(); if (newRenderRateIsHigher) { - ATRACE_FORMAT_INSTANT("newRenderRateIsHigher"); + SFTRACE_FORMAT_INSTANT("newRenderRateIsHigher"); mTimelines.clear(); mLastCommittedVsync = TimePoint::fromNs(0); @@ -415,7 +415,7 @@ void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) { void VSyncPredictor::setDisplayModePtr(ftl::NonNull modePtr) { LOG_ALWAYS_FATAL_IF(mId != modePtr->getPhysicalDisplayId(), "mode does not belong to the display"); - ATRACE_FORMAT("%s %s", __func__, to_string(*modePtr).c_str()); + SFTRACE_FORMAT("%s %s", __func__, to_string(*modePtr).c_str()); const auto timeout = modePtr->getVrrConfig() ? modePtr->getVrrConfig()->notifyExpectedPresentConfig : std::nullopt; @@ -443,7 +443,7 @@ void VSyncPredictor::setDisplayModePtr(ftl::NonNull modePtr) { Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentTime, TimePoint lastConfirmedPresentTime) { - ATRACE_CALL(); + SFTRACE_CALL(); if (mNumVsyncsForFrame <= 1) { return 0ns; @@ -456,14 +456,15 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT auto prev = lastConfirmedPresentTime.ns(); for (auto& current : mPastExpectedPresentTimes) { if (CC_UNLIKELY(mTraceOn)) { - ATRACE_FORMAT_INSTANT("current %.2f past last signaled fence", - static_cast(current.ns() - lastConfirmedPresentTime.ns()) / - 1e6f); + SFTRACE_FORMAT_INSTANT("current %.2f past last signaled fence", + static_cast(current.ns() - + lastConfirmedPresentTime.ns()) / + 1e6f); } const auto minPeriodViolation = current.ns() - prev + threshold < minFramePeriod; if (minPeriodViolation) { - ATRACE_NAME("minPeriodViolation"); + SFTRACE_NAME("minPeriodViolation"); current = TimePoint::fromNs(prev + minFramePeriod); prev = current.ns(); } else { @@ -487,16 +488,16 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT void VSyncPredictor::onFrameBegin(TimePoint expectedPresentTime, TimePoint lastConfirmedPresentTime) { - ATRACE_NAME("VSyncPredictor::onFrameBegin"); + SFTRACE_NAME("VSyncPredictor::onFrameBegin"); std::lock_guard lock(mMutex); if (!mDisplayModePtr->getVrrConfig()) return; if (CC_UNLIKELY(mTraceOn)) { - ATRACE_FORMAT_INSTANT("vsync is %.2f past last signaled fence", - static_cast(expectedPresentTime.ns() - - lastConfirmedPresentTime.ns()) / - 1e6f); + SFTRACE_FORMAT_INSTANT("vsync is %.2f past last signaled fence", + static_cast(expectedPresentTime.ns() - + lastConfirmedPresentTime.ns()) / + 1e6f); } const auto currentPeriod = mRateMap.find(idealPeriod())->second.slope; const auto threshold = currentPeriod / 2; @@ -507,9 +508,9 @@ void VSyncPredictor::onFrameBegin(TimePoint expectedPresentTime, const bool frontIsBeforeConfirmed = front < lastConfirmedPresentTime.ns() + threshold; if (frontIsBeforeConfirmed) { if (CC_UNLIKELY(mTraceOn)) { - ATRACE_FORMAT_INSTANT("Discarding old vsync - %.2f before last signaled fence", - static_cast(lastConfirmedPresentTime.ns() - front) / - 1e6f); + SFTRACE_FORMAT_INSTANT("Discarding old vsync - %.2f before last signaled fence", + static_cast(lastConfirmedPresentTime.ns() - front) / + 1e6f); } mPastExpectedPresentTimes.pop_front(); } else { @@ -524,7 +525,7 @@ void VSyncPredictor::onFrameBegin(TimePoint expectedPresentTime, } void VSyncPredictor::onFrameMissed(TimePoint expectedPresentTime) { - ATRACE_NAME("VSyncPredictor::onFrameMissed"); + SFTRACE_NAME("VSyncPredictor::onFrameMissed"); std::lock_guard lock(mMutex); if (!mDisplayModePtr->getVrrConfig()) return; @@ -550,7 +551,7 @@ VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModelLocked() const { } void VSyncPredictor::clearTimestamps() { - ATRACE_CALL(); + SFTRACE_CALL(); if (!mTimestamps.empty()) { auto const maxRb = *std::max_element(mTimestamps.begin(), mTimestamps.end()); @@ -612,7 +613,7 @@ void VSyncPredictor::purgeTimelines(android::TimePoint now) { if (mRenderRateOpt && mLastCommittedVsync.ns() + mRenderRateOpt->getPeriodNsecs() * kEnoughFramesToBreakPhase < mClock->now()) { - ATRACE_FORMAT_INSTANT("kEnoughFramesToBreakPhase"); + SFTRACE_FORMAT_INSTANT("kEnoughFramesToBreakPhase"); mTimelines.clear(); mLastCommittedVsync = TimePoint::fromNs(0); mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, mRenderRateOpt); @@ -648,16 +649,16 @@ VSyncPredictor::VsyncTimeline::VsyncTimeline(TimePoint knownVsync, Period idealP void VSyncPredictor::VsyncTimeline::freeze(TimePoint lastVsync) { LOG_ALWAYS_FATAL_IF(mValidUntil.has_value()); - ATRACE_FORMAT_INSTANT("renderRate %s valid for %.2f", - mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA", - float(lastVsync.ns() - TimePoint::now().ns()) / 1e6f); + SFTRACE_FORMAT_INSTANT("renderRate %s valid for %.2f", + mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA", + float(lastVsync.ns() - TimePoint::now().ns()) / 1e6f); mValidUntil = lastVsync; } std::optional VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTimeFrom( Model model, std::optional minFramePeriodOpt, nsecs_t vsync, MissedVsync missedVsync, std::optional lastVsyncOpt) { - ATRACE_FORMAT("renderRate %s", mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA"); + SFTRACE_FORMAT("renderRate %s", mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA"); nsecs_t vsyncTime = snapToVsyncAlignedWithRenderRate(model, vsync); const auto threshold = model.slope / 2; @@ -671,7 +672,7 @@ std::optional VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTime // on whether we skipped the frame (onFrameMissed) or not (onFrameBegin) we apply a // different fixup. There is no need to to shift the vsync timeline again. vsyncTime += missedVsync.fixup.ns(); - ATRACE_FORMAT_INSTANT("lastFrameMissed"); + SFTRACE_FORMAT_INSTANT("lastFrameMissed"); } else if (mightBackpressure && lastVsyncOpt) { if (!FlagManager::getInstance().vrr_bugfix_24q4()) { // lastVsyncOpt does not need to be corrected with the new rate, and @@ -682,27 +683,27 @@ std::optional VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTime const auto vsyncDiff = vsyncTime - *lastVsyncOpt; if (vsyncDiff <= minFramePeriodOpt->ns() - threshold) { // avoid a duplicate vsync - ATRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f " - "which " - "is %.2f " - "from " - "prev. " - "adjust by %.2f", - static_cast(vsyncTime - TimePoint::now().ns()) / 1e6f, - static_cast(vsyncDiff) / 1e6f, - static_cast(mRenderRateOpt->getPeriodNsecs()) / 1e6f); + SFTRACE_FORMAT_INSTANT("skipping a vsync to avoid duplicate frame. next in %.2f " + "which " + "is %.2f " + "from " + "prev. " + "adjust by %.2f", + static_cast(vsyncTime - TimePoint::now().ns()) / 1e6f, + static_cast(vsyncDiff) / 1e6f, + static_cast(mRenderRateOpt->getPeriodNsecs()) / 1e6f); vsyncTime += mRenderRateOpt->getPeriodNsecs(); } } } - ATRACE_FORMAT_INSTANT("vsync in %.2fms", float(vsyncTime - TimePoint::now().ns()) / 1e6f); + SFTRACE_FORMAT_INSTANT("vsync in %.2fms", float(vsyncTime - TimePoint::now().ns()) / 1e6f); const bool isVsyncInvalid = FlagManager::getInstance().vrr_bugfix_24q4() ? isWithin(TimePoint::fromNs(vsyncTime)) == VsyncOnTimeline::Outside : mValidUntil && vsyncTime > mValidUntil->ns(); if (isVsyncInvalid) { - ATRACE_FORMAT_INSTANT("no longer valid for vsync in %.2f", - static_cast(vsyncTime - TimePoint::now().ns()) / 1e6f); + SFTRACE_FORMAT_INSTANT("no longer valid for vsync in %.2f", + static_cast(vsyncTime - TimePoint::now().ns()) / 1e6f); return std::nullopt; } @@ -766,14 +767,14 @@ bool VSyncPredictor::VsyncTimeline::isVSyncInPhase(Model model, nsecs_t vsync, F return true; } const auto vsyncSequence = getVsyncSequenceLocked(model, vsync); - ATRACE_FORMAT_INSTANT("vsync in: %.2f sequence: %" PRId64 " divisor: %zu", - getVsyncIn(now, vsyncSequence.vsyncTime), vsyncSequence.seq, divisor); + SFTRACE_FORMAT_INSTANT("vsync in: %.2f sequence: %" PRId64 " divisor: %zu", + getVsyncIn(now, vsyncSequence.vsyncTime), vsyncSequence.seq, divisor); return vsyncSequence.seq % divisor == 0; } void VSyncPredictor::VsyncTimeline::shiftVsyncSequence(Duration phase) { if (mLastVsyncSequence) { - ATRACE_FORMAT_INSTANT("adjusting vsync by %.2f", static_cast(phase.ns()) / 1e6f); + SFTRACE_FORMAT_INSTANT("adjusting vsync by %.2f", static_cast(phase.ns()) / 1e6f); mLastVsyncSequence->vsyncTime += phase.ns(); } } diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp index 8038364453..2455822c7d 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp @@ -20,11 +20,10 @@ //#define LOG_NDEBUG 0 #include +#include #include #include -#include #include -#include #include "../TracedOrdinal.h" #include "VSyncDispatch.h" @@ -53,7 +52,7 @@ VSyncReactor::VSyncReactor(PhysicalDisplayId id, std::unique_ptr clock, VSyncReactor::~VSyncReactor() = default; bool VSyncReactor::addPresentFence(std::shared_ptr fence) { - ATRACE_CALL(); + SFTRACE_CALL(); if (!fence) { return false; @@ -66,8 +65,8 @@ bool VSyncReactor::addPresentFence(std::shared_ptr fence) { std::lock_guard lock(mMutex); if (mExternalIgnoreFences || mInternalIgnoreFences) { - ATRACE_FORMAT_INSTANT("mExternalIgnoreFences=%d mInternalIgnoreFences=%d", - mExternalIgnoreFences, mInternalIgnoreFences); + SFTRACE_FORMAT_INSTANT("mExternalIgnoreFences=%d mInternalIgnoreFences=%d", + mExternalIgnoreFences, mInternalIgnoreFences); return true; } @@ -121,7 +120,7 @@ void VSyncReactor::updateIgnorePresentFencesInternal() { } void VSyncReactor::startPeriodTransitionInternal(ftl::NonNull modePtr) { - ATRACE_FORMAT("%s %" PRIu64, __func__, mId.value); + SFTRACE_FORMAT("%s %" PRIu64, __func__, mId.value); mPeriodConfirmationInProgress = true; mModePtrTransitioningTo = modePtr.get(); mMoreSamplesNeeded = true; @@ -129,15 +128,15 @@ void VSyncReactor::startPeriodTransitionInternal(ftl::NonNull mo } void VSyncReactor::endPeriodTransition() { - ATRACE_FORMAT("%s %" PRIu64, __func__, mId.value); + SFTRACE_FORMAT("%s %" PRIu64, __func__, mId.value); mModePtrTransitioningTo.reset(); mPeriodConfirmationInProgress = false; mLastHwVsync.reset(); } void VSyncReactor::onDisplayModeChanged(ftl::NonNull modePtr, bool force) { - ATRACE_INT64(ftl::Concat("VSR-", __func__, " ", mId.value).c_str(), - modePtr->getVsyncRate().getPeriodNsecs()); + SFTRACE_INT64(ftl::Concat("VSR-", __func__, " ", mId.value).c_str(), + modePtr->getVsyncRate().getPeriodNsecs()); std::lock_guard lock(mMutex); mLastHwVsync.reset(); @@ -191,7 +190,7 @@ bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional std::lock_guard lock(mMutex); if (periodConfirmed(timestamp, hwcVsyncPeriod)) { - ATRACE_FORMAT("VSR %" PRIu64 ": period confirmed", mId.value); + SFTRACE_FORMAT("VSR %" PRIu64 ": period confirmed", mId.value); if (mModePtrTransitioningTo) { mTracker.setDisplayModePtr(ftl::as_non_null(mModePtrTransitioningTo)); *periodFlushed = true; @@ -205,12 +204,12 @@ bool VSyncReactor::addHwVsyncTimestamp(nsecs_t timestamp, std::optional endPeriodTransition(); mMoreSamplesNeeded = mTracker.needsMoreSamples(); } else if (mPeriodConfirmationInProgress) { - ATRACE_FORMAT("VSR %" PRIu64 ": still confirming period", mId.value); + SFTRACE_FORMAT("VSR %" PRIu64 ": still confirming period", mId.value); mLastHwVsync = timestamp; mMoreSamplesNeeded = true; *periodFlushed = false; } else { - ATRACE_FORMAT("VSR %" PRIu64 ": adding sample", mId.value); + SFTRACE_FORMAT("VSR %" PRIu64 ": adding sample", mId.value); *periodFlushed = false; mTracker.addVsyncTimestamp(timestamp); mMoreSamplesNeeded = mTracker.needsMoreSamples(); diff --git a/services/surfaceflinger/Scheduler/VsyncModulator.cpp b/services/surfaceflinger/Scheduler/VsyncModulator.cpp index 586357f50a..fa377e9323 100644 --- a/services/surfaceflinger/Scheduler/VsyncModulator.cpp +++ b/services/surfaceflinger/Scheduler/VsyncModulator.cpp @@ -22,8 +22,8 @@ #include "VsyncModulator.h" #include +#include #include -#include #include #include @@ -72,7 +72,7 @@ VsyncModulator::VsyncConfigOpt VsyncModulator::setTransactionSchedule(Transactio } if (mTraceDetailedInfo) { - ATRACE_INT("mEarlyWakeup", static_cast(mEarlyWakeupRequests.size())); + SFTRACE_INT("mEarlyWakeup", static_cast(mEarlyWakeupRequests.size())); } if (mEarlyWakeupRequests.empty() && schedule == Schedule::EarlyEnd) { @@ -172,9 +172,9 @@ VsyncConfig VsyncModulator::updateVsyncConfigLocked() { const bool isEarlyGpu = &offsets == &mVsyncConfigSet.earlyGpu; const bool isLate = &offsets == &mVsyncConfigSet.late; - ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly); - ATRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu); - ATRACE_INT("Vsync-LateOffsetsOn", isLate); + SFTRACE_INT("Vsync-EarlyOffsetsOn", isEarly); + SFTRACE_INT("Vsync-EarlyGpuOffsetsOn", isEarlyGpu); + SFTRACE_INT("Vsync-LateOffsetsOn", isLate); } return offsets; diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp index 2fa3318560..d3e312ae00 100644 --- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp +++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp @@ -18,8 +18,8 @@ #include +#include #include -#include #include #include @@ -182,7 +182,7 @@ void VsyncSchedule::enableHardwareVsync() { } void VsyncSchedule::enableHardwareVsyncLocked() { - ATRACE_CALL(); + SFTRACE_CALL(); if (mHwVsyncState == HwVsyncState::Disabled) { getTracker().resetModel(); mRequestHardwareVsync(mId, true); @@ -191,7 +191,7 @@ void VsyncSchedule::enableHardwareVsyncLocked() { } void VsyncSchedule::disableHardwareVsync(bool disallow) { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mHwVsyncLock); switch (mHwVsyncState) { case HwVsyncState::Enabled: diff --git a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp index badd21ef86..60694b96a4 100644 --- a/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp +++ b/services/surfaceflinger/Scheduler/src/FrameTargeter.cpp @@ -14,9 +14,8 @@ * limitations under the License. */ -#include - #include +#include #include #include @@ -90,9 +89,9 @@ void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& v mEarliestPresentTime = computeEarliestPresentTime(minFramePeriod, args.hwcMinWorkDuration); } - ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, ftl::to_underlying(args.vsyncId), - ticks(mExpectedPresentTime - TimePoint::now()), - mExpectedPresentTime == args.expectedVsyncTime ? "" : " (adjusted)"); + SFTRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, ftl::to_underlying(args.vsyncId), + ticks(mExpectedPresentTime - TimePoint::now()), + mExpectedPresentTime == args.expectedVsyncTime ? "" : " (adjusted)"); const FenceTimePtr& pastPresentFence = presentFenceForPastVsync(minFramePeriod); @@ -165,7 +164,7 @@ void FrameTargeter::dump(utils::Dumper& dumper) const { } bool FrameTargeter::isFencePending(const FenceTimePtr& fence, int graceTimeMs) { - ATRACE_CALL(); + SFTRACE_CALL(); const status_t status = fence->wait(graceTimeMs); // This is the same as Fence::Status::Unsignaled, but it saves a call to getStatus, diff --git a/services/surfaceflinger/Scheduler/src/Timer.cpp b/services/surfaceflinger/Scheduler/src/Timer.cpp index eeb9c60d15..fba3d58db5 100644 --- a/services/surfaceflinger/Scheduler/src/Timer.cpp +++ b/services/surfaceflinger/Scheduler/src/Timer.cpp @@ -24,10 +24,10 @@ #include #include +#include #include #include #include -#include #include @@ -190,7 +190,7 @@ bool Timer::dispatch() { setDebugState(DebugState::Running); if (ATRACE_ENABLED()) { ftl::Concat trace("TimerIteration #", iteration++); - ATRACE_NAME(trace.c_str()); + SFTRACE_NAME(trace.c_str()); } if (nfds == -1) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a65ef4e623..b3c9b7fa34 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,6 @@ #include #include #include -#include #include #include #include @@ -434,7 +434,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) } SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGI("SurfaceFlinger is starting"); hasSyncFramework = running_without_sync_framework(true); @@ -861,7 +861,7 @@ renderengine::RenderEngine::BlurAlgorithm chooseBlurAlgorithm(bool supportsBlur) } void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); addTransactionReadyFilters(); @@ -1313,7 +1313,7 @@ void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode) { const auto mode = desiredMode.mode; const auto displayId = mode.modePtr->getPhysicalDisplayId(); - ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str()); + SFTRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str()); const bool emitEvent = desiredMode.emitEvent; @@ -1366,7 +1366,7 @@ void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode) { status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp& displayToken, DisplayModeId modeId, Fps minFps, Fps maxFps) { - ATRACE_CALL(); + SFTRACE_CALL(); if (!displayToken) { return BAD_VALUE; @@ -1416,7 +1416,7 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp displayToUpdateImmediately; @@ -1559,7 +1559,7 @@ void SurfaceFlinger::initiateDisplayModeChanges() { void SurfaceFlinger::disableExpensiveRendering() { const char* const whence = __func__; auto future = mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) { - ATRACE_NAME(whence); + SFTRACE_NAME(whence); if (mPowerAdvisor->isUsingExpensiveRendering()) { for (const auto& [_, display] : mDisplays) { constexpr bool kDisable = false; @@ -2224,9 +2224,9 @@ void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t t } } - ATRACE_NAME(vsyncPeriod - ? ftl::Concat(__func__, ' ', hwcDisplayId, ' ', *vsyncPeriod, "ns").c_str() - : ftl::Concat(__func__, ' ', hwcDisplayId).c_str()); + SFTRACE_NAME(vsyncPeriod + ? ftl::Concat(__func__, ' ', hwcDisplayId, ' ', *vsyncPeriod, "ns").c_str() + : ftl::Concat(__func__, ' ', hwcDisplayId).c_str()); Mutex::Autolock lock(mStateLock); if (const auto displayIdOpt = getHwComposer().onVsync(hwcDisplayId, timestamp)) { @@ -2284,12 +2284,12 @@ void SurfaceFlinger::onComposerHalRefresh(hal::HWDisplayId) { } void SurfaceFlinger::onComposerHalVsyncIdle(hal::HWDisplayId) { - ATRACE_CALL(); + SFTRACE_CALL(); mScheduler->forceNextResync(); } void SurfaceFlinger::onRefreshRateChangedDebug(const RefreshRateChangedDebugData& data) { - ATRACE_CALL(); + SFTRACE_CALL(); const char* const whence = __func__; static_cast(mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD( kMainThreadContext) { @@ -2298,7 +2298,7 @@ void SurfaceFlinger::onRefreshRateChangedDebug(const RefreshRateChangedDebugData const Fps refreshRate = Fps::fromPeriodNsecs( getHwComposer().getComposer()->isVrrSupported() ? data.refreshPeriodNanos : data.vsyncPeriodNanos); - ATRACE_FORMAT("%s refresh rate = %d", whence, refreshRate.getIntValue()); + SFTRACE_FORMAT("%s refresh rate = %d", whence, refreshRate.getIntValue()); const auto renderRate = mDisplayModeController.getActiveMode(*displayIdOpt).fps; constexpr bool kSetByHwc = true; @@ -2318,7 +2318,7 @@ void SurfaceFlinger::configure() { bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, nsecs_t frameTimeNs, bool flushTransactions, bool& outTransactionsAreEmpty) { - ATRACE_CALL(); + SFTRACE_CALL(); frontend::Update update; if (flushTransactions) { update = flushLifecycleUpdates(); @@ -2417,10 +2417,10 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) { bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, bool flushTransactions, bool& outTransactionsAreEmpty) { using Changes = frontend::RequestedLayerState::Changes; - ATRACE_CALL(); + SFTRACE_CALL(); frontend::Update update; if (flushTransactions) { - ATRACE_NAME("TransactionHandler:flushTransactions"); + SFTRACE_NAME("TransactionHandler:flushTransactions"); // Locking: // 1. to prevent onHandleDestroyed from being called while the state lock is held, // we must keep a copy of the transactions (specifically the composer @@ -2472,7 +2472,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, mustComposite |= applyAndCommitDisplayTransactionStatesLocked(update.transactions); { - ATRACE_NAME("LayerSnapshotBuilder:update"); + SFTRACE_NAME("LayerSnapshotBuilder:update"); frontend::LayerSnapshotBuilder::Args args{.root = mLayerHierarchyBuilder.getHierarchy(), .layerLifecycleManager = mLayerLifecycleManager, @@ -2513,7 +2513,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, } bool newDataLatched = false; - ATRACE_NAME("DisplayCallbackAndStatsUpdates"); + SFTRACE_NAME("DisplayCallbackAndStatsUpdates"); mustComposite |= applyTransactionsLocked(update.transactions, vsyncId); traverseLegacyLayers([&](Layer* layer) { layer->commitTransaction(); }); const nsecs_t latchTime = systemTime(); @@ -2579,7 +2579,7 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, } { - ATRACE_NAME("LLM:commitChanges"); + SFTRACE_NAME("LLM:commitChanges"); mLayerLifecycleManager.commitChanges(); } @@ -2602,7 +2602,7 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, const scheduler::FrameTarget& pacesetterFrameTarget = *frameTargets.get(pacesetterId)->get(); const VsyncId vsyncId = pacesetterFrameTarget.vsyncId(); - ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str()); + SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str()); if (pacesetterFrameTarget.didMissFrame()) { mTimeStats->incrementMissedFrames(); @@ -2744,7 +2744,7 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( frameTargeters.get(pacesetterId)->get()->target(); const VsyncId vsyncId = pacesetterTarget.vsyncId(); - ATRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str()); + SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str()); compositionengine::CompositionRefreshArgs refreshArgs; refreshArgs.powerCallback = this; @@ -2908,7 +2908,7 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( } } - ATRACE_NAME("postComposition"); + SFTRACE_NAME("postComposition"); mTimeStats->recordFrameDuration(pacesetterTarget.frameBeginTime().ns(), systemTime()); // Send a power hint after presentation is finished. @@ -3004,7 +3004,7 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( } void SurfaceFlinger::updateLayerGeometry() { - ATRACE_CALL(); + SFTRACE_CALL(); if (mVisibleRegionsDirty) { computeLayerBounds(); @@ -3088,7 +3088,7 @@ ui::Rotation SurfaceFlinger::getPhysicalDisplayOrientation(DisplayId displayId, void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters, nsecs_t presentStartTime) { - ATRACE_CALL(); + SFTRACE_CALL(); ui::PhysicalDisplayMap> presentFences; ui::PhysicalDisplayMap> gpuCompositionDoneFences; @@ -3333,7 +3333,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, // side-effect of getTotalSize(), so we check that again here if (ATRACE_ENABLED()) { // getTotalSize returns the total number of buffers that were allocated by SurfaceFlinger - ATRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize()); + SFTRACE_INT64("Total Buffer Size", GraphicBufferAllocator::get().getTotalSize()); } logFrameStats(presentTime); @@ -3370,7 +3370,7 @@ void SurfaceFlinger::computeLayerBounds() { } void SurfaceFlinger::commitTransactions() { - ATRACE_CALL(); + SFTRACE_CALL(); mDebugInTransaction = systemTime(); // Here we're guaranteed that some transaction flags are set @@ -3383,7 +3383,7 @@ void SurfaceFlinger::commitTransactions() { } void SurfaceFlinger::commitTransactionsLegacy() { - ATRACE_CALL(); + SFTRACE_CALL(); // Keep a copy of the drawing state (that is going to be overwritten // by commitTransactionsLocked) outside of mStateLock so that the side @@ -4131,7 +4131,7 @@ void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId, TimePoint frameTime) { if (!mInputFlinger || (!mUpdateInputInfo && mInputWindowCommands.empty())) { return; } - ATRACE_CALL(); + SFTRACE_CALL(); std::vector windowInfos; std::vector displayInfos; @@ -4161,7 +4161,7 @@ void SurfaceFlinger::updateInputFlinger(VsyncId vsyncId, TimePoint frameTime) { std::move(mInputWindowCommands), inputFlinger = mInputFlinger, this, visibleWindowsChanged, vsyncId, frameTime]() { - ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); + SFTRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker ->windowInfosChanged(gui::WindowInfosUpdate{std::move(windowInfos), @@ -4274,7 +4274,7 @@ void SurfaceFlinger::requestDisplayModes(std::vector& display) { } void SurfaceFlinger::doCommitTransactions() { - ATRACE_CALL(); + SFTRACE_CALL(); if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from @@ -4622,7 +4622,7 @@ void SurfaceFlinger::invalidateLayerStack(const ui::LayerFilter& layerFilter, co } bool SurfaceFlinger::latchBuffers() { - ATRACE_CALL(); + SFTRACE_CALL(); const nsecs_t latchTime = systemTime(); @@ -4799,7 +4799,7 @@ uint32_t SurfaceFlinger::getTransactionFlags() const { uint32_t SurfaceFlinger::clearTransactionFlags(uint32_t mask) { uint32_t transactionFlags = mTransactionFlags.fetch_and(~mask); - ATRACE_INT("mTransactionFlags", transactionFlags); + SFTRACE_INT("mTransactionFlags", transactionFlags); return transactionFlags & mask; } @@ -4807,7 +4807,7 @@ void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule sche const sp& applyToken, FrameHint frameHint) { mScheduler->modulateVsync({}, &VsyncModulator::setTransactionSchedule, schedule, applyToken); uint32_t transactionFlags = mTransactionFlags.fetch_or(mask); - ATRACE_INT("mTransactionFlags", transactionFlags); + SFTRACE_INT("mTransactionFlags", transactionFlags); if (const bool scheduled = transactionFlags & mask; !scheduled) { scheduleCommit(frameHint); @@ -4832,8 +4832,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelin // for stability reasons. if (!transaction.isAutoTimestamp && desiredPresentTime >= expectedPresentTime && desiredPresentTime < expectedPresentTime + 1s) { - ATRACE_FORMAT("not current desiredPresentTime: %" PRId64 " expectedPresentTime: %" PRId64, - desiredPresentTime, expectedPresentTime); + SFTRACE_FORMAT("not current desiredPresentTime: %" PRId64 " expectedPresentTime: %" PRId64, + desiredPresentTime, expectedPresentTime); return TransactionReadiness::NotReady; } @@ -4845,16 +4845,16 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyTimelin // incorrectly as the frame rate of SF changed before it drained the older transactions. if (ftl::to_underlying(vsyncId) == FrameTimelineInfo::INVALID_VSYNC_ID && !mScheduler->isVsyncValid(expectedPresentTime, transaction.originUid)) { - ATRACE_FORMAT("!isVsyncValid expectedPresentTime: %" PRId64 " uid: %d", expectedPresentTime, - transaction.originUid); + SFTRACE_FORMAT("!isVsyncValid expectedPresentTime: %" PRId64 " uid: %d", + expectedPresentTime, transaction.originUid); return TransactionReadiness::NotReady; } // If the client didn't specify desiredPresentTime, use the vsyncId to determine the // expected present time of this transaction. if (transaction.isAutoTimestamp && frameIsEarly(expectedPresentTime, vsyncId)) { - ATRACE_FORMAT("frameIsEarly vsyncId: %" PRId64 " expectedPresentTime: %" PRId64, - transaction.frameTimelineInfo.vsyncId, expectedPresentTime); + SFTRACE_FORMAT("frameIsEarly vsyncId: %" PRId64 " expectedPresentTime: %" PRId64, + transaction.frameTimelineInfo.vsyncId, expectedPresentTime); return TransactionReadiness::NotReady; } @@ -4883,9 +4883,9 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC s.bufferData->acquireFence); // Delete the entire state at this point and not just release the buffer because // everything associated with the Layer in this Transaction is now out of date. - ATRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", - layer->getDebugName(), layer->getDrawingState().barrierProducerId, - s.bufferData->producerId); + SFTRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", + layer->getDebugName(), layer->getDrawingState().barrierProducerId, + s.bufferData->producerId); return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL; } @@ -4895,10 +4895,10 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >= s.bufferData->barrierFrameNumber)); if (!willApplyBarrierFrame) { - ATRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 " > %" PRId64, - layer->getDebugName(), - layer->getDrawingState().barrierFrameNumber, - s.bufferData->barrierFrameNumber); + SFTRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 " > %" PRId64, + layer->getDebugName(), + layer->getDrawingState().barrierFrameNumber, + s.bufferData->barrierFrameNumber); ready = TransactionReadiness::NotReadyBarrier; return TraverseBuffersReturnValues::STOP_TRAVERSAL; } @@ -4910,7 +4910,7 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC const bool hasPendingBuffer = flushState.bufferLayersReadyToPresent.contains(s.surface.get()); if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) { - ATRACE_FORMAT("hasPendingBuffer %s", layer->getDebugName()); + SFTRACE_FORMAT("hasPendingBuffer %s", layer->getDebugName()); ready = TransactionReadiness::NotReady; return TraverseBuffersReturnValues::STOP_TRAVERSAL; } @@ -4927,8 +4927,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC layer->isSimpleBufferUpdate(s); if (allowLatchUnsignaled) { - ATRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", - layer->getDebugName()); + SFTRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", + layer->getDebugName()); ready = TransactionReadiness::NotReadyUnsignaled; } else { ready = TransactionReadiness::NotReady; @@ -4947,7 +4947,7 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC .bufferId = s.bufferData->getId(), .frameNumber = s.bufferData->frameNumber}); } - ATRACE_FORMAT("fence unsignaled %s", layer->getDebugName()); + SFTRACE_FORMAT("fence unsignaled %s", layer->getDebugName()); return TraverseBuffersReturnValues::STOP_TRAVERSAL; } } @@ -4977,8 +4977,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC uint32_t currentMaxAcquiredBufferCount = getMaxAcquiredBufferCountForCurrentRefreshRate( layer->ownerUid.val()); - ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, - layer->name.c_str(), s.bufferData->frameNumber); + SFTRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, + layer->name.c_str(), s.bufferData->frameNumber); s.bufferData->releaseBufferListener ->onReleaseBuffer({resolvedState.externalTexture->getBuffer() ->getId(), @@ -4992,9 +4992,9 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC // Delete the entire state at this point and not just release the buffer // because everything associated with the Layer in this Transaction is now // out of date. - ATRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", - layer->name.c_str(), layer->barrierProducerId, - s.bufferData->producerId); + SFTRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", + layer->name.c_str(), layer->barrierProducerId, + s.bufferData->producerId); return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL; } @@ -5004,10 +5004,10 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >= s.bufferData->barrierFrameNumber)); if (!willApplyBarrierFrame) { - ATRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 - " > %" PRId64, - layer->name.c_str(), layer->barrierFrameNumber, - s.bufferData->barrierFrameNumber); + SFTRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 + " > %" PRId64, + layer->name.c_str(), layer->barrierFrameNumber, + s.bufferData->barrierFrameNumber); ready = TransactionReadiness::NotReadyBarrier; return TraverseBuffersReturnValues::STOP_TRAVERSAL; } @@ -5020,7 +5020,7 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC flushState.bufferLayersReadyToPresent.contains(s.surface.get()); if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) { - ATRACE_FORMAT("hasPendingBuffer %s", layer->name.c_str()); + SFTRACE_FORMAT("hasPendingBuffer %s", layer->name.c_str()); ready = TransactionReadiness::NotReady; return TraverseBuffersReturnValues::STOP_TRAVERSAL; } @@ -5037,8 +5037,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC flushState.firstTransaction) && layer->isSimpleBufferUpdate(s); if (allowLatchUnsignaled) { - ATRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", - layer->name.c_str()); + SFTRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", + layer->name.c_str()); ready = TransactionReadiness::NotReadyUnsignaled; } else { ready = TransactionReadiness::NotReady; @@ -5055,7 +5055,7 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC .frameNumber = s.bufferData->frameNumber}); } - ATRACE_FORMAT("fence unsignaled %s", layer->name.c_str()); + SFTRACE_FORMAT("fence unsignaled %s", layer->name.c_str()); return TraverseBuffersReturnValues::STOP_TRAVERSAL; } } @@ -5136,22 +5136,22 @@ bool SurfaceFlinger::frameIsEarly(TimePoint expectedPresentTime, VsyncId vsyncId bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t numStates, bool firstTransaction) const { if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) { - ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::Disabled)", __func__); + SFTRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::Disabled)", __func__); return false; } // We only want to latch unsignaled when a single layer is updated in this // transaction (i.e. not a blast sync transaction). if (numStates != 1) { - ATRACE_FORMAT_INSTANT("%s: false (numStates=%zu)", __func__, numStates); + SFTRACE_FORMAT_INSTANT("%s: false (numStates=%zu)", __func__, numStates); return false; } if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::AutoSingleLayer) { if (!firstTransaction) { - ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; not first " - "transaction)", - __func__); + SFTRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; not first " + "transaction)", + __func__); return false; } @@ -5159,9 +5159,9 @@ bool SurfaceFlinger::shouldLatchUnsignaled(const layer_state_t& state, size_t nu // as it leads to jank due to RenderEngine waiting for unsignaled buffer // or window animations being slow. if (mScheduler->vsyncModulator().isVsyncConfigEarly()) { - ATRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; " - "isVsyncConfigEarly)", - __func__); + SFTRACE_FORMAT_INSTANT("%s: false (LatchUnsignaledConfig::AutoSingleLayer; " + "isVsyncConfigEarly)", + __func__); return false; } } @@ -5176,7 +5176,7 @@ status_t SurfaceFlinger::setTransactionState( const std::vector& uncacheBuffers, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId, const std::vector& mergedTransactionIds) { - ATRACE_CALL(); + SFTRACE_CALL(); IPCThreadState* ipc = IPCThreadState::self(); const int originPid = ipc->getCallingPid(); @@ -6459,7 +6459,7 @@ void SurfaceFlinger::logFrameStats(TimePoint now) { if (now - sTimestamp < 30min) return; sTimestamp = now; - ATRACE_CALL(); + SFTRACE_CALL(); mDrawingState.traverse([&](Layer* layer) { layer->logFrameStats(); }); } @@ -7764,7 +7764,7 @@ void SurfaceFlinger::toggleKernelIdleTimer() { switch (action) { case KernelIdleTimerAction::TurnOff: if (mKernelIdleTimerEnabled) { - ATRACE_INT("KernelIdleTimer", 0); + SFTRACE_INT("KernelIdleTimer", 0); std::chrono::milliseconds constexpr kTimerDisabledTimeout = 0ms; updateKernelIdleTimer(kTimerDisabledTimeout, kernelIdleTimerController.value(), display->getPhysicalId()); @@ -7773,7 +7773,7 @@ void SurfaceFlinger::toggleKernelIdleTimer() { break; case KernelIdleTimerAction::TurnOn: if (!mKernelIdleTimerEnabled) { - ATRACE_INT("KernelIdleTimer", 1); + SFTRACE_INT("KernelIdleTimer", 1); const std::chrono::milliseconds timeout = display->refreshRateSelector().getIdleTimerTimeout(); updateKernelIdleTimer(timeout, kernelIdleTimerController.value(), @@ -7902,7 +7902,7 @@ static void invokeScreenCaptureError(const status_t status, void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, const sp& captureListener) { - ATRACE_CALL(); + SFTRACE_CALL(); status_t validate = validateScreenshotPermissions(args); if (validate != OK) { @@ -8033,7 +8033,7 @@ ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& a void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, const sp& captureListener) { - ATRACE_CALL(); + SFTRACE_CALL(); status_t validate = validateScreenshotPermissions(args); if (validate != OK) { @@ -8166,7 +8166,7 @@ std::optional SurfaceFlinger::getSnapsho std::vector>& layerFEs) { return mScheduler ->schedule([=, this, &renderAreaBuilder, &layerFEs]() REQUIRES(kMainThreadContext) { - ATRACE_NAME("getSnapshotsFromMainThread"); + SFTRACE_NAME("getSnapshotsFromMainThread"); auto layers = getLayerSnapshotsFn(); for (auto& [layer, layerFE] : layers) { attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK); @@ -8182,7 +8182,7 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp& captureListener) { - ATRACE_CALL(); + SFTRACE_CALL(); if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 @@ -8319,7 +8319,7 @@ ftl::SharedFuture SurfaceFlinger::captureScreenshot( const std::shared_ptr& buffer, bool regionSampling, bool grayscale, bool isProtected, const sp& captureListener, std::optional& displayState, std::vector>& layerFEs) { - ATRACE_CALL(); + SFTRACE_CALL(); ScreenCaptureResults captureResults; std::unique_ptr renderArea = @@ -8359,7 +8359,7 @@ ftl::SharedFuture SurfaceFlinger::captureScreenshotLegacy( RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, bool isProtected, const sp& captureListener) { - ATRACE_CALL(); + SFTRACE_CALL(); auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES( kMainThreadContext) mutable -> ftl::SharedFuture { @@ -8423,7 +8423,7 @@ ftl::SharedFuture SurfaceFlinger::renderScreenImpl( bool grayscale, bool isProtected, ScreenCaptureResults& captureResults, std::optional& displayState, std::vector>>& layers, std::vector>& layerFEs) { - ATRACE_CALL(); + SFTRACE_CALL(); for (auto& layerFE : layerFEs) { frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get(); @@ -8681,7 +8681,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal( const sp& display, const scheduler::RefreshRateSelector::PolicyVariant& policy) { const auto displayId = display->getPhysicalId(); - ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str()); + SFTRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str()); Mutex::Autolock lock(mStateLock); @@ -8774,7 +8774,7 @@ gui::DisplayModeSpecs::RefreshRateRanges translate(const FpsRanges& ranges) { status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp& displayToken, const gui::DisplayModeSpecs& specs) { - ATRACE_CALL(); + SFTRACE_CALL(); if (!displayToken) { return BAD_VALUE; @@ -8808,7 +8808,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp& displayTo status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp& displayToken, gui::DisplayModeSpecs* outSpecs) { - ATRACE_CALL(); + SFTRACE_CALL(); if (!displayToken || !outSpecs) { return BAD_VALUE; @@ -9100,7 +9100,7 @@ sp SurfaceFlinger::getActivatableDisplay() const { void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveDisplayPtr, const DisplayDevice& activeDisplay) { - ATRACE_CALL(); + SFTRACE_CALL(); if (inactiveDisplayPtr) { inactiveDisplayPtr->getCompositionDisplay()->setLayerCachingTexturePoolEnabled(false); @@ -9534,7 +9534,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t u frontend::Update SurfaceFlinger::flushLifecycleUpdates() { frontend::Update update; - ATRACE_NAME("TransactionHandler:flushTransactions"); + SFTRACE_NAME("TransactionHandler:flushTransactions"); // Locking: // 1. to prevent onHandleDestroyed from being called while the state lock is held, // we must keep a copy of the transactions (specifically the composer @@ -9580,7 +9580,7 @@ void SurfaceFlinger::doActiveLayersTracingIfNeeded(bool isCompositionComputed, perfetto::protos::LayersSnapshotProto SurfaceFlinger::takeLayersSnapshotProto( uint32_t traceFlags, TimePoint time, VsyncId vsyncId, bool visibleRegionDirty) { - ATRACE_CALL(); + SFTRACE_CALL(); perfetto::protos::LayersSnapshotProto snapshot; snapshot.set_elapsed_realtime_nanos(time.ns()); snapshot.set_vsync_id(ftl::to_underlying(vsyncId)); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 54717c0599..8242844b03 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,6 @@ #include #include #include -#include #include #include @@ -450,7 +450,7 @@ private: if (it != mCounterByLayerHandle.end()) { auto [name, pendingBuffers] = it->second; int32_t count = ++(*pendingBuffers); - ATRACE_INT(name.c_str(), count); + SFTRACE_INT(name.c_str(), count); } else { ALOGW("Handle not found! %p", layerHandle); } diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp index a631074f4d..ea86911bed 100644 --- a/services/surfaceflinger/TimeStats/Android.bp +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -24,6 +24,7 @@ cc_defaults { static_libs: [ "libtimestats_proto", + "libsurfaceflinger_common", ], export_static_lib_headers: [ diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 368cb41779..c60ded6e56 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -19,11 +19,11 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include +#include #include #include #include #include -#include #include #include @@ -271,7 +271,7 @@ bool TimeStats::onPullAtom(const int atomId, std::vector* pulledData) { } void TimeStats::parseArgs(bool asProto, const Vector& args, std::string& result) { - ATRACE_CALL(); + SFTRACE_CALL(); std::unordered_map argsMap; for (size_t index = 0; index < args.size(); ++index) { @@ -304,7 +304,7 @@ void TimeStats::parseArgs(bool asProto, const Vector& args, std::strin } std::string TimeStats::miniDump() { - ATRACE_CALL(); + SFTRACE_CALL(); std::string result = "TimeStats miniDump:\n"; std::lock_guard lock(mMutex); @@ -318,7 +318,7 @@ std::string TimeStats::miniDump() { void TimeStats::incrementTotalFrames() { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); mTimeStats.totalFramesLegacy++; @@ -327,7 +327,7 @@ void TimeStats::incrementTotalFrames() { void TimeStats::incrementMissedFrames() { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); mTimeStats.missedFramesLegacy++; @@ -338,7 +338,7 @@ void TimeStats::pushCompositionStrategyState(const TimeStats::ClientCompositionR return; } - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); if (record.changed) mTimeStats.compositionStrategyChangesLegacy++; @@ -351,7 +351,7 @@ void TimeStats::pushCompositionStrategyState(const TimeStats::ClientCompositionR void TimeStats::incrementRefreshRateSwitches() { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); mTimeStats.refreshRateSwitchesLegacy++; @@ -445,7 +445,7 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayR std::optional renderRate, SetFrameRateVote frameRateVote, GameMode gameMode) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-flushAvailableRecordsToStatsLocked", layerId); LayerRecord& layerRecord = mTimeStatsTracker[layerId]; @@ -568,7 +568,7 @@ void TimeStats::setPostTime(int32_t layerId, uint64_t frameNumber, const std::st uid_t uid, nsecs_t postTime, GameMode gameMode) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerId, frameNumber, layerName.c_str(), postTime); @@ -612,7 +612,7 @@ void TimeStats::setPostTime(int32_t layerId, uint64_t frameNumber, const std::st void TimeStats::setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerId, frameNumber, latchTime); std::lock_guard lock(mMutex); @@ -630,7 +630,7 @@ void TimeStats::setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latc void TimeStats::incrementLatchSkipped(int32_t layerId, LatchSkipReason reason) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-LatchSkipped-Reason[%d]", layerId, static_cast::type>(reason)); @@ -648,7 +648,7 @@ void TimeStats::incrementLatchSkipped(int32_t layerId, LatchSkipReason reason) { void TimeStats::incrementBadDesiredPresent(int32_t layerId) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-BadDesiredPresent", layerId); std::lock_guard lock(mMutex); @@ -660,7 +660,7 @@ void TimeStats::incrementBadDesiredPresent(int32_t layerId) { void TimeStats::setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerId, frameNumber, desiredTime); std::lock_guard lock(mMutex); @@ -678,7 +678,7 @@ void TimeStats::setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t de void TimeStats::setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerId, frameNumber, acquireTime); std::lock_guard lock(mMutex); @@ -697,7 +697,7 @@ void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerId, frameNumber, acquireFence->getSignalTime()); @@ -718,7 +718,7 @@ void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t pr SetFrameRateVote frameRateVote, GameMode gameMode) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerId, frameNumber, presentTime); std::lock_guard lock(mMutex); @@ -744,7 +744,7 @@ void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, SetFrameRateVote frameRateVote, GameMode gameMode) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerId, frameNumber, presentFence->getSignalTime()); @@ -805,7 +805,7 @@ static void updateJankPayload(T& t, int32_t reasons) { void TimeStats::incrementJankyFrames(const JankyFramesInfo& info) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); // Only update layer stats if we're already tracking the layer in TimeStats. @@ -861,7 +861,7 @@ void TimeStats::incrementJankyFrames(const JankyFramesInfo& info) { } void TimeStats::onDestroy(int32_t layerId) { - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-onDestroy", layerId); std::lock_guard lock(mMutex); mTimeStatsTracker.erase(layerId); @@ -870,7 +870,7 @@ void TimeStats::onDestroy(int32_t layerId) { void TimeStats::removeTimeRecord(int32_t layerId, uint64_t frameNumber) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerId, frameNumber); std::lock_guard lock(mMutex); @@ -935,7 +935,7 @@ void TimeStats::recordRefreshRate(uint32_t fps, nsecs_t duration) { } void TimeStats::flushAvailableGlobalRecordsToStatsLocked() { - ATRACE_CALL(); + SFTRACE_CALL(); while (!mGlobalRecord.presentFences.empty()) { const nsecs_t curPresentTime = mGlobalRecord.presentFences.front()->getSignalTime(); @@ -992,7 +992,7 @@ void TimeStats::flushAvailableGlobalRecordsToStatsLocked() { void TimeStats::setPresentFenceGlobal(const std::shared_ptr& presentFence) { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); if (presentFence == nullptr || !presentFence->isValid()) { mGlobalRecord.prevPresentTime = 0; @@ -1022,7 +1022,7 @@ void TimeStats::setPresentFenceGlobal(const std::shared_ptr& presentF void TimeStats::enable() { if (mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); mEnabled.store(true); @@ -1034,7 +1034,7 @@ void TimeStats::enable() { void TimeStats::disable() { if (!mEnabled.load()) return; - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); flushPowerTimeLocked(); @@ -1051,7 +1051,7 @@ void TimeStats::clearAll() { } void TimeStats::clearGlobalLocked() { - ATRACE_CALL(); + SFTRACE_CALL(); mTimeStats.statsStartLegacy = (mEnabled.load() ? static_cast(std::time(0)) : 0); mTimeStats.statsEndLegacy = 0; @@ -1078,7 +1078,7 @@ void TimeStats::clearGlobalLocked() { } void TimeStats::clearLayersLocked() { - ATRACE_CALL(); + SFTRACE_CALL(); mTimeStatsTracker.clear(); @@ -1093,7 +1093,7 @@ bool TimeStats::isEnabled() { } void TimeStats::dump(bool asProto, std::optional maxLayers, std::string& result) { - ATRACE_CALL(); + SFTRACE_CALL(); std::lock_guard lock(mMutex); if (mTimeStats.statsStartLegacy == 0) { diff --git a/services/surfaceflinger/TracedOrdinal.h b/services/surfaceflinger/TracedOrdinal.h index 1adc3a531d..eba1ecf760 100644 --- a/services/surfaceflinger/TracedOrdinal.h +++ b/services/surfaceflinger/TracedOrdinal.h @@ -21,8 +21,8 @@ #include #include +#include #include -#include namespace android { @@ -88,13 +88,13 @@ private: } if (!signbit(mData)) { - ATRACE_INT64(mName.c_str(), to_int64(mData)); + SFTRACE_INT64(mName.c_str(), to_int64(mData)); if (mHasGoneNegative) { - ATRACE_INT64(mNameNegative.c_str(), 0); + SFTRACE_INT64(mNameNegative.c_str(), 0); } } else { - ATRACE_INT64(mNameNegative.c_str(), -to_int64(mData)); - ATRACE_INT64(mName.c_str(), 0); + SFTRACE_INT64(mNameNegative.c_str(), -to_int64(mData)); + SFTRACE_INT64(mName.c_str(), 0); } } diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp index 41bcdf05c3..d40b888504 100644 --- a/services/surfaceflinger/Tracing/LayerTracing.cpp +++ b/services/surfaceflinger/Tracing/LayerTracing.cpp @@ -24,10 +24,10 @@ #include "Tracing/tools/LayerTraceGenerator.h" #include "TransactionTracing.h" +#include #include #include #include -#include namespace android { @@ -134,7 +134,7 @@ void LayerTracing::onStop(Mode mode) { void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot, Mode mode) { - ATRACE_CALL(); + SFTRACE_CALL(); if (mOutStream) { writeSnapshotToStream(std::move(snapshot)); } else { diff --git a/services/surfaceflinger/Tracing/TransactionRingBuffer.h b/services/surfaceflinger/Tracing/TransactionRingBuffer.h index 7d1d3fd7f2..2b66391853 100644 --- a/services/surfaceflinger/Tracing/TransactionRingBuffer.h +++ b/services/surfaceflinger/Tracing/TransactionRingBuffer.h @@ -19,13 +19,12 @@ #include #include +#include #include #include #include -#include #include #include -#include namespace android { @@ -57,7 +56,7 @@ public: } status_t appendToStream(FileProto& fileProto, std::ofstream& out) { - ATRACE_CALL(); + SFTRACE_CALL(); writeToProto(fileProto); std::string output; if (!fileProto.SerializeToString(&output)) { diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 37543ba171..881bf35b58 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -26,12 +26,10 @@ #include "TransactionCallbackInvoker.h" #include "BackgroundExecutor.h" #include "Utils/FenceUtils.h" -#include "utils/Trace.h" - -#include #include #include +#include #include namespace android { @@ -209,7 +207,7 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { BackgroundExecutor::getInstance().sendCallbacks( {[listenerStatsToSend = std::move(listenerStatsToSend)]() { - ATRACE_NAME("TransactionCallbackInvoker::sendCallbacks"); + SFTRACE_NAME("TransactionCallbackInvoker::sendCallbacks"); for (auto& stats : listenerStatsToSend) { interface_cast(stats.listener) ->onTransactionCompleted(stats); diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index effbfdb896..895e0543e1 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -17,8 +17,8 @@ #include #include #include +#include #include -#include #include #include @@ -42,7 +42,7 @@ void WindowInfosListenerInvoker::addWindowInfosListener(sp BackgroundExecutor::getInstance().sendCallbacks( {[this, listener = std::move(listener), listenerId]() { - ATRACE_NAME("WindowInfosListenerInvoker::addWindowInfosListener"); + SFTRACE_NAME("WindowInfosListenerInvoker::addWindowInfosListener"); sp asBinder = IInterface::asBinder(listener); asBinder->linkToDeath(sp::fromExisting(this)); mWindowInfosListeners.try_emplace(asBinder, @@ -53,7 +53,7 @@ void WindowInfosListenerInvoker::addWindowInfosListener(sp void WindowInfosListenerInvoker::removeWindowInfosListener( const sp& listener) { BackgroundExecutor::getInstance().sendCallbacks({[this, listener]() { - ATRACE_NAME("WindowInfosListenerInvoker::removeWindowInfosListener"); + SFTRACE_NAME("WindowInfosListenerInvoker::removeWindowInfosListener"); sp asBinder = IInterface::asBinder(listener); asBinder->unlinkToDeath(sp::fromExisting(this)); eraseListenerAndAckMessages(asBinder); @@ -62,7 +62,7 @@ void WindowInfosListenerInvoker::removeWindowInfosListener( void WindowInfosListenerInvoker::binderDied(const wp& who) { BackgroundExecutor::getInstance().sendCallbacks({[this, who]() { - ATRACE_NAME("WindowInfosListenerInvoker::binderDied"); + SFTRACE_NAME("WindowInfosListenerInvoker::binderDied"); eraseListenerAndAckMessages(who); }}); } @@ -146,7 +146,7 @@ void WindowInfosListenerInvoker::windowInfosChanged( WindowInfosListenerInvoker::DebugInfo WindowInfosListenerInvoker::getDebugInfo() { DebugInfo result; BackgroundExecutor::getInstance().sendCallbacks({[&, this]() { - ATRACE_NAME("WindowInfosListenerInvoker::getDebugInfo"); + SFTRACE_NAME("WindowInfosListenerInvoker::getDebugInfo"); updateMaxSendDelay(); result = mDebugInfo; result.pendingMessageCount = mUnackedState.size(); @@ -169,7 +169,7 @@ void WindowInfosListenerInvoker::updateMaxSendDelay() { binder::Status WindowInfosListenerInvoker::ackWindowInfosReceived(int64_t vsyncId, int64_t listenerId) { BackgroundExecutor::getInstance().sendCallbacks({[this, vsyncId, listenerId]() { - ATRACE_NAME("WindowInfosListenerInvoker::ackWindowInfosReceived"); + SFTRACE_NAME("WindowInfosListenerInvoker::ackWindowInfosReceived"); auto it = mUnackedState.find(vsyncId); if (it == mUnackedState.end()) { return; diff --git a/services/surfaceflinger/common/include/common/trace.h b/services/surfaceflinger/common/include/common/trace.h new file mode 100644 index 0000000000..c13cdde90d --- /dev/null +++ b/services/surfaceflinger/common/include/common/trace.h @@ -0,0 +1,104 @@ + +/* + * Copyright 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. + */ + +#pragma once + +#include +#include + +#define SFTRACE_ENABLED() ATRACE_ENABLED() +#define SFTRACE_BEGIN(name) ATRACE_BEGIN(name) +#define SFTRACE_END() ATRACE_END() +#define SFTRACE_ASYNC_BEGIN(name, cookie) ATRACE_ASYNC_BEGIN(name, cookie) +#define SFTRACE_ASYNC_END(name, cookie) ATRACE_ASYNC_END(name, cookie) +#define SFTRACE_ASYNC_FOR_TRACK_BEGIN(track_name, name, cookie) \ + ATRACE_ASYNC_FOR_TRACK_BEGIN(track_name, name, cookie) +#define SFTRACE_ASYNC_FOR_TRACK_END(track_name, cookie) \ + ATRACE_ASYNC_FOR_TRACK_END(track_name, cookie) +#define SFTRACE_INSTANT(name) ATRACE_INSTANT(name) +#define SFTRACE_INSTANT_FOR_TRACK(trackName, name) ATRACE_INSTANT_FOR_TRACK(trackName, name) +#define SFTRACE_INT(name, value) ATRACE_INT(name, value) +#define SFTRACE_INT64(name, value) ATRACE_INT64(name, value) + +// SFTRACE_NAME traces from its location until the end of its enclosing scope. +#define _PASTE(x, y) x##y +#define PASTE(x, y) _PASTE(x, y) +#define SFTRACE_NAME(name) ::android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name) + +// SFTRACE_CALL is an ATRACE_NAME that uses the current function name. +#define SFTRACE_CALL() SFTRACE_NAME(__FUNCTION__) + +#define SFTRACE_FORMAT(fmt, ...) \ + TraceUtils::TraceEnder traceEnder = \ + (CC_UNLIKELY(ATRACE_ENABLED()) && \ + (TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__), true), \ + TraceUtils::TraceEnder()) + +#define SFTRACE_FORMAT_INSTANT(fmt, ...) \ + (CC_UNLIKELY(ATRACE_ENABLED()) && (TraceUtils::instantFormat(fmt, ##__VA_ARGS__), true)) + +#define ALOGE_AND_TRACE(fmt, ...) \ + do { \ + ALOGE(fmt, ##__VA_ARGS__); \ + SFTRACE_FORMAT_INSTANT(fmt, ##__VA_ARGS__); \ + } while (false) + +namespace android { + +class TraceUtils { +public: + class TraceEnder { + public: + ~TraceEnder() { ATRACE_END(); } + }; + + static void atraceFormatBegin(const char* fmt, ...) { + const int BUFFER_SIZE = 256; + va_list ap; + char buf[BUFFER_SIZE]; + + va_start(ap, fmt); + vsnprintf(buf, BUFFER_SIZE, fmt, ap); + va_end(ap); + + SFTRACE_BEGIN(buf); + } + + static void instantFormat(const char* fmt, ...) { + const int BUFFER_SIZE = 256; + va_list ap; + char buf[BUFFER_SIZE]; + + va_start(ap, fmt); + vsnprintf(buf, BUFFER_SIZE, fmt, ap); + va_end(ap); + + SFTRACE_INSTANT(buf); + } +}; + +class ScopedTrace { +public: + inline ScopedTrace(uint64_t tag, const char* name) : mTag(tag) { atrace_begin(mTag, name); } + + inline ~ScopedTrace() { atrace_end(mTag); } + +private: + uint64_t mTag; +}; + +} // namespace android -- GitLab From f785b79617382b9ad79c62ac37fa0ca115b7c666 Mon Sep 17 00:00:00 2001 From: Frederick Mayle Date: Fri, 28 Jun 2024 20:04:29 +0000 Subject: [PATCH 066/530] libbinder: export fewer symbols for non-vendor builds We did this for bionic builds only in https://r.android.com/3096103, but it was reverted in https://r.android.com/3148521 because of issues in vendor code. We no longer need to limit this to bionic builds, so I've simplified that part of the change and added an override to disable for vendor builds. Bug: 338458975 Bug: 349657329 Test: boot mokey without seeing a libbinder related crash Change-Id: I6a67b4aea73ce496b2460a084736c472ed5e2430 --- libs/binder/Android.bp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 1abde5cb92..80720b0085 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -267,7 +267,20 @@ cc_defaults { "-Wunused-const-variable", "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION", "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", + // Hide symbols by default and set the BUILDING_LIBBINDER macro so that + // the code knows to export them. + "-fvisibility=hidden", + "-DBUILDING_LIBBINDER", ], + + target: { + vendor: { + // Trimming the exported symbols reveals a bug in vendor code, so + // disable it for the vendor variant for now. http://b/349657329 + // TODO: Fix the issue and remove this override. + cflags: ["-fvisibility=default"], + }, + }, } cc_defaults { -- GitLab From 3bd7ec304869d91886da13d9035768ebf008b1eb Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 28 Jun 2024 22:14:33 +0000 Subject: [PATCH 067/530] Sample from texel centers in downchunk shaders Previously we weren't sampling from texel centers, which caused incorrect pixels to be sampled when using nearest neighbor sampling. Bug: 329464641 Flag: com.android.graphics.surfaceflinger.flags.local_tonemap_screenshots Test: librenderengine_test Test: Screenshots of UltraHDR and HDR video Change-Id: Id1e3ea070368aecb18e5bd1ae7093537c76f6ddf --- libs/renderengine/skia/filters/MouriMap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/renderengine/skia/filters/MouriMap.cpp b/libs/renderengine/skia/filters/MouriMap.cpp index cc25fcc5b9..b45893919c 100644 --- a/libs/renderengine/skia/filters/MouriMap.cpp +++ b/libs/renderengine/skia/filters/MouriMap.cpp @@ -35,7 +35,7 @@ const SkString kCrosstalkAndChunk16x16(R"( float maximum = 0.0; for (int y = 0; y < 16; y++) { for (int x = 0; x < 16; x++) { - float3 linear = toLinearSrgb(bitmap.eval(xy * 16 + vec2(x, y)).rgb) * hdrSdrRatio; + float3 linear = toLinearSrgb(bitmap.eval((xy - 0.5) * 16 + 0.5 + vec2(x, y)).rgb) * hdrSdrRatio; float maxRGB = max(linear.r, max(linear.g, linear.b)); maximum = max(maximum, log2(max(maxRGB, 1.0))); } @@ -49,7 +49,7 @@ const SkString kChunk8x8(R"( float maximum = 0.0; for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { - maximum = max(maximum, bitmap.eval(xy * 8 + vec2(x, y)).r); + maximum = max(maximum, bitmap.eval((xy - 0.5) * 8 + 0.5 + vec2(x, y)).r); } } return float4(float3(maximum), 1.0); -- GitLab From 5aadd249f326b21e5ef6cadfebc15b6a0a016816 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Sat, 29 Jun 2024 01:17:02 +0000 Subject: [PATCH 068/530] Enable single hop screenshots for only threaded re Fixes a deadlock where screenshot requests are blocked on the main thread which inturn is blocked by the screenshot request finishing. Flag: EXEMPT bug fix Bug: 349776684 Test: presubmit Change-Id: Ibf038ad6db3e87c84508d3e101ca1eb144836d7c --- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 1eb865d600..cd3c638d7c 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -354,7 +354,7 @@ void RegionSamplingThread::captureSample() { FenceResult fenceResult; if (FlagManager::getInstance().single_hop_screenshot() && - FlagManager::getInstance().ce_fence_promise()) { + FlagManager::getInstance().ce_fence_promise() && mFlinger.mRenderEngine->isThreaded()) { std::vector> layerFEs; auto displayState = mFlinger.getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layerFEs); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a65ef4e623..fc288c562b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -8193,7 +8193,7 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuil } if (FlagManager::getInstance().single_hop_screenshot() && - FlagManager::getInstance().ce_fence_promise()) { + FlagManager::getInstance().ce_fence_promise() && mRenderEngine->isThreaded()) { std::vector> layerFEs; auto displayState = getSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, layerFEs); @@ -8566,10 +8566,8 @@ ftl::SharedFuture SurfaceFlinger::renderScreenImpl( // to CompositionEngine::present. ftl::SharedFuture presentFuture; if (FlagManager::getInstance().single_hop_screenshot() && - FlagManager::getInstance().ce_fence_promise()) { - presentFuture = mRenderEngine->isThreaded() - ? ftl::yield(present()).share() - : mScheduler->schedule(std::move(present)).share(); + FlagManager::getInstance().ce_fence_promise() && mRenderEngine->isThreaded()) { + presentFuture = ftl::yield(present()).share(); } else { presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share() : ftl::yield(present()).share(); -- GitLab From 5e94634dc57024dcae2d1484758c2a9a7a55d55e Mon Sep 17 00:00:00 2001 From: Tom Murphy Date: Tue, 25 Jun 2024 21:58:26 +0000 Subject: [PATCH 069/530] Fix race condition in extension string creation Change a17429660467548a1bc5f8d435a327500fbe972b introduced a race condition where the notfiy_all is called before the mExtensionString is set. Set mExtensionString before refCond.notify_all(); is called Bug: 345419965 Bug: 346881664 Test: Ran EGL unit tests Change-Id: Ifcb691f9b9769be494e204c97512c3f7fffec60a --- opengl/libs/EGL/egl_display.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp index 5b5afd33c6..b1a287fcec 100644 --- a/opengl/libs/EGL/egl_display.cpp +++ b/opengl/libs/EGL/egl_display.cpp @@ -383,6 +383,14 @@ EGLBoolean egl_display_t::initialize(EGLint* major, EGLint* minor) { // before using cnx->major & cnx->minor if (major != nullptr) *major = cnx->major; if (minor != nullptr) *minor = cnx->minor; + auto mergeExtensionStrings = [](const std::vector& strings) { + std::ostringstream combinedStringStream; + std::copy(strings.begin(), strings.end(), + std::ostream_iterator(combinedStringStream, " ")); + // gBuiltinExtensionString already has a trailing space so is added here + return gBuiltinExtensionString + combinedStringStream.str(); + }; + mExtensionString = mergeExtensionStrings(extensionStrings); } { // scope for refLock @@ -391,14 +399,6 @@ EGLBoolean egl_display_t::initialize(EGLint* major, EGLint* minor) { refCond.notify_all(); } - auto mergeExtensionStrings = [](const std::vector& strings) { - std::ostringstream combinedStringStream; - std::copy(strings.begin(), strings.end(), - std::ostream_iterator(combinedStringStream, " ")); - // gBuiltinExtensionString already has a trailing space so is added here - return gBuiltinExtensionString + combinedStringStream.str(); - }; - mExtensionString = mergeExtensionStrings(extensionStrings); return EGL_TRUE; } -- GitLab From 4e916b04bb67bfbab3032a916261fc5475ed7695 Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Tue, 23 Apr 2024 19:05:38 -0500 Subject: [PATCH 070/530] Fix transaction sanitization Bug: 336648041 Test: CredentialsTest (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:04e41761914c3c3aaca965103be3679b7a7af76f) Merged-In: I53894d014bfabc9c958a6f533d7e3b3a6dcd0a34 Change-Id: I53894d014bfabc9c958a6f533d7e3b3a6dcd0a34 24D1-dev is based on 24Q2-release. Therefore, we merged this CL to 24D1-dev. --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- .../surfaceflinger/tests/Credentials_test.cpp | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 486112ae4d..a7ea8a0438 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5050,7 +5050,7 @@ status_t SurfaceFlinger::setTransactionState( const int originPid = ipc->getCallingPid(); const int originUid = ipc->getCallingUid(); uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid); - for (auto composerState : states) { + for (auto& composerState : states) { composerState.state.sanitize(permissions); } diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 822ac4d99f..51fc868342 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -389,8 +389,13 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { .apply(); } - // Called from non privileged process - Transaction().setTrustedOverlay(surfaceControl, true); + // Attempt to set a trusted overlay from a non-privileged process. This should fail silently. + { + UIDFaker f{AID_BIN}; + Transaction().setTrustedOverlay(surfaceControl, true).apply(/*synchronous=*/true); + } + + // Verify that the layer was not made a trusted overlay. { UIDFaker f(AID_SYSTEM); auto windowIsPresentAndNotTrusted = [&](const std::vector& windowInfos) { @@ -401,12 +406,14 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { } return !foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY); }; - windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndNotTrusted); + ASSERT_TRUE( + windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndNotTrusted)); } + // Verify that privileged processes are able to set trusted overlays. { UIDFaker f(AID_SYSTEM); - Transaction().setTrustedOverlay(surfaceControl, true); + Transaction().setTrustedOverlay(surfaceControl, true).apply(/*synchronous=*/true); auto windowIsPresentAndTrusted = [&](const std::vector& windowInfos) { auto foundWindowInfo = WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos); @@ -415,7 +422,8 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { } return foundWindowInfo->inputConfig.test(WindowInfo::InputConfig::TRUSTED_OVERLAY); }; - windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndTrusted); + ASSERT_TRUE( + windowInfosListenerUtils.waitForWindowInfosPredicate(windowIsPresentAndTrusted)); } } -- GitLab From 818a2257151b862f1e1378dcc53a8601753f15fa Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Mon, 24 Jun 2024 14:48:14 +0100 Subject: [PATCH 071/530] Use android.hardware.vibrator NDK backend Update vibrator HAL dependency to use the NDK backend. Bug: 349595412 Test: libvibratorservice_test Flag: EXEMPT mechanical refactor Change-Id: I1eee7ea86d0535f93ed09d5295b3efbb4d5a1870 --- services/vibratorservice/Android.bp | 14 +- .../vibratorservice/VibratorHalController.cpp | 26 +- .../vibratorservice/VibratorHalWrapper.cpp | 124 +++---- .../VibratorManagerHalController.cpp | 15 +- .../VibratorManagerHalWrapper.cpp | 30 +- .../vibratorservice/benchmarks/Android.bp | 4 +- .../VibratorHalControllerBenchmarks.cpp | 21 +- .../vibratorservice/VibratorHalController.h | 2 +- .../vibratorservice/VibratorHalWrapper.h | 204 ++++++----- .../VibratorManagerHalController.h | 2 +- .../VibratorManagerHalWrapper.h | 29 +- services/vibratorservice/test/Android.bp | 4 +- .../test/VibratorHalControllerTest.cpp | 40 +-- .../test/VibratorHalWrapperAidlTest.cpp | 327 +++++++----------- .../test/VibratorHalWrapperHidlV1_0Test.cpp | 17 +- .../test/VibratorHalWrapperHidlV1_1Test.cpp | 7 +- .../test/VibratorHalWrapperHidlV1_2Test.cpp | 7 +- .../test/VibratorHalWrapperHidlV1_3Test.cpp | 9 +- .../test/VibratorManagerHalControllerTest.cpp | 7 + .../VibratorManagerHalWrapperAidlTest.cpp | 205 ++++------- .../VibratorManagerHalWrapperLegacyTest.cpp | 25 +- services/vibratorservice/test/test_mocks.h | 169 +++++++++ services/vibratorservice/test/test_utils.h | 26 +- 23 files changed, 680 insertions(+), 634 deletions(-) create mode 100644 services/vibratorservice/test/test_mocks.h diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp index 2002bdf628..503587f8ac 100644 --- a/services/vibratorservice/Android.bp +++ b/services/vibratorservice/Android.bp @@ -33,19 +33,19 @@ cc_library_shared { ], aidl: { - local_include_dirs: ["include"], - include_dirs: [ - "hardware/interfaces/vibrator/aidl/android/hardware/vibrator", - ], - export_aidl_headers: true + local_include_dirs: ["include"], + include_dirs: [ + "hardware/interfaces/vibrator/aidl/android/hardware/vibrator", + ], + export_aidl_headers: true, }, shared_libs: [ - "libbinder", + "libbinder_ndk", "libhidlbase", "liblog", "libutils", - "android.hardware.vibrator-V2-cpp", + "android.hardware.vibrator-V2-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/services/vibratorservice/VibratorHalController.cpp b/services/vibratorservice/VibratorHalController.cpp index c1795f5c32..283a5f0301 100644 --- a/services/vibratorservice/VibratorHalController.cpp +++ b/services/vibratorservice/VibratorHalController.cpp @@ -16,9 +16,9 @@ #define LOG_TAG "VibratorHalController" +#include +#include #include -#include -#include #include #include @@ -27,10 +27,10 @@ #include #include -using android::hardware::vibrator::CompositeEffect; -using android::hardware::vibrator::CompositePrimitive; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; using std::chrono::milliseconds; @@ -38,7 +38,7 @@ namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; namespace V1_3 = android::hardware::vibrator::V1_3; -namespace Aidl = android::hardware::vibrator; +namespace Aidl = aidl::android::hardware::vibrator; namespace android { @@ -53,10 +53,14 @@ std::shared_ptr connectHal(std::shared_ptr schedu return nullptr; } - sp aidlHal = waitForVintfService(); - if (aidlHal) { - ALOGV("Successfully connected to Vibrator HAL AIDL service."); - return std::make_shared(std::move(scheduler), aidlHal); + auto serviceName = std::string(Aidl::IVibrator::descriptor) + "/default"; + if (AServiceManager_isDeclared(serviceName.c_str())) { + std::shared_ptr hal = Aidl::IVibrator::fromBinder( + ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str()))); + if (hal) { + ALOGV("Successfully connected to Vibrator HAL AIDL service."); + return std::make_shared(std::move(scheduler), std::move(hal)); + } } sp halV1_0 = V1_0::IVibrator::getService(); diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp index f10ba44d74..abe78f0ef0 100644 --- a/services/vibratorservice/VibratorHalWrapper.cpp +++ b/services/vibratorservice/VibratorHalWrapper.cpp @@ -16,8 +16,8 @@ #define LOG_TAG "VibratorHalWrapper" +#include #include -#include #include #include @@ -26,12 +26,12 @@ #include #include -using android::hardware::vibrator::Braking; -using android::hardware::vibrator::CompositeEffect; -using android::hardware::vibrator::CompositePrimitive; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; -using android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::Braking; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::PrimitivePwle; using std::chrono::milliseconds; @@ -39,7 +39,7 @@ namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; namespace V1_3 = android::hardware::vibrator::V1_3; -namespace Aidl = android::hardware::vibrator; +namespace Aidl = aidl::android::hardware::vibrator; namespace android { @@ -200,7 +200,7 @@ HalResult> HalWrapper::getMaxAmplitudesInternal() { // ------------------------------------------------------------------------------------------------- HalResult AidlHalWrapper::ping() { - return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); + return HalResultFactory::fromStatus(AIBinder_ping(getHal()->asBinder().get())); } void AidlHalWrapper::tryReconnect() { @@ -208,7 +208,7 @@ void AidlHalWrapper::tryReconnect() { if (!result.isOk()) { return; } - sp newHandle = result.value(); + std::shared_ptr newHandle = result.value(); if (newHandle) { std::lock_guard lock(mHandleMutex); mHandle = std::move(newHandle); @@ -220,7 +220,8 @@ HalResult AidlHalWrapper::on(milliseconds timeout, HalResult capabilities = getCapabilities(); bool supportsCallback = capabilities.isOk() && static_cast(capabilities.value() & Capabilities::ON_CALLBACK); - auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; + auto cb = supportsCallback ? ndk::SharedRefBase::make(completionCallback) + : nullptr; auto ret = HalResultFactory::fromStatus(getHal()->on(timeout.count(), cb)); if (!supportsCallback && ret.isOk()) { @@ -255,13 +256,14 @@ HalResult AidlHalWrapper::performEffect( HalResult capabilities = getCapabilities(); bool supportsCallback = capabilities.isOk() && static_cast(capabilities.value() & Capabilities::PERFORM_CALLBACK); - auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; + auto cb = supportsCallback ? ndk::SharedRefBase::make(completionCallback) + : nullptr; int32_t lengthMs; - auto result = getHal()->perform(effect, strength, cb, &lengthMs); + auto status = getHal()->perform(effect, strength, cb, &lengthMs); milliseconds length = milliseconds(lengthMs); - auto ret = HalResultFactory::fromStatus(result, length); + auto ret = HalResultFactory::fromStatus(std::move(status), length); if (!supportsCallback && ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } @@ -273,7 +275,7 @@ HalResult AidlHalWrapper::performComposedEffect( const std::vector& primitives, const std::function& completionCallback) { // This method should always support callbacks, so no need to double check. - auto cb = new HalCallbackWrapper(completionCallback); + auto cb = ndk::SharedRefBase::make(completionCallback); auto durations = getPrimitiveDurations().valueOr({}); milliseconds duration(0); @@ -294,40 +296,40 @@ HalResult AidlHalWrapper::performComposedEffect( HalResult AidlHalWrapper::performPwleEffect(const std::vector& primitives, const std::function& completionCallback) { // This method should always support callbacks, so no need to double check. - auto cb = new HalCallbackWrapper(completionCallback); + auto cb = ndk::SharedRefBase::make(completionCallback); return HalResultFactory::fromStatus(getHal()->composePwle(primitives, cb)); } HalResult AidlHalWrapper::getCapabilitiesInternal() { - int32_t capabilities = 0; - auto result = getHal()->getCapabilities(&capabilities); - return HalResultFactory::fromStatus(result, - static_cast(capabilities)); + int32_t cap = 0; + auto status = getHal()->getCapabilities(&cap); + auto capabilities = static_cast(cap); + return HalResultFactory::fromStatus(std::move(status), capabilities); } HalResult> AidlHalWrapper::getSupportedEffectsInternal() { std::vector supportedEffects; - auto result = getHal()->getSupportedEffects(&supportedEffects); - return HalResultFactory::fromStatus>(result, supportedEffects); + auto status = getHal()->getSupportedEffects(&supportedEffects); + return HalResultFactory::fromStatus>(std::move(status), supportedEffects); } HalResult> AidlHalWrapper::getSupportedBrakingInternal() { std::vector supportedBraking; - auto result = getHal()->getSupportedBraking(&supportedBraking); - return HalResultFactory::fromStatus>(result, supportedBraking); + auto status = getHal()->getSupportedBraking(&supportedBraking); + return HalResultFactory::fromStatus>(std::move(status), supportedBraking); } HalResult> AidlHalWrapper::getSupportedPrimitivesInternal() { std::vector supportedPrimitives; - auto result = getHal()->getSupportedPrimitives(&supportedPrimitives); - return HalResultFactory::fromStatus>(result, + auto status = getHal()->getSupportedPrimitives(&supportedPrimitives); + return HalResultFactory::fromStatus>(std::move(status), supportedPrimitives); } HalResult> AidlHalWrapper::getPrimitiveDurationsInternal( const std::vector& supportedPrimitives) { std::vector durations; - constexpr auto primitiveRange = enum_range(); + constexpr auto primitiveRange = ndk::enum_range(); constexpr auto primitiveCount = std::distance(primitiveRange.begin(), primitiveRange.end()); durations.resize(primitiveCount); @@ -340,8 +342,8 @@ HalResult> AidlHalWrapper::getPrimitiveDurationsIntern continue; } int32_t duration = 0; - auto result = getHal()->getPrimitiveDuration(primitive, &duration); - auto halResult = HalResultFactory::fromStatus(result, duration); + auto status = getHal()->getPrimitiveDuration(primitive, &duration); + auto halResult = HalResultFactory::fromStatus(std::move(status), duration); if (halResult.isUnsupported()) { // Should not happen, supported primitives should always support requesting duration. ALOGE("Supported primitive %zu returned unsupported for getPrimitiveDuration", @@ -349,7 +351,7 @@ HalResult> AidlHalWrapper::getPrimitiveDurationsIntern } if (halResult.isFailed()) { // Fail entire request if one request has failed. - return HalResult>::failed(result.toString8().c_str()); + return HalResult>::failed(status.getMessage()); } durations[primitiveIdx] = milliseconds(duration); } @@ -359,59 +361,59 @@ HalResult> AidlHalWrapper::getPrimitiveDurationsIntern HalResult AidlHalWrapper::getPrimitiveDelayMaxInternal() { int32_t delay = 0; - auto result = getHal()->getCompositionDelayMax(&delay); - return HalResultFactory::fromStatus(result, milliseconds(delay)); + auto status = getHal()->getCompositionDelayMax(&delay); + return HalResultFactory::fromStatus(std::move(status), milliseconds(delay)); } HalResult AidlHalWrapper::getPrimitiveDurationMaxInternal() { int32_t delay = 0; - auto result = getHal()->getPwlePrimitiveDurationMax(&delay); - return HalResultFactory::fromStatus(result, milliseconds(delay)); + auto status = getHal()->getPwlePrimitiveDurationMax(&delay); + return HalResultFactory::fromStatus(std::move(status), milliseconds(delay)); } HalResult AidlHalWrapper::getCompositionSizeMaxInternal() { int32_t size = 0; - auto result = getHal()->getCompositionSizeMax(&size); - return HalResultFactory::fromStatus(result, size); + auto status = getHal()->getCompositionSizeMax(&size); + return HalResultFactory::fromStatus(std::move(status), size); } HalResult AidlHalWrapper::getPwleSizeMaxInternal() { int32_t size = 0; - auto result = getHal()->getPwleCompositionSizeMax(&size); - return HalResultFactory::fromStatus(result, size); + auto status = getHal()->getPwleCompositionSizeMax(&size); + return HalResultFactory::fromStatus(std::move(status), size); } HalResult AidlHalWrapper::getMinFrequencyInternal() { float minFrequency = 0; - auto result = getHal()->getFrequencyMinimum(&minFrequency); - return HalResultFactory::fromStatus(result, minFrequency); + auto status = getHal()->getFrequencyMinimum(&minFrequency); + return HalResultFactory::fromStatus(std::move(status), minFrequency); } HalResult AidlHalWrapper::getResonantFrequencyInternal() { float f0 = 0; - auto result = getHal()->getResonantFrequency(&f0); - return HalResultFactory::fromStatus(result, f0); + auto status = getHal()->getResonantFrequency(&f0); + return HalResultFactory::fromStatus(std::move(status), f0); } HalResult AidlHalWrapper::getFrequencyResolutionInternal() { float frequencyResolution = 0; - auto result = getHal()->getFrequencyResolution(&frequencyResolution); - return HalResultFactory::fromStatus(result, frequencyResolution); + auto status = getHal()->getFrequencyResolution(&frequencyResolution); + return HalResultFactory::fromStatus(std::move(status), frequencyResolution); } HalResult AidlHalWrapper::getQFactorInternal() { float qFactor = 0; - auto result = getHal()->getQFactor(&qFactor); - return HalResultFactory::fromStatus(result, qFactor); + auto status = getHal()->getQFactor(&qFactor); + return HalResultFactory::fromStatus(std::move(status), qFactor); } HalResult> AidlHalWrapper::getMaxAmplitudesInternal() { std::vector amplitudes; - auto result = getHal()->getBandwidthAmplitudeMap(&litudes); - return HalResultFactory::fromStatus>(result, amplitudes); + auto status = getHal()->getBandwidthAmplitudeMap(&litudes); + return HalResultFactory::fromStatus>(std::move(status), amplitudes); } -sp AidlHalWrapper::getHal() { +std::shared_ptr AidlHalWrapper::getHal() { std::lock_guard lock(mHandleMutex); return mHandle; } @@ -420,8 +422,7 @@ sp AidlHalWrapper::getHal() { template HalResult HidlHalWrapper::ping() { - auto result = getHal()->ping(); - return HalResultFactory::fromReturn(result); + return HalResultFactory::fromReturn(getHal()->ping()); } template @@ -436,8 +437,8 @@ void HidlHalWrapper::tryReconnect() { template HalResult HidlHalWrapper::on(milliseconds timeout, const std::function& completionCallback) { - auto result = getHal()->on(timeout.count()); - auto ret = HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + auto status = getHal()->on(timeout.count()); + auto ret = HalResultFactory::fromStatus(status.withDefault(V1_0::Status::UNKNOWN_ERROR)); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, timeout); } @@ -446,15 +447,15 @@ HalResult HidlHalWrapper::on(milliseconds timeout, template HalResult HidlHalWrapper::off() { - auto result = getHal()->off(); - return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + auto status = getHal()->off(); + return HalResultFactory::fromStatus(status.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template HalResult HidlHalWrapper::setAmplitude(float amplitude) { uint8_t amp = static_cast(amplitude * std::numeric_limits::max()); - auto result = getHal()->setAmplitude(amp); - return HalResultFactory::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR)); + auto status = getHal()->setAmplitude(amp); + return HalResultFactory::fromStatus(status.withDefault(V1_0::Status::UNKNOWN_ERROR)); } template @@ -480,7 +481,7 @@ HalResult HidlHalWrapper::getCapabilitiesInternal() { hardware::Return result = getHal()->supportsAmplitudeControl(); Capabilities capabilities = result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE; - return HalResultFactory::fromReturn(result, capabilities); + return HalResultFactory::fromReturn(std::move(result), capabilities); } template @@ -499,7 +500,7 @@ HalResult HidlHalWrapper::performInternal( auto result = std::invoke(performFn, handle, effect, effectStrength, effectCallback); milliseconds length = milliseconds(lengthMs); - auto ret = HalResultFactory::fromReturn(result, status, length); + auto ret = HalResultFactory::fromReturn(std::move(result), status, length); if (ret.isOk()) { mCallbackScheduler->schedule(completionCallback, length); } @@ -604,7 +605,7 @@ HalResult HidlHalWrapperV1_3::getCapabilitiesInternal() { sp hal = getHal(); auto amplitudeResult = hal->supportsAmplitudeControl(); if (!amplitudeResult.isOk()) { - return HalResultFactory::fromReturn(amplitudeResult, capabilities); + return HalResultFactory::fromReturn(std::move(amplitudeResult), capabilities); } auto externalControlResult = hal->supportsExternalControl(); @@ -619,7 +620,8 @@ HalResult HidlHalWrapperV1_3::getCapabilitiesInternal() { } } - return HalResultFactory::fromReturn(externalControlResult, capabilities); + return HalResultFactory::fromReturn(std::move(externalControlResult), + capabilities); } // ------------------------------------------------------------------------------------------------- diff --git a/services/vibratorservice/VibratorManagerHalController.cpp b/services/vibratorservice/VibratorManagerHalController.cpp index aa5b7fc86f..ba35d15bf2 100644 --- a/services/vibratorservice/VibratorManagerHalController.cpp +++ b/services/vibratorservice/VibratorManagerHalController.cpp @@ -20,7 +20,7 @@ #include -namespace Aidl = android::hardware::vibrator; +namespace Aidl = aidl::android::hardware::vibrator; namespace android { @@ -29,10 +29,15 @@ namespace vibrator { std::shared_ptr connectManagerHal(std::shared_ptr scheduler) { static bool gHalExists = true; if (gHalExists) { - sp hal = waitForVintfService(); - if (hal) { - ALOGV("Successfully connected to VibratorManager HAL AIDL service."); - return std::make_shared(std::move(scheduler), hal); + auto serviceName = std::string(Aidl::IVibratorManager::descriptor) + "/default"; + if (AServiceManager_isDeclared(serviceName.c_str())) { + std::shared_ptr hal = Aidl::IVibratorManager::fromBinder( + ndk::SpAIBinder(AServiceManager_checkService(serviceName.c_str()))); + if (hal) { + ALOGV("Successfully connected to VibratorManager HAL AIDL service."); + return std::make_shared(std::move(scheduler), + std::move(hal)); + } } } diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp index 13412667e0..93ec781b21 100644 --- a/services/vibratorservice/VibratorManagerHalWrapper.cpp +++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp @@ -20,7 +20,7 @@ #include -namespace Aidl = android::hardware::vibrator; +namespace Aidl = aidl::android::hardware::vibrator; namespace android { @@ -75,10 +75,11 @@ HalResult LegacyManagerHalWrapper::cancelSynced() { std::shared_ptr AidlManagerHalWrapper::connectToVibrator( int32_t vibratorId, std::shared_ptr callbackScheduler) { - std::function>()> reconnectFn = [=, this]() { - sp vibrator; - auto result = this->getHal()->getVibrator(vibratorId, &vibrator); - return HalResultFactory::fromStatus>(result, vibrator); + std::function>()> reconnectFn = [=, this]() { + std::shared_ptr vibrator; + auto status = this->getHal()->getVibrator(vibratorId, &vibrator); + return HalResultFactory::fromStatus>(std::move(status), + vibrator); }; auto result = reconnectFn(); if (!result.isOk()) { @@ -93,11 +94,13 @@ std::shared_ptr AidlManagerHalWrapper::connectToVibrator( } HalResult AidlManagerHalWrapper::ping() { - return HalResultFactory::fromStatus(IInterface::asBinder(getHal())->pingBinder()); + return HalResultFactory::fromStatus(AIBinder_ping(getHal()->asBinder().get())); } void AidlManagerHalWrapper::tryReconnect() { - sp newHandle = checkVintfService(); + auto aidlServiceName = std::string(Aidl::IVibratorManager::descriptor) + "/default"; + std::shared_ptr newHandle = Aidl::IVibratorManager::fromBinder( + ndk::SpAIBinder(AServiceManager_checkService(aidlServiceName.c_str()))); if (newHandle) { std::lock_guard lock(mHandleMutex); mHandle = std::move(newHandle); @@ -111,9 +114,9 @@ HalResult AidlManagerHalWrapper::getCapabilities() { return HalResult::ok(*mCapabilities); } int32_t cap = 0; - auto result = getHal()->getCapabilities(&cap); + auto status = getHal()->getCapabilities(&cap); auto capabilities = static_cast(cap); - auto ret = HalResultFactory::fromStatus(result, capabilities); + auto ret = HalResultFactory::fromStatus(std::move(status), capabilities); if (ret.isOk()) { // Cache copy of returned value. mCapabilities.emplace(ret.value()); @@ -128,8 +131,8 @@ HalResult> AidlManagerHalWrapper::getVibratorIds() { return HalResult>::ok(*mVibratorIds); } std::vector ids; - auto result = getHal()->getVibratorIds(&ids); - auto ret = HalResultFactory::fromStatus>(result, ids); + auto status = getHal()->getVibratorIds(&ids); + auto ret = HalResultFactory::fromStatus>(std::move(status), ids); if (ret.isOk()) { // Cache copy of returned value and the individual controllers. mVibratorIds.emplace(ret.value()); @@ -178,7 +181,8 @@ HalResult AidlManagerHalWrapper::triggerSynced( HalResult capabilities = getCapabilities(); bool supportsCallback = capabilities.isOk() && static_cast(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK); - auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr; + auto cb = supportsCallback ? ndk::SharedRefBase::make(completionCallback) + : nullptr; return HalResultFactory::fromStatus(getHal()->triggerSynced(cb)); } @@ -196,7 +200,7 @@ HalResult AidlManagerHalWrapper::cancelSynced() { return ret; } -sp AidlManagerHalWrapper::getHal() { +std::shared_ptr AidlManagerHalWrapper::getHal() { std::lock_guard lock(mHandleMutex); return mHandle; } diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp index 5437995899..5bb8cebe49 100644 --- a/services/vibratorservice/benchmarks/Android.bp +++ b/services/vibratorservice/benchmarks/Android.bp @@ -28,12 +28,12 @@ cc_benchmark { "VibratorHalControllerBenchmarks.cpp", ], shared_libs: [ - "libbinder", + "libbinder_ndk", "libhidlbase", "liblog", "libutils", "libvibratorservice", - "android.hardware.vibrator-V2-cpp", + "android.hardware.vibrator-V2-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp b/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp index 9b30337885..5c7c9f46c1 100644 --- a/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp +++ b/services/vibratorservice/benchmarks/VibratorHalControllerBenchmarks.cpp @@ -16,16 +16,15 @@ #define LOG_TAG "VibratorHalControllerBenchmarks" +#include #include -#include #include #include -using ::android::enum_range; -using ::android::hardware::vibrator::CompositeEffect; -using ::android::hardware::vibrator::CompositePrimitive; -using ::android::hardware::vibrator::Effect; -using ::android::hardware::vibrator::EffectStrength; +using ::aidl::android::hardware::vibrator::CompositeEffect; +using ::aidl::android::hardware::vibrator::CompositePrimitive; +using ::aidl::android::hardware::vibrator::Effect; +using ::aidl::android::hardware::vibrator::EffectStrength; using ::benchmark::Counter; using ::benchmark::Fixture; using ::benchmark::kMicrosecond; @@ -115,8 +114,8 @@ private: class VibratorBench : public Fixture { public: void SetUp(State& /*state*/) override { - android::ProcessState::self()->setThreadPoolMaxThreadCount(1); - android::ProcessState::self()->startThreadPool(); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); mController.init(); } @@ -388,11 +387,11 @@ public: return; } - for (const auto& effect : enum_range()) { + for (const auto& effect : ndk::enum_range()) { if (std::find(supported.begin(), supported.end(), effect) == supported.end()) { continue; } - for (const auto& strength : enum_range()) { + for (const auto& strength : ndk::enum_range()) { b->Args({static_cast(effect), static_cast(strength)}); } } @@ -533,7 +532,7 @@ public: return; } - for (const auto& primitive : enum_range()) { + for (const auto& primitive : ndk::enum_range()) { if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) { continue; } diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h index f97442ddee..a1cb3fad35 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h @@ -17,8 +17,8 @@ #ifndef ANDROID_OS_VIBRATORHALCONTROLLER_H #define ANDROID_OS_VIBRATORHALCONTROLLER_H +#include #include -#include #include #include diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h index 39c4eb441e..d4f7f1d387 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h @@ -17,10 +17,12 @@ #ifndef ANDROID_OS_VIBRATORHALWRAPPER_H #define ANDROID_OS_VIBRATORHALWRAPPER_H +#include +#include + #include +#include #include -#include -#include #include #include @@ -98,43 +100,49 @@ private: class HalResultFactory { public: template - static HalResult fromStatus(binder::Status status, T data) { - return status.isOk() ? HalResult::ok(data) : fromFailedStatus(status); + static HalResult fromStatus(ndk::ScopedAStatus&& status, T data) { + return status.isOk() ? HalResult::ok(std::move(data)) + : fromFailedStatus(std::move(status)); } template - static HalResult fromStatus(hardware::vibrator::V1_0::Status status, T data) { - return (status == hardware::vibrator::V1_0::Status::OK) ? HalResult::ok(data) - : fromFailedStatus(status); + static HalResult fromStatus(hardware::vibrator::V1_0::Status&& status, T data) { + return (status == hardware::vibrator::V1_0::Status::OK) + ? HalResult::ok(std::move(data)) + : fromFailedStatus(std::move(status)); } template - static HalResult fromReturn(hardware::Return& ret, T data) { - return ret.isOk() ? HalResult::ok(data) : fromFailedReturn(ret); + static HalResult fromReturn(hardware::Return&& ret, T data) { + return ret.isOk() ? HalResult::ok(std::move(data)) + : fromFailedReturn(std::move(ret)); } template - static HalResult fromReturn(hardware::Return& ret, + static HalResult fromReturn(hardware::Return&& ret, hardware::vibrator::V1_0::Status status, T data) { - return ret.isOk() ? fromStatus(status, data) : fromFailedReturn(ret); + return ret.isOk() ? fromStatus(std::move(status), std::move(data)) + : fromFailedReturn(std::move(ret)); } static HalResult fromStatus(status_t status) { - return (status == android::OK) ? HalResult::ok() : fromFailedStatus(status); + return (status == android::OK) ? HalResult::ok() + : fromFailedStatus(std::move(status)); } - static HalResult fromStatus(binder::Status status) { - return status.isOk() ? HalResult::ok() : fromFailedStatus(status); + static HalResult fromStatus(ndk::ScopedAStatus&& status) { + return status.isOk() ? HalResult::ok() : fromFailedStatus(std::move(status)); } - static HalResult fromStatus(hardware::vibrator::V1_0::Status status) { - return (status == hardware::vibrator::V1_0::Status::OK) ? HalResult::ok() - : fromFailedStatus(status); + static HalResult fromStatus(hardware::vibrator::V1_0::Status&& status) { + return (status == hardware::vibrator::V1_0::Status::OK) + ? HalResult::ok() + : fromFailedStatus(std::move(status)); } template - static HalResult fromReturn(hardware::Return& ret) { - return ret.isOk() ? HalResult::ok() : fromFailedReturn(ret); + static HalResult fromReturn(hardware::Return&& ret) { + return ret.isOk() ? HalResult::ok() : fromFailedReturn(std::move(ret)); } private: @@ -146,21 +154,21 @@ private: } template - static HalResult fromFailedStatus(binder::Status status) { - if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION || - status.transactionError() == android::UNKNOWN_TRANSACTION) { - // UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this is - // the same as the operation being unsupported by this HAL. Should not retry. + static HalResult fromFailedStatus(ndk::ScopedAStatus&& status) { + if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION || + status.getStatus() == STATUS_UNKNOWN_TRANSACTION) { + // STATUS_UNKNOWN_TRANSACTION means the HAL implementation is an older version, so this + // is the same as the operation being unsupported by this HAL. Should not retry. return HalResult::unsupported(); } - if (status.exceptionCode() == binder::Status::EX_TRANSACTION_FAILED) { - return HalResult::transactionFailed(status.toString8().c_str()); + if (status.getExceptionCode() == EX_TRANSACTION_FAILED) { + return HalResult::transactionFailed(status.getMessage()); } - return HalResult::failed(status.toString8().c_str()); + return HalResult::failed(status.getMessage()); } template - static HalResult fromFailedStatus(hardware::vibrator::V1_0::Status status) { + static HalResult fromFailedStatus(hardware::vibrator::V1_0::Status&& status) { switch (status) { case hardware::vibrator::V1_0::Status::UNSUPPORTED_OPERATION: return HalResult::unsupported(); @@ -171,7 +179,7 @@ private: } template - static HalResult fromFailedReturn(hardware::Return& ret) { + static HalResult fromFailedReturn(hardware::Return&& ret) { return ret.isDeadObject() ? HalResult::transactionFailed(ret.description().c_str()) : HalResult::failed(ret.description().c_str()); } @@ -179,14 +187,14 @@ private: // ------------------------------------------------------------------------------------------------- -class HalCallbackWrapper : public hardware::vibrator::BnVibratorCallback { +class HalCallbackWrapper : public aidl::android::hardware::vibrator::BnVibratorCallback { public: HalCallbackWrapper(std::function completionCallback) : mCompletionCallback(completionCallback) {} - binder::Status onComplete() override { + ndk::ScopedAStatus onComplete() override { mCompletionCallback(); - return binder::Status::ok(); + return ndk::ScopedAStatus::ok(); } private: @@ -198,14 +206,15 @@ private: // Vibrator HAL capabilities. enum class Capabilities : int32_t { NONE = 0, - ON_CALLBACK = hardware::vibrator::IVibrator::CAP_ON_CALLBACK, - PERFORM_CALLBACK = hardware::vibrator::IVibrator::CAP_PERFORM_CALLBACK, - AMPLITUDE_CONTROL = hardware::vibrator::IVibrator::CAP_AMPLITUDE_CONTROL, - EXTERNAL_CONTROL = hardware::vibrator::IVibrator::CAP_EXTERNAL_CONTROL, - EXTERNAL_AMPLITUDE_CONTROL = hardware::vibrator::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL, - COMPOSE_EFFECTS = hardware::vibrator::IVibrator::CAP_COMPOSE_EFFECTS, - COMPOSE_PWLE_EFFECTS = hardware::vibrator::IVibrator::CAP_COMPOSE_PWLE_EFFECTS, - ALWAYS_ON_CONTROL = hardware::vibrator::IVibrator::CAP_ALWAYS_ON_CONTROL, + ON_CALLBACK = aidl::android::hardware::vibrator::IVibrator::CAP_ON_CALLBACK, + PERFORM_CALLBACK = aidl::android::hardware::vibrator::IVibrator::CAP_PERFORM_CALLBACK, + AMPLITUDE_CONTROL = aidl::android::hardware::vibrator::IVibrator::CAP_AMPLITUDE_CONTROL, + EXTERNAL_CONTROL = aidl::android::hardware::vibrator::IVibrator::CAP_EXTERNAL_CONTROL, + EXTERNAL_AMPLITUDE_CONTROL = + aidl::android::hardware::vibrator::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL, + COMPOSE_EFFECTS = aidl::android::hardware::vibrator::IVibrator::CAP_COMPOSE_EFFECTS, + COMPOSE_PWLE_EFFECTS = aidl::android::hardware::vibrator::IVibrator::CAP_COMPOSE_PWLE_EFFECTS, + ALWAYS_ON_CONTROL = aidl::android::hardware::vibrator::IVibrator::CAP_ALWAYS_ON_CONTROL, }; inline Capabilities operator|(Capabilities lhs, Capabilities rhs) { @@ -230,10 +239,15 @@ inline Capabilities& operator&=(Capabilities& lhs, Capabilities rhs) { class Info { public: + using Effect = aidl::android::hardware::vibrator::Effect; + using EffectStrength = aidl::android::hardware::vibrator::EffectStrength; + using CompositePrimitive = aidl::android::hardware::vibrator::CompositePrimitive; + using Braking = aidl::android::hardware::vibrator::Braking; + const HalResult capabilities; - const HalResult> supportedEffects; - const HalResult> supportedBraking; - const HalResult> supportedPrimitives; + const HalResult> supportedEffects; + const HalResult> supportedBraking; + const HalResult> supportedPrimitives; const HalResult> primitiveDurations; const HalResult primitiveDelayMax; const HalResult pwlePrimitiveDurationMax; @@ -247,12 +261,9 @@ public: void logFailures() const { logFailure(capabilities, "getCapabilities"); - logFailure>(supportedEffects, - "getSupportedEffects"); - logFailure>(supportedBraking, - "getSupportedBraking"); - logFailure>(supportedPrimitives, - "getSupportedPrimitives"); + logFailure>(supportedEffects, "getSupportedEffects"); + logFailure>(supportedBraking, "getSupportedBraking"); + logFailure>(supportedPrimitives, "getSupportedPrimitives"); logFailure>(primitiveDurations, "getPrimitiveDuration"); logFailure(primitiveDelayMax, "getPrimitiveDelayMax"); @@ -309,12 +320,12 @@ private: // Create a transaction failed results as default so we can retry on the first time we get them. static const constexpr char* MSG = "never loaded"; HalResult mCapabilities = HalResult::transactionFailed(MSG); - HalResult> mSupportedEffects = - HalResult>::transactionFailed(MSG); - HalResult> mSupportedBraking = - HalResult>::transactionFailed(MSG); - HalResult> mSupportedPrimitives = - HalResult>::transactionFailed(MSG); + HalResult> mSupportedEffects = + HalResult>::transactionFailed(MSG); + HalResult> mSupportedBraking = + HalResult>::transactionFailed(MSG); + HalResult> mSupportedPrimitives = + HalResult>::transactionFailed(MSG); HalResult> mPrimitiveDurations = HalResult>::transactionFailed(MSG); HalResult mPrimitiveDelayMax = @@ -336,6 +347,13 @@ private: // Wrapper for Vibrator HAL handlers. class HalWrapper { public: + using Effect = aidl::android::hardware::vibrator::Effect; + using EffectStrength = aidl::android::hardware::vibrator::EffectStrength; + using CompositePrimitive = aidl::android::hardware::vibrator::CompositePrimitive; + using CompositeEffect = aidl::android::hardware::vibrator::CompositeEffect; + using Braking = aidl::android::hardware::vibrator::Braking; + using PrimitivePwle = aidl::android::hardware::vibrator::PrimitivePwle; + explicit HalWrapper(std::shared_ptr scheduler) : mCallbackScheduler(std::move(scheduler)) {} virtual ~HalWrapper() = default; @@ -355,21 +373,19 @@ public: virtual HalResult setAmplitude(float amplitude) = 0; virtual HalResult setExternalControl(bool enabled) = 0; - virtual HalResult alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect, - hardware::vibrator::EffectStrength strength) = 0; + virtual HalResult alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) = 0; virtual HalResult alwaysOnDisable(int32_t id) = 0; virtual HalResult performEffect( - hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, + Effect effect, EffectStrength strength, const std::function& completionCallback) = 0; virtual HalResult performComposedEffect( - const std::vector& primitives, + const std::vector& primitives, const std::function& completionCallback); - virtual HalResult performPwleEffect( - const std::vector& primitives, - const std::function& completionCallback); + virtual HalResult performPwleEffect(const std::vector& primitives, + const std::function& completionCallback); protected: // Shared pointer to allow CallbackScheduler to outlive this wrapper. @@ -381,12 +397,11 @@ protected: // Request vibrator info to HAL skipping cache. virtual HalResult getCapabilitiesInternal() = 0; - virtual HalResult> getSupportedEffectsInternal(); - virtual HalResult> getSupportedBrakingInternal(); - virtual HalResult> - getSupportedPrimitivesInternal(); + virtual HalResult> getSupportedEffectsInternal(); + virtual HalResult> getSupportedBrakingInternal(); + virtual HalResult> getSupportedPrimitivesInternal(); virtual HalResult> getPrimitiveDurationsInternal( - const std::vector& supportedPrimitives); + const std::vector& supportedPrimitives); virtual HalResult getPrimitiveDelayMaxInternal(); virtual HalResult getPrimitiveDurationMaxInternal(); virtual HalResult getCompositionSizeMaxInternal(); @@ -405,12 +420,17 @@ private: // Wrapper for the AIDL Vibrator HAL. class AidlHalWrapper : public HalWrapper { public: + using IVibrator = aidl::android::hardware::vibrator::IVibrator; + using reconnect_fn = std::function>()>; + AidlHalWrapper( - std::shared_ptr scheduler, sp handle, - std::function>()> reconnectFn = + std::shared_ptr scheduler, std::shared_ptr handle, + reconnect_fn reconnectFn = []() { - return HalResult>::ok( - checkVintfService()); + auto serviceName = std::string(IVibrator::descriptor) + "/default"; + auto hal = IVibrator::fromBinder( + ndk::SpAIBinder(AServiceManager_checkService(serviceName.c_str()))); + return HalResult>::ok(std::move(hal)); }) : HalWrapper(std::move(scheduler)), mReconnectFn(reconnectFn), @@ -427,32 +447,29 @@ public: HalResult setAmplitude(float amplitude) override final; HalResult setExternalControl(bool enabled) override final; - HalResult alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect, - hardware::vibrator::EffectStrength strength) override final; + HalResult alwaysOnEnable(int32_t id, Effect effect, + EffectStrength strength) override final; HalResult alwaysOnDisable(int32_t id) override final; HalResult performEffect( - hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, + Effect effect, EffectStrength strength, const std::function& completionCallback) override final; HalResult performComposedEffect( - const std::vector& primitives, + const std::vector& primitives, const std::function& completionCallback) override final; HalResult performPwleEffect( - const std::vector& primitives, + const std::vector& primitives, const std::function& completionCallback) override final; protected: HalResult getCapabilitiesInternal() override final; - HalResult> getSupportedEffectsInternal() override final; - HalResult> getSupportedBrakingInternal() - override final; - HalResult> getSupportedPrimitivesInternal() - override final; + HalResult> getSupportedEffectsInternal() override final; + HalResult> getSupportedBrakingInternal() override final; + HalResult> getSupportedPrimitivesInternal() override final; HalResult> getPrimitiveDurationsInternal( - const std::vector& supportedPrimitives) - override final; + const std::vector& supportedPrimitives) override final; HalResult getPrimitiveDelayMaxInternal() override final; HalResult getPrimitiveDurationMaxInternal() override final; HalResult getCompositionSizeMaxInternal() override final; @@ -464,11 +481,11 @@ protected: HalResult> getMaxAmplitudesInternal() override final; private: - const std::function>()> mReconnectFn; + const reconnect_fn mReconnectFn; std::mutex mHandleMutex; - sp mHandle GUARDED_BY(mHandleMutex); + std::shared_ptr mHandle GUARDED_BY(mHandleMutex); - sp getHal(); + std::shared_ptr getHal(); }; // Wrapper for the HDIL Vibrator HALs. @@ -489,8 +506,8 @@ public: HalResult setAmplitude(float amplitude) override final; virtual HalResult setExternalControl(bool enabled) override; - HalResult alwaysOnEnable(int32_t id, hardware::vibrator::Effect effect, - hardware::vibrator::EffectStrength strength) override final; + HalResult alwaysOnEnable(int32_t id, HalWrapper::Effect effect, + HalWrapper::EffectStrength strength) override final; HalResult alwaysOnDisable(int32_t id) override final; protected: @@ -506,8 +523,7 @@ protected: template HalResult performInternal( - perform_fn performFn, sp handle, T effect, - hardware::vibrator::EffectStrength strength, + perform_fn performFn, sp handle, T effect, HalWrapper::EffectStrength strength, const std::function& completionCallback); sp getHal(); @@ -523,7 +539,7 @@ public: virtual ~HidlHalWrapperV1_0() = default; HalResult performEffect( - hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, + HalWrapper::Effect effect, HalWrapper::EffectStrength strength, const std::function& completionCallback) override final; }; @@ -537,7 +553,7 @@ public: virtual ~HidlHalWrapperV1_1() = default; HalResult performEffect( - hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, + HalWrapper::Effect effect, HalWrapper::EffectStrength strength, const std::function& completionCallback) override final; }; @@ -551,7 +567,7 @@ public: virtual ~HidlHalWrapperV1_2() = default; HalResult performEffect( - hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, + HalWrapper::Effect effect, HalWrapper::EffectStrength strength, const std::function& completionCallback) override final; }; @@ -567,7 +583,7 @@ public: HalResult setExternalControl(bool enabled) override final; HalResult performEffect( - hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, + HalWrapper::Effect effect, HalWrapper::EffectStrength strength, const std::function& completionCallback) override final; protected: diff --git a/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h b/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h index 9168565ca0..70c846b4ae 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h +++ b/services/vibratorservice/include/vibratorservice/VibratorManagerHalController.h @@ -17,7 +17,7 @@ #ifndef ANDROID_OS_VIBRATOR_MANAGER_HAL_CONTROLLER_H #define ANDROID_OS_VIBRATOR_MANAGER_HAL_CONTROLLER_H -#include +#include #include #include #include diff --git a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h index 563f55e9f3..9e3f221fa7 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h +++ b/services/vibratorservice/include/vibratorservice/VibratorManagerHalWrapper.h @@ -17,7 +17,7 @@ #ifndef ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H #define ANDROID_OS_VIBRATOR_MANAGER_HAL_WRAPPER_H -#include +#include #include #include @@ -28,14 +28,17 @@ namespace vibrator { // VibratorManager HAL capabilities. enum class ManagerCapabilities : int32_t { NONE = 0, - SYNC = hardware::vibrator::IVibratorManager::CAP_SYNC, - PREPARE_ON = hardware::vibrator::IVibratorManager::CAP_PREPARE_ON, - PREPARE_PERFORM = hardware::vibrator::IVibratorManager::CAP_PREPARE_PERFORM, - PREPARE_COMPOSE = hardware::vibrator::IVibratorManager::CAP_PREPARE_COMPOSE, - MIXED_TRIGGER_ON = hardware::vibrator::IVibratorManager::IVibratorManager::CAP_MIXED_TRIGGER_ON, - MIXED_TRIGGER_PERFORM = hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_PERFORM, - MIXED_TRIGGER_COMPOSE = hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE, - TRIGGER_CALLBACK = hardware::vibrator::IVibratorManager::CAP_TRIGGER_CALLBACK + SYNC = aidl::android::hardware::vibrator::IVibratorManager::CAP_SYNC, + PREPARE_ON = aidl::android::hardware::vibrator::IVibratorManager::CAP_PREPARE_ON, + PREPARE_PERFORM = aidl::android::hardware::vibrator::IVibratorManager::CAP_PREPARE_PERFORM, + PREPARE_COMPOSE = aidl::android::hardware::vibrator::IVibratorManager::CAP_PREPARE_COMPOSE, + MIXED_TRIGGER_ON = aidl::android::hardware::vibrator::IVibratorManager::IVibratorManager:: + CAP_MIXED_TRIGGER_ON, + MIXED_TRIGGER_PERFORM = + aidl::android::hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_PERFORM, + MIXED_TRIGGER_COMPOSE = + aidl::android::hardware::vibrator::IVibratorManager::CAP_MIXED_TRIGGER_COMPOSE, + TRIGGER_CALLBACK = aidl::android::hardware::vibrator::IVibratorManager::CAP_TRIGGER_CALLBACK }; inline ManagerCapabilities operator|(ManagerCapabilities lhs, ManagerCapabilities rhs) { @@ -106,8 +109,10 @@ private: // Wrapper for the AIDL VibratorManager HAL. class AidlManagerHalWrapper : public ManagerHalWrapper { public: + using VibratorManager = aidl::android::hardware::vibrator::IVibratorManager; + explicit AidlManagerHalWrapper(std::shared_ptr callbackScheduler, - sp handle) + std::shared_ptr handle) : mHandle(std::move(handle)), mCallbackScheduler(callbackScheduler) {} virtual ~AidlManagerHalWrapper() = default; @@ -126,14 +131,14 @@ private: std::mutex mHandleMutex; std::mutex mCapabilitiesMutex; std::mutex mVibratorsMutex; - sp mHandle GUARDED_BY(mHandleMutex); + std::shared_ptr mHandle GUARDED_BY(mHandleMutex); std::optional mCapabilities GUARDED_BY(mCapabilitiesMutex); std::optional> mVibratorIds GUARDED_BY(mVibratorsMutex); std::unordered_map> mVibrators GUARDED_BY(mVibratorsMutex); std::shared_ptr mCallbackScheduler; - sp getHal(); + std::shared_ptr getHal(); std::shared_ptr connectToVibrator(int32_t vibratorId, std::shared_ptr scheduler); }; diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp index be71dc2ce3..cd051232cc 100644 --- a/services/vibratorservice/test/Android.bp +++ b/services/vibratorservice/test/Android.bp @@ -44,12 +44,12 @@ cc_test { ], shared_libs: [ "libbase", - "libbinder", + "libbinder_ndk", "libhidlbase", "liblog", "libvibratorservice", "libutils", - "android.hardware.vibrator-V2-cpp", + "android.hardware.vibrator-V2-ndk", "android.hardware.vibrator@1.0", "android.hardware.vibrator@1.1", "android.hardware.vibrator@1.2", diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp index 15fde914f6..f4c28981aa 100644 --- a/services/vibratorservice/test/VibratorHalControllerTest.cpp +++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorHalControllerTest" -#include +#include #include #include @@ -29,10 +29,11 @@ #include #include +#include "test_mocks.h" #include "test_utils.h" -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; using std::chrono::milliseconds; @@ -46,41 +47,12 @@ static const auto PING_FN = [](vibrator::HalWrapper* hal) { return hal->ping(); // ------------------------------------------------------------------------------------------------- -class MockHalWrapper : public vibrator::HalWrapper { -public: - MockHalWrapper(std::shared_ptr scheduler) - : HalWrapper(scheduler) {} - virtual ~MockHalWrapper() = default; - - MOCK_METHOD(vibrator::HalResult, ping, (), (override)); - MOCK_METHOD(void, tryReconnect, (), (override)); - MOCK_METHOD(vibrator::HalResult, on, - (milliseconds timeout, const std::function& completionCallback), - (override)); - MOCK_METHOD(vibrator::HalResult, off, (), (override)); - MOCK_METHOD(vibrator::HalResult, setAmplitude, (float amplitude), (override)); - MOCK_METHOD(vibrator::HalResult, setExternalControl, (bool enabled), (override)); - MOCK_METHOD(vibrator::HalResult, alwaysOnEnable, - (int32_t id, Effect effect, EffectStrength strength), (override)); - MOCK_METHOD(vibrator::HalResult, alwaysOnDisable, (int32_t id), (override)); - MOCK_METHOD(vibrator::HalResult, performEffect, - (Effect effect, EffectStrength strength, - const std::function& completionCallback), - (override)); - MOCK_METHOD(vibrator::HalResult, getCapabilitiesInternal, (), - (override)); - - vibrator::CallbackScheduler* getCallbackScheduler() { return mCallbackScheduler.get(); } -}; - -// ------------------------------------------------------------------------------------------------- - class VibratorHalControllerTest : public Test { public: void SetUp() override { mConnectCounter = 0; auto callbackScheduler = std::make_shared(); - mMockHal = std::make_shared>(callbackScheduler); + mMockHal = std::make_shared>(callbackScheduler); mController = std::make_unique< vibrator::HalController>(std::move(callbackScheduler), [&](std::shared_ptr) { @@ -92,7 +64,7 @@ public: protected: int32_t mConnectCounter; - std::shared_ptr mMockHal; + std::shared_ptr mMockHal; std::unique_ptr mController; }; diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp index 03c9e77f3e..91717f635d 100644 --- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorHalWrapperAidlTest" -#include +#include #include #include @@ -27,18 +27,17 @@ #include #include +#include "test_mocks.h" #include "test_utils.h" -using android::binder::Status; - -using android::hardware::vibrator::Braking; -using android::hardware::vibrator::CompositeEffect; -using android::hardware::vibrator::CompositePrimitive; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; -using android::hardware::vibrator::IVibrator; -using android::hardware::vibrator::IVibratorCallback; -using android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::Braking; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::IVibratorCallback; +using aidl::android::hardware::vibrator::PrimitivePwle; using namespace android; using namespace std::chrono_literals; @@ -46,61 +45,10 @@ using namespace testing; // ------------------------------------------------------------------------------------------------- -class MockBinder : public BBinder { -public: - MOCK_METHOD(status_t, linkToDeath, - (const sp& recipient, void* cookie, uint32_t flags), (override)); - MOCK_METHOD(status_t, unlinkToDeath, - (const wp& recipient, void* cookie, uint32_t flags, - wp* outRecipient), - (override)); - MOCK_METHOD(status_t, pingBinder, (), (override)); -}; - -class MockIVibrator : public IVibrator { -public: - MOCK_METHOD(Status, getCapabilities, (int32_t * ret), (override)); - MOCK_METHOD(Status, off, (), (override)); - MOCK_METHOD(Status, on, (int32_t timeout, const sp& cb), (override)); - MOCK_METHOD(Status, perform, - (Effect e, EffectStrength s, const sp& cb, int32_t* ret), - (override)); - MOCK_METHOD(Status, getSupportedEffects, (std::vector * ret), (override)); - MOCK_METHOD(Status, setAmplitude, (float amplitude), (override)); - MOCK_METHOD(Status, setExternalControl, (bool enabled), (override)); - MOCK_METHOD(Status, getCompositionDelayMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getCompositionSizeMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getSupportedPrimitives, (std::vector * ret), - (override)); - MOCK_METHOD(Status, getPrimitiveDuration, (CompositePrimitive p, int32_t* ret), (override)); - MOCK_METHOD(Status, compose, - (const std::vector& e, const sp& cb), - (override)); - MOCK_METHOD(Status, composePwle, - (const std::vector& e, const sp& cb), (override)); - MOCK_METHOD(Status, getSupportedAlwaysOnEffects, (std::vector * ret), (override)); - MOCK_METHOD(Status, alwaysOnEnable, (int32_t id, Effect e, EffectStrength s), (override)); - MOCK_METHOD(Status, alwaysOnDisable, (int32_t id), (override)); - MOCK_METHOD(Status, getQFactor, (float * ret), (override)); - MOCK_METHOD(Status, getResonantFrequency, (float * ret), (override)); - MOCK_METHOD(Status, getFrequencyResolution, (float* ret), (override)); - MOCK_METHOD(Status, getFrequencyMinimum, (float* ret), (override)); - MOCK_METHOD(Status, getBandwidthAmplitudeMap, (std::vector * ret), (override)); - MOCK_METHOD(Status, getPwlePrimitiveDurationMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getPwleCompositionSizeMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getSupportedBraking, (std::vector * ret), (override)); - MOCK_METHOD(int32_t, getInterfaceVersion, (), (override)); - MOCK_METHOD(std::string, getInterfaceHash, (), (override)); - MOCK_METHOD(IBinder*, onAsBinder, (), (override)); -}; - -// ------------------------------------------------------------------------------------------------- - class VibratorHalWrapperAidlTest : public Test { public: void SetUp() override { - mMockBinder = new StrictMock(); - mMockHal = new StrictMock(); + mMockHal = ndk::SharedRefBase::make>(); mMockScheduler = std::make_shared>(); mWrapper = std::make_unique(mMockScheduler, mMockHal); ASSERT_NE(mWrapper, nullptr); @@ -109,54 +57,28 @@ public: protected: std::shared_ptr> mMockScheduler = nullptr; std::unique_ptr mWrapper = nullptr; - sp> mMockHal = nullptr; - sp> mMockBinder = nullptr; + std::shared_ptr> mMockHal = nullptr; }; // ------------------------------------------------------------------------------------------------- -ACTION(TriggerCallbackInArg1) { - if (arg1 != nullptr) { - arg1->onComplete(); - } -} - -ACTION(TriggerCallbackInArg2) { - if (arg2 != nullptr) { - arg2->onComplete(); - } -} - -TEST_F(VibratorHalWrapperAidlTest, TestPing) { - EXPECT_CALL(*mMockHal.get(), onAsBinder()) - .Times(Exactly(2)) - .WillRepeatedly(Return(mMockBinder.get())); - EXPECT_CALL(*mMockBinder.get(), pingBinder()) - .Times(Exactly(2)) - .WillOnce(Return(android::OK)) - .WillRepeatedly(Return(android::DEAD_OBJECT)); - - ASSERT_TRUE(mWrapper->ping().isOk()); - ASSERT_TRUE(mWrapper->ping().isFailed()); -} - TEST_F(VibratorHalWrapperAidlTest, TestOnWithCallbackSupport) { { InSequence seq; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly( - DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), on(Eq(10), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status()))); + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), on(Eq(100), _)) .Times(Exactly(1)) - .WillRepeatedly(Return( - Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); EXPECT_CALL(*mMockHal.get(), on(Eq(1000), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -179,20 +101,20 @@ TEST_F(VibratorHalWrapperAidlTest, TestOnWithoutCallbackSupport) { InSequence seq; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly( - DoAll(SetArgPointee<0>(IVibrator::CAP_COMPOSE_EFFECTS), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_COMPOSE_EFFECTS), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), on(Eq(10), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status())); + .WillOnce(Return(ndk::ScopedAStatus::ok())); EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); + .WillOnce(vibrator::TriggerSchedulerCallback()); EXPECT_CALL(*mMockHal.get(), on(Eq(11), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), on(Eq(12), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -211,10 +133,9 @@ TEST_F(VibratorHalWrapperAidlTest, TestOnWithoutCallbackSupport) { TEST_F(VibratorHalWrapperAidlTest, TestOff) { EXPECT_CALL(*mMockHal.get(), off()) .Times(Exactly(3)) - .WillOnce(Return(Status())) - .WillOnce( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::ok())) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); ASSERT_TRUE(mWrapper->off().isOk()); ASSERT_TRUE(mWrapper->off().isUnsupported()); @@ -224,13 +145,15 @@ TEST_F(VibratorHalWrapperAidlTest, TestOff) { TEST_F(VibratorHalWrapperAidlTest, TestSetAmplitude) { { InSequence seq; - EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.1f))).Times(Exactly(1)); + EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.1f))) + .Times(Exactly(1)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.2f))) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), setAmplitude(Eq(0.5f))) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } ASSERT_TRUE(mWrapper->setAmplitude(0.1f).isOk()); @@ -241,12 +164,13 @@ TEST_F(VibratorHalWrapperAidlTest, TestSetAmplitude) { TEST_F(VibratorHalWrapperAidlTest, TestSetExternalControl) { { InSequence seq; - EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(true))).Times(Exactly(1)); + EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(true))) + .Times(Exactly(1)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); EXPECT_CALL(*mMockHal.get(), setExternalControl(Eq(false))) .Times(Exactly(2)) - .WillOnce(Return( - Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } ASSERT_TRUE(mWrapper->setExternalControl(true).isOk()); @@ -259,15 +183,16 @@ TEST_F(VibratorHalWrapperAidlTest, TestAlwaysOnEnable) { InSequence seq; EXPECT_CALL(*mMockHal.get(), alwaysOnEnable(Eq(1), Eq(Effect::CLICK), Eq(EffectStrength::LIGHT))) - .Times(Exactly(1)); + .Times(Exactly(1)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); EXPECT_CALL(*mMockHal.get(), alwaysOnEnable(Eq(2), Eq(Effect::TICK), Eq(EffectStrength::MEDIUM))) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), alwaysOnEnable(Eq(3), Eq(Effect::POP), Eq(EffectStrength::STRONG))) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } auto result = mWrapper->alwaysOnEnable(1, Effect::CLICK, EffectStrength::LIGHT); @@ -281,14 +206,15 @@ TEST_F(VibratorHalWrapperAidlTest, TestAlwaysOnEnable) { TEST_F(VibratorHalWrapperAidlTest, TestAlwaysOnDisable) { { InSequence seq; - EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(1))).Times(Exactly(1)); + EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(1))) + .Times(Exactly(1)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(2))) .Times(Exactly(1)) - .WillRepeatedly(Return( - Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); EXPECT_CALL(*mMockHal.get(), alwaysOnDisable(Eq(3))) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } ASSERT_TRUE(mWrapper->alwaysOnDisable(1).isOk()); @@ -311,66 +237,70 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) { std::vector amplitudes = {0.f, 1.f, 0.f}; std::vector primitiveDurations; - constexpr auto primitiveRange = enum_range(); + constexpr auto primitiveRange = ndk::enum_range(); constexpr auto primitiveCount = std::distance(primitiveRange.begin(), primitiveRange.end()); primitiveDurations.resize(primitiveCount); primitiveDurations[static_cast(CompositePrimitive::CLICK)] = 10ms; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getSupportedEffects(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(supportedEffects), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(supportedEffects), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getSupportedBraking(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(supportedBraking), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(supportedBraking), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(supportedPrimitives), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce( + DoAll(SetArgPointee<0>(supportedPrimitives), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(10), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(10), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce( + DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(F_MIN), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getResonantFrequency(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(F0), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(F0), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getFrequencyResolution(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(F_RESOLUTION), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(F_RESOLUTION), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getQFactor(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(Q_FACTOR), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(Q_FACTOR), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getBandwidthAmplitudeMap(_)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(amplitudes), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(amplitudes), Return(ndk::ScopedAStatus::ok()))); vibrator::Info failed = mWrapper->getInfo(); ASSERT_TRUE(failed.capabilities.isFailed()); @@ -417,46 +347,46 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) { EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getSupportedEffects(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(supportedEffects), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(supportedEffects), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getQFactor(_)) .Times(Exactly(1)) - .WillRepeatedly( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status()))); + .WillOnce( + DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(F_MIN), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getResonantFrequency(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(F0), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(F0), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getFrequencyResolution(_)) .Times(Exactly(1)) - .WillRepeatedly( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); EXPECT_CALL(*mMockHal.get(), getBandwidthAmplitudeMap(_)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), getSupportedBraking(_)) .Times(Exactly(1)) - .WillRepeatedly( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); std::vector threads; for (int i = 0; i < 10; i++) { @@ -487,18 +417,18 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithCallbackSupport) { InSequence seq; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly( - DoAll(SetArgPointee<0>(IVibrator::CAP_PERFORM_CALLBACK), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_PERFORM_CALLBACK), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::CLICK), Eq(EffectStrength::LIGHT), _, _)) .Times(Exactly(1)) - .WillRepeatedly( - DoAll(SetArgPointee<3>(1000), TriggerCallbackInArg2(), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<3>(1000), WithArg<2>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::POP), Eq(EffectStrength::MEDIUM), _, _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::THUD), Eq(EffectStrength::STRONG), _, _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -525,21 +455,20 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithoutCallbackSupport) { InSequence seq; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly( - DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::CLICK), Eq(EffectStrength::LIGHT), _, _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<3>(10), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<3>(10), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockScheduler.get(), schedule(_, Eq(10ms))) .Times(Exactly(1)) - .WillRepeatedly(vibrator::TriggerSchedulerCallback()); + .WillOnce(vibrator::TriggerSchedulerCallback()); EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::POP), Eq(EffectStrength::MEDIUM), _, _)) .Times(Exactly(1)) - .WillRepeatedly(Return( - Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); EXPECT_CALL(*mMockHal.get(), perform(Eq(Effect::THUD), Eq(EffectStrength::STRONG), _, _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -576,26 +505,28 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformComposedEffect) { InSequence seq; EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(supportedPrimitives), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(supportedPrimitives), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(1), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(1), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::SPIN), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(2), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::THUD), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(3), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(3), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), compose(Eq(emptyEffects), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status()))); + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), compose(Eq(singleEffect), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))); EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -630,26 +561,32 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformComposedCachesPrimitiveDurationsAn InSequence seq; EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(supportedPrimitives), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(supportedPrimitives), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::SPIN), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(2), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::THUD), _)) .Times(Exactly(1)) - .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))); EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status()))); + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::SPIN), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(2), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::THUD), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(2), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(2), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), compose(Eq(multipleEffects), _)) .Times(Exactly(2)) - .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status()))); + // ndk::ScopedAStatus::ok() cannot be copy-constructed so can't use WillRepeatedly + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))) + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -680,12 +617,12 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformPwleEffect) { InSequence seq; EXPECT_CALL(*mMockHal.get(), composePwle(Eq(emptyPrimitives), _)) .Times(Exactly(1)) - .WillRepeatedly(Return( - Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))); EXPECT_CALL(*mMockHal.get(), composePwle(Eq(multiplePrimitives), _)) .Times(Exactly(2)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(WithArg<1>(vibrator::TriggerCallback()), + Return(ndk::ScopedAStatus::ok()))); } std::unique_ptr callbackCounter = std::make_unique(); diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp index 0c27fc73b1..dd590935c4 100644 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorHalWrapperHidlV1_0Test" -#include +#include #include #include @@ -27,17 +27,18 @@ #include #include +#include "test_mocks.h" #include "test_utils.h" namespace V1_0 = android::hardware::vibrator::V1_0; -using android::hardware::vibrator::Braking; -using android::hardware::vibrator::CompositeEffect; -using android::hardware::vibrator::CompositePrimitive; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; -using android::hardware::vibrator::IVibrator; -using android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::Braking; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::PrimitivePwle; using namespace android; using namespace std::chrono_literals; diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp index d887efce80..b0a653769e 100644 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_1Test.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorHalWrapperHidlV1_1Test" -#include +#include #include #include @@ -26,13 +26,14 @@ #include #include +#include "test_mocks.h" #include "test_utils.h" namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; using namespace android; using namespace std::chrono_literals; diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp index 26d93503c6..dfe3fa0e68 100644 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_2Test.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorHalWrapperHidlV1_2Test" -#include +#include #include #include @@ -26,14 +26,15 @@ #include #include +#include "test_mocks.h" #include "test_utils.h" namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; using namespace android; using namespace std::chrono_literals; diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp index a6f1a74931..86243326ac 100644 --- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_3Test.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "VibratorHalWrapperHidlV1_3Test" -#include +#include #include #include @@ -27,6 +27,7 @@ #include #include +#include "test_mocks.h" #include "test_utils.h" namespace V1_0 = android::hardware::vibrator::V1_0; @@ -34,9 +35,9 @@ namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; namespace V1_3 = android::hardware::vibrator::V1_3; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; -using android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrator; using namespace android; using namespace std::chrono_literals; diff --git a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp index 11a8b66968..c7214e054e 100644 --- a/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp +++ b/services/vibratorservice/test/VibratorManagerHalControllerTest.cpp @@ -24,6 +24,7 @@ #include +#include "test_mocks.h" #include "test_utils.h" using android::vibrator::HalController; @@ -35,6 +36,8 @@ static constexpr int MAX_ATTEMPTS = 2; static const std::vector VIBRATOR_IDS = {1, 2}; static constexpr int VIBRATOR_ID = 1; +// ------------------------------------------------------------------------------------------------- + class MockManagerHalWrapper : public vibrator::ManagerHalWrapper { public: MOCK_METHOD(void, tryReconnect, (), (override)); @@ -51,6 +54,8 @@ public: MOCK_METHOD(vibrator::HalResult, cancelSynced, (), (override)); }; +// ------------------------------------------------------------------------------------------------- + class VibratorManagerHalControllerTest : public Test { public: void SetUp() override { @@ -106,6 +111,8 @@ protected: } }; +// ------------------------------------------------------------------------------------------------- + TEST_F(VibratorManagerHalControllerTest, TestInit) { mController->init(); ASSERT_EQ(1, mConnectCounter); diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp index dffc281fa1..764d9bea4f 100644 --- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp @@ -23,84 +23,42 @@ #include +#include "test_mocks.h" #include "test_utils.h" -using android::binder::Status; - -using android::hardware::vibrator::Braking; -using android::hardware::vibrator::CompositeEffect; -using android::hardware::vibrator::CompositePrimitive; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; -using android::hardware::vibrator::IVibrator; -using android::hardware::vibrator::IVibratorCallback; -using android::hardware::vibrator::IVibratorManager; -using android::hardware::vibrator::PrimitivePwle; +using aidl::android::hardware::vibrator::Braking; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::IVibratorCallback; +using aidl::android::hardware::vibrator::IVibratorManager; +using aidl::android::hardware::vibrator::PrimitivePwle; using namespace android; using namespace testing; static const auto OFF_FN = [](vibrator::HalWrapper* hal) { return hal->off(); }; -class MockBinder : public BBinder { -public: - MOCK_METHOD(status_t, linkToDeath, - (const sp& recipient, void* cookie, uint32_t flags), (override)); - MOCK_METHOD(status_t, unlinkToDeath, - (const wp& recipient, void* cookie, uint32_t flags, - wp* outRecipient), - (override)); - MOCK_METHOD(status_t, pingBinder, (), (override)); -}; +// ------------------------------------------------------------------------------------------------- -class MockIVibrator : public IVibrator { +class MockIVibratorManager : public IVibratorManager { public: - MOCK_METHOD(Status, getCapabilities, (int32_t * ret), (override)); - MOCK_METHOD(Status, off, (), (override)); - MOCK_METHOD(Status, on, (int32_t timeout, const sp& cb), (override)); - MOCK_METHOD(Status, perform, - (Effect e, EffectStrength s, const sp& cb, int32_t* ret), - (override)); - MOCK_METHOD(Status, getSupportedEffects, (std::vector * ret), (override)); - MOCK_METHOD(Status, setAmplitude, (float amplitude), (override)); - MOCK_METHOD(Status, setExternalControl, (bool enabled), (override)); - MOCK_METHOD(Status, getCompositionDelayMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getCompositionSizeMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getSupportedPrimitives, (std::vector * ret), + MockIVibratorManager() = default; + + MOCK_METHOD(ndk::ScopedAStatus, getCapabilities, (int32_t * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getVibratorIds, (std::vector * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getVibrator, (int32_t id, std::shared_ptr* ret), (override)); - MOCK_METHOD(Status, getPrimitiveDuration, (CompositePrimitive p, int32_t* ret), (override)); - MOCK_METHOD(Status, compose, - (const std::vector& e, const sp& cb), + MOCK_METHOD(ndk::ScopedAStatus, prepareSynced, (const std::vector& ids), (override)); + MOCK_METHOD(ndk::ScopedAStatus, triggerSynced, (const std::shared_ptr& cb), (override)); - MOCK_METHOD(Status, composePwle, - (const std::vector& e, const sp& cb), (override)); - MOCK_METHOD(Status, getSupportedAlwaysOnEffects, (std::vector * ret), (override)); - MOCK_METHOD(Status, alwaysOnEnable, (int32_t id, Effect e, EffectStrength s), (override)); - MOCK_METHOD(Status, alwaysOnDisable, (int32_t id), (override)); - MOCK_METHOD(Status, getQFactor, (float * ret), (override)); - MOCK_METHOD(Status, getResonantFrequency, (float * ret), (override)); - MOCK_METHOD(Status, getFrequencyResolution, (float* ret), (override)); - MOCK_METHOD(Status, getFrequencyMinimum, (float* ret), (override)); - MOCK_METHOD(Status, getBandwidthAmplitudeMap, (std::vector * ret), (override)); - MOCK_METHOD(Status, getPwlePrimitiveDurationMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getPwleCompositionSizeMax, (int32_t * ret), (override)); - MOCK_METHOD(Status, getSupportedBraking, (std::vector * ret), (override)); - MOCK_METHOD(int32_t, getInterfaceVersion, (), (override)); - MOCK_METHOD(std::string, getInterfaceHash, (), (override)); - MOCK_METHOD(IBinder*, onAsBinder, (), (override)); -}; - -class MockIVibratorManager : public IVibratorManager { -public: - MOCK_METHOD(Status, getCapabilities, (int32_t * ret), (override)); - MOCK_METHOD(Status, getVibratorIds, (std::vector * ret), (override)); - MOCK_METHOD(Status, getVibrator, (int32_t id, sp* ret), (override)); - MOCK_METHOD(Status, prepareSynced, (const std::vector& ids), (override)); - MOCK_METHOD(Status, triggerSynced, (const sp& cb), (override)); - MOCK_METHOD(Status, cancelSynced, (), (override)); - MOCK_METHOD(int32_t, getInterfaceVersion, (), (override)); - MOCK_METHOD(std::string, getInterfaceHash, (), (override)); - MOCK_METHOD(IBinder*, onAsBinder, (), (override)); + MOCK_METHOD(ndk::ScopedAStatus, cancelSynced, (), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t*), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string*), (override)); + MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override)); + MOCK_METHOD(bool, isRemote, (), (override)); }; // ------------------------------------------------------------------------------------------------- @@ -108,9 +66,8 @@ public: class VibratorManagerHalWrapperAidlTest : public Test { public: void SetUp() override { - mMockBinder = new StrictMock(); - mMockVibrator = new StrictMock(); - mMockHal = new StrictMock(); + mMockVibrator = ndk::SharedRefBase::make>(); + mMockHal = ndk::SharedRefBase::make>(); mMockScheduler = std::make_shared>(); mWrapper = std::make_unique(mMockScheduler, mMockHal); ASSERT_NE(mWrapper, nullptr); @@ -119,9 +76,8 @@ public: protected: std::shared_ptr> mMockScheduler = nullptr; std::unique_ptr mWrapper = nullptr; - sp> mMockHal = nullptr; - sp> mMockVibrator = nullptr; - sp> mMockBinder = nullptr; + std::shared_ptr> mMockHal = nullptr; + std::shared_ptr> mMockVibrator = nullptr; }; // ------------------------------------------------------------------------------------------------- @@ -129,32 +85,13 @@ protected: static const std::vector kVibratorIds = {1, 2}; static constexpr int kVibratorId = 1; -ACTION(TriggerCallback) { - if (arg0 != nullptr) { - arg0->onComplete(); - } -} - -TEST_F(VibratorManagerHalWrapperAidlTest, TestPing) { - EXPECT_CALL(*mMockHal.get(), onAsBinder()) - .Times(Exactly(2)) - .WillRepeatedly(Return(mMockBinder.get())); - EXPECT_CALL(*mMockBinder.get(), pingBinder()) - .Times(Exactly(2)) - .WillOnce(Return(android::OK)) - .WillRepeatedly(Return(android::DEAD_OBJECT)); - - ASSERT_TRUE(mWrapper->ping().isOk()); - ASSERT_TRUE(mWrapper->ping().isFailed()); -} - TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesDoesNotCacheFailedResult) { EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(3)) - .WillOnce( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), + Return(ndk::ScopedAStatus::ok()))); ASSERT_TRUE(mWrapper->getCapabilities().isUnsupported()); ASSERT_TRUE(mWrapper->getCapabilities().isFailed()); @@ -167,7 +104,8 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesDoesNotCacheFailedR TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesCachesResult) { EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), + Return(ndk::ScopedAStatus::ok()))); std::vector threads; for (int i = 0; i < 10; i++) { @@ -187,10 +125,9 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetCapabilitiesCachesResult) { TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorIdsDoesNotCacheFailedResult) { EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(3)) - .WillOnce( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); ASSERT_TRUE(mWrapper->getVibratorIds().isUnsupported()); ASSERT_TRUE(mWrapper->getVibratorIds().isFailed()); @@ -203,7 +140,7 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorIdsDoesNotCacheFailedRe TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorIdsCachesResult) { EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); std::vector threads; for (int i = 0; i < 10; i++) { @@ -225,11 +162,11 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorWithValidIdReturnsContr InSequence seq; EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getVibrator(Eq(kVibratorId), _)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))); } auto result = mWrapper->getVibrator(kVibratorId); @@ -241,7 +178,7 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorWithValidIdReturnsContr TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorWithInvalidIdFails) { EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); ASSERT_TRUE(mWrapper->getVibrator(0).isFailed()); } @@ -249,20 +186,21 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorWithInvalidIdFails) { TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorRecoversVibratorPointer) { EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getVibrator(Eq(kVibratorId), _)) .Times(Exactly(3)) .WillOnce(DoAll(SetArgPointee<1>(nullptr), - Return(Status::fromExceptionCode( - Status::Exception::EX_TRANSACTION_FAILED)))) - .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status()))); + Return(ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED)))) + // ndk::ScopedAStatus::ok() cannot be copy-constructed so can't use WillRepeatedly + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))) + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockVibrator.get(), off()) .Times(Exactly(3)) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_TRANSACTION_FAILED))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_TRANSACTION_FAILED))) - .WillRepeatedly(Return(Status())); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED))) + .WillOnce(Return(ndk::ScopedAStatus::ok())); // Get vibrator controller is successful even if first getVibrator. auto result = mWrapper->getVibrator(kVibratorId); @@ -281,18 +219,19 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestGetVibratorRecoversVibratorPointer TEST_F(VibratorManagerHalWrapperAidlTest, TestPrepareSynced) { EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getVibrator(_, _)) .Times(Exactly(2)) - .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status()))); + // ndk::ScopedAStatus::ok() cannot be copy-constructed so can't use WillRepeatedly + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))) + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), prepareSynced(Eq(kVibratorIds))) .Times(Exactly(3)) - .WillOnce( - Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(Return(Status())); + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(Return(ndk::ScopedAStatus::ok())); ASSERT_TRUE(mWrapper->getVibratorIds().isOk()); ASSERT_TRUE(mWrapper->prepareSynced(kVibratorIds).isUnsupported()); @@ -305,13 +244,13 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestTriggerSyncedWithCallbackSupport) InSequence seq; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(IVibratorManager::CAP_TRIGGER_CALLBACK), - Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibratorManager::CAP_TRIGGER_CALLBACK), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), triggerSynced(_)) .Times(Exactly(3)) - .WillOnce(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(DoAll(TriggerCallback(), Return(Status()))); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(DoAll(vibrator::TriggerCallback(), Return(ndk::ScopedAStatus::ok()))); } std::unique_ptr callbackCounter = std::make_unique(); @@ -328,11 +267,11 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestTriggerSyncedWithoutCallbackSuppor InSequence seq; EXPECT_CALL(*mMockHal.get(), getCapabilities(_)) .Times(Exactly(1)) - .WillRepeatedly( - DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(IVibratorManager::CAP_SYNC), + Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), triggerSynced(Eq(nullptr))) .Times(Exactly(1)) - .WillRepeatedly(Return(Status())); + .WillOnce(Return(ndk::ScopedAStatus::ok())); } std::unique_ptr callbackCounter = std::make_unique(); @@ -345,9 +284,9 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestTriggerSyncedWithoutCallbackSuppor TEST_F(VibratorManagerHalWrapperAidlTest, TestCancelSynced) { EXPECT_CALL(*mMockHal.get(), cancelSynced()) .Times(Exactly(3)) - .WillOnce(Return(Status::fromStatusT(UNKNOWN_TRANSACTION))) - .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) - .WillRepeatedly(Return(Status())); + .WillOnce(Return(ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION))) + .WillOnce(Return(ndk::ScopedAStatus::fromExceptionCode(EX_SECURITY))) + .WillOnce(Return(ndk::ScopedAStatus::ok())); ASSERT_TRUE(mWrapper->cancelSynced().isUnsupported()); ASSERT_TRUE(mWrapper->cancelSynced().isFailed()); @@ -357,13 +296,17 @@ TEST_F(VibratorManagerHalWrapperAidlTest, TestCancelSynced) { TEST_F(VibratorManagerHalWrapperAidlTest, TestCancelSyncedReloadsAllControllers) { EXPECT_CALL(*mMockHal.get(), getVibratorIds(_)) .Times(Exactly(1)) - .WillRepeatedly(DoAll(SetArgPointee<0>(kVibratorIds), Return(Status()))); + .WillOnce(DoAll(SetArgPointee<0>(kVibratorIds), Return(ndk::ScopedAStatus::ok()))); EXPECT_CALL(*mMockHal.get(), getVibrator(_, _)) .Times(Exactly(2)) - .WillRepeatedly(DoAll(SetArgPointee<1>(mMockVibrator), Return(Status()))); + // ndk::ScopedAStatus::ok() cannot be copy-constructed so can't use WillRepeatedly + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))) + .WillOnce(DoAll(SetArgPointee<1>(mMockVibrator), Return(ndk::ScopedAStatus::ok()))); - EXPECT_CALL(*mMockHal.get(), cancelSynced()).Times(Exactly(1)).WillRepeatedly(Return(Status())); + EXPECT_CALL(*mMockHal.get(), cancelSynced()) + .Times(Exactly(1)) + .WillOnce(Return(ndk::ScopedAStatus::ok())); ASSERT_TRUE(mWrapper->getVibratorIds().isOk()); ASSERT_TRUE(mWrapper->cancelSynced().isOk()); diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp index 0850ef3b8c..78772369bf 100644 --- a/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp +++ b/services/vibratorservice/test/VibratorManagerHalWrapperLegacyTest.cpp @@ -23,10 +23,12 @@ #include -using android::hardware::vibrator::CompositeEffect; -using android::hardware::vibrator::CompositePrimitive; -using android::hardware::vibrator::Effect; -using android::hardware::vibrator::EffectStrength; +#include "test_mocks.h" + +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; using std::chrono::milliseconds; @@ -35,27 +37,16 @@ using namespace testing; // ------------------------------------------------------------------------------------------------- -class MockHalController : public vibrator::HalController { -public: - MockHalController() = default; - virtual ~MockHalController() = default; - - MOCK_METHOD(bool, init, (), (override)); - MOCK_METHOD(void, tryReconnect, (), (override)); -}; - -// ------------------------------------------------------------------------------------------------- - class VibratorManagerHalWrapperLegacyTest : public Test { public: void SetUp() override { - mMockController = std::make_shared>(); + mMockController = std::make_shared>(); mWrapper = std::make_unique(mMockController); ASSERT_NE(mWrapper, nullptr); } protected: - std::shared_ptr> mMockController = nullptr; + std::shared_ptr> mMockController = nullptr; std::unique_ptr mWrapper = nullptr; }; diff --git a/services/vibratorservice/test/test_mocks.h b/services/vibratorservice/test/test_mocks.h new file mode 100644 index 0000000000..7882186b40 --- /dev/null +++ b/services/vibratorservice/test/test_mocks.h @@ -0,0 +1,169 @@ +/* + * 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. + */ + +#ifndef VIBRATORSERVICE_UNITTEST_MOCKS_H_ +#define VIBRATORSERVICE_UNITTEST_MOCKS_H_ + +#include + +#include + +#include +#include +#include + +namespace android { + +namespace vibrator { + +using std::chrono::milliseconds; + +using namespace testing; + +using aidl::android::hardware::vibrator::Braking; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::Effect; +using aidl::android::hardware::vibrator::EffectStrength; +using aidl::android::hardware::vibrator::IVibrator; +using aidl::android::hardware::vibrator::IVibratorCallback; +using aidl::android::hardware::vibrator::PrimitivePwle; + +// ------------------------------------------------------------------------------------------------- + +class MockIVibrator : public IVibrator { +public: + MockIVibrator() = default; + + MOCK_METHOD(ndk::ScopedAStatus, getCapabilities, (int32_t * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, off, (), (override)); + MOCK_METHOD(ndk::ScopedAStatus, on, + (int32_t timeout, const std::shared_ptr& cb), (override)); + MOCK_METHOD(ndk::ScopedAStatus, perform, + (Effect e, EffectStrength s, const std::shared_ptr& cb, + int32_t* ret), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, getSupportedEffects, (std::vector * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, setAmplitude, (float amplitude), (override)); + MOCK_METHOD(ndk::ScopedAStatus, setExternalControl, (bool enabled), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getCompositionDelayMax, (int32_t * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getCompositionSizeMax, (int32_t * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getSupportedPrimitives, (std::vector * ret), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, getPrimitiveDuration, (CompositePrimitive p, int32_t* ret), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, compose, + (const std::vector& e, + const std::shared_ptr& cb), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, composePwle, + (const std::vector& e, const std::shared_ptr& cb), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, getSupportedAlwaysOnEffects, (std::vector * ret), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, alwaysOnEnable, (int32_t id, Effect e, EffectStrength s), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, alwaysOnDisable, (int32_t id), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getQFactor, (float* ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getResonantFrequency, (float* ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getFrequencyResolution, (float* ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getFrequencyMinimum, (float* ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getBandwidthAmplitudeMap, (std::vector * ret), + (override)); + MOCK_METHOD(ndk::ScopedAStatus, getPwlePrimitiveDurationMax, (int32_t * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getPwleCompositionSizeMax, (int32_t * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getSupportedBraking, (std::vector * ret), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getInterfaceVersion, (int32_t*), (override)); + MOCK_METHOD(ndk::ScopedAStatus, getInterfaceHash, (std::string*), (override)); + MOCK_METHOD(ndk::SpAIBinder, asBinder, (), (override)); + MOCK_METHOD(bool, isRemote, (), (override)); +}; + +// gmock requirement to provide a WithArg<0>(TriggerCallback()) matcher +typedef void TriggerCallbackFunction(const std::shared_ptr&); + +class TriggerCallbackAction : public ActionInterface { +public: + explicit TriggerCallbackAction() {} + + virtual Result Perform(const ArgumentTuple& args) { + const std::shared_ptr& callback = get<0>(args); + if (callback) { + callback->onComplete(); + } + } +}; + +inline Action TriggerCallback() { + return MakeAction(new TriggerCallbackAction()); +} + +// ------------------------------------------------------------------------------------------------- + +class MockCallbackScheduler : public CallbackScheduler { +public: + MOCK_METHOD(void, schedule, (std::function callback, std::chrono::milliseconds delay), + (override)); +}; + +ACTION(TriggerSchedulerCallback) { + arg0(); +} + +// ------------------------------------------------------------------------------------------------- + +class MockHalWrapper : public HalWrapper { +public: + MockHalWrapper(std::shared_ptr scheduler) : HalWrapper(scheduler) {} + virtual ~MockHalWrapper() = default; + + MOCK_METHOD(vibrator::HalResult, ping, (), (override)); + MOCK_METHOD(void, tryReconnect, (), (override)); + MOCK_METHOD(vibrator::HalResult, on, + (milliseconds timeout, const std::function& completionCallback), + (override)); + MOCK_METHOD(vibrator::HalResult, off, (), (override)); + MOCK_METHOD(vibrator::HalResult, setAmplitude, (float amplitude), (override)); + MOCK_METHOD(vibrator::HalResult, setExternalControl, (bool enabled), (override)); + MOCK_METHOD(vibrator::HalResult, alwaysOnEnable, + (int32_t id, Effect effect, EffectStrength strength), (override)); + MOCK_METHOD(vibrator::HalResult, alwaysOnDisable, (int32_t id), (override)); + MOCK_METHOD(vibrator::HalResult, performEffect, + (Effect effect, EffectStrength strength, + const std::function& completionCallback), + (override)); + MOCK_METHOD(vibrator::HalResult, getCapabilitiesInternal, (), + (override)); + + CallbackScheduler* getCallbackScheduler() { return mCallbackScheduler.get(); } +}; + +class MockHalController : public vibrator::HalController { +public: + MockHalController() = default; + virtual ~MockHalController() = default; + + MOCK_METHOD(bool, init, (), (override)); + MOCK_METHOD(void, tryReconnect, (), (override)); +}; + +// ------------------------------------------------------------------------------------------------- + +} // namespace vibrator + +} // namespace android + +#endif // VIBRATORSERVICE_UNITTEST_MOCKS_H_ diff --git a/services/vibratorservice/test/test_utils.h b/services/vibratorservice/test/test_utils.h index 715c2215c4..e99965c877 100644 --- a/services/vibratorservice/test/test_utils.h +++ b/services/vibratorservice/test/test_utils.h @@ -17,7 +17,7 @@ #ifndef VIBRATORSERVICE_UNITTEST_UTIL_H_ #define VIBRATORSERVICE_UNITTEST_UTIL_H_ -#include +#include #include @@ -25,24 +25,12 @@ namespace android { namespace vibrator { -using ::android::hardware::vibrator::ActivePwle; -using ::android::hardware::vibrator::Braking; -using ::android::hardware::vibrator::BrakingPwle; -using ::android::hardware::vibrator::CompositeEffect; -using ::android::hardware::vibrator::CompositePrimitive; -using ::android::hardware::vibrator::PrimitivePwle; - -// ------------------------------------------------------------------------------------------------- - -class MockCallbackScheduler : public vibrator::CallbackScheduler { -public: - MOCK_METHOD(void, schedule, (std::function callback, std::chrono::milliseconds delay), - (override)); -}; - -ACTION(TriggerSchedulerCallback) { - arg0(); -} +using aidl::android::hardware::vibrator::ActivePwle; +using aidl::android::hardware::vibrator::Braking; +using aidl::android::hardware::vibrator::BrakingPwle; +using aidl::android::hardware::vibrator::CompositeEffect; +using aidl::android::hardware::vibrator::CompositePrimitive; +using aidl::android::hardware::vibrator::PrimitivePwle; // ------------------------------------------------------------------------------------------------- -- GitLab From b70f47100e711b907fe51399b65279ccd6c152c6 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Fri, 21 Jun 2024 11:58:54 -0700 Subject: [PATCH 072/530] Binder IPC: clean up includes - remove unused ones - IWYU - apply preupload lint checks Bug: 341997808 Test: mma Change-Id: Ib8eaff3c2587503fd1b529e0b32d73f7a9b2f479 --- cmds/servicemanager/NameUtil.h | 2 -- libs/binder/IPCThreadState.cpp | 2 -- libs/binder/IServiceManager.cpp | 1 - libs/binder/IShellCallback.cpp | 1 - libs/binder/LazyServiceRegistrar.cpp | 8 +++----- libs/binder/ProcessState.cpp | 1 - libs/binder/ndk/persistable_bundle.cpp | 3 ++- libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp | 6 ------ libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp | 1 + libs/binder/tests/binderDriverInterfaceTest.cpp | 5 +++-- libs/binder/tests/binderLibTest.cpp | 2 -- 11 files changed, 9 insertions(+), 23 deletions(-) diff --git a/cmds/servicemanager/NameUtil.h b/cmds/servicemanager/NameUtil.h index b08093960d..4b10c2bc5c 100644 --- a/cmds/servicemanager/NameUtil.h +++ b/cmds/servicemanager/NameUtil.h @@ -19,8 +19,6 @@ #include #include -#include - namespace android { #ifndef VENDORSERVICEMANAGER diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 61d0dbad31..94f947fce1 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -22,9 +22,7 @@ #include #include -#include #include -#include #include #include diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 2095586528..17e522d921 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #ifndef __ANDROID_VNDK__ diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp index 86dd5c4f4b..1d6852a9e4 100644 --- a/libs/binder/IShellCallback.cpp +++ b/libs/binder/IShellCallback.cpp @@ -21,7 +21,6 @@ #include -#include #include #include diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp index 7644806e2b..0f0af0b142 100644 --- a/libs/binder/LazyServiceRegistrar.cpp +++ b/libs/binder/LazyServiceRegistrar.cpp @@ -14,15 +14,13 @@ * limitations under the License. */ -#include "log/log_main.h" #define LOG_TAG "AidlLazyServiceRegistrar" -#include -#include -#include #include #include -#include +#include +#include +#include namespace android { namespace binder { diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 5de152a42a..a42ede29a2 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/libs/binder/ndk/persistable_bundle.cpp b/libs/binder/ndk/persistable_bundle.cpp index 9b6877daed..afa032ecfa 100644 --- a/libs/binder/ndk/persistable_bundle.cpp +++ b/libs/binder/ndk/persistable_bundle.cpp @@ -17,11 +17,12 @@ #include #include #include -#include #include #include +#include "persistable_bundle_internal.h" + __BEGIN_DECLS struct APersistableBundle { diff --git a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp index 43b2cb8577..66be94f5b5 100644 --- a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp +++ b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include #include #include @@ -30,13 +28,9 @@ #include #include #include - #include using namespace android; -using ::android::base::EndsWith; -using ::android::base::GetProperty; -using ::android::base::Split; using ::android::binder::Status; using ::android::internal::Stability; using ::ndk::ScopedAStatus; diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index 666b3af762..e2697c647c 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp index cf23a4658c..de9d42bac0 100644 --- a/libs/binder/tests/binderDriverInterfaceTest.cpp +++ b/libs/binder/tests/binderDriverInterfaceTest.cpp @@ -19,11 +19,12 @@ #include #include +#include #include #include -#include -#include #include +#include +#include #define BINDER_DEV_NAME "/dev/binder" diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 00406edcf2..5582a96ac1 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -57,7 +56,6 @@ using namespace android::binder::impl; using namespace std::string_literals; using namespace std::chrono_literals; using android::base::testing::HasValue; -using android::base::testing::Ok; using android::binder::Status; using android::binder::unique_fd; using testing::ExplainMatchResult; -- GitLab From 078ff90d134b413470cf0ad6a36fdc87be6b05fc Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Thu, 27 Jun 2024 10:18:40 -0700 Subject: [PATCH 073/530] Fix binder_sdk build Also, drop no longer necessary explicit libc++ prebuilt. Bug: 285204695 Test: atest --host binder_sdk_test Change-Id: I98dd792e379ff19f935108f17b47f26dd20042b3 --- libs/binder/Android.bp | 1 - libs/binder/include/binder/Functional.h | 2 +- libs/binder/include/binder/ProcessState.h | 1 + libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 1abde5cb92..87026bb98b 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -100,7 +100,6 @@ cc_cmake_snapshot { prebuilts: [ // to enable arm64 host support, build with musl - e.g. on aosp_cf_arm64_phone "aidl", - "libc++", ], include_sources: true, cflags: [ diff --git a/libs/binder/include/binder/Functional.h b/libs/binder/include/binder/Functional.h index bb0e5f4115..e153969963 100644 --- a/libs/binder/include/binder/Functional.h +++ b/libs/binder/include/binder/Functional.h @@ -36,7 +36,7 @@ public: inline void release() { f_.reset(); } private: - friend scope_guard android::binder::impl::make_scope_guard(F); + friend scope_guard android::binder::impl::make_scope_guard<>(F); inline scope_guard(F&& f) : f_(std::move(f)) {} diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index 8908cb8ae0..021bd58e21 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -25,6 +25,7 @@ #include #include +#include #include // --------------------------------------------------------------------------- diff --git a/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh b/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh index 0eca84607e..9ea8cb3a7c 100755 --- a/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh +++ b/libs/binder/tests/binder_sdk/binder_sdk_docker_test.sh @@ -57,7 +57,7 @@ else exit 1 fi ${ANDROID_BUILD_TOP}/build/soong/soong_ui.bash --make-mode binder_sdk - BINDER_SDK_ZIP="${ANDROID_BUILD_TOP}/out/soong/.intermediates/frameworks/native/libs/binder/binder_sdk/linux_glibc_x86_64/*/binder_sdk.zip" + BINDER_SDK_ZIP="${ANDROID_BUILD_TOP}/out/soong/.intermediates/frameworks/native/libs/binder/binder_sdk/linux_glibc_x86_64/binder_sdk.zip" DOCKER_PATH="$(dirname $(ls -1 ${BINDER_SDK_ZIP} | head --lines=1))" fi -- GitLab From f4c9b48c19f1b040efb35932b322f47e7779cafe Mon Sep 17 00:00:00 2001 From: Devin Moore Date: Mon, 1 Jul 2024 20:22:23 +0000 Subject: [PATCH 074/530] libbinder: Add log when FDs aren't supported in RpcSession Give a hint when this error is hit and make it obvious that both sides of the RpcSession need to agree on the FD support for the connection. Test: none Bug: none Change-Id: If7a559721d5886df0b418923e879538179658d85 --- libs/binder/Parcel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 77b32753de..f30b2aa3f4 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -1585,10 +1585,15 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) { fdVariant = borrowed_fd(fd); } if (!mAllowFds) { + ALOGE("FDs are not allowed in this parcel. Both the service and the client must set " + "the FileDescriptorTransportMode and agree on the support."); return FDS_NOT_ALLOWED; } switch (rpcFields->mSession->getFileDescriptorTransportMode()) { case RpcSession::FileDescriptorTransportMode::NONE: { + ALOGE("FDs are not allowed in this RpcSession. Both the service and the client " + "must set " + "the FileDescriptorTransportMode and agree on the support."); return FDS_NOT_ALLOWED; } case RpcSession::FileDescriptorTransportMode::UNIX: -- GitLab From be6f9e80aa2598305c0d2a2bb380bcb320d0a7f2 Mon Sep 17 00:00:00 2001 From: Nolan Scobie Date: Thu, 27 Jun 2024 17:04:12 -0400 Subject: [PATCH 075/530] Update RenderEngineTest's buffer dumping file paths Writing to `/data/file.ppm` was failing for me, even with `adb shell setenforce 0`. Changing this to `/data/local/tmp/file.ppm` let the write succeed, event without `adb shell setenforce 0`. I chose `/data/local/tmp/` based on context clues from other tests, but am happy with any directory, as long as we have write permission. After feedback I've also changed the code to create the target directory if it doesn't exist, which allows us to use `/data/local/tmp/RenderEngineTest` and remove the `texture_out_` file name prefix. Note: both `/data/` and `/data/local/tmp/` have the same permissions of 771, but they're owned by different users, `system` and `shell` respectively. I also tweaked the file name since tests parameterized by RenderEngine type were appending e.g. `/0`. Bug: N/A Test: manual Flag: EXEMPT test only Change-Id: I3017b870ecb4d61cd90206128774d45b003e3cf0 --- libs/renderengine/tests/RenderEngineTest.cpp | 51 ++++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index a8a98236e2..3c59fb30b1 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -34,9 +34,12 @@ #include #include +#include #include #include +#include #include +#include #include "../skia/SkiaGLRenderEngine.h" #include "../skia/SkiaVkRenderEngine.h" @@ -259,22 +262,51 @@ public: ~RenderEngineTest() { if (WRITE_BUFFER_TO_FILE_ON_FAILURE && ::testing::Test::HasFailure()) { - writeBufferToFile("/data/texture_out_"); + writeBufferToFile("/data/local/tmp/RenderEngineTest/"); } const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGI("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } - void writeBufferToFile(const char* basename) { - std::string filename(basename); - filename.append(::testing::UnitTest::GetInstance()->current_test_info()->name()); - filename.append(".ppm"); - std::ofstream file(filename.c_str(), std::ios::binary); + // If called during e.g. + // `PerRenderEngineType/RenderEngineTest#drawLayers_fillBufferCheckersRotate90_colorSource/0` + // with a directory of `/data/local/tmp/RenderEngineTest`, then mBuffer will be dumped to + // `/data/local/tmp/RenderEngineTest/drawLayers_fillBufferCheckersRotate90_colorSource-0.ppm` + // + // Note: if `directory` does not exist, then its full path will be recursively created with 777 + // permissions. If `directory` already exists but does not grant the executing user write + // permissions, then saving the buffer will fail. + // + // Since this is test-only code, no security considerations are made. + void writeBufferToFile(const filesystem::path& directory) { + const auto currentTestInfo = ::testing::UnitTest::GetInstance()->current_test_info(); + LOG_ALWAYS_FATAL_IF(!currentTestInfo, + "writeBufferToFile must be called during execution of a test"); + + std::string fileName(currentTestInfo->name()); + // Test names may include the RenderEngine variant separated by '/', which would separate + // the file name into a subdirectory if not corrected. + std::replace(fileName.begin(), fileName.end(), '/', '-'); + fileName.append(".ppm"); + + std::error_code err; + filesystem::create_directories(directory, err); + if (err.value()) { + ALOGE("Unable to create directory %s for writing %s (%d: %s)", directory.c_str(), + fileName.c_str(), err.value(), err.message().c_str()); + return; + } + + // Append operator ("/") ensures exactly one "/" directly before the argument. + const filesystem::path filePath = directory / fileName; + std::ofstream file(filePath.c_str(), std::ios::binary); if (!file.is_open()) { - ALOGE("Unable to open file: %s", filename.c_str()); - ALOGE("You may need to do: \"adb shell setenforce 0\" to enable " - "surfaceflinger to write debug images"); + ALOGE("Unable to open file: %s", filePath.c_str()); + ALOGE("You may need to do: \"adb shell setenforce 0\" to enable surfaceflinger to " + "write debug images, or the %s directory might not give the executing user write " + "permission", + directory.c_str()); return; } @@ -304,6 +336,7 @@ public: } } file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); + ALOGI("Image of incorrect output written to %s", filePath.c_str()); mBuffer->getBuffer()->unlock(); } -- GitLab From 6429b0b304e3684ae94366fb07c00c8b099c3138 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Fri, 28 Jun 2024 10:06:38 -0400 Subject: [PATCH 076/530] SF: Clean up DisplayModeSwitchingTest Use the ModeSettledTo and ModeSwitchingTo helpers in all tests. Clean up tests for brevity (e.g. minimal mock::createDisplayModeSpecs parameters) and consistency (e.g. NO_ERROR checks). Flag: TEST_ONLY Bug: 241285876 Test: DisplayModeSwitchingTest Change-Id: I5d92eae231d1b1a2c25f89ea7de4987569d9905e --- .../SurfaceFlinger_DisplayModeSwitching.cpp | 241 +++++++----------- .../unittests/mock/MockDisplayModeSpecs.h | 9 +- 2 files changed, 103 insertions(+), 147 deletions(-) diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp index 0c3e875432..6af965cd08 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp @@ -42,6 +42,47 @@ namespace { using android::hardware::graphics::composer::V2_4::Error; using android::hardware::graphics::composer::V2_4::VsyncPeriodChangeTimeline; +MATCHER_P2(ModeSettledTo, dmc, modeId, "") { + const auto displayId = arg->getPhysicalId(); + + if (const auto desiredOpt = dmc->getDesiredMode(displayId)) { + *result_listener << "Unsettled desired mode " + << ftl::to_underlying(desiredOpt->mode.modePtr->getId()); + return false; + } + + if (dmc->getActiveMode(displayId).modePtr->getId() != modeId) { + *result_listener << "Settled to unexpected active mode " << ftl::to_underlying(modeId); + return false; + } + + return true; +} + +MATCHER_P2(ModeSwitchingTo, flinger, modeId, "") { + const auto displayId = arg->getPhysicalId(); + auto& dmc = flinger->mutableDisplayModeController(); + + if (!dmc.getDesiredMode(displayId)) { + *result_listener << "No desired mode"; + return false; + } + + if (dmc.getDesiredMode(displayId)->mode.modePtr->getId() != modeId) { + *result_listener << "Unexpected desired mode " << ftl::to_underlying(modeId); + return false; + } + + // VsyncModulator should react to mode switches on the pacesetter display. + if (displayId == flinger->scheduler()->pacesetterDisplayId() && + !flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) { + *result_listener << "VsyncModulator did not shift to early phase"; + return false; + } + + return true; +} + class DisplayModeSwitchingTest : public DisplayTransactionTest { public: void SetUp() override { @@ -58,8 +99,7 @@ public: setupScheduler(selectorPtr); - mFlinger.onComposerHalHotplugEvent(PrimaryDisplayVariant::HWC_DISPLAY_ID, - DisplayHotplugEvent::CONNECTED); + mFlinger.onComposerHalHotplugEvent(kInnerDisplayHwcId, DisplayHotplugEvent::CONNECTED); mFlinger.configureAndCommit(); auto vsyncController = std::make_unique(); @@ -90,6 +130,11 @@ public: auto injectOuterDisplay() { constexpr PhysicalDisplayId kOuterDisplayId = PhysicalDisplayId::fromPort(254u); + // For the inner display, this is handled by setupHwcHotplugCallExpectations. + EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _)) + .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL), + Return(hal::V2_4::Error::NONE))); + constexpr bool kIsPrimary = false; TestableSurfaceFlinger::FakeHwcDisplayInjector(kOuterDisplayId, hal::DisplayType::PHYSICAL, kIsPrimary) @@ -169,129 +214,107 @@ void DisplayModeSwitchingTest::setupScheduler( TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp); } -TEST_F(DisplayModeSwitchingTest, changeRefreshRateOnActiveDisplayWithRefreshRequired) { - ftl::FakeGuard guard(kMainThreadContext); - - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); - - mFlinger.onActiveDisplayChanged(nullptr, *mDisplay); +TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithRefreshRequired) { + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60)); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, false, 0, 120)); + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90, 120_Hz))); - ASSERT_TRUE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getDesiredMode(mDisplayId)->mode.modePtr->getId(), kModeId90); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); + EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); // Verify that next commit will call setActiveConfigWithConstraints in HWC const VsyncPeriodChangeTimeline timeline{.refreshRequired = true}; - EXPECT_SET_ACTIVE_CONFIG(PrimaryDisplayVariant::HWC_DISPLAY_ID, kModeId90); + EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90); mFlinger.commit(); - Mock::VerifyAndClearExpectations(mComposer); - EXPECT_TRUE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); + EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); // Verify that the next commit will complete the mode change and send // a onModeChanged event to the framework. EXPECT_CALL(*mAppEventThread, onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)})); + mFlinger.commit(); Mock::VerifyAndClearExpectations(mAppEventThread); - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId90); + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90)); } -TEST_F(DisplayModeSwitchingTest, changeRefreshRateOnActiveDisplayWithoutRefreshRequired) { - ftl::FakeGuard guard(kMainThreadContext); - - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - - mFlinger.onActiveDisplayChanged(nullptr, *mDisplay); +TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithoutRefreshRequired) { + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60)); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, true, 0, 120)); + constexpr bool kAllowGroupSwitching = true; + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs( + mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90, 120_Hz, kAllowGroupSwitching))); - ASSERT_TRUE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getDesiredMode(mDisplayId)->mode.modePtr->getId(), kModeId90); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); + EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); // Verify that next commit will call setActiveConfigWithConstraints in HWC // and complete the mode change. const VsyncPeriodChangeTimeline timeline{.refreshRequired = false}; - EXPECT_SET_ACTIVE_CONFIG(PrimaryDisplayVariant::HWC_DISPLAY_ID, kModeId90); + EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90); EXPECT_CALL(*mAppEventThread, onModeChanged(scheduler::FrameRateMode{90_Hz, ftl::as_non_null(kMode90)})); mFlinger.commit(); - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId90); + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90)); } TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) { - ftl::FakeGuard guard(kMainThreadContext); - // Test that if we call setDesiredDisplayModeSpecs while a previous mode change // is still being processed the later call will be respected. - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); - - mFlinger.onActiveDisplayChanged(nullptr, *mDisplay); + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60)); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, false, 0, 120)); + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90, 120_Hz))); const VsyncPeriodChangeTimeline timeline{.refreshRequired = true}; - EXPECT_SET_ACTIVE_CONFIG(PrimaryDisplayVariant::HWC_DISPLAY_ID, kModeId90); + EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90); mFlinger.commit(); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId120, false, 0, 180)); + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId120, + 180_Hz))); - ASSERT_TRUE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getDesiredMode(mDisplayId)->mode.modePtr->getId(), kModeId120); + EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId120)); - EXPECT_SET_ACTIVE_CONFIG(PrimaryDisplayVariant::HWC_DISPLAY_ID, kModeId120); + EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId120); mFlinger.commit(); - ASSERT_TRUE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getDesiredMode(mDisplayId)->mode.modePtr->getId(), kModeId120); + EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId120)); mFlinger.commit(); - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId120); + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId120)); } -TEST_F(DisplayModeSwitchingTest, changeResolutionOnActiveDisplayWithoutRefreshRequired) { - ftl::FakeGuard guard(kMainThreadContext); - - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); - - mFlinger.onActiveDisplayChanged(nullptr, *mDisplay); +TEST_F(DisplayModeSwitchingTest, changeResolutionWithoutRefreshRequired) { + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId60)); - mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90_4K, false, 0, 120)); + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90_4K, + 120_Hz))); - ASSERT_TRUE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getDesiredMode(mDisplayId)->mode.modePtr->getId(), kModeId90_4K); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId60); + EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90_4K)); // Verify that next commit will call setActiveConfigWithConstraints in HWC // and complete the mode change. const VsyncPeriodChangeTimeline timeline{.refreshRequired = false}; - EXPECT_SET_ACTIVE_CONFIG(PrimaryDisplayVariant::HWC_DISPLAY_ID, kModeId90_4K); + EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90_4K); EXPECT_CALL(*mAppEventThread, onHotplugReceived(mDisplayId, true)); @@ -310,61 +333,12 @@ TEST_F(DisplayModeSwitchingTest, changeResolutionOnActiveDisplayWithoutRefreshRe mFlinger.commit(); - EXPECT_FALSE(dmc().getDesiredMode(mDisplayId)); - EXPECT_EQ(dmc().getActiveMode(mDisplayId).modePtr->getId(), kModeId90_4K); -} - -MATCHER_P2(ModeSwitchingTo, flinger, modeId, "") { - const auto displayId = arg->getPhysicalId(); - auto& dmc = flinger->mutableDisplayModeController(); - - if (!dmc.getDesiredMode(displayId)) { - *result_listener << "No desired mode"; - return false; - } - - if (dmc.getDesiredMode(displayId)->mode.modePtr->getId() != modeId) { - *result_listener << "Unexpected desired mode " << ftl::to_underlying(modeId); - return false; - } - - // VsyncModulator should react to mode switches on the pacesetter display. - if (displayId == flinger->scheduler()->pacesetterDisplayId() && - !flinger->scheduler()->vsyncModulator().isVsyncConfigEarly()) { - *result_listener << "VsyncModulator did not shift to early phase"; - return false; - } - - return true; -} - -MATCHER_P2(ModeSettledTo, dmc, modeId, "") { - const auto displayId = arg->getPhysicalId(); - - if (const auto desiredOpt = dmc->getDesiredMode(displayId)) { - *result_listener << "Unsettled desired mode " - << ftl::to_underlying(desiredOpt->mode.modePtr->getId()); - return false; - } - - ftl::FakeGuard guard(kMainThreadContext); - - if (dmc->getActiveMode(displayId).modePtr->getId() != modeId) { - *result_listener << "Settled to unexpected active mode " << ftl::to_underlying(modeId); - return false; - } - - return true; + EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90_4K)); } TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) { SET_FLAG_FOR_TEST(flags::connected_display, true); - // For the inner display, this is handled by setupHwcHotplugCallExpectations. - EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _)) - .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL), - Return(hal::V2_4::Error::NONE))); - const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); EXPECT_TRUE(innerDisplay->isPoweredOn()); @@ -381,13 +355,11 @@ TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) { EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId90, 120_Hz))); EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId60, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId60, 120_Hz))); EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60)); @@ -414,8 +386,7 @@ TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) { EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId60, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId60, 120_Hz))); EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId60)); EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId60); @@ -434,10 +405,6 @@ TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) { TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) { SET_FLAG_FOR_TEST(flags::connected_display, true); - // For the inner display, this is handled by setupHwcHotplugCallExpectations. - EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _)) - .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL), - Return(hal::V2_4::Error::NONE))); const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); EXPECT_TRUE(innerDisplay->isPoweredOn()); @@ -454,13 +421,11 @@ TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) { EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId90, 120_Hz))); EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId60, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId60, 120_Hz))); EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60)); @@ -486,8 +451,7 @@ TEST_F(DisplayModeSwitchingTest, powerOffDuringModeSet) { EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(mDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId90, 120_Hz))); EXPECT_THAT(mDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); @@ -511,11 +475,6 @@ TEST_F(DisplayModeSwitchingTest, powerOffDuringModeSet) { TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) { SET_FLAG_FOR_TEST(flags::connected_display, true); - // For the inner display, this is handled by setupHwcHotplugCallExpectations. - EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _)) - .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL), - Return(hal::V2_4::Error::NONE))); - const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); EXPECT_TRUE(innerDisplay->isPoweredOn()); @@ -532,13 +491,11 @@ TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) { EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId90, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId90, 120_Hz))); EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId60, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId60, 120_Hz))); EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60)); @@ -566,8 +523,8 @@ TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) { EXPECT_EQ(NO_ERROR, mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(), - mock::createDisplayModeSpecs(kModeId120, false, - 0.f, 120.f))); + mock::createDisplayModeSpecs(kModeId120, + 120_Hz))); EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId120); diff --git a/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h b/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h index 7b18a82283..4d35d4dcc6 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h +++ b/services/surfaceflinger/tests/unittests/mock/MockDisplayModeSpecs.h @@ -22,14 +22,13 @@ namespace android::mock { -inline gui::DisplayModeSpecs createDisplayModeSpecs(DisplayModeId defaultMode, - bool allowGroupSwitching, float minFps, - float maxFps) { +inline gui::DisplayModeSpecs createDisplayModeSpecs(DisplayModeId defaultMode, Fps maxFps, + bool allowGroupSwitching = false) { gui::DisplayModeSpecs specs; specs.defaultMode = ftl::to_underlying(defaultMode); specs.allowGroupSwitching = allowGroupSwitching; - specs.primaryRanges.physical.min = minFps; - specs.primaryRanges.physical.max = maxFps; + specs.primaryRanges.physical.min = 0.f; + specs.primaryRanges.physical.max = maxFps.getValue(); specs.primaryRanges.render = specs.primaryRanges.physical; specs.appRequestRanges = specs.primaryRanges; return specs; -- GitLab From 92900f8188bf923308c0b081c0a44c0f6ae36724 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 25 Jun 2024 11:50:43 -0400 Subject: [PATCH 077/530] SF: Generalize immediate mode set to multi-display When initiating a mode set, HWC may request an immediate mode change, in which case SF finalizes the change on the same (rather than next) frame. However, this would only be honored for at most one display, and further requests would be dropped. This was a historical hack: The loop used to iterate over mDisplays, and finalizeDisplayModeChange may recreate/invalidate the DisplayDevice. Now that the loop is over the immutable mPhysicalDisplays, the DisplayDevice can be safely recreated within the loop. Note that the only known user of this code path is ATV, so multi-display devices should not be affected by this change. Bug: 255635711 Flag: EXEMPT refactor Test: DisplayModeSwitchingTest (WithoutRefreshRequired cases) Change-Id: I842e39c2c5509de99b80fa9561ecb13b66f98c40 --- services/surfaceflinger/SurfaceFlinger.cpp | 23 ++++-------- .../SurfaceFlinger_DisplayModeSwitching.cpp | 36 +++++++++++++++++-- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5b40acf030..bba27b28e0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1481,8 +1481,6 @@ void SurfaceFlinger::applyActiveMode(PhysicalDisplayId displayId) { void SurfaceFlinger::initiateDisplayModeChanges() { ATRACE_CALL(); - std::optional displayToUpdateImmediately; - for (const auto& [displayId, physical] : FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays)) { auto desiredModeOpt = mDisplayModeController.getDesiredMode(displayId); if (!desiredModeOpt) { @@ -1536,21 +1534,14 @@ void SurfaceFlinger::initiateDisplayModeChanges() { if (outTimeline.refreshRequired) { scheduleComposite(FrameHint::kNone); } else { - // TODO(b/255635711): Remove `displayToUpdateImmediately` to `finalizeDisplayModeChange` - // for all displays. This was only needed when the loop iterated over `mDisplays` rather - // than `mPhysicalDisplays`. - displayToUpdateImmediately = displayId; - } - } - - if (displayToUpdateImmediately) { - const auto displayId = *displayToUpdateImmediately; - finalizeDisplayModeChange(displayId); + // HWC has requested to apply the mode change immediately rather than on the next frame. + finalizeDisplayModeChange(displayId); - const auto desiredModeOpt = mDisplayModeController.getDesiredMode(displayId); - if (desiredModeOpt && - mDisplayModeController.getActiveMode(displayId) == desiredModeOpt->mode) { - applyActiveMode(displayId); + const auto desiredModeOpt = mDisplayModeController.getDesiredMode(displayId); + if (desiredModeOpt && + mDisplayModeController.getActiveMode(displayId) == desiredModeOpt->mode) { + applyActiveMode(displayId); + } } } } diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp index 6af965cd08..4b0a7c3a04 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp @@ -127,9 +127,9 @@ public: static constexpr HWDisplayId kInnerDisplayHwcId = PrimaryDisplayVariant::HWC_DISPLAY_ID; static constexpr HWDisplayId kOuterDisplayHwcId = kInnerDisplayHwcId + 1; - auto injectOuterDisplay() { - constexpr PhysicalDisplayId kOuterDisplayId = PhysicalDisplayId::fromPort(254u); + static constexpr PhysicalDisplayId kOuterDisplayId = PhysicalDisplayId::fromPort(254u); + auto injectOuterDisplay() { // For the inner display, this is handled by setupHwcHotplugCallExpectations. EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _)) .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL), @@ -268,6 +268,38 @@ TEST_F(DisplayModeSwitchingTest, changeRefreshRateWithoutRefreshRequired) { EXPECT_THAT(mDisplay, ModeSettledTo(&dmc(), kModeId90)); } +TEST_F(DisplayModeSwitchingTest, changeRefreshRateOnTwoDisplaysWithoutRefreshRequired) { + const auto [innerDisplay, outerDisplay] = injectOuterDisplay(); + + EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId60)); + EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId120)); + + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs(innerDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId90, 120_Hz, + true))); + EXPECT_EQ(NO_ERROR, + mFlinger.setDesiredDisplayModeSpecs(outerDisplay->getDisplayToken().promote(), + mock::createDisplayModeSpecs(kModeId60, 60_Hz, + true))); + + EXPECT_THAT(innerDisplay, ModeSwitchingTo(&mFlinger, kModeId90)); + EXPECT_THAT(outerDisplay, ModeSwitchingTo(&mFlinger, kModeId60)); + + // Verify that next commit will call setActiveConfigWithConstraints in HWC + // and complete the mode change. + const VsyncPeriodChangeTimeline timeline{.refreshRequired = false}; + EXPECT_SET_ACTIVE_CONFIG(kInnerDisplayHwcId, kModeId90); + EXPECT_SET_ACTIVE_CONFIG(kOuterDisplayHwcId, kModeId60); + + EXPECT_CALL(*mAppEventThread, onModeChanged(_)).Times(2); + + mFlinger.commit(); + + EXPECT_THAT(innerDisplay, ModeSettledTo(&dmc(), kModeId90)); + EXPECT_THAT(outerDisplay, ModeSettledTo(&dmc(), kModeId60)); +} + TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) { // Test that if we call setDesiredDisplayModeSpecs while a previous mode change // is still being processed the later call will be respected. -- GitLab From a8b5d50f64bd77fc0ef7bf915ff7f47b8c30911a Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Mon, 1 Jul 2024 16:12:52 -0700 Subject: [PATCH 078/530] Add binder_sdk_test to postsubmit Bug: 285204695 Test: postsubmit Change-Id: Ibcd161c822cb7ebf02b7470c1c28ee9e0c5dffd7 --- libs/binder/TEST_MAPPING | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING index 2b3ff4407a..125617363a 100644 --- a/libs/binder/TEST_MAPPING +++ b/libs/binder/TEST_MAPPING @@ -129,6 +129,12 @@ "name": "memunreachable_binder_test" } ], + "postsubmit": [ + { + "name": "binder_sdk_test", + "host": true + } + ], "imports": [ { "path": "packages/modules/Virtualization" -- GitLab From 0ae829e1f13d2d2d097570ce2e2b95b747c87700 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 21 May 2024 14:21:22 +0000 Subject: [PATCH 079/530] rust: properly handle async->async handles Bug: 293406123 Test: Pending Change-Id: I270f45a5acced0cb9d55c1a2b2ffa7576923691a --- libs/binder/rust/src/binder.rs | 36 ++++++++++++++++++++------- libs/binder/rust/tests/integration.rs | 23 ++++++++++++++++- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index e34d31e58f..9a252b853b 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -768,14 +768,14 @@ macro_rules! declare_binder_interface { $interface:path[$descriptor:expr] { native: $native:ident($on_transact:path), proxy: $proxy:ident, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? } } => { $crate::declare_binder_interface! { $interface[$descriptor] { native: $native($on_transact), proxy: $proxy {}, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $crate::binder_impl::Stability::default(), } } @@ -785,7 +785,7 @@ macro_rules! declare_binder_interface { $interface:path[$descriptor:expr] { native: $native:ident($on_transact:path), proxy: $proxy:ident, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? stability: $stability:expr, } } => { @@ -793,7 +793,7 @@ macro_rules! declare_binder_interface { $interface[$descriptor] { native: $native($on_transact), proxy: $proxy {}, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $stability, } } @@ -805,7 +805,7 @@ macro_rules! declare_binder_interface { proxy: $proxy:ident { $($fname:ident: $fty:ty = $finit:expr),* }, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? } } => { $crate::declare_binder_interface! { @@ -814,7 +814,7 @@ macro_rules! declare_binder_interface { proxy: $proxy { $($fname: $fty = $finit),* }, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $crate::binder_impl::Stability::default(), } } @@ -826,7 +826,7 @@ macro_rules! declare_binder_interface { proxy: $proxy:ident { $($fname:ident: $fty:ty = $finit:expr),* }, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? stability: $stability:expr, } } => { @@ -838,7 +838,7 @@ macro_rules! declare_binder_interface { proxy: $proxy { $($fname: $fty = $finit),* }, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $stability, } } @@ -854,7 +854,7 @@ macro_rules! declare_binder_interface { $($fname:ident: $fty:ty = $finit:expr),* }, - $( async: $async_interface:ident, )? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? stability: $stability:expr, } @@ -1043,6 +1043,24 @@ macro_rules! declare_binder_interface { } if ibinder.associate_class(<$native as $crate::binder_impl::Remotable>::get_class()) { + let service: std::result::Result<$crate::binder_impl::Binder<$native>, $crate::StatusCode> = + std::convert::TryFrom::try_from(ibinder.clone()); + $( + // This part is only generated if the user of the macro specifies that the + // trait has an `try_into_local_async` implementation. + if let Ok(service) = service { + if let Some(async_service) = $native::$try_into_local_async(service) { + // We were able to associate with our expected class, + // the service is local, and the local service is async. + return Ok(async_service); + } + // The service is local but not async. Fall back to treating it as a + // remote service. This means that calls to this local service have an + // extra performance cost due to serialization, but async handle to + // non-async server is considered a rare case, so this is okay. + } + )? + // Treat service as remote. return Ok($crate::Strong::new(Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?))); } diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index 15ae56fdd7..5359832da1 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -182,7 +182,7 @@ declare_binder_interface! { proxy: BpTest { x: i32 = 100 }, - async: IATest, + async: IATest(try_into_local_async), } } @@ -323,6 +323,14 @@ impl IATest

for Binder { } } +impl BnTest { + fn try_into_local_async( + me: Binder, + ) -> Option>> { + Some(binder::Strong::new(Box::new(me) as _)) + } +} + /// Trivial testing binder interface pub trait ITestSameDescriptor: Interface {} @@ -900,6 +908,19 @@ mod tests { assert_eq!(service.test().unwrap(), service_name); } + #[tokio::test] + async fn reassociate_rust_binder_async() { + let service_name = "testing_service"; + let service_ibinder = + BnTest::new_binder(TestService::new(service_name), BinderFeatures::default()) + .as_binder(); + + let service: Strong> = + service_ibinder.into_interface().expect("Could not reassociate the generic ibinder"); + + assert_eq!(service.test().await.unwrap(), service_name); + } + #[test] fn weak_binder_upgrade() { let service_name = "testing_service"; -- GitLab From ac42d24c8fadc317bd547c9b5dffebb9fd02ca31 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Fri, 28 Jun 2024 10:43:53 -0700 Subject: [PATCH 080/530] Add more dispatcher tests for appearing windows It has been suggested that a window that appears while the gesture is active may cause incorrect behaviour in dispatcher if it then touched with additional new pointers. These tests attempt to check some of those scenarios. Currently, there's no evidence that this could lead to a crash. Flag: TEST_ONLY Bug: 341869464 Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_break_on_failure --gtest_filter="*SplitTouches*" Change-Id: I856907958684e84d08858aa4b92199a28095e58a --- .../dispatcher/InputDispatcher.cpp | 5 +- services/inputflinger/tests/FakeWindows.h | 7 ++ .../tests/InputDispatcher_test.cpp | 115 ++++++++++++++++++ 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index a76271da4e..a2e50d7d87 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2497,9 +2497,8 @@ std::vector InputDispatcher::findTouchedWindowTargetsLocked( } if (newTouchedWindows.empty()) { - ALOGI("Dropping event because there is no touchable window at (%.1f, %.1f) on display " - "%s.", - x, y, displayId.toString().c_str()); + LOG(INFO) << "Dropping event because there is no touchable window at (" << x << ", " + << y << ") on display " << displayId << ": " << entry; outInjectionResult = InputEventInjectionResult::FAILED; return {}; } diff --git a/services/inputflinger/tests/FakeWindows.h b/services/inputflinger/tests/FakeWindows.h index ee65d3a375..3a3238a6ad 100644 --- a/services/inputflinger/tests/FakeWindows.h +++ b/services/inputflinger/tests/FakeWindows.h @@ -304,6 +304,13 @@ public: WithFlags(expectedFlags))); } + inline void consumeMotionPointerDown(int32_t pointerIdx, + const ::testing::Matcher& matcher) { + const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN | + (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); + consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher)); + } + inline void consumeMotionPointerUp(int32_t pointerIdx, const ::testing::Matcher& matcher) { const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP | diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 5eab6be074..04ed67049d 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -4172,6 +4172,121 @@ TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) { window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime())); } +/** + * When events are not split, the downTime should be adjusted such that the downTime corresponds + * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect + * the event routing because the first window prevents splitting. + */ +TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) { + std::shared_ptr application = std::make_shared(); + sp window1 = + sp::make(application, mDispatcher, "Window1", DISPLAY_ID); + window1->setTouchableRegion(Region{{0, 0, 100, 100}}); + window1->setPreventSplitting(true); + + sp window2 = + sp::make(application, mDispatcher, "Window2", DISPLAY_ID); + window2->setTouchableRegion(Region{{100, 0, 200, 100}}); + + mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0}); + + // Touch down on the first window + NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .build(); + mDispatcher->notifyMotion(downArgs); + + window1->consumeMotionEvent( + AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime))); + + // Second window is added + mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0}); + + // Now touch down on the window with another pointer + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50)) + .downTime(downArgs.downTime) + .build()); + window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime))); + + // Finish the gesture + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50)) + .downTime(downArgs.downTime) + .build()); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .downTime(downArgs.downTime) + .build()); + window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime))); + window1->consumeMotionEvent( + AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime))); + window2->assertNoEvents(); +} + +/** + * When splitting touch events, the downTime should be adjusted such that the downTime corresponds + * to the event time of the first ACTION_DOWN sent to the new window. + * If a new window that does not support split appears on the screen and gets touched with the + * second finger, it should not get any events because it doesn't want split touches. At the same + * time, the first window should not get the pointer_down event because it supports split touches + * (and the touch occurred outside of the bounds of window1). + */ +TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) { + std::shared_ptr application = std::make_shared(); + sp window1 = + sp::make(application, mDispatcher, "Window1", DISPLAY_ID); + window1->setTouchableRegion(Region{{0, 0, 100, 100}}); + + sp window2 = + sp::make(application, mDispatcher, "Window2", DISPLAY_ID); + window2->setTouchableRegion(Region{{100, 0, 200, 100}}); + + mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0}); + + // Touch down on the first window + NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .build(); + mDispatcher->notifyMotion(downArgs); + + window1->consumeMotionEvent( + AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime))); + + // Second window is added + window2->setPreventSplitting(true); + mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0}); + + // Now touch down on the window with another pointer + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50)) + .downTime(downArgs.downTime) + .build()); + // Event is dropped because window2 doesn't support split touch, and window1 does. + + // Complete the gesture + mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50)) + .downTime(downArgs.downTime) + .build()); + // A redundant MOVE event is generated that doesn't carry any new information + window1->consumeMotionEvent( + AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime))); + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .downTime(downArgs.downTime) + .build()); + + window1->consumeMotionEvent( + AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime))); + window1->assertNoEvents(); + window2->assertNoEvents(); +} + TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) { std::shared_ptr application = std::make_shared(); sp windowLeft = sp::make(application, mDispatcher, "Left", -- GitLab From 94c51ab82f5c6efa0203a6eae5c6a37a2b0d5227 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Tue, 2 Jul 2024 15:06:02 -0700 Subject: [PATCH 081/530] binder_sdk: modules -> modules_host Bug: 285204695 Test: m binder_sdk Change-Id: I273123bb39aa1e0dfaf34eebea85c20ea91579de --- libs/binder/Android.bp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 55161a5259..cdc7166f65 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -87,7 +87,7 @@ cc_library_headers { cc_cmake_snapshot { name: "binder_sdk", - modules: [ + modules_host: [ "libbinder_sdk", "libbinder_sdk_single_threaded", "libbinder_ndk_sdk", -- GitLab From 052c51302e797260763a44b537820b7d54b18226 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Fri, 21 Jun 2024 15:45:26 -0700 Subject: [PATCH 082/530] Binder: enable/fix some warnings Bug: 341997808 Test: mma Change-Id: Ibd44eda768a714e85399a15f3c8e534d715f87ce --- libs/binder/IPCThreadState.cpp | 2 + libs/binder/PersistableBundle.cpp | 4 +- libs/binder/Utils.h | 13 +++ .../include_ndk/android/persistable_bundle.h | 5 + libs/binder/ndk/service_manager.cpp | 3 + libs/binder/ndk/tests/Android.bp | 5 + libs/binder/ndk/tests/iface.cpp | 7 +- .../ndk/tests/libbinder_ndk_unit_test.cpp | 108 ++++++++---------- libs/binder/tests/binderClearBufTest.cpp | 5 +- .../tests/binderDriverInterfaceTest.cpp | 12 +- libs/binder/tests/binderLibTest.cpp | 27 ++--- libs/binder/tests/binderStabilityTest.cpp | 18 ++- 12 files changed, 110 insertions(+), 99 deletions(-) diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 94f947fce1..984c93d370 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -285,7 +285,9 @@ static const void* printCommand(std::ostream& out, const void* _cmd) { return cmd; } +LIBBINDER_IGNORE("-Wzero-as-null-pointer-constant") static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; +LIBBINDER_IGNORE_END() static std::atomic gHaveTLS(false); static pthread_key_t gTLS = 0; static std::atomic gShutdown = false; diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp index 5b157cc7c3..abb6612a1c 100644 --- a/libs/binder/PersistableBundle.cpp +++ b/libs/binder/PersistableBundle.cpp @@ -113,7 +113,7 @@ status_t PersistableBundle::writeToParcel(Parcel* parcel) const { // Backpatch length. This length value includes the length header. parcel->setDataPosition(length_pos); size_t length = end_pos - start_pos; - if (length > std::numeric_limits::max()) { + if (length > static_cast(std::numeric_limits::max())) { ALOGE("Parcel length (%zu) too large to store in 32-bit signed int", length); return BAD_VALUE; } @@ -319,7 +319,7 @@ status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const { * pairs themselves. */ size_t num_entries = size(); - if (num_entries > std::numeric_limits::max()) { + if (num_entries > static_cast(std::numeric_limits::max())) { ALOGE("The size of this PersistableBundle (%zu) too large to store in 32-bit signed int", num_entries); return BAD_VALUE; diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h index 5e1012af01..881cdf3f4c 100644 --- a/libs/binder/Utils.h +++ b/libs/binder/Utils.h @@ -58,6 +58,19 @@ } \ } while (0) +#define LIBBINDER_PRAGMA(arg) _Pragma(#arg) +#if defined(__clang__) +#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) LIBBINDER_PRAGMA(clang arg) +#elif defined(__GNUC__) +#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) LIBBINDER_PRAGMA(GCC arg) +#else +#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) +#endif +#define LIBBINDER_IGNORE(warning_flag) \ + LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic push) \ + LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic ignored warning_flag) +#define LIBBINDER_IGNORE_END() LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic pop) + namespace android { /** diff --git a/libs/binder/ndk/include_ndk/android/persistable_bundle.h b/libs/binder/ndk/include_ndk/android/persistable_bundle.h index 42ae15ae61..5e0d4da97b 100644 --- a/libs/binder/ndk/include_ndk/android/persistable_bundle.h +++ b/libs/binder/ndk/include_ndk/android/persistable_bundle.h @@ -29,6 +29,11 @@ #include #include +#ifndef __clang__ +#define _Nullable +#define _Nonnull +#endif + __BEGIN_DECLS /* diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index 4436dbeed7..d6ac4acc29 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -18,6 +18,7 @@ #include #include +#include "../Utils.h" #include "ibinder_internal.h" #include "status_internal.h" @@ -89,7 +90,9 @@ AIBinder* AServiceManager_getService(const char* instance) { } sp sm = defaultServiceManager(); + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp binder = sm->getService(String16(instance)); + LIBBINDER_IGNORE_END() sp ret = ABpBinder::lookupOrCreateFromBinder(binder); AIBinder_incStrong(ret.get()); diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp index 8fb755cdac..c61a16413b 100644 --- a/libs/binder/ndk/tests/Android.bp +++ b/libs/binder/ndk/tests/Android.bp @@ -34,6 +34,11 @@ cc_defaults { cflags: [ "-O0", "-g", + "-Wall", + "-Wextra", + "-Wextra-semi", + "-Werror", + "-Winconsistent-missing-override", ], } diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp index ca927272f8..08b857fab2 100644 --- a/libs/binder/ndk/tests/iface.cpp +++ b/libs/binder/ndk/tests/iface.cpp @@ -20,6 +20,8 @@ #include +#include "../../Utils.h" + using ::android::sp; using ::android::wp; @@ -157,10 +159,9 @@ binder_status_t IFoo::addService(const char* instance) { } sp IFoo::getService(const char* instance, AIBinder** outBinder) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() if (binder == nullptr) { return nullptr; } diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index 6d638d0b3a..f518a22902 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -42,6 +42,7 @@ #include #include +#include "../Utils.h" #include "android/binder_ibinder.h" using namespace android; @@ -69,21 +70,21 @@ class MyTestFoo : public IFoo { }; class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { - ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { + ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) override { *out = in; return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus takeInterface(const std::shared_ptr& empty) { + ndk::ScopedAStatus takeInterface(const std::shared_ptr& empty) override { (void)empty; return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus forceFlushCommands() { + ndk::ScopedAStatus forceFlushCommands() override { // warning: this is assuming that libbinder_ndk is using the same copy // of libbinder that we are. android::IPCThreadState::self()->flushCommands(); return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus getsRequestedSid(bool* out) { + ndk::ScopedAStatus getsRequestedSid(bool* out) override { const char* sid = AIBinder_getCallingSid(); std::cout << "Got security context: " << (sid ?: "null") << std::endl; *out = sid != nullptr; @@ -97,11 +98,11 @@ class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { fsync(out); return STATUS_OK; } - ndk::ScopedAStatus forcePersist(bool persist) { + ndk::ScopedAStatus forcePersist(bool persist) override { AServiceManager_forceLazyServicesPersist(persist); return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus setCustomActiveServicesCallback() { + ndk::ScopedAStatus setCustomActiveServicesCallback() override { AServiceManager_setActiveServicesCallback(activeServicesCallback, this); return ndk::ScopedAStatus::ok(); } @@ -342,10 +343,9 @@ TEST(NdkBinder, UnimplementedShell) { // libbinder across processes to the NDK service which doesn't implement // shell static const sp sm(android::defaultServiceManager()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp testService = sm->getService(String16(IFoo::kSomeInstanceName)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() Vector argsVec; EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, @@ -388,10 +388,9 @@ TEST(NdkBinder, GetTestServiceStressTest) { // checkService on it, since the other process serving it might not be started yet. { // getService, not waitForService, to take advantage of timeout -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") auto binder = ndk::SpAIBinder(AServiceManager_getService(IFoo::kSomeInstanceName)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder.get()); } @@ -425,7 +424,7 @@ TEST(NdkBinder, GetDeclaredInstances) { // At the time of writing this test, there is no good interface guaranteed // to be on all devices. Cuttlefish has light, so this will generally test // things. - EXPECT_EQ(count, hasLight ? 1 : 0); + EXPECT_EQ(count, hasLight ? 1u : 0u); } TEST(NdkBinder, GetLazyService) { @@ -515,7 +514,7 @@ void LambdaOnDeath(void* cookie) { // may reference other cookie members (*funcs->onDeath)(); -}; +} void LambdaOnUnlink(void* cookie) { auto funcs = static_cast(cookie); (*funcs->onUnlink)(); @@ -523,7 +522,7 @@ void LambdaOnUnlink(void* cookie) { // may reference other cookie members delete funcs; -}; +} TEST(NdkBinder, DeathRecipient) { using namespace std::chrono_literals; @@ -701,7 +700,7 @@ TEST(NdkBinder, DeathRecipientDropBinderOnDied) { void LambdaOnUnlinkMultiple(void* cookie) { auto funcs = static_cast(cookie); (*funcs->onUnlink)(); -}; +} TEST(NdkBinder, DeathRecipientMultipleLinks) { using namespace std::chrono_literals; @@ -733,7 +732,7 @@ TEST(NdkBinder, DeathRecipientMultipleLinks) { ndk::ScopedAIBinder_DeathRecipient recipient(AIBinder_DeathRecipient_new(LambdaOnDeath)); AIBinder_DeathRecipient_setOnUnlinked(recipient.get(), LambdaOnUnlinkMultiple); - for (int32_t i = 0; i < kNumberOfLinksToDeath; i++) { + for (uint32_t i = 0; i < kNumberOfLinksToDeath; i++) { EXPECT_EQ(STATUS_OK, AIBinder_linkToDeath(binder.get(), recipient.get(), static_cast(cookie))); } @@ -745,14 +744,13 @@ TEST(NdkBinder, DeathRecipientMultipleLinks) { EXPECT_TRUE(unlinkCv.wait_for(lockUnlink, 5s, [&] { return unlinkReceived; })) << "countdown: " << countdown; EXPECT_TRUE(unlinkReceived); - EXPECT_EQ(countdown, 0); + EXPECT_EQ(countdown, 0u); } TEST(NdkBinder, RetrieveNonNdkService) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder); EXPECT_TRUE(AIBinder_isRemote(binder)); EXPECT_TRUE(AIBinder_isAlive(binder)); @@ -766,10 +764,9 @@ void OnBinderDeath(void* cookie) { } TEST(NdkBinder, LinkToDeath) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder); AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath); @@ -799,10 +796,9 @@ TEST(NdkBinder, SetInheritRt) { } TEST(NdkBinder, SetInheritRtNonLocal) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(binder, nullptr); ASSERT_TRUE(AIBinder_isRemote(binder)); @@ -838,14 +834,13 @@ TEST(NdkBinder, GetServiceInProcess) { } TEST(NdkBinder, EqualityOfRemoteBinderPointer) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService); ASSERT_NE(nullptr, binderA); AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService); ASSERT_NE(nullptr, binderB); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() EXPECT_EQ(binderA, binderB); @@ -859,10 +854,9 @@ TEST(NdkBinder, ToFromJavaNullptr) { } TEST(NdkBinder, ABpBinderRefCount) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() AIBinder_Weak* wBinder = AIBinder_Weak_new(binder); ASSERT_NE(nullptr, binder); @@ -885,10 +879,9 @@ TEST(NdkBinder, AddServiceMultipleTimes) { } TEST(NdkBinder, RequestedSidWorks) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() std::shared_ptr service = aidl::IBinderNdkUnitTest::fromBinder(binder); @@ -911,10 +904,9 @@ TEST(NdkBinder, SentAidlBinderCanBeDestroyed) { std::shared_ptr empty = ndk::SharedRefBase::make(); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() std::shared_ptr service = aidl::IBinderNdkUnitTest::fromBinder(binder); @@ -935,14 +927,11 @@ TEST(NdkBinder, SentAidlBinderCanBeDestroyed) { } TEST(NdkBinder, ConvertToPlatformBinder) { - for (const ndk::SpAIBinder& binder : - {// remote -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)), -#pragma clang diagnostic pop - // local - ndk::SharedRefBase::make()->asBinder()}) { + LIBBINDER_IGNORE("-Wdeprecated-declarations") + ndk::SpAIBinder remoteBinder(AServiceManager_getService(kBinderNdkUnitTestService)); + LIBBINDER_IGNORE_END() + auto localBinder = ndk::SharedRefBase::make()->asBinder(); + for (const ndk::SpAIBinder& binder : {remoteBinder, localBinder}) { // convert to platform binder EXPECT_NE(binder, nullptr); sp platformBinder = AIBinder_toPlatformBinder(binder.get()); @@ -971,14 +960,11 @@ TEST(NdkBinder, ConvertToPlatformParcel) { } TEST(NdkBinder, GetAndVerifyScopedAIBinder_Weak) { - for (const ndk::SpAIBinder& binder : - {// remote -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)), -#pragma clang diagnostic pop - // local - ndk::SharedRefBase::make()->asBinder()}) { + LIBBINDER_IGNORE("-Wdeprecated-declarations") + ndk::SpAIBinder remoteBinder(AServiceManager_getService(kBinderNdkUnitTestService)); + LIBBINDER_IGNORE_END() + auto localBinder = ndk::SharedRefBase::make()->asBinder(); + for (const ndk::SpAIBinder& binder : {remoteBinder, localBinder}) { // get a const ScopedAIBinder_Weak and verify promote EXPECT_NE(binder.get(), nullptr); const ndk::ScopedAIBinder_Weak wkAIBinder = @@ -1047,7 +1033,7 @@ std::string shellCmdToString(sp unitTestService, const std::vector resultReceiver = new MyResultReceiver(); Vector argsVec; - for (int i = 0; i < args.size(); i++) { + for (size_t i = 0; i < args.size(); i++) { argsVec.add(String16(args[i])); } status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec, @@ -1071,10 +1057,9 @@ std::string shellCmdToString(sp unitTestService, const std::vector sm(android::defaultServiceManager()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp testService = sm->getService(String16(kBinderNdkUnitTestService)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() EXPECT_EQ("", shellCmdToString(testService, {})); EXPECT_EQ("", shellCmdToString(testService, {"", ""})); @@ -1084,10 +1069,9 @@ TEST(NdkBinder, UseHandleShellCommand) { TEST(NdkBinder, FlaggedServiceAccessible) { static const sp sm(android::defaultServiceManager()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp testService = sm->getService(String16(kBinderNdkUnitTestServiceFlagged)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, testService); } diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp index 3230a3f904..63254cddd9 100644 --- a/libs/binder/tests/binderClearBufTest.cpp +++ b/libs/binder/tests/binderClearBufTest.cpp @@ -75,10 +75,9 @@ class FooBar : public BBinder { }; TEST(BinderClearBuf, ClearKernelBuffer) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp binder = defaultServiceManager()->getService(kServerName); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder); std::string replyBuffer; diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp index de9d42bac0..7be4f21cee 100644 --- a/libs/binder/tests/binderDriverInterfaceTest.cpp +++ b/libs/binder/tests/binderDriverInterfaceTest.cpp @@ -94,8 +94,9 @@ class BinderDriverInterfaceTest : public ::testing::Test { ret = ioctl(m_binderFd, cmd, arg); EXPECT_EQ(expect_ret, ret); if (ret < 0) { - if (errno != accept_errno) + if (errno != accept_errno) { EXPECT_EQ(expect_errno, errno); + } } } void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) { @@ -275,12 +276,15 @@ TEST_F(BinderDriverInterfaceTest, Transaction) { binderTestIoctl(BINDER_WRITE_READ, &bwr); } EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed); - if (bwr.read_consumed > offsetof(typeof(br), cmd0)) + if (bwr.read_consumed > offsetof(typeof(br), cmd0)) { EXPECT_EQ(BR_NOOP, br.cmd0); - if (bwr.read_consumed > offsetof(typeof(br), cmd1)) + } + if (bwr.read_consumed > offsetof(typeof(br), cmd1)) { EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1); - if (bwr.read_consumed > offsetof(typeof(br), cmd2)) + } + if (bwr.read_consumed > offsetof(typeof(br), cmd2)) { EXPECT_EQ(BR_REPLY, br.cmd2); + } if (bwr.read_consumed >= offsetof(typeof(br), pad)) { EXPECT_EQ(0u, br.arg2.target.ptr); EXPECT_EQ(0u, br.arg2.cookie); diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 5582a96ac1..9b1ba01146 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -47,10 +47,9 @@ #include #include +#include "../Utils.h" #include "../binder_module.h" -#define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) - using namespace android; using namespace android::binder::impl; using namespace std::string_literals; @@ -216,10 +215,9 @@ class BinderLibTestEnv : public ::testing::Environment { sp sm = defaultServiceManager(); //printf("%s: pid %d, get service\n", __func__, m_pid); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") m_server = sm->getService(binderLibTestServiceName); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_TRUE(m_server != nullptr); //printf("%s: pid %d, get service done\n", __func__, m_pid); } @@ -566,7 +564,7 @@ TEST_F(BinderLibTest, Freeze) { TEST_F(BinderLibTest, SetError) { int32_t testValue[] = { 0, -123, 123 }; - for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) { + for (size_t i = 0; i < countof(testValue); i++) { Parcel data, reply; data.writeInt32(testValue[i]); EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply), @@ -597,8 +595,8 @@ TEST_F(BinderLibTest, IndirectGetId2) Parcel data, reply; int32_t serverId[3]; - data.writeInt32(ARRAY_SIZE(serverId)); - for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) { + data.writeInt32(countof(serverId)); + for (size_t i = 0; i < countof(serverId); i++) { sp server; BinderLibTestBundle datai; @@ -616,7 +614,7 @@ TEST_F(BinderLibTest, IndirectGetId2) EXPECT_EQ(0, id); ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR)); - EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count); + EXPECT_EQ(countof(serverId), (size_t)count); for (size_t i = 0; i < (size_t)count; i++) { BinderLibTestBundle replyi(&reply); @@ -636,8 +634,8 @@ TEST_F(BinderLibTest, IndirectGetId3) Parcel data, reply; int32_t serverId[3]; - data.writeInt32(ARRAY_SIZE(serverId)); - for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) { + data.writeInt32(countof(serverId)); + for (size_t i = 0; i < countof(serverId); i++) { sp server; BinderLibTestBundle datai; BinderLibTestBundle datai2; @@ -662,7 +660,7 @@ TEST_F(BinderLibTest, IndirectGetId3) EXPECT_EQ(0, id); ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR)); - EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count); + EXPECT_EQ(countof(serverId), (size_t)count); for (size_t i = 0; i < (size_t)count; i++) { int32_t counti; @@ -2112,10 +2110,9 @@ int run_server(int index, int readypipefd, bool usePoll) if (index == 0) { ret = sm->addService(binderLibTestServiceName, testService); } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp server = sm->getService(binderLibTestServiceName); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() Parcel data, reply; data.writeInt32(index); data.writeStrongBinder(testService); diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp index 3d993588a4..7a8f48e0eb 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -27,8 +27,9 @@ #include -#include "aidl/BnBinderStabilityTest.h" +#include "../Utils.h" #include "BnBinderStabilityTest.h" +#include "aidl/BnBinderStabilityTest.h" using namespace android; using namespace ndk; @@ -155,10 +156,9 @@ TEST(BinderStability, NdkForceDowngradeToLocalStability) { } TEST(BinderStability, ForceDowngradeToVendorStability) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() auto server = interface_cast(serverBinder); ASSERT_NE(nullptr, server.get()); @@ -209,10 +209,9 @@ TEST(BinderStability, ConnectionInfoRequiresManifestEntries) { EXPECT_EQ(connectionInfo, std::nullopt); } TEST(BinderStability, CantCallVendorBinderInSystemContext) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() auto server = interface_cast(serverBinder); ASSERT_NE(nullptr, server.get()); @@ -316,11 +315,10 @@ static AIBinder_Class* kNdkBadStableBinder = extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") SpAIBinder binder = SpAIBinder(AServiceManager_getService( String8(kSystemStabilityServer).c_str())); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() std::shared_ptr remoteServer = aidl::IBinderStabilityTest::fromBinder(binder); -- GitLab From 370408e8d796adabaa84e4e2d488d529f9f1b38f Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Fri, 21 Jun 2024 15:45:26 -0700 Subject: [PATCH 083/530] Binder: enable/fix some warnings Bug: 341997808 Test: mma Change-Id: Ibd44eda768a714e85399a15f3c8e534d715f87ce Merged-In: Ibd44eda768a714e85399a15f3c8e534d715f87ce --- libs/binder/IPCThreadState.cpp | 2 + libs/binder/PersistableBundle.cpp | 4 +- libs/binder/Utils.h | 13 +++ .../include_ndk/android/persistable_bundle.h | 5 + libs/binder/ndk/service_manager.cpp | 3 + libs/binder/ndk/tests/Android.bp | 5 + libs/binder/ndk/tests/iface.cpp | 7 +- .../ndk/tests/libbinder_ndk_unit_test.cpp | 102 ++++++++---------- libs/binder/tests/binderClearBufTest.cpp | 5 +- .../tests/binderDriverInterfaceTest.cpp | 12 ++- libs/binder/tests/binderLibTest.cpp | 27 +++-- libs/binder/tests/binderStabilityTest.cpp | 18 ++-- 12 files changed, 107 insertions(+), 96 deletions(-) diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp index 94f947fce1..984c93d370 100644 --- a/libs/binder/IPCThreadState.cpp +++ b/libs/binder/IPCThreadState.cpp @@ -285,7 +285,9 @@ static const void* printCommand(std::ostream& out, const void* _cmd) { return cmd; } +LIBBINDER_IGNORE("-Wzero-as-null-pointer-constant") static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; +LIBBINDER_IGNORE_END() static std::atomic gHaveTLS(false); static pthread_key_t gTLS = 0; static std::atomic gShutdown = false; diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp index 5b157cc7c3..abb6612a1c 100644 --- a/libs/binder/PersistableBundle.cpp +++ b/libs/binder/PersistableBundle.cpp @@ -113,7 +113,7 @@ status_t PersistableBundle::writeToParcel(Parcel* parcel) const { // Backpatch length. This length value includes the length header. parcel->setDataPosition(length_pos); size_t length = end_pos - start_pos; - if (length > std::numeric_limits::max()) { + if (length > static_cast(std::numeric_limits::max())) { ALOGE("Parcel length (%zu) too large to store in 32-bit signed int", length); return BAD_VALUE; } @@ -319,7 +319,7 @@ status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const { * pairs themselves. */ size_t num_entries = size(); - if (num_entries > std::numeric_limits::max()) { + if (num_entries > static_cast(std::numeric_limits::max())) { ALOGE("The size of this PersistableBundle (%zu) too large to store in 32-bit signed int", num_entries); return BAD_VALUE; diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h index 5e1012af01..881cdf3f4c 100644 --- a/libs/binder/Utils.h +++ b/libs/binder/Utils.h @@ -58,6 +58,19 @@ } \ } while (0) +#define LIBBINDER_PRAGMA(arg) _Pragma(#arg) +#if defined(__clang__) +#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) LIBBINDER_PRAGMA(clang arg) +#elif defined(__GNUC__) +#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) LIBBINDER_PRAGMA(GCC arg) +#else +#define LIBBINDER_PRAGMA_FOR_COMPILER(arg) +#endif +#define LIBBINDER_IGNORE(warning_flag) \ + LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic push) \ + LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic ignored warning_flag) +#define LIBBINDER_IGNORE_END() LIBBINDER_PRAGMA_FOR_COMPILER(diagnostic pop) + namespace android { /** diff --git a/libs/binder/ndk/include_ndk/android/persistable_bundle.h b/libs/binder/ndk/include_ndk/android/persistable_bundle.h index 42ae15ae61..5e0d4da97b 100644 --- a/libs/binder/ndk/include_ndk/android/persistable_bundle.h +++ b/libs/binder/ndk/include_ndk/android/persistable_bundle.h @@ -29,6 +29,11 @@ #include #include +#ifndef __clang__ +#define _Nullable +#define _Nonnull +#endif + __BEGIN_DECLS /* diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index 5529455cc6..259cced32b 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -18,6 +18,7 @@ #include #include +#include "../Utils.h" #include "ibinder_internal.h" #include "status_internal.h" @@ -71,7 +72,9 @@ AIBinder* AServiceManager_getService(const char* instance) { } sp sm = defaultServiceManager(); + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp binder = sm->getService(String16(instance)); + LIBBINDER_IGNORE_END() sp ret = ABpBinder::lookupOrCreateFromBinder(binder); AIBinder_incStrong(ret.get()); diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp index 8fb755cdac..c61a16413b 100644 --- a/libs/binder/ndk/tests/Android.bp +++ b/libs/binder/ndk/tests/Android.bp @@ -34,6 +34,11 @@ cc_defaults { cflags: [ "-O0", "-g", + "-Wall", + "-Wextra", + "-Wextra-semi", + "-Werror", + "-Winconsistent-missing-override", ], } diff --git a/libs/binder/ndk/tests/iface.cpp b/libs/binder/ndk/tests/iface.cpp index 3ee36cd8c3..a532ae1db2 100644 --- a/libs/binder/ndk/tests/iface.cpp +++ b/libs/binder/ndk/tests/iface.cpp @@ -20,6 +20,8 @@ #include +#include "../../Utils.h" + using ::android::sp; using ::android::wp; @@ -156,10 +158,9 @@ binder_status_t IFoo::addService(const char* instance) { } sp IFoo::getService(const char* instance, AIBinder** outBinder) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() if (binder == nullptr) { return nullptr; } diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index e2697c647c..2bc1422bed 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -42,6 +42,7 @@ #include #include +#include "../Utils.h" #include "android/binder_ibinder.h" using namespace android; @@ -69,21 +70,21 @@ class MyTestFoo : public IFoo { }; class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { - ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) { + ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) override { *out = in; return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus takeInterface(const std::shared_ptr& empty) { + ndk::ScopedAStatus takeInterface(const std::shared_ptr& empty) override { (void)empty; return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus forceFlushCommands() { + ndk::ScopedAStatus forceFlushCommands() override { // warning: this is assuming that libbinder_ndk is using the same copy // of libbinder that we are. android::IPCThreadState::self()->flushCommands(); return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus getsRequestedSid(bool* out) { + ndk::ScopedAStatus getsRequestedSid(bool* out) override { const char* sid = AIBinder_getCallingSid(); std::cout << "Got security context: " << (sid ?: "null") << std::endl; *out = sid != nullptr; @@ -97,11 +98,11 @@ class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest { fsync(out); return STATUS_OK; } - ndk::ScopedAStatus forcePersist(bool persist) { + ndk::ScopedAStatus forcePersist(bool persist) override { AServiceManager_forceLazyServicesPersist(persist); return ndk::ScopedAStatus::ok(); } - ndk::ScopedAStatus setCustomActiveServicesCallback() { + ndk::ScopedAStatus setCustomActiveServicesCallback() override { AServiceManager_setActiveServicesCallback(activeServicesCallback, this); return ndk::ScopedAStatus::ok(); } @@ -342,10 +343,9 @@ TEST(NdkBinder, UnimplementedShell) { // libbinder across processes to the NDK service which doesn't implement // shell static const sp sm(android::defaultServiceManager()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp testService = sm->getService(String16(IFoo::kSomeInstanceName)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() Vector argsVec; EXPECT_EQ(OK, IBinder::shellCommand(testService, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, @@ -388,10 +388,9 @@ TEST(NdkBinder, GetTestServiceStressTest) { // checkService on it, since the other process serving it might not be started yet. { // getService, not waitForService, to take advantage of timeout -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") auto binder = ndk::SpAIBinder(AServiceManager_getService(IFoo::kSomeInstanceName)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder.get()); } @@ -425,7 +424,7 @@ TEST(NdkBinder, GetDeclaredInstances) { // At the time of writing this test, there is no good interface guaranteed // to be on all devices. Cuttlefish has light, so this will generally test // things. - EXPECT_EQ(count, hasLight ? 1 : 0); + EXPECT_EQ(count, hasLight ? 1u : 0u); } TEST(NdkBinder, GetLazyService) { @@ -515,7 +514,7 @@ void LambdaOnDeath(void* cookie) { // may reference other cookie members (*funcs->onDeath)(); -}; +} void LambdaOnUnlink(void* cookie) { auto funcs = static_cast(cookie); (*funcs->onUnlink)(); @@ -523,7 +522,7 @@ void LambdaOnUnlink(void* cookie) { // may reference other cookie members delete funcs; -}; +} TEST(NdkBinder, DeathRecipient) { using namespace std::chrono_literals; @@ -581,10 +580,9 @@ TEST(NdkBinder, DeathRecipient) { } TEST(NdkBinder, RetrieveNonNdkService) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder); EXPECT_TRUE(AIBinder_isRemote(binder)); EXPECT_TRUE(AIBinder_isAlive(binder)); @@ -598,10 +596,9 @@ void OnBinderDeath(void* cookie) { } TEST(NdkBinder, LinkToDeath) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder); AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath); @@ -631,10 +628,9 @@ TEST(NdkBinder, SetInheritRt) { } TEST(NdkBinder, SetInheritRtNonLocal) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(binder, nullptr); ASSERT_TRUE(AIBinder_isRemote(binder)); @@ -670,14 +666,13 @@ TEST(NdkBinder, GetServiceInProcess) { } TEST(NdkBinder, EqualityOfRemoteBinderPointer) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService); ASSERT_NE(nullptr, binderA); AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService); ASSERT_NE(nullptr, binderB); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() EXPECT_EQ(binderA, binderB); @@ -691,10 +686,9 @@ TEST(NdkBinder, ToFromJavaNullptr) { } TEST(NdkBinder, ABpBinderRefCount) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") AIBinder* binder = AServiceManager_getService(kExistingNonNdkService); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() AIBinder_Weak* wBinder = AIBinder_Weak_new(binder); ASSERT_NE(nullptr, binder); @@ -717,10 +711,9 @@ TEST(NdkBinder, AddServiceMultipleTimes) { } TEST(NdkBinder, RequestedSidWorks) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() std::shared_ptr service = aidl::IBinderNdkUnitTest::fromBinder(binder); @@ -743,10 +736,9 @@ TEST(NdkBinder, SentAidlBinderCanBeDestroyed) { std::shared_ptr empty = ndk::SharedRefBase::make(); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") ndk::SpAIBinder binder(AServiceManager_getService(kBinderNdkUnitTestService)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() std::shared_ptr service = aidl::IBinderNdkUnitTest::fromBinder(binder); @@ -767,14 +759,11 @@ TEST(NdkBinder, SentAidlBinderCanBeDestroyed) { } TEST(NdkBinder, ConvertToPlatformBinder) { - for (const ndk::SpAIBinder& binder : - {// remote -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)), -#pragma clang diagnostic pop - // local - ndk::SharedRefBase::make()->asBinder()}) { + LIBBINDER_IGNORE("-Wdeprecated-declarations") + ndk::SpAIBinder remoteBinder(AServiceManager_getService(kBinderNdkUnitTestService)); + LIBBINDER_IGNORE_END() + auto localBinder = ndk::SharedRefBase::make()->asBinder(); + for (const ndk::SpAIBinder& binder : {remoteBinder, localBinder}) { // convert to platform binder EXPECT_NE(binder, nullptr); sp platformBinder = AIBinder_toPlatformBinder(binder.get()); @@ -803,14 +792,11 @@ TEST(NdkBinder, ConvertToPlatformParcel) { } TEST(NdkBinder, GetAndVerifyScopedAIBinder_Weak) { - for (const ndk::SpAIBinder& binder : - {// remote -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)), -#pragma clang diagnostic pop - // local - ndk::SharedRefBase::make()->asBinder()}) { + LIBBINDER_IGNORE("-Wdeprecated-declarations") + ndk::SpAIBinder remoteBinder(AServiceManager_getService(kBinderNdkUnitTestService)); + LIBBINDER_IGNORE_END() + auto localBinder = ndk::SharedRefBase::make()->asBinder(); + for (const ndk::SpAIBinder& binder : {remoteBinder, localBinder}) { // get a const ScopedAIBinder_Weak and verify promote EXPECT_NE(binder.get(), nullptr); const ndk::ScopedAIBinder_Weak wkAIBinder = @@ -879,7 +865,7 @@ std::string shellCmdToString(sp unitTestService, const std::vector resultReceiver = new MyResultReceiver(); Vector argsVec; - for (int i = 0; i < args.size(); i++) { + for (size_t i = 0; i < args.size(); i++) { argsVec.add(String16(args[i])); } status_t error = IBinder::shellCommand(unitTestService, inFd[0], outFd[0], errFd[0], argsVec, @@ -903,10 +889,9 @@ std::string shellCmdToString(sp unitTestService, const std::vector sm(android::defaultServiceManager()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp testService = sm->getService(String16(kBinderNdkUnitTestService)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() EXPECT_EQ("", shellCmdToString(testService, {})); EXPECT_EQ("", shellCmdToString(testService, {"", ""})); @@ -916,10 +901,9 @@ TEST(NdkBinder, UseHandleShellCommand) { TEST(NdkBinder, FlaggedServiceAccessible) { static const sp sm(android::defaultServiceManager()); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp testService = sm->getService(String16(kBinderNdkUnitTestServiceFlagged)); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, testService); } diff --git a/libs/binder/tests/binderClearBufTest.cpp b/libs/binder/tests/binderClearBufTest.cpp index 3230a3f904..63254cddd9 100644 --- a/libs/binder/tests/binderClearBufTest.cpp +++ b/libs/binder/tests/binderClearBufTest.cpp @@ -75,10 +75,9 @@ class FooBar : public BBinder { }; TEST(BinderClearBuf, ClearKernelBuffer) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp binder = defaultServiceManager()->getService(kServerName); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_NE(nullptr, binder); std::string replyBuffer; diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp index de9d42bac0..7be4f21cee 100644 --- a/libs/binder/tests/binderDriverInterfaceTest.cpp +++ b/libs/binder/tests/binderDriverInterfaceTest.cpp @@ -94,8 +94,9 @@ class BinderDriverInterfaceTest : public ::testing::Test { ret = ioctl(m_binderFd, cmd, arg); EXPECT_EQ(expect_ret, ret); if (ret < 0) { - if (errno != accept_errno) + if (errno != accept_errno) { EXPECT_EQ(expect_errno, errno); + } } } void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) { @@ -275,12 +276,15 @@ TEST_F(BinderDriverInterfaceTest, Transaction) { binderTestIoctl(BINDER_WRITE_READ, &bwr); } EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed); - if (bwr.read_consumed > offsetof(typeof(br), cmd0)) + if (bwr.read_consumed > offsetof(typeof(br), cmd0)) { EXPECT_EQ(BR_NOOP, br.cmd0); - if (bwr.read_consumed > offsetof(typeof(br), cmd1)) + } + if (bwr.read_consumed > offsetof(typeof(br), cmd1)) { EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1); - if (bwr.read_consumed > offsetof(typeof(br), cmd2)) + } + if (bwr.read_consumed > offsetof(typeof(br), cmd2)) { EXPECT_EQ(BR_REPLY, br.cmd2); + } if (bwr.read_consumed >= offsetof(typeof(br), pad)) { EXPECT_EQ(0u, br.arg2.target.ptr); EXPECT_EQ(0u, br.arg2.cookie); diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index 5582a96ac1..9b1ba01146 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -47,10 +47,9 @@ #include #include +#include "../Utils.h" #include "../binder_module.h" -#define ARRAY_SIZE(array) (sizeof array / sizeof array[0]) - using namespace android; using namespace android::binder::impl; using namespace std::string_literals; @@ -216,10 +215,9 @@ class BinderLibTestEnv : public ::testing::Environment { sp sm = defaultServiceManager(); //printf("%s: pid %d, get service\n", __func__, m_pid); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") m_server = sm->getService(binderLibTestServiceName); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() ASSERT_TRUE(m_server != nullptr); //printf("%s: pid %d, get service done\n", __func__, m_pid); } @@ -566,7 +564,7 @@ TEST_F(BinderLibTest, Freeze) { TEST_F(BinderLibTest, SetError) { int32_t testValue[] = { 0, -123, 123 }; - for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) { + for (size_t i = 0; i < countof(testValue); i++) { Parcel data, reply; data.writeInt32(testValue[i]); EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply), @@ -597,8 +595,8 @@ TEST_F(BinderLibTest, IndirectGetId2) Parcel data, reply; int32_t serverId[3]; - data.writeInt32(ARRAY_SIZE(serverId)); - for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) { + data.writeInt32(countof(serverId)); + for (size_t i = 0; i < countof(serverId); i++) { sp server; BinderLibTestBundle datai; @@ -616,7 +614,7 @@ TEST_F(BinderLibTest, IndirectGetId2) EXPECT_EQ(0, id); ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR)); - EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count); + EXPECT_EQ(countof(serverId), (size_t)count); for (size_t i = 0; i < (size_t)count; i++) { BinderLibTestBundle replyi(&reply); @@ -636,8 +634,8 @@ TEST_F(BinderLibTest, IndirectGetId3) Parcel data, reply; int32_t serverId[3]; - data.writeInt32(ARRAY_SIZE(serverId)); - for (size_t i = 0; i < ARRAY_SIZE(serverId); i++) { + data.writeInt32(countof(serverId)); + for (size_t i = 0; i < countof(serverId); i++) { sp server; BinderLibTestBundle datai; BinderLibTestBundle datai2; @@ -662,7 +660,7 @@ TEST_F(BinderLibTest, IndirectGetId3) EXPECT_EQ(0, id); ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR)); - EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count); + EXPECT_EQ(countof(serverId), (size_t)count); for (size_t i = 0; i < (size_t)count; i++) { int32_t counti; @@ -2112,10 +2110,9 @@ int run_server(int index, int readypipefd, bool usePoll) if (index == 0) { ret = sm->addService(binderLibTestServiceName, testService); } else { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp server = sm->getService(binderLibTestServiceName); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() Parcel data, reply; data.writeInt32(index); data.writeStrongBinder(testService); diff --git a/libs/binder/tests/binderStabilityTest.cpp b/libs/binder/tests/binderStabilityTest.cpp index 3d993588a4..7a8f48e0eb 100644 --- a/libs/binder/tests/binderStabilityTest.cpp +++ b/libs/binder/tests/binderStabilityTest.cpp @@ -27,8 +27,9 @@ #include -#include "aidl/BnBinderStabilityTest.h" +#include "../Utils.h" #include "BnBinderStabilityTest.h" +#include "aidl/BnBinderStabilityTest.h" using namespace android; using namespace ndk; @@ -155,10 +156,9 @@ TEST(BinderStability, NdkForceDowngradeToLocalStability) { } TEST(BinderStability, ForceDowngradeToVendorStability) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() auto server = interface_cast(serverBinder); ASSERT_NE(nullptr, server.get()); @@ -209,10 +209,9 @@ TEST(BinderStability, ConnectionInfoRequiresManifestEntries) { EXPECT_EQ(connectionInfo, std::nullopt); } TEST(BinderStability, CantCallVendorBinderInSystemContext) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") sp serverBinder = android::defaultServiceManager()->getService(kSystemStabilityServer); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() auto server = interface_cast(serverBinder); ASSERT_NE(nullptr, server.get()); @@ -316,11 +315,10 @@ static AIBinder_Class* kNdkBadStableBinder = extern "C" void AIBinder_markVendorStability(AIBinder* binder); // <- BAD DO NOT COPY TEST(BinderStability, NdkCantCallVendorBinderInSystemContext) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + LIBBINDER_IGNORE("-Wdeprecated-declarations") SpAIBinder binder = SpAIBinder(AServiceManager_getService( String8(kSystemStabilityServer).c_str())); -#pragma clang diagnostic pop + LIBBINDER_IGNORE_END() std::shared_ptr remoteServer = aidl::IBinderStabilityTest::fromBinder(binder); -- GitLab From 4a5441fe4d60ce20f8de052d4439d4c549e300c4 Mon Sep 17 00:00:00 2001 From: Yu-Ting Tseng Date: Thu, 20 Jun 2024 13:33:55 -0700 Subject: [PATCH 084/530] Placeholder for binder freeze notification API. Adding the placeholder APIs to validate whether this breaks existing prebuilts. Bug: 338097747 Change-Id: Id7357076ad98c1f220a78186fe509326047cf922 Test: m --- libs/binder/Binder.cpp | 8 ++++++++ libs/binder/BpBinder.cpp | 8 ++++++++ libs/binder/include/binder/Binder.h | 7 +++++++ libs/binder/include/binder/BpBinder.h | 6 ++++++ libs/binder/include/binder/IBinder.h | 17 ++++++++++++++--- 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index c57c9cdd62..6185b7baf8 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -441,6 +441,14 @@ status_t BBinder::unlinkToDeath( return INVALID_OPERATION; } +status_t BBinder::addFrozenStateChangeCallback(const wp&) { + return INVALID_OPERATION; +} + +status_t BBinder::removeFrozenStateChangeCallback(const wp&) { + return INVALID_OPERATION; +} + status_t BBinder::dump(int /*fd*/, const Vector& /*args*/) { return NO_ERROR; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 6594aa6309..59c5be75ac 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -557,6 +557,14 @@ void BpBinder::sendObituary() } } +status_t BpBinder::addFrozenStateChangeCallback(const wp&) { + return INVALID_OPERATION; +} + +status_t BpBinder::removeFrozenStateChangeCallback(const wp&) { + return INVALID_OPERATION; +} + void BpBinder::reportOneDeath(const Obituary& obit) { sp recipient = obit.recipient.promote(); diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h index 135be89c6c..802a3bcd06 100644 --- a/libs/binder/include/binder/Binder.h +++ b/libs/binder/include/binder/Binder.h @@ -50,6 +50,13 @@ public: void* cookie = nullptr, uint32_t flags = 0, wp* outRecipient = nullptr); + // Placeholders to test if adding virtual functions here breaks things. + // Will be replaced by an actual API once things are verified to work. + LIBBINDER_EXPORTED virtual status_t addFrozenStateChangeCallback( + const wp& callback); + LIBBINDER_EXPORTED virtual status_t removeFrozenStateChangeCallback( + const wp& callback); + LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) final; diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index d7f74c4152..0f52f6df52 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -66,6 +66,12 @@ public: void* cookie = nullptr, uint32_t flags = 0, wp* outRecipient = nullptr); + [[nodiscard]] virtual status_t addFrozenStateChangeCallback( + const wp& recipient); + + [[nodiscard]] virtual status_t removeFrozenStateChangeCallback( + const wp& recipient); + LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) final; diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h index 17248ce289..62d7354387 100644 --- a/libs/binder/include/binder/IBinder.h +++ b/libs/binder/include/binder/IBinder.h @@ -198,9 +198,14 @@ public: virtual void binderDied(const wp& who) = 0; }; - #if defined(__clang__) - #pragma clang diagnostic pop - #endif + class FrozenStateChangeCallback : public virtual RefBase { + public: + virtual void onStateChanged(const wp& who, bool isFrozen) = 0; + }; + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif /** * Register the @a recipient for a notification if this binder @@ -249,6 +254,12 @@ public: uint32_t flags = 0, wp* outRecipient = nullptr) = 0; + // Placeholders. See Binder.h for details. + [[nodiscard]] virtual status_t addFrozenStateChangeCallback( + const wp& callback) = 0; + [[nodiscard]] virtual status_t removeFrozenStateChangeCallback( + const wp& callback) = 0; + virtual bool checkSubclass(const void* subclassID) const; typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie); -- GitLab From 5e9bccbc4c27bbd5e50b38cc6346faabbaa031db Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Wed, 3 Jul 2024 23:23:54 +0000 Subject: [PATCH 085/530] binder_bpBinderFuzz: log socket unlink failure A spurious, rare failure in this fuzzer can be disambiguated by knowing if unlink fails. Fixes: 346502426 Test: run binder_bpBinderFuzz Change-Id: Idf5d884537a004c6308bc905c166f4949c31bd74 --- libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp index a6fd487fe5..bc0d5af66f 100644 --- a/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp +++ b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp @@ -36,7 +36,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { FuzzedDataProvider fdp(data, size); std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark"; - (void)unlink(addr.c_str()); + if (0 != unlink(addr.c_str()) && errno != ENOENT) { + LOG(WARNING) << "Could not unlink: " << strerror(errno); + } sp server = RpcServer::make(); -- GitLab From dcc9d9b5cf697d238cbdca93a99a7a3aa48281fe Mon Sep 17 00:00:00 2001 From: Marzia Favaro Date: Wed, 10 Jan 2024 10:17:00 +0000 Subject: [PATCH 086/530] Edge extension effect: shader reimplementation X-axis activity transitions require the translation of the surfaces involved. As this movement would create unwanted see-through, we would have added side windows anchored to the moving activities, and textured them by clamping their parents. We are replacing the additional windows with the extension of the surfaces, and filling the area without buffer with a shader. See go/edge-extension-sksl for more info. Bug: 322036393 Test: LayerSnapshotTest Flag: EXEMPT (calls will be protected by wm shell with com.android.window.flags.edge_extension_shader) Change-Id: I3682efd16a1b311d67a522bb85960f100948b2ea --- libs/gui/LayerState.cpp | 7 ++ libs/gui/SurfaceComposerClient.cpp | 14 +++ .../android/gui/EdgeExtensionParameters.aidl | 27 ++++++ libs/gui/include/gui/LayerState.h | 7 +- libs/gui/include/gui/SurfaceComposerClient.h | 12 +++ libs/renderengine/Android.bp | 1 + .../include/renderengine/LayerSettings.h | 14 ++- libs/renderengine/skia/SkiaRenderEngine.cpp | 47 +++++---- libs/renderengine/skia/SkiaRenderEngine.h | 3 + .../filters/EdgeExtensionShaderFactory.cpp | 80 ++++++++++++++++ .../skia/filters/EdgeExtensionShaderFactory.h | 42 ++++++++ libs/ui/include/ui/EdgeExtensionEffect.h | 95 +++++++++++++++++++ .../LayerFECompositionState.h | 5 + .../src/ClientCompositionRequestCache.cpp | 3 +- .../surfaceflinger/FrontEnd/LayerSnapshot.cpp | 10 +- .../FrontEnd/LayerSnapshotBuilder.cpp | 67 ++++++++++++- .../FrontEnd/LayerSnapshotBuilder.h | 4 + .../FrontEnd/RequestedLayerState.cpp | 5 +- services/surfaceflinger/LayerFE.cpp | 1 + 19 files changed, 413 insertions(+), 31 deletions(-) create mode 100644 libs/gui/aidl/android/gui/EdgeExtensionParameters.aidl create mode 100644 libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp create mode 100644 libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h create mode 100644 libs/ui/include/ui/EdgeExtensionEffect.h diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 3745805aa3..307ae3990e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -177,6 +177,7 @@ status_t layer_state_t::write(Parcel& output) const } SAFE_PARCEL(output.write, stretchEffect); + SAFE_PARCEL(output.writeParcelable, edgeExtensionParameters); SAFE_PARCEL(output.write, bufferCrop); SAFE_PARCEL(output.write, destinationFrame); SAFE_PARCEL(output.writeInt32, static_cast(trustedOverlay)); @@ -306,6 +307,7 @@ status_t layer_state_t::read(const Parcel& input) } SAFE_PARCEL(input.read, stretchEffect); + SAFE_PARCEL(input.readParcelable, &edgeExtensionParameters); SAFE_PARCEL(input.read, bufferCrop); SAFE_PARCEL(input.read, destinationFrame); uint32_t trustedOverlayInt; @@ -682,6 +684,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eStretchChanged; stretchEffect = other.stretchEffect; } + if (other.what & eEdgeExtensionChanged) { + what |= eEdgeExtensionChanged; + edgeExtensionParameters = other.edgeExtensionParameters; + } if (other.what & eBufferCropChanged) { what |= eBufferCropChanged; bufferCrop = other.bufferCrop; @@ -783,6 +789,7 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const { CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh); CHECK_DIFF(diff, eTrustedOverlayChanged, other, trustedOverlay); CHECK_DIFF(diff, eStretchChanged, other, stretchEffect); + CHECK_DIFF(diff, eEdgeExtensionChanged, other, edgeExtensionParameters); CHECK_DIFF(diff, eBufferCropChanged, other, bufferCrop); CHECK_DIFF(diff, eDestinationFrameChanged, other, destinationFrame); if (other.what & eProducerDisconnect) diff |= eProducerDisconnect; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 902684cf03..88d3a7cb1d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -2330,6 +2331,19 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setStret return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setEdgeExtensionEffect( + const sp& sc, const gui::EdgeExtensionParameters& effect) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eEdgeExtensionChanged; + s->edgeExtensionParameters = effect; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBufferCrop( const sp& sc, const Rect& bufferCrop) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/aidl/android/gui/EdgeExtensionParameters.aidl b/libs/gui/aidl/android/gui/EdgeExtensionParameters.aidl new file mode 100644 index 0000000000..44f4259f74 --- /dev/null +++ b/libs/gui/aidl/android/gui/EdgeExtensionParameters.aidl @@ -0,0 +1,27 @@ +/* + * Copyright 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. + */ + +package android.gui; + + +/** @hide */ +parcelable EdgeExtensionParameters { + // These represent the translation of the window as requested by the animation + boolean extendRight; + boolean extendLeft; + boolean extendTop; + boolean extendBottom; +} \ No newline at end of file diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 5f2f8dc013..3fb1894585 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -218,6 +219,7 @@ struct layer_state_t { eTrustedOverlayChanged = 0x4000'00000000, eDropInputModeChanged = 0x8000'00000000, eExtendedRangeBrightnessChanged = 0x10000'00000000, + eEdgeExtensionChanged = 0x20000'00000000, }; layer_state_t(); @@ -241,7 +243,7 @@ struct layer_state_t { layer_state_t::eCropChanged | layer_state_t::eDestinationFrameChanged | layer_state_t::eMatrixChanged | layer_state_t::ePositionChanged | layer_state_t::eTransformToDisplayInverseChanged | - layer_state_t::eTransparentRegionChanged; + layer_state_t::eTransparentRegionChanged | layer_state_t::eEdgeExtensionChanged; // Buffer and related updates. static constexpr uint64_t BUFFER_CHANGES = layer_state_t::eApiChanged | @@ -393,6 +395,9 @@ struct layer_state_t { // Stretch effect to be applied to this layer StretchEffect stretchEffect; + // Edge extension effect to be applied to this layer + gui::EdgeExtensionParameters edgeExtensionParameters; + Rect bufferCrop; Rect destinationFrame; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 88c0c53e12..a10283b371 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -744,6 +745,17 @@ public: Transaction& setStretchEffect(const sp& sc, const StretchEffect& stretchEffect); + /** + * Provides the edge extension effect configured on a container that the + * surface is rendered within. + * @param sc target surface the edge extension should be applied to + * @param effect the corresponding EdgeExtensionParameters to be applied + * to the surface. + * @return The transaction being constructed + */ + Transaction& setEdgeExtensionEffect(const sp& sc, + const gui::EdgeExtensionParameters& effect); + Transaction& setBufferCrop(const sp& sc, const Rect& bufferCrop); Transaction& setDestinationFrame(const sp& sc, const Rect& destinationFrame); diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 4a04467308..ecf98c6696 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -105,6 +105,7 @@ filegroup { "skia/filters/LinearEffect.cpp", "skia/filters/MouriMap.cpp", "skia/filters/StretchShaderFactory.cpp", + "skia/filters/EdgeExtensionShaderFactory.cpp", ], } diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 8ac0af47c6..859ae8b6e2 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -31,6 +31,7 @@ #include #include #include +#include "ui/EdgeExtensionEffect.h" #include @@ -134,6 +135,7 @@ struct LayerSettings { mat4 blurRegionTransform = mat4(); StretchEffect stretchEffect; + EdgeExtensionEffect edgeExtensionEffect; // Name associated with the layer for debugging purposes. std::string name; @@ -183,7 +185,9 @@ static inline bool operator==(const LayerSettings& lhs, const LayerSettings& rhs lhs.skipContentDraw == rhs.skipContentDraw && lhs.shadow == rhs.shadow && lhs.backgroundBlurRadius == rhs.backgroundBlurRadius && lhs.blurRegionTransform == rhs.blurRegionTransform && - lhs.stretchEffect == rhs.stretchEffect && lhs.whitePointNits == rhs.whitePointNits; + lhs.stretchEffect == rhs.stretchEffect && + lhs.edgeExtensionEffect == rhs.edgeExtensionEffect && + lhs.whitePointNits == rhs.whitePointNits; } static inline void PrintTo(const Buffer& settings, ::std::ostream* os) { @@ -254,6 +258,10 @@ static inline void PrintTo(const StretchEffect& effect, ::std::ostream* os) { *os << "\n}"; } +static inline void PrintTo(const EdgeExtensionEffect& effect, ::std::ostream* os) { + *os << effect; +} + static inline void PrintTo(const LayerSettings& settings, ::std::ostream* os) { *os << "LayerSettings for '" << settings.name.c_str() << "' {"; *os << "\n .geometry = "; @@ -285,6 +293,10 @@ static inline void PrintTo(const LayerSettings& settings, ::std::ostream* os) { *os << "\n .stretchEffect = "; PrintTo(settings.stretchEffect, os); } + + if (settings.edgeExtensionEffect.hasEffect()) { + *os << "\n .edgeExtensionEffect = " << settings.edgeExtensionEffect; + } *os << "\n .whitePointNits = " << settings.whitePointNits; *os << "\n}"; } diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index 5f37125d16..a609f2d2b3 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -507,16 +507,24 @@ sk_sp SkiaRenderEngine::createRuntimeEffectShader( const RuntimeEffectShaderParameters& parameters) { // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces - // Determine later on if we need to leverage the stertch shader within + // Determine later on if we need to leverage the stretch shader within // surface flinger const auto& stretchEffect = parameters.layer.stretchEffect; const auto& targetBuffer = parameters.layer.source.buffer.buffer; + const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; + auto shader = parameters.shader; - if (stretchEffect.hasEffect()) { - const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; - if (graphicBuffer && shader) { + if (graphicBuffer && parameters.shader) { + if (stretchEffect.hasEffect()) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); } + // The given surface requires to be filled outside of its buffer bounds if the edge + // extension is required + const auto& edgeExtensionEffect = parameters.layer.edgeExtensionEffect; + if (edgeExtensionEffect.hasEffect()) { + shader = mEdgeExtensionShaderFactory.createSkShader(shader, parameters.layer, + parameters.imageBounds); + } } if (parameters.requiresLinearEffect) { @@ -566,8 +574,6 @@ sk_sp SkiaRenderEngine::createRuntimeEffectShader( parameters.layerDimmingRatio, 1.f)); } - const auto targetBuffer = parameters.layer.source.buffer.buffer; - const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; const auto hardwareBuffer = graphicBuffer ? graphicBuffer->toAHardwareBuffer() : nullptr; return createLinearEffectShader(shader, effect, runtimeEffect, std::move(colorTransform), parameters.display.maxLuminance, @@ -1039,18 +1045,20 @@ void SkiaRenderEngine::drawLayersInternal( toSkColorSpace(layerDataspace))); } - paint.setShader(createRuntimeEffectShader( - RuntimeEffectShaderParameters{.shader = shader, - .layer = layer, - .display = display, - .undoPremultipliedAlpha = !item.isOpaque && - item.usePremultipliedAlpha, - .requiresLinearEffect = requiresLinearEffect, - .layerDimmingRatio = dimInLinearSpace - ? layerDimmingRatio - : 1.f, - .outputDataSpace = display.outputDataspace, - .fakeOutputDataspace = fakeDataspace})); + SkRect imageBounds; + matrix.mapRect(&imageBounds, SkRect::Make(image->bounds())); + + paint.setShader(createRuntimeEffectShader(RuntimeEffectShaderParameters{ + .shader = shader, + .layer = layer, + .display = display, + .undoPremultipliedAlpha = !item.isOpaque && item.usePremultipliedAlpha, + .requiresLinearEffect = requiresLinearEffect, + .layerDimmingRatio = dimInLinearSpace ? layerDimmingRatio : 1.f, + .outputDataSpace = display.outputDataspace, + .fakeOutputDataspace = fakeDataspace, + .imageBounds = imageBounds, + })); // Turn on dithering when dimming beyond this (arbitrary) threshold... static constexpr float kDimmingThreshold = 0.9f; @@ -1118,7 +1126,8 @@ void SkiaRenderEngine::drawLayersInternal( .requiresLinearEffect = requiresLinearEffect, .layerDimmingRatio = layerDimmingRatio, .outputDataSpace = display.outputDataspace, - .fakeOutputDataspace = fakeDataspace})); + .fakeOutputDataspace = fakeDataspace, + .imageBounds = SkRect::MakeEmpty()})); } if (layer.disableBlending) { diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index c8f9241257..224a1cad92 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -38,6 +38,7 @@ #include "compat/SkiaGpuContext.h" #include "debug/SkiaCapture.h" #include "filters/BlurFilter.h" +#include "filters/EdgeExtensionShaderFactory.h" #include "filters/LinearEffect.h" #include "filters/StretchShaderFactory.h" @@ -156,6 +157,7 @@ private: float layerDimmingRatio; const ui::Dataspace outputDataSpace; const ui::Dataspace fakeOutputDataspace; + const SkRect& imageBounds; }; sk_sp createRuntimeEffectShader(const RuntimeEffectShaderParameters&); @@ -175,6 +177,7 @@ private: AutoBackendTexture::CleanupManager mTextureCleanupMgr GUARDED_BY(mRenderingMutex); StretchShaderFactory mStretchShaderFactory; + EdgeExtensionShaderFactory mEdgeExtensionShaderFactory; sp mLastDrawFence; BlurFilter* mBlurFilter = nullptr; diff --git a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp new file mode 100644 index 0000000000..1dbcc29190 --- /dev/null +++ b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp @@ -0,0 +1,80 @@ +/* + * 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. + */ + +#include "EdgeExtensionShaderFactory.h" +#include +#include +#include +#include +#include "log/log_main.h" + +namespace android::renderengine::skia { + +static const SkString edgeShader = SkString(R"( + uniform shader uContentTexture; + uniform vec2 uImgSize; + + // TODO(b/214232209) oobTolerance is temporary and will be removed when the scrollbar will be + // hidden during the animation + const float oobTolerance = 15; + const int blurRadius = 3; + const float blurArea = float((2 * blurRadius + 1) * (2 * blurRadius + 1)); + + vec4 boxBlur(vec2 p) { + vec4 sumColors = vec4(0); + + for (int i = -blurRadius; i <= blurRadius; i++) { + for (int j = -blurRadius; j <= blurRadius; j++) { + sumColors += uContentTexture.eval(p + vec2(i, j)); + } + } + return sumColors / blurArea; + } + + vec4 main(vec2 coord) { + vec2 nearestTexturePoint = clamp(coord, vec2(0, 0), uImgSize); + if (coord == nearestTexturePoint) { + return uContentTexture.eval(coord); + } else { + vec2 samplePoint = nearestTexturePoint + oobTolerance * normalize( + nearestTexturePoint - coord); + return boxBlur(samplePoint); + } + } +)"); + +sk_sp EdgeExtensionShaderFactory::createSkShader(const sk_sp& inputShader, + const LayerSettings& layer, + const SkRect& imageBounds) { + if (mBuilder == nullptr) { + const static SkRuntimeEffect::Result instance = SkRuntimeEffect::MakeForShader(edgeShader); + if (!instance.errorText.isEmpty()) { + ALOGE("EdgeExtensionShaderFactory terminated with an error: %s", + instance.errorText.c_str()); + return nullptr; + } + mBuilder = std::make_unique(instance.effect); + } + mBuilder->child("uContentTexture") = inputShader; + if (imageBounds.isEmpty()) { + mBuilder->uniform("uImgSize") = SkPoint{layer.geometry.boundaries.getWidth(), + layer.geometry.boundaries.getHeight()}; + } else { + mBuilder->uniform("uImgSize") = SkPoint{imageBounds.width(), imageBounds.height()}; + } + return mBuilder->makeShader(); +} +} // namespace android::renderengine::skia \ No newline at end of file diff --git a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h new file mode 100644 index 0000000000..b0a8a9357e --- /dev/null +++ b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace android::renderengine::skia { + +/** + * This shader is designed to prolong the texture of a surface whose bounds have been extended over + * the size of the texture. This shader is similar to the default clamp, but adds a blur effect and + * samples from close to the edge (compared to on the edge) to avoid weird artifacts when elements + * (in particular, scrollbars) touch the edge. + */ +class EdgeExtensionShaderFactory { +public: + sk_sp createSkShader(const sk_sp& inputShader, const LayerSettings& layer, + const SkRect& imageBounds); + +private: + std::unique_ptr mBuilder; +}; +} // namespace android::renderengine::skia diff --git a/libs/ui/include/ui/EdgeExtensionEffect.h b/libs/ui/include/ui/EdgeExtensionEffect.h new file mode 100644 index 0000000000..02126b12be --- /dev/null +++ b/libs/ui/include/ui/EdgeExtensionEffect.h @@ -0,0 +1,95 @@ +/* + * 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. + */ + +#pragma once + +/** + * Stores the edge that will be extended + */ +namespace android { + +enum CanonicalDirections { NONE = 0, LEFT = 1, RIGHT = 2, TOP = 4, BOTTOM = 8 }; + +inline std::string to_string(CanonicalDirections direction) { + switch (direction) { + case LEFT: + return "LEFT"; + case RIGHT: + return "RIGHT"; + case TOP: + return "TOP"; + case BOTTOM: + return "BOTTOM"; + case NONE: + return "NONE"; + } +} + +struct EdgeExtensionEffect { + EdgeExtensionEffect(bool left, bool right, bool top, bool bottom) { + extensionEdges = NONE; + if (left) { + extensionEdges |= LEFT; + } + if (right) { + extensionEdges |= RIGHT; + } + if (top) { + extensionEdges |= TOP; + } + if (bottom) { + extensionEdges |= BOTTOM; + } + } + + EdgeExtensionEffect() { EdgeExtensionEffect(false, false, false, false); } + + bool extendsEdge(CanonicalDirections edge) const { return extensionEdges & edge; } + + bool hasEffect() const { return extensionEdges != NONE; }; + + void reset() { extensionEdges = NONE; } + + bool operator==(const EdgeExtensionEffect& other) const { + return extensionEdges == other.extensionEdges; + } + + bool operator!=(const EdgeExtensionEffect& other) const { return !(*this == other); } + +private: + int extensionEdges; +}; + +inline std::string to_string(const EdgeExtensionEffect& effect) { + std::string s = "EdgeExtensionEffect={edges=["; + if (effect.hasEffect()) { + for (CanonicalDirections edge : {LEFT, RIGHT, TOP, BOTTOM}) { + if (effect.extendsEdge(edge)) { + s += to_string(edge) + ", "; + } + } + } else { + s += to_string(NONE); + } + s += "]}"; + return s; +} + +inline std::ostream& operator<<(std::ostream& os, const EdgeExtensionEffect effect) { + os << to_string(effect); + return os; +} +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 11759b855f..d1429a2ec6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -35,6 +35,7 @@ #pragma clang diagnostic ignored "-Wextra" #include +#include #include #include #include @@ -133,12 +134,16 @@ struct LayerFECompositionState { // The bounds of the layer in layer local coordinates FloatRect geomLayerBounds; + // The crop to apply to the layer in layer local coordinates + FloatRect geomLayerCrop; + ShadowSettings shadowSettings; // List of regions that require blur std::vector blurRegions; StretchEffect stretchEffect; + EdgeExtensionEffect edgeExtensionEffect; /* * Geometry state diff --git a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp index bdaa1d0ae1..d9018bc3ab 100644 --- a/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp +++ b/services/surfaceflinger/CompositionEngine/src/ClientCompositionRequestCache.cpp @@ -37,7 +37,8 @@ inline bool equalIgnoringSource(const renderengine::LayerSettings& lhs, lhs.colorTransform == rhs.colorTransform && lhs.disableBlending == rhs.disableBlending && lhs.shadow == rhs.shadow && lhs.backgroundBlurRadius == rhs.backgroundBlurRadius && - lhs.stretchEffect == rhs.stretchEffect; + lhs.stretchEffect == rhs.stretchEffect && + lhs.edgeExtensionEffect == rhs.edgeExtensionEffect; } inline bool equalIgnoringBuffer(const renderengine::Buffer& lhs, const renderengine::Buffer& rhs) { diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp index 70e3c64a0f..e5f6b7bcd1 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp @@ -322,6 +322,10 @@ std::ostream& operator<<(std::ostream& out, const LayerSnapshot& obj) { << touchableRegion.bottom << "," << touchableRegion.right << "}" << "}"; } + + if (obj.edgeExtensionEffect.hasEffect()) { + out << obj.edgeExtensionEffect; + } return out; } @@ -492,8 +496,10 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate requested.what & (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged | layer_state_t::eApiChanged | layer_state_t::eShadowRadiusChanged | - layer_state_t::eBlurRegionsChanged | layer_state_t::eStretchChanged)) { - forceClientComposition = shadowSettings.length > 0 || stretchEffect.hasEffect(); + layer_state_t::eBlurRegionsChanged | layer_state_t::eStretchChanged | + layer_state_t::eEdgeExtensionChanged)) { + forceClientComposition = shadowSettings.length > 0 || stretchEffect.hasEffect() || + edgeExtensionEffect.hasEffect(); } if (forceUpdate || diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp index 2b1b2c85b3..4e093816dd 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp @@ -367,6 +367,7 @@ LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() { snapshot.geomLayerBounds = getMaxDisplayBounds({}); snapshot.roundedCorner = RoundedCornerState(); snapshot.stretchEffect = {}; + snapshot.edgeExtensionEffect = {}; snapshot.outputFilter.layerStack = ui::DEFAULT_LAYER_STACK; snapshot.outputFilter.toInternalDisplay = false; snapshot.isSecure = false; @@ -811,6 +812,32 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a : parentSnapshot.stretchEffect; } + if (forceUpdate || + (snapshot.clientChanges | parentSnapshot.clientChanges) & + layer_state_t::eEdgeExtensionChanged) { + if (requested.edgeExtensionParameters.extendLeft || + requested.edgeExtensionParameters.extendRight || + requested.edgeExtensionParameters.extendTop || + requested.edgeExtensionParameters.extendBottom) { + // This is the root layer to which the extension is applied + snapshot.edgeExtensionEffect = + EdgeExtensionEffect(requested.edgeExtensionParameters.extendLeft, + requested.edgeExtensionParameters.extendRight, + requested.edgeExtensionParameters.extendTop, + requested.edgeExtensionParameters.extendBottom); + } else if (parentSnapshot.clientChanges & layer_state_t::eEdgeExtensionChanged) { + // Extension is inherited + snapshot.edgeExtensionEffect = parentSnapshot.edgeExtensionEffect; + } else { + // There is no edge extension + snapshot.edgeExtensionEffect.reset(); + } + if (snapshot.edgeExtensionEffect.hasEffect()) { + snapshot.clientChanges |= layer_state_t::eEdgeExtensionChanged; + snapshot.changes |= RequestedLayerState::Changes::Geometry; + } + } + if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) { if (!parentSnapshot.colorTransformIsIdentity) { snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform; @@ -899,6 +926,10 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags); } + if (snapshot.edgeExtensionEffect.hasEffect()) { + updateBoundsForEdgeExtension(snapshot); + } + if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged || snapshot.changes.any(RequestedLayerState::Changes::Geometry | RequestedLayerState::Changes::BufferUsageFlags)) { @@ -917,8 +948,8 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a } // computed snapshot properties - snapshot.forceClientComposition = - snapshot.shadowSettings.length > 0 || snapshot.stretchEffect.hasEffect(); + snapshot.forceClientComposition = snapshot.shadowSettings.length > 0 || + snapshot.stretchEffect.hasEffect() || snapshot.edgeExtensionEffect.hasEffect(); snapshot.contentOpaque = snapshot.isContentOpaque(); snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() && snapshot.color.a == 1.f; @@ -973,6 +1004,31 @@ void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot, } } +/** + * According to the edges that we are requested to extend, we increase the bounds to the maximum + * extension allowed by the crop (parent crop + requested crop). The animation that called + * Transition#setEdgeExtensionEffect is in charge of setting the requested crop. + * @param snapshot + */ +void LayerSnapshotBuilder::updateBoundsForEdgeExtension(LayerSnapshot& snapshot) { + EdgeExtensionEffect& effect = snapshot.edgeExtensionEffect; + + if (effect.extendsEdge(LEFT)) { + snapshot.geomLayerBounds.left = snapshot.geomLayerCrop.left; + } + if (effect.extendsEdge(RIGHT)) { + snapshot.geomLayerBounds.right = snapshot.geomLayerCrop.right; + } + if (effect.extendsEdge(TOP)) { + snapshot.geomLayerBounds.top = snapshot.geomLayerCrop.top; + } + if (effect.extendsEdge(BOTTOM)) { + snapshot.geomLayerBounds.bottom = snapshot.geomLayerCrop.bottom; + } + + snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds); +} + void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& requested, const LayerSnapshot& parentSnapshot, @@ -1012,11 +1068,12 @@ void LayerSnapshotBuilder::updateLayerBounds(LayerSnapshot& snapshot, FloatRect parentBounds = parentSnapshot.geomLayerBounds; parentBounds = snapshot.localTransform.inverse().transform(parentBounds); snapshot.geomLayerBounds = - (requested.externalTexture) ? snapshot.bufferSize.toFloatRect() : parentBounds; + requested.externalTexture ? snapshot.bufferSize.toFloatRect() : parentBounds; + snapshot.geomLayerCrop = parentBounds; if (!requested.crop.isEmpty()) { - snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(requested.crop.toFloatRect()); + snapshot.geomLayerCrop = snapshot.geomLayerCrop.intersect(requested.crop.toFloatRect()); } - snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(parentBounds); + snapshot.geomLayerBounds = snapshot.geomLayerBounds.intersect(snapshot.geomLayerCrop); snapshot.transformedBounds = snapshot.geomLayerTransform.transform(snapshot.geomLayerBounds); const Rect geomLayerBoundsWithoutTransparentRegion = RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds), diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h index dbbad7664a..f3c56a4ef0 100644 --- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h +++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h @@ -113,6 +113,10 @@ private: static void resetRelativeState(LayerSnapshot& snapshot); static void updateRoundedCorner(LayerSnapshot& snapshot, const RequestedLayerState& layerState, const LayerSnapshot& parentSnapshot, const Args& args); + static bool extensionEdgeSharedWithParent(LayerSnapshot& snapshot, + const RequestedLayerState& requested, + const LayerSnapshot& parentSnapshot); + static void updateBoundsForEdgeExtension(LayerSnapshot& snapshot); void updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& layerState, const LayerSnapshot& parentSnapshot, uint32_t displayRotationFlags); static void updateShadows(LayerSnapshot& snapshot, const RequestedLayerState& requested, diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp index 17d3f4bf38..17d2610d7a 100644 --- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp +++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp @@ -609,8 +609,9 @@ bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const { layer_state_t::eSidebandStreamChanged | layer_state_t::eColorSpaceAgnosticChanged | layer_state_t::eShadowRadiusChanged | layer_state_t::eFixedTransformHintChanged | layer_state_t::eTrustedOverlayChanged | layer_state_t::eStretchChanged | - layer_state_t::eBufferCropChanged | layer_state_t::eDestinationFrameChanged | - layer_state_t::eDimmingEnabledChanged | layer_state_t::eExtendedRangeBrightnessChanged | + layer_state_t::eEdgeExtensionChanged | layer_state_t::eBufferCropChanged | + layer_state_t::eDestinationFrameChanged | layer_state_t::eDimmingEnabledChanged | + layer_state_t::eExtendedRangeBrightnessChanged | layer_state_t::eDesiredHdrHeadroomChanged | (FlagManager::getInstance().latch_unsignaled_with_auto_refresh_changed() ? layer_state_t::eFlagsChanged diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp index 8f819b25e0..b05f0eecc4 100644 --- a/services/surfaceflinger/LayerFE.cpp +++ b/services/surfaceflinger/LayerFE.cpp @@ -173,6 +173,7 @@ std::optional LayerFE::prepareClientC break; } layerSettings.stretchEffect = mSnapshot->stretchEffect; + layerSettings.edgeExtensionEffect = mSnapshot->edgeExtensionEffect; // Record the name of the layer for debugging further down the stack. layerSettings.name = mSnapshot->name; -- GitLab From 8692f0198ab9887177f1ae6f9b7b726f30c8bd1d Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Thu, 4 Jul 2024 16:29:08 +0000 Subject: [PATCH 087/530] Make PersistableBundle getter functions const This is necessary when a PersistableBundle is received as a const& argument. Bug: 345409060 Change-Id: I996ccc5c2670729efd4a8b159a36c16fdf42ea9d Test: build Flag: EXEMPT refactor --- .../android/persistable_bundle_aidl.h | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h index b2ffb2bf3c..b771e9677e 100644 --- a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h +++ b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h @@ -271,7 +271,7 @@ class PersistableBundle { } } - bool getBoolean(const std::string& key, bool* _Nonnull val) { + bool getBoolean(const std::string& key, bool* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getBoolean(mPBundle, key.c_str(), val); } else { @@ -279,7 +279,7 @@ class PersistableBundle { } } - bool getInt(const std::string& key, int32_t* _Nonnull val) { + bool getInt(const std::string& key, int32_t* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getInt(mPBundle, key.c_str(), val); } else { @@ -287,7 +287,7 @@ class PersistableBundle { } } - bool getLong(const std::string& key, int64_t* _Nonnull val) { + bool getLong(const std::string& key, int64_t* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getLong(mPBundle, key.c_str(), val); } else { @@ -295,7 +295,7 @@ class PersistableBundle { } } - bool getDouble(const std::string& key, double* _Nonnull val) { + bool getDouble(const std::string& key, double* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return APersistableBundle_getDouble(mPBundle, key.c_str(), val); } else { @@ -307,7 +307,7 @@ class PersistableBundle { return (char*)malloc(bufferSizeBytes); } - bool getString(const std::string& key, std::string* _Nonnull val) { + bool getString(const std::string& key, std::string* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { char* outString = nullptr; bool ret = APersistableBundle_getString(mPBundle, key.c_str(), &outString, @@ -325,7 +325,7 @@ class PersistableBundle { bool getVecInternal(int32_t (*_Nonnull getVec)(const APersistableBundle* _Nonnull, const char* _Nonnull, T* _Nullable, int32_t), const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, - std::vector* _Nonnull vec) { + std::vector* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { int32_t bytes = 0; // call first with nullptr to get required size in bytes @@ -347,28 +347,28 @@ class PersistableBundle { return false; } - bool getBooleanVector(const std::string& key, std::vector* _Nonnull vec) { + bool getBooleanVector(const std::string& key, std::vector* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal(&APersistableBundle_getBooleanVector, mPBundle, key.c_str(), vec); } return false; } - bool getIntVector(const std::string& key, std::vector* _Nonnull vec) { + bool getIntVector(const std::string& key, std::vector* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal(&APersistableBundle_getIntVector, mPBundle, key.c_str(), vec); } return false; } - bool getLongVector(const std::string& key, std::vector* _Nonnull vec) { + bool getLongVector(const std::string& key, std::vector* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal(&APersistableBundle_getLongVector, mPBundle, key.c_str(), vec); } return false; } - bool getDoubleVector(const std::string& key, std::vector* _Nonnull vec) { + bool getDoubleVector(const std::string& key, std::vector* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getVecInternal(&APersistableBundle_getDoubleVector, mPBundle, key.c_str(), vec); @@ -379,7 +379,7 @@ class PersistableBundle { // Takes ownership of and frees the char** and its elements. // Creates a new set or vector based on the array of char*. template - T moveStringsInternal(char* _Nullable* _Nonnull strings, int32_t bufferSizeBytes) { + T moveStringsInternal(char* _Nullable* _Nonnull strings, int32_t bufferSizeBytes) const { if (strings && bufferSizeBytes > 0) { int32_t num = bufferSizeBytes / sizeof(char*); T ret; @@ -393,7 +393,7 @@ class PersistableBundle { return T(); } - bool getStringVector(const std::string& key, std::vector* _Nonnull vec) { + bool getStringVector(const std::string& key, std::vector* _Nonnull vec) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { int32_t bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), nullptr, 0, &stringAllocator, nullptr); @@ -410,7 +410,7 @@ class PersistableBundle { return false; } - bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) { + bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { APersistableBundle* bundle = nullptr; bool ret = APersistableBundle_getPersistableBundle(mPBundle, key.c_str(), &bundle); @@ -429,7 +429,7 @@ class PersistableBundle { int32_t bufferSizeBytes, APersistableBundle_stringAllocator stringAllocator, void* _Nullable), - const APersistableBundle* _Nonnull pBundle) { + const APersistableBundle* _Nonnull pBundle) const { // call first with nullptr to get required size in bytes int32_t bytes = getTypedKeys(pBundle, nullptr, 0, &stringAllocator, nullptr); if (bytes > 0) { @@ -442,84 +442,84 @@ class PersistableBundle { return {}; } - std::set getBooleanKeys() { + std::set getBooleanKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getBooleanKeys, mPBundle); } else { return {}; } } - std::set getIntKeys() { + std::set getIntKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getIntKeys, mPBundle); } else { return {}; } } - std::set getLongKeys() { + std::set getLongKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getLongKeys, mPBundle); } else { return {}; } } - std::set getDoubleKeys() { + std::set getDoubleKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getDoubleKeys, mPBundle); } else { return {}; } } - std::set getStringKeys() { + std::set getStringKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getStringKeys, mPBundle); } else { return {}; } } - std::set getBooleanVectorKeys() { + std::set getBooleanVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getBooleanVectorKeys, mPBundle); } else { return {}; } } - std::set getIntVectorKeys() { + std::set getIntVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getIntVectorKeys, mPBundle); } else { return {}; } } - std::set getLongVectorKeys() { + std::set getLongVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getLongVectorKeys, mPBundle); } else { return {}; } } - std::set getDoubleVectorKeys() { + std::set getDoubleVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getDoubleVectorKeys, mPBundle); } else { return {}; } } - std::set getStringVectorKeys() { + std::set getStringVectorKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getStringVectorKeys, mPBundle); } else { return {}; } } - std::set getPersistableBundleKeys() { + std::set getPersistableBundleKeys() const { if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { return getKeys(&APersistableBundle_getPersistableBundleKeys, mPBundle); } else { return {}; } } - std::set getMonKeys() { + std::set getMonKeys() const { // :P return {"c(o,o)b", "c(o,o)b"}; } -- GitLab From 099fb592e02f6f9cb02a49f1155ca6d0383cd89e Mon Sep 17 00:00:00 2001 From: Vaibhav Devmurari Date: Wed, 26 Jun 2024 14:26:30 +0000 Subject: [PATCH 088/530] Create basic data store to store keyboard classification Implements a basic file system backed data store (using a json file), to store keyboard classification information persisted across reboots. Test: atest --host libinput_rust_test Bug: 263559234 Flag: com.android.input.flags.enable_keyboard_classifier Change-Id: I521444342ae4e98191262273b881775fb2157ef2 --- libs/input/rust/Android.bp | 2 + libs/input/rust/data_store.rs | 232 +++++++++++++++++++++++++ libs/input/rust/input.rs | 5 +- libs/input/rust/keyboard_classifier.rs | 145 ++++++++++------ libs/input/rust/lib.rs | 11 +- 5 files changed, 343 insertions(+), 52 deletions(-) create mode 100644 libs/input/rust/data_store.rs diff --git a/libs/input/rust/Android.bp b/libs/input/rust/Android.bp index 018d199ce2..63853f77fa 100644 --- a/libs/input/rust/Android.bp +++ b/libs/input/rust/Android.bp @@ -24,6 +24,8 @@ rust_defaults { "liblogger", "liblog_rust", "inputconstants-rust", + "libserde", + "libserde_json", ], whole_static_libs: [ "libinput_from_rust_to_cpp", diff --git a/libs/input/rust/data_store.rs b/libs/input/rust/data_store.rs new file mode 100644 index 0000000000..6bdcefda36 --- /dev/null +++ b/libs/input/rust/data_store.rs @@ -0,0 +1,232 @@ +/* + * Copyright 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. + */ + +//! Contains the DataStore, used to store input related data in a persistent way. + +use crate::input::KeyboardType; +use log::{debug, error}; +use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::io::{Read, Write}; +use std::path::Path; +use std::sync::{Arc, RwLock}; + +/// Data store to be used to store information that persistent across device reboots. +pub struct DataStore { + file_reader_writer: Box, + inner: Arc>, +} + +#[derive(Default)] +struct DataStoreInner { + is_loaded: bool, + data: Data, +} + +#[derive(Default, Serialize, Deserialize)] +struct Data { + // Map storing data for keyboard classification for specific devices. + #[serde(default)] + keyboard_classifications: Vec, + // NOTE: Important things to consider: + // - Add any data that needs to be persisted here in this struct. + // - Mark all new fields with "#[serde(default)]" for backward compatibility. + // - Also, you can't modify the already added fields. + // - Can add new nested fields to existing structs. e.g. Add another field to the struct + // KeyboardClassification and mark it "#[serde(default)]". +} + +#[derive(Default, Serialize, Deserialize)] +struct KeyboardClassification { + descriptor: String, + keyboard_type: KeyboardType, + is_finalized: bool, +} + +impl DataStore { + /// Creates a new instance of Data store + pub fn new(file_reader_writer: Box) -> Self { + Self { file_reader_writer, inner: Default::default() } + } + + fn load(&mut self) { + if self.inner.read().unwrap().is_loaded { + return; + } + self.load_internal(); + } + + fn load_internal(&mut self) { + let s = self.file_reader_writer.read(); + let data: Data = if !s.is_empty() { + let deserialize: Data = match serde_json::from_str(&s) { + Ok(deserialize) => deserialize, + Err(msg) => { + error!("Unable to deserialize JSON data into struct: {:?} -> {:?}", msg, s); + Default::default() + } + }; + deserialize + } else { + Default::default() + }; + + let mut inner = self.inner.write().unwrap(); + inner.data = data; + inner.is_loaded = true; + } + + fn save(&mut self) { + let string_to_save; + { + let inner = self.inner.read().unwrap(); + string_to_save = serde_json::to_string(&inner.data).unwrap(); + } + self.file_reader_writer.write(string_to_save); + } + + /// Get keyboard type of the device (as stored in the data store) + pub fn get_keyboard_type(&mut self, descriptor: &String) -> Option<(KeyboardType, bool)> { + self.load(); + let data = &self.inner.read().unwrap().data; + for keyboard_classification in data.keyboard_classifications.iter() { + if keyboard_classification.descriptor == *descriptor { + return Some(( + keyboard_classification.keyboard_type, + keyboard_classification.is_finalized, + )); + } + } + None + } + + /// Save keyboard type of the device in the data store + pub fn set_keyboard_type( + &mut self, + descriptor: &String, + keyboard_type: KeyboardType, + is_finalized: bool, + ) { + { + let data = &mut self.inner.write().unwrap().data; + data.keyboard_classifications + .retain(|classification| classification.descriptor != *descriptor); + data.keyboard_classifications.push(KeyboardClassification { + descriptor: descriptor.to_string(), + keyboard_type, + is_finalized, + }) + } + self.save(); + } +} + +pub trait FileReaderWriter { + fn read(&self) -> String; + fn write(&self, to_write: String); +} + +/// Default file reader writer implementation +pub struct DefaultFileReaderWriter { + filepath: String, +} + +impl DefaultFileReaderWriter { + /// Creates a new instance of Default file reader writer that can read and write string to a + /// particular file in the filesystem + pub fn new(filepath: String) -> Self { + Self { filepath } + } +} + +impl FileReaderWriter for DefaultFileReaderWriter { + fn read(&self) -> String { + let path = Path::new(&self.filepath); + let mut fs_string = String::new(); + match File::open(path) { + Err(e) => error!("couldn't open {:?}: {}", path, e), + Ok(mut file) => match file.read_to_string(&mut fs_string) { + Err(e) => error!("Couldn't read from {:?}: {}", path, e), + Ok(_) => debug!("Successfully read from file {:?}", path), + }, + }; + fs_string + } + + fn write(&self, to_write: String) { + let path = Path::new(&self.filepath); + match File::create(path) { + Err(e) => error!("couldn't create {:?}: {}", path, e), + Ok(mut file) => match file.write_all(to_write.as_bytes()) { + Err(e) => error!("Couldn't write to {:?}: {}", path, e), + Ok(_) => debug!("Successfully saved to file {:?}", path), + }, + }; + } +} + +#[cfg(test)] +mod tests { + use crate::data_store::{ + test_file_reader_writer::TestFileReaderWriter, DataStore, FileReaderWriter, + }; + use crate::input::KeyboardType; + + #[test] + fn test_backward_compatibility_version_1() { + // This test tests JSON string that will be created by the first version of data store + // This test SHOULD NOT be modified + let test_reader_writer = TestFileReaderWriter::new(); + test_reader_writer.write(r#"{"keyboard_classifications":[{"descriptor":"descriptor","keyboard_type":{"type":"Alphabetic"},"is_finalized":true}]}"#.to_string()); + + let mut data_store = DataStore::new(Box::new(test_reader_writer)); + let (keyboard_type, is_finalized) = + data_store.get_keyboard_type(&"descriptor".to_string()).unwrap(); + assert_eq!(keyboard_type, KeyboardType::Alphabetic); + assert!(is_finalized); + } +} + +#[cfg(test)] +pub mod test_file_reader_writer { + + use crate::data_store::FileReaderWriter; + use std::sync::{Arc, RwLock}; + + #[derive(Default)] + struct TestFileReaderWriterInner { + fs_string: String, + } + + #[derive(Default, Clone)] + pub struct TestFileReaderWriter(Arc>); + + impl TestFileReaderWriter { + pub fn new() -> Self { + Default::default() + } + } + + impl FileReaderWriter for TestFileReaderWriter { + fn read(&self) -> String { + self.0.read().unwrap().fs_string.clone() + } + + fn write(&self, fs_string: String) { + self.0.write().unwrap().fs_string = fs_string; + } + } +} diff --git a/libs/input/rust/input.rs b/libs/input/rust/input.rs index c46b7bb85c..90f509d97f 100644 --- a/libs/input/rust/input.rs +++ b/libs/input/rust/input.rs @@ -20,6 +20,7 @@ use crate::ffi::RustInputDeviceIdentifier; use bitflags::bitflags; use inputconstants::aidl::android::os::IInputConstants; use inputconstants::aidl::android::os::MotionEventFlag::MotionEventFlag; +use serde::{Deserialize, Serialize}; use std::fmt; /// The InputDevice ID. @@ -324,9 +325,11 @@ bitflags! { /// A rust enum representation of a Keyboard type. #[repr(u32)] -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type")] pub enum KeyboardType { /// KEYBOARD_TYPE_NONE + #[default] None = input_bindgen::AINPUT_KEYBOARD_TYPE_NONE, /// KEYBOARD_TYPE_NON_ALPHABETIC NonAlphabetic = input_bindgen::AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, diff --git a/libs/input/rust/keyboard_classifier.rs b/libs/input/rust/keyboard_classifier.rs index 8721ef7687..3c789b41e2 100644 --- a/libs/input/rust/keyboard_classifier.rs +++ b/libs/input/rust/keyboard_classifier.rs @@ -31,9 +31,8 @@ //! across multiple device connections in a time period, then change type to //! KeyboardType::NonAlphabetic. Once changed, it can still change back to Alphabetic //! (i.e. verified = false). -//! -//! TODO(b/263559234): Data store implementation to store information about past classification +use crate::data_store::DataStore; use crate::input::{DeviceId, InputDevice, KeyboardType}; use crate::keyboard_classification_config::CLASSIFIED_DEVICES; use crate::{DeviceClass, ModifierState}; @@ -41,30 +40,28 @@ use std::collections::HashMap; /// The KeyboardClassifier is used to classify a keyboard device into non-keyboard, alphabetic /// keyboard or non-alphabetic keyboard -#[derive(Default)] pub struct KeyboardClassifier { device_map: HashMap, + data_store: DataStore, } struct KeyboardInfo { - _device: InputDevice, + device: InputDevice, keyboard_type: KeyboardType, is_finalized: bool, } impl KeyboardClassifier { /// Create a new KeyboardClassifier - pub fn new() -> Self { - Default::default() + pub fn new(data_store: DataStore) -> Self { + Self { device_map: HashMap::new(), data_store } } /// Adds keyboard to KeyboardClassifier pub fn notify_keyboard_changed(&mut self, device: InputDevice) { let (keyboard_type, is_finalized) = self.classify_keyboard(&device); - self.device_map.insert( - device.device_id, - KeyboardInfo { _device: device, keyboard_type, is_finalized }, - ); + self.device_map + .insert(device.device_id, KeyboardInfo { device, keyboard_type, is_finalized }); } /// Get keyboard type for a tracked keyboard in KeyboardClassifier @@ -107,11 +104,16 @@ impl KeyboardClassifier { if Self::is_alphabetic_key(&evdev_code) { keyboard.keyboard_type = KeyboardType::Alphabetic; keyboard.is_finalized = true; + self.data_store.set_keyboard_type( + &keyboard.device.identifier.descriptor, + keyboard.keyboard_type, + keyboard.is_finalized, + ); } } } - fn classify_keyboard(&self, device: &InputDevice) -> (KeyboardType, bool) { + fn classify_keyboard(&mut self, device: &InputDevice) -> (KeyboardType, bool) { // This should never happen but having keyboard device class is necessary to be classified // as any type of keyboard. if !device.classes.contains(DeviceClass::Keyboard) { @@ -128,10 +130,17 @@ impl KeyboardClassifier { }; } + // Check in data store + if let Some((keyboard_type, is_finalized)) = + self.data_store.get_keyboard_type(&device.identifier.descriptor) + { + return (keyboard_type, is_finalized); + } + // Check in known device list for classification - for data in CLASSIFIED_DEVICES.iter() { - if device.identifier.vendor == data.0 && device.identifier.product == data.1 { - return (data.2, data.3); + for (vendor, product, keyboard_type, is_finalized) in CLASSIFIED_DEVICES.iter() { + if device.identifier.vendor == *vendor && device.identifier.product == *product { + return (*keyboard_type, *is_finalized); } } @@ -177,18 +186,20 @@ impl KeyboardClassifier { #[cfg(test)] mod tests { + use crate::data_store::{test_file_reader_writer::TestFileReaderWriter, DataStore}; use crate::input::{DeviceId, InputDevice, KeyboardType}; use crate::keyboard_classification_config::CLASSIFIED_DEVICES; use crate::keyboard_classifier::KeyboardClassifier; use crate::{DeviceClass, ModifierState, RustInputDeviceIdentifier}; static DEVICE_ID: DeviceId = DeviceId(1); + static SECOND_DEVICE_ID: DeviceId = DeviceId(2); static KEY_A: i32 = 30; static KEY_1: i32 = 2; #[test] fn classify_external_alphabetic_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::AlphabeticKey | DeviceClass::External, )); @@ -198,7 +209,7 @@ mod tests { #[test] fn classify_external_non_alphabetic_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier .notify_keyboard_changed(create_device(DeviceClass::Keyboard | DeviceClass::External)); assert_eq!(classifier.get_keyboard_type(DEVICE_ID), KeyboardType::NonAlphabetic); @@ -207,7 +218,7 @@ mod tests { #[test] fn classify_mouse_pretending_as_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Cursor @@ -220,7 +231,7 @@ mod tests { #[test] fn classify_touchpad_pretending_as_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Touchpad @@ -233,7 +244,7 @@ mod tests { #[test] fn classify_stylus_pretending_as_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::ExternalStylus @@ -246,7 +257,7 @@ mod tests { #[test] fn classify_dpad_pretending_as_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Dpad @@ -259,7 +270,7 @@ mod tests { #[test] fn classify_joystick_pretending_as_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Joystick @@ -272,7 +283,7 @@ mod tests { #[test] fn classify_gamepad_pretending_as_keyboard() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Gamepad @@ -285,7 +296,7 @@ mod tests { #[test] fn reclassify_keyboard_on_alphabetic_key_event() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Dpad @@ -303,7 +314,7 @@ mod tests { #[test] fn dont_reclassify_keyboard_on_non_alphabetic_key_event() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Dpad @@ -321,7 +332,7 @@ mod tests { #[test] fn dont_reclassify_keyboard_on_alphabetic_key_event_with_modifiers() { - let mut classifier = KeyboardClassifier::new(); + let mut classifier = create_classifier(); classifier.notify_keyboard_changed(create_device( DeviceClass::Keyboard | DeviceClass::Dpad @@ -338,28 +349,71 @@ mod tests { #[test] fn classify_known_devices() { - let mut classifier = KeyboardClassifier::new(); - for device in CLASSIFIED_DEVICES.iter() { + let mut classifier = create_classifier(); + for (vendor, product, keyboard_type, is_finalized) in CLASSIFIED_DEVICES.iter() { classifier - .notify_keyboard_changed(create_device_with_vendor_product_ids(device.0, device.1)); - assert_eq!(classifier.get_keyboard_type(DEVICE_ID), device.2); - assert_eq!(classifier.is_finalized(DEVICE_ID), device.3); + .notify_keyboard_changed(create_device_with_vendor_product_ids(*vendor, *product)); + assert_eq!(classifier.get_keyboard_type(DEVICE_ID), *keyboard_type); + assert_eq!(classifier.is_finalized(DEVICE_ID), *is_finalized); + } + } + + #[test] + fn classify_previously_reclassified_devices() { + let test_reader_writer = TestFileReaderWriter::new(); + { + let mut classifier = + KeyboardClassifier::new(DataStore::new(Box::new(test_reader_writer.clone()))); + let device = create_device( + DeviceClass::Keyboard + | DeviceClass::Dpad + | DeviceClass::AlphabeticKey + | DeviceClass::External, + ); + classifier.notify_keyboard_changed(device); + classifier.process_key(DEVICE_ID, KEY_A, ModifierState::None); + } + + // Re-create classifier and data store to mimic a reboot (but use the same file system + // reader writer) + { + let mut classifier = + KeyboardClassifier::new(DataStore::new(Box::new(test_reader_writer.clone()))); + let device = InputDevice { + device_id: SECOND_DEVICE_ID, + identifier: create_identifier(/* vendor= */ 234, /* product= */ 345), + classes: DeviceClass::Keyboard + | DeviceClass::Dpad + | DeviceClass::AlphabeticKey + | DeviceClass::External, + }; + classifier.notify_keyboard_changed(device); + assert_eq!(classifier.get_keyboard_type(SECOND_DEVICE_ID), KeyboardType::Alphabetic); + assert!(classifier.is_finalized(SECOND_DEVICE_ID)); + } + } + + fn create_classifier() -> KeyboardClassifier { + KeyboardClassifier::new(DataStore::new(Box::new(TestFileReaderWriter::new()))) + } + + fn create_identifier(vendor: u16, product: u16) -> RustInputDeviceIdentifier { + RustInputDeviceIdentifier { + name: "test_device".to_string(), + location: "location".to_string(), + unique_id: "unique_id".to_string(), + bus: 123, + vendor, + product, + version: 567, + descriptor: "descriptor".to_string(), } } fn create_device(classes: DeviceClass) -> InputDevice { InputDevice { device_id: DEVICE_ID, - identifier: RustInputDeviceIdentifier { - name: "test_device".to_string(), - location: "location".to_string(), - unique_id: "unique_id".to_string(), - bus: 123, - vendor: 234, - product: 345, - version: 567, - descriptor: "descriptor".to_string(), - }, + identifier: create_identifier(/* vendor= */ 234, /* product= */ 345), classes, } } @@ -367,16 +421,7 @@ mod tests { fn create_device_with_vendor_product_ids(vendor: u16, product: u16) -> InputDevice { InputDevice { device_id: DEVICE_ID, - identifier: RustInputDeviceIdentifier { - name: "test_device".to_string(), - location: "location".to_string(), - unique_id: "unique_id".to_string(), - bus: 123, - vendor, - product, - version: 567, - descriptor: "descriptor".to_string(), - }, + identifier: create_identifier(vendor, product), classes: DeviceClass::Keyboard | DeviceClass::AlphabeticKey | DeviceClass::External, } } diff --git a/libs/input/rust/lib.rs b/libs/input/rust/lib.rs index af8f889cb5..008f675485 100644 --- a/libs/input/rust/lib.rs +++ b/libs/input/rust/lib.rs @@ -16,11 +16,13 @@ //! The rust component of libinput. +mod data_store; mod input; mod input_verifier; mod keyboard_classification_config; mod keyboard_classifier; +pub use data_store::{DataStore, DefaultFileReaderWriter}; pub use input::{ DeviceClass, DeviceId, InputDevice, ModifierState, MotionAction, MotionFlags, Source, }; @@ -149,7 +151,14 @@ fn reset_device(verifier: &mut InputVerifier, device_id: i32) { } fn create_keyboard_classifier() -> Box { - Box::new(KeyboardClassifier::new()) + // Future design: Make this data store singleton by passing it to C++ side and making it global + // and pass by reference to components that need to store persistent data. + // + // Currently only used by rust keyboard classifier so keeping it here. + let data_store = DataStore::new(Box::new(DefaultFileReaderWriter::new( + "/data/system/inputflinger-data.json".to_string(), + ))); + Box::new(KeyboardClassifier::new(data_store)) } fn notify_keyboard_changed( -- GitLab From 4125ea4e8677dbc13e8adbbbba742cc3fbed54a6 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 1 Jul 2024 16:38:17 -0700 Subject: [PATCH 089/530] Remove some logging information from InputDispatcher Currently, we are often printing information like "edgeFlags" and "xPrecision"/"yPrecision". Over the years, I've never found that information useful, and it clutters the logs. Separately, we are labeling input channels like "(server) and "(client)", which is also never useful. After the input channels were refactored several years ago, it's pretty hard to mix those up: dispatcher always has a unique_ptr of the InputChannel, so there's little risk of it leaking elsewhere. In this CL, those pieces of logs are removed to make it easier to read the various dumps and logs. Bug: 347700797 Flag: EXEMPT refactor Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_break_on_failure --gtest_filter="*SpyThatPreventsSplittingWithApplication*" Change-Id: I7414a6c35a7a1bc1c779d51cd7243b30356f803e --- libs/input/InputTransport.cpp | 6 ++---- libs/input/tests/InputChannel_test.cpp | 6 +----- .../dispatcher/InputDispatcher.cpp | 21 ++++++------------- .../inputflinger/dispatcher/InputState.cpp | 4 +++- 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index bac681df85..4d21d8c987 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -375,13 +375,11 @@ status_t InputChannel::openInputChannelPair(const std::string& name, sp token = sp::make(); - std::string serverChannelName = name + " (server)"; android::base::unique_fd serverFd(sockets[0]); - outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token); + outServerChannel = InputChannel::create(name, std::move(serverFd), token); - std::string clientChannelName = name + " (client)"; android::base::unique_fd clientFd(sockets[1]); - outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token); + outClientChannel = InputChannel::create(name, std::move(clientFd), token); return OK; } diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index 435bdcde2d..25356cfcf0 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -65,11 +65,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; - // Name - EXPECT_STREQ("channel name (server)", serverChannel->getName().c_str()) - << "server channel should have suffixed name"; - EXPECT_STREQ("channel name (client)", clientChannel->getName().c_str()) - << "client channel should have suffixed name"; + EXPECT_EQ(serverChannel->getName(), clientChannel->getName()); // Server->Client communication InputMessage serverMsg = {}; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index a2e50d7d87..a0c9b6de89 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2114,19 +2114,16 @@ void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionE if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%s, policyFlags=0x%x, " "action=%s, actionButton=0x%x, flags=0x%x, " - "metaState=0x%x, buttonState=0x%x," - "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64, + "metaState=0x%x, buttonState=0x%x, downTime=%" PRId64, prefix, entry.eventTime, entry.deviceId, inputEventSourceToString(entry.source).c_str(), entry.displayId.toString().c_str(), entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(), - entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags, - entry.xPrecision, entry.yPrecision, entry.downTime); + entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.downTime); for (uint32_t i = 0; i < entry.getPointerCount(); i++) { ALOGD(" Pointer %d: id=%d, toolType=%s, " "x=%f, y=%f, pressure=%f, size=%f, " - "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, " - "orientation=%f", + "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f", i, entry.pointerProperties[i].id, ftl::enum_string(entry.pointerProperties[i].toolType).c_str(), entry.pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X), @@ -4548,13 +4545,12 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) { ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=%s, " "displayId=%s, policyFlags=0x%x, " "action=%s, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, " - "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, " - "yCursorPosition=%f, downTime=%" PRId64, + "xCursorPosition=%f, yCursorPosition=%f, downTime=%" PRId64, args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(), args.displayId.toString().c_str(), args.policyFlags, MotionEvent::actionToString(args.action).c_str(), args.actionButton, args.flags, - args.metaState, args.buttonState, args.edgeFlags, args.xPrecision, args.yPrecision, - args.xCursorPosition, args.yCursorPosition, args.downTime); + args.metaState, args.buttonState, args.xCursorPosition, args.yCursorPosition, + args.downTime); for (uint32_t i = 0; i < args.getPointerCount(); i++) { ALOGD(" Pointer %d: id=%d, toolType=%s, x=%f, y=%f, pressure=%f, size=%f, " "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, orientation=%f", @@ -6024,17 +6020,12 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { dump += StringPrintf(INDENT3 "OutboundQueue: length=%zu\n", connection->outboundQueue.size()); dump += dumpQueue(connection->outboundQueue, currentTime); - - } else { - dump += INDENT3 "OutboundQueue: \n"; } if (!connection->waitQueue.empty()) { dump += StringPrintf(INDENT3 "WaitQueue: length=%zu\n", connection->waitQueue.size()); dump += dumpQueue(connection->waitQueue, currentTime); - } else { - dump += INDENT3 "WaitQueue: \n"; } std::string inputStateDump = streamableToString(connection->inputState); if (!inputStateDump.empty()) { diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp index dfbe02f332..4df23c54d6 100644 --- a/services/inputflinger/dispatcher/InputState.cpp +++ b/services/inputflinger/dispatcher/InputState.cpp @@ -647,7 +647,9 @@ std::ostream& operator<<(std::ostream& out, const InputState& state) { if (!state.mMotionMementos.empty()) { out << "mMotionMementos: "; for (const InputState::MotionMemento& memento : state.mMotionMementos) { - out << "{deviceId= " << memento.deviceId << ", hovering=" << memento.hovering << "}, "; + out << "{deviceId=" << memento.deviceId + << ", hovering=" << std::to_string(memento.hovering) + << ", downTime=" << memento.downTime << "}, "; } } return out; -- GitLab From b0058744c3d701845ef149c5605f2fee50006f10 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 1 Jul 2024 16:42:49 -0700 Subject: [PATCH 090/530] Dump dispatcher state during publisher error When publisher encounters an error, it crashes. Today, those crashes lack the corresponding dispatcher context. In this CL, we change the pipeline so that the dispatcher crashes instead. This would help us see the dump of the dispatcher state and get better idea of how things went wrong. Bug: 347700797 Flag: EXEMPT refactor Test: TEST=inputflinger_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_break_on_failure --gtest_filter="*SpyThatPreventsSplittingWithApplication*" Change-Id: Iac148751703de833503c2638ef20dcb4cb137297 --- include/input/InputTransport.h | 3 ++- libs/input/InputTransport.cpp | 3 ++- services/inputflinger/dispatcher/InputDispatcher.cpp | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index b26a194a0e..7d11f76c85 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -363,7 +363,8 @@ public: * Returns OK on success. * Returns WOULD_BLOCK if the channel is full. * Returns DEAD_OBJECT if the channel's peer has been closed. - * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS. + * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS, + * or if the verifier is enabled and the event failed verification upon publishing. * Other errors probably indicate that the channel is broken. */ status_t publishMotionEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index bac681df85..68cee0b211 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -590,7 +590,8 @@ status_t InputPublisher::publishMotionEvent( mInputVerifier.processMovement(deviceId, source, action, pointerCount, pointerProperties, pointerCoords, flags); if (!result.ok()) { - LOG(FATAL) << "Bad stream: " << result.error(); + LOG(ERROR) << "Bad stream: " << result.error(); + return BAD_VALUE; } } if (debugTransportPublisher()) { diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index a2e50d7d87..e76f098fb1 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3830,6 +3830,10 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, } const MotionEntry& motionEntry = static_cast(eventEntry); status = publishMotionEvent(*connection, *dispatchEntry); + if (status == BAD_VALUE) { + logDispatchStateLocked(); + LOG(FATAL) << "Publisher failed for " << motionEntry; + } if (mTracer) { ensureEventTraced(motionEntry); mTracer->traceEventDispatch(*dispatchEntry, *motionEntry.traceTracker); -- GitLab From ea6b29656befa3829850221a2d11f29dceb609ab Mon Sep 17 00:00:00 2001 From: Yu-Ting Tseng Date: Mon, 8 Jul 2024 07:31:06 +0000 Subject: [PATCH 091/530] Revert "Placeholder for binder freeze notification API." This reverts commit 4a5441fe4d60ce20f8de052d4439d4c549e300c4. Reason for revert: b/351718767 Change-Id: Ic8a6828b72f44746ec925e829748ad53e9050f57 --- libs/binder/Binder.cpp | 8 -------- libs/binder/BpBinder.cpp | 8 -------- libs/binder/include/binder/Binder.h | 7 ------- libs/binder/include/binder/BpBinder.h | 6 ------ libs/binder/include/binder/IBinder.h | 17 +++-------------- 5 files changed, 3 insertions(+), 43 deletions(-) diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp index 6185b7baf8..c57c9cdd62 100644 --- a/libs/binder/Binder.cpp +++ b/libs/binder/Binder.cpp @@ -441,14 +441,6 @@ status_t BBinder::unlinkToDeath( return INVALID_OPERATION; } -status_t BBinder::addFrozenStateChangeCallback(const wp&) { - return INVALID_OPERATION; -} - -status_t BBinder::removeFrozenStateChangeCallback(const wp&) { - return INVALID_OPERATION; -} - status_t BBinder::dump(int /*fd*/, const Vector& /*args*/) { return NO_ERROR; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 59c5be75ac..6594aa6309 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -557,14 +557,6 @@ void BpBinder::sendObituary() } } -status_t BpBinder::addFrozenStateChangeCallback(const wp&) { - return INVALID_OPERATION; -} - -status_t BpBinder::removeFrozenStateChangeCallback(const wp&) { - return INVALID_OPERATION; -} - void BpBinder::reportOneDeath(const Obituary& obit) { sp recipient = obit.recipient.promote(); diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h index 802a3bcd06..135be89c6c 100644 --- a/libs/binder/include/binder/Binder.h +++ b/libs/binder/include/binder/Binder.h @@ -50,13 +50,6 @@ public: void* cookie = nullptr, uint32_t flags = 0, wp* outRecipient = nullptr); - // Placeholders to test if adding virtual functions here breaks things. - // Will be replaced by an actual API once things are verified to work. - LIBBINDER_EXPORTED virtual status_t addFrozenStateChangeCallback( - const wp& callback); - LIBBINDER_EXPORTED virtual status_t removeFrozenStateChangeCallback( - const wp& callback); - LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) final; diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index 0f52f6df52..d7f74c4152 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -66,12 +66,6 @@ public: void* cookie = nullptr, uint32_t flags = 0, wp* outRecipient = nullptr); - [[nodiscard]] virtual status_t addFrozenStateChangeCallback( - const wp& recipient); - - [[nodiscard]] virtual status_t removeFrozenStateChangeCallback( - const wp& recipient); - LIBBINDER_EXPORTED virtual void* attachObject(const void* objectID, void* object, void* cleanupCookie, object_cleanup_func func) final; diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h index 62d7354387..17248ce289 100644 --- a/libs/binder/include/binder/IBinder.h +++ b/libs/binder/include/binder/IBinder.h @@ -198,14 +198,9 @@ public: virtual void binderDied(const wp& who) = 0; }; - class FrozenStateChangeCallback : public virtual RefBase { - public: - virtual void onStateChanged(const wp& who, bool isFrozen) = 0; - }; - -#if defined(__clang__) -#pragma clang diagnostic pop -#endif + #if defined(__clang__) + #pragma clang diagnostic pop + #endif /** * Register the @a recipient for a notification if this binder @@ -254,12 +249,6 @@ public: uint32_t flags = 0, wp* outRecipient = nullptr) = 0; - // Placeholders. See Binder.h for details. - [[nodiscard]] virtual status_t addFrozenStateChangeCallback( - const wp& callback) = 0; - [[nodiscard]] virtual status_t removeFrozenStateChangeCallback( - const wp& callback) = 0; - virtual bool checkSubclass(const void* subclassID) const; typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie); -- GitLab From 8ff5e5ecde93d80549208f25563f351da90a8dfc Mon Sep 17 00:00:00 2001 From: Biswarup Pal Date: Sat, 15 Jun 2024 12:58:20 +0000 Subject: [PATCH 092/530] Support high-resolution scroll VirtualMouse currently supports -1f to 1f float scroll values, but it worked for integer values only as input framework supported only REL_HWHEEL and REL_WHEEL events. With the introduction of high-res scroll event support (REL_HWHEEL_HI_RES and REL_WHEEL_HI_RES), granular mouse scrolling can be done, and VirtualMouse scroll API would work for all float values. Flag: android.companion.virtualdevice.flags.high_resolution_scroll Test: atest VirtualMouseTest Bug: 335160780 Change-Id: I7b13ac1722b6fd31736fe1c0117d4de6e838261a --- include/input/Input.h | 7 + include/input/VirtualInputDevice.h | 2 + libs/input/Android.bp | 1 + libs/input/VirtualInputDevice.cpp | 48 +++++- services/inputflinger/reader/Android.bp | 3 +- .../reader/mapper/TouchInputMapper.h | 4 +- .../accumulator/CursorScrollAccumulator.cpp | 37 ++++- .../accumulator/CursorScrollAccumulator.h | 11 +- services/inputflinger/tests/Android.bp | 1 + .../tests/CursorInputMapper_test.cpp | 139 ++++++++++++++++++ .../tests/RotaryEncoderInputMapper_test.cpp | 4 + .../inputflinger/tests/TestEventMatchers.h | 9 ++ 12 files changed, 251 insertions(+), 15 deletions(-) diff --git a/include/input/Input.h b/include/input/Input.h index 456977bb34..17672d11f7 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -195,6 +195,13 @@ static constexpr size_t MAX_POINTERS = 16; */ #define MAX_POINTER_ID 31 +/* + * Number of high resolution mouse scroll units for one detent (mouse wheel click), as defined in + * evdev. This is relevant when an input device is emitting REL_WHEEL_HI_RES or REL_HWHEEL_HI_RES + * events. + */ +constexpr int32_t kEvdevMouseHighResScrollUnitsPerDetent = 120; + /* * Declare a concrete type for the NDK's input event forward declaration. */ diff --git a/include/input/VirtualInputDevice.h b/include/input/VirtualInputDevice.h index 9bbaa0c5ec..9fbae73167 100644 --- a/include/input/VirtualInputDevice.h +++ b/include/input/VirtualInputDevice.h @@ -77,6 +77,8 @@ public: private: static const std::map BUTTON_CODE_MAPPING; + int32_t mAccumulatedHighResScrollX; + int32_t mAccumulatedHighResScrollY; }; class VirtualTouchscreen : public VirtualInputDevice { diff --git a/libs/input/Android.bp b/libs/input/Android.bp index c2a7ebb614..45ebc66ddc 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -258,6 +258,7 @@ cc_library { ], shared_libs: [ + "android.companion.virtualdevice.flags-aconfig-cc-host", "libbase", "libbinder", "libbinder_ndk", diff --git a/libs/input/VirtualInputDevice.cpp b/libs/input/VirtualInputDevice.cpp index b73ee65504..2e3e1a09b8 100644 --- a/libs/input/VirtualInputDevice.cpp +++ b/libs/input/VirtualInputDevice.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include ::type, U>::type; - using U2 = - typename std::conditional::value, - typename std::add_volatile::type, U1>::type; - using U3 = - typename std::conditional::value, - typename std::add_lvalue_reference::type, - U2>::type; - using U4 = - typename std::conditional::value, - typename std::add_rvalue_reference::type, - U3>::type; - - public: - using Type = U4; -}; - -template -using CopyCVReferenceType = typename CopyCVReference::Type; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_COPY_CV_REFERENCE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/default_initialization_allocator.h b/libs/vr/libpdx/private/pdx/rpc/default_initialization_allocator.h deleted file mode 100644 index b6e298084e..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/default_initialization_allocator.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef ANDROID_PDX_RPC_DEFAULT_INITIALIZATION_ALLOCATOR_H_ -#define ANDROID_PDX_RPC_DEFAULT_INITIALIZATION_ALLOCATOR_H_ - -#include - -namespace android { -namespace pdx { -namespace rpc { - -// Allocator adaptor that interposes construct() calls to convert value -// initialization into default initialization. All standard containers -// value-initialize their elements when constructed with a single size_type -// argument or when grown by a call to resize. This allocator avoids potentially -// costly value-initialization in these situations for value types that are -// default constructible. As a consequence, elements of non-class types are left -// uninitialized; this is desirable when using std::vector as a resizable -// buffer, for example. -template > -class DefaultInitializationAllocator : public Allocator { - typedef std::allocator_traits AllocatorTraits; - - public: - template - struct rebind { - using other = DefaultInitializationAllocator< - U, typename AllocatorTraits::template rebind_alloc>; - }; - - using Allocator::Allocator; - - template - void construct(U* pointer) noexcept( - std::is_nothrow_default_constructible::value) { - ::new (static_cast(pointer)) U; - } - template - void construct(U* pointer, Args&&... args) { - AllocatorTraits::construct(static_cast(*this), pointer, - std::forward(args)...); - } -}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_DEFAULT_INITIALIZATION_ALLOCATOR_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/encoding.h b/libs/vr/libpdx/private/pdx/rpc/encoding.h deleted file mode 100644 index f51d807f5b..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/encoding.h +++ /dev/null @@ -1,616 +0,0 @@ -#ifndef ANDROID_PDX_RPC_ENCODING_H_ -#define ANDROID_PDX_RPC_ENCODING_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "array_wrapper.h" -#include "buffer_wrapper.h" -#include "string_wrapper.h" -#include "variant.h" - -namespace android { -namespace pdx { -namespace rpc { - -// This library uses a subset, or profile, of MessagePack (http://msgpack.org) -// to encode supported data types during serialization and to verify the -// expected data types during deserialization. One notable deviation from the -// MessagePack specification is that little-endian byte order is used for -// multi-byte numeric types to avoid unnecessary conversion on nearly all -// relevant architectures. -// -// Some data types, integers for example, support multiple encoding strategies. -// This library attempts to optimize for space based on the value of such types. -// However, during decode all valid encodings for a given type are accepted. - -// Prefix byte for type encodings. This is the complete list of prefix bytes -// from the MessagePack specification, even though not all types are used by -// this library. -enum EncodingPrefix { - ENCODING_TYPE_POSITIVE_FIXINT = 0x00, - ENCODING_TYPE_POSITIVE_FIXINT_MIN = 0x00, - ENCODING_TYPE_POSITIVE_FIXINT_MAX = 0x7f, - ENCODING_TYPE_POSITIVE_FIXINT_MASK = 0x7f, - ENCODING_TYPE_FIXMAP = 0x80, - ENCODING_TYPE_FIXMAP_MIN = 0x80, - ENCODING_TYPE_FIXMAP_MAX = 0x8f, - ENCODING_TYPE_FIXMAP_MASK = 0x0f, - ENCODING_TYPE_FIXARRAY = 0x90, - ENCODING_TYPE_FIXARRAY_MIN = 0x90, - ENCODING_TYPE_FIXARRAY_MAX = 0x9f, - ENCODING_TYPE_FIXARRAY_MASK = 0x0f, - ENCODING_TYPE_FIXSTR = 0xa0, - ENCODING_TYPE_FIXSTR_MIN = 0xa0, - ENCODING_TYPE_FIXSTR_MAX = 0xbf, - ENCODING_TYPE_FIXSTR_MASK = 0x1f, - ENCODING_TYPE_NIL = 0xc0, - ENCODING_TYPE_RESERVED = 0xc1, - ENCODING_TYPE_FALSE = 0xc2, - ENCODING_TYPE_TRUE = 0xc3, - ENCODING_TYPE_BIN8 = 0xc4, - ENCODING_TYPE_BIN16 = 0xc5, - ENCODING_TYPE_BIN32 = 0xc6, - ENCODING_TYPE_EXT8 = 0xc7, - ENCODING_TYPE_EXT16 = 0xc8, - ENCODING_TYPE_EXT32 = 0xc9, - ENCODING_TYPE_FLOAT32 = 0xca, - ENCODING_TYPE_FLOAT64 = 0xcb, - ENCODING_TYPE_UINT8 = 0xcc, - ENCODING_TYPE_UINT16 = 0xcd, - ENCODING_TYPE_UINT32 = 0xce, - ENCODING_TYPE_UINT64 = 0xcf, - ENCODING_TYPE_INT8 = 0xd0, - ENCODING_TYPE_INT16 = 0xd1, - ENCODING_TYPE_INT32 = 0xd2, - ENCODING_TYPE_INT64 = 0xd3, - ENCODING_TYPE_FIXEXT1 = 0xd4, - ENCODING_TYPE_FIXEXT2 = 0xd5, - ENCODING_TYPE_FIXEXT4 = 0xd6, - ENCODING_TYPE_FIXEXT8 = 0xd7, - ENCODING_TYPE_FIXEXT16 = 0xd8, - ENCODING_TYPE_STR8 = 0xd9, - ENCODING_TYPE_STR16 = 0xda, - ENCODING_TYPE_STR32 = 0xdb, - ENCODING_TYPE_ARRAY16 = 0xdc, - ENCODING_TYPE_ARRAY32 = 0xdd, - ENCODING_TYPE_MAP16 = 0xde, - ENCODING_TYPE_MAP32 = 0xdf, - ENCODING_TYPE_NEGATIVE_FIXINT = 0xe0, - ENCODING_TYPE_NEGATIVE_FIXINT_MIN = 0xe0, - ENCODING_TYPE_NEGATIVE_FIXINT_MAX = 0xff, -}; - -// Base encoding classes grouping multi-strategy encodings. -enum EncodingClass { - ENCODING_CLASS_BOOL, - ENCODING_CLASS_NIL, - ENCODING_CLASS_INT, - ENCODING_CLASS_UINT, - ENCODING_CLASS_FLOAT, - ENCODING_CLASS_ARRAY, - ENCODING_CLASS_MAP, - ENCODING_CLASS_STRING, - ENCODING_CLASS_BINARY, - ENCODING_CLASS_EXTENSION, -}; - -// Encoding prefixes are unsigned bytes. -typedef std::uint8_t EncodingType; - -// Extension encoding types defined by this library. -enum EncodingExtType : int8_t { - ENCODING_EXT_TYPE_FILE_DESCRIPTOR, - ENCODING_EXT_TYPE_CHANNEL_HANDLE, -}; - -// Encoding predicates. Determines whether the given encoding is of a specific -// type. -inline constexpr bool IsFixintEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsUnsignedFixintEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt8Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt8Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt16Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_INT16: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt16Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_UINT16: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt32Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_INT16: - case ENCODING_TYPE_INT32: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt32Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_UINT16: - case ENCODING_TYPE_UINT32: - return true; - default: - return false; - } -} - -inline constexpr bool IsInt64Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_INT16: - case ENCODING_TYPE_INT32: - case ENCODING_TYPE_INT64: - return true; - default: - return false; - } -} - -inline constexpr bool IsUInt64Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_UINT16: - case ENCODING_TYPE_UINT32: - case ENCODING_TYPE_UINT64: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixmapEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXMAP_MIN ... ENCODING_TYPE_FIXMAP_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixarrayEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXARRAY_MIN ... ENCODING_TYPE_FIXARRAY_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixstrEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXSTR_MIN ... ENCODING_TYPE_FIXSTR_MAX: - return true; - default: - return false; - } -} - -inline constexpr bool IsFixextEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXEXT1: - case ENCODING_TYPE_FIXEXT2: - case ENCODING_TYPE_FIXEXT4: - case ENCODING_TYPE_FIXEXT8: - case ENCODING_TYPE_FIXEXT16: - return true; - default: - return false; - } -} - -inline constexpr bool IsFloat32Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FLOAT32: - return true; - default: - return false; - } -} - -inline constexpr bool IsFloat64Encoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FLOAT32: - case ENCODING_TYPE_FLOAT64: - return true; - default: - return false; - } -} - -inline constexpr bool IsBoolEncoding(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FALSE: - case ENCODING_TYPE_TRUE: - return true; - default: - return false; - } -} - -inline constexpr std::size_t GetFixstrSize(EncodingType encoding) { - return encoding & ENCODING_TYPE_FIXSTR_MASK; -} - -inline constexpr std::size_t GetFixarraySize(EncodingType encoding) { - return encoding & ENCODING_TYPE_FIXARRAY_MASK; -} - -inline constexpr std::size_t GetFixmapSize(EncodingType encoding) { - return encoding & ENCODING_TYPE_FIXMAP_MASK; -} - -inline constexpr std::size_t GetFixextSize(EncodingType encoding) { - switch (encoding) { - case ENCODING_TYPE_FIXEXT1: - return 1; - case ENCODING_TYPE_FIXEXT2: - return 2; - case ENCODING_TYPE_FIXEXT4: - return 4; - case ENCODING_TYPE_FIXEXT8: - return 8; - case ENCODING_TYPE_FIXEXT16: - return 16; - default: - return 0; // Invalid fixext size. - } -} - -// Gets the size of the encoding in bytes, not including external payload data. -inline constexpr std::size_t GetEncodingSize(EncodingType encoding) { - switch (encoding) { - // Encoding is fully contained within the type value. - case ENCODING_TYPE_POSITIVE_FIXINT_MIN ... ENCODING_TYPE_POSITIVE_FIXINT_MAX: - case ENCODING_TYPE_NEGATIVE_FIXINT_MIN ... ENCODING_TYPE_NEGATIVE_FIXINT_MAX: - case ENCODING_TYPE_FIXMAP_MIN ... ENCODING_TYPE_FIXMAP_MAX: - case ENCODING_TYPE_FIXARRAY_MIN ... ENCODING_TYPE_FIXARRAY_MAX: - case ENCODING_TYPE_FIXSTR_MIN ... ENCODING_TYPE_FIXSTR_MAX: - case ENCODING_TYPE_NIL: - case ENCODING_TYPE_RESERVED: - case ENCODING_TYPE_FALSE: - case ENCODING_TYPE_TRUE: - return 1; - - // Encoding type followed by one-byte size or immediate value. - case ENCODING_TYPE_BIN8: - case ENCODING_TYPE_EXT8: - case ENCODING_TYPE_UINT8: - case ENCODING_TYPE_INT8: - case ENCODING_TYPE_STR8: - // Encoding type followed by one-byte extension type. - case ENCODING_TYPE_FIXEXT1: - case ENCODING_TYPE_FIXEXT2: - case ENCODING_TYPE_FIXEXT4: - case ENCODING_TYPE_FIXEXT8: - case ENCODING_TYPE_FIXEXT16: - return 2; - - // Encoding type followed by two-byte size or immediate value. - case ENCODING_TYPE_BIN16: - case ENCODING_TYPE_EXT16: - case ENCODING_TYPE_UINT16: - case ENCODING_TYPE_INT16: - case ENCODING_TYPE_STR16: - case ENCODING_TYPE_ARRAY16: - case ENCODING_TYPE_MAP16: - return 3; - - // Encoding type followed by four-byte size or immediate value. - case ENCODING_TYPE_BIN32: - case ENCODING_TYPE_EXT32: - case ENCODING_TYPE_FLOAT32: - case ENCODING_TYPE_UINT32: - case ENCODING_TYPE_INT32: - case ENCODING_TYPE_STR32: - case ENCODING_TYPE_ARRAY32: - case ENCODING_TYPE_MAP32: - return 5; - - // Encoding type followed by eight-byte immediate value. - case ENCODING_TYPE_FLOAT64: - case ENCODING_TYPE_UINT64: - case ENCODING_TYPE_INT64: - return 9; - - default: - return 0; - } -} - -// Encoding for standard types. Each supported data type has an associated -// encoding or set of encodings. These functions determine the MessagePack -// encoding based on the data type, value, and size of their arguments. - -inline constexpr EncodingType EncodeArrayType(std::size_t size) { - if (size < (1U << 4)) - return ENCODING_TYPE_FIXARRAY | (size & ENCODING_TYPE_FIXARRAY_MASK); - else if (size < (1U << 16)) - return ENCODING_TYPE_ARRAY16; - else - return ENCODING_TYPE_ARRAY32; -} - -inline constexpr EncodingType EncodeMapType(std::size_t size) { - if (size < (1U << 4)) - return ENCODING_TYPE_FIXMAP | (size & ENCODING_TYPE_FIXMAP_MASK); - else if (size < (1U << 16)) - return ENCODING_TYPE_MAP16; - else - return ENCODING_TYPE_MAP32; -} - -inline constexpr EncodingType EncodeStringType(std::size_t size) { - if (size < (1U << 5)) - return ENCODING_TYPE_FIXSTR | (size & ENCODING_TYPE_FIXSTR_MASK); - else if (size < (1U << 8)) - return ENCODING_TYPE_STR8; - else if (size < (1U << 16)) - return ENCODING_TYPE_STR16; - else - return ENCODING_TYPE_STR32; -} - -inline constexpr EncodingType EncodeBinType(std::size_t size) { - if (size < (1U << 8)) - return ENCODING_TYPE_BIN8; - else if (size < (1U << 16)) - return ENCODING_TYPE_BIN16; - else - return ENCODING_TYPE_BIN32; -} - -inline EncodingType EncodeType(const EmptyVariant& /*empty*/) { - return ENCODING_TYPE_NIL; -} - -// Variant is encoded as a single-element map, with the type index as the key. -template -inline EncodingType EncodeType(const Variant& /*variant*/) { - return EncodeMapType(1); -} - -template -inline constexpr EncodingType EncodeType(const StringWrapper& value) { - return EncodeStringType(value.length()); -} - -inline constexpr EncodingType EncodeType(const std::string& value) { - return EncodeStringType(value.length()); -} - -template -inline constexpr EncodingType EncodeType(const std::array& /*value*/) { - return EncodeArrayType(Size); -} - -template -inline constexpr EncodingType EncodeType(const ArrayWrapper& value) { - return EncodeArrayType(value.size()); -} - -template -inline constexpr EncodingType EncodeType( - const std::vector& value) { - return EncodeArrayType(value.size()); -} - -template -inline constexpr EncodingType EncodeType( - const std::map& value) { - return EncodeMapType(value.size()); -} - -template -inline constexpr EncodingType EncodeType( - const std::unordered_map& value) { - return EncodeMapType(value.size()); -} - -template -inline constexpr EncodingType EncodeType(const BufferWrapper& value) { - // BIN size is in bytes. - return EncodeBinType(value.size() * - sizeof(typename BufferWrapper::value_type)); -} - -template -inline constexpr EncodingType EncodeType(const std::pair& /*value*/) { - return EncodeArrayType(2); -} - -template -inline constexpr EncodingType EncodeType(const std::tuple& /*value*/) { - return EncodeArrayType(sizeof...(T)); -} - -// FileHandle is encoded as a FIXEXT2 with a type code for "FileDescriptor" -// and a signed 16-bit index into the pushed fd array. Empty file descriptor -// have an array index of -1. -template -inline constexpr EncodingType EncodeType(const FileHandle& /*fd*/) { - return ENCODING_TYPE_FIXEXT2; -} - -// ChannelHandle is encoded as a FIXEXT4 with a type of -// ENCODING_EXT_TYPE_CHANNEL_HANDLE and a signed 32-bit value representing -// a client channel in a remote process. Empty handle has a value of -1. -template -inline constexpr EncodingType EncodeType( - const ChannelHandle& /*handle*/) { - return ENCODING_TYPE_FIXEXT4; -} - -inline constexpr EncodingType EncodeType(const bool& value) { - return value ? ENCODING_TYPE_TRUE : ENCODING_TYPE_FALSE; -} - -// Type 'char' is a little bit special in that it is distinct from 'signed char' -// and 'unsigned char'. Treating it as an unsigned 8-bit value is safe for -// encoding purposes and nicely handles 7-bit ASCII encodings as FIXINT. -inline constexpr EncodingType EncodeType(const char& value) { - if (value < static_cast(1 << 7)) - return value; - else - return ENCODING_TYPE_UINT8; -} - -inline constexpr EncodingType EncodeType(const uint8_t& value) { - if (value < (1U << 7)) - return value; - else - return ENCODING_TYPE_UINT8; -} -inline constexpr EncodingType EncodeType(const int8_t& value) { - if (value >= -32) - return value; - else - return ENCODING_TYPE_INT8; -} -inline constexpr EncodingType EncodeType(const uint16_t& value) { - if (value < (1U << 7)) - return static_cast(value); - else if (value < (1U << 8)) - return ENCODING_TYPE_UINT8; - else - return ENCODING_TYPE_UINT16; -} -inline constexpr EncodingType EncodeType(const int16_t& value) { - if (value >= -32 && value <= 127) - return static_cast(value); - else if (value >= -128 && value <= 127) - return ENCODING_TYPE_INT8; - else - return ENCODING_TYPE_INT16; -} -inline constexpr EncodingType EncodeType(const uint32_t& value) { - if (value < (1U << 7)) - return static_cast(value); - else if (value < (1U << 8)) - return ENCODING_TYPE_UINT8; - else if (value < (1U << 16)) - return ENCODING_TYPE_UINT16; - else - return ENCODING_TYPE_UINT32; -} -inline constexpr EncodingType EncodeType(const int32_t& value) { - if (value >= -32 && value <= 127) - return static_cast(value); - else if (value >= -128 && value <= 127) - return ENCODING_TYPE_INT8; - else if (value >= -32768 && value <= 32767) - return ENCODING_TYPE_INT16; - else - return ENCODING_TYPE_INT32; -} -inline constexpr EncodingType EncodeType(const uint64_t& value) { - if (value < (1ULL << 7)) - return static_cast(value); - else if (value < (1ULL << 8)) - return ENCODING_TYPE_UINT8; - else if (value < (1ULL << 16)) - return ENCODING_TYPE_UINT16; - else if (value < (1ULL << 32)) - return ENCODING_TYPE_UINT32; - else - return ENCODING_TYPE_UINT64; -} -inline constexpr EncodingType EncodeType(const int64_t& value) { - if (value >= -32 && value <= 127) - return static_cast(value); - else if (value >= -128 && value <= 127) // Effectively [-128, -32). - return ENCODING_TYPE_INT8; - else if (value >= -32768 && value <= 32767) - return ENCODING_TYPE_INT16; - else if (value >= -2147483648 && value <= 2147483647) - return ENCODING_TYPE_INT32; - else - return ENCODING_TYPE_INT64; -} - -inline constexpr EncodingType EncodeType(const float& /*value*/) { - return ENCODING_TYPE_FLOAT32; -} - -inline constexpr EncodingType EncodeType(const double& /*value*/) { - return ENCODING_TYPE_FLOAT64; -} - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_ENCODING_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/enumeration.h b/libs/vr/libpdx/private/pdx/rpc/enumeration.h deleted file mode 100644 index 7a35d31b22..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/enumeration.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef ANDROID_PDX_RPC_ENUMERATION_H_ -#define ANDROID_PDX_RPC_ENUMERATION_H_ - -#include - -namespace android { -namespace pdx { -namespace rpc { - -// Utility for manipulating lists of types. Provides operations to lookup an -// element by type or index. - -namespace detail { - -// Helper type that captures type and index for each element of a type -// enumeration. -template -struct IndexedElement { - using Type = T; - static constexpr std::size_t Index = I; -}; - -// Helper type that captures an IndexSequence and corresponding list of types. -template -struct ElementIndexer; - -// Partial specialization that generates an instantiation of IndexElement -// for each element of a type enumeration using inheritance. Once a type -// enumeration is instantiated this way the compiler is able to deduce either I -// or T from the other using the method below. -template -struct ElementIndexer, Ts...> : IndexedElement... { -}; - -// Helper function that causes the compiler to deduce an IndexedElement -// given T. -template -static IndexedElement SelectElementByType(IndexedElement); - -// Helper function that causes the compiler to deduce an IndexedElement -// given I. -template -static IndexedElement SelectElementByIndex(IndexedElement); - -} // namespace detail - -// Deduces the IndexedElement given T and a type sequence Ts. This may be -// used to determine the index of T within Ts at compile time. -template -using ElementForType = decltype(detail::SelectElementByType( - detail::ElementIndexer::type, Ts...>{})); - -// Deduces the IndexedElement given I and a type sequence Ts. This may be -// used to determine the type of the element at index I within Ts at compile -// time. Tuple operations may also be used to accomplish the same task, however -// this implementation is provided here for symmetry. -template -using ElementForIndex = decltype(detail::SelectElementByIndex( - detail::ElementIndexer::type, Ts...>{})); - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_ENUMERATION_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/find_replace.h b/libs/vr/libpdx/private/pdx/rpc/find_replace.h deleted file mode 100644 index b4b086bd05..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/find_replace.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef ANDROID_PDX_RPC_FIND_REPLACE_H_ -#define ANDROID_PDX_RPC_FIND_REPLACE_H_ - -#include - -#include - -namespace android { -namespace pdx { -namespace rpc { - -// Utility class to capture types to find and replace. -template -struct FindReplace; - -template -using IsSameBaseType = typename std::is_same::type, - typename std::decay::type>; - -// Replaces the type Subject with type Replace if type Subject is the same type -// as type Find, excluding cv-reference qualifiers in the match. -template -using ReplaceType = - typename std::conditional::value, - CopyCVReferenceType, - Subject>::type; - -// Determines whether the type Find (excluding cv-reference qualifiers) is in -// the given parameter pack. -template -struct ContainsType : std::true_type {}; - -template -struct ContainsType - : std::conditional::value, std::true_type, - ContainsType>::type {}; - -template -struct ContainsType : std::false_type {}; - -} // namespace rpc -} // namespace pdx -} // namespace android - -#endif // ANDROID_PDX_RPC_FIND_REPLACE_H_ diff --git a/libs/vr/libpdx/private/pdx/rpc/function_traits.h b/libs/vr/libpdx/private/pdx/rpc/function_traits.h deleted file mode 100644 index 7641b0a7c1..0000000000 --- a/libs/vr/libpdx/private/pdx/rpc/function_traits.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef ANDROID_PDX_RPC_FUNCTION_TRAITS_H_ -#define ANDROID_PDX_RPC_FUNCTION_TRAITS_H_ - -#include - -#include - -namespace android { -namespace pdx { -namespace rpc { - -// Utility type to capture return and argument types of a function signature. -// Examples: -// typedef SignatureType SignatureType; -// using SignatureType = SignatureType; -template -using SignatureType = T; - -// Utility class to extract return and argument types from function types. -// Provides nested types for return value, arguments, and full signature. Also -// provides accessor types for individual arguments, argument-arity, and type -// substitution. -template -struct FunctionTraits; - -template -struct FunctionTraits { - using Return = Return_; - using Args = std::tuple; - using Signature = SignatureType; - - enum : std::size_t { Arity = sizeof...(Args_) }; - - template - using Arg = typename std::tuple_element::type; - - template - using RewriteArgs = - SignatureType...)>; - - template - using RewriteSignature = - SignatureType( - ConditionalRewrite...)>; - - template