diff options
25 files changed, 392 insertions, 232 deletions
diff --git a/include/input/Input.h b/include/input/Input.h index d4defa8269..e8678d27c3 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -24,6 +24,9 @@ */ #include <android/input.h> +#ifdef __linux__ +#include <android/os/IInputConstants.h> +#endif #include <math.h> #include <stdint.h> #include <ui/Transform.h> @@ -219,7 +222,16 @@ enum { POLICY_FLAG_GESTURE = 0x00000008, POLICY_FLAG_RAW_MASK = 0x0000ffff, +#ifdef __linux__ + POLICY_FLAG_INPUTFILTER_TRUSTED = android::os::IInputConstants::POLICY_FLAG_INPUTFILTER_TRUSTED, + POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = + android::os::IInputConstants::POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY, +#else + POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000, + + POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000, +#endif /* These flags are set by the input dispatcher. */ // Indicates that the input event was injected. diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index 7f0324a4a8..1955104a22 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -318,6 +318,8 @@ extern std::string getInputDeviceConfigurationFilePathByName( const std::string& name, InputDeviceConfigurationFileType type); enum ReservedInputDeviceId : int32_t { + // Device id assigned to input events generated inside accessibility service + ACCESSIBILITY_DEVICE_ID = -2, // Device id of a special "virtual" keyboard that is always present. VIRTUAL_KEYBOARD_ID = -1, // Device id of the "built-in" keyboard if there is one. diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 96104376d1..660c5bd97d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -182,12 +182,12 @@ CallbackId TransactionCompletedListener::addCallbackFunction( void TransactionCompletedListener::addJankListener(const sp<JankDataListener>& listener, sp<SurfaceControl> surfaceControl) { - std::lock_guard<std::mutex> lock(mMutex); + std::scoped_lock<std::recursive_mutex> lock(mJankListenerMutex); mJankListeners.insert({surfaceControl->getHandle(), listener}); } void TransactionCompletedListener::removeJankListener(const sp<JankDataListener>& listener) { - std::lock_guard<std::mutex> lock(mMutex); + std::scoped_lock<std::recursive_mutex> lock(mJankListenerMutex); for (auto it = mJankListeners.begin(); it != mJankListeners.end();) { if (it->second == listener) { it = mJankListeners.erase(it); @@ -210,13 +210,13 @@ void TransactionCompletedListener::removeReleaseBufferCallback(uint64_t graphicB void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie, sp<SurfaceControl> surfaceControl, SurfaceStatsCallback listener) { - std::lock_guard<std::mutex> lock(mMutex); + std::scoped_lock<std::recursive_mutex> lock(mSurfaceStatsListenerMutex); mSurfaceStatsListeners.insert({surfaceControl->getHandle(), SurfaceStatsCallbackEntry(context, cookie, listener)}); } void TransactionCompletedListener::removeSurfaceStatsListener(void* context, void* cookie) { - std::lock_guard<std::mutex> lock(mMutex); + std::scoped_lock<std::recursive_mutex> lock(mSurfaceStatsListenerMutex); for (auto it = mSurfaceStatsListeners.begin(); it != mSurfaceStatsListeners.end();) { auto [itContext, itCookie, itListener] = it->second; if (itContext == context && itCookie == cookie) { @@ -242,8 +242,6 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> callbacksMap; - std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap; - std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry> surfaceListeners; { std::lock_guard<std::mutex> lock(mMutex); @@ -259,8 +257,6 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener * sp<SurfaceControl> that could possibly exist for the callbacks. */ callbacksMap = mCallbacks; - jankListenersMap = mJankListeners; - surfaceListeners = mSurfaceStatsListeners; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); @@ -341,15 +337,26 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceControlStats); } for (const auto& surfaceStats : transactionStats.surfaceStats) { - auto listenerRange = surfaceListeners.equal_range(surfaceStats.surfaceControl); - for (auto it = listenerRange.first; it != listenerRange.second; it++) { - auto entry = it->second; - entry.callback(entry.context, transactionStats.latchTime, - transactionStats.presentFence, surfaceStats); + { + // Acquire surface stats listener lock such that we guarantee that after calling + // unregister, there won't be any further callback. + std::scoped_lock<std::recursive_mutex> lock(mSurfaceStatsListenerMutex); + auto listenerRange = mSurfaceStatsListeners.equal_range( + surfaceStats.surfaceControl); + for (auto it = listenerRange.first; it != listenerRange.second; it++) { + auto entry = it->second; + entry.callback(entry.context, transactionStats.latchTime, + transactionStats.presentFence, surfaceStats); + } } if (surfaceStats.jankData.empty()) continue; - auto jankRange = jankListenersMap.equal_range(surfaceStats.surfaceControl); + + // Acquire jank listener lock such that we guarantee that after calling unregister, + // there won't be any further callback. + std::scoped_lock<std::recursive_mutex> lock(mJankListenerMutex); + auto copy = mJankListeners; + auto jankRange = copy.equal_range(surfaceStats.surfaceControl); for (auto it = jankRange.first; it != jankRange.second; it++) { it->second->onJankDataAvailable(surfaceStats.jankData); } diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 62a782fd3e..5aa132cd92 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -652,6 +652,12 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { std::mutex mMutex; + // This lock needs to be recursive so we can unregister a callback from within that callback. + std::recursive_mutex mJankListenerMutex; + + // This lock needs to be recursive so we can unregister a callback from within that callback. + std::recursive_mutex mSurfaceStatsListenerMutex; + bool mListening GUARDED_BY(mMutex) = false; int64_t mCallbackIdCounter GUARDED_BY(mMutex) = 1; @@ -674,11 +680,16 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { std::unordered_map<CallbackId, CallbackTranslation, CallbackIdHash> mCallbacks GUARDED_BY(mMutex); - std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex); + + // This is protected by mJankListenerMutex, but GUARDED_BY isn't supported for + // std::recursive_mutex + std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners; std::unordered_map<uint64_t /* graphicsBufferId */, ReleaseBufferCallback> mReleaseBufferCallbacks GUARDED_BY(mMutex); - std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry> - mSurfaceStatsListeners GUARDED_BY(mMutex); + + // This is protected by mSurfaceStatsListenerMutex, but GUARDED_BY isn't supported for + // std::recursive_mutex + std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry> mSurfaceStatsListeners; public: static sp<TransactionCompletedListener> getInstance(); diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl index 4b90844490..3038d9daa5 100644 --- a/libs/input/android/os/IInputConstants.aidl +++ b/libs/input/android/os/IInputConstants.aidl @@ -40,4 +40,18 @@ interface IInputConstants * available. */ const int INVALID_INPUT_EVENT_ID = 0; + + /** + * The injected event was originally sent from InputDispatcher. Most likely, the journey of the + * event looked as follows: + * InputDispatcherPolicyInterface::filterInputEvent -> InputFilter.java::onInputEvent -> + * InputFilter.java::sendInputEvent -> InputDispatcher::injectInputEvent, without being modified + * along the way. + */ + const int POLICY_FLAG_INPUTFILTER_TRUSTED = 0x10000; + + /** + * The input event was injected from accessibility + */ + const int POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY = 0x20000; } diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 18eb7b5c7c..b5dd8ac580 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -970,37 +970,17 @@ void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /*framebuffer*/) { glBindFramebuffer(GL_FRAMEBUFFER, 0); } -bool GLESRenderEngine::cleanupPostRender(CleanupMode mode) { +bool GLESRenderEngine::canSkipPostRenderCleanup() const { + return mPriorResourcesCleaned || + (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled); +} + +void GLESRenderEngine::cleanupPostRender() { ATRACE_CALL(); - if (mPriorResourcesCleaned || - (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled)) { + if (canSkipPostRenderCleanup()) { // If we don't have a prior frame needing cleanup, then don't do anything. - return false; - } - - // This is a bit of a band-aid fix for FrameCaptureProcessor, as we should - // not need to keep memory around if we don't need to do so. - if (mode == CleanupMode::CLEAN_ALL) { - // TODO: SurfaceFlinger memory utilization may benefit from resetting - // texture bindings as well. Assess if it does and there's no performance regression - // when rebinding the same image data to the same texture, and if so then its mode - // behavior can be tweaked. - if (mPlaceholderImage != EGL_NO_IMAGE_KHR) { - for (auto [textureName, bufferId] : mTextureView) { - if (bufferId && mPlaceholderImage != EGL_NO_IMAGE_KHR) { - glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, - static_cast<GLeglImageOES>(mPlaceholderImage)); - mTextureView[textureName] = std::nullopt; - checkErrors(); - } - } - } - { - std::lock_guard<std::mutex> lock(mRenderingMutex); - mImageCache.clear(); - } + return; } // Bind the texture to placeholder so that backing image data can be freed. @@ -1011,7 +991,6 @@ bool GLESRenderEngine::cleanupPostRender(CleanupMode mode) { // we could no-op repeated calls of this method instead. mLastDrawFence = nullptr; mPriorResourcesCleaned = true; - return true; } void GLESRenderEngine::cleanFramebufferCache() { diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 1ff3674c03..915dba364f 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -68,7 +68,7 @@ public: const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; - bool cleanupPostRender(CleanupMode mode) override; + void cleanupPostRender() override; int getContextPriority() override; bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } void onPrimaryDisplaySizeChanged(ui::Size size) override {} @@ -106,6 +106,7 @@ protected: void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) EXCLUDES(mRenderingMutex); void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex); + bool canSkipPostRenderCleanup() const override; private: friend class BindNativeBufferAsFramebuffer; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 1da9adcad4..ac0affb2ee 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -114,25 +114,6 @@ public: virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - enum class CleanupMode { - CLEAN_OUTPUT_RESOURCES, - CLEAN_ALL, - }; - // Clean-up method that should be called on the main thread after the - // drawFence returned by drawLayers fires. This method will free up - // resources used by the most recently drawn frame. If the frame is still - // being drawn, then this call is silently ignored. - // - // If mode is CLEAN_OUTPUT_RESOURCES, then only resources related to the - // output framebuffer are cleaned up, including the sibling texture. - // - // If mode is CLEAN_ALL, then we also cleanup resources related to any input - // buffers. - // - // Returns true if resources were cleaned up, and false if we didn't need to - // do any work. - virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0; - // queries that are required to be thread safe virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; @@ -186,6 +167,13 @@ public: const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0; + + // Clean-up method that should be called on the main thread after the + // drawFence returned by drawLayers fires. This method will free up + // resources used by the most recently drawn frame. If the frame is still + // being drawn, then the implementation is free to silently ignore this call. + virtual void cleanupPostRender() = 0; + virtual void cleanFramebufferCache() = 0; // Returns the priority this context was actually created with. Note: this may not be // the same as specified at context creation time, due to implementation limits on the @@ -234,8 +222,15 @@ protected: // that's conflict serializable, i.e. unmap a buffer should never occur before binding the // buffer if the caller called mapExternalTextureBuffer before calling unmap. virtual void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) = 0; + + // A thread safe query to determine if any post rendering cleanup is necessary. Returning true + // is a signal that calling the postRenderCleanup method would be a no-op and that callers can + // avoid any thread synchronization that may be required by directly calling postRenderCleanup. + virtual bool canSkipPostRenderCleanup() const = 0; + friend class ExternalTexture; friend class threaded::RenderEngineThreaded; + friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test; const RenderEngineType mRenderEngineType; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index baa1305212..0175af3a85 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -45,7 +45,8 @@ public: MOCK_CONST_METHOD0(isProtected, bool()); MOCK_CONST_METHOD0(supportsProtectedContent, bool()); MOCK_METHOD1(useProtectedContext, bool(bool)); - MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode)); + MOCK_METHOD0(cleanupPostRender, void()); + MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool()); MOCK_METHOD6(drawLayers, status_t(const DisplaySettings&, const std::vector<const LayerSettings*>&, const std::shared_ptr<ExternalTexture>&, const bool, base::unique_fd&&, diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp index 8356005911..5c122d4154 100644 --- a/libs/renderengine/skia/AutoBackendTexture.cpp +++ b/libs/renderengine/skia/AutoBackendTexture.cpp @@ -29,8 +29,8 @@ namespace renderengine { namespace skia { AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, - bool isOutputBuffer) - : mIsOutputBuffer(isOutputBuffer) { + bool isOutputBuffer, CleanupManager& cleanupMgr) + : mCleanupMgr(cleanupMgr), mIsOutputBuffer(isOutputBuffer) { ATRACE_CALL(); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); @@ -49,6 +49,13 @@ AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer this, desc.width, desc.height, createProtectedImage, isOutputBuffer, desc.format); } +AutoBackendTexture::~AutoBackendTexture() { + if (mBackendTexture.isValid()) { + mDeleteProc(mImageCtx); + mBackendTexture = {}; + } +} + void AutoBackendTexture::unref(bool releaseLocalResources) { if (releaseLocalResources) { mSurface = nullptr; @@ -57,11 +64,7 @@ void AutoBackendTexture::unref(bool releaseLocalResources) { mUsageCount--; if (mUsageCount <= 0) { - if (mBackendTexture.isValid()) { - mDeleteProc(mImageCtx); - mBackendTexture = {}; - } - delete this; + mCleanupMgr.add(this); } } diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index a9e8430d66..00b901be11 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -25,6 +25,9 @@ #include "android-base/macros.h" +#include <mutex> +#include <vector> + namespace android { namespace renderengine { namespace skia { @@ -36,13 +39,50 @@ namespace skia { */ class AutoBackendTexture { public: + // Manager class that is responsible for the immediate or deferred cleanup + // of AutoBackendTextures. Clients of AutoBackendTexture are responsible for + // ensuring that access to this class is thread safe. Clients also control when + // the resources are reclaimed by setting the manager into deferred mode. + class CleanupManager { + public: + CleanupManager() = default; + void add(AutoBackendTexture* abt) { + if (mDeferCleanup) { + mCleanupList.push_back(abt); + } else { + delete abt; + } + } + + void setDeferredStatus(bool enabled) { mDeferCleanup = enabled; } + + bool isEmpty() const { return mCleanupList.empty(); } + + // If any AutoBackedTextures were added while in deferred mode this method + // will ensure they are deleted before returning. It must only be called + // on the thread where the GPU context that created the AutoBackedTexture + // is active. + void cleanup() { + for (auto abt : mCleanupList) { + delete abt; + } + mCleanupList.clear(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(CleanupManager); + bool mDeferCleanup = false; + std::vector<AutoBackendTexture*> mCleanupList; + }; + // Local reference that supports RAII-style management of an AutoBackendTexture // AutoBackendTexture by itself can't be managed in a similar fashion because // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: - LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer) { - mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer); + LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, + CleanupManager& cleanupMgr) { + mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer, cleanupMgr); mTexture->ref(); } @@ -75,10 +115,11 @@ public: private: // Creates a GrBackendTexture whose contents come from the provided buffer. - AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer); + AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, + CleanupManager& cleanupMgr); // The only way to invoke dtor is with unref, when mUsageCount is 0. - ~AutoBackendTexture() {} + ~AutoBackendTexture(); void ref() { mUsageCount++; } @@ -100,6 +141,8 @@ private: GrAHardwareBufferUtils::UpdateImageProc mUpdateProc; GrAHardwareBufferUtils::TexImageCtx mImageCtx; + CleanupManager& mCleanupMgr; + static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext); static void releaseImageProc(SkImage::ReleaseContext releaseContext); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index f0986a3a22..d28d623b7f 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -531,7 +531,7 @@ void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffe std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(grContext, buffer->toAHardwareBuffer(), - isRenderable); + isRenderable, mTextureCleanupMgr); cache.insert({buffer->getId(), imageTextureRef}); } } @@ -559,6 +559,31 @@ void SkiaGLRenderEngine::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buf } } +bool SkiaGLRenderEngine::canSkipPostRenderCleanup() const { + std::lock_guard<std::mutex> lock(mRenderingMutex); + return mTextureCleanupMgr.isEmpty(); +} + +void SkiaGLRenderEngine::cleanupPostRender() { + ATRACE_CALL(); + std::lock_guard<std::mutex> lock(mRenderingMutex); + mTextureCleanupMgr.cleanup(); +} + +// Helper class intended to be used on the stack to ensure that texture cleanup +// is deferred until after this class goes out of scope. +class DeferTextureCleanup final { +public: + DeferTextureCleanup(AutoBackendTexture::CleanupManager& mgr) : mMgr(mgr) { + mMgr.setDeferredStatus(true); + } + ~DeferTextureCleanup() { mMgr.setDeferredStatus(false); } + +private: + DISALLOW_COPY_AND_ASSIGN(DeferTextureCleanup); + AutoBackendTexture::CleanupManager& mMgr; +}; + sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader( sk_sp<SkShader> shader, const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha, @@ -707,6 +732,9 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, auto grContext = getActiveGrContext(); auto& cache = mTextureCache; + // any AutoBackendTexture deletions will now be deferred until cleanupPostRender is called + DeferTextureCleanup dtc(mTextureCleanupMgr); + std::shared_ptr<AutoBackendTexture::LocalRef> surfaceTextureRef; if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) { surfaceTextureRef = it->second; @@ -715,7 +743,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, std::make_shared<AutoBackendTexture::LocalRef>(grContext, buffer->getBuffer() ->toAHardwareBuffer(), - true); + true, mTextureCleanupMgr); } const ui::Dataspace dstDataspace = @@ -971,7 +999,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, imageTextureRef = std::make_shared< AutoBackendTexture::LocalRef>(grContext, item.buffer->getBuffer()->toAHardwareBuffer(), - false); + false, mTextureCleanupMgr); } // isOpaque means we need to ignore the alpha in the image, diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index b972c73c1c..b30355bb67 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -59,7 +59,8 @@ public: const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; - void cleanFramebufferCache() override {} + void cleanupPostRender() override; + void cleanFramebufferCache() override{}; int getContextPriority() override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -75,6 +76,7 @@ protected: size_t getMaxViewportDims() const override; void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override; void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override; + bool canSkipPostRenderCleanup() const override; private: static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); @@ -130,13 +132,14 @@ private: std::unordered_map<GraphicBufferId, std::shared_ptr<AutoBackendTexture::LocalRef>> mTextureCache GUARDED_BY(mRenderingMutex); std::unordered_map<LinearEffect, sk_sp<SkRuntimeEffect>, LinearEffectHasher> mRuntimeEffects; + AutoBackendTexture::CleanupManager mTextureCleanupMgr GUARDED_BY(mRenderingMutex); StretchShaderFactory mStretchShaderFactory; // Mutex guarding rendering operations, so that: // 1. GL operations aren't interleaved, and // 2. Internal state related to rendering that is potentially modified by // multiple threads is guaranteed thread-safe. - std::mutex mRenderingMutex; + mutable std::mutex mRenderingMutex; sp<Fence> mLastDrawFence; diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index f098a8603b..31ad63e9ce 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -53,7 +53,6 @@ public: base::unique_fd* /*drawFence*/) override { return 0; }; - virtual bool cleanupPostRender(CleanupMode) override { return true; }; virtual int getContextPriority() override { return 0; } virtual void assertShadersCompiled(int numShaders) {} virtual int reportShadersCompiled() { return 0; } diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index dfab6e8cd2..e2587419d2 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -43,6 +43,7 @@ constexpr int DEFAULT_DISPLAY_OFFSET = 64; constexpr bool WRITE_BUFFER_TO_FILE_ON_FAILURE = false; namespace android { +namespace renderengine { class RenderEngineFactory { public: @@ -1779,13 +1780,6 @@ TEST_P(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) { } TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - initializeRenderEngine(); renderengine::DisplaySettings settings; @@ -1810,53 +1804,9 @@ TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { sync_wait(fd, -1); } // Only cleanup the first time. - EXPECT_TRUE(mRE->cleanupPostRender( - renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES)); - EXPECT_FALSE(mRE->cleanupPostRender( - renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES)); -} - -TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - renderengine::DisplaySettings settings; - settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - settings.physicalDisplay = fullscreenRect(); - settings.clip = fullscreenRect(); - - std::vector<const renderengine::LayerSettings*> layers; - renderengine::LayerSettings layer; - layer.geometry.boundaries = fullscreenRect().toFloatRect(); - BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this); - layer.alpha = 1.0; - layers.push_back(&layer); - - base::unique_fd fence; - mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence); - - const int fd = fence.get(); - if (fd >= 0) { - sync_wait(fd, -1); - } - - uint64_t bufferId = layer.source.buffer.buffer->getBuffer()->getId(); - uint32_t texName = layer.source.buffer.textureName; - EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); - EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName)); - - EXPECT_TRUE(mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL)); - - // Now check that our view of memory is good. - EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); - EXPECT_EQ(std::nullopt, mGLESRE->getBufferIdForTextureNameForTesting(bufferId)); - EXPECT_TRUE(mGLESRE->isTextureNameKnownForTesting(texName)); + EXPECT_FALSE(mRE->canSkipPostRenderCleanup()); + mRE->cleanupPostRender(); + EXPECT_TRUE(mRE->canSkipPostRenderCleanup()); } TEST_P(RenderEngineTest, testRoundedCornersCrop) { @@ -2080,6 +2030,7 @@ TEST_P(RenderEngineTest, test_isOpaque) { expectBufferColor(rect, 0, 255, 0, 255); } } +} // namespace renderengine } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index e3917cce09..c65e731230 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -130,22 +130,22 @@ TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsTrue) { ASSERT_EQ(true, result); } -TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsFalse) { - EXPECT_CALL(*mRenderEngine, - cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL)) - .WillOnce(Return(false)); - status_t result = - mThreadedRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL); - ASSERT_EQ(false, result); +TEST_F(RenderEngineThreadedTest, PostRenderCleanup_skipped) { + EXPECT_CALL(*mRenderEngine, canSkipPostRenderCleanup()).WillOnce(Return(true)); + EXPECT_CALL(*mRenderEngine, cleanupPostRender()).Times(0); + mThreadedRE->cleanupPostRender(); + + // call ANY synchronous function to ensure that cleanupPostRender has completed. + mThreadedRE->getContextPriority(); } -TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsTrue) { - EXPECT_CALL(*mRenderEngine, - cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL)) - .WillOnce(Return(true)); - status_t result = - mThreadedRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL); - ASSERT_EQ(true, result); +TEST_F(RenderEngineThreadedTest, PostRenderCleanup_notSkipped) { + EXPECT_CALL(*mRenderEngine, canSkipPostRenderCleanup()).WillOnce(Return(false)); + EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return()); + mThreadedRE->cleanupPostRender(); + + // call ANY synchronous function to ensure that cleanupPostRender has completed. + mThreadedRE->getContextPriority(); } TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsFalse) { diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 74c5f476dd..ea3871f235 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -24,6 +24,7 @@ #include <android-base/stringprintf.h> #include <private/gui/SyncFeatures.h> +#include <processgroup/processgroup.h> #include <utils/Trace.h> #include "gl/GLESRenderEngine.h" @@ -80,6 +81,10 @@ status_t RenderEngineThreaded::setSchedFifo(bool enabled) { void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); + if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) { + ALOGW("Failed to set render-engine task profile!"); + } + if (setSchedFifo(true) != NO_ERROR) { ALOGW("Couldn't set SCHED_FIFO"); } @@ -270,19 +275,26 @@ bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) { return resultFuture.get(); } -bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) { - std::promise<bool> resultPromise; - std::future<bool> resultFuture = resultPromise.get_future(); +void RenderEngineThreaded::cleanupPostRender() { + if (canSkipPostRenderCleanup()) { + return; + } + + // This function is designed so it can run asynchronously, so we do not need to wait + // for the futures. { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise, mode](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::cleanupPostRender"); - bool returnValue = instance.cleanupPostRender(mode); - resultPromise.set_value(returnValue); + mFunctionCalls.push([=](renderengine::RenderEngine& instance) { + ATRACE_NAME("REThreaded::unmapExternalTextureBuffer"); + instance.cleanupPostRender(); }); } mCondition.notify_one(); - return resultFuture.get(); +} + +bool RenderEngineThreaded::canSkipPostRenderCleanup() const { + waitUntilInitialized(); + return mRenderEngine->canSkipPostRenderCleanup(); } status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index c81f137726..9b523b2140 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -54,7 +54,7 @@ public: bool isProtected() const override; bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; - bool cleanupPostRender(CleanupMode mode) override; + void cleanupPostRender() override; status_t drawLayers(const DisplaySettings& display, const std::vector<const LayerSettings*>& layers, @@ -70,6 +70,7 @@ public: protected: void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override; void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override; + bool canSkipPostRenderCleanup() const override; private: void threadMain(CreateInstanceFactory factory); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index cf433c08d9..d2b8739f96 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3787,7 +3787,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs* args) { if (shouldSendKeyToInputFilterLocked(args)) { mLock.unlock(); - policyFlags |= POLICY_FLAG_FILTERED; + policyFlags |= POLICY_FLAG_FILTERED | POLICY_FLAG_INPUTFILTER_TRUSTED; if (!mPolicy->filterInputEvent(&event, policyFlags)) { return; // event was consumed by the filter } @@ -4009,6 +4009,19 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( policyFlags |= POLICY_FLAG_TRUSTED; } + // For all injected events, set device id = VIRTUAL_KEYBOARD_ID. The only exception is events + // that have gone through the InputFilter. If the event passed through the InputFilter, + // but did not get modified, assign the provided device id. If the InputFilter modifies the + // events in any way, it is responsible for removing this flag. + // If the injected event originated from accessibility, assign the accessibility device id, + // so that it can be distinguished from regular injected events. + int32_t resolvedDeviceId = VIRTUAL_KEYBOARD_ID; + if (policyFlags & POLICY_FLAG_INPUTFILTER_TRUSTED) { + resolvedDeviceId = event->getDeviceId(); + } else if (policyFlags & POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY) { + resolvedDeviceId = ACCESSIBILITY_DEVICE_ID; + } + std::queue<std::unique_ptr<EventEntry>> injectedEntries; switch (event->getType()) { case AINPUT_EVENT_TYPE_KEY: { @@ -4021,10 +4034,10 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( int32_t flags = incomingKey.getFlags(); int32_t keyCode = incomingKey.getKeyCode(); int32_t metaState = incomingKey.getMetaState(); - accelerateMetaShortcuts(VIRTUAL_KEYBOARD_ID, action, + accelerateMetaShortcuts(resolvedDeviceId, action, /*byref*/ keyCode, /*byref*/ metaState); KeyEvent keyEvent; - keyEvent.initialize(incomingKey.getId(), VIRTUAL_KEYBOARD_ID, incomingKey.getSource(), + keyEvent.initialize(incomingKey.getId(), resolvedDeviceId, incomingKey.getSource(), incomingKey.getDisplayId(), INVALID_HMAC, action, flags, keyCode, incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(), incomingKey.getDownTime(), incomingKey.getEventTime()); @@ -4045,7 +4058,7 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( mLock.lock(); std::unique_ptr<KeyEntry> injectedEntry = std::make_unique<KeyEntry>(incomingKey.getId(), incomingKey.getEventTime(), - VIRTUAL_KEYBOARD_ID, incomingKey.getSource(), + resolvedDeviceId, incomingKey.getSource(), incomingKey.getDisplayId(), policyFlags, action, flags, keyCode, incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(), @@ -4055,18 +4068,18 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( } case AINPUT_EVENT_TYPE_MOTION: { - const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event); - int32_t action = motionEvent->getAction(); - size_t pointerCount = motionEvent->getPointerCount(); - const PointerProperties* pointerProperties = motionEvent->getPointerProperties(); - int32_t actionButton = motionEvent->getActionButton(); - int32_t displayId = motionEvent->getDisplayId(); + const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); + int32_t action = motionEvent.getAction(); + size_t pointerCount = motionEvent.getPointerCount(); + const PointerProperties* pointerProperties = motionEvent.getPointerProperties(); + int32_t actionButton = motionEvent.getActionButton(); + int32_t displayId = motionEvent.getDisplayId(); if (!validateMotionEvent(action, actionButton, pointerCount, pointerProperties)) { return InputEventInjectionResult::FAILED; } if (!(policyFlags & POLICY_FLAG_FILTERED)) { - nsecs_t eventTime = motionEvent->getEventTime(); + nsecs_t eventTime = motionEvent.getEventTime(); android::base::Timer t; mPolicy->interceptMotionBeforeQueueing(displayId, eventTime, /*byref*/ policyFlags); if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) { @@ -4076,47 +4089,46 @@ InputEventInjectionResult InputDispatcher::injectInputEvent( } mLock.lock(); - const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes(); - const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords(); + const nsecs_t* sampleEventTimes = motionEvent.getSampleEventTimes(); + const PointerCoords* samplePointerCoords = motionEvent.getSamplePointerCoords(); std::unique_ptr<MotionEntry> injectedEntry = - std::make_unique<MotionEntry>(motionEvent->getId(), *sampleEventTimes, - VIRTUAL_KEYBOARD_ID, motionEvent->getSource(), - motionEvent->getDisplayId(), policyFlags, action, - actionButton, motionEvent->getFlags(), - motionEvent->getMetaState(), - motionEvent->getButtonState(), - motionEvent->getClassification(), - motionEvent->getEdgeFlags(), - motionEvent->getXPrecision(), - motionEvent->getYPrecision(), - motionEvent->getRawXCursorPosition(), - motionEvent->getRawYCursorPosition(), - motionEvent->getDownTime(), - uint32_t(pointerCount), pointerProperties, - samplePointerCoords, motionEvent->getXOffset(), - motionEvent->getYOffset()); + std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes, + resolvedDeviceId, motionEvent.getSource(), + motionEvent.getDisplayId(), policyFlags, action, + actionButton, motionEvent.getFlags(), + motionEvent.getMetaState(), + motionEvent.getButtonState(), + motionEvent.getClassification(), + motionEvent.getEdgeFlags(), + motionEvent.getXPrecision(), + motionEvent.getYPrecision(), + motionEvent.getRawXCursorPosition(), + motionEvent.getRawYCursorPosition(), + motionEvent.getDownTime(), uint32_t(pointerCount), + pointerProperties, samplePointerCoords, + motionEvent.getXOffset(), + motionEvent.getYOffset()); injectedEntries.push(std::move(injectedEntry)); - for (size_t i = motionEvent->getHistorySize(); i > 0; i--) { + for (size_t i = motionEvent.getHistorySize(); i > 0; i--) { sampleEventTimes += 1; samplePointerCoords += pointerCount; std::unique_ptr<MotionEntry> nextInjectedEntry = - std::make_unique<MotionEntry>(motionEvent->getId(), *sampleEventTimes, - VIRTUAL_KEYBOARD_ID, motionEvent->getSource(), - motionEvent->getDisplayId(), policyFlags, - action, actionButton, motionEvent->getFlags(), - motionEvent->getMetaState(), - motionEvent->getButtonState(), - motionEvent->getClassification(), - motionEvent->getEdgeFlags(), - motionEvent->getXPrecision(), - motionEvent->getYPrecision(), - motionEvent->getRawXCursorPosition(), - motionEvent->getRawYCursorPosition(), - motionEvent->getDownTime(), + std::make_unique<MotionEntry>(motionEvent.getId(), *sampleEventTimes, + resolvedDeviceId, motionEvent.getSource(), + motionEvent.getDisplayId(), policyFlags, + action, actionButton, motionEvent.getFlags(), + motionEvent.getMetaState(), + motionEvent.getButtonState(), + motionEvent.getClassification(), + motionEvent.getEdgeFlags(), + motionEvent.getXPrecision(), + motionEvent.getYPrecision(), + motionEvent.getRawXCursorPosition(), + motionEvent.getRawYCursorPosition(), + motionEvent.getDownTime(), uint32_t(pointerCount), pointerProperties, - samplePointerCoords, - motionEvent->getXOffset(), - motionEvent->getYOffset()); + samplePointerCoords, motionEvent.getXOffset(), + motionEvent.getYOffset()); injectedEntries.push(std::move(nextInjectedEntry)); } break; diff --git a/services/inputflinger/reader/TouchVideoDevice.cpp b/services/inputflinger/reader/TouchVideoDevice.cpp index c075078528..c7c8e28419 100644 --- a/services/inputflinger/reader/TouchVideoDevice.cpp +++ b/services/inputflinger/reader/TouchVideoDevice.cpp @@ -169,8 +169,9 @@ size_t TouchVideoDevice::readAndQueueFrames() { mFrames.insert(mFrames.end(), std::make_move_iterator(frames.begin()), std::make_move_iterator(frames.end())); if (mFrames.size() > MAX_QUEUE_SIZE) { - ALOGE("More than %zu frames have been accumulated. Dropping %zu frames", MAX_QUEUE_SIZE, - mFrames.size() - MAX_QUEUE_SIZE); + // A user-space grip suppression process may be processing the video frames, and holding + // back the input events. This could result in video frames being produced without the + // matching input events. Drop the oldest frame here to prepare for the next input event. mFrames.erase(mFrames.begin(), mFrames.end() - MAX_QUEUE_SIZE); } return numFrames; diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 93aa6aca6d..d51acce4b2 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -473,6 +473,7 @@ protected: const sp<InputWindowHandle>& focusedWindow = nullptr) { FocusRequest request; request.token = window->getToken(); + request.windowName = window->getName(); if (focusedWindow) { request.focusedToken = focusedWindow->getToken(); } @@ -1085,6 +1086,20 @@ public: return mInputReceiver->consume(); } + MotionEvent* consumeMotion() { + InputEvent* event = consume(); + if (event == nullptr) { + ADD_FAILURE() << "Consume failed : no event"; + return nullptr; + } + if (event->getType() != AINPUT_EVENT_TYPE_MOTION) { + ADD_FAILURE() << "Instead of motion event, got " + << inputEventTypeToString(event->getType()); + return nullptr; + } + return static_cast<MotionEvent*>(event); + } + void assertNoEvents() { if (mInputReceiver == nullptr && mInfo.inputFeatures.test(InputWindowInfo::Feature::NO_INPUT_CHANNEL)) { @@ -2446,13 +2461,10 @@ TEST_F(InputDispatcherTest, NonPointerMotionEvent_NotTransformed) { generateMotionArgs(AMOTION_EVENT_ACTION_MOVE, source, ADISPLAY_ID_DEFAULT); mDispatcher->notifyMotion(&motionArgs); - InputEvent* event = window->consume(); + MotionEvent* event = window->consumeMotion(); ASSERT_NE(event, nullptr); - ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) - << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION) - << " event, got " << inputEventTypeToString(event->getType()) << " event"; - const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event); + const MotionEvent& motionEvent = *event; EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, motionEvent.getAction()); EXPECT_EQ(motionArgs.pointerCount, motionEvent.getPointerCount()); @@ -3118,6 +3130,70 @@ TEST_F(InputFilterTest, KeyEvent_InputFilter) { testNotifyKey(/*expectToBeFiltered*/ false); } +class InputFilterInjectionPolicyTest : public InputDispatcherTest { +protected: + virtual void SetUp() override { + InputDispatcherTest::SetUp(); + + /** + * We don't need to enable input filter to test the injected event policy, but we enabled it + * here to make the tests more realistic, since this policy only matters when inputfilter is + * on. + */ + mDispatcher->setInputFilterEnabled(true); + + std::shared_ptr<InputApplicationHandle> application = + std::make_shared<FakeApplicationHandle>(); + mWindow = + new FakeWindowHandle(application, mDispatcher, "Test Window", ADISPLAY_ID_DEFAULT); + + mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); + mWindow->setFocusable(true); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}}); + setFocusedWindow(mWindow); + mWindow->consumeFocusEvent(true); + } + + void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId) { + KeyEvent event; + + const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC); + event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD, + ADISPLAY_ID_NONE, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, + KEY_A, AMETA_NONE, 0 /*repeatCount*/, eventTime, eventTime); + const int32_t additionalPolicyFlags = + POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT; + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID, + InputEventInjectionSync::WAIT_FOR_RESULT, 10ms, + policyFlags | additionalPolicyFlags)); + + InputEvent* received = mWindow->consume(); + ASSERT_NE(nullptr, received); + ASSERT_EQ(resolvedDeviceId, received->getDeviceId()); + } + +private: + sp<FakeWindowHandle> mWindow; +}; + +TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) { + // We don't need POLICY_FLAG_FILTERED here, but it will be set in practice, so keep it to make + // the test more closely resemble the real usage + testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INPUTFILTER_TRUSTED, 3 /*injectedDeviceId*/, + 3 /*resolvedDeviceId*/); +} + +TEST_F(InputFilterInjectionPolicyTest, EventsInjectedFromAccessibility_HaveAccessibilityDeviceId) { + testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY, + 3 /*injectedDeviceId*/, ACCESSIBILITY_DEVICE_ID /*resolvedDeviceId*/); +} + +TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) { + testInjectedKey(0 /*policyFlags*/, 3 /*injectedDeviceId*/, + VIRTUAL_KEYBOARD_ID /*resolvedDeviceId*/); +} + class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { virtual void SetUp() override { InputDispatcherTest::SetUp(); diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index a1c800ed06..228172140b 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -1626,19 +1626,17 @@ void SensorService::onProximityActiveLocked(bool isActive) { } void SensorService::notifyProximityStateLocked( - const std::vector<sp<ProximityActiveListener>>& listnrs) { - std::async( - std::launch::async, - [](uint64_t mySeq, bool isActive, std::vector<sp<ProximityActiveListener>> listeners) { - while (completedCallbackSeq.load() != mySeq - 1) - std::this_thread::sleep_for(1ms); - for (auto& listener : listeners) - listener->onProximityActive(isActive); - completedCallbackSeq++; - }, - ++curProxCallbackSeq, mProximityActiveCount > 0, - listnrs /* (this is meant to be a copy) */ - ); + const std::vector<sp<ProximityActiveListener>>& listeners) { + const bool isActive = mProximityActiveCount > 0; + const uint64_t mySeq = ++curProxCallbackSeq; + std::thread t([isActive, mySeq, listenersCopy = listeners]() { + while (completedCallbackSeq.load() != mySeq - 1) + std::this_thread::sleep_for(1ms); + for (auto& listener : listenersCopy) + listener->onProximityActive(isActive); + completedCallbackSeq++; + }); + t.detach(); } status_t SensorService::addProximityActiveListener(const sp<ProximityActiveListener>& callback) { diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 3523b565dc..c294ff2695 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -693,6 +693,7 @@ void SurfaceFrame::traceActuals(int64_t displayFrameToken) const { actualSurfaceFrameStartEvent->set_gpu_composition(mGpuComposition); actualSurfaceFrameStartEvent->set_jank_type(jankTypeBitmaskToProto(mJankType)); actualSurfaceFrameStartEvent->set_prediction_type(toProto(mPredictionState)); + actualSurfaceFrameStartEvent->set_is_buffer(mIsBuffer); }); // Actual timeline end diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f02f1e2864..c1d28b1746 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -63,6 +63,7 @@ #include <log/log.h> #include <private/android_filesystem_config.h> #include <private/gui/SyncFeatures.h> +#include <processgroup/processgroup.h> #include <renderengine/RenderEngine.h> #include <sys/types.h> #include <ui/ColorSpace.h> @@ -785,6 +786,12 @@ void SurfaceFlinger::init() { ? renderengine::RenderEngine::ContextPriority::REALTIME : renderengine::RenderEngine::ContextPriority::MEDIUM) .build())); + + // Set SF main policy after initializing RenderEngine which has its own policy. + if (!SetTaskProfiles(0, {"SFMainPolicy"})) { + ALOGW("Failed to set main task profile"); + } + mCompositionEngine->setTimeStats(mTimeStats); mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName)); mCompositionEngine->getHwComposer().setCallback(this); diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 71a567a23f..0a8c7486f7 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -877,7 +877,7 @@ ProtoExpectedSurfaceFrameStart createProtoExpectedSurfaceFrameStart(int64_t cook ProtoActualSurfaceFrameStart createProtoActualSurfaceFrameStart( int64_t cookie, int64_t token, int64_t displayFrameToken, pid_t pid, std::string layerName, ProtoPresentType presentType, bool onTimeFinish, bool gpuComposition, - ProtoJankType jankType, ProtoPredictionType predictionType) { + ProtoJankType jankType, ProtoPredictionType predictionType, bool isBuffer) { ProtoActualSurfaceFrameStart proto; proto.set_cookie(cookie); proto.set_token(token); @@ -889,6 +889,7 @@ ProtoActualSurfaceFrameStart createProtoActualSurfaceFrameStart( proto.set_gpu_composition(gpuComposition); proto.set_jank_type(jankType); proto.set_prediction_type(predictionType); + proto.set_is_buffer(isBuffer); return proto; } @@ -978,6 +979,8 @@ void validateTraceEvent(const ProtoActualSurfaceFrameStart& received, EXPECT_EQ(received.jank_type(), source.jank_type()); ASSERT_TRUE(received.has_prediction_type()); EXPECT_EQ(received.prediction_type(), source.prediction_type()); + ASSERT_TRUE(received.has_is_buffer()); + EXPECT_EQ(received.is_buffer(), source.is_buffer()); } void validateTraceEvent(const ProtoFrameEnd& received, const ProtoFrameEnd& source) { @@ -1154,7 +1157,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { displayFrameToken1, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_DROPPED, false, false, FrameTimelineEvent::JANK_NONE, - FrameTimelineEvent::PREDICTION_VALID); + FrameTimelineEvent::PREDICTION_VALID, true); auto protoDroppedSurfaceFrameActualEnd = createProtoFrameEnd(traceCookie + 2); auto protoPresentedSurfaceFrameExpectedStart = @@ -1166,7 +1169,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { displayFrameToken1, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_ON_TIME, true, false, FrameTimelineEvent::JANK_NONE, - FrameTimelineEvent::PREDICTION_VALID); + FrameTimelineEvent::PREDICTION_VALID, true); auto protoPresentedSurfaceFrameActualEnd = createProtoFrameEnd(traceCookie + 4); // Set up the display frame @@ -1309,7 +1312,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDoesNotTraceExpecte displayFrameToken, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_UNSPECIFIED, false, false, FrameTimelineEvent::JANK_UNKNOWN, - FrameTimelineEvent::PREDICTION_EXPIRED); + FrameTimelineEvent::PREDICTION_EXPIRED, true); auto protoActualSurfaceFrameEnd = createProtoFrameEnd(traceCookie + 1); // Set up the display frame @@ -1383,7 +1386,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_predictionExpiredDroppedFramesTraced displayFrameToken, sPidOne, sLayerNameOne, FrameTimelineEvent::PRESENT_DROPPED, false, false, FrameTimelineEvent::JANK_NONE, - FrameTimelineEvent::PREDICTION_EXPIRED); + FrameTimelineEvent::PREDICTION_EXPIRED, true); auto protoActualSurfaceFrameEnd = createProtoFrameEnd(traceCookie + 1); // Set up the display frame |