summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--cmds/flatland/GLHelper.cpp10
-rw-r--r--include/input/Resampler.h41
-rw-r--r--libs/binder/IServiceManager.cpp77
-rw-r--r--libs/binder/ndk/Android.bp3
-rw-r--r--libs/binder/tests/binderRpcTest.cpp4
-rw-r--r--libs/graphicsenv/GraphicsEnv.cpp61
-rw-r--r--libs/gui/BLASTBufferQueue.cpp19
-rw-r--r--libs/gui/LayerState.cpp82
-rw-r--r--libs/gui/aidl/Android.bp3
-rw-r--r--libs/gui/aidl/android/gui/CaptureArgs.aidl56
-rw-r--r--libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl15
-rw-r--r--libs/gui/aidl/android/gui/LayerCaptureArgs.aidl13
-rw-r--r--libs/gui/include/gui/AidlStatusUtil.h26
-rw-r--r--libs/gui/include/gui/BLASTBufferQueue.h9
-rw-r--r--libs/gui/include/gui/DisplayCaptureArgs.h84
-rw-r--r--libs/gui/include/gui/FrameTimestamps.h2
-rw-r--r--libs/gui/include/gui/IGraphicBufferProducer.h2
-rw-r--r--libs/gui/include/gui/ISurfaceComposer.h9
-rw-r--r--libs/gui/include/gui/LayerState.h4
-rw-r--r--libs/gui/include/gui/Surface.h15
-rw-r--r--libs/gui/include/gui/view/Surface.h3
-rw-r--r--libs/gui/rust/aidl_types/src/lib.rs3
-rw-r--r--libs/gui/tests/Android.bp51
-rw-r--r--libs/gui/tests/BLASTBufferQueue_test.cpp3
-rw-r--r--libs/gui/tests/LibGuiMain.cpp38
-rw-r--r--libs/gui/tests/Surface_test.cpp11
-rw-r--r--libs/gui/tests/TestServer_test.cpp99
-rw-r--r--libs/gui/tests/testserver/TestServer.cpp114
-rw-r--r--libs/gui/tests/testserver/TestServer.h (renamed from libs/gui/include/gui/LayerCaptureArgs.h)27
-rw-r--r--libs/gui/tests/testserver/TestServerClient.cpp199
-rw-r--r--libs/gui/tests/testserver/TestServerClient.h42
-rw-r--r--libs/gui/tests/testserver/TestServerCommon.h43
-rw-r--r--libs/gui/tests/testserver/TestServerHost.cpp95
-rw-r--r--libs/gui/tests/testserver/TestServerHost.h38
-rw-r--r--libs/gui/tests/testserver/aidl/libgui_test_server/ITestServer.aidl12
-rw-r--r--libs/gui/view/Surface.cpp6
-rw-r--r--libs/input/Resampler.cpp104
-rw-r--r--libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp39
-rw-r--r--libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h6
-rw-r--r--libs/ui/include/ui/Fence.h2
-rw-r--r--libs/ui/include/ui/GraphicBuffer.h2
-rw-r--r--libs/ui/include/ui/GraphicBufferAllocator.h2
-rw-r--r--libs/ui/include/ui/GraphicBufferMapper.h2
-rw-r--r--libs/ui/include/ui/PixelFormat.h2
-rw-r--r--libs/ui/include/ui/Point.h2
-rw-r--r--libs/ui/include/ui/Rect.h2
-rw-r--r--libs/ui/include/ui/Region.h2
-rw-r--r--opengl/Android.bp12
-rw-r--r--services/inputflinger/PointerChoreographer.cpp5
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp3
-rw-r--r--services/inputflinger/include/InputReaderBase.h4
-rw-r--r--services/inputflinger/reader/mapper/TouchpadInputMapper.cpp6
-rw-r--r--services/inputflinger/reader/mapper/TouchpadInputMapper.h4
-rw-r--r--services/surfaceflinger/CompositionEngine/Android.bp1
-rw-r--r--services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp3
-rw-r--r--services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp71
-rw-r--r--services/surfaceflinger/Display/DisplayModeController.cpp61
-rw-r--r--services/surfaceflinger/Display/DisplayModeController.h17
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp13
-rw-r--r--services/surfaceflinger/DisplayDevice.h2
-rw-r--r--services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp13
-rw-r--r--services/surfaceflinger/DisplayHardware/AidlComposerHal.h3
-rw-r--r--services/surfaceflinger/DisplayHardware/ComposerHal.h2
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp11
-rw-r--r--services/surfaceflinger/DisplayHardware/FramebufferSurface.h8
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.cpp13
-rw-r--r--services/surfaceflinger/DisplayHardware/HWC2.h5
-rw-r--r--services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp5
-rw-r--r--services/surfaceflinger/DisplayHardware/HidlComposerHal.h2
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp5
-rw-r--r--services/surfaceflinger/FrontEnd/LayerHierarchy.cpp51
-rw-r--r--services/surfaceflinger/FrontEnd/LayerHierarchy.h3
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp6
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h3
-rw-r--r--services/surfaceflinger/Layer.cpp26
-rw-r--r--services/surfaceflinger/Layer.h6
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.cpp41
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp387
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h28
-rw-r--r--services/surfaceflinger/tests/BufferGenerator.cpp22
-rw-r--r--services/surfaceflinger/tests/Credentials_test.cpp2
-rw-r--r--services/surfaceflinger/tests/LayerState_test.cpp60
-rw-r--r--services/surfaceflinger/tests/LayerTypeTransaction_test.cpp3
-rw-r--r--services/surfaceflinger/tests/MirrorLayer_test.cpp3
-rw-r--r--services/surfaceflinger/tests/ScreenCapture_test.cpp59
-rw-r--r--services/surfaceflinger/tests/TextureFiltering_test.cpp33
-rw-r--r--services/surfaceflinger/tests/TransactionTestHarnesses.h17
-rw-r--r--services/surfaceflinger/tests/VirtualDisplay_test.cpp7
-rw-r--r--services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h2
-rw-r--r--services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h2
-rw-r--r--services/surfaceflinger/tests/utils/ScreenshotUtils.h4
93 files changed, 1669 insertions, 851 deletions
diff --git a/Android.bp b/Android.bp
index 4befb1b377..72311f0263 100644
--- a/Android.bp
+++ b/Android.bp
@@ -38,6 +38,7 @@ license {
cc_library_headers {
name: "native_headers",
+ vendor_available: true,
host_supported: true,
target: {
windows: {
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index c163095c50..77e732805e 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -18,6 +18,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/SurfaceComposerClient.h>
#include <ui/DisplayMode.h>
@@ -202,6 +203,14 @@ bool GLHelper::getShaderProgram(const char* name, GLuint* outPgm) {
bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
sp<GLConsumer>* glConsumer, EGLSurface* surface) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<GLConsumer> glc = new GLConsumer(name, GL_TEXTURE_EXTERNAL_OES, false, true);
+ glc->setDefaultBufferSize(w, h);
+ glc->getSurface()->setMaxDequeuedBufferCount(2);
+ glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
+
+ sp<ANativeWindow> anw = glc->getSurface();
+#else
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
@@ -212,6 +221,7 @@ bool GLHelper::createNamedSurfaceTexture(GLuint name, uint32_t w, uint32_t h,
glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
sp<ANativeWindow> anw = new Surface(producer);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
EGLSurface s = eglCreateWindowSurface(mDisplay, mConfig, anw.get(), nullptr);
if (s == EGL_NO_SURFACE) {
fprintf(stderr, "eglCreateWindowSurface error: %#x\n", eglGetError());
diff --git a/include/input/Resampler.h b/include/input/Resampler.h
index ff9c4b0868..5980d5d4c4 100644
--- a/include/input/Resampler.h
+++ b/include/input/Resampler.h
@@ -44,7 +44,7 @@ struct Resampler {
* samples by the end of the resampling. No other field of motionEvent should be modified.
* - If resampling does not occur, then motionEvent must not be modified in any way.
*/
- virtual void resampleMotionEvent(const std::chrono::nanoseconds resampleTime,
+ virtual void resampleMotionEvent(std::chrono::nanoseconds resampleTime,
MotionEvent& motionEvent,
const InputMessage* futureSample) = 0;
};
@@ -60,7 +60,7 @@ public:
* data, LegacyResampler will extrapolate. Otherwise, no resampling takes place and
* `motionEvent` is unmodified.
*/
- void resampleMotionEvent(const std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
+ void resampleMotionEvent(std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
const InputMessage* futureSample) override;
private:
@@ -72,10 +72,6 @@ private:
struct Sample {
std::chrono::nanoseconds eventTime;
Pointer pointer;
-
- Sample(const std::chrono::nanoseconds eventTime, const PointerProperties& properties,
- const PointerCoords& coords)
- : eventTime{eventTime}, pointer{properties, coords} {}
};
/**
@@ -99,17 +95,34 @@ private:
void updateLatestSamples(const MotionEvent& motionEvent);
/**
- * May add a sample at the end of motionEvent with eventTime equal to resampleTime, and
- * interpolated coordinates between the latest motionEvent sample and futureSample.
+ * Checks if there are necessary conditions to interpolate. For example, interpolation cannot
+ * take place if samples are too far apart in time. mLatestSamples must have at least one sample
+ * when canInterpolate is invoked.
+ */
+ bool canInterpolate(const InputMessage& futureSample) const;
+
+ /**
+ * Returns a sample interpolated between the latest sample of mLatestSamples and futureSample,
+ * if the conditions from canInterpolate are satisfied. Otherwise, returns nullopt.
+ * mLatestSamples must have at least one sample when attemptInterpolation is called.
*/
- void interpolate(const std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent,
- const InputMessage& futureSample) const;
+ std::optional<Sample> attemptInterpolation(std::chrono::nanoseconds resampleTime,
+ const InputMessage& futureSample) const;
/**
- * May add a sample at the end of motionEvent by extrapolating from the latest two samples. The
- * added sample either has eventTime equal to resampleTime, or an earlier time if resampleTime
- * is too far in the future.
+ * Checks if there are necessary conditions to extrapolate. That is, there are at least two
+ * samples in mLatestSamples, and delta is bounded within a time interval.
*/
- void extrapolate(const std::chrono::nanoseconds resampleTime, MotionEvent& motionEvent) const;
+ bool canExtrapolate() const;
+
+ /**
+ * Returns a sample extrapolated from the two samples of mLatestSamples, if the conditions from
+ * canExtrapolate are satisfied. The returned sample either has eventTime equal to resampleTime,
+ * or an earlier time if resampleTime is too far in the future. If canExtrapolate returns false,
+ * this function returns nullopt.
+ */
+ std::optional<Sample> attemptExtrapolation(std::chrono::nanoseconds resampleTime) const;
+
+ inline static void addSampleToMotionEvent(const Sample& sample, MotionEvent& motionEvent);
};
} // namespace android \ No newline at end of file
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 333f956556..c55dd9de1b 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -79,10 +79,9 @@ IServiceManager::IServiceManager() {}
IServiceManager::~IServiceManager() {}
// From the old libbinder IServiceManager interface to IServiceManager.
-class ServiceManagerShim : public IServiceManager
-{
+class CppBackendShim : public IServiceManager {
public:
- explicit ServiceManagerShim (const sp<AidlServiceManager>& impl);
+ explicit CppBackendShim(const sp<BackendUnifiedServiceManager>& impl);
sp<IBinder> getService(const String16& name) const override;
sp<IBinder> checkService(const String16& name) const override;
@@ -136,11 +135,11 @@ protected:
sp<RegistrationWaiter>* waiter);
// Directly get the service in a way that, for lazy services, requests the service to be started
- // if it is not currently started. This way, calls directly to ServiceManagerShim::getService
+ // if it is not currently started. This way, calls directly to CppBackendShim::getService
// will still have the 5s delay that is expected by a large amount of Android code.
//
- // When implementing ServiceManagerShim, use realGetService instead of
- // mUnifiedServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
+ // When implementing CppBackendShim, use realGetService instead of
+ // mUnifiedServiceManager->getService so that it can be overridden in CppServiceManagerHostShim.
virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
Service service;
Status status = mUnifiedServiceManager->getService2(name, &service);
@@ -155,7 +154,7 @@ protected:
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
- gDefaultServiceManager = sp<ServiceManagerShim>::make(getBackendUnifiedServiceManager());
+ gDefaultServiceManager = sp<CppBackendShim>::make(getBackendUnifiedServiceManager());
});
return gDefaultServiceManager;
@@ -279,16 +278,14 @@ void* openDeclaredPassthroughHal(const String16& interface, const String16& inst
// ----------------------------------------------------------------------
-ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl) {
- mUnifiedServiceManager = sp<BackendUnifiedServiceManager>::make(impl);
-}
+CppBackendShim::CppBackendShim(const sp<BackendUnifiedServiceManager>& impl)
+ : mUnifiedServiceManager(impl) {}
// This implementation could be simplified and made more efficient by delegating
// to waitForService. However, this changes the threading structure in some
// cases and could potentially break prebuilts. Once we have higher logistical
// complexity, this could be attempted.
-sp<IBinder> ServiceManagerShim::getService(const String16& name) const
-{
+sp<IBinder> CppBackendShim::getService(const String16& name) const {
static bool gSystemBootCompleted = false;
sp<IBinder> svc = checkService(name);
@@ -332,8 +329,7 @@ sp<IBinder> ServiceManagerShim::getService(const String16& name) const
return nullptr;
}
-sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
-{
+sp<IBinder> CppBackendShim::checkService(const String16& name) const {
Service ret;
if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
return nullptr;
@@ -341,16 +337,14 @@ sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
return ret.get<Service::Tag::binder>();
}
-status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
- bool allowIsolated, int dumpsysPriority)
-{
+status_t CppBackendShim::addService(const String16& name, const sp<IBinder>& service,
+ bool allowIsolated, int dumpsysPriority) {
Status status = mUnifiedServiceManager->addService(String8(name).c_str(), service,
allowIsolated, dumpsysPriority);
return status.exceptionCode();
}
-Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority)
-{
+Vector<String16> CppBackendShim::listServices(int dumpsysPriority) {
std::vector<std::string> ret;
if (!mUnifiedServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
return {};
@@ -364,8 +358,7 @@ Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority)
return res;
}
-sp<IBinder> ServiceManagerShim::waitForService(const String16& name16)
-{
+sp<IBinder> CppBackendShim::waitForService(const String16& name16) {
class Waiter : public android::os::BnServiceCallback {
Status onRegistration(const std::string& /*name*/,
const sp<IBinder>& binder) override {
@@ -454,7 +447,7 @@ sp<IBinder> ServiceManagerShim::waitForService(const String16& name16)
}
}
-bool ServiceManagerShim::isDeclared(const String16& name) {
+bool CppBackendShim::isDeclared(const String16& name) {
bool declared;
if (Status status = mUnifiedServiceManager->isDeclared(String8(name).c_str(), &declared);
!status.isOk()) {
@@ -465,7 +458,7 @@ bool ServiceManagerShim::isDeclared(const String16& name) {
return declared;
}
-Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interface) {
+Vector<String16> CppBackendShim::getDeclaredInstances(const String16& interface) {
std::vector<std::string> out;
if (Status status =
mUnifiedServiceManager->getDeclaredInstances(String8(interface).c_str(), &out);
@@ -483,7 +476,7 @@ Vector<String16> ServiceManagerShim::getDeclaredInstances(const String16& interf
return res;
}
-std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& name) {
+std::optional<String16> CppBackendShim::updatableViaApex(const String16& name) {
std::optional<std::string> declared;
if (Status status = mUnifiedServiceManager->updatableViaApex(String8(name).c_str(), &declared);
!status.isOk()) {
@@ -494,7 +487,7 @@ std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& nam
return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
}
-Vector<String16> ServiceManagerShim::getUpdatableNames(const String16& apexName) {
+Vector<String16> CppBackendShim::getUpdatableNames(const String16& apexName) {
std::vector<std::string> out;
if (Status status = mUnifiedServiceManager->getUpdatableNames(String8(apexName).c_str(), &out);
!status.isOk()) {
@@ -511,7 +504,7 @@ Vector<String16> ServiceManagerShim::getUpdatableNames(const String16& apexName)
return res;
}
-std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnectionInfo(
+std::optional<IServiceManager::ConnectionInfo> CppBackendShim::getConnectionInfo(
const String16& name) {
std::optional<os::ConnectionInfo> connectionInfo;
if (Status status =
@@ -526,8 +519,8 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnection
: std::nullopt;
}
-status_t ServiceManagerShim::registerForNotifications(const String16& name,
- const sp<AidlRegistrationCallback>& cb) {
+status_t CppBackendShim::registerForNotifications(const String16& name,
+ const sp<AidlRegistrationCallback>& cb) {
if (cb == nullptr) {
ALOGE("%s: null cb passed", __FUNCTION__);
return BAD_VALUE;
@@ -546,9 +539,9 @@ status_t ServiceManagerShim::registerForNotifications(const String16& name,
return OK;
}
-void ServiceManagerShim::removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb,
- ServiceCallbackMap::iterator* it,
- sp<RegistrationWaiter>* waiter) {
+void CppBackendShim::removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb,
+ ServiceCallbackMap::iterator* it,
+ sp<RegistrationWaiter>* waiter) {
std::vector<LocalRegistrationAndWaiter>& localRegistrationAndWaiters = (*it)->second;
for (auto lit = localRegistrationAndWaiters.begin();
lit != localRegistrationAndWaiters.end();) {
@@ -567,8 +560,8 @@ void ServiceManagerShim::removeRegistrationCallbackLocked(const sp<AidlRegistrat
}
}
-status_t ServiceManagerShim::unregisterForNotifications(const String16& name,
- const sp<AidlRegistrationCallback>& cb) {
+status_t CppBackendShim::unregisterForNotifications(const String16& name,
+ const sp<AidlRegistrationCallback>& cb) {
if (cb == nullptr) {
ALOGE("%s: null cb passed", __FUNCTION__);
return BAD_VALUE;
@@ -597,7 +590,7 @@ status_t ServiceManagerShim::unregisterForNotifications(const String16& name,
return OK;
}
-std::vector<IServiceManager::ServiceDebugInfo> ServiceManagerShim::getServiceDebugInfo() {
+std::vector<IServiceManager::ServiceDebugInfo> CppBackendShim::getServiceDebugInfo() {
std::vector<os::ServiceDebugInfo> serviceDebugInfos;
std::vector<IServiceManager::ServiceDebugInfo> ret;
if (Status status = mUnifiedServiceManager->getServiceDebugInfo(&serviceDebugInfos);
@@ -615,21 +608,21 @@ std::vector<IServiceManager::ServiceDebugInfo> ServiceManagerShim::getServiceDeb
}
#ifndef __ANDROID__
-// ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
+// CppBackendShim for host. Implements the old libbinder android::IServiceManager API.
// The internal implementation of the AIDL interface android::os::IServiceManager calls into
// on-device service manager.
-class ServiceManagerHostShim : public ServiceManagerShim {
+class CppServiceManagerHostShim : public CppBackendShim {
public:
- ServiceManagerHostShim(const sp<AidlServiceManager>& impl,
- const RpcDelegateServiceManagerOptions& options)
- : ServiceManagerShim(impl), mOptions(options) {}
- // ServiceManagerShim::getService is based on checkService, so no need to override it.
+ CppServiceManagerHostShim(const sp<AidlServiceManager>& impl,
+ const RpcDelegateServiceManagerOptions& options)
+ : CppBackendShim(sp<BackendUnifiedServiceManager>::make(impl)), mOptions(options) {}
+ // CppBackendShim::getService is based on checkService, so no need to override it.
sp<IBinder> checkService(const String16& name) const override {
return getDeviceService({String8(name).c_str()}, mOptions);
}
protected:
- // Override realGetService for ServiceManagerShim::waitForService.
+ // Override realGetService for CppBackendShim::waitForService.
Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) override {
*_aidl_return = getDeviceService({"-g", name}, mOptions);
return Status::ok();
@@ -650,7 +643,7 @@ sp<IServiceManager> createRpcDelegateServiceManager(
ALOGE("getDeviceService(\"manager\") returns non service manager");
return nullptr;
}
- return sp<ServiceManagerHostShim>::make(interface, options);
+ return sp<CppServiceManagerHostShim>::make(interface, options);
}
#endif
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 26c228d9a4..4e02aceb86 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -255,6 +255,9 @@ ndk_headers {
"include_cpp/android/*.h",
],
license: "NOTICE",
+ // These are intentionally not C. It's a mistake that they're in the NDK.
+ // See the bug above.
+ skip_verification: true,
}
ndk_library {
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index cd78e82322..3038de9a41 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1384,8 +1384,8 @@ TEST(BinderRpc, Java) {
sp<IServiceManager> sm = defaultServiceManager();
ASSERT_NE(nullptr, sm);
// Any Java service with non-empty getInterfaceDescriptor() would do.
- // Let's pick batteryproperties.
- auto binder = sm->checkService(String16("batteryproperties"));
+ // Let's pick activity.
+ auto binder = sm->checkService(String16("activity"));
ASSERT_NE(nullptr, binder);
auto descriptor = binder->getInterfaceDescriptor();
ASSERT_GE(descriptor.size(), 0u);
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 52383acb34..4c3f4a6428 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -83,6 +83,55 @@ static constexpr const char* kNativeLibrariesSystemConfigPath[] =
static const char* kLlndkLibrariesTxtPath = "/system/etc/llndk.libraries.txt";
+// List of libraries that were previously available via VNDK-SP,
+// and are now available via SPHAL.
+// On modern devices that lack the VNDK APEX, the device no longer
+// contains a helpful list of these libraries on the filesystem as above.
+// See system/sepolicy/vendor/file_contexts
+static const char* kFormerlyVndkspLibrariesList =
+ "android.hardware.common-V2-ndk.so:"
+ "android.hardware.common.fmq-V1-ndk.so:"
+ "android.hardware.graphics.allocator-V2-ndk.so:"
+ "android.hardware.graphics.common-V5-ndk.so:"
+ "android.hardware.graphics.common@1.0.so:"
+ "android.hardware.graphics.common@1.1.so:"
+ "android.hardware.graphics.common@1.2.so:"
+ "android.hardware.graphics.composer3-V1-ndk.so:"
+ "android.hardware.graphics.mapper@2.0.so:"
+ "android.hardware.graphics.mapper@2.1.so:"
+ "android.hardware.graphics.mapper@3.0.so:"
+ "android.hardware.graphics.mapper@4.0.so:"
+ "android.hardware.renderscript@1.0.so:"
+ "android.hidl.memory.token@1.0.so:"
+ "android.hidl.memory@1.0-impl.so:"
+ "android.hidl.memory@1.0.so:"
+ "android.hidl.safe_union@1.0.so:"
+ "libRSCpuRef.so:"
+ "libRSDriver.so:"
+ "libRS_internal.so:"
+ "libbacktrace.so:"
+ "libbase.so:"
+ "libbcinfo.so:"
+ "libblas.so:"
+ "libc++.so:"
+ "libcompiler_rt.so:"
+ "libcutils.so:"
+ "libdmabufheap.so:"
+ "libft2.so:"
+ "libgralloctypes.so:"
+ "libhardware.so:"
+ "libhidlbase.so:"
+ "libhidlmemory.so:"
+ "libion.so:"
+ "libjsoncpp.so:"
+ "liblzma.so:"
+ "libpng.so:"
+ "libprocessgroup.so:"
+ "libunwindstack.so:"
+ "libutils.so:"
+ "libutilscallstack.so:"
+ "libz.so";
+
static std::string vndkVersionStr() {
#ifdef __BIONIC__
return base::GetProperty("ro.vndk.version", "");
@@ -122,8 +171,12 @@ static bool readConfig(const std::string& configFile, std::vector<std::string>*
static const std::string getSystemNativeLibraries(NativeLibrary type) {
std::string nativeLibrariesSystemConfig = "";
- if (!isVndkEnabled() && type == NativeLibrary::LLNDK) {
- nativeLibrariesSystemConfig = kLlndkLibrariesTxtPath;
+ if (!isVndkEnabled()) {
+ if (type == NativeLibrary::VNDKSP) {
+ return kFormerlyVndkspLibrariesList;
+ } else {
+ nativeLibrariesSystemConfig = kLlndkLibrariesTxtPath;
+ }
} else {
nativeLibrariesSystemConfig = kNativeLibrariesSystemConfigPath[type];
insertVndkVersionStr(&nativeLibrariesSystemConfig);
@@ -263,7 +316,7 @@ android_namespace_t* GraphicsEnv::getDriverNamespace() {
ALOGI("Driver path is setup via UPDATABLE_GFX_DRIVER: %s", mDriverPath.c_str());
}
- auto vndkNamespace = android_get_exported_namespace("vndk");
+ auto vndkNamespace = android_get_exported_namespace(isVndkEnabled() ? "vndk" : "sphal");
if (!vndkNamespace) {
mDriverNamespace = nullptr;
return mDriverNamespace;
@@ -631,7 +684,7 @@ android_namespace_t* GraphicsEnv::getAngleNamespace() {
return mAngleNamespace;
}
- auto vndkNamespace = android_get_exported_namespace("vndk");
+ auto vndkNamespace = android_get_exported_namespace(isVndkEnabled() ? "vndk" : "sphal");
if (!vndkNamespace) {
mAngleNamespace = nullptr;
return mAngleNamespace;
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index cda49850f2..f065ffa611 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -510,7 +510,7 @@ void BLASTBufferQueue::releaseBuffer(const ReleaseCallbackId& callbackId,
return;
}
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(BUFFER_RELEASE_CHANNEL)
- if (!it->second.mIsStale) {
+ if (!it->second.disconnectedAfterAcquired) {
mNumAcquired--;
}
#else
@@ -566,7 +566,7 @@ status_t BLASTBufferQueue::acquireNextBufferLocked(
applyTransaction = false;
}
- BufferItem bufferItem;
+ BLASTBufferItem bufferItem;
status_t status =
mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
@@ -1130,9 +1130,9 @@ public:
// can be non-blocking when the producer is in the client process.
class BBQBufferQueueProducer : public BufferQueueProducer {
public:
- BBQBufferQueueProducer(const sp<BufferQueueCore>& core, wp<BLASTBufferQueue> bbq)
+ BBQBufferQueueProducer(const sp<BufferQueueCore>& core, const wp<BLASTBufferQueue>& bbq)
: BufferQueueProducer(core, false /* consumerIsSurfaceFlinger*/),
- mBLASTBufferQueue(std::move(bbq)) {}
+ mBLASTBufferQueue(bbq) {}
status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
QueueBufferOutput* output) override {
@@ -1156,10 +1156,19 @@ public:
return status;
}
+ // We need to reset dequeued and acquired counts because BufferQueueProducer::disconnect
+ // calls BufferQueueCore::freeAllBuffersLocked which frees all dequeued and acquired
+ // buffers. We don't reset mNumFrameAvailable because these buffers are still available
+ // in BufferItemConsumer.
bbq->mNumDequeued = 0;
bbq->mNumAcquired = 0;
+ // SurfaceFlinger sends release callbacks for buffers that have been acquired after a
+ // disconnect. We set disconnectedAfterAcquired to true so that we can ignore any stale
+ // releases that come in after the producer is disconnected. Otherwise, releaseBuffer will
+ // decrement mNumAcquired for a buffer that was acquired before we reset mNumAcquired to
+ // zero.
for (auto& [releaseId, bufferItem] : bbq->mSubmitted) {
- bufferItem.mIsStale = true;
+ bufferItem.disconnectedAfterAcquired = true;
}
return OK;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 0714fd9501..b10996951b 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -892,88 +892,6 @@ status_t InputWindowCommands::read(const Parcel& input) {
// ----------------------------------------------------------------------------
-namespace gui {
-
-status_t CaptureArgs::writeToParcel(Parcel* output) const {
- SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(pixelFormat));
- SAFE_PARCEL(output->write, sourceCrop);
- SAFE_PARCEL(output->writeFloat, frameScaleX);
- SAFE_PARCEL(output->writeFloat, frameScaleY);
- SAFE_PARCEL(output->writeBool, captureSecureLayers);
- SAFE_PARCEL(output->writeInt32, uid);
- SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(dataspace));
- SAFE_PARCEL(output->writeBool, allowProtected);
- SAFE_PARCEL(output->writeBool, grayscale);
- SAFE_PARCEL(output->writeInt32, excludeHandles.size());
- for (auto& excludeHandle : excludeHandles) {
- SAFE_PARCEL(output->writeStrongBinder, excludeHandle);
- }
- SAFE_PARCEL(output->writeBool, hintForSeamlessTransition);
- return NO_ERROR;
-}
-
-status_t CaptureArgs::readFromParcel(const Parcel* input) {
- int32_t value = 0;
- SAFE_PARCEL(input->readInt32, &value);
- pixelFormat = static_cast<ui::PixelFormat>(value);
- SAFE_PARCEL(input->read, sourceCrop);
- SAFE_PARCEL(input->readFloat, &frameScaleX);
- SAFE_PARCEL(input->readFloat, &frameScaleY);
- SAFE_PARCEL(input->readBool, &captureSecureLayers);
- SAFE_PARCEL(input->readInt32, &uid);
- SAFE_PARCEL(input->readInt32, &value);
- dataspace = static_cast<ui::Dataspace>(value);
- SAFE_PARCEL(input->readBool, &allowProtected);
- SAFE_PARCEL(input->readBool, &grayscale);
- int32_t numExcludeHandles = 0;
- SAFE_PARCEL_READ_SIZE(input->readInt32, &numExcludeHandles, input->dataSize());
- excludeHandles.reserve(numExcludeHandles);
- for (int i = 0; i < numExcludeHandles; i++) {
- sp<IBinder> binder;
- SAFE_PARCEL(input->readStrongBinder, &binder);
- excludeHandles.emplace(binder);
- }
- SAFE_PARCEL(input->readBool, &hintForSeamlessTransition);
- return NO_ERROR;
-}
-
-status_t DisplayCaptureArgs::writeToParcel(Parcel* output) const {
- SAFE_PARCEL(CaptureArgs::writeToParcel, output);
-
- SAFE_PARCEL(output->writeStrongBinder, displayToken);
- SAFE_PARCEL(output->writeUint32, width);
- SAFE_PARCEL(output->writeUint32, height);
- return NO_ERROR;
-}
-
-status_t DisplayCaptureArgs::readFromParcel(const Parcel* input) {
- SAFE_PARCEL(CaptureArgs::readFromParcel, input);
-
- SAFE_PARCEL(input->readStrongBinder, &displayToken);
- SAFE_PARCEL(input->readUint32, &width);
- SAFE_PARCEL(input->readUint32, &height);
- return NO_ERROR;
-}
-
-status_t LayerCaptureArgs::writeToParcel(Parcel* output) const {
- SAFE_PARCEL(CaptureArgs::writeToParcel, output);
-
- SAFE_PARCEL(output->writeStrongBinder, layerHandle);
- SAFE_PARCEL(output->writeBool, childrenOnly);
- return NO_ERROR;
-}
-
-status_t LayerCaptureArgs::readFromParcel(const Parcel* input) {
- SAFE_PARCEL(CaptureArgs::readFromParcel, input);
-
- SAFE_PARCEL(input->readStrongBinder, &layerHandle);
-
- SAFE_PARCEL(input->readBool, &childrenOnly);
- return NO_ERROR;
-}
-
-}; // namespace gui
-
ReleaseCallbackId BufferData::generateReleaseCallbackId() const {
uint64_t bufferId;
if (buffer) {
diff --git a/libs/gui/aidl/Android.bp b/libs/gui/aidl/Android.bp
index 8ed08c2644..fd035f60f5 100644
--- a/libs/gui/aidl/Android.bp
+++ b/libs/gui/aidl/Android.bp
@@ -28,9 +28,6 @@ filegroup {
":libgui_extra_unstructured_aidl_files",
"android/gui/BitTube.aidl",
- "android/gui/CaptureArgs.aidl",
- "android/gui/DisplayCaptureArgs.aidl",
- "android/gui/LayerCaptureArgs.aidl",
"android/gui/LayerMetadata.aidl",
"android/gui/ParcelableVsyncEventData.aidl",
"android/gui/ScreenCaptureResults.aidl",
diff --git a/libs/gui/aidl/android/gui/CaptureArgs.aidl b/libs/gui/aidl/android/gui/CaptureArgs.aidl
index 9f198cae10..2bbed2b9d6 100644
--- a/libs/gui/aidl/android/gui/CaptureArgs.aidl
+++ b/libs/gui/aidl/android/gui/CaptureArgs.aidl
@@ -16,4 +16,58 @@
package android.gui;
-parcelable CaptureArgs cpp_header "gui/DisplayCaptureArgs.h" rust_type "gui_aidl_types_rs::CaptureArgs";
+import android.gui.ARect;
+
+// Common arguments for capturing content on-screen
+parcelable CaptureArgs {
+ const int UNSET_UID = -1;
+
+ // Desired pixel format of the final screenshotted buffer
+ int /*ui::PixelFormat*/ pixelFormat = 1;
+
+ // Crop in layer space: all content outside of the crop will not be captured.
+ ARect sourceCrop;
+
+ // Scale in the x-direction for the screenshotted result.
+ float frameScaleX = 1.0f;
+
+ // Scale in the y-direction for the screenshotted result.
+ float frameScaleY = 1.0f;
+
+ // True if capturing secure layers is permitted
+ boolean captureSecureLayers = false;
+
+ // UID whose content we want to screenshot
+ int uid = UNSET_UID;
+
+ // Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured
+ // result will be in a colorspace appropriate for capturing the display contents
+ // The display may use non-RGB dataspace (ex. displayP3) that could cause pixel data could be
+ // different from SRGB (byte per color), and failed when checking colors in tests.
+ // NOTE: In normal cases, we want the screen to be captured in display's colorspace.
+ int /*ui::Dataspace*/ dataspace = 0;
+
+ // The receiver of the capture can handle protected buffer. A protected buffer has
+ // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour.
+ // Any read/write access from unprotected context will result in undefined behaviour.
+ // Protected contents are typically DRM contents. This has no direct implication to the
+ // secure property of the surface, which is specified by the application explicitly to avoid
+ // the contents being accessed/captured by screenshot or unsecure display.
+ boolean allowProtected = false;
+
+ // True if the content should be captured in grayscale
+ boolean grayscale = false;
+
+ // List of layers to exclude capturing from
+ IBinder[] excludeHandles;
+
+ // Hint that the caller will use the screenshot animation as part of a transition animation.
+ // The canonical example would be screen rotation - in such a case any color shift in the
+ // screenshot is a detractor so composition in the display's colorspace is required.
+ // Otherwise, the system may choose a colorspace that is more appropriate for use-cases
+ // such as file encoding or for blending HDR content into an ap's UI, where the display's
+ // exact colorspace is not an appropriate intermediate result.
+ // Note that if the caller is requesting a specific dataspace, this hint does nothing.
+ boolean hintForSeamlessTransition = false;
+}
+
diff --git a/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl b/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl
index fc97dbf03d..e00a2dfa82 100644
--- a/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl
+++ b/libs/gui/aidl/android/gui/DisplayCaptureArgs.aidl
@@ -16,5 +16,18 @@
package android.gui;
-parcelable DisplayCaptureArgs cpp_header "gui/DisplayCaptureArgs.h" rust_type "gui_aidl_types_rs::DisplayCaptureArgs";
+import android.gui.CaptureArgs;
+
+// Arguments for screenshotting an entire display
+parcelable DisplayCaptureArgs {
+ CaptureArgs captureArgs;
+
+ // The display that we want to screenshot
+ IBinder displayToken;
+
+ // The width of the render area when we screenshot
+ int width = 0;
+ // The length of the render area when we screenshot
+ int height = 0;
+}
diff --git a/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl b/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl
index 18d293f211..004c35a5ce 100644
--- a/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl
+++ b/libs/gui/aidl/android/gui/LayerCaptureArgs.aidl
@@ -16,4 +16,15 @@
package android.gui;
-parcelable LayerCaptureArgs cpp_header "gui/LayerCaptureArgs.h" rust_type "gui_aidl_types_rs::LayerCaptureArgs";
+import android.gui.CaptureArgs;
+
+// Arguments for capturing a layer and/or its children
+parcelable LayerCaptureArgs {
+ CaptureArgs captureArgs;
+
+ // The Layer that we may want to capture. We would also capture its children
+ IBinder layerHandle;
+ // True if we don't actually want to capture the layer and want to capture
+ // its children instead.
+ boolean childrenOnly = false;
+}
diff --git a/libs/gui/include/gui/AidlStatusUtil.h b/libs/gui/include/gui/AidlStatusUtil.h
index 55be27bf35..159e0329ac 100644
--- a/libs/gui/include/gui/AidlStatusUtil.h
+++ b/libs/gui/include/gui/AidlStatusUtil.h
@@ -16,9 +16,11 @@
#pragma once
+#include <android/gui/ARect.h>
#include <binder/Status.h>
+#include <ui/Rect.h>
-// Extracted from frameworks/av/media/libaudioclient/include/media/AidlConversionUtil.h
+// Originally extracted from frameworks/av/media/libaudioclient/include/media/AidlConversionUtil.h
namespace android::gui::aidl_utils {
/**
@@ -111,4 +113,26 @@ static inline ::android::binder::Status binderStatusFromStatusT(
return Status::fromServiceSpecificError(status, emptyIfNull);
}
+static inline Rect fromARect(ARect rect) {
+ return Rect(rect.left, rect.top, rect.right, rect.bottom);
+}
+
+static inline ARect toARect(Rect rect) {
+ ARect aRect;
+
+ aRect.left = rect.left;
+ aRect.top = rect.top;
+ aRect.right = rect.right;
+ aRect.bottom = rect.bottom;
+ return aRect;
+}
+
+static inline ARect toARect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
+ return toARect(Rect(left, top, right, bottom));
+}
+
+static inline ARect toARect(int32_t width, int32_t height) {
+ return toARect(Rect(width, height));
+}
+
} // namespace android::gui::aidl_utils
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 4dafc57734..c2dcd2579c 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -198,9 +198,16 @@ private:
// latch stale buffers and that we don't wait on barriers from an old producer.
uint32_t mProducerId = 0;
+ class BLASTBufferItem : public BufferItem {
+ public:
+ // True if BBQBufferQueueProducer is disconnected after the buffer is acquried but
+ // before it is released.
+ bool disconnectedAfterAcquired{false};
+ };
+
// Keep a reference to the submitted buffers so we can release when surfaceflinger drops the
// buffer or the buffer has been presented and a new buffer is ready to be presented.
- std::unordered_map<ReleaseCallbackId, BufferItem, ReleaseBufferCallbackIdHash> mSubmitted
+ std::unordered_map<ReleaseCallbackId, BLASTBufferItem, ReleaseBufferCallbackIdHash> mSubmitted
GUARDED_BY(mMutex);
// Keep a queue of the released buffers instead of immediately releasing
diff --git a/libs/gui/include/gui/DisplayCaptureArgs.h b/libs/gui/include/gui/DisplayCaptureArgs.h
deleted file mode 100644
index e29ce41bd5..0000000000
--- a/libs/gui/include/gui/DisplayCaptureArgs.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#pragma once
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IBinder.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <gui/SpHash.h>
-#include <ui/GraphicTypes.h>
-#include <ui/PixelFormat.h>
-#include <ui/Rect.h>
-#include <unordered_set>
-
-namespace android::gui {
-
-struct CaptureArgs : public Parcelable {
- const static int32_t UNSET_UID = -1;
- virtual ~CaptureArgs() = default;
-
- ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888};
- Rect sourceCrop;
- float frameScaleX{1};
- float frameScaleY{1};
- bool captureSecureLayers{false};
- int32_t uid{UNSET_UID};
- // Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured
- // result will be in a colorspace appropriate for capturing the display contents
- // The display may use non-RGB dataspace (ex. displayP3) that could cause pixel data could be
- // different from SRGB (byte per color), and failed when checking colors in tests.
- // NOTE: In normal cases, we want the screen to be captured in display's colorspace.
- ui::Dataspace dataspace = ui::Dataspace::UNKNOWN;
-
- // The receiver of the capture can handle protected buffer. A protected buffer has
- // GRALLOC_USAGE_PROTECTED usage bit and must not be accessed unprotected behaviour.
- // Any read/write access from unprotected context will result in undefined behaviour.
- // Protected contents are typically DRM contents. This has no direct implication to the
- // secure property of the surface, which is specified by the application explicitly to avoid
- // the contents being accessed/captured by screenshot or unsecure display.
- bool allowProtected = false;
-
- bool grayscale = false;
-
- std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles;
-
- // Hint that the caller will use the screenshot animation as part of a transition animation.
- // The canonical example would be screen rotation - in such a case any color shift in the
- // screenshot is a detractor so composition in the display's colorspace is required.
- // Otherwise, the system may choose a colorspace that is more appropriate for use-cases
- // such as file encoding or for blending HDR content into an ap's UI, where the display's
- // exact colorspace is not an appropriate intermediate result.
- // Note that if the caller is requesting a specific dataspace, this hint does nothing.
- bool hintForSeamlessTransition = false;
-
- virtual status_t writeToParcel(Parcel* output) const;
- virtual status_t readFromParcel(const Parcel* input);
-};
-
-struct DisplayCaptureArgs : CaptureArgs {
- sp<IBinder> displayToken;
- uint32_t width{0};
- uint32_t height{0};
-
- status_t writeToParcel(Parcel* output) const override;
- status_t readFromParcel(const Parcel* input) override;
-};
-
-}; // namespace android::gui
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index 3d1be4d2eb..462081bfd2 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -116,7 +116,7 @@ public:
// Public for testing.
static nsecs_t snapToNextTick(
nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval);
- nsecs_t getReportedCompositeDeadline() const { return mCompositorTiming.deadline; };
+ nsecs_t getReportedCompositeDeadline() const { return mCompositorTiming.deadline; }
nsecs_t getNextCompositeDeadline(const nsecs_t now) const;
nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; }
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 8fca9460aa..3aac457a09 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -867,6 +867,6 @@ class BnGraphicBufferProducer : public IGraphicBufferProducer {
#endif
// ----------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_GUI_IGRAPHICBUFFERPRODUCER_H
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 1ecc216dff..9a422fd808 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -18,6 +18,7 @@
#include <android/gui/CachingHint.h>
#include <android/gui/DisplayBrightness.h>
+#include <android/gui/DisplayCaptureArgs.h>
#include <android/gui/FrameTimelineInfo.h>
#include <android/gui/IDisplayEventConnection.h>
#include <android/gui/IFpsListener.h>
@@ -27,6 +28,7 @@
#include <android/gui/ITunnelModeEnabledListener.h>
#include <android/gui/IWindowInfosListener.h>
#include <android/gui/IWindowInfosPublisher.h>
+#include <android/gui/LayerCaptureArgs.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <gui/ITransactionCompletedListener.h>
@@ -70,13 +72,6 @@ using gui::IRegionSamplingListener;
using gui::IScreenCaptureListener;
using gui::SpHash;
-namespace gui {
-
-struct DisplayCaptureArgs;
-struct LayerCaptureArgs;
-
-} // namespace gui
-
namespace ui {
struct DisplayMode;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index d41994589f..2cdde3255e 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -21,7 +21,9 @@
#include <stdint.h>
#include <sys/types.h>
+#include <android/gui/DisplayCaptureArgs.h>
#include <android/gui/IWindowInfosReportedListener.h>
+#include <android/gui/LayerCaptureArgs.h>
#include <android/gui/TrustedPresentationThresholds.h>
#include <android/native_window.h>
#include <gui/IGraphicBufferProducer.h>
@@ -35,9 +37,7 @@
#include <ftl/flags.h>
#include <gui/BufferReleaseChannel.h>
-#include <gui/DisplayCaptureArgs.h>
#include <gui/ISurfaceComposer.h>
-#include <gui/LayerCaptureArgs.h>
#include <gui/LayerMetadata.h>
#include <gui/SpHash.h>
#include <gui/SurfaceControl.h>
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 39207f835f..0f51f2dc13 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -194,6 +194,14 @@ public:
* in <system/window.h>. */
int setScalingMode(int mode);
+ virtual int setBuffersTimestamp(int64_t timestamp);
+ virtual int setBuffersDataSpace(ui::Dataspace dataSpace);
+ virtual int setCrop(Rect const* rect);
+ virtual int setBuffersTransform(uint32_t transform);
+ virtual int setBuffersStickyTransform(uint32_t transform);
+ virtual int setBuffersFormat(PixelFormat format);
+ virtual int setUsage(uint64_t reqUsage);
+
// See IGraphicBufferProducer::setDequeueTimeout
status_t setDequeueTimeout(nsecs_t timeout);
@@ -354,16 +362,9 @@ protected:
virtual int connect(int api);
virtual int setBufferCount(int bufferCount);
virtual int setBuffersUserDimensions(uint32_t width, uint32_t height);
- virtual int setBuffersFormat(PixelFormat format);
- virtual int setBuffersTransform(uint32_t transform);
- virtual int setBuffersStickyTransform(uint32_t transform);
- virtual int setBuffersTimestamp(int64_t timestamp);
- virtual int setBuffersDataSpace(ui::Dataspace dataSpace);
virtual int setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata);
virtual int setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata);
virtual int setBuffersHdr10PlusMetadata(const size_t size, const uint8_t* metadata);
- virtual int setCrop(Rect const* rect);
- virtual int setUsage(uint64_t reqUsage);
virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
public:
diff --git a/libs/gui/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h
index b7aba2b9dc..7ddac8139a 100644
--- a/libs/gui/include/gui/view/Surface.h
+++ b/libs/gui/include/gui/view/Surface.h
@@ -59,8 +59,9 @@ class Surface : public Parcelable {
// of the full parceling to happen on its native side.
status_t readFromParcel(const Parcel* parcel, bool nameAlreadyRead);
- private:
+ std::string toString() const;
+private:
static String16 readMaybeEmptyString16(const Parcel* parcel);
};
diff --git a/libs/gui/rust/aidl_types/src/lib.rs b/libs/gui/rust/aidl_types/src/lib.rs
index fead018bbf..2351df0318 100644
--- a/libs/gui/rust/aidl_types/src/lib.rs
+++ b/libs/gui/rust/aidl_types/src/lib.rs
@@ -42,10 +42,7 @@ macro_rules! stub_unstructured_parcelable {
}
stub_unstructured_parcelable!(BitTube);
-stub_unstructured_parcelable!(CaptureArgs);
-stub_unstructured_parcelable!(DisplayCaptureArgs);
stub_unstructured_parcelable!(DisplayInfo);
-stub_unstructured_parcelable!(LayerCaptureArgs);
stub_unstructured_parcelable!(LayerDebugInfo);
stub_unstructured_parcelable!(LayerMetadata);
stub_unstructured_parcelable!(ParcelableVsyncEventData);
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 1b216e9063..f07747f32f 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -12,6 +12,34 @@ package {
default_applicable_licenses: ["frameworks_native_license"],
}
+aidl_interface {
+ name: "libgui_test_server_aidl",
+ unstable: true,
+ srcs: ["testserver/aidl/**/*.aidl"],
+ local_include_dir: "testserver/aidl",
+ include_dirs: [
+ "frameworks/native/aidl/gui",
+ ],
+ backend: {
+ cpp: {
+ enabled: true,
+ additional_shared_libraries: [
+ "libgui",
+ "libui",
+ ],
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: false,
+ },
+ rust: {
+ enabled: false,
+ },
+ },
+}
+
cc_test {
name: "libgui_test",
test_suites: ["device-tests"],
@@ -30,7 +58,6 @@ cc_test {
],
srcs: [
- "LibGuiMain.cpp", // Custom gtest entrypoint
"BLASTBufferQueue_test.cpp",
"BufferItemConsumer_test.cpp",
"BufferQueue_test.cpp",
@@ -38,24 +65,29 @@ cc_test {
"Choreographer_test.cpp",
"CompositorTiming_test.cpp",
"CpuConsumer_test.cpp",
- "EndToEndNativeInputTest.cpp",
- "FrameRateUtilsTest.cpp",
- "DisplayInfo_test.cpp",
"DisplayedContentSampling_test.cpp",
+ "DisplayInfo_test.cpp",
+ "EndToEndNativeInputTest.cpp",
"FillBuffer.cpp",
+ "FrameRateUtilsTest.cpp",
"GLTest.cpp",
"IGraphicBufferProducer_test.cpp",
+ "LibGuiMain.cpp", // Custom gtest entrypoint
"Malicious.cpp",
"MultiTextureConsumer_test.cpp",
"RegionSampling_test.cpp",
"StreamSplitter_test.cpp",
+ "Surface_test.cpp",
"SurfaceTextureClient_test.cpp",
"SurfaceTextureFBO_test.cpp",
+ "SurfaceTextureGL_test.cpp",
"SurfaceTextureGLThreadToGL_test.cpp",
"SurfaceTextureGLToGL_test.cpp",
- "SurfaceTextureGL_test.cpp",
"SurfaceTextureMultiContextGL_test.cpp",
- "Surface_test.cpp",
+ "TestServer_test.cpp",
+ "testserver/TestServer.cpp",
+ "testserver/TestServerClient.cpp",
+ "testserver/TestServerHost.cpp",
"TextureRenderer.cpp",
"VsyncEventData_test.cpp",
"WindowInfo_test.cpp",
@@ -66,10 +98,17 @@ cc_test {
"android.hardware.configstore-utils",
"libSurfaceFlingerProp",
"libGLESv1_CM",
+ "libgui_test_server_aidl-cpp",
"libinput",
"libnativedisplay",
],
+ // This needs to get copied over for the test since it's not part of the
+ // platform.
+ data_libs: [
+ "libgui_test_server_aidl-cpp",
+ ],
+
static_libs: [
"libgmock",
],
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 6852589e32..46a19c273d 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -229,7 +229,8 @@ protected:
ISurfaceComposerClient::eFXSurfaceBufferState,
/*parent*/ mRootSurfaceControl->getHandle());
- mCaptureArgs.sourceCrop = Rect(ui::Size(mDisplayWidth, mDisplayHeight));
+ mCaptureArgs.captureArgs.sourceCrop =
+ gui::aidl_utils::toARect(mDisplayWidth, mDisplayHeight);
mCaptureArgs.layerHandle = mRootSurfaceControl->getHandle();
}
diff --git a/libs/gui/tests/LibGuiMain.cpp b/libs/gui/tests/LibGuiMain.cpp
index 10f7207588..7c7c2cc30f 100644
--- a/libs/gui/tests/LibGuiMain.cpp
+++ b/libs/gui/tests/LibGuiMain.cpp
@@ -14,8 +14,15 @@
* limitations under the License.
*/
-#include "gtest/gtest.h"
-#include "log/log.h"
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+
+#include "testserver/TestServer.h"
+#include "testserver/TestServerClient.h"
+#include "testserver/TestServerHost.h"
+
+using namespace android;
namespace {
@@ -32,7 +39,34 @@ class TestCaseLogger : public ::testing::EmptyTestEventListener {
} // namespace
int main(int argc, char** argv) {
+ // There are three modes that we can run in to support the libgui TestServer:
+ //
+ // - libgui_test : normal mode, runs tests and fork/execs the testserver host process
+ // - libgui_test --test-server-host $recvPipeFd $sendPipeFd : TestServerHost mode, listens on
+ // $recvPipeFd for commands and sends responses over $sendPipeFd
+ // - libgui_test --test-server $name : TestServer mode, starts a ITestService binder service
+ // under $name
+ for (int i = 1; i < argc; i++) {
+ std::string arg = argv[i];
+ if (arg == "--test-server-host") {
+ LOG_ALWAYS_FATAL_IF(argc < (i + 2), "--test-server-host requires two pipe fds");
+ // Note that the send/recv are from our perspective.
+ base::unique_fd recvPipeFd = base::unique_fd(atoi(argv[i + 1]));
+ base::unique_fd sendPipeFd = base::unique_fd(atoi(argv[i + 2]));
+ return TestServerHostMain(argv[0], std::move(sendPipeFd), std::move(recvPipeFd));
+ }
+ if (arg == "--test-server") {
+ LOG_ALWAYS_FATAL_IF(argc < (i + 1), "--test-server requires a name");
+ return TestServerMain(argv[i + 1]);
+ }
+ }
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(new TestCaseLogger());
+
+ // This has to be run *before* any test initialization, because it fork/execs a TestServerHost,
+ // which will later create new binder service. You can't do that in a forked thread after you've
+ // initialized any binder stuff, which some tests do.
+ TestServerClient::InitializeOrDie(argv[0]);
+
return RUN_ALL_TESTS();
} \ No newline at end of file
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 8ab8783c4c..4232443308 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "gui/view/Surface.h"
#include "Constants.h"
#include "MockConsumer.h"
@@ -53,6 +54,8 @@
#include <limits>
#include <thread>
+#include "testserver/TestServerClient.h"
+
namespace android {
using namespace std::chrono_literals;
@@ -2363,6 +2366,14 @@ TEST_F(SurfaceTest, QueueAcquireReleaseDequeue_CalledInStack_DoesNotDeadlock) {
EXPECT_EQ(OK, surface->disconnect(NATIVE_WINDOW_API_CPU));
}
+
+TEST_F(SurfaceTest, ViewSurface_toString) {
+ view::Surface surface{};
+ EXPECT_EQ("", surface.toString());
+
+ surface.name = String16("name");
+ EXPECT_EQ("name", surface.toString());
+}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
} // namespace android
diff --git a/libs/gui/tests/TestServer_test.cpp b/libs/gui/tests/TestServer_test.cpp
new file mode 100644
index 0000000000..8712988e52
--- /dev/null
+++ b/libs/gui/tests/TestServer_test.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <SurfaceFlingerProperties.h>
+#include <android/gui/IDisplayEventConnection.h>
+#include <android/gui/ISurfaceComposer.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware_buffer.h>
+#include <binder/ProcessState.h>
+#include <com_android_graphics_libgui_flags.h>
+#include <configstore/Utils.h>
+#include <gui/AidlStatusUtil.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/BufferQueue.h>
+#include <gui/CpuConsumer.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/SyncScreenCaptureListener.h>
+#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
+#include <sys/types.h>
+#include <system/window.h>
+#include <ui/BufferQueueDefs.h>
+#include <ui/DisplayMode.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+
+#include <cstddef>
+#include <limits>
+#include <thread>
+
+#include "binder/IInterface.h"
+#include "testserver/TestServerClient.h"
+
+namespace android {
+
+namespace {
+
+class TestServerTest : public ::testing::Test {
+protected:
+ TestServerTest() { ProcessState::self()->startThreadPool(); }
+};
+
+} // namespace
+
+TEST_F(TestServerTest, Create) {
+ EXPECT_NE(nullptr, TestServerClient::Create());
+}
+
+TEST_F(TestServerTest, CreateProducer) {
+ sp<TestServerClient> client = TestServerClient::Create();
+ EXPECT_NE(nullptr, client->CreateProducer());
+}
+
+TEST_F(TestServerTest, KillServer) {
+ class DeathWaiter : public IBinder::DeathRecipient {
+ public:
+ virtual void binderDied(const wp<IBinder>&) override { mPromise.set_value(true); }
+ std::future<bool> getFuture() { return mPromise.get_future(); }
+
+ std::promise<bool> mPromise;
+ };
+
+ sp<TestServerClient> client = TestServerClient::Create();
+ sp<IGraphicBufferProducer> producer = client->CreateProducer();
+ EXPECT_NE(nullptr, producer);
+
+ sp<DeathWaiter> deathWaiter = sp<DeathWaiter>::make();
+ EXPECT_EQ(OK, IInterface::asBinder(producer)->linkToDeath(deathWaiter));
+
+ auto deathWaiterFuture = deathWaiter->getFuture();
+ EXPECT_EQ(OK, client->Kill());
+ EXPECT_EQ(nullptr, client->CreateProducer());
+
+ EXPECT_TRUE(deathWaiterFuture.get());
+}
+
+} // namespace android
diff --git a/libs/gui/tests/testserver/TestServer.cpp b/libs/gui/tests/testserver/TestServer.cpp
new file mode 100644
index 0000000000..cd8824e355
--- /dev/null
+++ b/libs/gui/tests/testserver/TestServer.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TestServer"
+
+#include <android-base/stringprintf.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/Status.h>
+#include <gui/BufferQueue.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/view/Surface.h>
+#include <libgui_test_server/BnTestServer.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+
+#include <cstdint>
+#include <cstdlib>
+#include <memory>
+#include <mutex>
+#include <vector>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "TestServer.h"
+
+namespace android {
+
+namespace {
+class TestConsumerListener : public BnConsumerListener {
+ virtual void onFrameAvailable(const BufferItem&) override {}
+ virtual void onBuffersReleased() override {}
+ virtual void onSidebandStreamChanged() override {}
+};
+
+class TestServiceImpl : public libgui_test_server::BnTestServer {
+public:
+ TestServiceImpl(const char* name) : mName(name) {}
+
+ virtual binder::Status createProducer(view::Surface* out) override {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ BufferQueueHolder bq;
+ BufferQueue::createBufferQueue(&bq.producer, &bq.consumer);
+ sp<TestConsumerListener> listener = sp<TestConsumerListener>::make();
+ bq.consumer->consumerConnect(listener, /*controlledByApp*/ true);
+
+ uint64_t id = 0;
+ bq.producer->getUniqueId(&id);
+ std::string name = base::StringPrintf("%s-%" PRIu64, mName, id);
+
+ out->name = String16(name.c_str());
+ out->graphicBufferProducer = bq.producer;
+ mBqs.push_back(std::move(bq));
+
+ return binder::Status::ok();
+ }
+
+ virtual binder::Status killNow() override {
+ ALOGE("LibGUI Test Service %s dying in response to killNow", mName);
+ _exit(0);
+ // Not reached:
+ return binder::Status::ok();
+ }
+
+private:
+ std::mutex mMutex;
+ const char* mName;
+
+ struct BufferQueueHolder {
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ };
+
+ std::vector<BufferQueueHolder> mBqs;
+};
+} // namespace
+
+int TestServerMain(const char* name) {
+ ProcessState::self()->startThreadPool();
+
+ sp<TestServiceImpl> testService = sp<TestServiceImpl>::make(name);
+ ALOGE("service");
+ sp<IServiceManager> serviceManager(defaultServiceManager());
+ LOG_ALWAYS_FATAL_IF(OK != serviceManager->addService(String16(name), testService));
+
+ ALOGD("LibGUI Test Service %s STARTED", name);
+
+ IPCThreadState::self()->joinThreadPool();
+
+ ALOGW("LibGUI Test Service %s DIED", name);
+
+ return 0;
+}
+
+} // namespace android \ No newline at end of file
diff --git a/libs/gui/include/gui/LayerCaptureArgs.h b/libs/gui/tests/testserver/TestServer.h
index fae2bcc787..4226f1bb09 100644
--- a/libs/gui/include/gui/LayerCaptureArgs.h
+++ b/libs/gui/tests/testserver/TestServer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,19 +16,16 @@
#pragma once
-#include <stdint.h>
-#include <sys/types.h>
+namespace android {
-#include <gui/DisplayCaptureArgs.h>
-
-namespace android::gui {
-
-struct LayerCaptureArgs : CaptureArgs {
- sp<IBinder> layerHandle;
- bool childrenOnly{false};
-
- status_t writeToParcel(Parcel* output) const override;
- status_t readFromParcel(const Parcel* input) override;
-};
+/*
+ * Main method for a libgui ITestServer server.
+ *
+ * This must be called without any binder setup having been done, because you can't fork and do
+ * binder things once ProcessState is set up.
+ * @param name The service name of the test server to start.
+ * @return retcode
+ */
+int TestServerMain(const char* name);
-}; // namespace android::gui
+} // namespace android
diff --git a/libs/gui/tests/testserver/TestServerClient.cpp b/libs/gui/tests/testserver/TestServerClient.cpp
new file mode 100644
index 0000000000..e388074675
--- /dev/null
+++ b/libs/gui/tests/testserver/TestServerClient.cpp
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/wait.h>
+#include <cerrno>
+#define LOG_TAG "TestServerClient"
+
+#include <android-base/stringprintf.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <libgui_test_server/ITestServer.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <csignal>
+#include <cstdlib>
+#include <mutex>
+#include <string>
+
+#include "TestServerClient.h"
+#include "TestServerCommon.h"
+
+namespace android {
+
+namespace {
+
+std::string GetUniqueServiceName() {
+ static std::atomic<int> uniqueId = 1;
+
+ pid_t pid = getpid();
+ int id = uniqueId++;
+ return base::StringPrintf("Libgui-TestServer-%d-%d", pid, id);
+}
+
+struct RemoteTestServerHostHolder {
+ RemoteTestServerHostHolder(pid_t pid, int sendFd, int recvFd)
+ : mPid(pid), mSendFd(sendFd), mRecvFd(recvFd) {}
+ ~RemoteTestServerHostHolder() {
+ std::lock_guard lock(mMutex);
+
+ kill(mPid, SIGKILL);
+ close(mSendFd);
+ close(mRecvFd);
+ }
+
+ pid_t CreateTestServerOrDie(std::string name) {
+ std::lock_guard lock(mMutex);
+
+ CreateServerRequest request;
+ strlcpy(request.name, name.c_str(), sizeof(request.name) / sizeof(request.name[0]));
+
+ ssize_t bytes = write(mSendFd, &request, sizeof(request));
+ LOG_ALWAYS_FATAL_IF(bytes != sizeof(request));
+
+ CreateServerResponse response;
+ bytes = read(mRecvFd, &response, sizeof(response));
+ LOG_ALWAYS_FATAL_IF(bytes != sizeof(response));
+
+ return response.pid;
+ }
+
+private:
+ std::mutex mMutex;
+
+ pid_t mPid;
+ int mSendFd;
+ int mRecvFd;
+};
+
+std::unique_ptr<RemoteTestServerHostHolder> g_remoteTestServerHostHolder = nullptr;
+
+} // namespace
+
+void TestServerClient::InitializeOrDie(const char* filename) {
+ int sendPipeFds[2];
+ int ret = pipe(sendPipeFds);
+ LOG_ALWAYS_FATAL_IF(ret, "Unable to create subprocess send pipe");
+
+ int recvPipeFds[2];
+ ret = pipe(recvPipeFds);
+ LOG_ALWAYS_FATAL_IF(ret, "Unable to create subprocess recv pipe");
+
+ pid_t childPid = fork();
+ LOG_ALWAYS_FATAL_IF(childPid < 0, "Unable to fork child process");
+
+ if (childPid == 0) {
+ // We forked!
+ close(sendPipeFds[1]);
+ close(recvPipeFds[0]);
+
+ // We'll be reading from the parent's "send" and writing to the parent's "recv".
+ std::string sendPipe = std::to_string(sendPipeFds[0]);
+ std::string recvPipe = std::to_string(recvPipeFds[1]);
+ char* args[] = {
+ const_cast<char*>(filename),
+ const_cast<char*>("--test-server-host"),
+ const_cast<char*>(sendPipe.c_str()),
+ const_cast<char*>(recvPipe.c_str()),
+ nullptr,
+ };
+
+ ret = execv(filename, args);
+ ALOGE("Failed to exec libguiTestServer. ret=%d errno=%d (%s)", ret, errno, strerror(errno));
+ status_t status = -errno;
+ write(recvPipeFds[1], &status, sizeof(status));
+ _exit(EXIT_FAILURE);
+ }
+
+ close(sendPipeFds[0]);
+ close(recvPipeFds[1]);
+
+ // Check for an OK status that the host started. If so, we're good to go.
+ status_t status;
+ ret = read(recvPipeFds[0], &status, sizeof(status));
+ LOG_ALWAYS_FATAL_IF(ret != sizeof(status), "Unable to read from pipe: %d", ret);
+ LOG_ALWAYS_FATAL_IF(OK != status, "Pipe returned failed status: %d", status);
+
+ g_remoteTestServerHostHolder =
+ std::make_unique<RemoteTestServerHostHolder>(childPid, sendPipeFds[1], recvPipeFds[0]);
+}
+
+sp<TestServerClient> TestServerClient::Create() {
+ std::string serviceName = GetUniqueServiceName();
+
+ pid_t childPid = g_remoteTestServerHostHolder->CreateTestServerOrDie(serviceName);
+ ALOGD("Created child server %s with pid %d", serviceName.c_str(), childPid);
+
+ sp<libgui_test_server::ITestServer> server =
+ waitForService<libgui_test_server::ITestServer>(String16(serviceName.c_str()));
+ LOG_ALWAYS_FATAL_IF(server == nullptr);
+ ALOGD("Created connected to child server %s", serviceName.c_str());
+
+ return sp<TestServerClient>::make(server);
+}
+
+TestServerClient::TestServerClient(const sp<libgui_test_server::ITestServer>& server)
+ : mServer(server) {}
+
+TestServerClient::~TestServerClient() {
+ Kill();
+}
+
+sp<IGraphicBufferProducer> TestServerClient::CreateProducer() {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (!mIsAlive) {
+ return nullptr;
+ }
+
+ view::Surface surface;
+ binder::Status status = mServer->createProducer(&surface);
+
+ if (!status.isOk()) {
+ ALOGE("Failed to create remote producer. Error: %s", status.exceptionMessage().c_str());
+ return nullptr;
+ }
+
+ if (!surface.graphicBufferProducer) {
+ ALOGE("Remote producer returned no IGBP.");
+ return nullptr;
+ }
+
+ return surface.graphicBufferProducer;
+}
+
+status_t TestServerClient::Kill() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (!mIsAlive) {
+ return DEAD_OBJECT;
+ }
+
+ mServer->killNow();
+ mServer = nullptr;
+ mIsAlive = false;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/libs/gui/tests/testserver/TestServerClient.h b/libs/gui/tests/testserver/TestServerClient.h
new file mode 100644
index 0000000000..53296344a3
--- /dev/null
+++ b/libs/gui/tests/testserver/TestServerClient.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libgui_test_server/ITestServer.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class TestServerClient : public RefBase {
+public:
+ static void InitializeOrDie(const char* filename);
+ static sp<TestServerClient> Create();
+
+ TestServerClient(const sp<libgui_test_server::ITestServer>& server);
+ virtual ~TestServerClient() override;
+
+ sp<IGraphicBufferProducer> CreateProducer();
+ status_t Kill();
+
+private:
+ std::mutex mMutex;
+
+ sp<libgui_test_server::ITestServer> mServer;
+ bool mIsAlive = true;
+};
+
+} // namespace android
diff --git a/libs/gui/tests/testserver/TestServerCommon.h b/libs/gui/tests/testserver/TestServerCommon.h
new file mode 100644
index 0000000000..7370f20ef8
--- /dev/null
+++ b/libs/gui/tests/testserver/TestServerCommon.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <fcntl.h>
+
+namespace android {
+
+/*
+ * Test -> TestServerHost Request to create a new ITestServer fork.
+ */
+struct CreateServerRequest {
+ /*
+ * Service name for new ITestServer.
+ */
+ char name[128];
+};
+
+/*
+ * TestServerHost -> Test Response for creating an ITestServer fork.
+ */
+struct CreateServerResponse {
+ /*
+ * pid of new ITestServer.
+ */
+ pid_t pid;
+};
+
+} // namespace android \ No newline at end of file
diff --git a/libs/gui/tests/testserver/TestServerHost.cpp b/libs/gui/tests/testserver/TestServerHost.cpp
new file mode 100644
index 0000000000..696c3b9817
--- /dev/null
+++ b/libs/gui/tests/testserver/TestServerHost.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "TestServerHost"
+
+#include <android-base/unique_fd.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/Status.h>
+#include <gui/BufferQueue.h>
+#include <gui/IConsumerListener.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <libgui_test_server/BnTestServer.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+
+#include <memory>
+#include <vector>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <cstddef>
+#include <cstdlib>
+
+#include "TestServerCommon.h"
+#include "TestServerHost.h"
+
+namespace android {
+
+namespace {
+
+pid_t ForkTestServer(const char* filename, char* name) {
+ pid_t childPid = fork();
+ LOG_ALWAYS_FATAL_IF(childPid == -1);
+
+ if (childPid != 0) {
+ return childPid;
+ }
+
+ // We forked!
+ const char* test_server_flag = "--test-server";
+ char* args[] = {
+ const_cast<char*>(filename),
+ const_cast<char*>(test_server_flag),
+ name,
+ nullptr,
+ };
+
+ int ret = execv(filename, args);
+ ALOGE("Failed to exec libgui_test as a TestServer. ret=%d errno=%d (%s)", ret, errno,
+ strerror(errno));
+ _exit(EXIT_FAILURE);
+}
+
+} // namespace
+
+int TestServerHostMain(const char* filename, base::unique_fd sendPipeFd,
+ base::unique_fd recvPipeFd) {
+ status_t status = OK;
+ LOG_ALWAYS_FATAL_IF(sizeof(status) != write(sendPipeFd.get(), &status, sizeof(status)));
+
+ ALOGE("Launched TestServerHost");
+
+ while (true) {
+ CreateServerRequest request = {};
+ ssize_t bytes = read(recvPipeFd.get(), &request, sizeof(request));
+ LOG_ALWAYS_FATAL_IF(bytes != sizeof(request));
+ pid_t childPid = ForkTestServer(filename, request.name);
+
+ CreateServerResponse response = {};
+ response.pid = childPid;
+ bytes = write(sendPipeFd.get(), &response, sizeof(response));
+ LOG_ALWAYS_FATAL_IF(bytes != sizeof(response));
+ }
+
+ return 0;
+}
+
+} // namespace android \ No newline at end of file
diff --git a/libs/gui/tests/testserver/TestServerHost.h b/libs/gui/tests/testserver/TestServerHost.h
new file mode 100644
index 0000000000..df22c0c3fe
--- /dev/null
+++ b/libs/gui/tests/testserver/TestServerHost.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+
+#include <string>
+
+namespace android {
+
+/*
+ * Main method for a host process for TestServers.
+ *
+ * This must be called without any binder setup having been done, because you can't fork and do
+ * binder things once ProcessState is set up.
+ * @param filename File name of this binary / the binary to execve into
+ * @param sendPipeFd Pipe FD to send data to.
+ * @param recvPipeFd Pipe FD to receive data from.
+ * @return retcode
+ */
+int TestServerHostMain(const char* filename, base::unique_fd sendPipeFd,
+ base::unique_fd recvPipeFd);
+
+} // namespace android
diff --git a/libs/gui/tests/testserver/aidl/libgui_test_server/ITestServer.aidl b/libs/gui/tests/testserver/aidl/libgui_test_server/ITestServer.aidl
new file mode 100644
index 0000000000..c939ea00c1
--- /dev/null
+++ b/libs/gui/tests/testserver/aidl/libgui_test_server/ITestServer.aidl
@@ -0,0 +1,12 @@
+package libgui_test_server;
+
+import android.view.Surface;
+
+// Test server for libgui_test
+interface ITestServer {
+ // Create a new producer. The server will have connected to the consumer.
+ Surface createProducer();
+
+ // Kills the server immediately.
+ void killNow();
+}
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp
index 7c15e7cf92..84c2a6ac71 100644
--- a/libs/gui/view/Surface.cpp
+++ b/libs/gui/view/Surface.cpp
@@ -121,5 +121,11 @@ String16 Surface::readMaybeEmptyString16(const Parcel* parcel) {
return str.value_or(String16());
}
+std::string Surface::toString() const {
+ std::stringstream out;
+ out << name;
+ return out.str();
+}
+
} // namespace view
} // namespace android
diff --git a/libs/input/Resampler.cpp b/libs/input/Resampler.cpp
index 836a97af53..342f7f557f 100644
--- a/libs/input/Resampler.cpp
+++ b/libs/input/Resampler.cpp
@@ -60,8 +60,8 @@ inline float lerp(float a, float b, float alpha) {
return a + alpha * (b - a);
}
-const PointerCoords calculateResampledCoords(const PointerCoords& a, const PointerCoords& b,
- const float alpha) {
+PointerCoords calculateResampledCoords(const PointerCoords& a, const PointerCoords& b,
+ float alpha) {
// We use the value of alpha to initialize resampledCoords with the latest sample information.
PointerCoords resampledCoords = (alpha < 1.0f) ? a : b;
resampledCoords.isResampled = true;
@@ -72,52 +72,85 @@ const PointerCoords calculateResampledCoords(const PointerCoords& a, const Point
} // namespace
void LegacyResampler::updateLatestSamples(const MotionEvent& motionEvent) {
- const size_t motionEventSampleSize = motionEvent.getHistorySize() + 1;
- for (size_t i = 0; i < motionEventSampleSize; ++i) {
- Sample sample{static_cast<nanoseconds>(motionEvent.getHistoricalEventTime(i)),
- *motionEvent.getPointerProperties(0),
- motionEvent.getSamplePointerCoords()[i]};
- mLatestSamples.pushBack(sample);
+ const size_t numSamples = motionEvent.getHistorySize() + 1;
+ for (size_t i = 0; i < numSamples; ++i) {
+ mLatestSamples.pushBack(
+ Sample{static_cast<nanoseconds>(motionEvent.getHistoricalEventTime(i)),
+ Pointer{*motionEvent.getPointerProperties(0),
+ motionEvent.getSamplePointerCoords()[i]}});
}
}
-void LegacyResampler::interpolate(const nanoseconds resampleTime, MotionEvent& motionEvent,
- const InputMessage& futureSample) const {
- const Sample pastSample = mLatestSamples.back();
+bool LegacyResampler::canInterpolate(const InputMessage& futureSample) const {
+ LOG_IF(FATAL, mLatestSamples.empty())
+ << "Not resampled. mLatestSamples must not be empty to interpolate.";
+
+ const Sample& pastSample = *(mLatestSamples.end() - 1);
const nanoseconds delta =
static_cast<nanoseconds>(futureSample.body.motion.eventTime) - pastSample.eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
LOG_IF(INFO, debugResampling()) << "Not resampled. Delta is too small: " << delta << "ns.";
- return;
+ return false;
+ }
+ return true;
+}
+
+std::optional<LegacyResampler::Sample> LegacyResampler::attemptInterpolation(
+ nanoseconds resampleTime, const InputMessage& futureSample) const {
+ if (!canInterpolate(futureSample)) {
+ return std::nullopt;
}
+ LOG_IF(FATAL, mLatestSamples.empty())
+ << "Not resampled. mLatestSamples must not be empty to interpolate.";
+
+ const Sample& pastSample = *(mLatestSamples.end() - 1);
+ const nanoseconds delta =
+ static_cast<nanoseconds>(futureSample.body.motion.eventTime) - pastSample.eventTime;
const float alpha =
std::chrono::duration<float, std::milli>(resampleTime - pastSample.eventTime) / delta;
-
const PointerCoords resampledCoords =
calculateResampledCoords(pastSample.pointer.coords,
futureSample.body.motion.pointers[0].coords, alpha);
- motionEvent.addSample(resampleTime.count(), &resampledCoords, motionEvent.getId());
+
+ return Sample{resampleTime, Pointer{pastSample.pointer.properties, resampledCoords}};
}
-void LegacyResampler::extrapolate(const nanoseconds resampleTime, MotionEvent& motionEvent) const {
+bool LegacyResampler::canExtrapolate() const {
if (mLatestSamples.size() < 2) {
- return;
+ LOG_IF(INFO, debugResampling()) << "Not resampled. Not enough data.";
+ return false;
}
- const Sample pastSample = *(mLatestSamples.end() - 2);
- const Sample presentSample = *(mLatestSamples.end() - 1);
- const nanoseconds delta =
- static_cast<nanoseconds>(presentSample.eventTime - pastSample.eventTime);
+
+ const Sample& pastSample = *(mLatestSamples.end() - 2);
+ const Sample& presentSample = *(mLatestSamples.end() - 1);
+
+ const nanoseconds delta = presentSample.eventTime - pastSample.eventTime;
if (delta < RESAMPLE_MIN_DELTA) {
LOG_IF(INFO, debugResampling()) << "Not resampled. Delta is too small: " << delta << "ns.";
- return;
+ return false;
} else if (delta > RESAMPLE_MAX_DELTA) {
LOG_IF(INFO, debugResampling()) << "Not resampled. Delta is too large: " << delta << "ns.";
- return;
+ return false;
}
+ return true;
+}
+
+std::optional<LegacyResampler::Sample> LegacyResampler::attemptExtrapolation(
+ nanoseconds resampleTime) const {
+ if (!canExtrapolate()) {
+ return std::nullopt;
+ }
+ LOG_IF(FATAL, mLatestSamples.size() < 2)
+ << "Not resampled. mLatestSamples must have at least two samples to extrapolate.";
+
+ const Sample& pastSample = *(mLatestSamples.end() - 2);
+ const Sample& presentSample = *(mLatestSamples.end() - 1);
+
+ const nanoseconds delta = presentSample.eventTime - pastSample.eventTime;
// The farthest future time to which we can extrapolate. If the given resampleTime exceeds this,
// we use this value as the resample time target.
- const nanoseconds farthestPrediction = static_cast<nanoseconds>(presentSample.eventTime) +
- std::min<nanoseconds>(delta / 2, RESAMPLE_MAX_PREDICTION);
+ const nanoseconds farthestPrediction =
+ presentSample.eventTime + std::min<nanoseconds>(delta / 2, RESAMPLE_MAX_PREDICTION);
const nanoseconds newResampleTime =
(resampleTime > farthestPrediction) ? (farthestPrediction) : (resampleTime);
LOG_IF(INFO, debugResampling() && newResampleTime == farthestPrediction)
@@ -127,25 +160,32 @@ void LegacyResampler::extrapolate(const nanoseconds resampleTime, MotionEvent& m
const float alpha =
std::chrono::duration<float, std::milli>(newResampleTime - pastSample.eventTime) /
delta;
-
const PointerCoords resampledCoords =
calculateResampledCoords(pastSample.pointer.coords, presentSample.pointer.coords,
alpha);
- motionEvent.addSample(newResampleTime.count(), &resampledCoords, motionEvent.getId());
+
+ return Sample{newResampleTime, Pointer{presentSample.pointer.properties, resampledCoords}};
+}
+
+inline void LegacyResampler::addSampleToMotionEvent(const Sample& sample,
+ MotionEvent& motionEvent) {
+ motionEvent.addSample(sample.eventTime.count(), &sample.pointer.coords, motionEvent.getId());
}
-void LegacyResampler::resampleMotionEvent(const nanoseconds resampleTime, MotionEvent& motionEvent,
+void LegacyResampler::resampleMotionEvent(nanoseconds resampleTime, MotionEvent& motionEvent,
const InputMessage* futureSample) {
if (mPreviousDeviceId && *mPreviousDeviceId != motionEvent.getDeviceId()) {
mLatestSamples.clear();
}
mPreviousDeviceId = motionEvent.getDeviceId();
+
updateLatestSamples(motionEvent);
- if (futureSample) {
- interpolate(resampleTime, motionEvent, *futureSample);
- } else {
- extrapolate(resampleTime, motionEvent);
+
+ const std::optional<Sample> sample = (futureSample != nullptr)
+ ? (attemptInterpolation(resampleTime, *futureSample))
+ : (attemptExtrapolation(resampleTime));
+ if (sample.has_value()) {
+ addSampleToMotionEvent(*sample, motionEvent);
}
- LOG_IF(INFO, debugResampling()) << "Not resampled. Not enough data.";
}
} // namespace android
diff --git a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp
index 1dbcc29190..4164c4b4c9 100644
--- a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp
+++ b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.cpp
@@ -19,6 +19,7 @@
#include <SkRuntimeEffect.h>
#include <SkStream.h>
#include <SkString.h>
+#include <com_android_graphics_libgui_flags.h>
#include "log/log_main.h"
namespace android::renderengine::skia {
@@ -56,25 +57,33 @@ static const SkString edgeShader = SkString(R"(
}
)");
+EdgeExtensionShaderFactory::EdgeExtensionShaderFactory() {
+ if (!com::android::graphics::libgui::flags::edge_extension_shader()) {
+ return;
+ }
+ mResult = std::make_unique<SkRuntimeEffect::Result>(SkRuntimeEffect::MakeForShader(edgeShader));
+ LOG_ALWAYS_FATAL_IF(!mResult->errorText.isEmpty(),
+ "EdgeExtensionShaderFactory compilation "
+ "failed with an unexpected error: %s",
+ mResult->errorText.c_str());
+}
+
sk_sp<SkShader> EdgeExtensionShaderFactory::createSkShader(const sk_sp<SkShader>& inputShader,
const LayerSettings& layer,
- const SkRect& imageBounds) {
- if (mBuilder == nullptr) {
- const static SkRuntimeEffect::Result instance = SkRuntimeEffect::MakeForShader(edgeShader);
- if (!instance.errorText.isEmpty()) {
- ALOGE("EdgeExtensionShaderFactory terminated with an error: %s",
- instance.errorText.c_str());
- return nullptr;
- }
- mBuilder = std::make_unique<SkRuntimeShaderBuilder>(instance.effect);
- }
- mBuilder->child("uContentTexture") = inputShader;
+ const SkRect& imageBounds) const {
+ LOG_ALWAYS_FATAL_IF(mResult == nullptr,
+ "EdgeExtensionShaderFactory did not initialize mResult. "
+ "This means that we unexpectedly applied the edge extension shader");
+
+ SkRuntimeShaderBuilder builder = SkRuntimeShaderBuilder(mResult->effect);
+
+ builder.child("uContentTexture") = inputShader;
if (imageBounds.isEmpty()) {
- mBuilder->uniform("uImgSize") = SkPoint{layer.geometry.boundaries.getWidth(),
- layer.geometry.boundaries.getHeight()};
+ builder.uniform("uImgSize") = SkPoint{layer.geometry.boundaries.getWidth(),
+ layer.geometry.boundaries.getHeight()};
} else {
- mBuilder->uniform("uImgSize") = SkPoint{imageBounds.width(), imageBounds.height()};
+ builder.uniform("uImgSize") = SkPoint{imageBounds.width(), imageBounds.height()};
}
- return mBuilder->makeShader();
+ return builder.makeShader();
}
} // namespace android::renderengine::skia \ No newline at end of file
diff --git a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h
index b0a8a9357e..17c6b9139f 100644
--- a/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h
+++ b/libs/renderengine/skia/filters/EdgeExtensionShaderFactory.h
@@ -33,10 +33,12 @@ namespace android::renderengine::skia {
*/
class EdgeExtensionShaderFactory {
public:
+ EdgeExtensionShaderFactory();
+
sk_sp<SkShader> createSkShader(const sk_sp<SkShader>& inputShader, const LayerSettings& layer,
- const SkRect& imageBounds);
+ const SkRect& imageBounds) const;
private:
- std::unique_ptr<SkRuntimeShaderBuilder> mBuilder;
+ std::unique_ptr<const SkRuntimeEffect::Result> mResult;
};
} // namespace android::renderengine::skia
diff --git a/libs/ui/include/ui/Fence.h b/libs/ui/include/ui/Fence.h
index 9aae145c04..a75ba37d2c 100644
--- a/libs/ui/include/ui/Fence.h
+++ b/libs/ui/include/ui/Fence.h
@@ -156,6 +156,6 @@ private:
base::unique_fd mFenceFd;
};
-}; // namespace android
+} // namespace android
#endif // ANDROID_FENCE_H
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 652d8ba709..936bf8f862 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -297,6 +297,6 @@ private:
mDeathCallbacks;
};
-}; // namespace android
+} // namespace android
#endif // ANDROID_GRAPHIC_BUFFER_H
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index bbb2d77058..97ed05af6d 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -137,6 +137,6 @@ protected:
};
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_BUFFER_ALLOCATOR_H
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 9da1447aed..91aabe9f12 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -188,7 +188,7 @@ private:
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
#endif // ANDROID_UI_BUFFER_MAPPER_H
diff --git a/libs/ui/include/ui/PixelFormat.h b/libs/ui/include/ui/PixelFormat.h
index cf5c2e8c12..1f20787bb0 100644
--- a/libs/ui/include/ui/PixelFormat.h
+++ b/libs/ui/include/ui/PixelFormat.h
@@ -72,6 +72,6 @@ typedef int32_t PixelFormat;
uint32_t bytesPerPixel(PixelFormat format);
-}; // namespace android
+} // namespace android
#endif // UI_PIXELFORMAT_H
diff --git a/libs/ui/include/ui/Point.h b/libs/ui/include/ui/Point.h
index d050ede02d..97a54beca7 100644
--- a/libs/ui/include/ui/Point.h
+++ b/libs/ui/include/ui/Point.h
@@ -83,6 +83,6 @@ public:
ANDROID_BASIC_TYPES_TRAITS(Point)
-}; // namespace android
+} // namespace android
#endif // ANDROID_UI_POINT
diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
index 9e24a077ff..2eb9330cc9 100644
--- a/libs/ui/include/ui/Rect.h
+++ b/libs/ui/include/ui/Rect.h
@@ -233,7 +233,7 @@ void PrintTo(const Rect& rect, ::std::ostream* os);
ANDROID_BASIC_TYPES_TRAITS(Rect)
-}; // namespace android
+} // namespace android
namespace std {
template <>
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 927c334c85..d1b38f3bd3 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -233,7 +233,7 @@ static inline void PrintTo(const Region& region, ::std::ostream* os) {
}
// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
namespace std {
template <>
diff --git a/opengl/Android.bp b/opengl/Android.bp
index 4454f36b67..37dc9314e2 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -30,6 +30,10 @@ ndk_headers {
to: "",
srcs: ["include/EGL/**/*.h"],
license: "include/EGL/NOTICE",
+ // eglext.h is not self-contained. Safe to skip C-compat verification
+ // though since upstream also cares about C compatibility, and the header is
+ // auto-generated anyway.
+ skip_verification: true,
}
ndk_headers {
@@ -38,6 +42,10 @@ ndk_headers {
to: "",
srcs: ["include/GLES/**/*.h"],
license: "include/GLES/NOTICE",
+ // glext.h is not self-contained. Safe to skip C-compat verification
+ // though since upstream also cares about C compatibility, and the header is
+ // auto-generated anyway.
+ skip_verification: true,
}
ndk_headers {
@@ -46,6 +54,10 @@ ndk_headers {
to: "",
srcs: ["include/GLES2/**/*.h"],
license: "include/GLES2/NOTICE",
+ // gl2ext.h is not self-contained. Safe to skip C-compat verification
+ // though since upstream also cares about C compatibility, and the header is
+ // auto-generated anyway.
+ skip_verification: true,
}
ndk_headers {
diff --git a/services/inputflinger/PointerChoreographer.cpp b/services/inputflinger/PointerChoreographer.cpp
index 625599a775..397fedac4c 100644
--- a/services/inputflinger/PointerChoreographer.cpp
+++ b/services/inputflinger/PointerChoreographer.cpp
@@ -511,8 +511,9 @@ void PointerChoreographer::dump(std::string& dump) {
std::scoped_lock _l(mLock);
dump += "PointerChoreographer:\n";
- dump += StringPrintf("show touches: %s\n", mShowTouchesEnabled ? "true" : "false");
- dump += StringPrintf("stylus pointer icon enabled: %s\n",
+ dump += StringPrintf(INDENT "Show Touches Enabled: %s\n",
+ mShowTouchesEnabled ? "true" : "false");
+ dump += StringPrintf(INDENT "Stylus PointerIcon Enabled: %s\n",
mStylusPointerIconEnabled ? "true" : "false");
dump += INDENT "MousePointerControllers:\n";
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 0384257c35..bcef35021e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2713,7 +2713,8 @@ InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime, const Motio
{
std::vector<TouchedWindow> hoveringWindows =
getHoveringWindowsLocked(oldState, tempTouchState, entry,
- [this]() REQUIRES(mLock) { logDispatchStateLocked(); });
+ std::bind_front(&InputDispatcher::logDispatchStateLocked,
+ this));
// Hardcode to single hovering pointer for now.
std::bitset<MAX_POINTER_ID + 1> pointerIds;
pointerIds.set(entry.pointerProperties[0].id);
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 42a03c10ca..76aa6eb887 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -227,6 +227,9 @@ struct InputReaderConfiguration {
// True to enable tap dragging on touchpads.
bool touchpadTapDraggingEnabled;
+ // True if hardware state update notifications should be sent to the policy.
+ bool shouldNotifyTouchpadHardwareState;
+
// True to enable a zone on the right-hand side of touchpads where clicks will be turned into
// context (a.k.a. "right") clicks.
bool touchpadRightClickZoneEnabled;
@@ -268,6 +271,7 @@ struct InputReaderConfiguration {
touchpadNaturalScrollingEnabled(true),
touchpadTapToClickEnabled(true),
touchpadTapDraggingEnabled(false),
+ shouldNotifyTouchpadHardwareState(false),
touchpadRightClickZoneEnabled(false),
stylusButtonMotionEventsEnabled(true),
stylusPointerIconEnabled(false) {}
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 5c5fd3fb5f..588dc0c520 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -372,6 +372,7 @@ std::list<NotifyArgs> TouchpadInputMapper::reconfigure(nsecs_t when,
.setBoolValues({config.touchpadTapDraggingEnabled});
mPropertyProvider.getProperty("Button Right Click Zone Enable")
.setBoolValues({config.touchpadRightClickZoneEnabled});
+ mTouchpadHardwareStateNotificationsEnabled = config.shouldNotifyTouchpadHardwareState;
}
std::list<NotifyArgs> out;
if ((!changes.any() && config.pointerCaptureRequest.isEnable()) ||
@@ -421,6 +422,11 @@ std::list<NotifyArgs> TouchpadInputMapper::process(const RawEvent& rawEvent) {
}
std::optional<SelfContainedHardwareState> state = mStateConverter.processRawEvent(rawEvent);
if (state) {
+ if (mTouchpadHardwareStateNotificationsEnabled) {
+ // TODO(b/286551975): Notify policy of the touchpad hardware state.
+ LOG(DEBUG) << "Notify touchpad hardware state here!";
+ }
+
updatePalmDetectionMetrics();
return sendHardwareState(rawEvent.when, rawEvent.readTime, *state);
} else {
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.h b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
index 8baa63e8e0..4856fe0474 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.h
@@ -112,6 +112,10 @@ private:
std::optional<ui::LogicalDisplayId> mDisplayId;
nsecs_t mGestureStartTime{0};
+
+ // True if hardware state update notifications is available for usage based on its feature flag
+ // and settings value.
+ bool mTouchpadHardwareStateNotificationsEnabled = false;
};
} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index ed4c47dc87..b4ac9ba741 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -149,6 +149,7 @@ cc_test {
"tests/CompositionEngineTest.cpp",
"tests/DisplayColorProfileTest.cpp",
"tests/DisplayTest.cpp",
+ "tests/HwcAsyncWorkerTest.cpp",
"tests/HwcBufferCacheTest.cpp",
"tests/MockHWC2.cpp",
"tests/MockHWComposer.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
index 6086f0be3f..91385b4ff3 100644
--- a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
@@ -24,6 +24,7 @@
#include <android-base/thread_annotations.h>
#include <cutils/sched_policy.h>
+#include <ftl/fake_guard.h>
namespace android::compositionengine::impl {
@@ -60,7 +61,7 @@ void HwcAsyncWorker::run() {
std::unique_lock<std::mutex> lock(mMutex);
android::base::ScopedLockAssertion assumeLock(mMutex);
while (!mDone) {
- mCv.wait(lock);
+ mCv.wait(lock, [this]() FTL_FAKE_GUARD(mMutex) { return mTaskRequested || mDone; });
if (mTaskRequested && mTask.valid()) {
mTask();
mTaskRequested = false;
diff --git a/services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp
new file mode 100644
index 0000000000..dd04df6d6b
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/HwcAsyncWorkerTest.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <future>
+
+#include <compositionengine/impl/HwcAsyncWorker.h>
+#include <gtest/gtest.h>
+
+namespace android::compositionengine {
+namespace {
+
+using namespace std::chrono_literals;
+
+// For the edge case tests below, how much real time should be spent trying to reproduce edge cases
+// problems in a loop.
+//
+// Larger values mean problems are more likely to be detected, at the cost of making the unit test
+// run slower.
+//
+// As we expect the tests to be run continuously, even a short loop will eventually catch
+// problems, though not necessarily from changes in the same build that introduce them.
+constexpr auto kWallTimeForEdgeCaseTests = 5ms;
+
+TEST(HwcAsyncWorker, continuousTasksEdgeCase) {
+ // Ensures that a single worker that is given multiple tasks in short succession will run them.
+
+ impl::HwcAsyncWorker worker;
+ const auto endTime = std::chrono::steady_clock::now() + kWallTimeForEdgeCaseTests;
+ while (std::chrono::steady_clock::now() < endTime) {
+ auto f1 = worker.send([] { return false; });
+ EXPECT_FALSE(f1.get());
+ auto f2 = worker.send([] { return true; });
+ EXPECT_TRUE(f2.get());
+ }
+}
+
+TEST(HwcAsyncWorker, constructAndDestroyEdgeCase) {
+ // Ensures that newly created HwcAsyncWorkers can be immediately destroyed.
+
+ const auto endTime = std::chrono::steady_clock::now() + kWallTimeForEdgeCaseTests;
+ while (std::chrono::steady_clock::now() < endTime) {
+ impl::HwcAsyncWorker worker;
+ }
+}
+
+TEST(HwcAsyncWorker, newlyCreatedRunsTasksEdgeCase) {
+ // Ensures that newly created HwcAsyncWorkers will run a task if given one immediately.
+
+ const auto endTime = std::chrono::steady_clock::now() + kWallTimeForEdgeCaseTests;
+ while (std::chrono::steady_clock::now() < endTime) {
+ impl::HwcAsyncWorker worker;
+ auto f = worker.send([] { return true; });
+ f.get();
+ }
+}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/Display/DisplayModeController.cpp b/services/surfaceflinger/Display/DisplayModeController.cpp
index c43d585270..0e9218cb93 100644
--- a/services/surfaceflinger/Display/DisplayModeController.cpp
+++ b/services/surfaceflinger/Display/DisplayModeController.cpp
@@ -22,7 +22,9 @@
#include "Display/DisplaySnapshot.h"
#include "DisplayHardware/HWComposer.h"
+#include <android-base/properties.h>
#include <common/FlagManager.h>
+#include <common/trace.h>
#include <ftl/concat.h>
#include <ftl/expected.h>
#include <log/log.h>
@@ -237,4 +239,63 @@ void DisplayModeController::setActiveModeLocked(PhysicalDisplayId displayId, Dis
}
}
+void DisplayModeController::updateKernelIdleTimer(PhysicalDisplayId displayId) {
+ std::lock_guard lock(mDisplayLock);
+ const auto& displayPtr = FTL_TRY(mDisplays.get(displayId).ok_or(ftl::Unit())).get();
+
+ const auto controllerOpt = displayPtr->selectorPtr->kernelIdleTimerController();
+ if (!controllerOpt) return;
+
+ using KernelIdleTimerAction = scheduler::RefreshRateSelector::KernelIdleTimerAction;
+
+ switch (displayPtr->selectorPtr->getIdleTimerAction()) {
+ case KernelIdleTimerAction::TurnOff:
+ if (displayPtr->isKernelIdleTimerEnabled) {
+ SFTRACE_INT("KernelIdleTimer", 0);
+ updateKernelIdleTimer(displayId, std::chrono::milliseconds::zero(), *controllerOpt);
+ displayPtr->isKernelIdleTimerEnabled = false;
+ }
+ break;
+ case KernelIdleTimerAction::TurnOn:
+ if (!displayPtr->isKernelIdleTimerEnabled) {
+ SFTRACE_INT("KernelIdleTimer", 1);
+ const auto timeout = displayPtr->selectorPtr->getIdleTimerTimeout();
+ updateKernelIdleTimer(displayId, timeout, *controllerOpt);
+ displayPtr->isKernelIdleTimerEnabled = true;
+ }
+ break;
+ }
+}
+
+void DisplayModeController::updateKernelIdleTimer(PhysicalDisplayId displayId,
+ std::chrono::milliseconds timeout,
+ KernelIdleTimerController controller) {
+ switch (controller) {
+ case KernelIdleTimerController::HwcApi:
+ mComposerPtr->setIdleTimerEnabled(displayId, timeout);
+ break;
+
+ case KernelIdleTimerController::Sysprop:
+ using namespace std::string_literals;
+ base::SetProperty("graphics.display.kernel_idle_timer.enabled"s,
+ timeout > std::chrono::milliseconds::zero() ? "true"s : "false"s);
+ break;
+ }
+}
+
+auto DisplayModeController::getKernelIdleTimerState(PhysicalDisplayId displayId) const
+ -> KernelIdleTimerState {
+ std::lock_guard lock(mDisplayLock);
+ const auto& displayPtr =
+ FTL_EXPECT(mDisplays.get(displayId).ok_or(KernelIdleTimerState())).get();
+
+ const auto desiredModeIdOpt =
+ (std::scoped_lock(displayPtr->desiredModeLock), displayPtr->desiredModeOpt)
+ .transform([](const display::DisplayModeRequest& request) {
+ return request.mode.modePtr->getId();
+ });
+
+ return {desiredModeIdOpt, displayPtr->isKernelIdleTimerEnabled};
+}
+
} // namespace android::display
diff --git a/services/surfaceflinger/Display/DisplayModeController.h b/services/surfaceflinger/Display/DisplayModeController.h
index 258b04b876..9ec603d5f6 100644
--- a/services/surfaceflinger/Display/DisplayModeController.h
+++ b/services/surfaceflinger/Display/DisplayModeController.h
@@ -97,6 +97,17 @@ public:
void setActiveMode(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
EXCLUDES(mDisplayLock);
+ void updateKernelIdleTimer(PhysicalDisplayId) REQUIRES(kMainThreadContext)
+ EXCLUDES(mDisplayLock);
+
+ struct KernelIdleTimerState {
+ std::optional<DisplayModeId> desiredModeIdOpt = std::nullopt;
+ bool isEnabled = false;
+ };
+
+ KernelIdleTimerState getKernelIdleTimerState(PhysicalDisplayId) const
+ REQUIRES(kMainThreadContext) EXCLUDES(mDisplayLock);
+
private:
struct Display {
template <size_t N>
@@ -121,6 +132,8 @@ private:
DisplayModeRequestOpt pendingModeOpt GUARDED_BY(kMainThreadContext);
bool isModeSetPending GUARDED_BY(kMainThreadContext) = false;
+
+ bool isKernelIdleTimerEnabled GUARDED_BY(kMainThreadContext) = false;
};
using DisplayPtr = std::unique_ptr<Display>;
@@ -128,6 +141,10 @@ private:
void setActiveModeLocked(PhysicalDisplayId, DisplayModeId, Fps vsyncRate, Fps renderFps)
REQUIRES(mDisplayLock);
+ using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;
+ void updateKernelIdleTimer(PhysicalDisplayId, std::chrono::milliseconds timeout,
+ KernelIdleTimerController) REQUIRES(mDisplayLock);
+
// Set once when initializing the DisplayModeController, which the HWComposer must outlive.
HWComposer* mComposerPtr = nullptr;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 75b07a8854..402a3d2e2f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -201,19 +201,6 @@ bool DisplayDevice::isPoweredOn() const {
return mPowerMode != hal::PowerMode::OFF;
}
-nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
- const auto physicalId = getPhysicalId();
- if (!mHwComposer.isConnected(physicalId)) {
- return 0;
- }
-
- if (const auto vsyncPeriodOpt = mHwComposer.getDisplayVsyncPeriod(physicalId).value_opt()) {
- return *vsyncPeriodOpt;
- }
-
- return refreshRateSelector().getActiveMode().modePtr->getVsyncRate().getPeriodNsecs();
-}
-
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 1b8a3a8f54..3e3f558cee 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -203,8 +203,6 @@ public:
void updateHdrSdrRatioOverlayRatio(float currentHdrSdrRatio);
bool isHdrSdrRatioOverlayEnabled() const { return mHdrSdrRatioOverlay != nullptr; }
- nsecs_t getVsyncPeriodFromHWC() const;
-
Fps getAdjustedRefreshRate() const { return mAdjustedRefreshRate; }
// Round the requested refresh rate to match a divisor of the pacesetter
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index d50a0bcec1..0eced73ff9 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -44,6 +44,7 @@ using hardware::Return;
using aidl::android::hardware::graphics::composer3::BnComposerCallback;
using aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness;
+using aidl::android::hardware::graphics::composer3::Lut;
using aidl::android::hardware::graphics::composer3::PowerMode;
using aidl::android::hardware::graphics::composer3::VirtualDisplay;
@@ -1539,6 +1540,18 @@ Error AidlComposer::getClientTargetProperty(
return error;
}
+Error AidlComposer::getDisplayLuts(Display display, std::vector<Lut>* outLuts) {
+ Error error = Error::NONE;
+ mMutex.lock_shared();
+ if (auto reader = getReader(display)) {
+ *outLuts = reader->get().takeDisplayLuts(translate<int64_t>(display));
+ } else {
+ error = Error::BAD_DISPLAY;
+ }
+ mMutex.unlock_shared();
+ return error;
+}
+
Error AidlComposer::setLayerBrightness(Display display, Layer layer, float brightness) {
Error error = Error::NONE;
mMutex.lock_shared();
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index ea0e53a202..3669d4c996 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -244,6 +244,9 @@ public:
Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override;
Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime,
int32_t frameIntervalNs) override;
+ Error getDisplayLuts(
+ Display display,
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>* outLuts) override;
private:
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index bc067a0e5d..888dc08134 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -41,6 +41,7 @@
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
#include <aidl/android/hardware/graphics/composer3/DisplayConfiguration.h>
#include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
+#include <aidl/android/hardware/graphics/composer3/Lut.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
#include <aidl/android/hardware/graphics/common/Transform.h>
@@ -303,6 +304,7 @@ public:
virtual Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) = 0;
virtual Error notifyExpectedPresent(Display, nsecs_t expectedPresentTime,
int32_t frameIntervalNs) = 0;
+ virtual Error getDisplayLuts(Display display, std::vector<V3_0::Lut>* outLuts) = 0;
};
} // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index c77cdd4432..748765a4e4 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -31,10 +31,11 @@
#include <utils/String8.h>
#include <log/log.h>
-#include <hardware/hardware.h>
+#include <com_android_graphics_libgui_flags.h>
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/Surface.h>
+#include <hardware/hardware.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
@@ -48,10 +49,18 @@ namespace android {
using ui::Dataspace;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
+ const sp<IGraphicBufferProducer>& producer,
+ const sp<IGraphicBufferConsumer>& consumer,
+ const ui::Size& size, const ui::Size& maxSize)
+ : ConsumerBase(producer, consumer),
+#else
FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
const sp<IGraphicBufferConsumer>& consumer,
const ui::Size& size, const ui::Size& maxSize)
: ConsumerBase(consumer),
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
mDisplayId(displayId),
mMaxSize(maxSize),
mCurrentBufferSlot(-1),
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 2728cf637e..6ca64a2437 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <com_android_graphics_libgui_flags.h>
#include <compositionengine/DisplaySurface.h>
#include <gui/BufferQueue.h>
#include <gui/ConsumerBase.h>
@@ -40,9 +41,16 @@ class HWComposer;
class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
public:
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
+ const sp<IGraphicBufferProducer>& producer,
const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
const ui::Size& maxSize);
+#else
+ FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
+ const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
+ const ui::Size& maxSize);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 8c0f81e051..d5f65c6211 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -41,6 +41,7 @@ using aidl::android::hardware::graphics::composer3::Color;
using aidl::android::hardware::graphics::composer3::Composition;
using AidlCapability = aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
+using aidl::android::hardware::graphics::composer3::Lut;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
namespace android {
@@ -607,6 +608,18 @@ Error Display::getClientTargetProperty(
return static_cast<Error>(error);
}
+Error Display::getDisplayLuts(std::vector<Lut>* outLuts) {
+ std::vector<Lut> tmpLuts;
+ const auto error = mComposer.getDisplayLuts(mId, &tmpLuts);
+ for (Lut& lut : tmpLuts) {
+ if (lut.pfd.get() >= 0) {
+ outLuts->push_back(
+ {lut.layer, ndk::ScopedFileDescriptor(lut.pfd.release()), lut.lutProperties});
+ }
+ }
+ return static_cast<Error>(error);
+}
+
Error Display::getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 5b948318ae..be2059a935 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -45,6 +45,7 @@
#include <aidl/android/hardware/graphics/composer3/Color.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
+#include <aidl/android/hardware/graphics/composer3/Lut.h>
#include <aidl/android/hardware/graphics/composer3/OverlayProperties.h>
#include <aidl/android/hardware/graphics/composer3/RefreshRateChangedDebugData.h>
@@ -178,6 +179,8 @@ public:
[[nodiscard]] virtual hal::Error getClientTargetProperty(
aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness*
outClientTargetProperty) = 0;
+ [[nodiscard]] virtual hal::Error getDisplayLuts(
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>* outLuts) = 0;
[[nodiscard]] virtual hal::Error getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) = 0;
@@ -261,6 +264,8 @@ public:
hal::Error getClientTargetProperty(
aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness*
outClientTargetProperty) override;
+ hal::Error getDisplayLuts(
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>* outLuts) override;
hal::Error getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) override;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 7c4aa7530d..ec2a3ec024 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -46,6 +46,7 @@ using aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::ClientTargetPropertyWithBrightness;
using aidl::android::hardware::graphics::composer3::DimmingStage;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
+using aidl::android::hardware::graphics::composer3::Lut;
using aidl::android::hardware::graphics::composer3::OverlayProperties;
namespace android {
@@ -1408,6 +1409,10 @@ Error HidlComposer::getClientTargetProperty(
return Error::NONE;
}
+Error HidlComposer::getDisplayLuts(Display, std::vector<Lut>*) {
+ return Error::NONE;
+}
+
Error HidlComposer::setLayerBrightness(Display, Layer, float) {
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index d78bfb7c6b..8bca5ad31f 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -351,6 +351,8 @@ public:
Hdr*) override;
Error setRefreshRateChangedCallbackDebugEnabled(Display, bool) override;
Error notifyExpectedPresent(Display, nsecs_t, int32_t) override;
+ Error getDisplayLuts(Display,
+ std::vector<aidl::android::hardware::graphics::composer3::Lut>*) override;
private:
class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 4b5a68cefa..384f7b22c7 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -22,6 +22,7 @@
#include <cinttypes>
+#include <com_android_graphics_libgui_flags.h>
#include <ftl/enum.h>
#include <ftl/flags.h>
#include <gui/BufferItem.h>
@@ -51,7 +52,11 @@ VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, VirtualDisplayId d
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
const std::string& name)
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ : ConsumerBase(bqProducer, bqConsumer),
+#else
: ConsumerBase(bqConsumer),
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
mHwc(hwc),
mDisplayId(displayId),
mDisplayName(name),
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index f4335f36bc..d709530990 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -18,6 +18,8 @@
#undef LOG_TAG
#define LOG_TAG "SurfaceFlinger"
+#include <android-base/logging.h>
+
#include "LayerHierarchy.h"
#include "LayerLog.h"
#include "SwapErase.h"
@@ -485,6 +487,55 @@ LayerHierarchy* LayerHierarchyBuilder::getHierarchyFromId(uint32_t layerId, bool
return it->second;
}
+void LayerHierarchyBuilder::logSampledChildren(const LayerHierarchy& hierarchy) const {
+ LOG(ERROR) << "Dumping random sampling of child layers.";
+ int sampleSize = static_cast<int>(hierarchy.mChildren.size() / 100 + 1);
+ for (const auto& [child, variant] : hierarchy.mChildren) {
+ if (rand() % sampleSize == 0) {
+ LOG(ERROR) << "Child Layer: " << *(child->mLayer);
+ }
+ }
+}
+
+void LayerHierarchyBuilder::dumpLayerSample(const LayerHierarchy& root) const {
+ LOG(ERROR) << "Dumping layer keeping > 20 children alive:";
+ // If mLayer is nullptr, it will be skipped while traversing.
+ if (!root.mLayer && root.mChildren.size() > 20) {
+ LOG(ERROR) << "ROOT has " << root.mChildren.size() << " children";
+ logSampledChildren(root);
+ }
+ root.traverse([&](const LayerHierarchy& hierarchy, const auto&) -> bool {
+ if (hierarchy.mChildren.size() <= 20) {
+ return true;
+ }
+ // mLayer is ensured to be non-null. See LayerHierarchy::traverse.
+ const auto* layer = hierarchy.mLayer;
+ const auto childrenCount = hierarchy.mChildren.size();
+ LOG(ERROR) << "Layer " << *layer << " has " << childrenCount << " children";
+
+ const auto* parent = hierarchy.mParent;
+ while (parent != nullptr) {
+ if (!parent->mLayer) break;
+ LOG(ERROR) << "Parent Layer: " << *(parent->mLayer);
+ parent = parent->mParent;
+ }
+
+ logSampledChildren(hierarchy);
+ // Stop traversing.
+ return false;
+ });
+ LOG(ERROR) << "Dumping random sampled layers.";
+ size_t numLayers = 0;
+ root.traverse([&](const LayerHierarchy& hierarchy, const auto&) -> bool {
+ if (hierarchy.mLayer) numLayers++;
+ if ((rand() % 20 == 13) && hierarchy.mLayer) {
+ LOG(ERROR) << "Layer: " << *(hierarchy.mLayer);
+ }
+ return true;
+ });
+ LOG(ERROR) << "Total layer count: " << numLayers;
+}
+
const LayerHierarchy::TraversalPath LayerHierarchy::TraversalPath::ROOT =
{.id = UNASSIGNED_LAYER_ID, .variant = LayerHierarchy::Attached};
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index d023f9e9f5..47d0041a8b 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -211,8 +211,11 @@ public:
const LayerHierarchy& getHierarchy() const;
const LayerHierarchy& getOffscreenHierarchy() const;
std::string getDebugString(uint32_t layerId, uint32_t depth = 0) const;
+ void dumpLayerSample(const LayerHierarchy& layerHierarchy) const;
private:
+ void logSampledChildren(const LayerHierarchy& hierarchy) const;
+
void onLayerAdded(RequestedLayerState* layer);
void attachToParent(LayerHierarchy*);
void detachFromParent(LayerHierarchy*);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index c874db358e..ac15b92175 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -1265,6 +1265,12 @@ void LayerSnapshotBuilder::forEachSnapshot(const Visitor& visitor,
}
}
+void LayerSnapshotBuilder::forEachSnapshot(const ConstVisitor& visitor) const {
+ for (auto& snapshot : mSnapshots) {
+ visitor(*snapshot);
+ }
+}
+
void LayerSnapshotBuilder::forEachInputSnapshot(const ConstVisitor& visitor) const {
for (int i = mNumInterestingSnapshots - 1; i >= 0; i--) {
LayerSnapshot& snapshot = *mSnapshots[(size_t)i];
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 207e23a4c1..486cb33959 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -91,6 +91,9 @@ public:
// snapshots in z-order
void forEachSnapshot(const Visitor& visitor, const ConstPredicate& predicate);
+ // Visit each snapshot
+ void forEachSnapshot(const ConstVisitor& visitor) const;
+
// Visit each snapshot interesting to input reverse z-order
void forEachInputSnapshot(const ConstVisitor& visitor) const;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 26834ebeb3..636f7bdabf 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -317,7 +317,6 @@ void Layer::addToCurrentState() {
if (mRemovedFromDrawingState) {
mRemovedFromDrawingState = false;
mFlinger->mScheduler->registerLayer(this, FrameRateCompatibility::Default);
- mFlinger->removeFromOffscreenLayers(this);
}
for (const auto& child : mCurrentChildren) {
@@ -1350,14 +1349,6 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const {
return usage;
}
-void Layer::updateTransformHint(ui::Transform::RotationFlags transformHint) {
- if (mFlinger->mDebugDisableTransformHint || transformHint & ui::Transform::ROT_INVALID) {
- transformHint = ui::Transform::ROT_0;
- }
-
- setTransformHintLegacy(transformHint);
-}
-
// ----------------------------------------------------------------------------
// debugging
// ----------------------------------------------------------------------------
@@ -3792,7 +3783,8 @@ void Layer::onCompositionPresented(const DisplayDevice* display,
}
if (display) {
- const Fps refreshRate = display->refreshRateSelector().getActiveMode().fps;
+ const auto activeMode = display->refreshRateSelector().getActiveMode();
+ const Fps refreshRate = activeMode.fps;
const std::optional<Fps> renderRate =
mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
@@ -3812,7 +3804,12 @@ void Layer::onCompositionPresented(const DisplayDevice* display,
mFlinger->getHwComposer().getPresentTimestamp(*displayId);
const nsecs_t now = systemTime(CLOCK_MONOTONIC);
- const nsecs_t vsyncPeriod = display->getVsyncPeriodFromHWC();
+ const nsecs_t vsyncPeriod =
+ mFlinger->getHwComposer()
+ .getDisplayVsyncPeriod(*displayId)
+ .value_opt()
+ .value_or(activeMode.modePtr->getVsyncRate().getPeriodNsecs());
+
const nsecs_t actualPresentTime = now - ((now - presentTimestamp) % vsyncPeriod);
mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
@@ -3995,13 +3992,6 @@ sp<GraphicBuffer> Layer::getBuffer() const {
return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr;
}
-void Layer::setTransformHintLegacy(ui::Transform::RotationFlags displayTransformHint) {
- mTransformHintLegacy = getFixedTransformHint();
- if (mTransformHintLegacy == ui::Transform::ROT_INVALID) {
- mTransformHintLegacy = displayTransformHint;
- }
-}
-
const std::shared_ptr<renderengine::ExternalTexture>& Layer::getExternalTexture() const {
return mBufferInfo.mBuffer;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 948c62df3c..f6eed6332b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -687,10 +687,6 @@ public:
*/
void addToCurrentState();
- /*
- * Sets display transform hint on BufferLayerConsumer.
- */
- void updateTransformHint(ui::Transform::RotationFlags);
inline const State& getDrawingState() const { return mDrawingState; }
inline State& getDrawingState() { return mDrawingState; }
@@ -1212,13 +1208,11 @@ private:
bool findInHierarchy(const sp<Layer>&);
- void setTransformHintLegacy(ui::Transform::RotationFlags);
void releasePreviousBuffer();
void resetDrawingStateBufferInfo();
// Transform hint provided to the producer. This must be accessed holding
// the mStateLock.
- ui::Transform::RotationFlags mTransformHintLegacy = ui::Transform::ROT_0;
std::optional<ui::Transform::RotationFlags> mTransformHint = std::nullopt;
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 80d5499df9..566bb8ede8 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -122,6 +122,12 @@ void Scheduler::setPacesetterDisplay(PhysicalDisplayId pacesetterId) {
demotePacesetterDisplay(kPromotionParams);
promotePacesetterDisplay(pacesetterId, kPromotionParams);
+
+ // Cancel the pending refresh rate change, if any, before updating the phase configuration.
+ mVsyncModulator->cancelRefreshRateChange();
+
+ mVsyncConfiguration->reset();
+ updatePhaseConfiguration(pacesetterSelectorPtr()->getActiveMode().fps);
}
void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
@@ -488,14 +494,6 @@ void Scheduler::updatePhaseConfiguration(Fps refreshRate) {
refreshRate.getPeriod());
}
-void Scheduler::resetPhaseConfiguration(Fps refreshRate) {
- // Cancel the pending refresh rate change, if any, before updating the phase configuration.
- mVsyncModulator->cancelRefreshRateChange();
-
- mVsyncConfiguration->reset();
- updatePhaseConfiguration(refreshRate);
-}
-
void Scheduler::setActiveDisplayPowerModeForRefreshRateStats(hal::PowerMode powerMode) {
mRefreshRateStats->setPowerMode(powerMode);
}
@@ -877,22 +875,19 @@ void Scheduler::dump(utils::Dumper& dumper) const {
mRefreshRateStats->dump(dumper.out());
dumper.eol();
- {
- utils::Dumper::Section section(dumper, "Frame Targeting"sv);
-
- std::scoped_lock lock(mDisplayLock);
- ftl::FakeGuard guard(kMainThreadContext);
+ std::scoped_lock lock(mDisplayLock);
+ ftl::FakeGuard guard(kMainThreadContext);
- for (const auto& [id, display] : mDisplays) {
- utils::Dumper::Section
- section(dumper,
- id == mPacesetterDisplayId
- ? ftl::Concat("Pacesetter Display ", id.value).c_str()
- : ftl::Concat("Follower Display ", id.value).c_str());
-
- display.targeterPtr->dump(dumper);
- dumper.eol();
- }
+ for (const auto& [id, display] : mDisplays) {
+ utils::Dumper::Section
+ section(dumper,
+ id == mPacesetterDisplayId
+ ? ftl::Concat("Pacesetter Display ", id.value).c_str()
+ : ftl::Concat("Follower Display ", id.value).c_str());
+
+ display.selectorPtr->dump(dumper);
+ display.targeterPtr->dump(dumper);
+ dumper.eol();
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 9b32fa99f2..88f0e9435a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -188,7 +188,6 @@ public:
}
void updatePhaseConfiguration(Fps);
- void resetPhaseConfiguration(Fps) REQUIRES(kMainThreadContext);
const VsyncConfiguration& getVsyncConfiguration() const { return *mVsyncConfiguration; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 534df13f55..764e0ccd7f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -40,6 +40,7 @@
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
+#include <com_android_graphics_libgui_flags.h>
#include <com_android_graphics_surfaceflinger_flags.h>
#include <common/FlagManager.h>
#include <common/trace.h>
@@ -205,8 +206,6 @@ using ui::Dataspace;
using ui::DisplayPrimaries;
using ui::RenderIntent;
-using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;
-
namespace hal = android::hardware::graphics::composer::hal;
namespace {
@@ -374,8 +373,6 @@ const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONT
const String16 sInternalSystemWindow("android.permission.INTERNAL_SYSTEM_WINDOW");
const String16 sWakeupSurfaceFlinger("android.permission.WAKEUP_SURFACE_FLINGER");
-const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
-
// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -2187,14 +2184,6 @@ void SurfaceFlinger::scheduleSample() {
static_cast<void>(mScheduler->schedule([this] { sample(); }));
}
-nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
- if (const auto display = getDefaultDisplayDeviceLocked()) {
- return display->getVsyncPeriodFromHWC();
- }
-
- return 0;
-}
-
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
if (FlagManager::getInstance().connected_display() && timestamp < 0 &&
@@ -2532,12 +2521,18 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs,
}
updateLayerHistory(latchTime);
- mLayerSnapshotBuilder.forEachVisibleSnapshot([&](const frontend::LayerSnapshot& snapshot) {
- if (mLayersIdsWithQueuedFrames.find(snapshot.path.id) == mLayersIdsWithQueuedFrames.end())
- return;
- Region visibleReg;
- visibleReg.set(snapshot.transformedBoundsWithoutTransparentRegion);
- invalidateLayerStack(snapshot.outputFilter, visibleReg);
+ mLayerSnapshotBuilder.forEachSnapshot([&](const frontend::LayerSnapshot& snapshot) {
+ // update output dirty region if we have a queued buffer that is visible or a snapshot
+ // recently became invisible
+ // TODO(b/360050020) investigate if we need to update dirty region when layer color changes
+ if ((snapshot.isVisible &&
+ (mLayersIdsWithQueuedFrames.find(snapshot.path.id) !=
+ mLayersIdsWithQueuedFrames.end())) ||
+ (!snapshot.isVisible && snapshot.changes.test(Changes::Visibility))) {
+ Region visibleReg;
+ visibleReg.set(snapshot.transformedBoundsWithoutTransparentRegion);
+ invalidateLayerStack(snapshot.outputFilter, visibleReg);
+ }
});
for (auto& destroyedLayer : mLayerLifecycleManager.getDestroyedLayers()) {
@@ -3734,11 +3729,20 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
state.surface.get());
const auto displayId = PhysicalDisplayId::tryCast(compositionDisplay->getId());
LOG_FATAL_IF(!displayId);
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ const auto frameBufferSurface =
+ sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqProducer, bqConsumer,
+ state.physical->activeMode->getResolution(),
+ ui::Size(maxGraphicsWidth, maxGraphicsHeight));
+ displaySurface = frameBufferSurface;
+ producer = frameBufferSurface->getSurface()->getIGraphicBufferProducer();
+#else
displaySurface =
sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
state.physical->activeMode->getResolution(),
ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
}
LOG_FATAL_IF(!displaySurface);
@@ -3842,11 +3846,8 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
setPowerModeInternal(display, hal::PowerMode::ON);
}
- // TODO(b/175678251) Call a listener instead.
- if (currentState.physical->hwcDisplayId == getHwComposer().getPrimaryHwcDisplayId()) {
- const Fps refreshRate =
- mDisplayModeController.getActiveMode(display->getPhysicalId()).fps;
- mScheduler->resetPhaseConfiguration(refreshRate);
+ if (display->getPhysicalId() == mActiveDisplayId) {
+ onActiveDisplayChangedLocked(nullptr, *display);
}
}
return;
@@ -3938,51 +3939,6 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) {
mUpdateInputInfo = true;
}
- // Update transform hint.
- if (transactionFlags & (eTransformHintUpdateNeeded | eDisplayTransactionNeeded)) {
- // Layers and/or displays have changed, so update the transform hint for each layer.
- //
- // NOTE: we do this here, rather than when presenting the display so that
- // the hint is set before we acquire a buffer from the surface texture.
- //
- // NOTE: layer transactions have taken place already, so we use their
- // drawing state. However, SurfaceFlinger's own transaction has not
- // happened yet, so we must use the current state layer list
- // (soon to become the drawing state list).
- //
- sp<const DisplayDevice> hintDisplay;
- ui::LayerStack layerStack;
-
- mCurrentState.traverse([&](Layer* layer) REQUIRES(mStateLock) {
- // NOTE: we rely on the fact that layers are sorted by
- // layerStack first (so we don't have to traverse the list
- // of displays for every layer).
- if (const auto filter = layer->getOutputFilter(); layerStack != filter.layerStack) {
- layerStack = filter.layerStack;
- hintDisplay = nullptr;
-
- // Find the display that includes the layer.
- for (const auto& [token, display] : mDisplays) {
- if (!display->getCompositionDisplay()->includesLayer(filter)) {
- continue;
- }
-
- // Pick the primary display if another display mirrors the layer.
- if (hintDisplay) {
- hintDisplay = nullptr;
- break;
- }
-
- hintDisplay = display;
- }
- }
-
- if (hintDisplay) {
- layer->updateTransformHint(hintDisplay->getTransformHint());
- }
- });
- }
-
if (mLayersAdded) {
mLayersAdded = false;
// Layers have been added.
@@ -3996,14 +3952,6 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) {
mLayersRemoved = false;
mVisibleRegionsDirty = true;
mUpdateInputInfo = true;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (mLayersPendingRemoval.indexOf(sp<Layer>::fromExisting(layer)) >= 0) {
- // this layer is not visible anymore
- Region visibleReg;
- visibleReg.set(layer->getScreenBounds());
- invalidateLayerStack(layer->getOutputFilter(), visibleReg);
- }
- });
}
if (transactionFlags & eInputInfoUpdateNeeded) {
@@ -4421,13 +4369,6 @@ void SurfaceFlinger::doCommitTransactions() {
l->setIsAtRoot(false);
mCurrentState.layersSortedByZ.remove(l);
}
-
- // If the layer has been removed and has no parent, then it will not be reachable
- // when traversing layers on screen. Add the layer to the offscreenLayers set to
- // ensure we can copy its current to drawing state.
- if (!l->getParent()) {
- mOffscreenLayers.emplace(l.get());
- }
}
mLayersPendingRemoval.clear();
}
@@ -4441,7 +4382,6 @@ void SurfaceFlinger::doCommitTransactions() {
}
}
- commitOffscreenLayers();
if (mLayerMirrorRoots.size() > 0) {
std::deque<Layer*> pendingUpdates;
pendingUpdates.insert(pendingUpdates.end(), mLayerMirrorRoots.begin(),
@@ -4463,17 +4403,6 @@ void SurfaceFlinger::doCommitTransactions() {
}
}
-void SurfaceFlinger::commitOffscreenLayers() {
- for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverse(LayerVector::StateSet::Drawing, [](Layer* layer) {
- if (layer->clearTransactionFlags(eTransactionNeeded)) {
- layer->doTransaction(0);
- layer->commitChildList();
- }
- });
- }
-}
-
void SurfaceFlinger::invalidateLayerStack(const ui::LayerFilter& layerFilter, const Region& dirty) {
for (const auto& [token, displayDevice] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
auto display = displayDevice->getCompositionDisplay();
@@ -4487,65 +4416,26 @@ status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinde
const sp<Layer>& layer, const wp<Layer>& parent,
uint32_t* outTransformHint) {
if (mNumLayers >= MAX_LAYERS) {
+ static std::atomic<nsecs_t> lasttime{0};
+ nsecs_t now = systemTime();
+ if (lasttime != 0 && ns2s(now - lasttime.load()) < 10) {
+ ALOGE("AddClientLayer already dumped 10s before");
+ return NO_MEMORY;
+ } else {
+ lasttime = now;
+ }
+
ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
MAX_LAYERS);
- static_cast<void>(mScheduler->schedule([=, this] {
- ALOGE("Dumping layer keeping > 20 children alive:");
- bool leakingParentLayerFound = false;
- mDrawingState.traverse([&](Layer* layer) {
- if (leakingParentLayerFound) {
- return;
- }
- if (layer->getChildrenCount() > 20) {
- leakingParentLayerFound = true;
- sp<Layer> parent = sp<Layer>::fromExisting(layer);
- while (parent) {
- ALOGE("Parent Layer: %s%s", parent->getName().c_str(),
- (parent->isHandleAlive() ? "handleAlive" : ""));
- parent = parent->getParent();
- }
- // Sample up to 100 layers
- ALOGE("Dumping random sampling of child layers total(%zu): ",
- layer->getChildrenCount());
- int sampleSize = (layer->getChildrenCount() / 100) + 1;
- layer->traverseChildren([&](Layer* layer) {
- if (rand() % sampleSize == 0) {
- ALOGE("Child Layer: %s%s", layer->getName().c_str(),
- (layer->isHandleAlive() ? "handleAlive" : ""));
- }
- });
- }
- });
-
- int numLayers = 0;
- mDrawingState.traverse([&](Layer* layer) { numLayers++; });
-
- ALOGE("Dumping random sampling of on-screen layers total(%u):", numLayers);
- mDrawingState.traverse([&](Layer* layer) {
- // Aim to dump about 200 layers to avoid totally trashing
- // logcat. On the other hand, if there really are 4096 layers
- // something has gone totally wrong its probably the most
- // useful information in logcat.
- if (rand() % 20 == 13) {
- ALOGE("Layer: %s%s", layer->getName().c_str(),
- (layer->isHandleAlive() ? "handleAlive" : ""));
- std::this_thread::sleep_for(std::chrono::milliseconds(5));
- }
- });
- ALOGE("Dumping random sampling of off-screen layers total(%zu): ",
- mOffscreenLayers.size());
- for (Layer* offscreenLayer : mOffscreenLayers) {
- if (rand() % 20 == 13) {
- ALOGE("Offscreen-layer: %s%s", offscreenLayer->getName().c_str(),
- (offscreenLayer->isHandleAlive() ? "handleAlive" : ""));
- std::this_thread::sleep_for(std::chrono::milliseconds(5));
- }
- }
+ static_cast<void>(mScheduler->schedule([&]() FTL_FAKE_GUARD(kMainThreadContext) {
+ ALOGE("Dumping on-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getHierarchy());
+ ALOGE("Dumping off-screen layers.");
+ mLayerHierarchyBuilder.dumpLayerSample(mLayerHierarchyBuilder.getOffscreenHierarchy());
}));
return NO_MEMORY;
}
- layer->updateTransformHint(mActiveDisplayTransformHint);
if (outTransformHint) {
*outTransformHint = mActiveDisplayTransformHint;
}
@@ -5724,7 +5614,7 @@ void SurfaceFlinger::listLayers(std::string& result) const {
}
void SurfaceFlinger::dumpStats(const DumpArgs& args, std::string& result) const {
- StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriodFromHWC());
+ StringAppendF(&result, "%" PRId64 "\n", mScheduler->getPacesetterVsyncPeriod().ns());
if (args.size() < 2) return;
const auto name = String8(args[1]);
@@ -5760,7 +5650,7 @@ void SurfaceFlinger::logFrameStats(TimePoint now) {
sTimestamp = now;
SFTRACE_CALL();
- mDrawingState.traverse([&](Layer* layer) { layer->logFrameStats(); });
+ traverseLegacyLayers([&](Layer* layer) { layer->logFrameStats(); });
}
void SurfaceFlinger::appendSfConfigString(std::string& result) const {
@@ -5784,11 +5674,6 @@ void SurfaceFlinger::dumpScheduler(std::string& result) const {
// TODO(b/241285876): Move to DisplayModeController.
dumper.dump("debugDisplayModeSetByBackdoor"sv, mDebugDisplayModeSetByBackdoor);
dumper.eol();
-
- StringAppendF(&result,
- " present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64
- " ns\n\n",
- dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
}
void SurfaceFlinger::dumpEvents(std::string& result) const {
@@ -6068,20 +5953,6 @@ perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t t
.get();
}
-void SurfaceFlinger::dumpOffscreenLayers(std::string& result) {
- auto future = mScheduler->schedule([this] {
- std::string result;
- for (Layer* offscreenLayer : mOffscreenLayers) {
- offscreenLayer->traverse(LayerVector::StateSet::Drawing,
- [&](Layer* layer) { layer->dumpOffscreenDebugInfo(result); });
- }
- return result;
- });
-
- result.append("Offscreen Layers:\n");
- result.append(future.get());
-}
-
void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const {
for (const auto& [token, display] : mDisplays) {
const auto displayId = HalDisplayId::tryCast(display->getId());
@@ -6945,7 +6816,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
// Update the overlay on the main thread to avoid race conditions with
// RefreshRateSelector::getActiveMode
- static_cast<void>(mScheduler->schedule([=, this] {
+ static_cast<void>(mScheduler->schedule([=, this]() FTL_FAKE_GUARD(kMainThreadContext) {
const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
if (!display) {
ALOGW("%s: default display is null", __func__);
@@ -6953,15 +6824,9 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) {
}
if (!display->isRefreshRateOverlayEnabled()) return;
- const auto desiredModeIdOpt =
- mDisplayModeController.getDesiredMode(display->getPhysicalId())
- .transform([](const display::DisplayModeRequest& request) {
- return request.mode.modePtr->getId();
- });
-
- const bool timerExpired = mKernelIdleTimerEnabled && expired;
+ const auto state = mDisplayModeController.getKernelIdleTimerState(display->getPhysicalId());
- if (display->onKernelTimerChanged(desiredModeIdOpt, timerExpired)) {
+ if (display->onKernelTimerChanged(state.desiredModeIdOpt, state.isEnabled && expired)) {
mScheduler->scheduleFrame();
}
}));
@@ -6983,8 +6848,8 @@ void SurfaceFlinger::vrrDisplayIdle(bool idle) {
}));
}
-std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
-SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId) {
+auto SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId)
+ -> std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds> {
const bool isKernelIdleTimerHwcSupported = getHwComposer().getComposer()->isSupported(
android::Hwc2::Composer::OptionalFeature::KernelIdleTimer);
const auto timeout = getIdleTimerTimeout(displayId);
@@ -7008,63 +6873,6 @@ SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId) {
return {std::nullopt, timeout};
}
-void SurfaceFlinger::updateKernelIdleTimer(std::chrono::milliseconds timeout,
- KernelIdleTimerController controller,
- PhysicalDisplayId displayId) {
- switch (controller) {
- case KernelIdleTimerController::HwcApi: {
- getHwComposer().setIdleTimerEnabled(displayId, timeout);
- break;
- }
- case KernelIdleTimerController::Sysprop: {
- base::SetProperty(KERNEL_IDLE_TIMER_PROP, timeout > 0ms ? "true" : "false");
- break;
- }
- }
-}
-
-void SurfaceFlinger::toggleKernelIdleTimer() {
- using KernelIdleTimerAction = scheduler::RefreshRateSelector::KernelIdleTimerAction;
-
- const auto display = getDefaultDisplayDeviceLocked();
- if (!display) {
- ALOGW("%s: default display is null", __func__);
- return;
- }
-
- // If the support for kernel idle timer is disabled for the active display,
- // don't do anything.
- const std::optional<KernelIdleTimerController> kernelIdleTimerController =
- display->refreshRateSelector().kernelIdleTimerController();
- if (!kernelIdleTimerController.has_value()) {
- return;
- }
-
- const KernelIdleTimerAction action = display->refreshRateSelector().getIdleTimerAction();
-
- switch (action) {
- case KernelIdleTimerAction::TurnOff:
- if (mKernelIdleTimerEnabled) {
- SFTRACE_INT("KernelIdleTimer", 0);
- std::chrono::milliseconds constexpr kTimerDisabledTimeout = 0ms;
- updateKernelIdleTimer(kTimerDisabledTimeout, kernelIdleTimerController.value(),
- display->getPhysicalId());
- mKernelIdleTimerEnabled = false;
- }
- break;
- case KernelIdleTimerAction::TurnOn:
- if (!mKernelIdleTimerEnabled) {
- SFTRACE_INT("KernelIdleTimer", 1);
- const std::chrono::milliseconds timeout =
- display->refreshRateSelector().getIdleTimerTimeout();
- updateKernelIdleTimer(timeout, kernelIdleTimerController.value(),
- display->getPhysicalId());
- mKernelIdleTimerEnabled = true;
- }
- break;
- }
-}
-
// A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
class WindowDisconnector {
public:
@@ -7185,7 +6993,8 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
const sp<IScreenCaptureListener>& captureListener) {
SFTRACE_CALL();
- status_t validate = validateScreenshotPermissions(args);
+ const auto& captureArgs = args.captureArgs;
+ status_t validate = validateScreenshotPermissions(captureArgs);
if (validate != OK) {
ALOGD("Permission denied to captureDisplay");
invokeScreenCaptureError(validate, captureListener);
@@ -7198,7 +7007,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
return;
}
- if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) {
+ if (captureArgs.captureSecureLayers && !hasCaptureBlackoutContentPermission()) {
ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT");
invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
return;
@@ -7224,7 +7033,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
reqSize = display->getLayerStackSpaceRect().getSize();
}
- for (const auto& handle : args.excludeHandles) {
+ for (const auto& handle : captureArgs.excludeHandles) {
uint32_t excludeLayer = LayerHandle::getLayerId(handle);
if (excludeLayer != UNASSIGNED_LAYER_ID) {
excludeLayerIds.emplace(excludeLayer);
@@ -7237,17 +7046,21 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
}
GetLayerSnapshotsFunction getLayerSnapshotsFn =
- getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds));
+ getLayerSnapshotsForScreenshots(layerStack, captureArgs.uid,
+ std::move(excludeLayerIds));
ftl::Flags<RenderArea::Options> options;
- if (args.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
- if (args.hintForSeamlessTransition)
+ if (captureArgs.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
+ if (captureArgs.hintForSeamlessTransition)
options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
- args.sourceCrop, reqSize, args.dataspace,
+ gui::aidl_utils::fromARect(captureArgs.sourceCrop),
+ reqSize,
+ static_cast<ui::Dataspace>(captureArgs.dataspace),
displayWeak, options),
- getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected,
- args.grayscale, captureListener);
+ getLayerSnapshotsFn, reqSize,
+ static_cast<ui::PixelFormat>(captureArgs.pixelFormat),
+ captureArgs.allowProtected, captureArgs.grayscale, captureListener);
}
void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args,
@@ -7300,10 +7113,11 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args
if (args.hintForSeamlessTransition)
options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>,
- Rect(), size, args.dataspace, displayWeak,
- options),
- getLayerSnapshotsFn, size, args.pixelFormat, kAllowProtected, kGrayscale,
- captureListener);
+ Rect(), size,
+ static_cast<ui::Dataspace>(args.dataspace),
+ displayWeak, options),
+ getLayerSnapshotsFn, size, static_cast<ui::PixelFormat>(args.pixelFormat),
+ kAllowProtected, kGrayscale, captureListener);
}
ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& args) {
@@ -7316,20 +7130,23 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
const sp<IScreenCaptureListener>& captureListener) {
SFTRACE_CALL();
- status_t validate = validateScreenshotPermissions(args);
+ const auto& captureArgs = args.captureArgs;
+
+ status_t validate = validateScreenshotPermissions(captureArgs);
if (validate != OK) {
ALOGD("Permission denied to captureLayers");
invokeScreenCaptureError(validate, captureListener);
return;
}
+ auto crop = gui::aidl_utils::fromARect(captureArgs.sourceCrop);
+
ui::Size reqSize;
sp<Layer> parent;
- Rect crop(args.sourceCrop);
std::unordered_set<uint32_t> excludeLayerIds;
- ui::Dataspace dataspace = args.dataspace;
+ ui::Dataspace dataspace = static_cast<ui::Dataspace>(captureArgs.dataspace);
- if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) {
+ if (captureArgs.captureSecureLayers && !hasCaptureBlackoutContentPermission()) {
ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT");
invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
return;
@@ -7346,26 +7163,27 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
}
Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState());
- if (args.sourceCrop.width() <= 0) {
+ if (crop.width() <= 0) {
crop.left = 0;
crop.right = parentSourceBounds.getWidth();
}
- if (args.sourceCrop.height() <= 0) {
+ if (crop.height() <= 0) {
crop.top = 0;
crop.bottom = parentSourceBounds.getHeight();
}
- if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {
+ if (crop.isEmpty() || captureArgs.frameScaleX <= 0.0f || captureArgs.frameScaleY <= 0.0f) {
// Error out if the layer has no source bounds (i.e. they are boundless) and a source
// crop was not specified, or an invalid frame scale was provided.
ALOGD("Boundless layer, unspecified crop, or invalid frame scale to captureLayers");
invokeScreenCaptureError(BAD_VALUE, captureListener);
return;
}
- reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);
+ reqSize = ui::Size(crop.width() * captureArgs.frameScaleX,
+ crop.height() * captureArgs.frameScaleY);
- for (const auto& handle : args.excludeHandles) {
+ for (const auto& handle : captureArgs.excludeHandles) {
uint32_t excludeLayer = LayerHandle::getLayerId(handle);
if (excludeLayer != UNASSIGNED_LAYER_ID) {
excludeLayerIds.emplace(excludeLayer);
@@ -7391,8 +7209,9 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
}
GetLayerSnapshotsFunction getLayerSnapshotsFn =
- getLayerSnapshotsForScreenshots(parent->sequence, args.uid, std::move(excludeLayerIds),
- args.childrenOnly, parentCrop);
+ getLayerSnapshotsForScreenshots(parent->sequence, captureArgs.uid,
+ std::move(excludeLayerIds), args.childrenOnly,
+ parentCrop);
if (captureListener == nullptr) {
ALOGD("capture screen must provide a capture listener callback");
@@ -7401,14 +7220,15 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
}
ftl::Flags<RenderArea::Options> options;
- if (args.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
- if (args.hintForSeamlessTransition)
+ if (captureArgs.captureSecureLayers) options |= RenderArea::Options::CAPTURE_SECURE_LAYERS;
+ if (captureArgs.hintForSeamlessTransition)
options |= RenderArea::Options::HINT_FOR_SEAMLESS_TRANSITION;
captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<LayerRenderAreaBuilder>, crop,
reqSize, dataspace, parent, args.childrenOnly,
options),
- getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected,
- args.grayscale, captureListener);
+ getLayerSnapshotsFn, reqSize,
+ static_cast<ui::PixelFormat>(captureArgs.pixelFormat),
+ captureArgs.allowProtected, captureArgs.grayscale, captureListener);
}
// Creates a Future release fence for a layer and keeps track of it in a list to
@@ -7951,7 +7771,7 @@ status_t SurfaceFlinger::applyRefreshRateSelectorPolicy(
if (const bool isPacesetter =
mScheduler->onDisplayModeChanged(displayId, selector.getActiveMode())) {
- toggleKernelIdleTimer();
+ mDisplayModeController.updateKernelIdleTimer(displayId);
}
auto preferredModeOpt = getPreferredDisplayMode(displayId, currentPolicy.defaultMode);
@@ -8074,7 +7894,6 @@ void SurfaceFlinger::onLayerFirstRef(Layer* layer) {
void SurfaceFlinger::onLayerDestroyed(Layer* layer) {
mNumLayers--;
- removeHierarchyFromOffscreenLayers(layer);
if (!layer->isRemovedFromCurrentState()) {
mScheduler->deregisterLayer(layer);
}
@@ -8088,24 +7907,6 @@ void SurfaceFlinger::onLayerUpdate() {
scheduleCommit(FrameHint::kActive);
}
-// WARNING: ONLY CALL THIS FROM LAYER DTOR
-// Here we add children in the current state to offscreen layers and remove the
-// layer itself from the offscreen layer list. Since
-// this is the dtor, it is safe to access the current state. This keeps us
-// from dangling children layers such that they are not reachable from the
-// Drawing state nor the offscreen layer list
-// See b/141111965
-void SurfaceFlinger::removeHierarchyFromOffscreenLayers(Layer* layer) {
- for (auto& child : layer->getCurrentChildren()) {
- mOffscreenLayers.emplace(child.get());
- }
- mOffscreenLayers.erase(layer);
-}
-
-void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) {
- mOffscreenLayers.erase(layer);
-}
-
status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ,
float lightRadius) {
@@ -8277,20 +8078,6 @@ void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state, Vs
} else {
parent->addChild(layer);
}
-
- ui::LayerStack layerStack = layer->getLayerStack(LayerVector::StateSet::Current);
- sp<const DisplayDevice> hintDisplay;
- // Find the display that includes the layer.
- for (const auto& [token, display] : mDisplays) {
- if (display->getLayerStack() == layerStack) {
- hintDisplay = display;
- break;
- }
- }
-
- if (hintDisplay) {
- layer->updateTransformHint(hintDisplay->getTransformHint());
- }
}
void SurfaceFlinger::sample() {
@@ -8335,8 +8122,6 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD
mActiveDisplayId = activeDisplay.getPhysicalId();
activeDisplay.getCompositionDisplay()->setLayerCachingTexturePoolEnabled(true);
- mScheduler->resetPhaseConfiguration(mDisplayModeController.getActiveMode(mActiveDisplayId).fps);
-
// TODO(b/255635711): Check for pending mode changes on other displays.
mScheduler->setModeChangePending(false);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8b71f3be55..282c8cf803 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -292,9 +292,6 @@ public:
void onLayerDestroyed(Layer*);
void onLayerUpdate();
- void removeHierarchyFromOffscreenLayers(Layer* layer);
- void removeFromOffscreenLayers(Layer* layer);
-
// Called when all clients have released all their references to
// this layer. The layer may still be kept alive by its parents but
// the client can no longer modify this layer directly.
@@ -707,22 +704,13 @@ private:
// ICEPowerCallback overrides:
void notifyCpuLoadUp() override;
- // Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
- void toggleKernelIdleTimer() REQUIRES(mStateLock);
-
using KernelIdleTimerController = scheduler::RefreshRateSelector::KernelIdleTimerController;
// Get the controller and timeout that will help decide how the kernel idle timer will be
// configured and what value to use as the timeout.
std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
getKernelIdleTimerProperties(PhysicalDisplayId) REQUIRES(mStateLock);
- // Updates the kernel idle timer either through HWC or through sysprop
- // depending on which controller is provided
- void updateKernelIdleTimer(std::chrono::milliseconds timeoutMs, KernelIdleTimerController,
- PhysicalDisplayId) REQUIRES(mStateLock);
- // Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
- // make calls to sys prop each time.
- bool mKernelIdleTimerEnabled = false;
+
// Show spinner with refresh rate overlay
bool mRefreshRateOverlaySpinner = false;
// Show render rate with refresh rate overlay
@@ -833,8 +821,6 @@ private:
// Clears and returns the masked bits.
uint32_t clearTransactionFlags(uint32_t mask);
- void commitOffscreenLayers();
-
static LatchUnsignaledConfig getLatchUnsignaledConfig();
bool shouldLatchUnsignaled(const layer_state_t&, size_t numStates, bool firstTransaction) const;
bool applyTransactionsLocked(std::vector<TransactionState>& transactions, VsyncId)
@@ -1068,11 +1054,6 @@ private:
REQUIRES(mStateLock, kMainThreadContext);
/*
- * VSYNC
- */
- nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock);
-
- /*
* Display identification
*/
sp<display::DisplayToken> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const
@@ -1161,7 +1142,6 @@ private:
void dumpHwc(std::string& result) const;
perfetto::protos::LayersProto dumpProtoFromMainThread(
uint32_t traceFlags = LayerTracing::TRACE_ALL) EXCLUDES(mStateLock);
- void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock);
void dumpPlannerInfo(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock);
status_t doDump(int fd, const DumpArgs& args, bool asProto);
@@ -1407,12 +1387,6 @@ private:
// Flag used to set override desired display mode from backdoor
bool mDebugDisplayModeSetByBackdoor = false;
- // A set of layers that have no parent so they are not drawn on screen.
- // Should only be accessed by the main thread.
- // The Layer pointer is removed from the set when the destructor is called so there shouldn't
- // be any issues with a raw pointer referencing an invalid object.
- std::unordered_set<Layer*> mOffscreenLayers;
-
BufferCountTracker mBufferCountTracker;
std::unordered_map<DisplayId, sp<HdrLayerInfoReporter>> mHdrLayerInfoListeners
diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp
index d74bd55987..efab7b856a 100644
--- a/services/surfaceflinger/tests/BufferGenerator.cpp
+++ b/services/surfaceflinger/tests/BufferGenerator.cpp
@@ -42,8 +42,13 @@ public:
* through saved callback. */
class BufferListener : public ConsumerBase::FrameAvailableListener {
public:
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ BufferListener(sp<BufferItemConsumer> consumer, BufferCallback callback)
+#else
BufferListener(sp<IGraphicBufferConsumer> consumer, BufferCallback callback)
- : mConsumer(consumer), mCallback(callback) {}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ : mConsumer(consumer), mCallback(callback) {
+ }
void onFrameAvailable(const BufferItem& /*item*/) {
BufferItem item;
@@ -55,7 +60,11 @@ public:
}
private:
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<BufferItemConsumer> mConsumer;
+#else
sp<IGraphicBufferConsumer> mConsumer;
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
BufferCallback mCallback;
};
@@ -63,6 +72,16 @@ public:
* queue. */
void initialize(uint32_t width, uint32_t height, android_pixel_format_t format,
BufferCallback callback) {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ mBufferItemConsumer = sp<BufferItemConsumer>::make(GraphicBuffer::USAGE_HW_TEXTURE);
+ mBufferItemConsumer->setDefaultBufferSize(width, height);
+ mBufferItemConsumer->setDefaultBufferFormat(format);
+
+ mListener = sp<BufferListener>::make(mBufferItemConsumer, callback);
+ mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+ mSurface = mBufferItemConsumer->getSurface();
+#else
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
@@ -77,6 +96,7 @@ public:
mBufferItemConsumer->setFrameAvailableListener(mListener);
mSurface = sp<Surface>::make(producer, true);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
}
/* Used by Egl manager. The surface is never displayed. */
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index d355e720d1..babbcd4e35 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -280,7 +280,7 @@ TEST_F(CredentialsTest, CaptureLayersTest) {
std::function<status_t()> condition = [=, this]() {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = mBGSurfaceControl->getHandle();
- captureArgs.sourceCrop = {0, 0, 1, 1};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(0, 0, 1, 1);
ScreenCaptureResults captureResults;
return ScreenCapture::captureLayers(captureArgs, captureResults);
diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp
index 15a98df275..cc57e11206 100644
--- a/services/surfaceflinger/tests/LayerState_test.cpp
+++ b/services/surfaceflinger/tests/LayerState_test.cpp
@@ -28,66 +28,6 @@ using gui::ScreenCaptureResults;
namespace test {
-TEST(LayerStateTest, ParcellingDisplayCaptureArgs) {
- DisplayCaptureArgs args;
- args.pixelFormat = ui::PixelFormat::RGB_565;
- args.sourceCrop = Rect(0, 0, 500, 200);
- args.frameScaleX = 2;
- args.frameScaleY = 4;
- args.captureSecureLayers = true;
- args.displayToken = sp<BBinder>::make();
- args.width = 10;
- args.height = 20;
- args.grayscale = true;
-
- Parcel p;
- args.writeToParcel(&p);
- p.setDataPosition(0);
-
- DisplayCaptureArgs args2;
- args2.readFromParcel(&p);
-
- ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
- ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
- ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
- ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
- ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
- ASSERT_EQ(args.displayToken, args2.displayToken);
- ASSERT_EQ(args.width, args2.width);
- ASSERT_EQ(args.height, args2.height);
- ASSERT_EQ(args.grayscale, args2.grayscale);
-}
-
-TEST(LayerStateTest, ParcellingLayerCaptureArgs) {
- LayerCaptureArgs args;
- args.pixelFormat = ui::PixelFormat::RGB_565;
- args.sourceCrop = Rect(0, 0, 500, 200);
- args.frameScaleX = 2;
- args.frameScaleY = 4;
- args.captureSecureLayers = true;
- args.layerHandle = sp<BBinder>::make();
- args.excludeHandles = {sp<BBinder>::make(), sp<BBinder>::make()};
- args.childrenOnly = false;
- args.grayscale = true;
-
- Parcel p;
- args.writeToParcel(&p);
- p.setDataPosition(0);
-
- LayerCaptureArgs args2;
- args2.readFromParcel(&p);
-
- ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
- ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
- ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
- ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
- ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
- ASSERT_EQ(args.layerHandle, args2.layerHandle);
- ASSERT_EQ(args.excludeHandles, args2.excludeHandles);
- ASSERT_EQ(args.childrenOnly, args2.childrenOnly);
- ASSERT_EQ(args.grayscale, args2.grayscale);
-}
-
TEST(LayerStateTest, ParcellingScreenCaptureResultsWithFence) {
ScreenCaptureResults results;
results.buffer = sp<GraphicBuffer>::make(100u, 200u, PIXEL_FORMAT_RGBA_8888, 1u, 0u);
diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
index f9b4bbac22..e655df7695 100644
--- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp
@@ -15,6 +15,7 @@
*/
// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#include "gui/AidlStatusUtil.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
@@ -64,7 +65,7 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) {
// only layerB is in this range
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = parent->getHandle();
- captureArgs.sourceCrop = {0, 0, 32, 32};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(32, 32);
ScreenCapture::captureLayers(&screenshot, captureArgs);
screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
}
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index d97d433160..2a535881b2 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -20,6 +20,7 @@
#include <android-base/properties.h>
#include <common/FlagManager.h>
+#include <gui/AidlStatusUtil.h>
#include <private/android_filesystem_config.h>
#include "LayerTransactionTest.h"
#include "utils/TransactionUtils.h"
@@ -350,7 +351,7 @@ TEST_F(MirrorLayerTest, OffscreenMirrorScreenshot) {
// Capture just the mirror layer and child.
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = mirrorParent->getHandle();
- captureArgs.sourceCrop = childBounds;
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(childBounds);
std::unique_ptr<ScreenCapture> shot;
ScreenCapture::captureLayers(&shot, captureArgs);
shot->expectSize(childBounds.width(), childBounds.height());
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 9a78550d00..069f199cab 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -20,6 +20,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
+#include <gui/AidlStatusUtil.h>
#include <private/android_filesystem_config.h>
#include <ui/DisplayState.h>
@@ -65,7 +66,7 @@ protected:
.show(mFGSurfaceControl);
});
- mCaptureArgs.sourceCrop = mDisplayRect;
+ mCaptureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(mDisplayRect);
mCaptureArgs.layerHandle = mRootSurfaceControl->getHandle();
}
@@ -112,7 +113,7 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) {
shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
}
- mCaptureArgs.captureSecureLayers = true;
+ mCaptureArgs.captureArgs.captureSecureLayers = true;
// AID_SYSTEM is allowed to capture secure content.
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
ASSERT_TRUE(mCaptureResults.capturedSecureLayers);
@@ -164,7 +165,7 @@ TEST_F(ScreenCaptureTest, CaptureChildSetParentFlagsSecureEUidSystem) {
// Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able
// to receive them...we are expected to take care with the results.
- mCaptureArgs.captureSecureLayers = true;
+ mCaptureArgs.captureArgs.captureSecureLayers = true;
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, mCaptureResults));
ASSERT_TRUE(mCaptureResults.capturedSecureLayers);
ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers);
@@ -198,8 +199,8 @@ TEST_F(ScreenCaptureTest, CaptureChildRespectsParentSecureFlag) {
.apply();
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = childLayer->getHandle();
- captureArgs.sourceCrop = size;
- captureArgs.captureSecureLayers = false;
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(size);
+ captureArgs.captureArgs.captureSecureLayers = false;
{
SCOPED_TRACE("parent hidden");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -208,7 +209,7 @@ TEST_F(ScreenCaptureTest, CaptureChildRespectsParentSecureFlag) {
sc.expectColor(size, Color::BLACK);
}
- captureArgs.captureSecureLayers = true;
+ captureArgs.captureArgs.captureSecureLayers = true;
{
SCOPED_TRACE("capture secure parent not visible");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -218,7 +219,7 @@ TEST_F(ScreenCaptureTest, CaptureChildRespectsParentSecureFlag) {
}
Transaction().show(parentLayer).apply();
- captureArgs.captureSecureLayers = false;
+ captureArgs.captureArgs.captureSecureLayers = false;
{
SCOPED_TRACE("parent visible");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -227,7 +228,7 @@ TEST_F(ScreenCaptureTest, CaptureChildRespectsParentSecureFlag) {
sc.expectColor(size, Color::BLACK);
}
- captureArgs.captureSecureLayers = true;
+ captureArgs.captureArgs.captureSecureLayers = true;
{
SCOPED_TRACE("capture secure parent visible");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -259,8 +260,8 @@ TEST_F(ScreenCaptureTest, CaptureOffscreenChildRespectsParentSecureFlag) {
.apply();
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = childLayer->getHandle();
- captureArgs.sourceCrop = size;
- captureArgs.captureSecureLayers = false;
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(size);
+ captureArgs.captureArgs.captureSecureLayers = false;
{
SCOPED_TRACE("parent hidden");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -269,7 +270,7 @@ TEST_F(ScreenCaptureTest, CaptureOffscreenChildRespectsParentSecureFlag) {
sc.expectColor(size, Color::BLACK);
}
- captureArgs.captureSecureLayers = true;
+ captureArgs.captureArgs.captureSecureLayers = true;
{
SCOPED_TRACE("capture secure parent not visible");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -279,7 +280,7 @@ TEST_F(ScreenCaptureTest, CaptureOffscreenChildRespectsParentSecureFlag) {
}
Transaction().show(parentLayer).apply();
- captureArgs.captureSecureLayers = false;
+ captureArgs.captureArgs.captureSecureLayers = false;
{
SCOPED_TRACE("parent visible");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -288,7 +289,7 @@ TEST_F(ScreenCaptureTest, CaptureOffscreenChildRespectsParentSecureFlag) {
sc.expectColor(size, Color::BLACK);
}
- captureArgs.captureSecureLayers = true;
+ captureArgs.captureArgs.captureSecureLayers = true;
{
SCOPED_TRACE("capture secure parent visible");
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(captureArgs, mCaptureResults));
@@ -361,14 +362,14 @@ TEST_F(ScreenCaptureTest, CaptureLayerExclude) {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = fgHandle;
captureArgs.childrenOnly = true;
- captureArgs.excludeHandles = {child2->getHandle()};
+ captureArgs.captureArgs.excludeHandles = {child2->getHandle()};
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->checkPixel(10, 10, 0, 0, 0);
mCapture->checkPixel(0, 0, 200, 200, 200);
}
TEST_F(ScreenCaptureTest, CaptureLayerExcludeThroughDisplayArgs) {
- mCaptureArgs.excludeHandles = {mFGSurfaceControl->getHandle()};
+ mCaptureArgs.captureArgs.excludeHandles = {mFGSurfaceControl->getHandle()};
ScreenCapture::captureLayers(&mCapture, mCaptureArgs);
mCapture->expectBGColor(0, 0);
// Doesn't capture FG layer which is at 64, 64
@@ -401,7 +402,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = fgHandle;
captureArgs.childrenOnly = true;
- captureArgs.excludeHandles = {child2->getHandle()};
+ captureArgs.captureArgs.excludeHandles = {child2->getHandle()};
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->checkPixel(10, 10, 0, 0, 0);
mCapture->checkPixel(0, 0, 200, 200, 200);
@@ -418,7 +419,7 @@ TEST_F(ScreenCaptureTest, CaptureTransparent) {
// Captures child
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = child->getHandle();
- captureArgs.sourceCrop = {0, 0, 10, 20};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(10, 20);
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255});
// Area outside of child's bounds is transparent.
@@ -481,7 +482,7 @@ TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithSourceCrop) {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = child->getHandle();
- captureArgs.sourceCrop = {0, 0, 10, 10};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(10, 10);
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect(0, 0, 9, 9), Color::RED);
@@ -623,7 +624,7 @@ TEST_F(ScreenCaptureTest, CaptureCrop) {
// red area to the right of the blue area
mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
- captureArgs.sourceCrop = {0, 0, 30, 30};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(30, 30);
ScreenCapture::captureLayers(&mCapture, captureArgs);
// Capturing the cropped screen, cropping out the shown red area, should leave only the blue
// area visible.
@@ -658,8 +659,8 @@ TEST_F(ScreenCaptureTest, CaptureSize) {
// red area to the right of the blue area
mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
- captureArgs.frameScaleX = 0.5f;
- captureArgs.frameScaleY = 0.5f;
+ captureArgs.captureArgs.frameScaleX = 0.5f;
+ captureArgs.captureArgs.frameScaleY = 0.5f;
sleep(1);
ScreenCapture::captureLayers(&mCapture, captureArgs);
@@ -689,8 +690,8 @@ TEST_F(ScreenCaptureTest, CaptureTooLargeLayer) {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = redLayer->getHandle();
- captureArgs.frameScaleX = INT32_MAX / 60;
- captureArgs.frameScaleY = INT32_MAX / 60;
+ captureArgs.captureArgs.frameScaleX = INT32_MAX / 60;
+ captureArgs.captureArgs.frameScaleY = INT32_MAX / 60;
ScreenCaptureResults captureResults;
ASSERT_EQ(BAD_VALUE, ScreenCapture::captureLayers(captureArgs, captureResults));
@@ -736,7 +737,7 @@ TEST_F(ScreenCaptureTest, CaptureSecureLayer) {
mCapture->expectColor(Rect(30, 30, 60, 60), Color::RED);
// Passing flag secure so the blue layer should be screenshot too.
- args.captureSecureLayers = true;
+ args.captureArgs.captureSecureLayers = true;
ScreenCapture::captureLayers(&mCapture, args);
mCapture->expectColor(Rect(0, 0, 30, 30), Color::BLUE);
mCapture->expectColor(Rect(30, 30, 60, 60), Color::RED);
@@ -780,7 +781,7 @@ TEST_F(ScreenCaptureTest, ScreenshotProtectedBuffer) {
// Reading color data will expectedly result in crash, only check usage bit
// b/309965549 Checking that the usage bit is protected does not work for
// devices that do not support usage protected.
- mCaptureArgs.allowProtected = true;
+ mCaptureArgs.captureArgs.allowProtected = true;
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(mCaptureArgs, captureResults));
// ASSERT_EQ(GRALLOC_USAGE_PROTECTED, GRALLOC_USAGE_PROTECTED &
// captureResults.buffer->getUsage());
@@ -898,7 +899,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithUid) {
// Make screenshot request with current uid set. No layers were created with the current
// uid so screenshot will be black.
- captureArgs.uid = fakeUid;
+ captureArgs.captureArgs.uid = fakeUid;
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect(0, 0, 32, 32), Color::TRANSPARENT);
mCapture->expectBorder(Rect(0, 0, 32, 32), Color::TRANSPARENT);
@@ -935,7 +936,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithUid) {
mCapture->expectBorder(Rect(128, 128, 160, 160), Color::TRANSPARENT);
// Screenshot from the fakeUid caller with no uid requested allows everything to be screenshot.
- captureArgs.uid = -1;
+ captureArgs.captureArgs.uid = -1;
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect(128, 128, 160, 160), Color::RED);
mCapture->expectBorder(Rect(128, 128, 160, 160), {63, 63, 195, 255});
@@ -955,7 +956,7 @@ TEST_F(ScreenCaptureTest, CaptureWithGrayscale) {
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);
- captureArgs.grayscale = true;
+ captureArgs.captureArgs.grayscale = true;
const uint8_t tolerance = 1;
@@ -1052,7 +1053,7 @@ TEST_F(ScreenCaptureTest, captureOffscreenNullSnapshot) {
LayerCaptureArgs captureArgs;
captureArgs.layerHandle = mirroredLayer->getHandle();
- captureArgs.sourceCrop = Rect(0, 0, 1, 1);
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(1, 1);
// Screenshot path should only use the children of the layer hierarchy so
// that it will not create a new snapshot. A snapshot would otherwise be
diff --git a/services/surfaceflinger/tests/TextureFiltering_test.cpp b/services/surfaceflinger/tests/TextureFiltering_test.cpp
index c5d118c1aa..f8c536430a 100644
--- a/services/surfaceflinger/tests/TextureFiltering_test.cpp
+++ b/services/surfaceflinger/tests/TextureFiltering_test.cpp
@@ -14,9 +14,10 @@
* limitations under the License.
*/
+#include <android/gui/DisplayCaptureArgs.h>
#include <android/gui/ISurfaceComposerClient.h>
#include <gtest/gtest.h>
-#include <gui/DisplayCaptureArgs.h>
+#include <gui/AidlStatusUtil.h>
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
@@ -84,7 +85,7 @@ protected:
};
TEST_F(TextureFilteringTest, NoFiltering) {
- captureArgs.sourceCrop = Rect{0, 0, 100, 100};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(100, 100);
captureArgs.layerHandle = mParent->getHandle();
ScreenCapture::captureLayers(&mCapture, captureArgs);
@@ -93,7 +94,7 @@ TEST_F(TextureFilteringTest, NoFiltering) {
}
TEST_F(TextureFilteringTest, BufferCropNoFiltering) {
- captureArgs.sourceCrop = Rect{0, 0, 100, 100};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(100, 100);
captureArgs.layerHandle = mParent->getHandle();
ScreenCapture::captureLayers(&mCapture, captureArgs);
@@ -105,7 +106,7 @@ TEST_F(TextureFilteringTest, BufferCropNoFiltering) {
TEST_F(TextureFilteringTest, BufferCropIsFiltered) {
Transaction().setBufferCrop(mLayer, Rect{25, 25, 75, 75}).apply();
- captureArgs.sourceCrop = Rect{0, 0, 100, 100};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(100, 100);
captureArgs.layerHandle = mParent->getHandle();
ScreenCapture::captureLayers(&mCapture, captureArgs);
@@ -114,9 +115,9 @@ TEST_F(TextureFilteringTest, BufferCropIsFiltered) {
// Expect filtering because the output source crop is stretched to the output buffer's size.
TEST_F(TextureFilteringTest, OutputSourceCropIsFiltered) {
- captureArgs.frameScaleX = 2;
- captureArgs.frameScaleY = 2;
- captureArgs.sourceCrop = Rect{25, 25, 75, 75};
+ captureArgs.captureArgs.frameScaleX = 2;
+ captureArgs.captureArgs.frameScaleY = 2;
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(25, 25, 75, 75);
captureArgs.layerHandle = mParent->getHandle();
ScreenCapture::captureLayers(&mCapture, captureArgs);
@@ -127,9 +128,9 @@ TEST_F(TextureFilteringTest, OutputSourceCropIsFiltered) {
// buffer's size.
TEST_F(TextureFilteringTest, LayerCropOutputSourceCropIsFiltered) {
Transaction().setCrop(mLayer, Rect{25, 25, 75, 75}).apply();
- captureArgs.frameScaleX = 2;
- captureArgs.frameScaleY = 2;
- captureArgs.sourceCrop = Rect{25, 25, 75, 75};
+ captureArgs.captureArgs.frameScaleX = 2;
+ captureArgs.captureArgs.frameScaleY = 2;
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(25, 25, 75, 75);
captureArgs.layerHandle = mParent->getHandle();
ScreenCapture::captureLayers(&mCapture, captureArgs);
@@ -139,8 +140,8 @@ TEST_F(TextureFilteringTest, LayerCropOutputSourceCropIsFiltered) {
// Expect filtering because the layer is scaled up.
TEST_F(TextureFilteringTest, LayerCaptureWithScalingIsFiltered) {
captureArgs.layerHandle = mLayer->getHandle();
- captureArgs.frameScaleX = 2;
- captureArgs.frameScaleY = 2;
+ captureArgs.captureArgs.frameScaleX = 2;
+ captureArgs.captureArgs.frameScaleY = 2;
ScreenCapture::captureLayers(&mCapture, captureArgs);
expectFiltered({0, 0, 100, 200}, {100, 0, 200, 200});
@@ -149,7 +150,7 @@ TEST_F(TextureFilteringTest, LayerCaptureWithScalingIsFiltered) {
// Expect no filtering because the output buffer's size matches the source crop.
TEST_F(TextureFilteringTest, LayerCaptureOutputSourceCropNoFiltering) {
captureArgs.layerHandle = mLayer->getHandle();
- captureArgs.sourceCrop = Rect{25, 25, 75, 75};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(25, 25, 75, 75);
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect{0, 0, 25, 50}, Color::RED);
@@ -162,7 +163,7 @@ TEST_F(TextureFilteringTest, LayerCaptureWithCropNoFiltering) {
Transaction().setCrop(mLayer, Rect{10, 10, 90, 90}).apply();
captureArgs.layerHandle = mLayer->getHandle();
- captureArgs.sourceCrop = Rect{25, 25, 75, 75};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(25, 25, 75, 75);
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect{0, 0, 25, 50}, Color::RED);
@@ -172,7 +173,7 @@ TEST_F(TextureFilteringTest, LayerCaptureWithCropNoFiltering) {
// Expect no filtering because the output source crop and output buffer are the same size.
TEST_F(TextureFilteringTest, OutputSourceCropDisplayFrameMatchNoFiltering) {
captureArgs.layerHandle = mLayer->getHandle();
- captureArgs.sourceCrop = Rect{25, 25, 75, 75};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(25, 25, 75, 75);
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect{0, 0, 25, 50}, Color::RED);
@@ -206,7 +207,7 @@ TEST_F(TextureFilteringTest, ParentHasTransformNoFiltering) {
Transaction().setPosition(mParent, 100, 100).apply();
captureArgs.layerHandle = mParent->getHandle();
- captureArgs.sourceCrop = Rect{0, 0, 100, 100};
+ captureArgs.captureArgs.sourceCrop = gui::aidl_utils::toARect(100, 100);
ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect{0, 0, 50, 100}, Color::RED);
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index af3cb9aec1..67a524799d 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -16,6 +16,7 @@
#ifndef ANDROID_TRANSACTION_TEST_HARNESSES
#define ANDROID_TRANSACTION_TEST_HARNESSES
+#include <com_android_graphics_libgui_flags.h>
#include <common/FlagManager.h>
#include <ui/DisplayState.h>
@@ -51,6 +52,16 @@ public:
const ui::Size& resolution = displayMode.resolution;
sp<IBinder> vDisplay;
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ sp<BufferItemConsumer> itemConsumer = sp<BufferItemConsumer>::make(
+ // Sample usage bits from screenrecord
+ GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_SW_READ_OFTEN);
+ sp<BufferListener> listener = sp<BufferListener>::make(this);
+ itemConsumer->setFrameAvailableListener(listener);
+ itemConsumer->setName(String8("Virtual disp consumer"));
+ itemConsumer->setDefaultBufferSize(resolution.getWidth(), resolution.getHeight());
+#else
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
sp<BufferItemConsumer> itemConsumer;
@@ -65,6 +76,7 @@ public:
GRALLOC_USAGE_SW_READ_OFTEN);
sp<BufferListener> listener = sp<BufferListener>::make(this);
itemConsumer->setFrameAvailableListener(listener);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
static const std::string kDisplayName("VirtualDisplay");
vDisplay = SurfaceComposerClient::createVirtualDisplay(kDisplayName,
@@ -76,7 +88,12 @@ public:
SurfaceComposerClient::getDefault()->mirrorDisplay(displayId);
SurfaceComposerClient::Transaction t;
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ t.setDisplaySurface(vDisplay,
+ itemConsumer->getSurface()->getIGraphicBufferProducer());
+#else
t.setDisplaySurface(vDisplay, producer);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
t.setDisplayProjection(vDisplay, displayState.orientation,
Rect(displayState.layerStackSpaceRect), Rect(resolution));
if (FlagManager::getInstance().ce_fence_promise()) {
diff --git a/services/surfaceflinger/tests/VirtualDisplay_test.cpp b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
index cd66dd20bb..d69378cec2 100644
--- a/services/surfaceflinger/tests/VirtualDisplay_test.cpp
+++ b/services/surfaceflinger/tests/VirtualDisplay_test.cpp
@@ -27,6 +27,12 @@ namespace {
class VirtualDisplayTest : public ::testing::Test {
protected:
void SetUp() override {
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
+ mGLConsumer = sp<GLConsumer>::make(GLConsumer::TEXTURE_EXTERNAL, true, false, false);
+ mGLConsumer->setName(String8("Virtual disp consumer"));
+ mGLConsumer->setDefaultBufferSize(100, 100);
+ mProducer = mGLConsumer->getSurface()->getIGraphicBufferProducer();
+#else
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&mProducer, &consumer);
@@ -34,6 +40,7 @@ protected:
consumer->setDefaultBufferSize(100, 100);
mGLConsumer = sp<GLConsumer>::make(consumer, GLConsumer::TEXTURE_EXTERNAL, true, false);
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
}
sp<IGraphicBufferProducer> mProducer;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 184dada32e..e380e19797 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -180,6 +180,8 @@ public:
MOCK_METHOD1(onHotplugDisconnect, void(Display));
MOCK_METHOD(Error, setRefreshRateChangedCallbackDebugEnabled, (Display, bool));
MOCK_METHOD(Error, notifyExpectedPresent, (Display, nsecs_t, int32_t));
+ MOCK_METHOD(Error, getDisplayLuts,
+ (Display, std::vector<aidl::android::hardware::graphics::composer3::Lut>*));
};
} // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 602bdfc152..1eda3586c5 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -109,6 +109,8 @@ public:
MOCK_METHOD(hal::Error, getOverlaySupport,
(aidl::android::hardware::graphics::composer3::OverlayProperties *),
(const override));
+ MOCK_METHOD(hal::Error, getDisplayLuts,
+ (std::vector<aidl::android::hardware::graphics::composer3::Lut>*), (override));
};
class Layer : public HWC2::Layer {
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index 1675584f5a..efce6b6b44 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -39,7 +39,7 @@ public:
const auto sf = ComposerServiceAIDL::getComposerService();
SurfaceComposerClient::Transaction().apply(true);
- captureArgs.dataspace = ui::Dataspace::V0_SRGB;
+ captureArgs.captureArgs.dataspace = static_cast<int32_t>(ui::Dataspace::V0_SRGB);
const sp<SyncScreenCaptureListener> captureListener = sp<SyncScreenCaptureListener>::make();
binder::Status status = sf->captureDisplay(captureArgs, captureListener);
status_t err = statusTFromBinderStatus(status);
@@ -77,7 +77,7 @@ public:
const auto sf = ComposerServiceAIDL::getComposerService();
SurfaceComposerClient::Transaction().apply(true);
- captureArgs.dataspace = ui::Dataspace::V0_SRGB;
+ captureArgs.captureArgs.dataspace = static_cast<int32_t>(ui::Dataspace::V0_SRGB);
const sp<SyncScreenCaptureListener> captureListener = sp<SyncScreenCaptureListener>::make();
binder::Status status = sf->captureLayers(captureArgs, captureListener);
status_t err = statusTFromBinderStatus(status);