diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-11 15:43:34 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-11 15:43:34 +0000 |
commit | afc35d4f699f7c1381798211e81b981c9ff8df3e (patch) | |
tree | c5509fb9771d705785e19c2828343af782e59240 | |
parent | 0b8eb47db7d05c77cd2ac1950c7d524e4319f26c (diff) | |
parent | 8f4e41d679d67436ee3868cab8785a35b3cc613f (diff) | |
download | native-afc35d4f699f7c1381798211e81b981c9ff8df3e.tar.gz |
Snap for 8712302 from 8f4e41d679d67436ee3868cab8785a35b3cc613f to tm-frc-art-release
Change-Id: I88a6fd208081959943095954754607240a17ef30
44 files changed, 513 insertions, 48 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 890c15f895..2b94b71a7f 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -1648,7 +1648,7 @@ static Dumpstate::RunStatus dumpstate() { DumpPacketStats(); - RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"}); + RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"}); DoKmsg(); @@ -2084,7 +2084,7 @@ Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) { int timeout_failures = 0; bool dalvik_found = false; - const std::set<int> hal_pids = get_interesting_hal_pids(); + const std::set<int> hal_pids = get_interesting_pids(); struct dirent* d; while ((d = readdir(proc.get()))) { diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index 49c1318945..f0c19b93ec 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -65,6 +65,7 @@ class ServiceManagerMock : public IServiceManager { const sp<LocalRegistrationCallback>&)); MOCK_METHOD2(unregisterForNotifications, status_t(const String16&, const sp<LocalRegistrationCallback>&)); + MOCK_METHOD0(getServiceDebugInfo, std::vector<ServiceDebugInfo>()); protected: MOCK_METHOD0(onAsBinder, IBinder*()); }; diff --git a/headers/media_plugin/media/openmax/OMX_IndexExt.h b/headers/media_plugin/media/openmax/OMX_IndexExt.h index 07bd749f6c..0af40dd28e 100644 --- a/headers/media_plugin/media/openmax/OMX_IndexExt.h +++ b/headers/media_plugin/media/openmax/OMX_IndexExt.h @@ -104,6 +104,7 @@ typedef enum OMX_INDEXEXTTYPE { OMX_IndexConfigLatency, /**< reference: OMX_PARAM_U32TYPE */ OMX_IndexConfigLowLatency, /**< reference: OMX_CONFIG_BOOLEANTYPE */ OMX_IndexConfigAndroidTunnelPeek, /**< reference: OMX_CONFIG_BOOLEANTYPE */ + OMX_IndexConfigAndroidTunnelPeekLegacyMode, /**< reference: OMX_CONFIG_BOOLEANTYPE */ OMX_IndexExtOtherEndUnused, /* Time configurations */ diff --git a/include/input/Input.h b/include/input/Input.h index b23a9518f7..e7d68fc349 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -837,6 +837,8 @@ protected: std::vector<PointerCoords> mSamplePointerCoords; }; +std::ostream& operator<<(std::ostream& out, const MotionEvent& event); + /* * Focus events. */ diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp index 41b34605f7..76e3e66749 100644 --- a/libs/arect/Android.bp +++ b/libs/arect/Android.bp @@ -39,9 +39,16 @@ ndk_headers { cc_library_headers { name: "libarect_headers", + vendor_available: true, + min_sdk_version: "29", // TODO(b/153609531): remove when no longer needed. native_bridge_supported: true, export_include_dirs: ["include"], + apex_available: [ + "//apex_available:platform", + "com.android.media", + "com.android.media.swcodec", + ], } cc_library_static { diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp index 63d87dae5a..d8d2cf2652 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -226,6 +226,10 @@ cc_library { ], afdo: true, + + header_abi_checker: { + diff_flags: ["-allow-adding-removing-weak-symbols"], + }, } cc_defaults { diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index ea2f8d2274..fd2d86857e 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -99,6 +99,8 @@ public: status_t unregisterForNotifications(const String16& service, const sp<AidlRegistrationCallback>& cb) override; + + std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override; // for legacy ABI const String16& getInterfaceDescriptor() const override { return mTheRealServiceManager->getInterfaceDescriptor(); @@ -543,6 +545,23 @@ status_t ServiceManagerShim::unregisterForNotifications(const String16& name, return OK; } +std::vector<IServiceManager::ServiceDebugInfo> ServiceManagerShim::getServiceDebugInfo() { + std::vector<os::ServiceDebugInfo> serviceDebugInfos; + std::vector<IServiceManager::ServiceDebugInfo> ret; + if (Status status = mTheRealServiceManager->getServiceDebugInfo(&serviceDebugInfos); + !status.isOk()) { + ALOGW("%s Failed to get ServiceDebugInfo", __FUNCTION__); + return ret; + } + for (const auto& serviceDebugInfo : serviceDebugInfos) { + IServiceManager::ServiceDebugInfo retInfo; + retInfo.pid = serviceDebugInfo.debugPid; + retInfo.name = serviceDebugInfo.name; + ret.emplace_back(retInfo); + } + return ret; +} + #ifndef __ANDROID__ // ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API. // The internal implementation of the AIDL interface android::os::IServiceManager calls into diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index bb55831ec2..413c97f349 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -134,6 +134,12 @@ public: virtual status_t unregisterForNotifications(const String16& name, const sp<LocalRegistrationCallback>& callback) = 0; + + struct ServiceDebugInfo { + std::string name; + int pid; + }; + virtual std::vector<ServiceDebugInfo> getServiceDebugInfo() = 0; }; sp<IServiceManager> defaultServiceManager(); diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp index acda402993..09fbdea0e8 100644 --- a/libs/dumputils/Android.bp +++ b/libs/dumputils/Android.bp @@ -26,6 +26,7 @@ cc_library { shared_libs: [ "libbase", + "libbinder", "libhidlbase", "liblog", "libutils", @@ -33,7 +34,10 @@ cc_library { srcs: ["dump_utils.cpp"], - cflags: ["-Wall", "-Werror"], + cflags: [ + "-Wall", + "-Werror", + ], export_include_dirs: [ "include", diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index 29c788bca3..0f1a02a553 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -20,6 +20,7 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android/hidl/manager/1.0/IServiceManager.h> +#include <binder/IServiceManager.h> #include <dumputils/dump_utils.h> #include <log/log.h> @@ -52,8 +53,8 @@ static const char* debuggable_native_processes_to_dump[] = { NULL, }; -/* list of hal interface to dump containing process during native dumps */ -static const char* hal_interfaces_to_dump[] { +/* list of hidl hal interface to dump containing process during native dumps */ +static const char* hidl_hal_interfaces_to_dump[] { "android.hardware.audio@4.0::IDevicesFactory", "android.hardware.audio@5.0::IDevicesFactory", "android.hardware.audio@6.0::IDevicesFactory", @@ -82,6 +83,11 @@ static const char* hal_interfaces_to_dump[] { NULL, }; +/* list of hal interface to dump containing process during native dumps */ +static const std::vector<std::string> aidl_interfaces_to_dump { + "android.hardware.camera.provider.ICameraProvider", +}; + /* list of extra hal interfaces to dump containing process during native dumps */ // This is filled when dumpstate is called. static std::set<const std::string> extra_hal_interfaces_to_dump; @@ -104,7 +110,7 @@ static void read_extra_hals_to_dump_from_property() { // check if interface is included in either default hal list or extra hal list bool should_dump_hal_interface(const std::string& interface) { - for (const char** i = hal_interfaces_to_dump; *i; i++) { + for (const char** i = hidl_hal_interfaces_to_dump; *i; i++) { if (interface == *i) { return true; } @@ -130,14 +136,26 @@ bool should_dump_native_traces(const char* path) { return false; } -std::set<int> get_interesting_hal_pids() { +static void get_interesting_aidl_pids(std::set<int> &pids) { + using ServiceDebugInfo = android::IServiceManager::ServiceDebugInfo; + auto sm = android::defaultServiceManager(); + std::vector<ServiceDebugInfo> serviceDebugInfos = sm->getServiceDebugInfo(); + for (const auto & serviceDebugInfo : serviceDebugInfos) { + for (const auto &aidl_prefix : aidl_interfaces_to_dump) { + // Check for prefix match with aidl interface to dump + if (serviceDebugInfo.name.rfind(aidl_prefix, 0) == 0) { + pids.insert(serviceDebugInfo.pid); + } + } + } +} + +static void get_interesting_hidl_pids(std::set<int> &pids) { using android::hidl::manager::V1_0::IServiceManager; using android::sp; using android::hardware::Return; sp<IServiceManager> manager = IServiceManager::getService(); - std::set<int> pids; - read_extra_hals_to_dump_from_property(); Return<void> ret = manager->debugDump([&](auto& hals) { @@ -146,11 +164,9 @@ std::set<int> get_interesting_hal_pids() { continue; } - if (!should_dump_hal_interface(info.interfaceName)) { - continue; + if (should_dump_hal_interface(info.interfaceName)) { + pids.insert(info.pid); } - - pids.insert(info.pid); } }); @@ -158,7 +174,14 @@ std::set<int> get_interesting_hal_pids() { ALOGE("Could not get list of HAL PIDs: %s\n", ret.description().c_str()); } - return pids; // whether it was okay or not + return; +} + +std::set<int> get_interesting_pids() { + std::set<int> interesting_pids; + get_interesting_hidl_pids(interesting_pids); + get_interesting_aidl_pids(interesting_pids); + return interesting_pids; } bool IsZygote(int pid) { diff --git a/libs/dumputils/include/dumputils/dump_utils.h b/libs/dumputils/include/dumputils/dump_utils.h index 25f712733a..7c5329d01b 100644 --- a/libs/dumputils/include/dumputils/dump_utils.h +++ b/libs/dumputils/include/dumputils/dump_utils.h @@ -21,7 +21,7 @@ bool should_dump_native_traces(const char* path); -std::set<int> get_interesting_hal_pids(); +std::set<int> get_interesting_pids(); bool IsZygote(int pid); diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp index 61e4a98846..6c6d7f3641 100644 --- a/libs/fakeservicemanager/ServiceManager.cpp +++ b/libs/fakeservicemanager/ServiceManager.cpp @@ -94,4 +94,8 @@ status_t ServiceManager::unregisterForNotifications(const String16&, return INVALID_OPERATION; } +std::vector<IServiceManager::ServiceDebugInfo> ServiceManager::getServiceDebugInfo() { + std::vector<IServiceManager::ServiceDebugInfo> ret; + return ret; +} } // namespace android diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h index 6d6e008c4f..e0af5d4ba8 100644 --- a/libs/fakeservicemanager/ServiceManager.h +++ b/libs/fakeservicemanager/ServiceManager.h @@ -20,6 +20,7 @@ #include <map> #include <optional> +#include <vector> namespace android { @@ -58,6 +59,9 @@ public: status_t unregisterForNotifications(const String16& name, const sp<LocalRegistrationCallback>& callback) override; + + std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override; + private: std::map<String16, sp<IBinder>> mNameToService; }; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 501f8cf15c..47d801a78d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1497,6 +1497,13 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe releaseBufferIfOverwriting(*s); + if (buffer == nullptr) { + s->what &= ~layer_state_t::eBufferChanged; + s->bufferData = nullptr; + mContainsBuffer = false; + return *this; + } + std::shared_ptr<BufferData> bufferData = std::make_shared<BufferData>(); bufferData->buffer = buffer; uint64_t frameNumber = sc->resolveFrameNumber(optFrameNumber); diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp index 804ce4fac0..4e966d1393 100644 --- a/libs/gui/WindowInfo.cpp +++ b/libs/gui/WindowInfo.cpp @@ -76,7 +76,7 @@ bool WindowInfo::operator==(const WindowInfo& info) const { info.inputConfig == inputConfig && info.displayId == displayId && info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType && - info.layoutParamsFlags == layoutParamsFlags; + info.layoutParamsFlags == layoutParamsFlags && info.isClone == isClone; } status_t WindowInfo::writeToParcel(android::Parcel* parcel) const { @@ -124,7 +124,8 @@ status_t WindowInfo::writeToParcel(android::Parcel* parcel) const { parcel->write(touchableRegion) ?: parcel->writeBool(replaceTouchableRegionWithCrop) ?: parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?: - parcel->writeStrongBinder(windowToken); + parcel->writeStrongBinder(windowToken) ?: + parcel->writeBool(isClone); // clang-format on return status; } @@ -175,7 +176,8 @@ status_t WindowInfo::readFromParcel(const android::Parcel* parcel) { parcel->read(touchableRegion) ?: parcel->readBool(&replaceTouchableRegionWithCrop) ?: parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?: - parcel->readNullableStrongBinder(&windowToken); + parcel->readNullableStrongBinder(&windowToken) ?: + parcel->readBool(&isClone); // clang-format on if (status != OK) { diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl index a9977b0f45..b31b37bada 100644 --- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl +++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl @@ -54,10 +54,11 @@ interface ISurfaceComposer { */ void setPowerMode(IBinder display, int mode); - /* returns display statistics for a given display + /** + * Returns display statistics for a given display * intended to be used by the media framework to properly schedule * video frames */ - DisplayStatInfo getDisplayStats(IBinder display); + DisplayStatInfo getDisplayStats(@nullable IBinder display); /** * Get transactional state of given display. diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h index 0e1d25812e..169f7f022b 100644 --- a/libs/gui/include/gui/WindowInfo.h +++ b/libs/gui/include/gui/WindowInfo.h @@ -236,6 +236,8 @@ struct WindowInfo : public Parcelable { void setInputConfig(ftl::Flags<InputConfig> config, bool value); + bool isClone = false; + void addTouchableRegion(const Rect& region); bool touchableRegionContainsPoint(int32_t x, int32_t y) const; diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp index c51b244c50..99658ccd4b 100644 --- a/libs/gui/tests/WindowInfo_test.cpp +++ b/libs/gui/tests/WindowInfo_test.cpp @@ -71,6 +71,7 @@ TEST(WindowInfo, Parcelling) { i.applicationInfo.name = "ApplicationFooBar"; i.applicationInfo.token = new BBinder(); i.applicationInfo.dispatchingTimeoutMillis = 0x12345678ABCD; + i.isClone = true; Parcel p; i.writeToParcel(&p); @@ -101,6 +102,7 @@ TEST(WindowInfo, Parcelling) { ASSERT_EQ(i.replaceTouchableRegionWithCrop, i2.replaceTouchableRegionWithCrop); ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle); ASSERT_EQ(i.applicationInfo, i2.applicationInfo); + ASSERT_EQ(i.isClone, i2.isClone); } TEST(InputApplicationInfo, Parcelling) { diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp index fe1754c78b..13ca9ecd35 100644 --- a/libs/input/Input.cpp +++ b/libs/input/Input.cpp @@ -22,7 +22,9 @@ #include <inttypes.h> #include <string.h> +#include <android-base/logging.h> #include <android-base/stringprintf.h> +#include <cutils/compiler.h> #include <gui/constants.h> #include <input/DisplayViewport.h> #include <input/Input.h> @@ -542,7 +544,14 @@ void MotionEvent::setCursorPosition(float x, float y) { } const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { - return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; + if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) { + LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this; + } + const size_t position = getHistorySize() * getPointerCount() + pointerIndex; + if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) { + LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this; + } + return &mSamplePointerCoords[position]; } float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { @@ -555,7 +564,18 @@ float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( size_t pointerIndex, size_t historicalIndex) const { - return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; + if (CC_UNLIKELY(pointerIndex < 0 || pointerIndex >= getPointerCount())) { + LOG(FATAL) << __func__ << ": Invalid pointer index " << pointerIndex << " for " << *this; + } + if (CC_UNLIKELY(historicalIndex < 0 || historicalIndex > getHistorySize())) { + LOG(FATAL) << __func__ << ": Invalid historical index " << historicalIndex << " for " + << *this; + } + const size_t position = historicalIndex * getPointerCount() + pointerIndex; + if (CC_UNLIKELY(position < 0 || position >= mSamplePointerCoords.size())) { + LOG(FATAL) << __func__ << ": Invalid array index " << position << " for " << *this; + } + return &mSamplePointerCoords[position]; } float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, @@ -903,6 +923,53 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source, return out; } +std::ostream& operator<<(std::ostream& out, const MotionEvent& event) { + out << "MotionEvent { action=" << MotionEvent::actionToString(event.getAction()); + if (event.getActionButton() != 0) { + out << ", actionButton=" << std::to_string(event.getActionButton()); + } + const size_t pointerCount = event.getPointerCount(); + for (size_t i = 0; i < pointerCount; i++) { + out << ", id[" << i << "]=" << event.getPointerId(i); + float x = event.getX(i); + float y = event.getY(i); + if (x != 0 || y != 0) { + out << ", x[" << i << "]=" << x; + out << ", y[" << i << "]=" << y; + } + int toolType = event.getToolType(i); + if (toolType != AMOTION_EVENT_TOOL_TYPE_FINGER) { + out << ", toolType[" << i << "]=" << toolType; + } + } + if (event.getButtonState() != 0) { + out << ", buttonState=" << event.getButtonState(); + } + if (event.getClassification() != MotionClassification::NONE) { + out << ", classification=" << motionClassificationToString(event.getClassification()); + } + if (event.getMetaState() != 0) { + out << ", metaState=" << event.getMetaState(); + } + if (event.getEdgeFlags() != 0) { + out << ", edgeFlags=" << event.getEdgeFlags(); + } + if (pointerCount != 1) { + out << ", pointerCount=" << pointerCount; + } + if (event.getHistorySize() != 0) { + out << ", historySize=" << event.getHistorySize(); + } + out << ", eventTime=" << event.getEventTime(); + out << ", downTime=" << event.getDownTime(); + out << ", deviceId=" << event.getDeviceId(); + out << ", source=" << inputEventSourceToString(event.getSource()); + out << ", displayId=" << event.getDisplayId(); + out << ", eventId=" << event.getId(); + out << "}"; + return out; +} + // --- FocusEvent --- void FocusEvent::initialize(int32_t id, bool hasFocus) { diff --git a/libs/shaders/TEST_MAPPING b/libs/shaders/TEST_MAPPING new file mode 100644 index 0000000000..ad6514d201 --- /dev/null +++ b/libs/shaders/TEST_MAPPING @@ -0,0 +1,10 @@ +{ + "presubmit": [ + { + "name": "librenderengine_test" + }, + { + "name": "libshaders_test" + } + ] +} diff --git a/libs/shaders/shaders.cpp b/libs/shaders/shaders.cpp index 62745dc8d5..f80e93f6f8 100644 --- a/libs/shaders/shaders.cpp +++ b/libs/shaders/shaders.cpp @@ -469,12 +469,17 @@ std::vector<tonemap::ShaderUniform> buildLinearEffectUniforms( float currentDisplayLuminanceNits, float maxLuminance, AHardwareBuffer* buffer, aidl::android::hardware::graphics::composer3::RenderIntent renderIntent) { std::vector<tonemap::ShaderUniform> uniforms; - if (linearEffect.inputDataspace == linearEffect.outputDataspace) { + + const ui::Dataspace inputDataspace = linearEffect.fakeInputDataspace == ui::Dataspace::UNKNOWN + ? linearEffect.inputDataspace + : linearEffect.fakeInputDataspace; + + if (inputDataspace == linearEffect.outputDataspace) { uniforms.push_back({.name = "in_rgbToXyz", .value = buildUniformValue<mat4>(mat4())}); uniforms.push_back( {.name = "in_xyzToRgb", .value = buildUniformValue<mat4>(colorTransform)}); } else { - ColorSpace inputColorSpace = toColorSpace(linearEffect.inputDataspace); + ColorSpace inputColorSpace = toColorSpace(inputDataspace); ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace); uniforms.push_back({.name = "in_rgbToXyz", .value = buildUniformValue<mat4>(mat4(inputColorSpace.getRGBtoXYZ()))}); diff --git a/libs/shaders/tests/Android.bp b/libs/shaders/tests/Android.bp new file mode 100644 index 0000000000..cf671bcb7a --- /dev/null +++ b/libs/shaders/tests/Android.bp @@ -0,0 +1,48 @@ +// Copyright 2022 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_native_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_native_license"], +} + +cc_test { + name: "libshaders_test", + test_suites: ["device-tests"], + srcs: [ + "shaders_test.cpp", + ], + header_libs: [ + "libtonemap_headers", + ], + shared_libs: [ + "android.hardware.graphics.common-V3-ndk", + "android.hardware.graphics.composer3-V1-ndk", + "android.hardware.graphics.common@1.2", + "libnativewindow", + ], + static_libs: [ + "libarect", + "libgmock", + "libgtest", + "libmath", + "libshaders", + "libtonemap", + "libui-types", + ], +} diff --git a/libs/shaders/tests/shaders_test.cpp b/libs/shaders/tests/shaders_test.cpp new file mode 100644 index 0000000000..d45fb246c7 --- /dev/null +++ b/libs/shaders/tests/shaders_test.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "shaders/shaders.h" +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <math/mat4.h> +#include <tonemap/tonemap.h> +#include <ui/ColorSpace.h> +#include <cmath> + +namespace android { + +using testing::Contains; +using testing::HasSubstr; + +struct ShadersTest : public ::testing::Test {}; + +namespace { + +MATCHER_P2(UniformEq, name, value, "") { + return arg.name == name && arg.value == value; +} + +template <typename T, std::enable_if_t<std::is_trivially_copyable<T>::value, bool> = true> +std::vector<uint8_t> buildUniformValue(T value) { + std::vector<uint8_t> result; + result.resize(sizeof(value)); + std::memcpy(result.data(), &value, sizeof(value)); + return result; +} + +} // namespace + +TEST_F(ShadersTest, buildLinearEffectUniforms_selectsNoOpGamutMatrices) { + shaders::LinearEffect effect = + shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB_LINEAR, + .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, + .fakeInputDataspace = ui::Dataspace::UNKNOWN}; + + mat4 colorTransform = mat4::scale(vec4(.9, .9, .9, 1.)); + auto uniforms = + shaders::buildLinearEffectUniforms(effect, colorTransform, 1.f, 1.f, 1.f, nullptr, + aidl::android::hardware::graphics::composer3:: + RenderIntent::COLORIMETRIC); + EXPECT_THAT(uniforms, Contains(UniformEq("in_rgbToXyz", buildUniformValue<mat4>(mat4())))); + EXPECT_THAT(uniforms, + Contains(UniformEq("in_xyzToRgb", buildUniformValue<mat4>(colorTransform)))); +} + +TEST_F(ShadersTest, buildLinearEffectUniforms_selectsGamutTransformMatrices) { + shaders::LinearEffect effect = + shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB, + .outputDataspace = ui::Dataspace::DISPLAY_P3, + .fakeInputDataspace = ui::Dataspace::UNKNOWN}; + + ColorSpace inputColorSpace = ColorSpace::sRGB(); + ColorSpace outputColorSpace = ColorSpace::DisplayP3(); + auto uniforms = + shaders::buildLinearEffectUniforms(effect, mat4(), 1.f, 1.f, 1.f, nullptr, + aidl::android::hardware::graphics::composer3:: + RenderIntent::COLORIMETRIC); + EXPECT_THAT(uniforms, + Contains(UniformEq("in_rgbToXyz", + buildUniformValue<mat4>(mat4(inputColorSpace.getRGBtoXYZ()))))); + EXPECT_THAT(uniforms, + Contains(UniformEq("in_xyzToRgb", + buildUniformValue<mat4>(mat4(outputColorSpace.getXYZtoRGB()))))); +} + +TEST_F(ShadersTest, buildLinearEffectUniforms_respectsFakeInputDataspace) { + shaders::LinearEffect effect = + shaders::LinearEffect{.inputDataspace = ui::Dataspace::V0_SRGB, + .outputDataspace = ui::Dataspace::DISPLAY_P3, + .fakeInputDataspace = ui::Dataspace::DISPLAY_P3}; + + auto uniforms = + shaders::buildLinearEffectUniforms(effect, mat4(), 1.f, 1.f, 1.f, nullptr, + aidl::android::hardware::graphics::composer3:: + RenderIntent::COLORIMETRIC); + EXPECT_THAT(uniforms, Contains(UniformEq("in_rgbToXyz", buildUniformValue<mat4>(mat4())))); + EXPECT_THAT(uniforms, Contains(UniformEq("in_xyzToRgb", buildUniformValue<mat4>(mat4())))); +} + +} // namespace android diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index a9380c6e79..d138495036 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -243,6 +243,10 @@ cc_library_shared { ], afdo: true, + + header_abi_checker: { + diff_flags: ["-allow-adding-removing-weak-symbols"], + }, } cc_library_headers { diff --git a/services/gpuservice/gpuwork/bpfprogs/include/gpuwork/gpu_work.h b/services/gpuservice/gpuwork/bpfprogs/include/gpuwork/gpu_work.h index 57338f4c91..2affb60a0c 100644 --- a/services/gpuservice/gpuwork/bpfprogs/include/gpuwork/gpu_work.h +++ b/services/gpuservice/gpuwork/bpfprogs/include/gpuwork/gpu_work.h @@ -49,6 +49,8 @@ typedef struct { // negative duration. uint32_t error_count; + // Needed to make 32-bit arch struct size match 64-bit BPF arch struct size. + uint32_t padding0; } UidTrackingInfo; typedef struct { diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 4d25c5947b..5e9427ad87 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2507,7 +2507,7 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) { } void InputDispatcher::addDragEventLocked(const MotionEntry& entry) { - if (!mDragState) { + if (!mDragState || mDragState->dragWindow->getInfo()->displayId != entry.displayId) { return; } @@ -4765,9 +4765,11 @@ void InputDispatcher::setInputWindowsLocked( // If drag window is gone, it would receive a cancel event and broadcast the DRAG_END. We // could just clear the state here. - if (mDragState && + if (mDragState && mDragState->dragWindow->getInfo()->displayId == displayId && std::find(windowHandles.begin(), windowHandles.end(), mDragState->dragWindow) == windowHandles.end()) { + ALOGI("Drag window went away: %s", mDragState->dragWindow->getName().c_str()); + sendDropWindowCommandLocked(nullptr, 0, 0); mDragState.reset(); } } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 91a666c699..df4307101f 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -6407,6 +6407,58 @@ TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) { mSecondWindow->consumeMotionMove(); } +TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) { + performDrag(); + + // Update window of second display. + sp<FakeWindowHandle> windowInSecondary = + new FakeWindowHandle(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID); + mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); + + // Let second display has a touch state. + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, + MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, + AINPUT_SOURCE_TOUCHSCREEN) + .displayId(SECOND_DISPLAY_ID) + .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_FINGER) + .x(100) + .y(100)) + .build())); + windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, + SECOND_DISPLAY_ID, 0 /* expectedFlag */); + // Update window again. + mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {windowInSecondary}}}); + + // 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->consumeDragEvent(false, 50, 50); + + // 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(mSecondWindow->getToken()); + mWindow->assertNoEvents(); + mSecondWindow->assertNoEvents(); +} + class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {}; TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) { diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f8c53c338e..d9c89cd821 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -358,8 +358,6 @@ void BufferLayer::onPostComposition(const DisplayDevice* display, // composition. if (!mBufferInfo.mFrameLatencyNeeded) return; - mAlreadyDisplayedThisCompose = false; - // Update mFrameEventHistory. finalizeFrameEventHistory(glDoneFence, compositorTiming); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 1a5b925b13..fecf5ae059 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -79,10 +79,10 @@ void BufferStateLayer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFen // For example we can only use it if all the displays are client comp, and we need // to merge all the client comp fences. We could do this, but for now we just // disable the optimization when a layer is composed on multiple displays. - if (mAlreadyDisplayedThisCompose) { + if (mClearClientCompositionFenceOnLayerDisplayed) { mLastClientCompositionFence = nullptr; } else { - mAlreadyDisplayedThisCompose = true; + mClearClientCompositionFenceOnLayerDisplayed = true; } // The previous release fence notifies the client that SurfaceFlinger is done with the previous diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index 2e7a377feb..e65aa7393c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -147,6 +147,8 @@ public: bool hasProtectedLayers() const; + bool hasSolidColorLayers() const; + private: CachedSet() = default; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h index 29d33662ab..5aec7c2e88 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h @@ -248,6 +248,12 @@ public: bool isProtected() const { return getOutputLayer()->getLayerFE().getCompositionState()->hasProtectedContent; } + + bool hasSolidColorCompositionType() const { + return getOutputLayer()->getLayerFE().getCompositionState()->compositionType == + aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR; + } + float getFps() const { return getOutputLayer()->getLayerFE().getCompositionState()->fps; } void dump(std::string& result) const; diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index aac478de40..c3385a8a8b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1300,6 +1300,7 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( const auto& layerState = layer->getState(); const auto* layerFEState = layer->getLayerFE().getCompositionState(); auto& layerFE = layer->getLayerFE(); + layerFE.setWasClientComposed(nullptr); const Region clip(viewportRegion.intersect(layerState.visibleRegion)); ALOGV("Layer: %s", layerFE.getDebugName()); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 5ffbb7ff91..1bb9d0eb63 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -377,6 +377,7 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t auto requestedCompositionType = outputIndependentState->compositionType; if (requestedCompositionType == Composition::SOLID_COLOR && state.overrideInfo.buffer) { + // this should never happen, as SOLID_COLOR is skipped from caching, b/230073351 requestedCompositionType = Composition::DEVICE; } @@ -416,7 +417,12 @@ void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer, if (outputDependentState.overrideInfo.buffer != nullptr) { displayFrame = outputDependentState.overrideInfo.displayFrame; - sourceCrop = displayFrame.toFloatRect(); + sourceCrop = + FloatRect(0.f, 0.f, + static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer() + ->getWidth()), + static_cast<float>(outputDependentState.overrideInfo.buffer->getBuffer() + ->getHeight())); } ALOGV("Writing display frame [%d, %d, %d, %d]", displayFrame.left, displayFrame.top, @@ -790,7 +796,7 @@ std::vector<LayerFE::LayerSettings> OutputLayer::getOverrideCompositionList() co // framebuffer space of the override buffer to layer space. const ProjectionSpace& layerSpace = getOutput().getState().layerStackSpace; const ui::Transform transform = getState().overrideInfo.displaySpace.getTransform(layerSpace); - const Rect boundaries = transform.transform(getState().overrideInfo.displaySpace.getContent()); + const Rect boundaries = transform.transform(getState().overrideInfo.displayFrame); LayerFE::LayerSettings settings; settings.geometry = renderengine::Geometry{ diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index d15b0a7646..641b806aec 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -388,6 +388,12 @@ bool CachedSet::hasProtectedLayers() const { [](const Layer& layer) { return layer.getState()->isProtected(); }); } +bool CachedSet::hasSolidColorLayers() const { + return std::any_of(mLayers.cbegin(), mLayers.cend(), [](const Layer& layer) { + return layer.getState()->hasSolidColorCompositionType(); + }); +} + void CachedSet::dump(std::string& result) const { const auto now = std::chrono::steady_clock::now(); diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index 0918510eef..1062b700dd 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -316,7 +316,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers state.overrideInfo = { .buffer = mNewCachedSet->getBuffer(), .acquireFence = mNewCachedSet->getDrawFence(), - .displayFrame = mNewCachedSet->getBounds(), + .displayFrame = mNewCachedSet->getTextureBounds(), .dataspace = mNewCachedSet->getOutputDataspace(), .displaySpace = mNewCachedSet->getOutputSpace(), .damageRegion = Region::INVALID_REGION, @@ -356,7 +356,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers state.overrideInfo = { .buffer = currentLayerIter->getBuffer(), .acquireFence = currentLayerIter->getDrawFence(), - .displayFrame = currentLayerIter->getBounds(), + .displayFrame = currentLayerIter->getTextureBounds(), .dataspace = currentLayerIter->getOutputDataspace(), .displaySpace = currentLayerIter->getOutputSpace(), .damageRegion = Region(), @@ -498,6 +498,13 @@ void Flattener::buildCachedSets(time_point now) { } } + for (const CachedSet& layer : mLayers) { + if (layer.hasSolidColorLayers()) { + ATRACE_NAME("layer->hasSolidColorLayers()"); + return; + } + } + std::vector<Run> runs = findCandidateRuns(now); std::optional<Run> bestRun = findBestRun(runs); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 7038e8cda1..5290bd9cba 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -940,7 +940,7 @@ const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 8 84.f / 255.f}; const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044}; const Rect OutputLayerWriteStateToHWCTest::kOverrideDisplayFrame{1002, 1003, 1004, 20044}; -const FloatRect OutputLayerWriteStateToHWCTest::kOverrideSourceCrop{1002, 1003, 1004, 20044}; +const FloatRect OutputLayerWriteStateToHWCTest::kOverrideSourceCrop{0.f, 0.f, 4.f, 5.f}; const Region OutputLayerWriteStateToHWCTest::kOutputSpaceVisibleRegion{ Rect{1005, 1006, 1007, 1008}}; const Region OutputLayerWriteStateToHWCTest::kOverrideVisibleRegion{Rect{1006, 1007, 1008, 1009}}; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b1de9665d5..6ed4a94f25 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2391,6 +2391,7 @@ WindowInfo Layer::fillInputInfo(const ui::Transform& displayTransform, bool disp // If the layer is a clone, we need to crop the input region to cloned root to prevent // touches from going outside the cloned area. if (isClone()) { + info.isClone = true; if (const sp<Layer> clonedRoot = getClonedRoot()) { const Rect rect = displayTransform.transform(Rect{clonedRoot->mScreenBounds}); info.touchableRegion = info.touchableRegion.intersect(rect); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3988e51f84..24abad9b45 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -620,6 +620,7 @@ public: void setWasClientComposed(const sp<Fence>& fence) override { mLastClientCompositionFence = fence; + mClearClientCompositionFenceOnLayerDisplayed = false; } const char* getDebugName() const override; @@ -1035,7 +1036,7 @@ protected: mutable bool mDrawingStateModified = false; sp<Fence> mLastClientCompositionFence; - bool mAlreadyDisplayedThisCompose = false; + bool mClearClientCompositionFenceOnLayerDisplayed = false; private: virtual void setTransformHint(ui::Transform::RotationFlags) {} diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index cbea77e8fb..639ba5a3f1 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -177,6 +177,11 @@ void EventThreadConnection::onFirstRef() { } binder::Status EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) { + std::scoped_lock lock(mLock); + if (mChannel.initCheck() != NO_ERROR) { + return binder::Status::fromStatusT(NAME_NOT_FOUND); + } + outChannel->setReceiveFd(mChannel.moveReceiveFd()); outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); return binder::Status::ok(); diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index c406478c17..adb96fd462 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -112,7 +112,8 @@ public: private: virtual void onFirstRef(); EventThread* const mEventThread; - gui::BitTube mChannel; + std::mutex mLock; + gui::BitTube mChannel GUARDED_BY(mLock); std::vector<DisplayEventReceiver::Event> mPendingEvents; }; diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp index 9c6e56dfa8..3c8dc64f10 100644 --- a/services/surfaceflinger/Scheduler/OneShotTimer.cpp +++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp @@ -118,16 +118,17 @@ void OneShotTimer::loop() { auto triggerTime = mClock->now() + mInterval; state = TimerState::WAITING; while (true) { - mWaiting = true; - constexpr auto zero = std::chrono::steady_clock::duration::zero(); - // Wait for mInterval time to check if we need to reset or drop into the idle state. - struct timespec ts; - calculateTimeoutTime(std::chrono::nanoseconds(mInterval), &ts); - int result = sem_clockwait(&mSemaphore, CLOCK_MONOTONIC, &ts); - if (result && errno != ETIMEDOUT && errno != EINTR) { - std::stringstream ss; - ss << "sem_clockwait failed (" << errno << ")"; - LOG_ALWAYS_FATAL("%s", ss.str().c_str()); + // Wait until triggerTime time to check if we need to reset or drop into the idle state. + if (const auto triggerInterval = triggerTime - mClock->now(); triggerInterval > 0ns) { + mWaiting = true; + struct timespec ts; + calculateTimeoutTime(triggerInterval, &ts); + int result = sem_clockwait(&mSemaphore, CLOCK_MONOTONIC, &ts); + if (result && errno != ETIMEDOUT && errno != EINTR) { + std::stringstream ss; + ss << "sem_clockwait failed (" << errno << ")"; + LOG_ALWAYS_FATAL("%s", ss.str().c_str()); + } } mWaiting = false; @@ -136,7 +137,7 @@ void OneShotTimer::loop() { break; } - if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= zero) { + if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= 0ns) { triggerTimeout = true; state = TimerState::IDLE; break; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97d8aef88a..6a17cd8881 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6747,6 +6747,7 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( clientCompositionDisplay.orientation = rotation; clientCompositionDisplay.outputDataspace = dataspace; + clientCompositionDisplay.currentLuminanceNits = displayBrightnessNits; clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance; clientCompositionDisplay.renderIntent = static_cast<aidl::android::hardware::graphics::composer3::RenderIntent>(renderIntent); diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp index 027a15e3f6..a6d7f5834f 100644 --- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp +++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp @@ -465,4 +465,22 @@ TEST_F(ReleaseBufferCallbackTest, DISABLED_MergeBuffers_Different_Processes) { ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId)); } +TEST_F(ReleaseBufferCallbackTest, SetBuffer_OverwriteBuffersWithNull) { + sp<SurfaceControl> layer = createBufferStateLayer(); + ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper(); + + sp<GraphicBuffer> firstBuffer = getBuffer(); + ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber()); + + // Create transaction with a buffer. + Transaction transaction; + transaction.setBuffer(layer, firstBuffer, std::nullopt, firstBufferCallbackId.framenumber, + releaseCallback->getCallback()); + + // Call setBuffer on the same transaction with a null buffer. + transaction.setBuffer(layer, nullptr, std::nullopt, 0, releaseCallback->getCallback()); + + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId)); +} + } // namespace android diff --git a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp index 597e5e71a2..aafc323a9b 100644 --- a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp +++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp @@ -130,6 +130,40 @@ TEST_F(OneShotTimerTest, DISABLED_resetBackToBackTest) { EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value()); } +// TODO(b/186417847) This test is new and passes locally, but may be flaky +TEST_F(OneShotTimerTest, DISABLED_resetBackToBackSlowAdvanceTest) { + fake::FakeClock* clock = new fake::FakeClock(); + mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms, + mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable(), + std::unique_ptr<fake::FakeClock>(clock)); + mIdleTimer->start(); + EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); + + mIdleTimer->reset(); + EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value()); + EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value()); + + clock->advanceTime(200us); + mIdleTimer->reset(); + + // Normally we would check that the timer callbacks weren't invoked here + // after resetting the timer, but we need to precisely control the timing of + // this test, and checking that callbacks weren't invoked requires non-zero + // time. + + clock->advanceTime(1500us); + EXPECT_TRUE(mExpiredTimerCallback.waitForCall(1100us).has_value()); + mIdleTimer->reset(); + EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); + + mIdleTimer->stop(); + clock->advanceTime(2ms); + // Final quick check that no more callback were observed. + EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value()); + EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value()); +} + TEST_F(OneShotTimerTest, startNotCalledTest) { fake::FakeClock* clock = new fake::FakeClock(); mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms, |