summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-11 15:43:34 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-11 15:43:34 +0000
commitafc35d4f699f7c1381798211e81b981c9ff8df3e (patch)
treec5509fb9771d705785e19c2828343af782e59240
parent0b8eb47db7d05c77cd2ac1950c7d524e4319f26c (diff)
parent8f4e41d679d67436ee3868cab8785a35b3cc613f (diff)
downloadnative-afc35d4f699f7c1381798211e81b981c9ff8df3e.tar.gz
Snap for 8712302 from 8f4e41d679d67436ee3868cab8785a35b3cc613f to tm-frc-art-release
Change-Id: I88a6fd208081959943095954754607240a17ef30
-rw-r--r--cmds/dumpstate/dumpstate.cpp4
-rw-r--r--cmds/dumpsys/tests/dumpsys_test.cpp1
-rw-r--r--headers/media_plugin/media/openmax/OMX_IndexExt.h1
-rw-r--r--include/input/Input.h2
-rw-r--r--libs/arect/Android.bp7
-rw-r--r--libs/binder/Android.bp4
-rw-r--r--libs/binder/IServiceManager.cpp19
-rw-r--r--libs/binder/include/binder/IServiceManager.h6
-rw-r--r--libs/dumputils/Android.bp6
-rw-r--r--libs/dumputils/dump_utils.cpp45
-rw-r--r--libs/dumputils/include/dumputils/dump_utils.h2
-rw-r--r--libs/fakeservicemanager/ServiceManager.cpp4
-rw-r--r--libs/fakeservicemanager/ServiceManager.h4
-rw-r--r--libs/gui/SurfaceComposerClient.cpp7
-rw-r--r--libs/gui/WindowInfo.cpp8
-rw-r--r--libs/gui/aidl/android/gui/ISurfaceComposer.aidl5
-rw-r--r--libs/gui/include/gui/WindowInfo.h2
-rw-r--r--libs/gui/tests/WindowInfo_test.cpp2
-rw-r--r--libs/input/Input.cpp71
-rw-r--r--libs/shaders/TEST_MAPPING10
-rw-r--r--libs/shaders/shaders.cpp9
-rw-r--r--libs/shaders/tests/Android.bp48
-rw-r--r--libs/shaders/tests/shaders_test.cpp98
-rw-r--r--libs/ui/Android.bp4
-rw-r--r--services/gpuservice/gpuwork/bpfprogs/include/gpuwork/gpu_work.h2
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp6
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp52
-rw-r--r--services/surfaceflinger/BufferLayer.cpp2
-rw-r--r--services/surfaceflinger/BufferStateLayer.cpp4
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h2
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h6
-rw-r--r--services/surfaceflinger/CompositionEngine/src/Output.cpp1
-rw-r--r--services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp10
-rw-r--r--services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp6
-rw-r--r--services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp11
-rw-r--r--services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp2
-rw-r--r--services/surfaceflinger/Layer.cpp1
-rw-r--r--services/surfaceflinger/Layer.h3
-rw-r--r--services/surfaceflinger/Scheduler/EventThread.cpp5
-rw-r--r--services/surfaceflinger/Scheduler/EventThread.h3
-rw-r--r--services/surfaceflinger/Scheduler/OneShotTimer.cpp23
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp1
-rw-r--r--services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp18
-rw-r--r--services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp34
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,