diff options
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); |