diff options
132 files changed, 1836 insertions, 1932 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 7ab2a8d03f..e2ffd02c54 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -2175,14 +2175,13 @@ void Dumpstate::DumpstateBoard(int out_fd) { } /* - * mount debugfs for non-user builds which launch with S and unmount it - * after invoking dumpstateBoard_* methods. This is to enable debug builds - * to not have debugfs mounted during runtime. It will also ensure that - * debugfs is only accessed by the dumpstate HAL. + * mount debugfs for non-user builds with ro.product.enforce_debugfs_restrictions + * set to true and unmount it after invoking dumpstateBoard_* methods. + * This is to enable debug builds to not have debugfs mounted during runtime. + * It will also ensure that debugfs is only accessed by the dumpstate HAL. */ - auto api_level = android::base::GetIntProperty("ro.product.first_api_level", 0); - bool mount_debugfs = !PropertiesHelper::IsUserBuild() && api_level >= 31; - + auto mount_debugfs = + android::base::GetBoolProperty("ro.product.enforce_debugfs_restrictions", false); if (mount_debugfs) { RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"}, AS_ROOT_20); @@ -2290,7 +2289,10 @@ void Dumpstate::DumpstateBoard(int out_fd) { } if (mount_debugfs) { - RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20); + auto keep_debugfs_mounted = + android::base::GetProperty("persist.dbg.keep_debugfs_mounted", ""); + if (keep_debugfs_mounted.empty()) + RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20); } auto file_sizes = std::make_unique<ssize_t[]>(paths.size()); diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp index 2c573e4f4a..db508b52bd 100644 --- a/cmds/dumpstate/tests/dumpstate_test.cpp +++ b/cmds/dumpstate/tests/dumpstate_test.cpp @@ -1032,12 +1032,12 @@ class ZippedBugReportStreamTest : public DumpstateBaseTest { ZipArchiveHandle handle_; }; -// Generate a quick wifi report redirected to a file, open it and verify entry exist. -TEST_F(ZippedBugReportStreamTest, StreamWifiReport) { - std::string out_path = kTestDataPath + "out.zip"; +// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist. +TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) { + std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip"; android::base::unique_fd out_fd; CreateFd(out_path, &out_fd); - ds_.options_->wifi_only = true; + ds_.options_->limited_only = true; ds_.options_->stream_to_socket = true; RedirectOutputToFd(out_fd); @@ -1051,7 +1051,7 @@ TEST_F(ZippedBugReportStreamTest, StreamWifiReport) { ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()), entry.uncompressed_length); EXPECT_THAT(bugreport_txt_name, - testing::ContainsRegex("(bugreport-.+-wifi(-[[:digit:]]+){6}\\.txt)")); + testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)")); VerifyEntry(handle_, bugreport_txt_name, &entry); } diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 79aab822e4..3798ba73a4 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -46,11 +46,9 @@ message SurfaceChange { HiddenFlagChange hidden_flag = 12; OpaqueFlagChange opaque_flag = 13; SecureFlagChange secure_flag = 14; - DeferredTransactionChange deferred_transaction = 15; CornerRadiusChange corner_radius = 16; ReparentChange reparent = 17; RelativeParentChange relative_parent = 18; - ReparentChildrenChange reparent_children = 19; BackgroundBlurRadiusChange background_blur_radius = 20; ShadowRadiusChange shadow_radius = 21; BlurRegionsChange blur_regions = 22; @@ -114,11 +112,6 @@ message SecureFlagChange { required bool secure_flag = 1; } -message DeferredTransactionChange { - required int32 layer_id = 1; - required uint64 frame_number = 2; -} - message DisplayChange { required int32 id = 1; @@ -190,10 +183,6 @@ message ReparentChange { required int32 parent_id = 1; } -message ReparentChildrenChange { - required int32 parent_id = 1; -} - message RelativeParentChange { required int32 relative_parent_id = 1; required int32 z = 2; diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index bbbe6f7ec4..cfd42fec30 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -402,17 +402,9 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kSecureFlag: setSecureFlag(transaction, change.id(), change.secure_flag()); break; - case SurfaceChange::SurfaceChangeCase::kDeferredTransaction: - waitUntilDeferredTransactionLayerExists(change.deferred_transaction(), lock); - setDeferredTransaction(transaction, change.id(), - change.deferred_transaction()); - break; case SurfaceChange::SurfaceChangeCase::kReparent: setReparentChange(transaction, change.id(), change.reparent()); break; - case SurfaceChange::SurfaceChangeCase::kReparentChildren: - setReparentChildrenChange(transaction, change.id(), change.reparent_children()); - break; case SurfaceChange::SurfaceChangeCase::kRelativeParent: setRelativeParentChange(transaction, change.id(), change.relative_parent()); break; @@ -563,19 +555,6 @@ void Replayer::setSecureFlag(SurfaceComposerClient::Transaction& t, t.setFlags(mLayers[id], flag, layer_state_t::eLayerSecure); } -void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, - layer_id id, const DeferredTransactionChange& dtc) { - ALOGV("Layer %d: Setting Deferred Transaction -- layer_id=%d, " - "frame_number=%llu", - id, dtc.layer_id(), dtc.frame_number()); - if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) { - ALOGE("Layer %d not found in Deferred Transaction", dtc.layer_id()); - return; - } - - t.deferTransactionUntil_legacy(mLayers[id], mLayers[dtc.layer_id()], dtc.frame_number()); -} - void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, display_id id, const DispSurfaceChange& /*dsc*/) { sp<IGraphicBufferProducer> outProducer; @@ -679,13 +658,6 @@ void Replayer::waitUntilTimestamp(int64_t timestamp) { std::this_thread::sleep_for(std::chrono::nanoseconds(timestamp - mCurrentTime)); } -void Replayer::waitUntilDeferredTransactionLayerExists( - const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock) { - if (mLayers.count(dtc.layer_id()) == 0 || mLayers[dtc.layer_id()] == nullptr) { - mLayerCond.wait(lock, [&] { return (mLayers[dtc.layer_id()] != nullptr); }); - } -} - status_t Replayer::loadSurfaceComposerClient() { mComposerClient = new SurfaceComposerClient; return mComposerClient->initCheck(); @@ -709,15 +681,6 @@ void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t, t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z()); } -void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t, - layer_id id, const ReparentChildrenChange& c) { - if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) { - ALOGE("Layer %d not found in reparent children transaction", c.parent_id()); - return; - } - t.reparentChildren(mLayers[id], mLayers[c.parent_id()]); -} - void Replayer::setShadowRadiusChange(SurfaceComposerClient::Transaction& t, layer_id id, const ShadowRadiusChange& c) { t.setShadowRadius(mLayers[id], c.radius()); diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 324d591eaa..d62522a497 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -110,14 +110,10 @@ class Replayer { layer_id id, const OpaqueFlagChange& ofc); void setSecureFlag(SurfaceComposerClient::Transaction& t, layer_id id, const SecureFlagChange& sfc); - void setDeferredTransaction(SurfaceComposerClient::Transaction& t, - layer_id id, const DeferredTransactionChange& dtc); void setReparentChange(SurfaceComposerClient::Transaction& t, layer_id id, const ReparentChange& c); void setRelativeParentChange(SurfaceComposerClient::Transaction& t, layer_id id, const RelativeParentChange& c); - void setReparentChildrenChange(SurfaceComposerClient::Transaction& t, - layer_id id, const ReparentChildrenChange& c); void setShadowRadiusChange(SurfaceComposerClient::Transaction& t, layer_id id, const ShadowRadiusChange& c); void setBlurRegionsChange(SurfaceComposerClient::Transaction& t, @@ -133,8 +129,6 @@ class Replayer { display_id id, const ProjectionChange& pc); void waitUntilTimestamp(int64_t timestamp); - void waitUntilDeferredTransactionLayerExists( - const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock); status_t loadSurfaceComposerClient(); Trace mTrace; diff --git a/data/etc/android.software.translation.xml b/data/etc/android.software.translation.xml deleted file mode 100644 index 3b361e5cb8..0000000000 --- a/data/etc/android.software.translation.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2020 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<permissions> - <feature name="android.software.translation" /> -</permissions> diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml index c3c3a7f247..41f15144d4 100644 --- a/data/etc/handheld_core_hardware.xml +++ b/data/etc/handheld_core_hardware.xml @@ -54,7 +54,6 @@ <feature name="android.software.autofill" /> <feature name="android.software.cant_save_state" /> <feature name="android.software.secure_lock_screen" /> - <feature name="android.software.translation" /> <!-- Feature to specify if the device supports adding device admins. --> <feature name="android.software.device_admin" /> diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml index 4b565fda97..8c369dea99 100644 --- a/data/etc/tablet_core_hardware.xml +++ b/data/etc/tablet_core_hardware.xml @@ -54,7 +54,6 @@ <feature name="android.software.autofill" /> <feature name="android.software.cant_save_state" /> <feature name="android.software.secure_lock_screen" /> - <feature name="android.software.translation" /> <!-- Feature to specify if the device supports adding device admins. --> <feature name="android.software.device_admin" /> diff --git a/include/android/bitmap.h b/include/android/bitmap.h index a70dffd756..6704a1ddf2 100644 --- a/include/android/bitmap.h +++ b/include/android/bitmap.h @@ -241,6 +241,7 @@ typedef struct AHardwareBuffer AHardwareBuffer; * * Available since API level 30. * + * @param env Handle to the JNI environment pointer. * @param bitmap Handle to an android.graphics.Bitmap. * @param outBuffer On success, is set to a pointer to the * {@link AHardwareBuffer} associated with bitmap. This acquires diff --git a/include/android/choreographer.h b/include/android/choreographer.h index cc5420e239..b743f491e4 100644 --- a/include/android/choreographer.h +++ b/include/android/choreographer.h @@ -32,6 +32,11 @@ __BEGIN_DECLS struct AChoreographer; +/** + * Opaque type that provides access to an AChoreographer object. + * + * A pointer can be obtained using {@link AChoreographer_getInstance()}. + */ typedef struct AChoreographer AChoreographer; /** diff --git a/include/android/font.h b/include/android/font.h index a172618829..8a3a474f25 100644 --- a/include/android/font.h +++ b/include/android/font.h @@ -189,7 +189,7 @@ const char* _Nonnull AFont_getFontFilePath(const AFont* _Nonnull font) __INTRODU * Available since API level 29. * * \param font a font object. Passing NULL is not allowed. - * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned. + * \return a positive integer less than or equal to {@link AFONT_WEIGHT_MAX} is returned. */ uint16_t AFont_getWeight(const AFont* _Nonnull font) __INTRODUCED_IN(29); @@ -241,7 +241,7 @@ size_t AFont_getCollectionIndex(const AFont* _Nonnull font) __INTRODUCED_IN(29); * In this case, AFont_getAxisCount returns 2 and AFont_getAxisTag * and AFont_getAxisValue will return following values. * \code{.cpp} - * AFont* font = AFontIterator_next(ite); + * AFont* font = ASystemFontIterator_next(ite); * * // Returns the number of axes * AFont_getAxisCount(font); // Returns 2 @@ -289,7 +289,7 @@ uint32_t AFont_getAxisTag(const AFont* _Nonnull font, uint32_t axisIndex) * * \param font a font object. Passing NULL is not allowed. * \param axisIndex an index to the font variation settings. Passing value larger than or - * equal to {@link ASYstemFont_getAxisCount} is not allwed. + * equal to {@link AFont_getAxisCount} is not allowed. * \return a float value for the given font variation setting. */ float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex) diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h index 49e478c2f3..4417422687 100644 --- a/include/android/font_matcher.h +++ b/include/android/font_matcher.h @@ -36,7 +36,7 @@ * // Simple font query for the ASCII character. * std::vector<uint16_t> text = { 'A' }; * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); - * ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); * // runLength will be 1 and the font will points a valid font file. * AFontMatcher_destroy(matcher); * @@ -44,17 +44,17 @@ * std::vector<uint16_t> text = { 0x9AA8 }; * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); * AFontMatcher_setLocales(matcher, "zh-CN,ja-JP"); - * ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); * // runLength will be 1 and the font will points a Simplified Chinese font. * AFontMatcher_setLocales(matcher, "ja-JP,zh-CN"); - * ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); * // runLength will be 1 and the font will points a Japanese font. * AFontMatcher_destroy(matcher); * * // Querying font for text/color emoji * std::vector<uint16_t> text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 }; * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); - * ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); * // runLength will be 8 and the font will points a color emoji font. * AFontMatcher_destroy(matcher); * @@ -62,7 +62,7 @@ * // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character. * std::vector<uint16_t> text = { 0x05D0, 0x0E01 }; * AFontMatcher* matcher = AFontMatcher_create("sans-serif"); - * ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); + * AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength); * // runLength will be 1 and the font will points a Hebrew font. * AFontMatcher_destroy(matcher); * \endcode @@ -146,7 +146,7 @@ void AFontMatcher_destroy(AFontMatcher* _Nonnull matcher) __INTRODUCED_IN(29); /** * Set font style to matcher. * - * If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL} + * If this function is not called, the matcher performs with {@link AFONT_WEIGHT_NORMAL} * with non-italic style. * * Available since API level 29. @@ -206,7 +206,7 @@ void AFontMatcher_setFamilyVariant( * \param textLength a length of the given text buffer. This must not be zero. * \param runLengthOut if not null, the font run length will be filled. * \return a font to be used for given text and params. You need to release the returned font by - * ASystemFont_close when it is no longer needed. + * AFont_close when it is no longer needed. */ AFont* _Nonnull AFontMatcher_match( const AFontMatcher* _Nonnull matcher, diff --git a/include/powermanager/PowerHalController.h b/include/powermanager/PowerHalController.h index dd34c0a6c2..71a36d09e5 100644 --- a/include/powermanager/PowerHalController.h +++ b/include/powermanager/PowerHalController.h @@ -20,6 +20,7 @@ #include <android-base/thread_annotations.h> #include <android/hardware/power/Boost.h> #include <android/hardware/power/IPower.h> +#include <android/hardware/power/IPowerHintSession.h> #include <android/hardware/power/Mode.h> #include <powermanager/PowerHalWrapper.h> @@ -54,8 +55,12 @@ public: void init(); - virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override; - virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override; + virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) override; + virtual HalResult<int64_t> getHintSessionPreferredRate() override; private: std::mutex mConnectedHalMutex; @@ -67,7 +72,8 @@ private: const std::shared_ptr<HalWrapper> mDefaultHal = std::make_shared<EmptyHalWrapper>(); std::shared_ptr<HalWrapper> initHal(); - HalResult processHalResult(HalResult result, const char* functionName); + template <typename T> + HalResult<T> processHalResult(HalResult<T> result, const char* functionName); }; // ------------------------------------------------------------------------------------------------- diff --git a/include/powermanager/PowerHalWrapper.h b/include/powermanager/PowerHalWrapper.h index c3e7601c29..2c6eacbfaa 100644 --- a/include/powermanager/PowerHalWrapper.h +++ b/include/powermanager/PowerHalWrapper.h @@ -21,6 +21,7 @@ #include <android/hardware/power/1.1/IPower.h> #include <android/hardware/power/Boost.h> #include <android/hardware/power/IPower.h> +#include <android/hardware/power/IPowerHintSession.h> #include <android/hardware/power/Mode.h> namespace android { @@ -34,11 +35,81 @@ enum class HalSupport { OFF = 2, }; -// State of the Power HAL api call result. -enum class HalResult { - SUCCESSFUL = 0, - FAILED = 1, - UNSUPPORTED = 2, +// Result of a call to the Power HAL wrapper, holding data if successful. +template <typename T> +class HalResult { +public: + static HalResult<T> ok(T value) { return HalResult(value); } + static HalResult<T> failed(std::string msg) { + return HalResult(std::move(msg), /* unsupported= */ false); + } + static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); } + + static HalResult<T> fromStatus(binder::Status status, T data) { + if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { + return HalResult<T>::unsupported(); + } + if (status.isOk()) { + return HalResult<T>::ok(data); + } + return HalResult<T>::failed(std::string(status.toString8().c_str())); + } + static HalResult<T> fromStatus(hardware::power::V1_0::Status status, T data); + + template <typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, T data); + + template <typename R> + static HalResult<T> fromReturn(hardware::Return<R>& ret, hardware::power::V1_0::Status status, + T data); + + // This will throw std::bad_optional_access if this result is not ok. + const T& value() const { return mValue.value(); } + bool isOk() const { return !mUnsupported && mValue.has_value(); } + bool isFailed() const { return !mUnsupported && !mValue.has_value(); } + bool isUnsupported() const { return mUnsupported; } + const char* errorMessage() const { return mErrorMessage.c_str(); } + +private: + std::optional<T> mValue; + std::string mErrorMessage; + bool mUnsupported; + + explicit HalResult(T value) + : mValue(std::make_optional(value)), mErrorMessage(), mUnsupported(false) {} + explicit HalResult(std::string errorMessage, bool unsupported) + : mValue(), mErrorMessage(std::move(errorMessage)), mUnsupported(unsupported) {} +}; + +// Empty result of a call to the Power HAL wrapper. +template <> +class HalResult<void> { +public: + static HalResult<void> ok() { return HalResult(); } + static HalResult<void> failed(std::string msg) { return HalResult(std::move(msg)); } + static HalResult<void> unsupported() { return HalResult(/* unsupported= */ true); } + + static HalResult<void> fromStatus(status_t status); + static HalResult<void> fromStatus(binder::Status status); + static HalResult<void> fromStatus(hardware::power::V1_0::Status status); + + template <typename R> + static HalResult<void> fromReturn(hardware::Return<R>& ret); + + bool isOk() const { return !mUnsupported && !mFailed; } + bool isFailed() const { return !mUnsupported && mFailed; } + bool isUnsupported() const { return mUnsupported; } + const char* errorMessage() const { return mErrorMessage.c_str(); } + +private: + std::string mErrorMessage; + bool mFailed; + bool mUnsupported; + + explicit HalResult(bool unsupported = false) + : mErrorMessage(), mFailed(false), mUnsupported(unsupported) {} + explicit HalResult(std::string errorMessage) + : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {} }; // Wrapper for Power HAL handlers. @@ -46,8 +117,12 @@ class HalWrapper { public: virtual ~HalWrapper() = default; - virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) = 0; - virtual HalResult setMode(hardware::power::Mode mode, bool enabled) = 0; + virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) = 0; + virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) = 0; + virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) = 0; + virtual HalResult<int64_t> getHintSessionPreferredRate() = 0; }; // Empty Power HAL wrapper that ignores all api calls. @@ -56,8 +131,12 @@ public: EmptyHalWrapper() = default; ~EmptyHalWrapper() = default; - virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override; - virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override; + virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) override; + virtual HalResult<int64_t> getHintSessionPreferredRate() override; }; // Wrapper for the HIDL Power HAL v1.0. @@ -67,16 +146,20 @@ public: : mHandleV1_0(std::move(Hal)) {} virtual ~HidlHalWrapperV1_0() = default; - virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override; - virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override; + virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) override; + virtual HalResult<int64_t> getHintSessionPreferredRate() override; protected: - virtual HalResult sendPowerHint(hardware::power::V1_0::PowerHint hintId, uint32_t data); + virtual HalResult<void> sendPowerHint(hardware::power::V1_0::PowerHint hintId, uint32_t data); private: sp<hardware::power::V1_0::IPower> mHandleV1_0; - HalResult setInteractive(bool enabled); - HalResult setFeature(hardware::power::V1_0::Feature feature, bool enabled); + HalResult<void> setInteractive(bool enabled); + HalResult<void> setFeature(hardware::power::V1_0::Feature feature, bool enabled); }; // Wrapper for the HIDL Power HAL v1.1. @@ -88,8 +171,8 @@ public: virtual ~HidlHalWrapperV1_1() = default; protected: - virtual HalResult sendPowerHint(hardware::power::V1_0::PowerHint hintId, - uint32_t data) override; + virtual HalResult<void> sendPowerHint(hardware::power::V1_0::PowerHint hintId, + uint32_t data) override; private: sp<hardware::power::V1_1::IPower> mHandleV1_1; @@ -101,8 +184,12 @@ public: explicit AidlHalWrapper(sp<hardware::power::IPower> handle) : mHandle(std::move(handle)) {} virtual ~AidlHalWrapper() = default; - virtual HalResult setBoost(hardware::power::Boost boost, int32_t durationMs) override; - virtual HalResult setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<void> setBoost(hardware::power::Boost boost, int32_t durationMs) override; + virtual HalResult<void> setMode(hardware::power::Mode mode, bool enabled) override; + virtual HalResult<sp<hardware::power::IPowerHintSession>> createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos) override; + virtual HalResult<int64_t> getHintSessionPreferredRate() override; private: // Control access to the boost and mode supported arrays. diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index e980dd04ec..6da4e9eff9 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -160,6 +160,7 @@ cc_library { "-Werror", "-Wzero-as-null-pointer-constant", "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION", + "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION", ], product_variables: { binder32bit: { diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp index de42f36d74..baa9d75116 100644 --- a/libs/binder/AppOpsManager.cpp +++ b/libs/binder/AppOpsManager.cpp @@ -37,7 +37,7 @@ static const sp<IBinder>& getClientId() { pthread_mutex_lock(&gClientIdMutex); if (gClientId == nullptr) { - gClientId = new BBinder(); + gClientId = sp<BBinder>::make(); } pthread_mutex_unlock(&gClientIdMutex); return gClientId; diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 53b36fffdc..fdcf94acfa 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -107,8 +107,7 @@ void BpBinder::ObjectManager::kill() // --------------------------------------------------------------------------- - -BpBinder* BpBinder::create(int32_t handle) { +sp<BpBinder> BpBinder::create(int32_t handle) { int32_t trackedUid = -1; if (sCountByUidEnabled) { trackedUid = IPCThreadState::self()->getCallingUid(); @@ -134,10 +133,10 @@ BpBinder* BpBinder::create(int32_t handle) { } sTrackingMap[trackedUid]++; } - return new BpBinder(BinderHandle{handle}, trackedUid); + return sp<BpBinder>::make(BinderHandle{handle}, trackedUid); } -BpBinder* BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) { +sp<BpBinder> BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) { LOG_ALWAYS_FATAL_IF(connection == nullptr, "BpBinder::create null connection"); // These are not currently tracked, since there is no UID or other @@ -145,7 +144,7 @@ BpBinder* BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress // needed, connection objects keep track of all BpBinder objects on a // per-connection basis. - return new BpBinder(SocketHandle{connection, address}); + return sp<BpBinder>::make(SocketHandle{connection, address}); } BpBinder::BpBinder(Handle&& handle) @@ -194,7 +193,7 @@ bool BpBinder::isDescriptorCached() const { const String16& BpBinder::getInterfaceDescriptor() const { if (isDescriptorCached() == false) { - sp<BpBinder> thiz = const_cast<BpBinder*>(this); + sp<BpBinder> thiz = sp<BpBinder>::fromExisting(const_cast<BpBinder*>(this)); Parcel data; data.markForBinder(thiz); @@ -226,7 +225,7 @@ bool BpBinder::isBinderAlive() const status_t BpBinder::pingBinder() { Parcel data; - data.markForBinder(this); + data.markForBinder(sp<BpBinder>::fromExisting(this)); Parcel reply; return transact(PING_TRANSACTION, data, &reply); } @@ -403,7 +402,7 @@ void BpBinder::reportOneDeath(const Obituary& obit) ALOGV("Reporting death to recipient: %p\n", recipient.get()); if (recipient == nullptr) return; - recipient->binderDied(this); + recipient->binderDied(wp<BpBinder>::fromExisting(this)); } diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp index 349658ecfa..a90bfd29ba 100644 --- a/libs/binder/BufferedTextOutput.cpp +++ b/libs/binder/BufferedTextOutput.cpp @@ -254,7 +254,7 @@ BufferedTextOutput::BufferState* BufferedTextOutput::getBuffer() const BufferState* bs = ts.states[mIndex].get(); if (bs != nullptr && bs->seq == mSeq) return bs; - ts.states.editItemAt(mIndex) = new BufferState(mIndex); + ts.states.editItemAt(mIndex) = sp<BufferState>::make(mIndex); bs = ts.states[mIndex].get(); if (bs != nullptr) return bs; } diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp index b19004d454..2780bd4cd9 100644 --- a/libs/binder/IInterface.cpp +++ b/libs/binder/IInterface.cpp @@ -33,14 +33,14 @@ IInterface::~IInterface() { sp<IBinder> IInterface::asBinder(const IInterface* iface) { if (iface == nullptr) return nullptr; - return const_cast<IInterface*>(iface)->onAsBinder(); + return sp<IBinder>::fromExisting(const_cast<IInterface*>(iface)->onAsBinder()); } // static sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface) { if (iface == nullptr) return nullptr; - return iface->onAsBinder(); + return sp<IBinder>::fromExisting(iface->onAsBinder()); } diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp index cca8f81e45..bd974b02b1 100644 --- a/libs/binder/IMemory.cpp +++ b/libs/binder/IMemory.cpp @@ -68,7 +68,7 @@ private: // TODO: Reimplemement based on standard C++ container? }; -static sp<HeapCache> gHeapCache = new HeapCache(); +static sp<HeapCache> gHeapCache = sp<HeapCache>::make(); /******************************************************************************/ @@ -288,7 +288,7 @@ void BpMemoryHeap::assertMapped() const int32_t heapId = mHeapId.load(memory_order_acquire); if (heapId == -1) { sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this))); - sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get())); + sp<BpMemoryHeap> heap = sp<BpMemoryHeap>::cast(find_heap(binder)); heap->assertReallyMapped(); if (heap->mBase != MAP_FAILED) { Mutex::Autolock _l(mLock); diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index ca067e2d7f..61f4581df3 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -102,7 +102,7 @@ sp<IServiceManager> defaultServiceManager() } } - gDefaultServiceManager = new ServiceManagerShim(sm); + gDefaultServiceManager = sp<ServiceManagerShim>::make(sm); }); return gDefaultServiceManager; @@ -324,7 +324,7 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16) } if (out != nullptr) return out; - sp<Waiter> waiter = new Waiter; + sp<Waiter> waiter = sp<Waiter>::make(); if (!mTheRealServiceManager->registerForNotifications( name, waiter).isOk()) { return nullptr; diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp index f96b6bb4eb..b503bebc5e 100644 --- a/libs/binder/LazyServiceRegistrar.cpp +++ b/libs/binder/LazyServiceRegistrar.cpp @@ -129,7 +129,9 @@ bool ClientCounterCallbackImpl::registerService(const sp<IBinder>& service, cons } if (!reRegister) { - if(!manager->registerClientCallback(name, service, this).isOk()) { + if (!manager->registerClientCallback(name, service, + sp<android::os::IClientCallback>::fromExisting(this)) + .isOk()) { ALOGE("Failed to add client callback for service %s", name.c_str()); return false; } diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp index b46b3e88fc..c4475c7780 100644 --- a/libs/binder/MemoryDealer.cpp +++ b/libs/binder/MemoryDealer.cpp @@ -228,10 +228,8 @@ Allocation::~Allocation() // ---------------------------------------------------------------------------- MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags) - : mHeap(new MemoryHeapBase(size, flags, name)), - mAllocator(new SimpleBestFitAllocator(size)) -{ -} + : mHeap(sp<MemoryHeapBase>::make(size, flags, name)), + mAllocator(new SimpleBestFitAllocator(size)) {} MemoryDealer::~MemoryDealer() { @@ -243,7 +241,7 @@ sp<IMemory> MemoryDealer::allocate(size_t size) sp<IMemory> memory; const ssize_t offset = allocator()->allocate(size); if (offset >= 0) { - memory = new Allocation(this, heap(), offset, size); + memory = sp<Allocation>::make(sp<MemoryDealer>::fromExisting(this), heap(), offset, size); } return memory; } diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 0425159f63..a73530938c 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -293,7 +293,8 @@ status_t Parcel::unflattenBinder(sp<IBinder>* out) const if (flat) { switch (flat->hdr.type) { case BINDER_TYPE_BINDER: { - sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie); + sp<IBinder> binder = + sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie)); return finishUnflattenBinder(binder, out); } case BINDER_TYPE_HANDLE: { diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index abb792eda0..7647a8c0df 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -105,7 +105,7 @@ sp<ProcessState> ProcessState::init(const char *driver, bool requireDefault) } std::lock_guard<std::mutex> l(gProcessMutex); - gProcess = new ProcessState(driver); + gProcess = sp<ProcessState>::make(driver); }); if (requireDefault) { @@ -299,8 +299,8 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) return nullptr; } - b = BpBinder::create(handle); - e->binder = b; + sp<BpBinder> b = BpBinder::create(handle); + e->binder = b.get(); if (b) e->refs = b->getWeakRefs(); result = b; } else { @@ -340,7 +340,7 @@ void ProcessState::spawnPooledThread(bool isMain) if (mThreadPoolStarted) { String8 name = makeBinderThreadName(); ALOGV("Spawning new pooled thread, name=%s\n", name.string()); - sp<Thread> t = new PoolThread(isMain); + sp<Thread> t = sp<PoolThread>::make(isMain); t->run(name.string()); } } diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp index dab3246fc5..1bf3d889a5 100644 --- a/libs/binder/RpcConnection.cpp +++ b/libs/binder/RpcConnection.cpp @@ -54,7 +54,7 @@ RpcConnection::~RpcConnection() { } sp<RpcConnection> RpcConnection::make() { - return new RpcConnection; + return sp<RpcConnection>::make(); } class UnixSocketAddress : public RpcConnection::SocketAddress { @@ -120,20 +120,21 @@ bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) { #endif // __BIONIC__ sp<IBinder> RpcConnection::getRootObject() { - ExclusiveSocket socket(this, SocketUse::CLIENT); - return state()->getRootObject(socket.fd(), this); + ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT); + return state()->getRootObject(socket.fd(), sp<RpcConnection>::fromExisting(this)); } status_t RpcConnection::transact(const RpcAddress& address, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - ExclusiveSocket socket(this, + ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), (flags & IBinder::FLAG_ONEWAY) ? SocketUse::CLIENT_ASYNC : SocketUse::CLIENT); - return state()->transact(socket.fd(), address, code, data, this, reply, flags); + return state()->transact(socket.fd(), address, code, data, + sp<RpcConnection>::fromExisting(this), reply, flags); } status_t RpcConnection::sendDecStrong(const RpcAddress& address) { - ExclusiveSocket socket(this, SocketUse::CLIENT_REFCOUNT); + ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT_REFCOUNT); return state()->sendDecStrong(socket.fd(), address); } @@ -157,10 +158,11 @@ void RpcConnection::join() { // We may not use the connection we just established (two threads might // establish connections for each other), but for now, just use one // server/socket connection. - ExclusiveSocket socket(this, SocketUse::SERVER); + ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::SERVER); while (true) { - status_t error = state()->getAndExecuteCommand(socket.fd(), this); + status_t error = + state()->getAndExecuteCommand(socket.fd(), sp<RpcConnection>::fromExisting(this)); if (error != OK) { ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str()); @@ -221,7 +223,7 @@ bool RpcConnection::addClient(const SocketAddress& addr) { LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get()); std::lock_guard<std::mutex> _l(mSocketMutex); - sp<ConnectionSocket> connection = new ConnectionSocket(); + sp<ConnectionSocket> connection = sp<ConnectionSocket>::make(); connection->fd = std::move(serverFd); mClients.push_back(connection); return true; @@ -229,7 +231,7 @@ bool RpcConnection::addClient(const SocketAddress& addr) { void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) { std::lock_guard<std::mutex> _l(mSocketMutex); - sp<ConnectionSocket> connection = new ConnectionSocket(); + sp<ConnectionSocket> connection = sp<ConnectionSocket>::make(); connection->fd = std::move(fd); mServers.push_back(connection); } diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index df07916f7a..1fa37bacb3 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -36,7 +36,7 @@ RpcServer::RpcServer() {} RpcServer::~RpcServer() {} sp<RpcServer> RpcServer::make() { - return new RpcServer; + return sp<RpcServer>::make(); } void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() { @@ -47,7 +47,7 @@ sp<RpcConnection> RpcServer::addClientConnection() { LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); auto connection = RpcConnection::make(); - connection->setForServer(this); + connection->setForServer(sp<RpcServer>::fromExisting(this)); mConnections.push_back(connection); return connection; } diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h index 7079544080..7e9be417e1 100644 --- a/libs/binder/include/binder/Binder.h +++ b/libs/binder/include/binder/Binder.h @@ -131,8 +131,8 @@ protected: virtual void onLastStrongRef(const void* id); virtual bool onIncStrongAttempted(uint32_t flags, const void* id); - inline IBinder* remote() { return mRemote; } - inline IBinder* remote() const { return mRemote; } + inline IBinder* remote() const { return mRemote; } + inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); } private: BpRefBase(const BpRefBase& o); diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h index 8ab789318d..ad618f9de4 100644 --- a/libs/binder/include/binder/BpBinder.h +++ b/libs/binder/include/binder/BpBinder.h @@ -40,8 +40,8 @@ using binder_proxy_limit_callback = void(*)(int); class BpBinder : public IBinder { public: - static BpBinder* create(int32_t handle); - static BpBinder* create(const sp<RpcConnection>& connection, const RpcAddress& address); + static sp<BpBinder> create(int32_t handle); + static sp<BpBinder> create(const sp<RpcConnection>& connection, const RpcAddress& address); /** * Return value: @@ -143,6 +143,7 @@ public: private: friend PrivateAccessorForId; + friend class sp<BpBinder>; struct BinderHandle { int32_t handle; diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h index b86fc0b629..ff90b30380 100644 --- a/libs/binder/include/binder/IInterface.h +++ b/libs/binder/include/binder/IInterface.h @@ -143,11 +143,10 @@ public: \ { \ ::android::sp<I##INTERFACE> intr; \ if (obj != nullptr) { \ - intr = static_cast<I##INTERFACE*>( \ - obj->queryLocalInterface( \ - I##INTERFACE::descriptor).get()); \ + intr = ::android::sp<I##INTERFACE>::cast( \ + obj->queryLocalInterface(I##INTERFACE::descriptor)); \ if (intr == nullptr) { \ - intr = new Bp##INTERFACE(obj); \ + intr = ::android::sp<Bp##INTERFACE>::make(obj); \ } \ } \ return intr; \ diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h index ca29440e7c..0919648541 100644 --- a/libs/binder/include/binder/ProcessState.h +++ b/libs/binder/include/binder/ProcessState.h @@ -88,7 +88,8 @@ private: static sp<ProcessState> init(const char *defaultDriver, bool requireDefault); friend class IPCThreadState; - + friend class sp<ProcessState>; + explicit ProcessState(const char* driver); ~ProcessState(); diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index a2c2aee7b8..d29b651f0b 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -72,6 +72,7 @@ public: ~RpcServer(); private: + friend sp<RpcServer>; RpcServer(); bool mAgreedExperimental = false; diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index ff059d7e2b..64203f78a8 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -39,12 +39,50 @@ cc_library_headers { min_sdk_version: "29", } +cc_library_headers { + name: "libgui_aidl_headers", + vendor_available: true, + static_libs: [ + "libgui_aidl_static", + ], + + export_static_lib_headers: [ + "libgui_aidl_static", + ], +} + filegroup { name: "libgui_aidl", srcs: ["aidl/**/*.aidl"], path: "aidl/", } +cc_library_static { + name: "libgui_aidl_static", + vendor_available: true, + srcs: [ + ":libgui_aidl", + ], + + shared_libs: [ + "libbinder", + "libui", + ], + + local_include_dirs: [ + "include", + ], + + export_shared_lib_headers: [ + "libbinder", + ], + + aidl: { + export_aidl_headers: true + } +} + + cc_library_shared { name: "libgui", vendor_available: true, @@ -56,10 +94,16 @@ cc_library_shared { defaults: ["libgui_bufferqueue-defaults"], + static_libs: [ + "libgui_aidl_static", + ], + export_static_lib_headers: [ + "libgui_aidl_static", + ], + srcs: [ ":framework_native_aidl", ":inputconstants_aidl", - ":libgui_aidl", ":libgui_bufferqueue_sources", "BitTube.cpp", @@ -115,6 +159,10 @@ cc_library_shared { "libinput", ], + export_header_lib_headers: [ + "libgui_aidl_headers", + ], + // bufferhub is not used when building libgui for vendors target: { vendor: { @@ -136,15 +184,16 @@ cc_library_shared { }, }, + aidl: { + export_aidl_headers: true, + }, + header_libs: [ "libdvr_headers", + "libgui_aidl_headers", "libpdx_headers", ], - aidl: { - export_aidl_headers: true, - }, - pgo: { sampling: true, profile_file: "libgui/libgui.profdata", @@ -175,8 +224,8 @@ cc_library_static { srcs: [ ":inputconstants_aidl", - ":libgui_aidl", ":libgui_bufferqueue_sources", + ":libgui_aidl", ], } diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index bcdd06b6c8..e5afd408a9 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -204,13 +204,16 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width, if (mRequestedSize != newSize) { mRequestedSize.set(newSize); mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height); - if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { + if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - t.setFrame(mSurfaceControl, - {0, 0, static_cast<int32_t>(mSize.width), - static_cast<int32_t>(mSize.height)}); + // We only need to update the scale if we've received at least one buffer. The reason + // for this is the scale is calculated based on the requested size and buffer size. + // If there's no buffer, the scale will always be 1. + if (mLastBufferInfo.hasBuffer) { + setMatrix(&t, mLastBufferInfo); + } applyTransaction = true; } } @@ -374,8 +377,10 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); - mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; + mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), + bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, + bufferItem.mScalingMode); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */, @@ -388,8 +393,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this)); - t->setFrame(mSurfaceControl, - {0, 0, static_cast<int32_t>(mSize.width), static_cast<int32_t>(mSize.height)}); + setMatrix(t, mLastBufferInfo); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); @@ -515,6 +519,17 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } +void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, + const BufferInfo& bufferInfo) { + uint32_t bufWidth = bufferInfo.width; + uint32_t bufHeight = bufferInfo.height; + + float dsdx = mSize.width / static_cast<float>(bufWidth); + float dsdy = mSize.height / static_cast<float>(bufHeight); + + t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); +} + void BLASTBufferQueue::setTransactionCompleteCallback( uint64_t frameNumber, std::function<void(int64_t)>&& transactionCompleteCallback) { std::lock_guard _lock{mMutex}; diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 9cd3f631c8..e1b1efc0ed 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -152,6 +152,7 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outCount = ev.vsync.count; outVsyncEventData->id = ev.vsync.vsyncId; outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp; + outVsyncEventData->frameInterval = ev.vsync.frameInterval; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2a9a97ed13..55ed7fe298 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -45,7 +45,6 @@ layer_state_t::layer_state_t() reserved(0), cornerRadius(0.0f), backgroundBlurRadius(0), - barrierFrameNumber(0), transform(0), transformToDisplayInverse(false), crop(Rect::INVALID_RECT), @@ -87,9 +86,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeUint32, mask); SAFE_PARCEL(matrix.write, output); SAFE_PARCEL(output.write, crop); - SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, barrierSurfaceControl_legacy); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, reparentSurfaceControl); - SAFE_PARCEL(output.writeUint64, barrierFrameNumber); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, relativeLayerSurfaceControl); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, parentSurfaceControlForChild); SAFE_PARCEL(output.writeFloat, color.r); @@ -193,9 +190,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(matrix.read, input); SAFE_PARCEL(input.read, crop); - SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &barrierSurfaceControl_legacy); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &reparentSurfaceControl); - SAFE_PARCEL(input.readUint64, &barrierFrameNumber); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &relativeLayerSurfaceControl); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &parentSurfaceControlForChild); @@ -425,15 +420,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eBlurRegionsChanged; blurRegions = other.blurRegions; } - if (other.what & eDeferTransaction_legacy) { - what |= eDeferTransaction_legacy; - barrierSurfaceControl_legacy = other.barrierSurfaceControl_legacy; - barrierFrameNumber = other.barrierFrameNumber; - } - if (other.what & eReparentChildren) { - what |= eReparentChildren; - reparentSurfaceControl = other.reparentSurfaceControl; - } if (other.what & eRelativeLayerChanged) { what |= eRelativeLayerChanged; what &= ~eLayerChanged; @@ -459,10 +445,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } - if (other.what & eFrameChanged) { - what |= eFrameChanged; - orientedDisplaySpaceRect = other.orientedDisplaySpaceRect; - } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 879955b7d7..e6baba6e1d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1140,37 +1140,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBlurR return *this; } -SurfaceComposerClient::Transaction& -SurfaceComposerClient::Transaction::deferTransactionUntil_legacy( - const sp<SurfaceControl>& sc, const sp<SurfaceControl>& barrierSurfaceControl, - uint64_t frameNumber) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eDeferTransaction_legacy; - s->barrierSurfaceControl_legacy = barrierSurfaceControl; - s->barrierFrameNumber = frameNumber; - - registerSurfaceControlForCallback(sc); - return *this; -} - -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren( - const sp<SurfaceControl>& sc, const sp<SurfaceControl>& newParent) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eReparentChildren; - s->reparentSurfaceControl = newParent; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent( const sp<SurfaceControl>& sc, const sp<SurfaceControl>& newParent) { layer_state_t* s = getLayerState(sc); @@ -1246,20 +1215,6 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp<Surfac return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame( - const sp<SurfaceControl>& sc, const Rect& frame) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eFrameChanged; - s->orientedDisplaySpaceRect = frame; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, ReleaseBufferCallback callback) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index fbd16f4ea2..a48f95ae73 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -142,6 +142,33 @@ private: ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); + struct BufferInfo { + bool hasBuffer = false; + uint32_t width; + uint32_t height; + uint32_t transform; + // This is used to check if we should update the blast layer size immediately or wait until + // we get the next buffer. This will support scenarios where the layer can change sizes + // and the buffer will scale to fit the new size. + uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + + void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, + uint32_t scalingMode) { + this->hasBuffer = hasBuffer; + this->width = width; + this->height = height; + this->transform = transform; + this->scalingMode = scalingMode; + } + }; + + // Last acquired buffer's info. This is used to calculate the correct scale when size change is + // requested. We need to use the old buffer's info to determine what scale we need to apply to + // ensure the correct size. + BufferInfo mLastBufferInfo GUARDED_BY(mMutex); + void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) + REQUIRES(mMutex); + uint32_t mTransformHint GUARDED_BY(mMutex); sp<IGraphicBufferConsumer> mConsumer; @@ -159,11 +186,6 @@ private: std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); - // Last acquired buffer's scaling mode. This is used to check if we should update the blast - // layer size immediately or wait until we get the next buffer. This will support scenarios - // where the layer can change sizes and the buffer will scale to fit the new size. - uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index d74c2ba72b..4ade240dcf 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -30,6 +30,9 @@ struct VsyncEventData { // The deadline in CLOCK_MONOTONIC that the app needs to complete its // frame by (both on the CPU and the GPU) int64_t deadlineTimestamp = std::numeric_limits<int64_t>::max(); + + // The current frame interval in ns when this frame was scheduled. + int64_t frameInterval = 0; }; class DisplayEventDispatcher : public LooperCallback { diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 7179a20d22..0dffbde88a 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -75,6 +75,7 @@ public: uint32_t count; nsecs_t expectedVSyncTimestamp __attribute__((aligned(8))); nsecs_t deadlineTimestamp __attribute__((aligned(8))); + nsecs_t frameInterval __attribute__((aligned(8))); int64_t vsyncId; }; diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h index 3b4c009609..a23c20248c 100644 --- a/libs/gui/include/gui/FrameTimelineInfo.h +++ b/libs/gui/include/gui/FrameTimelineInfo.h @@ -18,7 +18,6 @@ #include <stdint.h> -#include <android/os/IInputConstants.h> #include <binder/Parcel.h> namespace android { @@ -31,7 +30,11 @@ struct FrameTimelineInfo { int64_t vsyncId = INVALID_VSYNC_ID; // The id of the input event that caused this buffer - int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID; + // Default is android::os::IInputConstants::INVALID_INPUT_EVENT_ID = 0 + // We copy the value of the input event ID instead of including the header, because libgui + // header libraries containing FrameTimelineInfo must be available to vendors, but libinput is + // not directly vendor available. + int32_t inputEventId = 0; status_t write(Parcel& output) const; status_t read(const Parcel& input); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 6c265c898a..d2d1e5b91c 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -82,11 +82,8 @@ struct layer_state_t { eTransparentRegionChanged = 0x00000020, eFlagsChanged = 0x00000040, eLayerStackChanged = 0x00000080, - /* was eCropChanged_legacy, now available 0x00000100, */ - eDeferTransaction_legacy = 0x00000200, eReleaseBufferListenerChanged = 0x00000400, eShadowRadiusChanged = 0x00000800, - eReparentChildren = 0x00001000, /* was eDetachChildren, now available 0x00002000, */ eRelativeLayerChanged = 0x00004000, eReparent = 0x00008000, @@ -106,7 +103,7 @@ struct layer_state_t { eHasListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, - eFrameChanged = 0x1'00000000, + /* was eFrameChanged, now available 0x1'00000000, */ eCachedBufferChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, @@ -153,9 +150,7 @@ struct layer_state_t { matrix22_t matrix; float cornerRadius; uint32_t backgroundBlurRadius; - sp<SurfaceControl> barrierSurfaceControl_legacy; sp<SurfaceControl> reparentSurfaceControl; - uint64_t barrierFrameNumber; sp<SurfaceControl> relativeLayerSurfaceControl; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 7ec5d8df83..fe6a30aa42 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -454,20 +454,8 @@ public: const std::vector<BlurRegion>& regions); Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack); Transaction& setMetadata(const sp<SurfaceControl>& sc, uint32_t key, const Parcel& p); - // Defers applying any changes made in this transaction until the Layer - // identified by handle reaches the given frameNumber. If the Layer identified - // by handle is removed, then we will apply this transaction regardless of - // what frame number has been reached. - Transaction& deferTransactionUntil_legacy(const sp<SurfaceControl>& sc, - const sp<SurfaceControl>& barrierSurfaceControl, - uint64_t frameNumber); - // Reparents all children of this layer to the new parent handle. - Transaction& reparentChildren(const sp<SurfaceControl>& sc, - const sp<SurfaceControl>& newParent); /// Reparents the current layer to the new parent handle. The new parent must not be null. - // This can be used instead of reparentChildren if the caller wants to - // only re-parent a specific child. Transaction& reparent(const sp<SurfaceControl>& sc, const sp<SurfaceControl>& newParent); Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color); @@ -479,7 +467,6 @@ public: Transaction& setTransform(const sp<SurfaceControl>& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc, bool transformToDisplayInverse); - Transaction& setFrame(const sp<SurfaceControl>& sc, const Rect& frame); Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp<SurfaceControl>& sc, int32_t bufferId); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index fe48d88376..9b1f0db83b 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -140,7 +140,6 @@ protected: /*parent*/ nullptr); t.setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max()) - .setFrame(mSurfaceControl, Rect(resolution)) .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); @@ -218,13 +217,13 @@ protected: col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { - EXPECT_GE(epsilon, abs(r - *(pixel))); - EXPECT_GE(epsilon, abs(g - *(pixel + 1))); - EXPECT_GE(epsilon, abs(b - *(pixel + 2))); + ASSERT_GE(epsilon, abs(r - *(pixel))); + ASSERT_GE(epsilon, abs(g - *(pixel + 1))); + ASSERT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { - EXPECT_GE(epsilon, abs(r - *(pixel))); - EXPECT_GE(epsilon, abs(g - *(pixel + 1))); - EXPECT_GE(epsilon, abs(b - *(pixel + 2))); + ASSERT_GE(epsilon, abs(r - *(pixel))); + ASSERT_GE(epsilon, abs(g - *(pixel + 1))); + ASSERT_GE(epsilon, abs(b - *(pixel + 2))); } ASSERT_EQ(false, ::testing::Test::HasFailure()); } @@ -466,7 +465,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); } TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { @@ -523,13 +523,15 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); + Rect bounds; + bounds.left = finalCropSideLength / 2; + bounds.top = 0; + bounds.right = bounds.left + finalCropSideLength; + bounds.bottom = finalCropSideLength; + + ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); - ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(0, 0, 0, - {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, - /*border*/ 0, /*outsideRegion*/ true)); + checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { @@ -596,7 +598,6 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { t.setLayerStack(bgSurface, 0) .show(bgSurface) .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) - .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setLayer(bgSurface, std::numeric_limits<int32_t>::max() - 1) .apply(); @@ -619,7 +620,8 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp index 7dbba31ba8..bcd39dbbf4 100644 --- a/libs/gui/tests/DisplayEventStructLayout_test.cpp +++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp @@ -34,7 +34,8 @@ TEST(DisplayEventStructLayoutTest, TestEventAlignment) { CHECK_OFFSET(DisplayEventReceiver::Event::VSync, count, 0); CHECK_OFFSET(DisplayEventReceiver::Event::VSync, expectedVSyncTimestamp, 8); CHECK_OFFSET(DisplayEventReceiver::Event::VSync, deadlineTimestamp, 16); - CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncId, 24); + CHECK_OFFSET(DisplayEventReceiver::Event::VSync, frameInterval, 24); + CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncId, 32); CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0); diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index dc2dd297c5..0edb213089 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -130,7 +130,7 @@ public: virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); int64_t getVsyncId() const; int64_t getFrameDeadline() const; - + int64_t getFrameInterval() const; private: Choreographer(const Choreographer&) = delete; @@ -418,6 +418,10 @@ int64_t Choreographer::getFrameDeadline() const { return mLastVsyncEventData.deadlineTimestamp; } +int64_t Choreographer::getFrameInterval() const { + return mLastVsyncEventData.frameInterval; +} + } // namespace android using namespace android; @@ -501,6 +505,10 @@ int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline(); } +int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) { + return AChoreographer_to_Choreographer(choreographer)->getFrameInterval(); +} + } // namespace android /* Glue for the NDK interface */ diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h index 0f4fd4521f..7d25ce8253 100644 --- a/libs/nativedisplay/include-private/private/android/choreographer.h +++ b/libs/nativedisplay/include-private/private/android/choreographer.h @@ -42,6 +42,11 @@ int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer); // value. int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer); +// Returns the current interval in ns between frames. +// Client are expected to call this function from their frame callback function. +// Calling this function from anywhere else will return an undefined value. +int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer); + // Trampoline functions allowing libandroid.so to define the NDK symbols without including // the entirety of libnativedisplay as a whole static lib. As libnativedisplay // maintains global state, libnativedisplay can never be directly statically diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt index fda6a20a0b..9ed4915481 100644 --- a/libs/nativedisplay/libnativedisplay.map.txt +++ b/libs/nativedisplay/libnativedisplay.map.txt @@ -31,6 +31,7 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographer_signalRefreshRateCallbacks*; android::AChoreographer_getVsyncId*; android::AChoreographer_getFrameDeadline*; + android::AChoreographer_getFrameInterval*; android::ADisplay_acquirePhysicalDisplays*; android::ADisplay_release*; android::ADisplay_getMaxSupportedFps*; diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h index 50e9d53604..61b3f94aab 100644 --- a/libs/nativewindow/include/android/native_window.h +++ b/libs/nativewindow/include/android/native_window.h @@ -157,6 +157,7 @@ int32_t ANativeWindow_getFormat(ANativeWindow* window); * For all of these parameters, if 0 is supplied then the window's base * value will come back in force. * + * \param window pointer to an ANativeWindow object. * \param width width of the buffers in pixels. * \param height height of the buffers in pixels. * \param format one of the AHardwareBuffer_Format constants. @@ -191,6 +192,7 @@ int32_t ANativeWindow_unlockAndPost(ANativeWindow* window); * * Available since API level 26. * + * \param window pointer to an ANativeWindow object. * \param transform combination of {@link ANativeWindowTransform} flags * \return 0 for success, or -EINVAL if \p transform is invalid */ @@ -208,6 +210,7 @@ int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transfo * * Available since API level 28. * + * \param window pointer to an ANativeWindow object. * \param dataSpace data space of all buffers queued after this call. * \return 0 for success, -EINVAL if window is invalid or the dataspace is not * supported. @@ -306,6 +309,8 @@ enum ANativeWindow_ChangeFrameRateStrategy { * valid refresh rate for this device's display - e.g., it's fine to pass 30fps * to a device that can only run the display at 60fps. * + * \param window pointer to an ANativeWindow object. + * * \param compatibility The frame rate compatibility of this window. The * compatibility value may influence the system's choice of display refresh * rate. See the ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* values for more info. diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp new file mode 100644 index 0000000000..9492bda8a1 --- /dev/null +++ b/libs/permission/Android.bp @@ -0,0 +1,5 @@ +// TODO(b/183654927): empty place holder to start moving permission related things out of libbinder +// (appops, permission controller, etc..) +cc_library_shared { + name: "libpermission", +} diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 026b19a75a..ec39137e24 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -91,6 +91,7 @@ filegroup { "skia/debug/CaptureTimer.cpp", "skia/debug/CommonPool.cpp", "skia/debug/SkiaCapture.cpp", + "skia/debug/SkiaMemoryReporter.cpp", "skia/filters/BlurFilter.cpp", "skia/filters/LinearEffect.cpp", ], diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index a69d1f0da0..8dd98c3ba3 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -141,7 +141,7 @@ public: // do any work. virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0; - // queries + // queries that are required to be thread safe virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; @@ -149,8 +149,11 @@ public: // ----- BEGIN NEW INTERFACE ----- + // queries that are required to be thread safe virtual bool isProtected() const = 0; virtual bool supportsProtectedContent() const = 0; + + // Attempt to switch RenderEngine into and out of protectedContext mode virtual bool useProtectedContext(bool useProtectedContext) = 0; // Notify RenderEngine of changes to the dimensions of the primary display @@ -197,7 +200,8 @@ public: virtual int getContextPriority() = 0; // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation - // also supports background blur. If false, no blur will be applied when drawing layers. + // also supports background blur. If false, no blur will be applied when drawing layers. This + // query is required to be thread safe. virtual bool supportsBackgroundBlur() = 0; // Returns the current type of RenderEngine instance that was created. diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index 69c6a09076..1db20c0be0 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "Cache.h" #include "AutoBackendTexture.h" #include "SkiaRenderEngine.h" @@ -28,9 +27,24 @@ namespace android::renderengine::skia { +namespace { // Warming shader cache, not framebuffer cache. constexpr bool kUseFrameBufferCache = false; +// clang-format off +// Any non-identity matrix will do. +const auto kScaleAndTranslate = mat4(0.7f, 0.f, 0.f, 0.f, + 0.f, 0.7f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 67.3f, 52.2f, 0.f, 1.f); +// clang-format on +// When choosing dataspaces below, whether the match the destination or not determined whether +// a color correction effect is added to the shader. There may be other additional shader details +// for particular color spaces. +// TODO(b/184842383) figure out which color related shaders are necessary +constexpr auto kDestDataSpace = ui::Dataspace::SRGB; +} // namespace + static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, sp<GraphicBuffer> dstBuffer) { // Somewhat arbitrary dimensions, but on screen and slightly shorter, based @@ -51,23 +65,29 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin .lightRadius = 2200.0f, .length = 0.955342f, }, + // important that this matches dest so the general shadow fragment shader doesn't + // have color correction added, and important that it be srgb, so the *vertex* shader + // doesn't have color correction added. + .sourceDataspace = kDestDataSpace, }; auto layers = std::vector<const LayerSettings*>{&layer}; - // The identity matrix will generate the fast shaders, and the second matrix - // (based on one seen while going from dialer to the home screen) will - // generate the slower (more general case) version. If we also need a - // slow version without color correction, we should use this matrix with - // display.outputDataspace set to SRGB. - bool identity = true; - for (const mat4 transform : { mat4(), mat4(0.728872f, 0.f, 0.f, 0.f, - 0.f, 0.727627f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 167.355743f, 1852.257812f, 0.f, 1.f) }) { - layer.geometry.positionTransform = transform; + // The identity matrix will generate the fast shader + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), + nullptr); + // This matrix, which has different scales for x and y, will + // generate the slower (more general case) version, which has variants for translucent + // casters and rounded rects. + // clang-format off + layer.geometry.positionTransform = mat4(0.7f, 0.f, 0.f, 0.f, + 0.f, 0.8f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f); + // clang-format on + for (auto translucent : {false, true}) { + layer.shadow.casterIsTranslucent = translucent; renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); - identity = false; } } @@ -89,33 +109,25 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }}, }; - // This matrix is based on actual data seen when opening the dialer. - // translate and scale creates new shaders when combined with rounded corners - // clang-format off - auto scale_and_translate = mat4(.19f, .0f, .0f, .0f, - .0f, .19f, .0f, .0f, - .0f, .0f, 1.f, .0f, - 169.f, 1527.f, .0f, 1.f); - // clang-format on + auto threeCornerRadii = {0.0f, 0.05f, 50.f}; + auto oneCornerRadius = {50.f}; // Test both drawRect and drawRRect auto layers = std::vector<const LayerSettings*>{&layer}; - for (auto transform : {mat4(), scale_and_translate}) { - layer.geometry.positionTransform = transform; - // fractional corner radius creates a shader that is used during home button swipe - for (float roundedCornersRadius : {0.0f, 0.05f, 500.f}) { + for (bool identity : {true, false}) { + layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate; + // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage + // due to animating corner radius. + // For the non-idenity matrix, only the large corner radius will create a new shader. + for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) { // roundedCornersCrop is always set, but it is this radius that triggers the behavior layer.geometry.roundedCornersRadius = roundedCornersRadius; - // No need to check UNKNOWN, which is treated as SRGB. - for (auto dataspace : {ui::Dataspace::SRGB, ui::Dataspace::DISPLAY_P3}) { - layer.sourceDataspace = dataspace; - for (bool isOpaque : {true, false}) { - layer.source.buffer.isOpaque = isOpaque; - for (auto alpha : {half(.23999f), half(1.0f)}) { - layer.alpha = alpha; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, - base::unique_fd(), nullptr); - } + for (bool isOpaque : {true, false}) { + layer.source.buffer.isOpaque = isOpaque; + for (auto alpha : {half(.23999f), half(1.0f)}) { + layer.alpha = alpha; + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + base::unique_fd(), nullptr); } } } @@ -139,11 +151,54 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting }; auto layers = std::vector<const LayerSettings*>{&layer}; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), - nullptr); + for (auto transform : {mat4(), kScaleAndTranslate}) { + layer.geometry.positionTransform = transform; + for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) { + layer.geometry.roundedCornersRadius = roundedCornersRadius; + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + base::unique_fd(), nullptr); + } + } } +static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, + sp<GraphicBuffer> dstBuffer) { + const Rect& displayRect = display.physicalDisplay; + FloatRect rect(0, 0, displayRect.width(), displayRect.height()); + LayerSettings layer{ + .geometry = + Geometry{ + .boundaries = rect, + }, + .alpha = 1, + }; + + auto layers = std::vector<const LayerSettings*>{&layer}; + for (int radius : {9, 60}) { + layer.backgroundBlurRadius = radius; + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + base::unique_fd(), nullptr); + } +} + +// +// The collection of shaders cached here were found by using perfetto to record shader compiles +// during actions that involve RenderEngine, logging the layer settings, and the shader code +// and reproducing those settings here. +// +// It is helpful when debugging this to turn on +// in SkGLRenderEngine.cpp: +// kPrintLayerSettings = true +// kFlushAfterEveryLayer = true +// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp +// gPrintSKSL = true +// +// TODO(b/184631553) cache the shader involved in youtube pip return. void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { + const int previousCount = renderengine->reportShadersCompiled(); + if (previousCount) { + ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount); + } const nsecs_t timeBefore = systemTime(); // The dimensions should not matter, so long as we draw inside them. const Rect displayRect(0, 0, 1080, 2340); @@ -151,7 +206,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { .physicalDisplay = displayRect, .clip = displayRect, .maxLuminance = 500, - .outputDataspace = ui::Dataspace::DISPLAY_P3, + .outputDataspace = kDestDataSpace, }; const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; @@ -166,12 +221,30 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp<GraphicBuffer> srcBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "drawImageLayer_src"); + drawSolidLayers(renderengine, display, dstBuffer); drawShadowLayers(renderengine, display, srcBuffer); + drawBlurLayers(renderengine, display, dstBuffer); + // The majority of shaders are related to sampling images. drawImageLayers(renderengine, display, dstBuffer, srcBuffer); + + // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; + const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE; + + sp<GraphicBuffer> externalBuffer = + new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, + usageExternal, "primeShaderCache_external"); + // TODO(b/184665179) doubles number of image shader compilations, but only somewhere + // between 6 and 8 will occur in real uses. + drawImageLayers(renderengine, display, dstBuffer, externalBuffer); + renderengine->unbindExternalTextureBuffer(externalBuffer->getId()); + + renderengine->unbindExternalTextureBuffer(srcBuffer->getId()); + const nsecs_t timeAfter = systemTime(); const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6; - ALOGD("shader cache generated in %f ms\n", compileTimeMs); + const int shadersCompiled = renderengine->reportShadersCompiled(); + ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs); } } // namespace android::renderengine::skia diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 94a0dca7f6..3b2c7e5f66 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -28,6 +28,7 @@ #include <SkColorFilter.h> #include <SkColorMatrix.h> #include <SkColorSpace.h> +#include <SkGraphics.h> #include <SkImage.h> #include <SkImageFilters.h> #include <SkRegion.h> @@ -40,13 +41,13 @@ #include <ui/DebugUtils.h> #include <ui/GraphicBuffer.h> #include <utils/Trace.h> -#include "Cache.h" #include <cmath> #include <cstdint> #include <memory> #include "../gl/GLExtensions.h" +#include "Cache.h" #include "ColorSpaces.h" #include "SkBlendMode.h" #include "SkImageInfo.h" @@ -54,8 +55,15 @@ #include "filters/LinearEffect.h" #include "log/log_main.h" #include "skia/debug/SkiaCapture.h" +#include "skia/debug/SkiaMemoryReporter.h" #include "system/graphics-base-v1.0.h" +namespace { +// Debugging settings +static const bool kPrintLayerSettings = false; +static const bool kFlushAfterEveryLayer = false; +} // namespace + bool checkGlError(const char* op, int lineNumber); namespace android { @@ -285,6 +293,10 @@ void SkiaGLRenderEngine::assertShadersCompiled(int numShaders) { numShaders, cached); } +int SkiaGLRenderEngine::reportShadersCompiled() { + return mSkSLCacheMonitor.shadersCachedSinceLastCall(); +} + SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLContext ctxt, EGLSurface placeholder, EGLContext protectedContext, EGLSurface protectedPlaceholder) @@ -735,6 +747,17 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, for (const auto& layer : layers) { ATRACE_NAME("DrawLayer"); + if (kPrintLayerSettings) { + std::stringstream ls; + PrintTo(*layer, &ls); + auto debugs = ls.str(); + int pos = 0; + while (pos < debugs.size()) { + ALOGD("cache_debug %s", debugs.substr(pos, 1000).c_str()); + pos += 1000; + } + } + sk_sp<SkImage> blurInput; if (blurCompositionLayer == layer) { LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface); @@ -956,6 +979,10 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } else { canvas->drawRect(bounds, paint); } + if (kFlushAfterEveryLayer) { + ATRACE_NAME("flush surface"); + activeSurface->flush(); + } } surfaceAutoSaveRestore.restore(); mCapture->endCapture(); @@ -1224,9 +1251,38 @@ void SkiaGLRenderEngine::dump(std::string& result) { StringAppendF(&result, "RenderEngine shaders cached since last dump/primeCache: %d\n", mSkSLCacheMonitor.shadersCachedSinceLastCall()); + std::vector<ResourcePair> cpuResourceMap = { + {"skia/sk_resource_cache/bitmap_", "Bitmaps"}, + {"skia/sk_resource_cache/rrect-blur_", "Masks"}, + {"skia/sk_resource_cache/rects-blur_", "Masks"}, + {"skia/sk_resource_cache/tessellated", "Shadows"}, + {"skia", "Other"}, + }; + SkiaMemoryReporter cpuReporter(cpuResourceMap, false); + SkGraphics::DumpMemoryStatistics(&cpuReporter); + StringAppendF(&result, "Skia CPU Caches: "); + cpuReporter.logTotals(result); + cpuReporter.logOutput(result); + { std::lock_guard<std::mutex> lock(mRenderingMutex); - StringAppendF(&result, "RenderEngine texture cache size: %zu\n", mTextureCache.size()); + + std::vector<ResourcePair> gpuResourceMap = { + {"texture_renderbuffer", "Texture/RenderBuffer"}, + {"texture", "Texture"}, + {"gr_text_blob_cache", "Text"}, + {"skia", "Other"}, + }; + SkiaMemoryReporter gpuReporter(gpuResourceMap, true); + mGrContext->dumpMemoryStatistics(&gpuReporter); + StringAppendF(&result, "Skia's GPU Caches: "); + gpuReporter.logTotals(result); + gpuReporter.logOutput(result); + StringAppendF(&result, "Skia's Wrapped Objects:\n"); + gpuReporter.logOutput(result, true); + + StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n", + mTextureCache.size()); StringAppendF(&result, "Dumping buffer ids...\n"); // TODO(178539829): It would be nice to know which layer these are coming from and what // the texture sizes are. @@ -1234,7 +1290,16 @@ void SkiaGLRenderEngine::dump(std::string& result) { StringAppendF(&result, "- 0x%" PRIx64 "\n", id); } StringAppendF(&result, "\n"); - StringAppendF(&result, "RenderEngine protected texture cache size: %zu\n", + + SkiaMemoryReporter gpuProtectedReporter(gpuResourceMap, true); + mProtectedGrContext->dumpMemoryStatistics(&gpuProtectedReporter); + StringAppendF(&result, "Skia's GPU Protected Caches: "); + gpuProtectedReporter.logTotals(result); + gpuProtectedReporter.logOutput(result); + StringAppendF(&result, "Skia's Protected Wrapped Objects:\n"); + gpuProtectedReporter.logOutput(result, true); + + StringAppendF(&result, "RenderEngine protected AHB/BackendTexture cache size: %zu\n", mProtectedTextureCache.size()); StringAppendF(&result, "Dumping buffer ids...\n"); for (const auto& [id, unused] : mProtectedTextureCache) { diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index 25557f1ce0..8e77c16b40 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -66,6 +66,7 @@ public: bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } void assertShadersCompiled(int numShaders) override; void onPrimaryDisplaySizeChanged(ui::Size size) override; + int reportShadersCompiled() override; protected: void dump(std::string& result) override; diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 59d7e2ff89..51ef088a25 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -59,6 +59,7 @@ public: virtual bool cleanupPostRender(CleanupMode) override { return true; }; virtual int getContextPriority() override { return 0; } virtual void assertShadersCompiled(int numShaders) {} + virtual int reportShadersCompiled() { return 0; } }; } // namespace skia diff --git a/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp b/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp new file mode 100644 index 0000000000..f24a4f1c05 --- /dev/null +++ b/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#undef LOG_TAG +#define LOG_TAG "RenderEngine" + +#include "SkiaMemoryReporter.h" + +#include <SkString.h> +#include <android-base/stringprintf.h> +#include <log/log_main.h> + +namespace android { +namespace renderengine { +namespace skia { + +using base::StringAppendF; + +SkiaMemoryReporter::SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize) + : mResourceMap(resourceMap), + mItemize(itemize), + mTotalSize("bytes", 0), + mPurgeableSize("bytes", 0) {} + +const char* SkiaMemoryReporter::mapName(const char* resourceName) { + for (auto& resource : mResourceMap) { + if (SkStrContains(resourceName, resource.first)) { + return resource.second; + } + } + return nullptr; +} + +void SkiaMemoryReporter::resetCurrentElement() { + mCurrentElement.clear(); + mCurrentValues.clear(); + mIsCurrentValueWrapped = false; +} + +void SkiaMemoryReporter::processCurrentElement() { + // compute the top level element name using the map + const char* resourceName = mCurrentElement.empty() ? nullptr : mapName(mCurrentElement.c_str()); + + // if we don't have a resource name then we don't know how to label the + // data and should abort. + if (resourceName == nullptr) { + resetCurrentElement(); + return; + } + + // Only count elements that contain "size"; other values just provide metadata. + auto sizeResult = mCurrentValues.find("size"); + if (sizeResult != mCurrentValues.end() && sizeResult->second.value > 0) { + if (!mIsCurrentValueWrapped) { + mTotalSize.value += sizeResult->second.value; + mTotalSize.count++; + } + } else { + resetCurrentElement(); + return; + } + + // find the purgeable size if one exists + auto purgeableResult = mCurrentValues.find("purgeable_size"); + if (!mIsCurrentValueWrapped && purgeableResult != mCurrentValues.end()) { + mPurgeableSize.value += purgeableResult->second.value; + mPurgeableSize.count++; + } + + // do we store this element in the wrapped list or the skia managed list + auto& results = mIsCurrentValueWrapped ? mWrappedResults : mResults; + + // insert a copy of the element and all of its keys. We must make a copy here instead of + // std::move() as we will continue to use these values later in the function and again + // when we move on to process the next element. + results.insert({mCurrentElement, mCurrentValues}); + + // insert the item into its mapped category + auto result = results.find(resourceName); + if (result != results.end()) { + auto& resourceValues = result->second; + auto totalResult = resourceValues.find(sizeResult->first); + if (totalResult != resourceValues.end()) { + ALOGE_IF(sizeResult->second.units != totalResult->second.units, + "resource units do not match so the sum of resource type (%s) will be invalid", + resourceName); + totalResult->second.value += sizeResult->second.value; + totalResult->second.count++; + } else { + ALOGE("an entry (%s) should not exist in the results without a size", resourceName); + } + } else { + // only store the size for the top level resource + results.insert({resourceName, {{sizeResult->first, sizeResult->second}}}); + } + + resetCurrentElement(); +} + +void SkiaMemoryReporter::dumpNumericValue(const char* dumpName, const char* valueName, + const char* units, uint64_t value) { + if (mCurrentElement != dumpName) { + processCurrentElement(); + mCurrentElement = dumpName; + } + mCurrentValues.insert({valueName, {units, value}}); +} + +void SkiaMemoryReporter::dumpWrappedState(const char* dumpName, bool isWrappedObject) { + if (mCurrentElement != dumpName) { + processCurrentElement(); + mCurrentElement = dumpName; + } + mIsCurrentValueWrapped = isWrappedObject; +} + +void SkiaMemoryReporter::logOutput(std::string& log, bool wrappedResources) { + // process the current element before logging + processCurrentElement(); + + const auto& resultsMap = wrappedResources ? mWrappedResults : mResults; + + // log each individual element based on the resource map + for (const auto& resourceCategory : mResourceMap) { + // find the named item and print the totals + const auto categoryItem = resultsMap.find(resourceCategory.second); + if (categoryItem != resultsMap.end()) { + auto result = categoryItem->second.find("size"); + if (result != categoryItem->second.end()) { + TraceValue traceValue = convertUnits(result->second); + const char* entry = (traceValue.count > 1) ? "entries" : "entry"; + StringAppendF(&log, " %s: %.2f %s (%d %s)\n", categoryItem->first.c_str(), + traceValue.value, traceValue.units, traceValue.count, entry); + } + if (mItemize) { + for (const auto& individualItem : resultsMap) { + // if the individual item matches the category then print all its details or + // in the case of wrapped resources just print the wrapped size + const char* categoryMatch = mapName(individualItem.first.c_str()); + if (categoryMatch && strcmp(categoryMatch, resourceCategory.second) == 0) { + auto result = individualItem.second.find("size"); + TraceValue size = convertUnits(result->second); + StringAppendF(&log, " %s: size[%.2f %s]", individualItem.first.c_str(), + size.value, size.units); + if (!wrappedResources) { + for (const auto& itemValues : individualItem.second) { + if (strcmp("size", itemValues.first) == 0) { + continue; + } + TraceValue traceValue = convertUnits(itemValues.second); + if (traceValue.value == 0.0f) { + StringAppendF(&log, " %s[%s]", itemValues.first, + traceValue.units); + } else { + StringAppendF(&log, " %s[%.2f %s]", itemValues.first, + traceValue.value, traceValue.units); + } + } + } + StringAppendF(&log, "\n"); + } + } + } + } + } +} + +void SkiaMemoryReporter::logTotals(std::string& log) { + // process the current element before logging + processCurrentElement(); + + TraceValue total = convertUnits(mTotalSize); + TraceValue purgeable = convertUnits(mPurgeableSize); + StringAppendF(&log, " %.0f bytes, %.2f %s (%.2f %s is purgeable)\n", mTotalSize.value, + total.value, total.units, purgeable.value, purgeable.units); +} + +SkiaMemoryReporter::TraceValue SkiaMemoryReporter::convertUnits(const TraceValue& value) { + TraceValue output(value); + if (SkString("bytes") == SkString(output.units) && output.value >= 1024) { + output.value = output.value / 1024.0f; + output.units = "KB"; + } + if (SkString("KB") == SkString(output.units) && output.value >= 1024) { + output.value = output.value / 1024.0f; + output.units = "MB"; + } + return output; +} + +} /* namespace skia */ +} /* namespace renderengine */ +} /* namespace android */ diff --git a/libs/renderengine/skia/debug/SkiaMemoryReporter.h b/libs/renderengine/skia/debug/SkiaMemoryReporter.h new file mode 100644 index 0000000000..dbbd65b3da --- /dev/null +++ b/libs/renderengine/skia/debug/SkiaMemoryReporter.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2021 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 <SkTraceMemoryDump.h> + +#include <string> +#include <unordered_map> +#include <vector> + +namespace android { +namespace renderengine { +namespace skia { + +// Mapping of resource substrings (1st element) that if found within a trace "dumpName" +// should be mapped to the category name (2nd element). All char* used in a resourcePair +// are expected to have a lifetime longer than the SkiaMemoryReporter in which they are used. +typedef std::pair<const char*, const char*> ResourcePair; + +/* + * Utility class for logging the CPU/GPU usage of Skia caches in a format that is specific + * to RenderEngine. HWUI has a similar logging class, but the data collected and the way + * it is formatted and reported on are intended to be unique to each use case. + */ +class SkiaMemoryReporter : public SkTraceMemoryDump { +public: + /** + * Creates the reporter class that can be populated by various Skia entry points, like + * SkGraphics and GrContext, as well as format and log the results. + * @param resourceMap An array of values that maps a Skia dumpName into a user defined category. + * The first vector entry that matches the dumpName is used for the mapping. + * @param itemize if true when logging the categories the individual elements will be printed + * directly after the category details are printed. Otherwise, only the category + * totals will be printed. + */ + SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize); + ~SkiaMemoryReporter() override {} + + void logOutput(std::string& log, bool wrappedResources = false); + void logTotals(std::string& log); + + void dumpNumericValue(const char* dumpName, const char* valueName, const char* units, + uint64_t value) override; + + void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override { + // for convenience we just store this in the same format as numerical values + dumpNumericValue(dumpName, valueName, value, 0); + } + void dumpWrappedState(const char* dumpName, bool isWrappedObject) override; + + LevelOfDetail getRequestedDetails() const override { + return SkTraceMemoryDump::kLight_LevelOfDetail; + } + + bool shouldDumpWrappedObjects() const override { return true; } + void setMemoryBacking(const char*, const char*, const char*) override {} + void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override {} + +private: + struct TraceValue { + TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {} + TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {} + + const char* units; + float value; + int count; + }; + + const char* mapName(const char* resourceName); + void processCurrentElement(); + void resetCurrentElement(); + TraceValue convertUnits(const TraceValue& value); + + const std::vector<ResourcePair>& mResourceMap; + const bool mItemize; + + // variables storing the size of all non-wrapped elements being dumped + TraceValue mTotalSize; + TraceValue mPurgeableSize; + + // variables storing information on the current node being dumped + std::string mCurrentElement; + std::unordered_map<const char*, TraceValue> mCurrentValues; + bool mIsCurrentValueWrapped = false; + + // variable that stores the final format of the data after the individual elements are processed + std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults; + std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mWrappedResults; +}; + +} /* namespace skia */ +} /* namespace renderengine */ +} /* namespace android */
\ No newline at end of file diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 63aa4c891c..b093e88d4f 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -49,6 +49,9 @@ TEST_F(RenderEngineThreadedTest, dump) { TEST_F(RenderEngineThreadedTest, primeCache) { EXPECT_CALL(*mRenderEngine, primeCache()); mThreadedRE->primeCache(); + // need to call ANY synchronous function after primeCache to ensure that primeCache has + // completed asynchronously before the test completes execution. + mThreadedRE->getContextPriority(); } TEST_F(RenderEngineThreadedTest, genTextures) { diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 783e37fc22..194c7da1c7 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -74,6 +74,12 @@ void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_S std::unique_lock<std::mutex> lock(mThreadMutex); pthread_setname_np(pthread_self(), mThreadName); + { + std::unique_lock<std::mutex> lock(mInitializedMutex); + mIsInitialized = true; + } + mInitializedCondition.notify_all(); + while (mRunning) { if (!mFunctionCalls.empty()) { auto task = mFunctionCalls.front(); @@ -86,19 +92,22 @@ void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_S } } +void RenderEngineThreaded::waitUntilInitialized() const { + std::unique_lock<std::mutex> lock(mInitializedMutex); + mInitializedCondition.wait(lock, [=] { return mIsInitialized; }); +} + void RenderEngineThreaded::primeCache() { - std::promise<void> resultPromise; - std::future<void> resultFuture = resultPromise.get_future(); + // This function is designed so it can run asynchronously, so we do not need to wait + // for the futures. { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { + mFunctionCalls.push([](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::primeCache"); instance.primeCache(); - resultPromise.set_value(); }); } mCondition.notify_one(); - resultFuture.wait(); } void RenderEngineThreaded::dump(std::string& result) { @@ -175,63 +184,26 @@ void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { } size_t RenderEngineThreaded::getMaxTextureSize() const { - std::promise<size_t> resultPromise; - std::future<size_t> resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::getMaxTextureSize"); - size_t size = instance.getMaxTextureSize(); - resultPromise.set_value(size); - }); - } - mCondition.notify_one(); - return resultFuture.get(); + waitUntilInitialized(); + return mRenderEngine->getMaxTextureSize(); } size_t RenderEngineThreaded::getMaxViewportDims() const { - std::promise<size_t> resultPromise; - std::future<size_t> resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::getMaxViewportDims"); - size_t size = instance.getMaxViewportDims(); - resultPromise.set_value(size); - }); - } - mCondition.notify_one(); - return resultFuture.get(); + waitUntilInitialized(); + return mRenderEngine->getMaxViewportDims(); } bool RenderEngineThreaded::isProtected() const { - std::promise<bool> resultPromise; - std::future<bool> resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::isProtected"); - bool returnValue = instance.isProtected(); - resultPromise.set_value(returnValue); - }); - } - mCondition.notify_one(); - return resultFuture.get(); + waitUntilInitialized(); + // ensure that useProtectedContext is not currently being changed by some + // other thread. + std::lock_guard lock(mThreadMutex); + return mRenderEngine->isProtected(); } bool RenderEngineThreaded::supportsProtectedContent() const { - std::promise<bool> resultPromise; - std::future<bool> resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::supportsProtectedContent"); - bool returnValue = instance.supportsProtectedContent(); - resultPromise.set_value(returnValue); - }); - } - mCondition.notify_one(); - return resultFuture.get(); + waitUntilInitialized(); + return mRenderEngine->supportsProtectedContent(); } bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) { @@ -288,18 +260,16 @@ status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, } void RenderEngineThreaded::cleanFramebufferCache() { - std::promise<void> resultPromise; - std::future<void> resultFuture = resultPromise.get_future(); + // This function is designed so it can run asynchronously, so we do not need to wait + // for the futures. { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { + mFunctionCalls.push([](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::cleanFramebufferCache"); instance.cleanFramebufferCache(); - resultPromise.set_value(); }); } mCondition.notify_one(); - resultFuture.wait(); } int RenderEngineThreaded::getContextPriority() { @@ -318,33 +288,21 @@ int RenderEngineThreaded::getContextPriority() { } bool RenderEngineThreaded::supportsBackgroundBlur() { - std::promise<bool> resultPromise; - std::future<bool> resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::supportsBackgroundBlur"); - bool returnValue = instance.supportsBackgroundBlur(); - resultPromise.set_value(returnValue); - }); - } - mCondition.notify_one(); - return resultFuture.get(); + waitUntilInitialized(); + return mRenderEngine->supportsBackgroundBlur(); } void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) { - std::promise<void> resultPromise; - std::future<void> resultFuture = resultPromise.get_future(); + // This function is designed so it can run asynchronously, so we do not need to wait + // for the futures. { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise, size](renderengine::RenderEngine& instance) { + mFunctionCalls.push([size](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged"); instance.onPrimaryDisplaySizeChanged(size); - resultPromise.set_value(); }); } mCondition.notify_one(); - resultFuture.wait(); } } // namespace threaded diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 117257a90e..61ae9b8cf8 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -70,6 +70,7 @@ public: private: void threadMain(CreateInstanceFactory factory); + void waitUntilInitialized() const; /* ------------------------------------------------------------------------ * Threading @@ -83,6 +84,12 @@ private: GUARDED_BY(mThreadMutex); mutable std::condition_variable mCondition; + // Used to allow select thread safe methods to be accessed without requiring the + // method to be invoked on the RenderEngine thread + bool mIsInitialized = false; + mutable std::mutex mInitializedMutex; + mutable std::condition_variable mInitializedCondition; + /* ------------------------------------------------------------------------ * Render Engine */ diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 073455a7ff..4e058478a7 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2326,6 +2326,8 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { if (dropWindow) { vec2 local = dropWindow->getInfo()->transform.transform(x, y); notifyDropWindowLocked(dropWindow->getToken(), local.x, local.y); + } else { + notifyDropWindowLocked(nullptr, 0, 0); } mDragState.reset(); } @@ -2372,6 +2374,7 @@ void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { } else if (maskedAction == AMOTION_EVENT_ACTION_UP) { finishDragAndDrop(entry.displayId, x, y); } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) { + notifyDropWindowLocked(nullptr, 0, 0); mDragState.reset(); } } diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp index 746889409c..7db32e3071 100644 --- a/services/inputflinger/reader/Android.bp +++ b/services/inputflinger/reader/Android.bp @@ -36,7 +36,7 @@ filegroup { srcs: [ "EventHub.cpp", "InputDevice.cpp", - "controller/InputController.cpp", + "controller/PeripheralController.cpp", "mapper/accumulator/CursorButtonAccumulator.cpp", "mapper/accumulator/CursorScrollAccumulator.cpp", "mapper/accumulator/SingleTouchMotionAccumulator.cpp", diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 045d24cac6..e3e6c12485 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -363,7 +363,7 @@ EventHub::Device::Device(int fd, int32_t id, const std::string& path, virtualKeyMap(nullptr), ffEffectPlaying(false), ffEffectId(-1), - miscDevice(nullptr), + associatedDevice(nullptr), controllerNumber(0), enabled(true), isVirtual(fd < 0) {} @@ -554,7 +554,7 @@ status_t EventHub::Device::mapLed(int32_t led, int32_t* outScanCode) const { } // Check the sysfs path for any input device batteries, returns true if battery found. -bool EventHub::MiscDevice::configureBatteryLocked() { +bool EventHub::AssociatedDevice::configureBatteryLocked() { nextBatteryId = 0; // Check if device has any battery. const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY); @@ -580,7 +580,7 @@ bool EventHub::MiscDevice::configureBatteryLocked() { } // Check the sysfs path for any input device lights, returns true if lights found. -bool EventHub::MiscDevice::configureLightsLocked() { +bool EventHub::AssociatedDevice::configureLightsLocked() { nextLightId = 0; // Check if device has any lights. const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS); @@ -988,14 +988,10 @@ const std::unordered_map<int32_t, RawBatteryInfo>& EventHub::getBatteryInfoLocke int32_t deviceId) const { static const std::unordered_map<int32_t, RawBatteryInfo> EMPTY_BATTERY_INFO = {}; Device* device = getDeviceLocked(deviceId); - if (device == nullptr) { - return EMPTY_BATTERY_INFO; - } - auto it = mMiscDevices.find(device->identifier.descriptor); - if (it == mMiscDevices.end()) { + if (device == nullptr || !device->associatedDevice) { return EMPTY_BATTERY_INFO; } - return it->second->batteryInfos; + return device->associatedDevice->batteryInfos; } const std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) { @@ -1028,14 +1024,10 @@ const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked( int32_t deviceId) const { static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {}; Device* device = getDeviceLocked(deviceId); - if (device == nullptr) { - return EMPTY_LIGHT_INFO; - } - auto it = mMiscDevices.find(device->identifier.descriptor); - if (it == mMiscDevices.end()) { + if (device == nullptr || !device->associatedDevice) { return EMPTY_LIGHT_INFO; } - return it->second->lightInfos; + return device->associatedDevice->lightInfos; } const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) { @@ -1946,18 +1938,20 @@ void EventHub::openDeviceLocked(const std::string& devicePath) { // Check the sysfs root path std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str()); if (sysfsRootPath.has_value()) { - std::shared_ptr<MiscDevice> miscDevice; - auto it = mMiscDevices.find(device->identifier.descriptor); - if (it == mMiscDevices.end()) { - miscDevice = std::make_shared<MiscDevice>(sysfsRootPath.value()); - } else { - miscDevice = it->second; + std::shared_ptr<AssociatedDevice> associatedDevice; + for (const auto& [id, dev] : mDevices) { + if (device->identifier.descriptor == dev->identifier.descriptor && + !dev->associatedDevice) { + associatedDevice = dev->associatedDevice; + } } - hasBattery = miscDevice->configureBatteryLocked(); - hasLights = miscDevice->configureLightsLocked(); + if (!associatedDevice) { + associatedDevice = std::make_shared<AssociatedDevice>(sysfsRootPath.value()); + } + hasBattery = associatedDevice->configureBatteryLocked(); + hasLights = associatedDevice->configureLightsLocked(); - device->miscDevice = miscDevice; - mMiscDevices.insert_or_assign(device->identifier.descriptor, std::move(miscDevice)); + device->associatedDevice = associatedDevice; } // Figure out the kinds of events the device reports. @@ -2329,12 +2323,6 @@ void EventHub::closeDeviceLocked(Device& device) { mClosingDevices.push_back(std::move(mDevices[device.id])); mDevices.erase(device.id); - // If all devices with the descriptor have been removed then the miscellaneous device should - // be removed too. - std::string descriptor = device.identifier.descriptor; - if (getDeviceByDescriptorLocked(descriptor) == nullptr) { - mMiscDevices.erase(descriptor); - } } status_t EventHub::readNotifyLocked() { diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index f935c3679f..8f75d22d87 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -23,11 +23,11 @@ #include "CursorInputMapper.h" #include "ExternalStylusInputMapper.h" -#include "InputController.h" #include "InputReaderContext.h" #include "JoystickInputMapper.h" #include "KeyboardInputMapper.h" #include "MultiTouchInputMapper.h" +#include "PeripheralController.h" #include "RotaryEncoderInputMapper.h" #include "SensorInputMapper.h" #include "SingleTouchInputMapper.h" @@ -165,9 +165,9 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) { } // Battery-like devices or light-containing devices. - // InputController will be created with associated EventHub device. + // PeripheralController will be created with associated EventHub device. if (classes.test(InputDeviceClass::BATTERY) || classes.test(InputDeviceClass::LIGHT)) { - mController = std::make_unique<InputController>(*contextPtr); + mController = std::make_unique<PeripheralController>(*contextPtr); } // Keyboard-like devices. @@ -504,8 +504,6 @@ void InputDevice::cancelTouch(nsecs_t when, nsecs_t readTime) { for_each_mapper([when, readTime](InputMapper& mapper) { mapper.cancelTouch(when, readTime); }); } -// TODO b/180733860 support multiple battery in API and remove this. -constexpr int32_t DEFAULT_BATTERY_ID = 1; std::optional<int32_t> InputDevice::getBatteryCapacity() { return mController ? mController->getBatteryCapacity(DEFAULT_BATTERY_ID) : std::nullopt; } diff --git a/services/inputflinger/reader/controller/InputController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp index 45266fbd2d..1a40d06f45 100644 --- a/services/inputflinger/reader/controller/InputController.cpp +++ b/services/inputflinger/reader/controller/PeripheralController.cpp @@ -19,7 +19,7 @@ #include "../Macros.h" -#include "InputController.h" +#include "PeripheralController.h" #include "input/NamedEnum.h" // Log detailed debug messages about input device lights. @@ -52,15 +52,15 @@ static inline int32_t toArgb(int32_t brightness, int32_t red, int32_t green, int * lights, getting and setting the lights brightness and color, by interacting with EventHub * devices. */ -InputController::InputController(InputDeviceContext& deviceContext) +PeripheralController::PeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) { configureBattries(); configureLights(); } -InputController::~InputController() {} +PeripheralController::~PeripheralController() {} -std::optional<std::int32_t> InputController::Light::getRawLightBrightness(int32_t rawLightId) { +std::optional<std::int32_t> PeripheralController::Light::getRawLightBrightness(int32_t rawLightId) { std::optional<RawLightInfo> rawInfoOpt = context.getRawLightInfo(rawLightId); if (!rawInfoOpt.has_value()) { return std::nullopt; @@ -85,7 +85,7 @@ std::optional<std::int32_t> InputController::Light::getRawLightBrightness(int32_ return brightness; } -void InputController::Light::setRawLightBrightness(int32_t rawLightId, int32_t brightness) { +void PeripheralController::Light::setRawLightBrightness(int32_t rawLightId, int32_t brightness) { std::optional<RawLightInfo> rawInfo = context.getRawLightInfo(rawLightId); if (!rawInfo.has_value()) { return; @@ -104,14 +104,14 @@ void InputController::Light::setRawLightBrightness(int32_t rawLightId, int32_t b context.setLightBrightness(rawLightId, brightness); } -bool InputController::SingleLight::setLightColor(int32_t color) { +bool PeripheralController::SingleLight::setLightColor(int32_t color) { int32_t brightness = getAlpha(color); setRawLightBrightness(rawId, brightness); return true; } -bool InputController::RgbLight::setLightColor(int32_t color) { +bool PeripheralController::RgbLight::setLightColor(int32_t color) { // Compose color value as per: // https://developer.android.com/reference/android/graphics/Color?hl=en // int color = (A & 0xff) << 24 | (R & 0xff) << 16 | (G & 0xff) << 8 | (B & 0xff); @@ -137,7 +137,7 @@ bool InputController::RgbLight::setLightColor(int32_t color) { return true; } -bool InputController::MultiColorLight::setLightColor(int32_t color) { +bool PeripheralController::MultiColorLight::setLightColor(int32_t color) { std::unordered_map<LightColor, int32_t> intensities; intensities.emplace(LightColor::RED, getRed(color)); intensities.emplace(LightColor::GREEN, getGreen(color)); @@ -148,7 +148,7 @@ bool InputController::MultiColorLight::setLightColor(int32_t color) { return true; } -std::optional<int32_t> InputController::SingleLight::getLightColor() { +std::optional<int32_t> PeripheralController::SingleLight::getLightColor() { std::optional<int32_t> brightness = getRawLightBrightness(rawId); if (!brightness.has_value()) { return std::nullopt; @@ -157,7 +157,7 @@ std::optional<int32_t> InputController::SingleLight::getLightColor() { return toArgb(brightness.value(), 0 /* red */, 0 /* green */, 0 /* blue */); } -std::optional<int32_t> InputController::RgbLight::getLightColor() { +std::optional<int32_t> PeripheralController::RgbLight::getLightColor() { // If the Alpha component is zero, then return color 0. if (brightness == 0) { return 0; @@ -192,7 +192,7 @@ std::optional<int32_t> InputController::RgbLight::getLightColor() { return toArgb(brightness, red, green, blue); } -std::optional<int32_t> InputController::MultiColorLight::getLightColor() { +std::optional<int32_t> PeripheralController::MultiColorLight::getLightColor() { auto ret = context.getLightIntensities(rawId); if (!ret.has_value()) { return std::nullopt; @@ -210,7 +210,7 @@ std::optional<int32_t> InputController::MultiColorLight::getLightColor() { return std::nullopt; } -bool InputController::PlayerIdLight::setLightPlayerId(int32_t playerId) { +bool PeripheralController::PlayerIdLight::setLightPlayerId(int32_t playerId) { if (rawLightIds.find(playerId) == rawLightIds.end()) { return false; } @@ -224,7 +224,7 @@ bool InputController::PlayerIdLight::setLightPlayerId(int32_t playerId) { return true; } -std::optional<int32_t> InputController::PlayerIdLight::getLightPlayerId() { +std::optional<int32_t> PeripheralController::PlayerIdLight::getLightPlayerId() { for (const auto& [id, rawId] : rawLightIds) { std::optional<int32_t> brightness = getRawLightBrightness(rawId); if (brightness.has_value() && brightness.value() > 0) { @@ -234,11 +234,11 @@ std::optional<int32_t> InputController::PlayerIdLight::getLightPlayerId() { return std::nullopt; } -void InputController::SingleLight::dump(std::string& dump) { +void PeripheralController::SingleLight::dump(std::string& dump) { dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0)); } -void InputController::PlayerIdLight::dump(std::string& dump) { +void PeripheralController::PlayerIdLight::dump(std::string& dump) { dump += StringPrintf(INDENT4 "PlayerId: %d\n", getLightPlayerId().value_or(-1)); dump += StringPrintf(INDENT4 "Raw Player ID LEDs:"); for (const auto& [id, rawId] : rawLightIds) { @@ -247,7 +247,7 @@ void InputController::PlayerIdLight::dump(std::string& dump) { dump += "\n"; } -void InputController::RgbLight::dump(std::string& dump) { +void PeripheralController::RgbLight::dump(std::string& dump) { dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0)); dump += StringPrintf(INDENT4 "Raw RGB LEDs: [%d, %d, %d] ", rawRgbIds.at(LightColor::RED), rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE)); @@ -257,11 +257,11 @@ void InputController::RgbLight::dump(std::string& dump) { dump += "\n"; } -void InputController::MultiColorLight::dump(std::string& dump) { +void PeripheralController::MultiColorLight::dump(std::string& dump) { dump += StringPrintf(INDENT4 "Color: 0x%x\n", getLightColor().value_or(0)); } -void InputController::populateDeviceInfo(InputDeviceInfo* deviceInfo) { +void PeripheralController::populateDeviceInfo(InputDeviceInfo* deviceInfo) { // TODO: b/180733860 Remove this after enabling multi-battery if (!mBatteries.empty()) { deviceInfo->setHasBattery(true); @@ -279,7 +279,7 @@ void InputController::populateDeviceInfo(InputDeviceInfo* deviceInfo) { } } -void InputController::dump(std::string& dump) { +void PeripheralController::dump(std::string& dump) { dump += INDENT2 "Input Controller:\n"; if (!mLights.empty()) { dump += INDENT3 "Lights:\n"; @@ -340,7 +340,7 @@ void InputController::dump(std::string& dump) { } } -void InputController::configureBattries() { +void PeripheralController::configureBattries() { // Check raw batteries const std::vector<int32_t> rawBatteryIds = getDeviceContext().getRawBatteryIds(); @@ -355,7 +355,7 @@ void InputController::configureBattries() { } } -void InputController::configureLights() { +void PeripheralController::configureLights() { bool hasRedLed = false; bool hasGreenLed = false; bool hasBlueLed = false; @@ -472,15 +472,15 @@ void InputController::configureLights() { } } -std::optional<int32_t> InputController::getBatteryCapacity(int batteryId) { +std::optional<int32_t> PeripheralController::getBatteryCapacity(int batteryId) { return getDeviceContext().getBatteryCapacity(batteryId); } -std::optional<int32_t> InputController::getBatteryStatus(int batteryId) { +std::optional<int32_t> PeripheralController::getBatteryStatus(int batteryId) { return getDeviceContext().getBatteryStatus(batteryId); } -bool InputController::setLightColor(int32_t lightId, int32_t color) { +bool PeripheralController::setLightColor(int32_t lightId, int32_t color) { auto it = mLights.find(lightId); if (it == mLights.end()) { return false; @@ -493,7 +493,7 @@ bool InputController::setLightColor(int32_t lightId, int32_t color) { return light->setLightColor(color); } -std::optional<int32_t> InputController::getLightColor(int32_t lightId) { +std::optional<int32_t> PeripheralController::getLightColor(int32_t lightId) { auto it = mLights.find(lightId); if (it == mLights.end()) { return std::nullopt; @@ -507,7 +507,7 @@ std::optional<int32_t> InputController::getLightColor(int32_t lightId) { return color; } -bool InputController::setLightPlayerId(int32_t lightId, int32_t playerId) { +bool PeripheralController::setLightPlayerId(int32_t lightId, int32_t playerId) { auto it = mLights.find(lightId); if (it == mLights.end()) { return false; @@ -516,7 +516,7 @@ bool InputController::setLightPlayerId(int32_t lightId, int32_t playerId) { return light->setLightPlayerId(playerId); } -std::optional<int32_t> InputController::getLightPlayerId(int32_t lightId) { +std::optional<int32_t> PeripheralController::getLightPlayerId(int32_t lightId) { auto it = mLights.find(lightId); if (it == mLights.end()) { return std::nullopt; diff --git a/services/inputflinger/reader/controller/InputController.h b/services/inputflinger/reader/controller/PeripheralController.h index d4222e2804..ff3607f6c1 100644 --- a/services/inputflinger/reader/controller/InputController.h +++ b/services/inputflinger/reader/controller/PeripheralController.h @@ -17,19 +17,19 @@ #ifndef _UI_INPUTREADER_LIGHT_CONTROLLER_H #define _UI_INPUTREADER_LIGHT_CONTROLLER_H -#include "InputControllerInterface.h" +#include "PeripheralControllerInterface.h" namespace android { -class InputController : public InputControllerInterface { +class PeripheralController : public PeripheralControllerInterface { // Refer to https://developer.android.com/reference/kotlin/android/graphics/Color /* Number of colors : {red, green, blue} */ static constexpr size_t COLOR_NUM = 3; static constexpr int32_t MAX_BRIGHTNESS = 0xff; public: - explicit InputController(InputDeviceContext& deviceContext); - ~InputController() override; + explicit PeripheralController(InputDeviceContext& deviceContext); + ~PeripheralController() override; void populateDeviceInfo(InputDeviceInfo* deviceInfo) override; void dump(std::string& dump) override; diff --git a/services/inputflinger/reader/controller/InputControllerInterface.h b/services/inputflinger/reader/controller/PeripheralControllerInterface.h index 504ededf9d..7688a431d1 100644 --- a/services/inputflinger/reader/controller/InputControllerInterface.h +++ b/services/inputflinger/reader/controller/PeripheralControllerInterface.h @@ -24,14 +24,14 @@ namespace android { -/* An input controller manages the miscellaneous devices associated with the input device, +/* A peripheral controller manages the input device peripherals associated with the input device, * like the sysfs based battery and light class devices. * */ -class InputControllerInterface { +class PeripheralControllerInterface { public: - InputControllerInterface() {} - virtual ~InputControllerInterface() {} + PeripheralControllerInterface() {} + virtual ~PeripheralControllerInterface() {} // Interface methods for Battery virtual std::optional<int32_t> getBatteryCapacity(int32_t batteryId) = 0; diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index c970c8bcda..410a7063ea 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -528,7 +528,7 @@ public: ~EventHub() override; private: - struct MiscDevice { + struct AssociatedDevice { // The device descriptor from evdev device the misc device associated with. std::string descriptor; // The sysfs root path of the misc device. @@ -538,7 +538,7 @@ private: int32_t nextLightId; std::unordered_map<int32_t, RawBatteryInfo> batteryInfos; std::unordered_map<int32_t, RawLightInfo> lightInfos; - explicit MiscDevice(std::filesystem::path sysfsRootPath) + explicit AssociatedDevice(std::filesystem::path sysfsRootPath) : sysfsRootPath(sysfsRootPath), nextBatteryId(0), nextLightId(0) {} bool configureBatteryLocked(); bool configureLightsLocked(); @@ -573,7 +573,9 @@ private: bool ffEffectPlaying; int16_t ffEffectId; // initially -1 - std::shared_ptr<MiscDevice> miscDevice; + // A shared_ptr of a device associated with the input device. + // The input devices with same descriptor has the same associated device. + std::shared_ptr<AssociatedDevice> associatedDevice; int32_t controllerNumber; @@ -690,11 +692,6 @@ private: std::vector<std::unique_ptr<Device>> mOpeningDevices; std::vector<std::unique_ptr<Device>> mClosingDevices; - // Map from std::string descriptor, to a shared_ptr of a miscellaneous device associated with - // the input device. The descriptor is the same from the EventHub device which it associates - // with. - std::unordered_map<std::string, std::shared_ptr<MiscDevice>> mMiscDevices; - bool mNeedToSendFinishedDeviceScan; bool mNeedToReopenDevices; bool mNeedToScanDevices; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 5d56f5a2ef..b2b23e5977 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -32,9 +32,11 @@ #include "InputReaderContext.h" namespace android { +// TODO b/180733860 support multiple battery in API and remove this. +constexpr int32_t DEFAULT_BATTERY_ID = 1; -class InputController; -class InputControllerInterface; +class PeripheralController; +class PeripheralControllerInterface; class InputDeviceContext; class InputMapper; @@ -162,7 +164,7 @@ private: // Map from EventHub ID to pair of device context and vector of mapper. std::unordered_map<int32_t, DevicePair> mDevices; // Misc devices controller for lights, battery, etc. - std::unique_ptr<InputControllerInterface> mController; + std::unique_ptr<PeripheralControllerInterface> mController; uint32_t mSources; bool mIsExternal; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index b62fce4a1c..31d6900ef2 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -268,7 +268,9 @@ public: void assertDropTargetEquals(const sp<IBinder>& targetToken) { std::scoped_lock lock(mLock); + ASSERT_TRUE(mNotifyDropWindowWasCalled); ASSERT_EQ(targetToken, mDropTargetWindowToken); + mNotifyDropWindowWasCalled = false; } private: @@ -290,6 +292,7 @@ private: std::condition_variable mNotifyAnr; sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock); + bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false; void notifyConfigurationChanged(nsecs_t when) override { std::scoped_lock lock(mLock); @@ -403,6 +406,7 @@ private: void notifyDropWindow(const sp<IBinder>& token, float x, float y) override { std::scoped_lock lock(mLock); + mNotifyDropWindowWasCalled = true; mDropTargetWindowToken = token; } @@ -4951,4 +4955,40 @@ TEST_F(InputDispatcherDragTests, StylusDragAndDrop) { mSecondWindow->assertNoEvents(); } +TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) { + performDrag(); + + // Set second window invisible. + mSecondWindow->setVisible(false); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}}); + + // Move on window. + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {50, 50})) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); + mWindow->consumeDragEvent(false, 50, 50); + mSecondWindow->assertNoEvents(); + + // Move to another window. + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {150, 50})) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT); + mWindow->consumeDragEvent(true, 150, 50); + mSecondWindow->assertNoEvents(); + + // drop to another window. + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, + {150, 50})) + << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; + mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT); + mFakePolicy->assertDropTargetEquals(nullptr); + mWindow->assertNoEvents(); + mSecondWindow->assertNoEvents(); +} + } // namespace android::inputdispatcher diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 3d99a6b863..0e721e909d 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -15,7 +15,6 @@ */ #include <CursorInputMapper.h> -#include <InputController.h> #include <InputDevice.h> #include <InputMapper.h> #include <InputReader.h> @@ -23,6 +22,7 @@ #include <InputReaderFactory.h> #include <KeyboardInputMapper.h> #include <MultiTouchInputMapper.h> +#include <PeripheralController.h> #include <SensorInputMapper.h> #include <SingleTouchInputMapper.h> #include <SwitchInputMapper.h> @@ -2015,13 +2015,13 @@ TEST_F(InputReaderTest, VibratorGetVibratorIds) { ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U); } -// --- FakeInputController --- +// --- FakePeripheralController --- -class FakeInputController : public InputControllerInterface { +class FakePeripheralController : public PeripheralControllerInterface { public: - FakeInputController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {} + FakePeripheralController(InputDeviceContext& deviceContext) : mDeviceContext(deviceContext) {} - ~FakeInputController() override {} + ~FakePeripheralController() override {} void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {} @@ -2064,7 +2064,8 @@ TEST_F(InputReaderTest, BatteryGetCapacity) { constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); - FakeInputController& controller = device->addController<FakeInputController>(eventHubId); + FakePeripheralController& controller = + device->addController<FakePeripheralController>(eventHubId); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr)); @@ -2079,7 +2080,8 @@ TEST_F(InputReaderTest, BatteryGetStatus) { constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); - FakeInputController& controller = device->addController<FakeInputController>(eventHubId); + FakePeripheralController& controller = + device->addController<FakePeripheralController>(eventHubId); mReader->pushNextDevice(device); ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr)); @@ -2094,7 +2096,8 @@ TEST_F(InputReaderTest, LightGetColor) { constexpr int32_t eventHubId = 1; const char* DEVICE_LOCATION = "BLUETOOTH"; std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION); - FakeInputController& controller = device->addController<FakeInputController>(eventHubId); + FakePeripheralController& controller = + device->addController<FakePeripheralController>(eventHubId); mReader->pushNextDevice(device); RawLightInfo info = {.id = 1, .name = "Mono", @@ -8598,9 +8601,9 @@ TEST_F(MultiTouchInputMapperTest, WhenCapturedAndNotCaptured_GetSources) { ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources()); } -// --- InputControllerTest --- +// --- PeripheralControllerTest --- -class InputControllerTest : public testing::Test { +class PeripheralControllerTest : public testing::Test { protected: static const char* DEVICE_NAME; static const char* DEVICE_LOCATION; @@ -8663,41 +8666,43 @@ protected: } }; -const char* InputControllerTest::DEVICE_NAME = "device"; -const char* InputControllerTest::DEVICE_LOCATION = "BLUETOOTH"; -const int32_t InputControllerTest::DEVICE_ID = END_RESERVED_ID + 1000; -const int32_t InputControllerTest::DEVICE_GENERATION = 2; -const int32_t InputControllerTest::DEVICE_CONTROLLER_NUMBER = 0; -const Flags<InputDeviceClass> InputControllerTest::DEVICE_CLASSES = +const char* PeripheralControllerTest::DEVICE_NAME = "device"; +const char* PeripheralControllerTest::DEVICE_LOCATION = "BLUETOOTH"; +const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000; +const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2; +const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0; +const Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES = Flags<InputDeviceClass>(0); // not needed for current tests -const int32_t InputControllerTest::EVENTHUB_ID = 1; +const int32_t PeripheralControllerTest::EVENTHUB_ID = 1; // --- BatteryControllerTest --- -class BatteryControllerTest : public InputControllerTest { +class BatteryControllerTest : public PeripheralControllerTest { protected: void SetUp() override { - InputControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY); + PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY); } }; TEST_F(BatteryControllerTest, GetBatteryCapacity) { - InputController& controller = addControllerAndConfigure<InputController>(); + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); ASSERT_TRUE(controller.getBatteryCapacity(DEFAULT_BATTERY)); ASSERT_EQ(controller.getBatteryCapacity(DEFAULT_BATTERY).value_or(-1), BATTERY_CAPACITY); } TEST_F(BatteryControllerTest, GetBatteryStatus) { - InputController& controller = addControllerAndConfigure<InputController>(); + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); ASSERT_TRUE(controller.getBatteryStatus(DEFAULT_BATTERY)); ASSERT_EQ(controller.getBatteryStatus(DEFAULT_BATTERY).value_or(-1), BATTERY_STATUS); } // --- LightControllerTest --- -class LightControllerTest : public InputControllerTest { +class LightControllerTest : public PeripheralControllerTest { protected: - void SetUp() override { InputControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT); } + void SetUp() override { + PeripheralControllerTest::SetUp(DEVICE_CLASSES | InputDeviceClass::LIGHT); + } }; TEST_F(LightControllerTest, SingleLight) { @@ -8708,7 +8713,7 @@ TEST_F(LightControllerTest, SingleLight) { .path = ""}; mFakeEventHub->addRawLightInfo(infoSingle.id, std::move(infoSingle)); - InputController& controller = addControllerAndConfigure<InputController>(); + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); InputDeviceInfo info; controller.populateDeviceInfo(&info); const auto& ids = info.getLightIds(); @@ -8739,7 +8744,7 @@ TEST_F(LightControllerTest, RGBLight) { mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen)); mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue)); - InputController& controller = addControllerAndConfigure<InputController>(); + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); InputDeviceInfo info; controller.populateDeviceInfo(&info); const auto& ids = info.getLightIds(); @@ -8761,7 +8766,7 @@ TEST_F(LightControllerTest, MultiColorRGBLight) { mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor)); - InputController& controller = addControllerAndConfigure<InputController>(); + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); InputDeviceInfo info; controller.populateDeviceInfo(&info); const auto& ids = info.getLightIds(); @@ -8798,7 +8803,7 @@ TEST_F(LightControllerTest, PlayerIdLight) { mFakeEventHub->addRawLightInfo(info3.id, std::move(info3)); mFakeEventHub->addRawLightInfo(info4.id, std::move(info4)); - InputController& controller = addControllerAndConfigure<InputController>(); + PeripheralController& controller = addControllerAndConfigure<PeripheralController>(); InputDeviceInfo info; controller.populateDeviceInfo(&info); const auto& ids = info.getLightIds(); diff --git a/services/memtrackproxy/MemtrackProxy.cpp b/services/memtrackproxy/MemtrackProxy.cpp index 8da6e894eb..467616724a 100644 --- a/services/memtrackproxy/MemtrackProxy.cpp +++ b/services/memtrackproxy/MemtrackProxy.cpp @@ -122,11 +122,9 @@ ndk::ScopedAStatus MemtrackProxy::getMemory(int pid, MemtrackType type, _aidl_return->clear(); - if (memtrack_aidl_instance_ || - (memtrack_aidl_instance_ = MemtrackProxy::MemtrackAidlInstance())) { + if (memtrack_aidl_instance_) { return memtrack_aidl_instance_->getMemory(pid, type, _aidl_return); - } else if (memtrack_hidl_instance_ || - (memtrack_hidl_instance_ = MemtrackProxy::MemtrackHidlInstance())) { + } else if (memtrack_hidl_instance_) { ndk::ScopedAStatus aidl_status; Return<void> ret = memtrack_hidl_instance_->getMemory( diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp index 1d3e5b53fa..d828aa97a0 100644 --- a/services/powermanager/Android.bp +++ b/services/powermanager/Android.bp @@ -38,7 +38,7 @@ cc_library_shared { "libutils", "android.hardware.power@1.0", "android.hardware.power@1.1", - "android.hardware.power-V1-cpp", + "android.hardware.power-V2-cpp", ], cflags: [ diff --git a/services/powermanager/PowerHalController.cpp b/services/powermanager/PowerHalController.cpp index 178f545b2e..8c225d5d02 100644 --- a/services/powermanager/PowerHalController.cpp +++ b/services/powermanager/PowerHalController.cpp @@ -18,6 +18,7 @@ #include <android/hardware/power/1.1/IPower.h> #include <android/hardware/power/Boost.h> #include <android/hardware/power/IPower.h> +#include <android/hardware/power/IPowerHintSession.h> #include <android/hardware/power/Mode.h> #include <powermanager/PowerHalController.h> #include <powermanager/PowerHalLoader.h> @@ -73,9 +74,10 @@ std::shared_ptr<HalWrapper> PowerHalController::initHal() { // Check if a call to Power HAL function failed; if so, log the failure and // invalidate the current Power HAL handle. -HalResult PowerHalController::processHalResult(HalResult result, const char* fnName) { - if (result == HalResult::FAILED) { - ALOGE("%s() failed: power HAL service not available.", fnName); +template <typename T> +HalResult<T> PowerHalController::processHalResult(HalResult<T> result, const char* fnName) { + if (result.isFailed()) { + ALOGE("%s failed: %s", fnName, result.errorMessage()); std::lock_guard<std::mutex> lock(mConnectedHalMutex); // Drop Power HAL handle. This will force future api calls to reconnect. mConnectedHal = nullptr; @@ -84,18 +86,31 @@ HalResult PowerHalController::processHalResult(HalResult result, const char* fnN return result; } -HalResult PowerHalController::setBoost(Boost boost, int32_t durationMs) { +HalResult<void> PowerHalController::setBoost(Boost boost, int32_t durationMs) { std::shared_ptr<HalWrapper> handle = initHal(); auto result = handle->setBoost(boost, durationMs); return processHalResult(result, "setBoost"); } -HalResult PowerHalController::setMode(Mode mode, bool enabled) { +HalResult<void> PowerHalController::setMode(Mode mode, bool enabled) { std::shared_ptr<HalWrapper> handle = initHal(); auto result = handle->setMode(mode, enabled); return processHalResult(result, "setMode"); } +HalResult<sp<IPowerHintSession>> PowerHalController::createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) { + std::shared_ptr<HalWrapper> handle = initHal(); + auto result = handle->createHintSession(tgid, uid, threadIds, durationNanos); + return processHalResult(result, "createHintSession"); +} + +HalResult<int64_t> PowerHalController::getHintSessionPreferredRate() { + std::shared_ptr<HalWrapper> handle = initHal(); + auto result = handle->getHintSessionPreferredRate(); + return processHalResult(result, "getHintSessionPreferredRate"); +} + } // namespace power } // namespace android diff --git a/services/powermanager/PowerHalWrapper.cpp b/services/powermanager/PowerHalWrapper.cpp index 2f32827367..d74bd23a8d 100644 --- a/services/powermanager/PowerHalWrapper.cpp +++ b/services/powermanager/PowerHalWrapper.cpp @@ -16,11 +16,17 @@ #define LOG_TAG "HalWrapper" #include <android/hardware/power/Boost.h> +#include <android/hardware/power/IPowerHintSession.h> #include <android/hardware/power/Mode.h> #include <powermanager/PowerHalWrapper.h> #include <utils/Log.h> +#include <cinttypes> + using namespace android::hardware::power; +namespace V1_0 = android::hardware::power::V1_0; +namespace V1_1 = android::hardware::power::V1_1; +namespace Aidl = android::hardware::power; namespace android { @@ -28,49 +34,88 @@ namespace power { // ------------------------------------------------------------------------------------------------- -inline HalResult toHalResult(const binder::Status& result) { +inline HalResult<void> toHalResult(const binder::Status& result) { if (result.isOk()) { - return HalResult::SUCCESSFUL; + return HalResult<void>::ok(); } ALOGE("Power HAL request failed: %s", result.toString8().c_str()); - return HalResult::FAILED; + return HalResult<void>::fromStatus(result); } template <typename T> -inline HalResult toHalResult(const hardware::Return<T>& result) { - if (result.isOk()) { - return HalResult::SUCCESSFUL; +template <typename R> +HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, T data) { + return ret.isOk() ? HalResult<T>::ok(data) : HalResult<T>::failed(ret.description()); +} + +template <typename T> +template <typename R> +HalResult<T> HalResult<T>::fromReturn(hardware::Return<R>& ret, V1_0::Status status, T data) { + return ret.isOk() ? HalResult<T>::fromStatus(status, data) + : HalResult<T>::failed(ret.description()); +} + +// ------------------------------------------------------------------------------------------------- + +HalResult<void> HalResult<void>::fromStatus(status_t status) { + if (status == android::OK) { + return HalResult<void>::ok(); + } + return HalResult<void>::failed(statusToString(status)); +} + +HalResult<void> HalResult<void>::fromStatus(binder::Status status) { + if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) { + return HalResult<void>::unsupported(); + } + if (status.isOk()) { + return HalResult<void>::ok(); } - ALOGE("Power HAL request failed: %s", result.description().c_str()); - return HalResult::FAILED; + return HalResult<void>::failed(std::string(status.toString8().c_str())); } +template <typename R> +HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) { + return ret.isOk() ? HalResult<void>::ok() : HalResult<void>::failed(ret.description()); +} // ------------------------------------------------------------------------------------------------- -HalResult EmptyHalWrapper::setBoost(Boost boost, int32_t durationMs) { +HalResult<void> EmptyHalWrapper::setBoost(Boost boost, int32_t durationMs) { ALOGV("Skipped setBoost %s with duration %dms because Power HAL not available", toString(boost).c_str(), durationMs); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } -HalResult EmptyHalWrapper::setMode(Mode mode, bool enabled) { +HalResult<void> EmptyHalWrapper::setMode(Mode mode, bool enabled) { ALOGV("Skipped setMode %s to %s because Power HAL not available", toString(mode).c_str(), enabled ? "true" : "false"); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); +} + +HalResult<sp<Aidl::IPowerHintSession>> EmptyHalWrapper::createHintSession( + int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) { + ALOGV("Skipped createHintSession(task num=%zu) because Power HAL not available", + threadIds.size()); + return HalResult<sp<Aidl::IPowerHintSession>>::unsupported(); +} + +HalResult<int64_t> EmptyHalWrapper::getHintSessionPreferredRate() { + ALOGV("Skipped getHintSessionPreferredRate because Power HAL not available"); + return HalResult<int64_t>::unsupported(); } // ------------------------------------------------------------------------------------------------- -HalResult HidlHalWrapperV1_0::setBoost(Boost boost, int32_t durationMs) { +HalResult<void> HidlHalWrapperV1_0::setBoost(Boost boost, int32_t durationMs) { if (boost == Boost::INTERACTION) { return sendPowerHint(V1_0::PowerHint::INTERACTION, durationMs); } else { ALOGV("Skipped setBoost %s because Power HAL AIDL not available", toString(boost).c_str()); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } } -HalResult HidlHalWrapperV1_0::setMode(Mode mode, bool enabled) { +HalResult<void> HidlHalWrapperV1_0::setMode(Mode mode, bool enabled) { uint32_t data = enabled ? 1 : 0; switch (mode) { case Mode::LAUNCH: @@ -88,38 +133,54 @@ HalResult HidlHalWrapperV1_0::setMode(Mode mode, bool enabled) { default: ALOGV("Skipped setMode %s because Power HAL AIDL not available", toString(mode).c_str()); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } } -HalResult HidlHalWrapperV1_0::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) { - return toHalResult(mHandleV1_0->powerHint(hintId, data)); +HalResult<void> HidlHalWrapperV1_0::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) { + auto ret = mHandleV1_0->powerHint(hintId, data); + return HalResult<void>::fromReturn(ret); +} + +HalResult<void> HidlHalWrapperV1_0::setInteractive(bool enabled) { + auto ret = mHandleV1_0->setInteractive(enabled); + return HalResult<void>::fromReturn(ret); } -HalResult HidlHalWrapperV1_0::setInteractive(bool enabled) { - return toHalResult(mHandleV1_0->setInteractive(enabled)); +HalResult<void> HidlHalWrapperV1_0::setFeature(V1_0::Feature feature, bool enabled) { + auto ret = mHandleV1_0->setFeature(feature, enabled); + return HalResult<void>::fromReturn(ret); } -HalResult HidlHalWrapperV1_0::setFeature(V1_0::Feature feature, bool enabled) { - return toHalResult(mHandleV1_0->setFeature(feature, enabled)); +HalResult<sp<Aidl::IPowerHintSession>> HidlHalWrapperV1_0::createHintSession( + int32_t, int32_t, const std::vector<int32_t>& threadIds, int64_t) { + ALOGV("Skipped createHintSession(task num=%zu) because Power HAL not available", + threadIds.size()); + return HalResult<sp<Aidl::IPowerHintSession>>::unsupported(); +} + +HalResult<int64_t> HidlHalWrapperV1_0::getHintSessionPreferredRate() { + ALOGV("Skipped getHintSessionPreferredRate because Power HAL not available"); + return HalResult<int64_t>::unsupported(); } // ------------------------------------------------------------------------------------------------- -HalResult HidlHalWrapperV1_1::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) { - return toHalResult(mHandleV1_1->powerHintAsync(hintId, data)); +HalResult<void> HidlHalWrapperV1_1::sendPowerHint(V1_0::PowerHint hintId, uint32_t data) { + auto ret = mHandleV1_1->powerHintAsync(hintId, data); + return HalResult<void>::fromReturn(ret); } // ------------------------------------------------------------------------------------------------- -HalResult AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) { +HalResult<void> AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) { std::unique_lock<std::mutex> lock(mBoostMutex); size_t idx = static_cast<size_t>(boost); // Quick return if boost is not supported by HAL if (idx >= mBoostSupportedArray.size() || mBoostSupportedArray[idx] == HalSupport::OFF) { ALOGV("Skipped setBoost %s because Power HAL doesn't support it", toString(boost).c_str()); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } if (mBoostSupportedArray[idx] == HalSupport::UNKNOWN) { @@ -128,14 +189,15 @@ HalResult AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) { if (!isSupportedRet.isOk()) { ALOGE("Skipped setBoost %s because check support failed with: %s", toString(boost).c_str(), isSupportedRet.toString8().c_str()); - return HalResult::FAILED; + // return HalResult::FAILED; + return HalResult<void>::fromStatus(isSupportedRet); } mBoostSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF; if (!isSupported) { ALOGV("Skipped setBoost %s because Power HAL doesn't support it", toString(boost).c_str()); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } } lock.unlock(); @@ -143,30 +205,28 @@ HalResult AidlHalWrapper::setBoost(Boost boost, int32_t durationMs) { return toHalResult(mHandle->setBoost(boost, durationMs)); } -HalResult AidlHalWrapper::setMode(Mode mode, bool enabled) { +HalResult<void> AidlHalWrapper::setMode(Mode mode, bool enabled) { std::unique_lock<std::mutex> lock(mModeMutex); size_t idx = static_cast<size_t>(mode); // Quick return if mode is not supported by HAL if (idx >= mModeSupportedArray.size() || mModeSupportedArray[idx] == HalSupport::OFF) { ALOGV("Skipped setMode %s because Power HAL doesn't support it", toString(mode).c_str()); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } if (mModeSupportedArray[idx] == HalSupport::UNKNOWN) { bool isSupported = false; auto isSupportedRet = mHandle->isModeSupported(mode, &isSupported); if (!isSupportedRet.isOk()) { - ALOGE("Skipped setMode %s because check support failed with: %s", - toString(mode).c_str(), isSupportedRet.toString8().c_str()); - return HalResult::FAILED; + return HalResult<void>::failed(isSupportedRet.toString8().c_str()); } mModeSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF; if (!isSupported) { ALOGV("Skipped setMode %s because Power HAL doesn't support it", toString(mode).c_str()); - return HalResult::UNSUPPORTED; + return HalResult<void>::unsupported(); } } lock.unlock(); @@ -174,6 +234,20 @@ HalResult AidlHalWrapper::setMode(Mode mode, bool enabled) { return toHalResult(mHandle->setMode(mode, enabled)); } +HalResult<sp<Aidl::IPowerHintSession>> AidlHalWrapper::createHintSession( + int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, int64_t durationNanos) { + sp<IPowerHintSession> appSession; + return HalResult<sp<Aidl::IPowerHintSession>>:: + fromStatus(mHandle->createHintSession(tgid, uid, threadIds, durationNanos, &appSession), + appSession); +} + +HalResult<int64_t> AidlHalWrapper::getHintSessionPreferredRate() { + int64_t rate = -1; + auto result = mHandle->getHintSessionPreferredRate(&rate); + return HalResult<int64_t>::fromStatus(result, rate); +} + // ------------------------------------------------------------------------------------------------- } // namespace power diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp index a489253207..3997929053 100644 --- a/services/powermanager/benchmarks/Android.bp +++ b/services/powermanager/benchmarks/Android.bp @@ -38,7 +38,7 @@ cc_benchmark { "libutils", "android.hardware.power@1.0", "android.hardware.power@1.1", - "android.hardware.power-V1-cpp", + "android.hardware.power-V2-cpp", ], static_libs: [ "libtestUtil", diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp index 10048286b9..1100cad361 100644 --- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp +++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp @@ -18,7 +18,9 @@ #include <android/hardware/power/Boost.h> #include <android/hardware/power/IPower.h> +#include <android/hardware/power/IPowerHintSession.h> #include <android/hardware/power/Mode.h> +#include <android/hardware/power/WorkDuration.h> #include <benchmark/benchmark.h> #include <binder/IServiceManager.h> #include <testUtil.h> @@ -26,7 +28,9 @@ using android::hardware::power::Boost; using android::hardware::power::IPower; +using android::hardware::power::IPowerHintSession; using android::hardware::power::Mode; +using android::hardware::power::WorkDuration; using std::chrono::microseconds; using namespace android; @@ -38,6 +42,21 @@ static constexpr int64_t LAST_BOOST = static_cast<int64_t>(Boost::CAMERA_SHOT); static constexpr int64_t FIRST_MODE = static_cast<int64_t>(Mode::DOUBLE_TAP_TO_WAKE); static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING_HIGH); +class DurationWrapper : public WorkDuration { +public: + DurationWrapper(int64_t dur, int64_t time) { + durationNanos = dur; + timeStampNanos = time; + } +}; + +static const std::vector<WorkDuration> DURATIONS = { + DurationWrapper(1L, 1L), + DurationWrapper(1000L, 2L), + DurationWrapper(1000000L, 3L), + DurationWrapper(1000000000L, 4L), +}; + // Delay between oneway method calls to avoid overflowing the binder buffers. static constexpr microseconds ONEWAY_API_DELAY = 100us; @@ -68,6 +87,47 @@ static void runBenchmark(benchmark::State& state, microseconds delay, R (IPower: } } +template <class R, class... Args0, class... Args1> +static void runSessionBenchmark(benchmark::State& state, R (IPowerHintSession::*fn)(Args0...), + Args1&&... args1) { + sp<IPower> pwHal = waitForVintfService<IPower>(); + + if (pwHal == nullptr) { + ALOGI("Power HAL not available, skipping test..."); + return; + } + + // do not use tid from the benchmark process, use 1 for init + std::vector<int32_t> threadIds{1}; + int64_t durationNanos = 16666666L; + sp<IPowerHintSession> hal; + + auto status = pwHal->createHintSession(1, 0, threadIds, durationNanos, &hal); + + if (hal == nullptr) { + ALOGI("Power HAL doesn't support session, skipping test..."); + return; + } + + binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...); + if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) { + ALOGI("Power HAL does not support this operation, skipping test..."); + return; + } + + while (state.KeepRunning()) { + ret = (*hal.*fn)(std::forward<Args1>(args1)...); + state.PauseTiming(); + if (!ret.isOk()) state.SkipWithError(ret.toString8().c_str()); + if (ONEWAY_API_DELAY > 0us) { + testDelaySpin(std::chrono::duration_cast<std::chrono::duration<float>>(ONEWAY_API_DELAY) + .count()); + } + state.ResumeTiming(); + } + hal->close(); +} + static void BM_PowerHalAidlBenchmarks_isBoostSupported(benchmark::State& state) { bool isSupported; Boost boost = static_cast<Boost>(state.range(0)); @@ -90,7 +150,53 @@ static void BM_PowerHalAidlBenchmarks_setMode(benchmark::State& state) { runBenchmark(state, ONEWAY_API_DELAY, &IPower::setMode, mode, false); } +static void BM_PowerHalAidlBenchmarks_createHintSession(benchmark::State& state) { + std::vector<int32_t> threadIds{static_cast<int32_t>(state.range(0))}; + int64_t durationNanos = 16666666L; + int32_t tgid = 999; + int32_t uid = 1001; + sp<IPowerHintSession> appSession; + sp<IPower> hal = waitForVintfService<IPower>(); + + if (hal == nullptr) { + ALOGI("Power HAL not available, skipping test..."); + return; + } + + binder::Status ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession); + if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) { + ALOGI("Power HAL does not support this operation, skipping test..."); + return; + } + + while (state.KeepRunning()) { + ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession); + state.PauseTiming(); + if (!ret.isOk()) state.SkipWithError(ret.toString8().c_str()); + appSession->close(); + state.ResumeTiming(); + } +} + +static void BM_PowerHalAidlBenchmarks_getHintSessionPreferredRate(benchmark::State& state) { + int64_t rate; + runBenchmark(state, 0us, &IPower::getHintSessionPreferredRate, &rate); +} + +static void BM_PowerHalAidlBenchmarks_updateTargetWorkDuration(benchmark::State& state) { + int64_t duration = 1000; + runSessionBenchmark(state, &IPowerHintSession::updateTargetWorkDuration, duration); +} + +static void BM_PowerHalAidlBenchmarks_reportActualWorkDuration(benchmark::State& state) { + runSessionBenchmark(state, &IPowerHintSession::reportActualWorkDuration, DURATIONS); +} + BENCHMARK(BM_PowerHalAidlBenchmarks_isBoostSupported)->DenseRange(FIRST_BOOST, LAST_BOOST, 1); BENCHMARK(BM_PowerHalAidlBenchmarks_isModeSupported)->DenseRange(FIRST_MODE, LAST_MODE, 1); BENCHMARK(BM_PowerHalAidlBenchmarks_setBoost)->DenseRange(FIRST_BOOST, LAST_BOOST, 1); BENCHMARK(BM_PowerHalAidlBenchmarks_setMode)->DenseRange(FIRST_MODE, LAST_MODE, 1); +BENCHMARK(BM_PowerHalAidlBenchmarks_createHintSession)->Arg(1); +BENCHMARK(BM_PowerHalAidlBenchmarks_getHintSessionPreferredRate); +BENCHMARK(BM_PowerHalAidlBenchmarks_updateTargetWorkDuration); +BENCHMARK(BM_PowerHalAidlBenchmarks_reportActualWorkDuration); diff --git a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp index 598080b5bc..f8abc7aba6 100644 --- a/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp +++ b/services/powermanager/benchmarks/PowerHalControllerBenchmarks.cpp @@ -40,29 +40,29 @@ static constexpr int64_t LAST_MODE = static_cast<int64_t>(Mode::CAMERA_STREAMING // Delay between oneway method calls to avoid overflowing the binder buffers. static constexpr std::chrono::microseconds ONEWAY_API_DELAY = 100us; -template <class... Args0, class... Args1> -static void runBenchmark(benchmark::State& state, HalResult (PowerHalController::*fn)(Args0...), +template <typename T, class... Args0, class... Args1> +static void runBenchmark(benchmark::State& state, HalResult<T> (PowerHalController::*fn)(Args0...), Args1&&... args1) { while (state.KeepRunning()) { PowerHalController controller; - HalResult ret = (controller.*fn)(std::forward<Args1>(args1)...); + HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...); state.PauseTiming(); - if (ret == HalResult::FAILED) state.SkipWithError("Power HAL request failed"); + if (ret.isFailed()) state.SkipWithError("Power HAL request failed"); state.ResumeTiming(); } } -template <class... Args0, class... Args1> +template <typename T, class... Args0, class... Args1> static void runCachedBenchmark(benchmark::State& state, - HalResult (PowerHalController::*fn)(Args0...), Args1&&... args1) { + HalResult<T> (PowerHalController::*fn)(Args0...), Args1&&... args1) { PowerHalController controller; // First call out of test, to cache HAL service and isSupported result. (controller.*fn)(std::forward<Args1>(args1)...); while (state.KeepRunning()) { - HalResult ret = (controller.*fn)(std::forward<Args1>(args1)...); + HalResult<T> ret = (controller.*fn)(std::forward<Args1>(args1)...); state.PauseTiming(); - if (ret == HalResult::FAILED) { + if (ret.isFailed()) { state.SkipWithError("Power HAL request failed"); } testDelaySpin( diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp index 69e4041aaa..659b2d273a 100644 --- a/services/powermanager/tests/Android.bp +++ b/services/powermanager/tests/Android.bp @@ -46,7 +46,7 @@ cc_test { "libutils", "android.hardware.power@1.0", "android.hardware.power@1.1", - "android.hardware.power-V1-cpp", + "android.hardware.power-V2-cpp", ], static_libs: [ "libgmock", diff --git a/services/powermanager/tests/PowerHalControllerTest.cpp b/services/powermanager/tests/PowerHalControllerTest.cpp index 141b2440b8..6cc7a6f3da 100644 --- a/services/powermanager/tests/PowerHalControllerTest.cpp +++ b/services/powermanager/tests/PowerHalControllerTest.cpp @@ -134,9 +134,9 @@ TEST_F(PowerHalControllerTest, TestUnableToConnectToPowerHalIgnoresAllApiCalls) // Still works with EmptyPowerHalWrapper as fallback ignoring every api call // and logging. auto result = halController.setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); result = halController.setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); // PowerHalConnector was called every time to attempt to reconnect with // underlying service. @@ -159,9 +159,9 @@ TEST_F(PowerHalControllerTest, TestAllApiCallsDelegatedToConnectedPowerHal) { } auto result = mHalController->setBoost(Boost::INTERACTION, 100); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mHalController->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); // PowerHalConnector was called only once and never reset. powerHalConnectCount = mHalConnector->getConnectCount(); @@ -182,13 +182,13 @@ TEST_F(PowerHalControllerTest, TestPowerHalRecoversFromFailureByRecreatingPowerH EXPECT_CALL(*mMockHal.get(), powerHint(_, _)).Times(Exactly(4)); auto result = mHalController->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mHalController->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); result = mHalController->setMode(Mode::VR, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mHalController->setMode(Mode::LOW_POWER, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); // PowerHalConnector was called only twice: on first api call and after failed // call. @@ -204,9 +204,9 @@ TEST_F(PowerHalControllerTest, TestPowerHalDoesNotTryToRecoverFromFailureOnUnsup EXPECT_EQ(powerHalConnectCount, 0); auto result = mHalController->setBoost(Boost::CAMERA_LAUNCH, 1000); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); result = mHalController->setMode(Mode::CAMERA_STREAMING_HIGH, true); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); // PowerHalConnector was called only once and never reset. powerHalConnectCount = mHalConnector->getConnectCount(); @@ -225,7 +225,7 @@ TEST_F(PowerHalControllerTest, TestMultiThreadConnectsOnlyOnce) { for (int i = 0; i < 10; i++) { threads.push_back(std::thread([&]() { auto result = mHalController->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); })); } std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); @@ -253,19 +253,19 @@ TEST_F(PowerHalControllerTest, TestMultiThreadWithFailureReconnectIsThreadSafe) for (int i = 0; i < 10; i++) { threads.push_back(std::thread([&]() { auto result = mHalController->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); })); threads.push_back(std::thread([&]() { auto result = mHalController->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); })); threads.push_back(std::thread([&]() { auto result = mHalController->setMode(Mode::LOW_POWER, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); })); threads.push_back(std::thread([&]() { auto result = mHalController->setMode(Mode::VR, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); })); } std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); diff --git a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp index a7656598f0..d890f5c332 100644 --- a/services/powermanager/tests/PowerHalWrapperAidlTest.cpp +++ b/services/powermanager/tests/PowerHalWrapperAidlTest.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "PowerHalWrapperAidlTest" #include <android/hardware/power/Boost.h> +#include <android/hardware/power/IPowerHintSession.h> #include <android/hardware/power/Mode.h> #include <binder/IServiceManager.h> #include <gmock/gmock.h> @@ -24,11 +25,13 @@ #include <powermanager/PowerHalWrapper.h> #include <utils/Log.h> +#include <unistd.h> #include <thread> using android::binder::Status; using android::hardware::power::Boost; using android::hardware::power::IPower; +using android::hardware::power::IPowerHintSession; using android::hardware::power::Mode; using namespace android; @@ -44,6 +47,11 @@ public: MOCK_METHOD(Status, setBoost, (Boost boost, int32_t durationMs), (override)); MOCK_METHOD(Status, isModeSupported, (Mode mode, bool* ret), (override)); MOCK_METHOD(Status, setMode, (Mode mode, bool enabled), (override)); + MOCK_METHOD(Status, createHintSession, + (int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds, + int64_t durationNanos, sp<IPowerHintSession>* session), + (override)); + MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * rate), (override)); MOCK_METHOD(int32_t, getInterfaceVersion, (), (override)); MOCK_METHOD(std::string, getInterfaceHash, (), (override)); MOCK_METHOD(IBinder*, onAsBinder, (), (override)); @@ -65,7 +73,7 @@ protected: void PowerHalWrapperAidlTest::SetUp() { mMockHal = new StrictMock<MockIPower>(); mWrapper = std::make_unique<AidlHalWrapper>(mMockHal); - ASSERT_NE(mWrapper, nullptr); + ASSERT_NE(nullptr, mWrapper); } // ------------------------------------------------------------------------------------------------- @@ -81,7 +89,7 @@ TEST_F(PowerHalWrapperAidlTest, TestSetBoostSuccessful) { } auto result = mWrapper->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 100); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); } TEST_F(PowerHalWrapperAidlTest, TestSetBoostFailed) { @@ -99,9 +107,9 @@ TEST_F(PowerHalWrapperAidlTest, TestSetBoostFailed) { } auto result = mWrapper->setBoost(Boost::INTERACTION, 100); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); result = mWrapper->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 1000); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); } TEST_F(PowerHalWrapperAidlTest, TestSetBoostUnsupported) { @@ -110,9 +118,9 @@ TEST_F(PowerHalWrapperAidlTest, TestSetBoostUnsupported) { .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status()))); auto result = mWrapper->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); result = mWrapper->setBoost(Boost::CAMERA_SHOT, 10); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); } TEST_F(PowerHalWrapperAidlTest, TestSetBoostMultiThreadCheckSupportedOnlyOnce) { @@ -128,7 +136,7 @@ TEST_F(PowerHalWrapperAidlTest, TestSetBoostMultiThreadCheckSupportedOnlyOnce) { for (int i = 0; i < 10; i++) { threads.push_back(std::thread([&]() { auto result = mWrapper->setBoost(Boost::INTERACTION, 100); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); })); } std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); @@ -145,7 +153,7 @@ TEST_F(PowerHalWrapperAidlTest, TestSetModeSuccessful) { } auto result = mWrapper->setMode(Mode::DISPLAY_INACTIVE, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); } TEST_F(PowerHalWrapperAidlTest, TestSetModeFailed) { @@ -163,9 +171,9 @@ TEST_F(PowerHalWrapperAidlTest, TestSetModeFailed) { } auto result = mWrapper->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); result = mWrapper->setMode(Mode::DISPLAY_INACTIVE, false); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); } TEST_F(PowerHalWrapperAidlTest, TestSetModeUnsupported) { @@ -174,9 +182,9 @@ TEST_F(PowerHalWrapperAidlTest, TestSetModeUnsupported) { .WillRepeatedly(DoAll(SetArgPointee<1>(false), Return(Status()))); auto result = mWrapper->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); } TEST_F(PowerHalWrapperAidlTest, TestSetModeMultiThreadCheckSupportedOnlyOnce) { @@ -192,8 +200,41 @@ TEST_F(PowerHalWrapperAidlTest, TestSetModeMultiThreadCheckSupportedOnlyOnce) { for (int i = 0; i < 10; i++) { threads.push_back(std::thread([&]() { auto result = mWrapper->setMode(Mode::LAUNCH, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); })); } std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); } + +TEST_F(PowerHalWrapperAidlTest, TestCreateHintSessionSuccessful) { + std::vector<int> threadIds{gettid()}; + int32_t tgid = 999; + int32_t uid = 1001; + int64_t durationNanos = 16666666L; + EXPECT_CALL(*mMockHal.get(), + createHintSession(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos), _)) + .Times(Exactly(1)); + auto result = mWrapper->createHintSession(tgid, uid, threadIds, durationNanos); + ASSERT_TRUE(result.isOk()); +} + +TEST_F(PowerHalWrapperAidlTest, TestCreateHintSessionFailed) { + int32_t tgid = 999; + int32_t uid = 1001; + std::vector<int> threadIds{}; + int64_t durationNanos = 16666666L; + EXPECT_CALL(*mMockHal.get(), + createHintSession(Eq(tgid), Eq(uid), Eq(threadIds), Eq(durationNanos), _)) + .Times(Exactly(1)) + .WillRepeatedly(Return(Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT))); + auto result = mWrapper->createHintSession(tgid, uid, threadIds, durationNanos); + ASSERT_TRUE(result.isFailed()); +} + +TEST_F(PowerHalWrapperAidlTest, TestGetHintSessionPreferredRate) { + EXPECT_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).Times(Exactly(1)); + auto result = mWrapper->getHintSessionPreferredRate(); + ASSERT_TRUE(result.isOk()); + int64_t rate = result.value(); + ASSERT_GE(0, rate); +} diff --git a/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp b/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp index 6693d0b070..b54762cf6d 100644 --- a/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp +++ b/services/powermanager/tests/PowerHalWrapperHidlV1_0Test.cpp @@ -72,7 +72,7 @@ TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostSuccessful) { EXPECT_CALL(*mMockHal.get(), powerHint(Eq(PowerHint::INTERACTION), Eq(1000))).Times(Exactly(1)); auto result = mWrapper->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); } TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostFailed) { @@ -83,12 +83,12 @@ TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostFailed) { }); auto result = mWrapper->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); } TEST_F(PowerHalWrapperHidlV1_0Test, TestSetBoostUnsupported) { auto result = mWrapper->setBoost(Boost::CAMERA_LAUNCH, 10); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); } TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeSuccessful) { @@ -106,17 +106,17 @@ TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeSuccessful) { } auto result = mWrapper->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::LOW_POWER, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::SUSTAINED_PERFORMANCE, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::VR, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::INTERACTIVE, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::DOUBLE_TAP_TO_WAKE, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); } TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeFailed) { @@ -127,10 +127,10 @@ TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeFailed) { }); auto result = mWrapper->setMode(Mode::LAUNCH, 1); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); } TEST_F(PowerHalWrapperHidlV1_0Test, TestSetModeIgnored) { auto result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); } diff --git a/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp b/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp index 55bbd6df79..d30e8d2c49 100644 --- a/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp +++ b/services/powermanager/tests/PowerHalWrapperHidlV1_1Test.cpp @@ -89,7 +89,7 @@ TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostSuccessful) { .Times(Exactly(1)); auto result = mWrapper->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); } TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostFailed) { @@ -100,12 +100,12 @@ TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostFailed) { }); auto result = mWrapper->setBoost(Boost::INTERACTION, 1000); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); } TEST_F(PowerHalWrapperHidlV1_1Test, TestSetBoostUnsupported) { auto result = mWrapper->setBoost(Boost::CAMERA_LAUNCH, 10); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); } TEST_F(PowerHalWrapperHidlV1_1Test, TestSetMode) { @@ -127,17 +127,17 @@ TEST_F(PowerHalWrapperHidlV1_1Test, TestSetMode) { } auto result = mWrapper->setMode(Mode::LAUNCH, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::LOW_POWER, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::SUSTAINED_PERFORMANCE, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::VR, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::INTERACTIVE, true); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); result = mWrapper->setMode(Mode::DOUBLE_TAP_TO_WAKE, false); - ASSERT_EQ(HalResult::SUCCESSFUL, result); + ASSERT_TRUE(result.isOk()); } TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeFailed) { @@ -148,10 +148,10 @@ TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeFailed) { }); auto result = mWrapper->setMode(Mode::LAUNCH, 1); - ASSERT_EQ(HalResult::FAILED, result); + ASSERT_TRUE(result.isFailed()); } TEST_F(PowerHalWrapperHidlV1_1Test, TestSetModeIgnored) { auto result = mWrapper->setMode(Mode::CAMERA_STREAMING_HIGH, true); - ASSERT_EQ(HalResult::UNSUPPORTED, result); + ASSERT_TRUE(result.isUnsupported()); } diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index b976eb535b..98853523f3 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -60,7 +60,6 @@ cc_defaults { "libnativewindow", "libprocessgroup", "libprotobuf-cpp-lite", - "libstatslog", "libsync", "libtimestats", "libui", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index be9bce0795..12f63dbbf1 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -507,11 +507,6 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, BufferInfo oldBufferInfo = mBufferInfo; - if (!allTransactionsSignaled(expectedPresentTime)) { - mFlinger->setTransactionFlags(eTraversalNeeded); - return false; - } - status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime); if (err != NO_ERROR) { return false; @@ -556,53 +551,9 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - // Remove any sync points corresponding to the buffer which was just - // latched - { - Mutex::Autolock lock(mLocalSyncPointMutex); - auto point = mLocalSyncPoints.begin(); - while (point != mLocalSyncPoints.end()) { - if (!(*point)->frameIsAvailable() || !(*point)->transactionIsApplied()) { - // This sync point must have been added since we started - // latching. Don't drop it yet. - ++point; - continue; - } - - if ((*point)->getFrameNumber() <= mCurrentFrameNumber) { - std::stringstream ss; - ss << "Dropping sync point " << (*point)->getFrameNumber(); - ATRACE_NAME(ss.str().c_str()); - point = mLocalSyncPoints.erase(point); - } else { - ++point; - } - } - } - return true; } -// transaction -void BufferLayer::notifyAvailableFrames(nsecs_t expectedPresentTime) { - const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime); - const bool headFenceSignaled = fenceHasSignaled(); - const bool presentTimeIsCurrent = framePresentTimeIsCurrent(expectedPresentTime); - Mutex::Autolock lock(mLocalSyncPointMutex); - for (auto& point : mLocalSyncPoints) { - if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled && - presentTimeIsCurrent) { - point->setFrameAvailable(); - sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer(); - if (requestedSyncLayer) { - // Need to update the transaction flag to ensure the layer's pending transaction - // gets applied. - requestedSyncLayer->setTransactionFlags(eTransactionNeeded); - } - } - } -} - bool BufferLayer::hasReadyFrame() const { return hasFrameUpdate() || getSidebandStreamChanged() || getAutoRefresh(); } @@ -616,33 +567,6 @@ bool BufferLayer::isProtected() const { return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } -// h/w composer set-up -bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) { - const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime); - bool matchingFramesFound = false; - bool allTransactionsApplied = true; - Mutex::Autolock lock(mLocalSyncPointMutex); - - for (auto& point : mLocalSyncPoints) { - if (point->getFrameNumber() > headFrameNumber) { - break; - } - matchingFramesFound = true; - - if (!point->frameIsAvailable()) { - // We haven't notified the remote layer that the frame for - // this point is available yet. Notify it now, and then - // abort this attempt to latch. - point->setFrameAvailable(); - allTransactionsApplied = false; - break; - } - - allTransactionsApplied = allTransactionsApplied && point->transactionIsApplied(); - } - return !matchingFramesFound || allTransactionsApplied; -} - // As documented in libhardware header, formats in the range // 0x100 - 0x1FF are specific to the HAL implementation, and // are known to have no alpha channel diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b8d3f12322..0a5235aa08 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -90,8 +90,6 @@ public: bool isBufferLatched() const override { return mRefreshPending; } - void notifyAvailableFrames(nsecs_t expectedPresentTime) override; - bool hasReadyFrame() const override; // Returns the current scaling mode @@ -153,11 +151,6 @@ protected: bool onPreComposition(nsecs_t) override; void preparePerFrameCompositionState() override; - // Check all of the local sync points to ensure that all transactions - // which need to have been applied prior to the frame which is about to - // be latched have signaled - bool allTransactionsSignaled(nsecs_t expectedPresentTime); - static bool getOpacityForFormat(uint32_t format); // from graphics API diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 48a0be2c45..fa9cecf787 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -259,28 +259,8 @@ bool BufferStateLayer::willPresentCurrentTransaction() const { (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))); } -/* TODO: vhau uncomment once deferred transaction migration complete in - * WindowManager -void BufferStateLayer::pushPendingState() { - if (!mCurrentState.modified) { - return; - } - mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); -} -*/ - -bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { - mCurrentStateModified = mCurrentState.modified; - bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit); - mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified; - mCurrentState.modified = false; - return stateUpdateAvailable; -} - -// Crop that applies to the window -Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { - return Rect::INVALID_RECT; +Rect BufferStateLayer::getCrop(const Layer::State& s) const { + return s.crop; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -301,57 +281,53 @@ bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInver } bool BufferStateLayer::setCrop(const Rect& crop) { - Rect c = crop; - if (c.left < 0) { - c.left = 0; - } - if (c.top < 0) { - c.top = 0; - } - // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below - // treats all invalid rectangles the same. - if (!c.isValid()) { - c.makeInvalid(); - } + if (mCurrentState.crop == crop) return false; + mCurrentState.sequence++; + mCurrentState.crop = crop; - if (mCurrentState.crop == c) return false; - mCurrentState.crop = c; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setFrame(const Rect& frame) { - int x = frame.left; - int y = frame.top; - int w = frame.getWidth(); - int h = frame.getHeight(); - - if (x < 0) { - x = 0; - w = frame.right; +bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + if (mCurrentState.transform.dsdx() == matrix.dsdx && + mCurrentState.transform.dtdy() == matrix.dtdy && + mCurrentState.transform.dtdx() == matrix.dtdx && + mCurrentState.transform.dsdy() == matrix.dsdy) { + return false; } - if (y < 0) { - y = 0; - h = frame.bottom; - } + ui::Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y && - mCurrentState.width == w && mCurrentState.height == h) { + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " + "ROTATE_SURFACE_FLINGER ignored"); return false; } - if (!frame.isValid()) { - x = y = w = h = 0; + mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + + return true; +} + +bool BufferStateLayer::setPosition(float x, float y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) { + return false; } + mCurrentState.transform.set(x, y); - mCurrentState.width = w; - mCurrentState.height = h; mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + return true; } @@ -428,6 +404,10 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE); } + + mCurrentState.width = mCurrentState.buffer->width; + mCurrentState.height = mCurrentState.buffer->height; + return true; } @@ -858,33 +838,6 @@ sp<Layer> BufferStateLayer::createClone() { return layer; } -Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { - const auto& p = mDrawingParent.promote(); - if (p != nullptr) { - RoundedCornerState parentState = p->getRoundedCornerState(); - if (parentState.radius > 0) { - ui::Transform t = getActiveTransform(getDrawingState()); - t = t.inverse(); - parentState.cropRect = t.transform(parentState.cropRect); - // The rounded corners shader only accepts 1 corner radius for performance reasons, - // but a transform matrix can define horizontal and vertical scales. - // Let's take the average between both of them and pass into the shader, practically we - // never do this type of transformation on windows anyway. - parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; - return parentState; - } - } - const float radius = getDrawingState().cornerRadius; - const State& s(getDrawingState()); - if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) - return RoundedCornerState(); - return RoundedCornerState(FloatRect(static_cast<float>(s.transform.tx()), - static_cast<float>(s.transform.ty()), - static_cast<float>(s.transform.tx() + s.width), - static_cast<float>(s.transform.ty() + s.height)), - radius); -} - bool BufferStateLayer::bufferNeedsFiltering() const { const State& s(getDrawingState()); if (!s.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 3878f50776..24e0ad290f 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -50,10 +50,6 @@ public: uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { return flags; } - /*TODO:vhau return to using BufferStateLayer override once WM - * has removed deferred transactions! - void pushPendingState() override;*/ - bool applyPendingStates(Layer::State* stateToCommit) override; uint32_t getActiveWidth(const Layer::State& s) const override { return s.width; } uint32_t getActiveHeight(const Layer::State& s) const override { return s.height; } @@ -66,7 +62,6 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setFrame(const Rect& frame) override; bool setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, @@ -81,23 +76,16 @@ public: bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override; bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; + bool setPosition(float /*x*/, float /*y*/) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/); // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } - bool setPosition(float /*x*/, float /*y*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; - bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, - bool /*allowNonRectPreservingTransforms*/) override { - return false; - } - void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/, - uint64_t /*frameNumber*/) override {} - void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/, - uint64_t /*frameNumber*/) override {} Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; - Layer::RoundedCornerState getRoundedCornerState() const override; void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- @@ -169,7 +157,6 @@ private: uint64_t mPreviousBufferId = 0; uint64_t mPreviousReleasedFrameNumber = 0; - mutable bool mCurrentStateModified = false; bool mReleasePreviousBuffer = false; // Stores the last set acquire fence signal time used to populate the callback handle's acquire diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 4c065ec112..48a54d6c66 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -115,6 +115,9 @@ struct OutputLayerCompositionState { // The buffer cache for this layer. This is used to lower the // cost of sending reused buffers to the HWC. HwcBufferCache hwcBufferCache; + + // Set to true when overridden info has been sent to HW composer + bool stateOverridden = false; }; // The HWC state is optional, and is only set up if there is any potential diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index afa02cd0c2..c5d03a7218 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -108,7 +108,7 @@ public: private: CachedSet() = default; - NonBufferHash mFingerprint = 0; + const NonBufferHash mFingerprint; std::chrono::steady_clock::time_point mLastUpdate = std::chrono::steady_clock::now(); std::vector<Layer> mLayers; Rect mBounds = Rect::EMPTY_RECT; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index 313a180f4f..2f2ad4c9b5 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -54,7 +54,7 @@ private: void resetActivities(NonBufferHash, std::chrono::steady_clock::time_point now); - void updateLayersHash(); + NonBufferHash computeLayersHash() const; bool mergeWithCachedSets(const std::vector<const LayerState*>& layers, std::chrono::steady_clock::time_point now); @@ -69,7 +69,6 @@ private: std::chrono::steady_clock::time_point mLastGeometryUpdate; std::vector<CachedSet> mLayers; - NonBufferHash mLayersHash = 0; std::optional<CachedSet> mNewCachedSet; // Statistics diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index aed3be93c3..3ac5433457 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -722,10 +722,7 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr previousOverride = layer->getState().overrideInfo.buffer; } - // TODO(b/181172795): We now update geometry for all flattened layers. We should update it - // only when the geometry actually changes - const bool includeGeometry = refreshArgs.updatingGeometryThisFrame || - layer->getState().overrideInfo.buffer != nullptr || skipLayer; + const bool includeGeometry = refreshArgs.updatingGeometryThisFrame; layer->writeStateToHWC(includeGeometry, skipLayer); } } @@ -1104,6 +1101,7 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( Region stubRegion; bool disableBlurs = false; + sp<GraphicBuffer> previousOverrideBuffer = nullptr; for (auto* layer : getOutputLayersOrderedByZ()) { const auto& layerState = layer->getState(); @@ -1153,8 +1151,14 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( std::vector<LayerFE::LayerSettings> results; if (layer->getState().overrideInfo.buffer != nullptr) { - results = layer->getOverrideCompositionList(); - ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName()); + if (layer->getState().overrideInfo.buffer != previousOverrideBuffer) { + results = layer->getOverrideCompositionList(); + previousOverrideBuffer = layer->getState().overrideInfo.buffer; + ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName()); + } else { + ALOGV("Skipping redundant override buffer for [%s] in RE", + layer->getLayerFE().getDebugName()); + } } else { results = layerFE.prepareClientCompositionList(targetSettings); if (realContentIsVisible && !results.empty()) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 3f36a8feea..f640f85bca 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -333,7 +333,11 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer) { auto requestedCompositionType = outputIndependentState->compositionType; - if (includeGeometry) { + // TODO(b/181172795): We now update geometry for all flattened layers. We should update it + // only when the geometry actually changes + const bool isOverridden = state.overrideInfo.buffer != nullptr; + const bool prevOverridden = state.hwc->stateOverridden; + if (isOverridden || prevOverridden || skipLayer || includeGeometry) { writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType); writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), *outputIndependentState, skipLayer); @@ -346,6 +350,8 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer) { // Always set the layer color after setting the composition type. writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState); + + editState().hwc->stateOverridden = isOverridden; } void OutputLayer::writeOutputDependentGeometryStateToHWC( diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index ffca5baab7..9c9649ccbe 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -40,13 +40,17 @@ NonBufferHash Flattener::flattenLayers(const std::vector<const LayerState*>& lay ++mInitialLayerCounts[layers.size()]; - if (mergeWithCachedSets(layers, now)) { - hash = mLayersHash; - } + // Only buildCachedSets if these layers are already stored in mLayers. + // Otherwise (i.e. mergeWithCachedSets returns false), the time has not + // changed, so buildCachedSets will never find any runs. + const bool alreadyHadCachedSets = mergeWithCachedSets(layers, now); ++mFinalLayerCounts[mLayers.size()]; - buildCachedSets(now); + if (alreadyHadCachedSets) { + buildCachedSets(now); + hash = computeLayersHash(); + } return hash; } @@ -157,14 +161,17 @@ void Flattener::resetActivities(NonBufferHash hash, time_point now) { } } -void Flattener::updateLayersHash() { +NonBufferHash Flattener::computeLayersHash() const{ size_t hash = 0; for (const auto& layer : mLayers) { android::hashCombineSingleHashed(hash, layer.getNonBufferHash()); } - mLayersHash = hash; + return hash; } +// Only called if the geometry matches the last frame. Return true if mLayers +// was already populated with these layers, i.e. on the second and following +// calls with the same geometry. bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers, time_point now) { std::vector<CachedSet> merged; @@ -272,7 +279,6 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers } mLayers = std::move(merged); - updateLayersHash(); return true; } diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index 1bf43dacdf..fd7098869d 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -20,11 +20,7 @@ #undef LOG_TAG #define LOG_TAG "HwcComposer" - -#include <log/log.h> - -#include <algorithm> -#include <cinttypes> +#define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "ComposerHal.h" @@ -32,6 +28,11 @@ #include <gui/BufferQueue.h> #include <hidl/HidlTransportSupport.h> #include <hidl/HidlTransportUtils.h> +#include <log/log.h> +#include <utils/Trace.h> + +#include <algorithm> +#include <cinttypes> namespace android { @@ -492,6 +493,7 @@ Error Composer::getReleaseFences(Display display, Error Composer::presentDisplay(Display display, int* outPresentFence) { + ATRACE_NAME("HwcPresentDisplay"); mWriter.selectDisplay(display); mWriter.presentDisplay(); @@ -586,6 +588,7 @@ Error Composer::setClientTargetSlotCount(Display display) Error Composer::validateDisplay(Display display, uint32_t* outNumTypes, uint32_t* outNumRequests) { + ATRACE_NAME("HwcValidateDisplay"); mWriter.selectDisplay(display); mWriter.validateDisplay(); @@ -601,13 +604,14 @@ Error Composer::validateDisplay(Display display, uint32_t* outNumTypes, Error Composer::presentOrValidateDisplay(Display display, uint32_t* outNumTypes, uint32_t* outNumRequests, int* outPresentFence, uint32_t* state) { - mWriter.selectDisplay(display); - mWriter.presentOrvalidateDisplay(); + ATRACE_NAME("HwcPresentOrValidateDisplay"); + mWriter.selectDisplay(display); + mWriter.presentOrvalidateDisplay(); - Error error = execute(); - if (error != Error::NONE) { - return error; - } + Error error = execute(); + if (error != Error::NONE) { + return error; + } mReader.takePresentOrValidateStage(display, state); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 77ee6a1875..b45f2bcd92 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -202,19 +202,6 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, */ void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {} -void Layer::removeRemoteSyncPoints() { - for (auto& point : mRemoteSyncPoints) { - point->setTransactionApplied(); - } - mRemoteSyncPoints.clear(); - - { - for (State pendingState : mPendingStates) { - pendingState.barrierLayer_legacy = nullptr; - } - } -} - void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) { if (mCurrentState.zOrderRelativeOf == nullptr) { return; @@ -236,21 +223,6 @@ void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) { void Layer::removeFromCurrentState() { mRemovedFromCurrentState = true; - // Since we are no longer reachable from CurrentState SurfaceFlinger - // will no longer invoke doTransaction for us, and so we will - // never finish applying transactions. We signal the sync point - // now so that another layer will not become indefinitely - // blocked. - removeRemoteSyncPoints(); - - { - Mutex::Autolock syncLock(mLocalSyncPointMutex); - for (auto& point : mLocalSyncPoints) { - point->setFrameAvailable(); - } - mLocalSyncPoints.clear(); - } - mFlinger->markLayerPendingRemovalLocked(this); } @@ -775,21 +747,6 @@ Hwc2::IComposerClient::Composition Layer::getCompositionType(const DisplayDevice } } -bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) { - if (point->getFrameNumber() <= mCurrentFrameNumber) { - // Don't bother with a SyncPoint, since we've already latched the - // relevant frame - return false; - } - if (isRemovedFromCurrentState()) { - return false; - } - - Mutex::Autolock lock(mLocalSyncPointMutex); - mLocalSyncPoints.push_back(point); - return true; -} - // ---------------------------------------------------------------------------- // local state // ---------------------------------------------------------------------------- @@ -808,132 +765,6 @@ bool Layer::isSecure() const { // transaction // ---------------------------------------------------------------------------- -void Layer::pushPendingState() { - if (!mCurrentState.modified) { - return; - } - ATRACE_CALL(); - - // If this transaction is waiting on the receipt of a frame, generate a sync - // point and send it to the remote layer. - // We don't allow installing sync points after we are removed from the current state - // as we won't be able to signal our end. - if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { - sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote(); - if (barrierLayer == nullptr) { - ALOGE("[%s] Unable to promote barrier Layer.", getDebugName()); - // If we can't promote the layer we are intended to wait on, - // then it is expired or otherwise invalid. Allow this transaction - // to be applied as per normal (no synchronization). - mCurrentState.barrierLayer_legacy = nullptr; - } else { - auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.barrierFrameNumber, this, - barrierLayer); - if (barrierLayer->addSyncPoint(syncPoint)) { - std::stringstream ss; - ss << "Adding sync point " << mCurrentState.barrierFrameNumber; - ATRACE_NAME(ss.str().c_str()); - mRemoteSyncPoints.push_back(std::move(syncPoint)); - } else { - // We already missed the frame we're supposed to synchronize - // on, so go ahead and apply the state update - mCurrentState.barrierLayer_legacy = nullptr; - } - } - - // Wake us up to check if the frame has been received - setTransactionFlags(eTransactionNeeded); - mFlinger->setTransactionFlags(eTraversalNeeded); - } - if (mCurrentState.bufferlessSurfaceFramesTX.size() >= State::kStateSurfaceFramesThreshold) { - // Ideally, the currentState would only contain one SurfaceFrame per transaction (assuming - // each Tx uses a different token). We don't expect the current state to hold a huge amount - // of SurfaceFrames. However, in the event it happens, this debug statement will leave a - // trail that can help in debugging. - ALOGW("Bufferless SurfaceFrames size on current state of layer %s is %" PRIu32 "", - mName.c_str(), static_cast<uint32_t>(mCurrentState.bufferlessSurfaceFramesTX.size())); - } - mPendingStates.push_back(mCurrentState); - // Since the current state along with the SurfaceFrames has been pushed into the pendingState, - // we no longer need to retain them. If multiple states are pushed and applied together, we have - // a merging logic to address the SurfaceFrames at mergeSurfaceFrames(). - mCurrentState.bufferlessSurfaceFramesTX.clear(); - ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); -} - -void Layer::mergeSurfaceFrames(State& source, State& target) { - // No need to merge BufferSurfaceFrame as the target's surfaceFrame, if it exists, will be used - // directly. Dropping of source's SurfaceFrame is taken care of at setBuffer(). - target.bufferlessSurfaceFramesTX.merge(source.bufferlessSurfaceFramesTX); - source.bufferlessSurfaceFramesTX.clear(); -} - -void Layer::popPendingState(State* stateToCommit) { - ATRACE_CALL(); - - mergeSurfaceFrames(*stateToCommit, mPendingStates[0]); - *stateToCommit = mPendingStates[0]; - mPendingStates.pop_front(); - ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); -} - -bool Layer::applyPendingStates(State* stateToCommit) { - bool stateUpdateAvailable = false; - while (!mPendingStates.empty()) { - if (mPendingStates[0].barrierLayer_legacy != nullptr) { - if (mRemoteSyncPoints.empty()) { - // If we don't have a sync point for this, apply it anyway. It - // will be visually wrong, but it should keep us from getting - // into too much trouble. - ALOGV("[%s] No local sync point found", getDebugName()); - popPendingState(stateToCommit); - stateUpdateAvailable = true; - continue; - } - - if (mRemoteSyncPoints.front()->getFrameNumber() != - mPendingStates[0].barrierFrameNumber) { - ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); - - // Signal our end of the sync point and then dispose of it - mRemoteSyncPoints.front()->setTransactionApplied(); - mRemoteSyncPoints.pop_front(); - continue; - } - - if (mRemoteSyncPoints.front()->frameIsAvailable()) { - ATRACE_NAME("frameIsAvailable"); - // Apply the state update - popPendingState(stateToCommit); - stateUpdateAvailable = true; - - // Signal our end of the sync point and then dispose of it - mRemoteSyncPoints.front()->setTransactionApplied(); - mRemoteSyncPoints.pop_front(); - } else { - ATRACE_NAME("!frameIsAvailable"); - mRemoteSyncPoints.front()->checkTimeoutAndLog(); - break; - } - } else { - popPendingState(stateToCommit); - stateUpdateAvailable = true; - } - } - - // If we still have pending updates, we need to ensure SurfaceFlinger - // will keep calling doTransaction, and so we force a traversal. - // However, our pending states won't clear until a frame is available, - // and so there is no need to specifically trigger a wakeup. - if (!mPendingStates.empty()) { - setTransactionFlags(eTransactionNeeded); - mFlinger->setTraversalNeeded(); - } - - mCurrentState.modified = false; - return stateUpdateAvailable; -} - uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const State& s(getDrawingState()); @@ -1014,15 +845,14 @@ uint32_t Layer::doTransaction(uint32_t flags) { mChildrenChanged = false; } - pushPendingState(); - State c = getCurrentState(); - if (!applyPendingStates(&c)) { - return flags; - } + // TODO: This is unfortunate. + mCurrentStateModified = mCurrentState.modified; + mCurrentState.modified = false; - flags = doTransactionResize(flags, &c); + flags = doTransactionResize(flags, &mCurrentState); const State& s(getDrawingState()); + State& c(getCurrentState()); if (getActiveGeometry(c) != getActiveGeometry(s)) { // invalidate and recompute the visible regions if needed @@ -1054,7 +884,6 @@ uint32_t Layer::doTransaction(uint32_t flags) { // Commit the transaction commitTransaction(c); - mPendingStatesSnapshot = mPendingStates; mCurrentState.callbackHandles = {}; return flags; @@ -1662,25 +1491,6 @@ Layer::FrameRate Layer::getFrameRateForLayerTree() const { return frameRate; } -void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) { - ATRACE_CALL(); - - mCurrentState.barrierLayer_legacy = barrierLayer; - mCurrentState.barrierFrameNumber = frameNumber; - // We don't set eTransactionNeeded, because just receiving a deferral - // request without any other state updates shouldn't actually induce a delay - mCurrentState.modified = true; - pushPendingState(); - mCurrentState.barrierLayer_legacy = nullptr; - mCurrentState.barrierFrameNumber = 0; - mCurrentState.modified = false; -} - -void Layer::deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber) { - sp<Handle> handle = static_cast<Handle*>(barrierHandle.get()); - deferTransactionUntil_legacy(handle->owner.promote(), frameNumber); -} - // ---------------------------------------------------------------------------- // pageflip handling... // ---------------------------------------------------------------------------- @@ -1949,32 +1759,6 @@ ssize_t Layer::removeChild(const sp<Layer>& layer) { return removeResult; } -void Layer::reparentChildren(const sp<Layer>& newParent) { - for (const sp<Layer>& child : mCurrentChildren) { - newParent->addChild(child); - } - mCurrentChildren.clear(); - updateTreeHasFrameRateVote(); -} - -bool Layer::reparentChildren(const sp<IBinder>& newParentHandle) { - sp<Handle> handle = nullptr; - sp<Layer> newParent = nullptr; - if (newParentHandle == nullptr) { - return false; - } - handle = static_cast<Handle*>(newParentHandle.get()); - newParent = handle->owner.promote(); - if (newParent == nullptr) { - ALOGE("Unable to promote Layer handle"); - return false; - } - - reparentChildren(newParent); - - return true; -} - void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) { for (const sp<Layer>& child : mDrawingChildren) { child->mDrawingParent = newParent; @@ -2290,8 +2074,13 @@ int32_t Layer::getBackgroundBlurRadius() const { return parentAlpha * getDrawingState().backgroundBlurRadius; } -const std::vector<BlurRegion>& Layer::getBlurRegions() const { - return getDrawingState().blurRegions; +const std::vector<BlurRegion> Layer::getBlurRegions() const { + auto regionsCopy(getDrawingState().blurRegions); + int layerAlpha = getAlpha(); + for (auto& region : regionsCopy) { + region.alpha = region.alpha * layerAlpha; + } + return regionsCopy; } Layer::RoundedCornerState Layer::getRoundedCornerState() const { @@ -2313,8 +2102,8 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCrop(getDrawingState()).isValid() - ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() + ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } @@ -2388,14 +2177,6 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, const ui::Transform transform = getTransform(); if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { - for (const auto& pendingState : mPendingStatesSnapshot) { - auto barrierLayer = pendingState.barrierLayer_legacy.promote(); - if (barrierLayer != nullptr) { - BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); - barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.barrierFrameNumber); - } - } auto buffer = getBuffer(); if (buffer != nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 78debf2bae..5379d7490d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -166,11 +166,6 @@ public: Rect crop; Rect requestedCrop; - // If set, defers this state update until the identified Layer - // receives a frame with the given frameNumber - wp<Layer> barrierLayer_legacy; - uint64_t barrierFrameNumber; - // the transparentRegion hint is a bit special, it's latched only // when we receive a buffer -- this is because it's "content" // dependent. @@ -398,9 +393,6 @@ public: virtual bool setFlags(uint32_t flags, uint32_t mask); virtual bool setLayerStack(uint32_t layerStack); virtual uint32_t getLayerStack() const; - virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, - uint64_t frameNumber); - virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber); virtual bool setMetadata(const LayerMetadata& data); virtual void setChildrenDrawingParent(const sp<Layer>&); virtual bool reparent(const sp<IBinder>& newParentHandle); @@ -412,7 +404,6 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, const sp<Fence>& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, @@ -579,14 +570,6 @@ public: virtual int32_t getQueuedFrameCount() const { return 0; } - virtual void pushPendingState(); - - /* - * Merges the BufferlessSurfaceFrames from source with the target. If the same token exists in - * both source and target, target's SurfaceFrame will be retained. - */ - void mergeSurfaceFrames(State& source, State& target); - /** * Returns active buffer size in the correct orientation. Buffer size is determined by undoing * any buffer transformations. If the layer has no buffer then return INVALID_RECT. @@ -616,7 +599,6 @@ public: // ignored. virtual RoundedCornerState getRoundedCornerState() const; - virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {} virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } /** * Return whether this layer needs an input info. For most layer types @@ -638,8 +620,6 @@ public: void onLayerDisplayed(const sp<Fence>& releaseFence) override; const char* getDebugName() const override; - bool reparentChildren(const sp<IBinder>& newParentHandle); - void reparentChildren(const sp<Layer>& newParent); bool setShadowRadius(float shadowRadius); // Before color management is introduced, contents on Android have to be @@ -906,65 +886,6 @@ public: virtual std::string getPendingBufferCounterName() { return ""; } protected: - class SyncPoint { - public: - explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer, - wp<Layer> barrierLayer_legacy) - : mFrameNumber(frameNumber), - mFrameIsAvailable(false), - mTransactionIsApplied(false), - mRequestedSyncLayer(requestedSyncLayer), - mBarrierLayer_legacy(barrierLayer_legacy) {} - uint64_t getFrameNumber() const { return mFrameNumber; } - - bool frameIsAvailable() const { return mFrameIsAvailable; } - - void setFrameAvailable() { mFrameIsAvailable = true; } - - bool transactionIsApplied() const { return mTransactionIsApplied; } - - void setTransactionApplied() { mTransactionIsApplied = true; } - - sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); } - - sp<Layer> getBarrierLayer() const { return mBarrierLayer_legacy.promote(); } - - bool isTimeout() const { - using namespace std::chrono_literals; - static constexpr std::chrono::nanoseconds TIMEOUT_THRESHOLD = 1s; - - return std::chrono::steady_clock::now() - mCreateTimeStamp > TIMEOUT_THRESHOLD; - } - - void checkTimeoutAndLog() { - using namespace std::chrono_literals; - static constexpr std::chrono::nanoseconds LOG_PERIOD = 1s; - - if (!frameIsAvailable() && isTimeout()) { - const auto now = std::chrono::steady_clock::now(); - if (now - mLastLogTime > LOG_PERIOD) { - mLastLogTime = now; - sp<Layer> requestedSyncLayer = getRequestedSyncLayer(); - sp<Layer> barrierLayer = getBarrierLayer(); - ALOGW("[%s] sync point %" PRIu64 " wait timeout %lld for %s", - requestedSyncLayer ? requestedSyncLayer->getDebugName() : "Removed", - mFrameNumber, (now - mCreateTimeStamp).count(), - barrierLayer ? barrierLayer->getDebugName() : "Removed"); - } - } - } - - private: - const uint64_t mFrameNumber; - std::atomic<bool> mFrameIsAvailable; - std::atomic<bool> mTransactionIsApplied; - wp<Layer> mRequestedSyncLayer; - wp<Layer> mBarrierLayer_legacy; - const std::chrono::time_point<std::chrono::steady_clock> mCreateTimeStamp = - std::chrono::steady_clock::now(); - std::chrono::time_point<std::chrono::steady_clock> mLastLogTime; - }; - friend class impl::SurfaceInterceptor; // For unit tests @@ -983,7 +904,6 @@ protected: ui::Dataspace outputDataspace); virtual void preparePerFrameCompositionState(); virtual void commitTransaction(State& stateToCommit); - virtual bool applyPendingStates(State* stateToCommit); virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {} @@ -1029,21 +949,6 @@ protected: virtual ui::Transform getInputTransform() const; virtual Rect getInputBounds() const; - // SyncPoints which will be signaled when the correct frame is at the head - // of the queue and dropped after the frame has been latched. Protected by - // mLocalSyncPointMutex. - Mutex mLocalSyncPointMutex; - std::list<std::shared_ptr<SyncPoint>> mLocalSyncPoints; - - // SyncPoints which will be signaled and then dropped when the transaction - // is applied - std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints; - - // Returns false if the relevant frame has already been latched - bool addSyncPoint(const std::shared_ptr<SyncPoint>& point); - - void popPendingState(State* stateToCommit); - // constant sp<SurfaceFlinger> mFlinger; @@ -1053,14 +958,10 @@ protected: // These are only accessed by the main thread or the tracing thread. State mDrawingState; - // Store a copy of the pending state so that the drawing thread can access the - // states without a lock. - std::deque<State> mPendingStatesSnapshot; // these are protected by an external lock (mStateLock) State mCurrentState; std::atomic<uint32_t> mTransactionFlags{0}; - std::deque<State> mPendingStates; // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; @@ -1122,6 +1023,8 @@ protected: // Used in buffer stuffing analysis in FrameTimeline. nsecs_t mLastLatchTime = 0; + mutable bool mCurrentStateModified = false; + private: virtual void setTransformHint(ui::Transform::RotationFlags) {} @@ -1146,7 +1049,6 @@ private: void updateTreeHasFrameRateVote(); void setZOrderRelativeOf(const wp<Layer>& relativeOf); - void removeRemoteSyncPoints(); // Find the root of the cloned hierarchy, this means the first non cloned parent. // This will return null if first non cloned parent is not found. @@ -1194,7 +1096,7 @@ private: float mEffectiveShadowRadius = 0.f; // A list of regions on this layer that should have blurs. - const std::vector<BlurRegion>& getBlurRegions() const; + const std::vector<BlurRegion> getBlurRegions() const; }; std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate); diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 1d00cc38f2..7a3e433660 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -231,8 +231,14 @@ const std::vector<sp<GraphicBuffer>>& RefreshRateOverlay::getOrCreateBuffers(uin void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); - mLayer->setFrame(frame); + layer_state_t::matrix22_t matrix; + matrix.dsdx = frame.getWidth() / static_cast<float>(SevenSegmentDrawer::getWidth()); + matrix.dtdx = 0; + matrix.dtdy = 0; + matrix.dsdy = frame.getHeight() / static_cast<float>(SevenSegmentDrawer::getHeight()); + mLayer->setMatrix(matrix, true); + mLayer->setPosition(frame.left, frame.top); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 6553efe794..2321e2d082 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -217,12 +217,18 @@ namespace impl { EventThread::EventThread(std::unique_ptr<VSyncSource> vsyncSource, android::frametimeline::TokenManager* tokenManager, InterceptVSyncsCallback interceptVSyncsCallback, - ThrottleVsyncCallback throttleVsyncCallback) + ThrottleVsyncCallback throttleVsyncCallback, + GetVsyncPeriodFunction getVsyncPeriodFunction) : mVSyncSource(std::move(vsyncSource)), mTokenManager(tokenManager), mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)), mThrottleVsyncCallback(std::move(throttleVsyncCallback)), + mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)), mThreadName(mVSyncSource->getName()) { + + LOG_ALWAYS_FATAL_IF(getVsyncPeriodFunction == nullptr, + "getVsyncPeriodFunction must not be null"); + mVSyncSource->setCallback(this); mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS { @@ -565,7 +571,11 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, const DisplayEventConsumers& consumers) { for (const auto& consumer : consumers) { - switch (consumer->postEvent(event)) { + DisplayEventReceiver::Event copy = event; + if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { + copy.vsync.frameInterval = mGetVsyncPeriodFunction(consumer->mOwnerUid); + } + switch (consumer->postEvent(copy)) { case NO_ERROR: break; diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 35406041a8..1e6793f77c 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -152,9 +152,10 @@ class EventThread : public android::EventThread, private VSyncSource::Callback { public: using InterceptVSyncsCallback = std::function<void(nsecs_t)>; using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>; + using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>; EventThread(std::unique_ptr<VSyncSource>, frametimeline::TokenManager*, InterceptVSyncsCallback, - ThrottleVsyncCallback); + ThrottleVsyncCallback, GetVsyncPeriodFunction); ~EventThread(); sp<EventThreadConnection> createEventConnection( @@ -210,6 +211,7 @@ private: const InterceptVSyncsCallback mInterceptVSyncsCallback; const ThrottleVsyncCallback mThrottleVsyncCallback; + const GetVsyncPeriodFunction mGetVsyncPeriodFunction; const char* const mThreadName; std::thread mThread; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 8426737597..1d25c7247f 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -248,15 +248,34 @@ impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() }; } +impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const { + return [this](uid_t uid) { + nsecs_t basePeriod = mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod(); + const auto frameRate = getFrameRateOverride(uid); + if (!frameRate.has_value()) { + return basePeriod; + } + + const auto divider = scheduler::RefreshRateConfigs::getFrameRateDivider( + mRefreshRateConfigs.getCurrentRefreshRate().getFps(), *frameRate); + if (divider <= 1) { + return basePeriod; + } + return basePeriod * divider; + }; +} + Scheduler::ConnectionHandle Scheduler::createConnection( const char* connectionName, frametimeline::TokenManager* tokenManager, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration, impl::EventThread::InterceptVSyncsCallback interceptCallback) { auto vsyncSource = makePrimaryDispSyncSource(connectionName, workDuration, readyDuration); auto throttleVsync = makeThrottleVsyncCallback(); + auto getVsyncPeriod = makeGetVsyncPeriodFunction(); auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource), tokenManager, std::move(interceptCallback), - std::move(throttleVsync)); + std::move(throttleVsync), + std::move(getVsyncPeriod)); return createConnection(std::move(eventThread)); } @@ -444,7 +463,8 @@ Scheduler::ConnectionHandle Scheduler::enableVSyncInjection(bool enable) { std::make_unique<impl::EventThread>(std::move(vsyncSource), /*tokenManager=*/nullptr, impl::EventThread::InterceptVSyncsCallback(), - impl::EventThread::ThrottleVsyncCallback()); + impl::EventThread::ThrottleVsyncCallback(), + impl::EventThread::GetVsyncPeriodFunction()); // EventThread does not dispatch VSYNC unless the display is connected and powered on. eventThread->onHotplugReceived(PhysicalDisplayId::fromPort(0), true); diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index d4932e7f8e..4d1f3c6572 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -240,6 +240,7 @@ private: EXCLUDES(mFrameRateOverridesMutex); impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const; + impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 24f6b37893..047b2f5437 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -693,12 +693,16 @@ uint32_t SurfaceFlinger::getNewTexture() { // The pool was empty, so we need to get a new texture name directly using a // blocking call to the main thread - return schedule([this] { + auto genTextures = [this] { uint32_t name = 0; getRenderEngine().genTextures(1, &name); return name; - }) - .get(); + }; + if (std::this_thread::get_id() == mMainThreadId) { + return genTextures(); + } else { + return schedule(genTextures).get(); + } } void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { @@ -1814,10 +1818,6 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT if (frameMissed) { mFrameMissedCount++; mTimeStats->incrementMissedFrames(); - if (mMissedFrameJankCount == 0) { - mMissedFrameJankStart = systemTime(); - } - mMissedFrameJankCount++; } if (hwcFrameMissed) { @@ -1849,37 +1849,6 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT } } - // Our jank window is always at least 100ms since we missed a - // frame... - static constexpr nsecs_t kMinJankyDuration = - std::chrono::duration_cast<std::chrono::nanoseconds>(100ms).count(); - // ...but if it's larger than 1s then we missed the trace cutoff. - static constexpr nsecs_t kMaxJankyDuration = - std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count(); - nsecs_t jankDurationToUpload = -1; - // If we're in a user build then don't push any atoms - if (!mIsUserBuild && mMissedFrameJankCount > 0) { - const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); - // Only report jank when the display is on, as displays in DOZE - // power mode may operate at a different frame rate than is - // reported in their config, which causes noticeable (but less - // severe) jank. - if (display && display->getPowerMode() == hal::PowerMode::ON) { - const nsecs_t currentTime = systemTime(); - const nsecs_t jankDuration = currentTime - mMissedFrameJankStart; - if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) { - jankDurationToUpload = jankDuration; - } - - // We either reported a jank event or we missed the trace - // window, so clear counters here. - if (jankDuration > kMinJankyDuration) { - mMissedFrameJankCount = 0; - mMissedFrameJankStart = 0; - } - } - } - if (mTracingEnabledChanged) { mTracingEnabled = mTracing.isEnabled(); mTracingEnabledChanged = false; @@ -1926,7 +1895,6 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT refreshNeeded |= mRepaintEverything; if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { - mLastJankDuration = jankDurationToUpload; // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint @@ -2302,14 +2270,6 @@ void SurfaceFlinger::postComposition() { const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle); mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections); - if (mLastJankDuration > 0) { - ATRACE_NAME("Jank detected"); - const int32_t jankyDurationMillis = mLastJankDuration / (1000 * 1000); - android::util::stats_write(android::util::DISPLAY_JANK_REPORTED, jankyDurationMillis, - mMissedFrameJankCount); - mLastJankDuration = -1; - } - if (isDisplayConnected && !display->isPoweredOn()) { return; } @@ -2859,13 +2819,6 @@ void SurfaceFlinger::processDisplayChangesLocked() { } void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { - const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); - - // Notify all layers of available frames - mCurrentState.traverse([expectedPresentTime](Layer* layer) { - layer->notifyAvailableFrames(expectedPresentTime); - }); - /* * Traversal of the children * (perform the transaction for each of them if needed) @@ -3877,12 +3830,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( const uint64_t what = s.what; - // If we are deferring transaction, make sure to push the pending state, as otherwise the - // pending state will also be deferred. - if (what & layer_state_t::eDeferTransaction_legacy) { - layer->pushPendingState(); - } - // Only set by BLAST adapter layers if (what & layer_state_t::eProducerDisconnect) { layer->onDisconnect(); @@ -4017,17 +3964,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded | eTraversalNeeded | eTransformHintUpdateNeeded; } } - if (what & layer_state_t::eDeferTransaction_legacy) { - layer->deferTransactionUntil_legacy(s.barrierSurfaceControl_legacy->getHandle(), - s.barrierFrameNumber); - // We don't trigger a traversal here because if no other state is - // changed, we don't want this to cause any more work - } - if (what & layer_state_t::eReparentChildren) { - if (layer->reparentChildren(s.reparentSurfaceControl->getHandle())) { - flags |= eTransactionNeeded|eTraversalNeeded; - } - } if (what & layer_state_t::eTransformChanged) { if (layer->setTransform(s.transform)) flags |= eTraversalNeeded; } @@ -4038,9 +3974,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFrameChanged) { - if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded; - } if (what & layer_state_t::eAcquireFenceChanged) { if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c7601fae5a..b3da61e810 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1387,13 +1387,6 @@ private: // be any issues with a raw pointer referencing an invalid object. std::unordered_set<Layer*> mOffscreenLayers; - // Fields tracking the current jank event: when it started and how many - // janky frames there are. - nsecs_t mMissedFrameJankStart = 0; - int32_t mMissedFrameJankCount = 0; - // Positive if jank should be uploaded in postComposition - nsecs_t mLastJankDuration = -1; - int mFrameRateFlexibilityTokenCount = 0; sp<IBinder> mDebugFrameRateFlexibilityToken; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 8a3be9f4ed..113f463c39 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -141,11 +141,6 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius); addBackgroundBlurRadiusLocked(transaction, layerId, layer->mCurrentState.backgroundBlurRadius); addBlurRegionsLocked(transaction, layerId, layer->mCurrentState.blurRegions); - if (layer->mCurrentState.barrierLayer_legacy != nullptr) { - addDeferTransactionLocked(transaction, layerId, - layer->mCurrentState.barrierLayer_legacy.promote(), - layer->mCurrentState.barrierFrameNumber); - } addFlagsLocked(transaction, layerId, layer->mCurrentState.flags, layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque | layer_state_t::eLayerSecure); @@ -380,20 +375,6 @@ void SurfaceInterceptor::addBlurRegionsLocked(Transaction* transaction, int32_t } } -void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, - const sp<const Layer>& layer, uint64_t frameNumber) -{ - SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - if (layer == nullptr) { - ALOGE("An existing layer could not be retrieved with the handle" - " for the deferred transaction"); - return; - } - DeferredTransactionChange* deferTransaction(change->mutable_deferred_transaction()); - deferTransaction->set_layer_id(getLayerId(layer)); - deferTransaction->set_frame_number(frameNumber); -} - void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); @@ -401,13 +382,6 @@ void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t lay overrideChange->set_parent_id(parentId); } -void SurfaceInterceptor::addReparentChildrenLocked(Transaction* transaction, int32_t layerId, - int32_t parentId) { - SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - ReparentChildrenChange* overrideChange(change->mutable_reparent_children()); - overrideChange->set_parent_id(parentId); -} - void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); @@ -471,25 +445,12 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eBlurRegionsChanged) { addBlurRegionsLocked(transaction, layerId, state.blurRegions); } - if (state.what & layer_state_t::eDeferTransaction_legacy) { - sp<Layer> otherLayer = nullptr; - if (state.barrierSurfaceControl_legacy != nullptr) { - otherLayer = static_cast<Layer::Handle*>( - state.barrierSurfaceControl_legacy->getHandle().get()) - ->owner.promote(); - } - addDeferTransactionLocked(transaction, layerId, otherLayer, state.barrierFrameNumber); - } if (state.what & layer_state_t::eReparent) { auto parentHandle = (state.parentSurfaceControlForChild) ? state.parentSurfaceControlForChild->getHandle() : nullptr; addReparentLocked(transaction, layerId, getLayerIdFromHandle(parentHandle)); } - if (state.what & layer_state_t::eReparentChildren) { - addReparentChildrenLocked(transaction, layerId, - getLayerIdFromHandle(state.reparentSurfaceControl->getHandle())); - } if (state.what & layer_state_t::eRelativeLayerChanged) { addRelativeParentLocked(transaction, layerId, getLayerIdFromHandle( diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 3e27e83b02..30aca8340e 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -167,8 +167,6 @@ private: int32_t backgroundBlurRadius); void addBlurRegionsLocked(Transaction* transaction, int32_t layerId, const std::vector<BlurRegion>& effectRegions); - void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, - const sp<const Layer>& layer, uint64_t frameNumber); void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state); void addTransactionLocked(Increment* increment, const Vector<ComposerState>& stateUpdates, const DefaultKeyedVector<wp<IBinder>, DisplayDeviceState>& displays, @@ -176,7 +174,6 @@ private: uint32_t transactionFlags, int originPid, int originUid, uint64_t transactionId); void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId); - void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId); void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z); void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius); diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index 2b8424c987..9686523525 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -89,13 +89,47 @@ int main(int, char**) { // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); + // The binder threadpool we start will inherit sched policy and priority + // of (this) creating thread. We want the binder thread pool to have + // SCHED_FIFO policy and priority 1 (lowest RT priority) + // Once the pool is created we reset this thread's priority back to + // original. + int newPriority = 0; + int origPolicy = sched_getscheduler(0); + struct sched_param origSchedParam; + + int errorInPriorityModification = sched_getparam(0, &origSchedParam); + if (errorInPriorityModification == 0) { + int policy = SCHED_FIFO; + newPriority = sched_get_priority_min(policy); + + struct sched_param param; + param.sched_priority = newPriority; + + errorInPriorityModification = sched_setscheduler(0, policy, ¶m); + } + // start the thread pool sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); + // Reset current thread's policy and priority + if (errorInPriorityModification == 0) { + errorInPriorityModification = sched_setscheduler(0, origPolicy, &origSchedParam); + } else { + ALOGE("Failed to set SurfaceFlinger binder threadpool priority to SCHED_FIFO"); + } + // instantiate surfaceflinger sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger(); + // Set the minimum policy of surfaceflinger node to be SCHED_FIFO. + // So any thread with policy/priority lower than {SCHED_FIFO, 1}, will run + // at least with SCHED_FIFO policy and priority 1. + if (errorInPriorityModification == 0) { + flinger->setMinSchedulerPolicy(SCHED_FIFO, newPriority); + } + setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); set_sched_policy(0, SP_FOREGROUND); diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 03f8e1afba..47a150dd35 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -296,12 +296,12 @@ private: BufferGenerator::BufferGenerator() : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { - const float width = 1000.0; - const float height = 1000.0; + mBufferSize.set(1000.0, 1000.0); auto setBufferWithContext = std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); - mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); + mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888, + setBufferWithContext); if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; @@ -309,7 +309,9 @@ BufferGenerator::BufferGenerator() if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; mProgram->use(); - mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); + mProgram->bindVec4(0, + vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width, + 1.0f / mBufferSize.height}); mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); glEnableVertexAttribArray(0); @@ -372,6 +374,10 @@ status_t BufferGenerator::get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) return NO_ERROR; } +ui::Size BufferGenerator::getSize() { + return mBufferSize; +} + // static void BufferGenerator::setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence, void* bufferGenerator) { diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h index a3ffe86572..f7d548b6bf 100644 --- a/services/surfaceflinger/tests/BufferGenerator.h +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -37,6 +37,7 @@ public: /* Static callback that sets the fence on a particular instance */ static void setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence, void* fenceGenerator); + ui::Size getSize(); private: bool mInitialized = false; @@ -53,6 +54,7 @@ private: using Epoch = std::chrono::time_point<std::chrono::steady_clock>; Epoch mEpoch = std::chrono::steady_clock::now(); + ui::Size mBufferSize; }; } // namespace android diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index f470eda7d3..af00ec7fc9 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -149,7 +149,6 @@ TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) { t.reparent(blurLayer, mParentLayer); t.setBackgroundBlurRadius(blurLayer, blurRadius); t.setCrop(blurLayer, blurRect); - t.setFrame(blurLayer, blurRect); t.setAlpha(blurLayer, 0.0f); t.show(blurLayer); }); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index a8647c3e50..9fa3d4c417 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,7 +161,6 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max()) - .setFrame(mSurfaceControl, Rect(0, 0, width, height)) .setBuffer(mSurfaceControl, gb) .setAcquireFence(mSurfaceControl, fence) .show(mSurfaceControl) diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 158801a705..011ff70409 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -164,7 +164,10 @@ TEST_F(LayerCallbackTest, NoBufferNoColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, @@ -184,7 +187,10 @@ TEST_F(LayerCallbackTest, BufferNoColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -203,7 +209,10 @@ TEST_F(LayerCallbackTest, NoBufferColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, @@ -238,7 +247,10 @@ TEST_F(LayerCallbackTest, OffScreen) { return; } - transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(-100, -100, 100, 100)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -263,8 +275,15 @@ TEST_F(LayerCallbackTest, MergeBufferNoColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -290,8 +309,15 @@ TEST_F(LayerCallbackTest, MergeNoBufferColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -318,8 +344,15 @@ TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); @@ -405,8 +438,15 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -491,7 +531,11 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { } } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -523,8 +567,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -564,8 +616,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -606,8 +666,15 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -661,8 +728,15 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -682,7 +756,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + transaction2.merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, ExpectedResult::Buffer::NOT_ACQUIRED); @@ -762,7 +839,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -781,7 +861,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + TransactionUtils::setFrame(transaction, layer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 7505e6ea9b..53d230abe7 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -204,11 +204,7 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(16, 16, 48, 48)) - .setRelativeLayer(layerG, layerR, 1) - .apply(); + Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; default: ASSERT_FALSE(true) << "Unsupported layer type"; @@ -260,10 +256,9 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(8, 8, 40, 40)) + .setPosition(layerG, 8, 8) .setRelativeLayer(layerG, layerR, 3) - .setFrame(layerB, Rect(16, 16, 48, 48)) + .setPosition(layerB, 16, 16) .setLayer(layerB, mLayerZBase + 2) .apply(); break; @@ -388,7 +383,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) - .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -447,7 +441,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_Buffe // check that transparent region hint is bound by the layer size Transaction() .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setFrame(layerR, Rect(16, 16, 48, 48)) + .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); ASSERT_NO_FATAL_FAILURE( @@ -477,8 +471,7 @@ void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { Transaction() .setAlpha(layer1, 0.25f) .setAlpha(layer2, 0.75f) - .setFrame(layer1, Rect(0, 0, 32, 32)) - .setFrame(layer2, Rect(16, 0, 48, 32)) + .setPosition(layer2, 16, 0) .setLayer(layer2, mLayerZBase + 1) .apply(); break; @@ -573,7 +566,7 @@ void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); expectedColor = fillColor; } - Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); + Transaction().setCrop(layer, Rect(0, 0, width, height)).apply(); break; default: GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; @@ -849,42 +842,39 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction() - .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) - .setFrame(layer, Rect(0, 0, 32, 32)) - .apply(); + Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN, Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED, + Color::WHITE, Color::BLUE); } Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); { SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE, + Color::RED, Color::GREEN); } Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); { SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED, + Color::WHITE, Color::GREEN); } Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); { SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE, 1 /* tolerance */); } } @@ -955,8 +945,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { @@ -986,13 +976,13 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { { SCOPED_TRACE("empty rect"); Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1016,8 +1006,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); - Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); - Transaction().setBuffer(layer, buffer).apply(); // Partially out of bounds in the negative (upper left) direction @@ -1025,8 +1013,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, negative (upper left) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK); } // Partially out of bounds in the positive (lower right) direction @@ -1034,8 +1022,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, positive (lower right) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 16, 32, 64), Color::RED); + shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK); } // Fully out of buffer space bounds @@ -1043,9 +1031,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("Fully out of bounds"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); - shot->expectColor(Rect(0, 16, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK); } } @@ -1068,12 +1054,11 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); + Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(frame, Color::RED); - shot->expectBorder(frame, Color::BLACK); + shot->expectColor(Rect(40, 40, 56, 56), Color::RED); + shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { @@ -1121,7 +1106,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect frame(8, 8, 24, 24); - Transaction().setFrame(layer, frame).apply(); + Transaction t; + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame); + t.apply(); + auto shot = getScreenCapture(); shot->expectColor(frame, Color::RED); shot->expectBorder(frame, Color::BLACK); @@ -1133,16 +1121,23 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction t; { SCOPED_TRACE("empty rect"); - Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8)); + t.apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } { SCOPED_TRACE("negative rect"); - Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0)); + t.apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 8, 8), Color::RED); + shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK); } } @@ -1152,10 +1147,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - // A parentless layer will default to a frame with the same size as the buffer + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 10, 10), Color::RED); + shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { @@ -1163,17 +1158,16 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer will default to the frame of its parent + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1183,14 +1177,14 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer will default to the frame of its parent + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1199,11 +1193,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(500ms); - Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); + Transaction().setPosition(layer, 16, 16).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1215,18 +1208,20 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); + Rect childDst(0, 16, 32, 32); + Transaction t; + TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst); + t.apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); + shot->expectColor(childDst, Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1238,8 +1233,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { @@ -1252,8 +1247,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 1"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); @@ -1261,8 +1256,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 2"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); @@ -1270,8 +1265,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 3"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } } @@ -1286,7 +1281,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); - Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = getScreenCapture(); @@ -1295,7 +1289,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); - Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = getScreenCapture(); @@ -1350,8 +1343,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } idx++; } @@ -1383,8 +1376,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } idx++; } @@ -1416,8 +1409,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } if (idx == 0) { buffers[0].clear(); @@ -1435,7 +1428,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) .apply(); @@ -1452,7 +1444,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) .apply(); @@ -1469,7 +1460,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) .apply(); @@ -1518,8 +1508,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { @@ -1534,8 +1524,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { @@ -1552,8 +1542,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { @@ -1570,8 +1560,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { @@ -1586,8 +1576,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 87c7b7d829..0bc8fe7aa0 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -244,6 +244,11 @@ protected: return bufferGenerator.get(outBuffer, outFence); } + static ui::Size getBufferSize() { + static BufferGenerator bufferGenerator; + return bufferGenerator.getSize(); + } + sp<SurfaceComposerClient> mClient; bool deviceSupportsBlurs() { diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index ac5e297e43..edf55ea6ef 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -196,17 +196,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - Transaction() - .setCornerRadius(layer, cornerRadius) - .setCrop(layer, Rect(0, 0, size, size)) - .apply(); - } else { - Transaction() - .setCornerRadius(layer, cornerRadius) - .setFrame(layer, Rect(0, 0, size, size)) - .apply(); - } + Transaction().setCornerRadius(layer, cornerRadius).apply(); { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -234,19 +224,13 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); - auto transaction = Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setPosition(child, 0, size) - // Rotate by half PI - .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - transaction.setCrop(parent, Rect(0, 0, size, size)); - } else { - transaction.setFrame(parent, Rect(0, 0, size, size)); - } - transaction.apply(); + Transaction() + .setCornerRadius(parent, cornerRadius) + .reparent(child, parent) + .setPosition(child, 0, size) + // Rotate by half PI + .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f) + .apply(); { const uint8_t bottom = size - 1; @@ -275,21 +259,12 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setPosition(child, 0, size / 2) - .apply(); - } else { - Transaction() - .setCornerRadius(parent, cornerRadius) - .setFrame(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setFrame(child, Rect(0, size / 2, size, size)) - .apply(); - } + Transaction() + .setCornerRadius(parent, cornerRadius) + .reparent(child, parent) + .setPosition(child, 0, size / 2) + .apply(); + { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -331,12 +306,9 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { Transaction() .setLayer(greenLayer, mLayerZBase) - .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2}) .setLayer(leftLayer, mLayerZBase + 1) - .setFrame(leftLayer, leftRect) .setLayer(rightLayer, mLayerZBase + 2) .setPosition(rightLayer, rightRect.left, rightRect.top) - .setFrame(rightLayer, rightRect) .apply(); { @@ -352,7 +324,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { .setLayer(blurLayer, mLayerZBase + 3) .setBackgroundBlurRadius(blurLayer, blurRadius) .setCrop(blurLayer, blurRect) - .setFrame(blurLayer, blurRect) .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight()) .setAlpha(blurLayer, 0.0f) .apply(); @@ -435,10 +406,8 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA Transaction() .setLayer(left, mLayerZBase + 1) - .setFrame(left, {0, 0, size, size}) .setLayer(right, mLayerZBase + 2) .setPosition(right, size, 0) - .setFrame(right, {size, 0, size * 2, size}) .apply(); { @@ -457,7 +426,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA .setAlpha(blurParent, 0.5) .setLayer(blur, mLayerZBase + 4) .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect - .setFrame(blur, {0, 0, size * 2, size}) .reparent(blur, blurParent) .apply(); diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index e5c2ec8bfb..adb5d58e8c 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -160,61 +160,6 @@ protected: } }; -TEST_F(LayerUpdateTest, DeferredTransactionTest) { - std::unique_ptr<ScreenCapture> sc; - { - SCOPED_TRACE("before anything"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->expectFGColor(96, 96); - sc->expectBGColor(160, 160); - } - - // set up two deferred transactions on different frames - asTransaction([&](Transaction& t) { - t.setAlpha(mFGSurfaceControl, 0.75); - t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl, - mSyncSurfaceControl->getSurface()->getNextFrameNumber()); - }); - - asTransaction([&](Transaction& t) { - t.setPosition(mFGSurfaceControl, 128, 128); - t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl, - mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); - }); - - { - SCOPED_TRACE("before any trigger"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->expectFGColor(96, 96); - sc->expectBGColor(160, 160); - } - - // should trigger the first deferred transaction, but not the second one - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - { - SCOPED_TRACE("after first trigger"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->checkPixel(96, 96, 162, 63, 96); - sc->expectBGColor(160, 160); - } - - // should show up immediately since it's not deferred - asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); }); - - // trigger the second deferred transaction - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - { - SCOPED_TRACE("after second trigger"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->expectBGColor(96, 96); - sc->expectFGColor(160, 160); - } -} - TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { std::unique_ptr<ScreenCapture> sc; @@ -462,38 +407,6 @@ TEST_F(ChildLayerTest, ChildLayerAlpha) { } } -TEST_F(ChildLayerTest, ReparentChildren) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - asTransaction( - [&](Transaction& t) { t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl); }); - - { - mCapture = screenshot(); - mCapture->expectFGColor(64, 64); - // In reparenting we should have exposed the entire foreground surface. - mCapture->expectFGColor(74, 74); - // And the child layer should now begin at 10, 10 (since the BG - // layer is at (0, 0)). - mCapture->expectBGColor(9, 9); - mCapture->expectChildColor(10, 10); - } -} - TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { sp<SurfaceControl> mGrandChild = createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); @@ -539,7 +452,7 @@ TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) { asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); - t.reparentChildren(mChild, mFGSurfaceControl); + t.reparent(mGrandChild, mFGSurfaceControl); }); { @@ -734,36 +647,6 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) { } } -TEST_F(ChildLayerTest, Bug36858924) { - // Destroy the child layer - mChild.clear(); - - // Now recreate it as hidden - mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eHidden, mFGSurfaceControl.get()); - - // Show the child layer in a deferred transaction - asTransaction([&](Transaction& t) { - t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl, - mFGSurfaceControl->getSurface()->getNextFrameNumber()); - t.show(mChild); - }); - - // Render the foreground surface a few times - // - // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third - // frame because SurfaceFlinger would never process the deferred transaction and would therefore - // never acquire/release the first buffer - ALOGI("Filling 1"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); - ALOGI("Filling 2"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255); - ALOGI("Filling 3"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0); - ALOGI("Filling 4"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); -} - TEST_F(ChildLayerTest, Reparent) { asTransaction([&](Transaction& t) { t.show(mChild); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index 613b21ef04..ccf434d63a 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -195,7 +195,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); - Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); + Transaction().show(bufferStateLayer).apply(); { SCOPED_TRACE("Initial Mirror BufferStateLayer"); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index d9cab42aae..af23e2a9cc 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -44,7 +44,6 @@ constexpr uint32_t BUFFER_UPDATES = 18; constexpr uint32_t LAYER_UPDATE = INT_MAX - 2; constexpr uint32_t SIZE_UPDATE = 134; constexpr uint32_t STACK_UPDATE = 1; -constexpr uint64_t DEFERRED_UPDATE = 0; constexpr int32_t RELATIVE_Z = 42; constexpr float ALPHA_UPDATE = 0.29f; constexpr float CORNER_RADIUS_UPDATE = 0.2f; @@ -191,10 +190,8 @@ public: bool hiddenFlagUpdateFound(const SurfaceChange& change, bool foundHiddenFlag); bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag); bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag); - bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred); bool reparentUpdateFound(const SurfaceChange& change, bool found); bool relativeParentUpdateFound(const SurfaceChange& change, bool found); - bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found); bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found); bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); @@ -228,10 +225,8 @@ public: void hiddenFlagUpdate(Transaction&); void opaqueFlagUpdate(Transaction&); void secureFlagUpdate(Transaction&); - void deferredTransactionUpdate(Transaction&); void reparentUpdate(Transaction&); void relativeParentUpdate(Transaction&); - void reparentChildrenUpdate(Transaction&); void shadowRadiusUpdate(Transaction&); void surfaceCreation(Transaction&); void displayCreation(Transaction&); @@ -398,10 +393,6 @@ void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) { t.setFlags(mBGSurfaceControl, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure); } -void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { - t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl, DEFERRED_UPDATE); -} - void SurfaceInterceptorTest::reparentUpdate(Transaction& t) { t.reparent(mBGSurfaceControl, mFGSurfaceControl); } @@ -410,10 +401,6 @@ void SurfaceInterceptorTest::relativeParentUpdate(Transaction& t) { t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z); } -void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) { - t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl); -} - void SurfaceInterceptorTest::shadowRadiusUpdate(Transaction& t) { t.setShadowRadius(mBGSurfaceControl, SHADOW_RADIUS_UPDATE); } @@ -443,9 +430,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::hiddenFlagUpdate); runInTransaction(&SurfaceInterceptorTest::opaqueFlagUpdate); runInTransaction(&SurfaceInterceptorTest::secureFlagUpdate); - runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate); runInTransaction(&SurfaceInterceptorTest::reparentUpdate); - runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate); runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate); runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate); } @@ -628,18 +613,6 @@ bool SurfaceInterceptorTest::secureFlagUpdateFound(const SurfaceChange& change, return foundSecureFlag; } -bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& change, - bool foundDeferred) { - bool hasId(change.deferred_transaction().layer_id() == mBGLayerId); - bool hasFrameNumber(change.deferred_transaction().frame_number() == DEFERRED_UPDATE); - if (hasId && hasFrameNumber && !foundDeferred) { - foundDeferred = true; - } else if (hasId && hasFrameNumber && foundDeferred) { - [] () { FAIL(); }(); - } - return foundDeferred; -} - bool SurfaceInterceptorTest::reparentUpdateFound(const SurfaceChange& change, bool found) { bool hasId(change.reparent().parent_id() == mFGLayerId); if (hasId && !found) { @@ -660,16 +633,6 @@ bool SurfaceInterceptorTest::relativeParentUpdateFound(const SurfaceChange& chan return found; } -bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) { - bool hasId(change.reparent_children().parent_id() == mFGLayerId); - if (hasId && !found) { - found = true; - } else if (hasId && found) { - []() { FAIL(); }(); - } - return found; -} - bool SurfaceInterceptorTest::shadowRadiusUpdateFound(const SurfaceChange& change, bool foundShadowRadius) { bool hasShadowRadius(change.shadow_radius().radius() == SHADOW_RADIUS_UPDATE); @@ -732,15 +695,9 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kSecureFlag: foundUpdate = secureFlagUpdateFound(change, foundUpdate); break; - case SurfaceChange::SurfaceChangeCase::kDeferredTransaction: - foundUpdate = deferredTransactionUpdateFound(change, foundUpdate); - break; case SurfaceChange::SurfaceChangeCase::kReparent: foundUpdate = reparentUpdateFound(change, foundUpdate); break; - case SurfaceChange::SurfaceChangeCase::kReparentChildren: - foundUpdate = reparentChildrenUpdateFound(change, foundUpdate); - break; case SurfaceChange::SurfaceChangeCase::kRelativeParent: foundUpdate = relativeParentUpdateFound(change, foundUpdate); break; @@ -769,9 +726,7 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kHiddenFlag)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOpaqueFlag)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSecureFlag)); - ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDeferredTransaction)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent)); - ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent)); } @@ -927,21 +882,11 @@ TEST_F(SurfaceInterceptorTest, InterceptSecureFlagUpdateWorks) { SurfaceChange::SurfaceChangeCase::kSecureFlag); } -TEST_F(SurfaceInterceptorTest, InterceptDeferredTransactionUpdateWorks) { - captureTest(&SurfaceInterceptorTest::deferredTransactionUpdate, - SurfaceChange::SurfaceChangeCase::kDeferredTransaction); -} - TEST_F(SurfaceInterceptorTest, InterceptReparentUpdateWorks) { captureTest(&SurfaceInterceptorTest::reparentUpdate, SurfaceChange::SurfaceChangeCase::kReparent); } -TEST_F(SurfaceInterceptorTest, InterceptReparentChildrenUpdateWorks) { - captureTest(&SurfaceInterceptorTest::reparentChildrenUpdate, - SurfaceChange::SurfaceChangeCase::kReparentChildren); -} - TEST_F(SurfaceInterceptorTest, InterceptRelativeParentUpdateWorks) { captureTest(&SurfaceInterceptorTest::relativeParentUpdate, SurfaceChange::SurfaceChangeCase::kRelativeParent); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 820f248dbb..eb31e2eca1 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -91,7 +91,6 @@ constexpr static TestColor RED = {195, 63, 63, 255}; constexpr static TestColor LIGHT_RED = {255, 177, 177, 255}; constexpr static TestColor GREEN = {63, 195, 63, 255}; constexpr static TestColor BLUE = {63, 63, 195, 255}; -constexpr static TestColor DARK_GRAY = {63, 63, 63, 255}; constexpr static TestColor LIGHT_GRAY = {200, 200, 200, 255}; // Fill an RGBA_8888 formatted surface with a single color. @@ -1469,77 +1468,6 @@ protected: } } - void Test_DeferredTransaction() { - // Synchronization surface - constexpr static int SYNC_LAYER = 2; - auto syncSurfaceControl = mComposerClient->createSurface(String8("Sync Test Surface"), 1, 1, - PIXEL_FORMAT_RGBA_8888, 0); - ASSERT_TRUE(syncSurfaceControl != nullptr); - ASSERT_TRUE(syncSurfaceControl->isValid()); - - fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); - - { - TransactionScope ts(*sFakeComposer); - ts.setLayer(syncSurfaceControl, INT32_MAX - 1); - ts.setPosition(syncSurfaceControl, mDisplayWidth - 2, mDisplayHeight - 2); - ts.show(syncSurfaceControl); - } - auto referenceFrame = mBaseFrame; - referenceFrame.push_back(makeSimpleRect(mDisplayWidth - 2, mDisplayHeight - 2, - mDisplayWidth - 1, mDisplayHeight - 1)); - referenceFrame[SYNC_LAYER].mSwapCount = 1; - EXPECT_EQ(2, sFakeComposer->getFrameCount()); - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); - - // set up two deferred transactions on different frames - these should not yield composited - // frames - { - TransactionScope ts(*sFakeComposer); - ts.setAlpha(mFGSurfaceControl, 0.75); - ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl, - syncSurfaceControl->getSurface()->getNextFrameNumber()); - } - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); - - { - TransactionScope ts(*sFakeComposer); - ts.setPosition(mFGSurfaceControl, 128, 128); - ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl, - syncSurfaceControl->getSurface()->getNextFrameNumber() + - 1); - } - EXPECT_EQ(4, sFakeComposer->getFrameCount()); - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); - - // should trigger the first deferred transaction, but not the second one - fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); - sFakeComposer->runVSyncAndWait(); - EXPECT_EQ(5, sFakeComposer->getFrameCount()); - - referenceFrame[FG_LAYER].mPlaneAlpha = 0.75f; - referenceFrame[SYNC_LAYER].mSwapCount++; - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); - - // should show up immediately since it's not deferred - { - TransactionScope ts(*sFakeComposer); - ts.setAlpha(mFGSurfaceControl, 1.0); - } - referenceFrame[FG_LAYER].mPlaneAlpha = 1.f; - EXPECT_EQ(6, sFakeComposer->getFrameCount()); - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); - - // trigger the second deferred transaction - fillSurfaceRGBA8(syncSurfaceControl, DARK_GRAY); - sFakeComposer->runVSyncAndWait(); - // TODO: Compute from layer size? - referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{128, 128, 128 + 64, 128 + 64}; - referenceFrame[SYNC_LAYER].mSwapCount++; - EXPECT_EQ(7, sFakeComposer->getFrameCount()); - EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); - } - void Test_SetRelativeLayer() { constexpr int RELATIVE_LAYER = 2; auto relativeSurfaceControl = mComposerClient->createSurface(String8("Test Surface"), 64, @@ -1625,10 +1553,6 @@ TEST_F(TransactionTest_2_1, DISABLED_LayerSetMatrix) { Test_LayerSetMatrix(); } -TEST_F(TransactionTest_2_1, DISABLED_DeferredTransaction) { - Test_DeferredTransaction(); -} - TEST_F(TransactionTest_2_1, DISABLED_SetRelativeLayer) { Test_SetRelativeLayer(); } @@ -1766,30 +1690,6 @@ protected: EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); } - void Test_ReparentChildren() { - { - TransactionScope ts(*Base::sFakeComposer); - ts.show(mChild); - ts.setPosition(mChild, 10, 10); - ts.setPosition(Base::mFGSurfaceControl, 64, 64); - } - auto referenceFrame = Base::mBaseFrame; - referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; - referenceFrame[CHILD_LAYER].mDisplayFrame = - hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; - EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); - - { - TransactionScope ts(*Base::sFakeComposer); - ts.reparentChildren(Base::mFGSurfaceControl, Base::mBGSurfaceControl); - } - - auto referenceFrame2 = referenceFrame; - referenceFrame2[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; - referenceFrame2[CHILD_LAYER].mDisplayFrame = hwc_rect_t{10, 10, 10 + 10, 10 + 10}; - EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); - } - // Regression test for b/37673612 void Test_ChildrenWithParentBufferTransform() { { @@ -1823,44 +1723,6 @@ protected: EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); } - void Test_Bug36858924() { - // Destroy the child layer - mChild.clear(); - - // Now recreate it as hidden - mChild = Base::mComposerClient->createSurface(String8("Child surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eHidden, - Base::mFGSurfaceControl->getHandle()); - - // Show the child layer in a deferred transaction - { - TransactionScope ts(*Base::sFakeComposer); - ts.deferTransactionUntil_legacy(mChild, Base::mFGSurfaceControl, - Base::mFGSurfaceControl->getSurface() - ->getNextFrameNumber()); - ts.show(mChild); - } - - // Render the foreground surface a few times - // - // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the - // third frame because SurfaceFlinger would never process the deferred transaction and would - // therefore never acquire/release the first buffer - ALOGI("Filling 1"); - fillSurfaceRGBA8(Base::mFGSurfaceControl, GREEN); - Base::sFakeComposer->runVSyncAndWait(); - ALOGI("Filling 2"); - fillSurfaceRGBA8(Base::mFGSurfaceControl, BLUE); - Base::sFakeComposer->runVSyncAndWait(); - ALOGI("Filling 3"); - fillSurfaceRGBA8(Base::mFGSurfaceControl, RED); - Base::sFakeComposer->runVSyncAndWait(); - ALOGI("Filling 4"); - fillSurfaceRGBA8(Base::mFGSurfaceControl, GREEN); - Base::sFakeComposer->runVSyncAndWait(); - } - sp<SurfaceControl> mChild; }; @@ -1886,19 +1748,11 @@ TEST_F(ChildLayerTest_2_1, DISABLED_LayerAlpha) { Test_LayerAlpha(); } -TEST_F(ChildLayerTest_2_1, DISABLED_ReparentChildren) { - Test_ReparentChildren(); -} - // Regression test for b/37673612 TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) { Test_ChildrenWithParentBufferTransform(); } -TEST_F(ChildLayerTest_2_1, DISABLED_Bug36858924) { - Test_Bug36858924(); -} - template <typename FakeComposerService> class ChildColorLayerTest : public ChildLayerTest<FakeComposerService> { using Base = ChildLayerTest<FakeComposerService>; diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 7cc0032bc8..b4a1481e9c 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -44,7 +44,7 @@ namespace { constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID(111); constexpr PhysicalDisplayId EXTERNAL_DISPLAY_ID(222); constexpr PhysicalDisplayId DISPLAY_ID_64BIT(0xabcd12349876fedcULL); - +constexpr std::chrono::duration VSYNC_PERIOD(16ms); class MockVSyncSource : public VSyncSource { public: const char* getName() const override { return "test"; } @@ -166,11 +166,14 @@ void EventThreadTest::createThread(std::unique_ptr<VSyncSource> source) { mThrottleVsyncCallRecorder.getInvocable()(expectedVsyncTimestamp, uid); return (uid == mThrottledConnectionUid); }; + const auto getVsyncPeriod = [](uid_t uid) { + return VSYNC_PERIOD.count(); + }; mThread = std::make_unique<impl::EventThread>(std::move(source), /*tokenManager=*/nullptr, mInterceptVSyncCallRecorder.getInvocable(), - throttleVsync); + throttleVsync, getVsyncPeriod); // EventThread should register itself as VSyncSource callback. mCallback = expectVSyncSetCallbackCallReceived(); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp index abecd4b45b..9c6ad06e1d 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -118,11 +118,8 @@ void RefreshRateSelectionTest::setParent(Layer* child, Layer* parent) { } void RefreshRateSelectionTest::commitTransaction(Layer* layer) { - layer->pushPendingState(); auto c = layer->getCurrentState(); - if (layer->applyPendingStates(&c)) { - layer->commitTransaction(c); - } + layer->commitTransaction(c); } void RefreshRateSelectionTest::setupScheduler() { diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 7e602a29a0..c088ddc971 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -122,7 +122,6 @@ protected: void addChild(sp<Layer> layer, sp<Layer> child); void removeChild(sp<Layer> layer, sp<Layer> child); - void reparentChildren(sp<Layer> layer, sp<Layer> child); void commitTransaction(); TestableSurfaceFlinger mFlinger; @@ -152,17 +151,10 @@ void SetFrameRateTest::removeChild(sp<Layer> layer, sp<Layer> child) { layer.get()->removeChild(child.get()); } -void SetFrameRateTest::reparentChildren(sp<Layer> parent, sp<Layer> newParent) { - parent.get()->reparentChildren(newParent); -} - void SetFrameRateTest::commitTransaction() { for (auto layer : mLayers) { - layer->pushPendingState(); auto c = layer->getCurrentState(); - if (layer->applyPendingStates(&c)) { - layer->commitTransaction(c); - } + layer->commitTransaction(c); } } @@ -433,41 +425,6 @@ TEST_P(SetFrameRateTest, SetAndGetParentNotInTree) { EXPECT_EQ(FRAME_RATE_NO_VOTE, child2_1->getFrameRateForLayerTree()); } -TEST_P(SetFrameRateTest, SetAndGetReparentChildren) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto parent2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - - child2->setFrameRate(FRAME_RATE_VOTE1); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent2->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - reparentChildren(parent, parent2); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, parent2->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - child2->setFrameRate(FRAME_RATE_NO_VOTE); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent2->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest, testing::Values(std::make_shared<BufferQueueLayerFactory>(), std::make_shared<BufferStateLayerFactory>(), diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index b5ef0a1334..ea1ce47b70 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -60,11 +60,8 @@ public: } void commitTransaction(Layer* layer) { - layer->pushPendingState(); auto c = layer->getCurrentState(); - if (layer->applyPendingStates(&c)) { - layer->commitTransaction(c); - } + layer->commitTransaction(c); } void setupScheduler() { @@ -151,4 +148,4 @@ TEST_F(TransactionFrameTracerTest, BLASTTransactionSendsFrameTracerEvents) { BLASTTransactionSendsFrameTracerEvents(); } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index c75538f476..09a1c2af75 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -60,13 +60,8 @@ public: } void commitTransaction(Layer* layer) { - layer->pushPendingState(); - // After pushing the state, the currentState should not store any BufferlessSurfaceFrames - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); auto c = layer->getCurrentState(); - if (layer->applyPendingStates(&c)) { - layer->commitTransaction(c); - } + layer->commitTransaction(c); } void setupScheduler() { @@ -283,69 +278,6 @@ public: EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState()); } - void MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken() { - sp<BufferStateLayer> layer = createBufferStateLayer(); - layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, - 10); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto bufferlessSurfaceFrame1 = - layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); - - layer->pushPendingState(); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - - layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, - 12); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto bufferlessSurfaceFrame2 = - layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 2); - - commitTransaction(layer.get()); - - EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); - EXPECT_EQ(false, bufferlessSurfaceFrame1->getIsBuffer()); - EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState()); - EXPECT_EQ(10, bufferlessSurfaceFrame1->getActuals().endTime); - - EXPECT_EQ(2, bufferlessSurfaceFrame2->getToken()); - EXPECT_EQ(false, bufferlessSurfaceFrame2->getIsBuffer()); - EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); - EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime); - } - - void MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken() { - sp<BufferStateLayer> layer = createBufferStateLayer(); - layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, - 10); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto bufferlessSurfaceFrame1 = - layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); - - layer->pushPendingState(); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - - layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, - 12); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto bufferlessSurfaceFrame2 = - layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); - - commitTransaction(layer.get()); - - EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); - EXPECT_EQ(false, bufferlessSurfaceFrame1->getIsBuffer()); - EXPECT_EQ(PresentState::Unknown, bufferlessSurfaceFrame1->getPresentState()); - - EXPECT_EQ(1, bufferlessSurfaceFrame2->getToken()); - EXPECT_EQ(false, bufferlessSurfaceFrame2->getIsBuffer()); - EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); - EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime); - } - void PendingSurfaceFramesRemovedAfterClassification() { sp<BufferStateLayer> layer = createBufferStateLayer(); @@ -529,16 +461,6 @@ TEST_F(TransactionSurfaceFrameTest, MultipleSurfaceFramesPresentedTogether) { MultipleSurfaceFramesPresentedTogether(); } -TEST_F(TransactionSurfaceFrameTest, - MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken) { - MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken(); -} - -TEST_F(TransactionSurfaceFrameTest, - MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken) { - MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken(); -} - TEST_F(TransactionSurfaceFrameTest, PendingSurfaceFramesRemovedAfterClassification) { PendingSurfaceFramesRemovedAfterClassification(); } @@ -552,4 +474,4 @@ TEST_F(TransactionSurfaceFrameTest, MultipleCommitsBeforeLatch) { MultipleCommitsBeforeLatch(); } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 3cbfed98f5..8c448e2f96 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -126,7 +126,7 @@ public: const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; - EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) + ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare)) << "pixel @ (" << x + i << ", " << y + j << "): " << "expected (" << color << "), " << "got (" << Color{src[0], src[1], src[2], src[3]} << ")"; @@ -161,6 +161,22 @@ public: ASSERT_EQ(NO_ERROR, s->unlockAndPost()); } } + + static void setFrame(Transaction& t, const sp<SurfaceControl>& sc, Rect source, Rect dest, + int32_t transform = 0) { + uint32_t sourceWidth = source.getWidth(); + uint32_t sourceHeight = source.getHeight(); + + if (transform & ui::Transform::ROT_90) { + std::swap(sourceWidth, sourceHeight); + } + + float dsdx = dest.getWidth() / static_cast<float>(sourceWidth); + float dsdy = dest.getHeight() / static_cast<float>(sourceHeight); + + t.setMatrix(sc, dsdx, 0, 0, dsdy); + t.setPosition(sc, dest.left, dest.top); + } }; enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY }; diff --git a/services/vibratorservice/VibratorManagerHalWrapper.cpp b/services/vibratorservice/VibratorManagerHalWrapper.cpp index a9d499de1d..6e660e7e41 100644 --- a/services/vibratorservice/VibratorManagerHalWrapper.cpp +++ b/services/vibratorservice/VibratorManagerHalWrapper.cpp @@ -30,7 +30,7 @@ constexpr int32_t SINGLE_VIBRATOR_ID = 0; const constexpr char* MISSING_VIBRATOR_MESSAGE_PREFIX = "No vibrator with id="; HalResult<void> LegacyManagerHalWrapper::ping() { - auto pingFn = [](std::shared_ptr<HalWrapper> hal) { return hal->ping(); }; + auto pingFn = [](HalWrapper* hal) { return hal->ping(); }; return mController->doWithRetry<void>(pingFn, "ping"); } diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h index 354e56ca68..6c31e2b882 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h @@ -30,7 +30,7 @@ namespace vibrator { std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler); template <typename T> -using HalFunction = std::function<T(std::shared_ptr<HalWrapper>)>; +using HalFunction = std::function<T(HalWrapper*)>; // Controller for Vibrator HAL handle. // This relies on a given Connector to connect to the underlying Vibrator HAL service and reconnects @@ -64,8 +64,7 @@ public: */ Info getInfo() { static Info sDefaultInfo = InfoCache().get(); - return apply<Info>([](std::shared_ptr<HalWrapper> hal) { return hal->getInfo(); }, - sDefaultInfo, "getInfo"); + return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo"); } /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the @@ -103,7 +102,7 @@ private: } for (int i = 0; i < MAX_RETRIES; i++) { - T result = halFn(hal); + T result = halFn(hal.get()); if (result.checkAndLogFailure(functionName)) { tryReconnect(); } else { @@ -111,7 +110,7 @@ private: } } - return halFn(hal); + return halFn(hal.get()); } }; diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp index 279496a8b8..8e77bc57f3 100644 --- a/services/vibratorservice/test/VibratorHalControllerTest.cpp +++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp @@ -40,11 +40,9 @@ using namespace android; using namespace std::chrono_literals; using namespace testing; -static const auto ON_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { - return hal->on(10ms, []() {}); -}; -static const auto OFF_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->off(); }; -static const auto PING_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->ping(); }; +static const auto ON_FN = [](vibrator::HalWrapper* hal) { return hal->on(10ms, []() {}); }; +static const auto OFF_FN = [](vibrator::HalWrapper* hal) { return hal->off(); }; +static const auto PING_FN = [](vibrator::HalWrapper* hal) { return hal->ping(); }; // ------------------------------------------------------------------------------------------------- @@ -233,7 +231,7 @@ TEST_F(VibratorHalControllerTest, TestScheduledCallbackSurvivesReconnection) { std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get()); - auto onFn = [&](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->on(10ms, callback); }; + auto onFn = [&](vibrator::HalWrapper* hal) { return hal->on(10ms, callback); }; ASSERT_TRUE(mController->doWithRetry<void>(onFn, "on").isOk()); ASSERT_TRUE(mController->doWithRetry<void>(PING_FN, "ping").isFailed()); mMockHal.reset(); diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp index d1db82b4ca..af0cdb85b1 100644 --- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp @@ -644,7 +644,6 @@ TEST_F(VibratorHalWrapperAidlTest, TestPerformPwleEffect) { .Times(Exactly(2)) .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) .WillRepeatedly(DoAll(TriggerCallbackInArg1(), Return(Status()))); - ; } std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>(); diff --git a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp index 3de157667c..548d02817a 100644 --- a/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorManagerHalWrapperAidlTest.cpp @@ -40,7 +40,7 @@ using android::hardware::vibrator::PrimitivePwle; using namespace android; using namespace testing; -static const auto OFF_FN = [](std::shared_ptr<vibrator::HalWrapper> hal) { return hal->off(); }; +static const auto OFF_FN = [](vibrator::HalWrapper* hal) { return hal->off(); }; class MockBinder : public BBinder { public: diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index 020b520a7c..8d6681c9f4 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -1086,7 +1086,8 @@ VkResult CreateSwapchainKHR(VkDevice device, ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)", strerror(-err), err); - err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, -1); + err = + window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1}); if (err != android::OK) { ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)", strerror(-err), err); |