diff options
30 files changed, 550 insertions, 120 deletions
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h index 4365a3c4e3..d23e3b7767 100644 --- a/include/input/IInputFlinger.h +++ b/include/input/IInputFlinger.h @@ -37,7 +37,6 @@ public: virtual void setInputWindows(const std::vector<InputWindowInfo>& inputHandles, const sp<ISetInputWindowsListener>& setInputWindowsListener) = 0; - virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0; virtual void registerInputChannel(const sp<InputChannel>& channel) = 0; virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0; }; @@ -51,8 +50,7 @@ public: enum { SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, REGISTER_INPUT_CHANNEL_TRANSACTION, - UNREGISTER_INPUT_CHANNEL_TRANSACTION, - TRANSFER_TOUCH_FOCUS + UNREGISTER_INPUT_CHANNEL_TRANSACTION }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp index 0ede8b1916..90fded0e85 100644 --- a/libs/dumputils/dump_utils.cpp +++ b/libs/dumputils/dump_utils.cpp @@ -71,6 +71,9 @@ static const char* hal_interfaces_to_dump[] { "android.hardware.sensors@1.0::ISensors", "android.hardware.thermal@2.0::IThermal", "android.hardware.vr@1.0::IVr", + "android.hardware.automotive.audiocontrol@1.0::IAudioControl", + "android.hardware.automotive.vehicle@2.0::IVehicle", + "android.hardware.automotive.evs@1.0::IEvsCamera", NULL, }; diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 528bfb194e..3a7cb44450 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -166,7 +166,9 @@ status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, mCore->mFreeBuffers.push_back(front->mSlot); } - listener = mCore->mConnectedProducerListener; + if (mCore->mBufferReleasedCbEnabled) { + listener = mCore->mConnectedProducerListener; + } ++numDroppedBuffers; } @@ -457,7 +459,9 @@ status_t BufferQueueConsumer::releaseBuffer(int slot, uint64_t frameNumber, mCore->mFreeBuffers.push_back(slot); } - listener = mCore->mConnectedProducerListener; + if (mCore->mBufferReleasedCbEnabled) { + listener = mCore->mConnectedProducerListener; + } BQ_LOGV("releaseBuffer: releasing slot %d", slot); mCore->mDequeueCondition.notify_all(); @@ -668,7 +672,7 @@ status_t BufferQueueConsumer::setMaxAcquiredBufferCount( BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers); mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers; VALIDATE_CONSISTENCY(); - if (delta < 0) { + if (delta < 0 && mCore->mBufferReleasedCbEnabled) { listener = mCore->mConsumerListener; } } diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index e0e3431ca5..0264bd24a6 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -65,6 +65,7 @@ BufferQueueCore::BufferQueueCore() : mConnectedApi(NO_CONNECTED_API), mLinkedToDeath(), mConnectedProducerListener(), + mBufferReleasedCbEnabled(false), mSlots(), mQueue(), mFreeSlots(), @@ -260,6 +261,12 @@ void BufferQueueCore::freeAllBuffersLocked() { } void BufferQueueCore::discardFreeBuffersLocked() { + // Notify producer about the discarded buffers. + if (mConnectedProducerListener != nullptr && mFreeBuffers.size() > 0) { + std::vector<int32_t> freeBuffers(mFreeBuffers.begin(), mFreeBuffers.end()); + mConnectedProducerListener->onBuffersDiscarded(freeBuffers); + } + for (int s : mFreeBuffers) { mFreeSlots.insert(s); clearBufferSlotLocked(s); diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 3efb1b6acb..4f8eb6b5e8 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1221,9 +1221,8 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, } mCore->mLinkedToDeath = listener; } - if (listener->needsReleaseNotify()) { - mCore->mConnectedProducerListener = listener; - } + mCore->mConnectedProducerListener = listener; + mCore->mBufferReleasedCbEnabled = listener->needsReleaseNotify(); } break; default: diff --git a/libs/gui/IProducerListener.cpp b/libs/gui/IProducerListener.cpp index 936063a5bd..808e3369f1 100644 --- a/libs/gui/IProducerListener.cpp +++ b/libs/gui/IProducerListener.cpp @@ -24,6 +24,7 @@ namespace android { enum { ON_BUFFER_RELEASED = IBinder::FIRST_CALL_TRANSACTION, NEEDS_RELEASE_NOTIFY, + ON_BUFFERS_DISCARDED, }; class BpProducerListener : public BpInterface<IProducerListener> @@ -56,6 +57,13 @@ public: } return result; } + + virtual void onBuffersDiscarded(const std::vector<int>& discardedSlots) { + Parcel data, reply; + data.writeInterfaceToken(IProducerListener::getInterfaceDescriptor()); + data.writeInt32Vector(discardedSlots); + remote()->transact(ON_BUFFERS_DISCARDED, data, &reply, IBinder::FLAG_ONEWAY); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -76,6 +84,10 @@ public: virtual bool needsReleaseNotify() override { return mBase->needsReleaseNotify(); } + + virtual void onBuffersDiscarded(const std::vector<int32_t>& discardedSlots) override { + return mBase->onBuffersDiscarded(discardedSlots); + } }; IMPLEMENT_HYBRID_META_INTERFACE(ProducerListener, @@ -92,6 +104,17 @@ status_t BnProducerListener::onTransact(uint32_t code, const Parcel& data, CHECK_INTERFACE(IProducerListener, data, reply); reply->writeBool(needsReleaseNotify()); return NO_ERROR; + case ON_BUFFERS_DISCARDED: { + CHECK_INTERFACE(IProducerListener, data, reply); + std::vector<int32_t> discardedSlots; + status_t result = data.readInt32Vector(&discardedSlots); + if (result != NO_ERROR) { + ALOGE("ON_BUFFERS_DISCARDED failed to read discardedSlots: %d", result); + return result; + } + onBuffersDiscarded(discardedSlots); + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } @@ -104,4 +127,7 @@ bool BnProducerListener::needsReleaseNotify() { return true; } +void BnProducerListener::onBuffersDiscarded(const std::vector<int32_t>& /*discardedSlots*/) { +} + } // namespace android diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 9fe5de82d1..b822319d22 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -35,6 +35,7 @@ #include <ui/DisplayStatInfo.h> #include <ui/Fence.h> +#include <ui/GraphicBuffer.h> #include <ui/HdrCapabilities.h> #include <ui/Region.h> @@ -1287,6 +1288,14 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) { } int Surface::connect( + int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) { + if (sListener != nullptr) { + mListenerProxy = new ProducerListenerProxy(this, sListener); + } + return connect(api, mListenerProxy, reportBufferRemoval); +} + +int Surface::connect( int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) { ATRACE_CALL(); ALOGV("Surface::connect"); @@ -1684,6 +1693,28 @@ void Surface::freeAllBuffers() { } } +status_t Surface::getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots, + std::vector<sp<GraphicBuffer>>* outBuffers) { + ALOGV("Surface::getAndFlushBuffersFromSlots"); + for (int32_t i : slots) { + if (i < 0 || i >= NUM_BUFFER_SLOTS) { + ALOGE("%s: Invalid slotIndex: %d", __FUNCTION__, i); + return BAD_VALUE; + } + } + + Mutex::Autolock lock(mMutex); + for (int32_t i : slots) { + if (mSlots[i].buffer == nullptr) { + ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i); + continue; + } + outBuffers->push_back(mSlots[i].buffer); + mSlots[i].buffer = nullptr; + } + return OK; +} + void Surface::setSurfaceDamage(android_native_rect_t* rects, size_t numRects) { ATRACE_CALL(); ALOGV("Surface::setSurfaceDamage"); @@ -1951,4 +1982,22 @@ status_t Surface::attachAndQueueBufferWithDataspace(Surface* surface, sp<Graphic return err; } +void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_t>& slots) { + ATRACE_CALL(); + sp<Surface> parent = mParent.promote(); + if (parent == nullptr) { + return; + } + + std::vector<sp<GraphicBuffer>> discardedBufs; + status_t res = parent->getAndFlushBuffersFromSlots(slots, &discardedBufs); + if (res != OK) { + ALOGE("%s: Failed to get buffers from slots: %s(%d)", __FUNCTION__, + strerror(-res), res); + return; + } + + mSurfaceListener->onBuffersDiscarded(discardedBufs); +} + }; // namespace android diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h index 690a85f395..17617bce13 100644 --- a/libs/gui/include/gui/BufferQueueCore.h +++ b/libs/gui/include/gui/BufferQueueCore.h @@ -189,8 +189,12 @@ private: sp<IProducerListener> mLinkedToDeath; // mConnectedProducerListener is used to handle the onBufferReleased - // notification. + // and onBuffersDiscarded notification. sp<IProducerListener> mConnectedProducerListener; + // mBufferReleasedCbEnabled is used to indicate whether onBufferReleased() + // callback is registered by the listener. When set to false, + // mConnectedProducerListener will not trigger onBufferReleased() callback. + bool mBufferReleasedCbEnabled; // mSlots is an array of buffer slots that must be mirrored on the producer // side. This allows buffer ownership to be transferred between the producer diff --git a/libs/gui/include/gui/IProducerListener.h b/libs/gui/include/gui/IProducerListener.h index a13d8e4945..32a3690ff2 100644 --- a/libs/gui/include/gui/IProducerListener.h +++ b/libs/gui/include/gui/IProducerListener.h @@ -17,6 +17,8 @@ #ifndef ANDROID_GUI_IPRODUCERLISTENER_H #define ANDROID_GUI_IPRODUCERLISTENER_H +#include <vector> + #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h> #include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h> #include <binder/IInterface.h> @@ -44,6 +46,9 @@ public: // multiple threads. virtual void onBufferReleased() = 0; // Asynchronous virtual bool needsReleaseNotify() = 0; + // onBuffersFreed is called from IGraphicBufferConsumer::discardFreeBuffers + // to notify the producer that certain free buffers are discarded by the consumer. + virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) = 0; // Asynchronous }; class IProducerListener : public ProducerListener, public IInterface @@ -65,6 +70,7 @@ public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); virtual bool needsReleaseNotify(); + virtual void onBuffersDiscarded(const std::vector<int32_t>& slots); }; class DummyProducerListener : public BnProducerListener diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 5c6a1ee383..a5641b07e5 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -20,6 +20,7 @@ #include <gui/BufferQueueDefs.h> #include <gui/HdrMetadata.h> #include <gui/IGraphicBufferProducer.h> +#include <gui/IProducerListener.h> #include <ui/ANativeObjectBase.h> #include <ui/GraphicTypes.h> @@ -35,6 +36,21 @@ namespace android { class ISurfaceComposer; +/* This is the same as ProducerListener except that onBuffersDiscarded is + * called with a vector of graphic buffers instead of buffer slots. + */ +class SurfaceListener : public virtual RefBase +{ +public: + SurfaceListener() = default; + virtual ~SurfaceListener() = default; + + virtual void onBufferReleased() = 0; + virtual bool needsReleaseNotify() = 0; + + virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) = 0; +}; + /* * An implementation of ANativeWindow that feeds graphics buffers into a * BufferQueue. @@ -283,6 +299,10 @@ public: sp<Fence>* outFence); virtual int attachBuffer(ANativeWindowBuffer*); + virtual int connect( + int api, bool reportBufferRemoval, + const sp<SurfaceListener>& sListener); + // When client connects to Surface with reportBufferRemoval set to true, any buffers removed // from this Surface will be collected and returned here. Once this method returns, these // buffers will no longer be referenced by this Surface unless they are attached to this @@ -299,6 +319,26 @@ protected: enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS }; enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 }; + class ProducerListenerProxy : public BnProducerListener { + public: + ProducerListenerProxy(wp<Surface> parent, sp<SurfaceListener> listener) + : mParent(parent), mSurfaceListener(listener) {} + virtual ~ProducerListenerProxy() {} + + virtual void onBufferReleased() { + mSurfaceListener->onBufferReleased(); + } + + virtual bool needsReleaseNotify() { + return mSurfaceListener->needsReleaseNotify(); + } + + virtual void onBuffersDiscarded(const std::vector<int32_t>& slots); + private: + wp<Surface> mParent; + sp<SurfaceListener> mSurfaceListener; + }; + void querySupportedTimestampsLocked() const; void freeAllBuffers(); @@ -466,6 +506,10 @@ protected: bool mReportRemovedBuffers = false; std::vector<sp<GraphicBuffer>> mRemovedBuffers; + + sp<IProducerListener> mListenerProxy; + status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots, + std::vector<sp<GraphicBuffer>>* outBuffers); }; } // namespace android diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 119e888edb..406f21faf6 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -998,12 +998,31 @@ TEST_F(BufferQueueTest, TestOccupancyHistory) { ASSERT_EQ(true, thirdSegment.usedThirdBuffer); } +struct BufferDiscardedListener : public BnProducerListener { +public: + BufferDiscardedListener() = default; + virtual ~BufferDiscardedListener() = default; + + virtual void onBufferReleased() {} + virtual bool needsReleaseNotify() { return false; } + virtual void onBuffersDiscarded(const std::vector<int32_t>& slots) { + mDiscardedSlots.insert(mDiscardedSlots.end(), slots.begin(), slots.end()); + } + + const std::vector<int32_t>& getDiscardedSlots() const { return mDiscardedSlots; } +private: + // No need to use lock given the test triggers the listener in the same + // thread context. + std::vector<int32_t> mDiscardedSlots; +}; + TEST_F(BufferQueueTest, TestDiscardFreeBuffers) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false)); IGraphicBufferProducer::QueueBufferOutput output; - ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener, + sp<BufferDiscardedListener> pl(new BufferDiscardedListener); + ASSERT_EQ(OK, mProducer->connect(pl, NATIVE_WINDOW_API_CPU, false, &output)); int slot = BufferQueue::INVALID_BUFFER_SLOT; @@ -1044,12 +1063,19 @@ TEST_F(BufferQueueTest, TestDiscardFreeBuffers) { ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE)); + int releasedSlot = item.mSlot; + // Acquire 1 buffer, leaving 1 filled buffer in queue ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0)); // Now discard the free buffers ASSERT_EQ(OK, mConsumer->discardFreeBuffers()); + // Check onBuffersDiscarded is called with correct slots + auto buffersDiscarded = pl->getDiscardedSlots(); + ASSERT_EQ(buffersDiscarded.size(), 1); + ASSERT_EQ(buffersDiscarded[0], releasedSlot); + // Check no free buffers in dump String8 dumpString; mConsumer->dumpState(String8{}, &dumpString); diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 386f731d23..03b9cd75db 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -133,27 +133,6 @@ public: EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction()); } - void expectMotionEvent(int motionEventType, int x, int y) { - InputEvent *ev = consumeEvent(); - ASSERT_NE(ev, nullptr); - ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION); - MotionEvent *mev = static_cast<MotionEvent *>(ev); - EXPECT_EQ(motionEventType, mev->getAction()); - EXPECT_EQ(x, mev->getX(0)); - EXPECT_EQ(y, mev->getY(0)); - } - - void expectNoMotionEvent(int motionEventType) { - InputEvent *ev = consumeEvent(); - if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) { - // Didn't find an event or a motion event so assume action didn't occur. - return; - } - - MotionEvent *mev = static_cast<MotionEvent *>(ev); - EXPECT_NE(motionEventType, mev->getAction()); - } - ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel); } @@ -278,15 +257,6 @@ void injectTap(int x, int y) { } } -void injectMotionEvent(std::string event, int x, int y) { - char *buf1, *buf2; - asprintf(&buf1, "%d", x); - asprintf(&buf2, "%d", y); - if (fork() == 0) { - execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL); - } -} - TEST_F(InputSurfacesTest, can_receive_input) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(100, 100); @@ -435,9 +405,11 @@ TEST_F(InputSurfacesTest, input_ignores_transparent_region) { surface->expectTap(1, 1); } -// Ensure we send the input to the right surface when the surface visibility changes due to the -// first buffer being submitted. ref: b/120839715 -TEST_F(InputSurfacesTest, input_respects_buffer_layer_buffer) { +// TODO(b/139494112) update tests once we define expected behavior +// Ensure we still send input to the surface regardless of surface visibility changes due to the +// first buffer being submitted or alpha changes. +// Original bug ref: b/120839715 +TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> bufferSurface = InputSurface::makeBufferInputSurface(mComposerClient, 100, 100); @@ -446,14 +418,14 @@ TEST_F(InputSurfacesTest, input_respects_buffer_layer_buffer) { bufferSurface->showAt(10, 10); injectTap(11, 11); - bgSurface->expectTap(1, 1); + bufferSurface->expectTap(1, 1); postBuffer(bufferSurface->mSurfaceControl); injectTap(11, 11); bufferSurface->expectTap(1, 1); } -TEST_F(InputSurfacesTest, input_respects_buffer_layer_alpha) { +TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> bufferSurface = InputSurface::makeBufferInputSurface(mComposerClient, 100, 100); @@ -468,10 +440,10 @@ TEST_F(InputSurfacesTest, input_respects_buffer_layer_alpha) { bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); }); injectTap(11, 11); - bgSurface->expectTap(1, 1); + bufferSurface->expectTap(1, 1); } -TEST_F(InputSurfacesTest, input_respects_color_layer_alpha) { +TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) { std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); @@ -484,7 +456,7 @@ TEST_F(InputSurfacesTest, input_respects_color_layer_alpha) { fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); }); injectTap(11, 11); - bgSurface->expectTap(1, 1); + fgSurface->expectTap(1, 1); } TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { @@ -504,26 +476,6 @@ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { bgSurface->expectTap(1, 1); } -TEST_F(InputSurfacesTest, transfer_touch_focus) { - std::unique_ptr<InputSurface> fromSurface = makeSurface(100, 100); - - fromSurface->showAt(10, 10); - injectMotionEvent("DOWN", 11, 11); - fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1); - - std::unique_ptr<InputSurface> toSurface = makeSurface(100, 100); - toSurface->showAt(10, 10); - - sp<IBinder> fromToken = fromSurface->mServerChannel->getToken(); - sp<IBinder> toToken = toSurface->mServerChannel->getToken(); - SurfaceComposerClient::Transaction t; - t.transferTouchFocus(fromToken, toToken).apply(true); - - injectMotionEvent("UP", 11, 11); - toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1); - fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP); -} - TEST_F(InputSurfacesTest, input_respects_outscreen) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); surface->showAt(-1, -1); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index d3708586f5..a8516872fd 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -57,6 +57,37 @@ class FakeProducerFrameEventHistory; static constexpr uint64_t NO_FRAME_INDEX = std::numeric_limits<uint64_t>::max(); +class DummySurfaceListener : public SurfaceListener { +public: + DummySurfaceListener(bool enableReleasedCb = false) : + mEnableReleaseCb(enableReleasedCb), + mBuffersReleased(0) {} + virtual ~DummySurfaceListener() = default; + + virtual void onBufferReleased() { + mBuffersReleased++; + } + virtual bool needsReleaseNotify() { + return mEnableReleaseCb; + } + virtual void onBuffersDiscarded(const std::vector<sp<GraphicBuffer>>& buffers) { + mDiscardedBuffers.insert(mDiscardedBuffers.end(), buffers.begin(), buffers.end()); + } + + int getReleaseNotifyCount() const { + return mBuffersReleased; + } + const std::vector<sp<GraphicBuffer>>& getDiscardedBuffers() const { + return mDiscardedBuffers; + } +private: + // No need to use lock given the test triggers the listener in the same + // thread context. + bool mEnableReleaseCb; + int32_t mBuffersReleased; + std::vector<sp<GraphicBuffer>> mDiscardedBuffers; +}; + class SurfaceTest : public ::testing::Test { protected: SurfaceTest() { @@ -88,6 +119,86 @@ protected: mComposerClient->dispose(); } + void testSurfaceListener(bool hasSurfaceListener, bool enableReleasedCb, + int32_t extraDiscardedBuffers) { + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + sp<DummyConsumer> dummyConsumer(new DummyConsumer); + consumer->consumerConnect(dummyConsumer, false); + consumer->setConsumerName(String8("TestConsumer")); + + sp<Surface> surface = new Surface(producer); + sp<ANativeWindow> window(surface); + sp<DummySurfaceListener> listener; + if (hasSurfaceListener) { + listener = new DummySurfaceListener(enableReleasedCb); + } + ASSERT_EQ(OK, surface->connect( + NATIVE_WINDOW_API_CPU, + /*reportBufferRemoval*/true, + /*listener*/listener)); + const int BUFFER_COUNT = 4 + extraDiscardedBuffers; + ASSERT_EQ(NO_ERROR, native_window_set_buffer_count(window.get(), BUFFER_COUNT)); + + ANativeWindowBuffer* buffers[BUFFER_COUNT]; + // Dequeue first to allocate a number of buffers + for (int i = 0; i < BUFFER_COUNT; i++) { + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffers[i])); + } + for (int i = 0; i < BUFFER_COUNT; i++) { + ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffers[i], -1)); + } + + ANativeWindowBuffer* buffer; + // Fill BUFFER_COUNT-1 buffers + for (int i = 0; i < BUFFER_COUNT-1; i++) { + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer)); + ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, -1)); + } + + // Dequeue 1 buffer + ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(window.get(), &buffer)); + + // Acquire and free 1+extraDiscardedBuffers buffer, check onBufferReleased is called. + std::vector<BufferItem> releasedItems; + releasedItems.resize(1+extraDiscardedBuffers); + for (int i = 0; i < releasedItems.size(); i++) { + ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&releasedItems[i], 0)); + ASSERT_EQ(NO_ERROR, consumer->releaseBuffer(releasedItems[i].mSlot, + releasedItems[i].mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, + Fence::NO_FENCE)); + } + int32_t expectedReleaseCb = (enableReleasedCb ? releasedItems.size() : 0); + if (hasSurfaceListener) { + ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount()); + } + + // Acquire 1 buffer, leaving 1+extraDiscardedBuffers filled buffer in queue + BufferItem item; + ASSERT_EQ(NO_ERROR, consumer->acquireBuffer(&item, 0)); + + // Discard free buffers + ASSERT_EQ(NO_ERROR, consumer->discardFreeBuffers()); + + if (hasSurfaceListener) { + ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount()); + + // Check onBufferDiscarded is called with correct buffer + auto discardedBuffers = listener->getDiscardedBuffers(); + ASSERT_EQ(discardedBuffers.size(), releasedItems.size()); + for (int i = 0; i < releasedItems.size(); i++) { + ASSERT_EQ(discardedBuffers[i], releasedItems[i].mGraphicBuffer); + } + + ASSERT_EQ(expectedReleaseCb, listener->getReleaseNotifyCount()); + } + + // Disconnect the surface + ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU)); + } + sp<Surface> mSurface; sp<SurfaceComposerClient> mComposerClient; sp<SurfaceControl> mSurfaceControl; @@ -480,6 +591,21 @@ TEST_F(SurfaceTest, GetAndFlushRemovedBuffers) { ASSERT_LE(removedBuffers.size(), 1u); } +TEST_F(SurfaceTest, SurfaceListenerTest) { + // Test discarding 1 free buffers with no listener + testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/0); + // Test discarding 2 free buffers with no listener + testSurfaceListener(/*hasListener*/false, /*enableReleaseCb*/false, /*extraDiscardedBuffers*/1); + // Test discarding 1 free buffers with a listener, disabling onBufferReleased + testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/0); + // Test discarding 2 free buffers with a listener, disabling onBufferReleased + testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/false, /*extraDiscardedBuffers*/1); + // Test discarding 1 free buffers with a listener, enabling onBufferReleased + testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/0); + // Test discarding 3 free buffers with a listener, enabling onBufferReleased + testSurfaceListener(/*hasListener*/true, /*enableReleasedCb*/true, /*extraDiscardedBuffers*/2); +} + TEST_F(SurfaceTest, TestGetLastDequeueStartTime) { sp<ANativeWindow> anw(mSurface); ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU)); diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp index d6a73bfd27..de3a23d76e 100644 --- a/libs/input/IInputFlinger.cpp +++ b/libs/input/IInputFlinger.cpp @@ -45,16 +45,6 @@ public: IBinder::FLAG_ONEWAY); } - virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - - data.writeStrongBinder(fromToken); - data.writeStrongBinder(toToken); - remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply, - IBinder::FLAG_ONEWAY); - } - virtual void registerInputChannel(const sp<InputChannel>& channel) { Parcel data, reply; data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); @@ -104,13 +94,6 @@ status_t BnInputFlinger::onTransact( unregisterInputChannel(channel); break; } - case TRANSFER_TOUCH_FOCUS: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp<IBinder> fromToken = data.readStrongBinder(); - sp<IBinder> toToken = data.readStrongBinder(); - transferTouchFocus(fromToken, toToken); - break; - } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp index 5f1c71ec4f..b54ce0fcf7 100644 --- a/libs/ui/GraphicBufferAllocator.cpp +++ b/libs/ui/GraphicBufferAllocator.cpp @@ -132,6 +132,17 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, status_t error = mAllocator->allocate(width, height, format, layerCount, usage, 1, stride, handle); + size_t bufSize; + + // if stride has no meaning or is too large, + // approximate size with the input width instead + if ((*stride) != 0 && + std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) { + bufSize = static_cast<size_t>(width) * height * bpp; + } else { + bufSize = static_cast<size_t>((*stride)) * height * bpp; + } + if (error == NO_ERROR) { Mutex::Autolock _l(sLock); KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList); @@ -142,7 +153,7 @@ status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height, rec.format = format; rec.layerCount = layerCount; rec.usage = usage; - rec.size = static_cast<size_t>(height * (*stride) * bpp); + rec.size = bufSize; rec.requestorName = std::move(requestorName); list.add(*handle, rec); diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h index faec97855a..06357270f5 100644 --- a/libs/ui/include/ui/GraphicBufferAllocator.h +++ b/libs/ui/include/ui/GraphicBufferAllocator.h @@ -54,7 +54,7 @@ public: void dump(std::string& res) const; static void dumpToSystemLog(); -private: +protected: struct alloc_rec_t { uint32_t width; uint32_t height; diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp index 99434b7273..0a07a48bd1 100644 --- a/libs/ui/tests/Android.bp +++ b/libs/ui/tests/Android.bp @@ -29,6 +29,26 @@ cc_test { } cc_test { + name: "GraphicBufferAllocator_test", + header_libs: [ + "libdvr_headers", + "libnativewindow_headers", + ], + static_libs: [ + "libgmock", + ], + shared_libs: [ + "liblog", + "libui", + ], + srcs: [ + "GraphicBufferAllocator_test.cpp", + "mock/MockGrallocAllocator.cpp", + ], + cflags: ["-Wall", "-Werror"], +} + +cc_test { name: "GraphicBuffer_test", header_libs: [ "libdvr_headers", diff --git a/libs/ui/tests/GraphicBufferAllocator_test.cpp b/libs/ui/tests/GraphicBufferAllocator_test.cpp new file mode 100644 index 0000000000..efca083e6e --- /dev/null +++ b/libs/ui/tests/GraphicBufferAllocator_test.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2019 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 "GraphicBufferAllocatorTest" + +#include <ui/GraphicBuffer.h> +#include <ui/GraphicBufferAllocator.h> +#include <ui/PixelFormat.h> + +#include <gtest/gtest.h> + +#include "mock/MockGrallocAllocator.h" + +#include <algorithm> +#include <limits> + +namespace android { + +namespace { + +constexpr uint32_t kTestWidth = 1024; +constexpr uint32_t kTestHeight = 1; +constexpr uint32_t kTestLayerCount = 1; +constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN; + +} // namespace + +using ::testing::DoAll; +using ::testing::Return; +using ::testing::SetArgPointee; + +class TestableGraphicBufferAllocator : public GraphicBufferAllocator { +public: + TestableGraphicBufferAllocator() { + mAllocator = std::make_unique<const mock::MockGrallocAllocator>(); + } + void setUpAllocateExpectations(status_t err, uint32_t stride) { + std::cout << "Setting expected stride to " << stride << std::endl; + EXPECT_CALL(*(reinterpret_cast<const mock::MockGrallocAllocator*>(mAllocator.get())), + allocate) + .WillOnce(DoAll(SetArgPointee<6>(stride), Return(err))); + } + std::unique_ptr<const GrallocAllocator>& getAllocator() { return mAllocator; } +}; + +class GraphicBufferAllocatorTest : public testing::Test { +public: + GraphicBufferAllocatorTest() : mAllocator() {} + const TestableGraphicBufferAllocator& getAllocator() { return mAllocator; } + +protected: + TestableGraphicBufferAllocator mAllocator; +}; + +TEST_F(GraphicBufferAllocatorTest, AllocateNoError) { + mAllocator.setUpAllocateExpectations(NO_ERROR, kTestWidth); + android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; + uint32_t stride = 0; + buffer_handle_t handle; + status_t err = mAllocator.allocate(kTestWidth, kTestHeight, format, kTestLayerCount, kTestUsage, + &handle, &stride, 0, "GraphicBufferAllocatorTest"); + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(kTestWidth, stride); +} + +TEST_F(GraphicBufferAllocatorTest, AllocateZeroStride) { + android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; + uint32_t expectedStride = 0; + + mAllocator.setUpAllocateExpectations(NO_ERROR, expectedStride); + uint32_t stride = 0; + buffer_handle_t handle; + // a divide by zero would cause a crash + status_t err = mAllocator.allocate(kTestWidth, kTestHeight, format, kTestLayerCount, kTestUsage, + &handle, &stride, 0, "GraphicBufferAllocatorTest"); + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(expectedStride, stride); +} + +TEST_F(GraphicBufferAllocatorTest, AllocateLargeStride) { + uint32_t height = std::numeric_limits<uint32_t>::max(); + uint32_t bpp = 4; + android::PixelFormat format = PIXEL_FORMAT_RGBA_8888; + + if (std::numeric_limits<size_t>::max() / height / bpp >= std::numeric_limits<uint32_t>::max()) { + std::cout << "stride cannot cause overflow" << std::endl; + GTEST_SUCCEED() << "stride cannot cause overflow"; + return; + } + uint32_t width = std::numeric_limits<size_t>::max() / height / bpp; + + uint32_t expectedStride = std::numeric_limits<uint32_t>::max(); + + mAllocator.setUpAllocateExpectations(NO_ERROR, expectedStride); + uint32_t stride = 0; + buffer_handle_t handle; + // an overflow would cause a crash + status_t err = mAllocator.allocate(width, height, format, kTestLayerCount, kTestUsage, &handle, + &stride, 0, "GraphicBufferAllocatorTest"); + ASSERT_EQ(NO_ERROR, err); + ASSERT_EQ(expectedStride, stride); +} +} // namespace android diff --git a/libs/ui/tests/mock/MockGrallocAllocator.cpp b/libs/ui/tests/mock/MockGrallocAllocator.cpp new file mode 100644 index 0000000000..d71e25fc08 --- /dev/null +++ b/libs/ui/tests/mock/MockGrallocAllocator.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 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 "MockGrallocAllocator.h" + +namespace android { + +namespace mock { + +MockGrallocAllocator::MockGrallocAllocator() = default; +MockGrallocAllocator::~MockGrallocAllocator() = default; + +} // namespace mock +} // namespace android diff --git a/libs/ui/tests/mock/MockGrallocAllocator.h b/libs/ui/tests/mock/MockGrallocAllocator.h new file mode 100644 index 0000000000..22c80a4638 --- /dev/null +++ b/libs/ui/tests/mock/MockGrallocAllocator.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2019 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 <gmock/gmock.h> + +#include <ui/Gralloc.h> + +namespace android { + +class GraphicBuffer; + +namespace mock { + +class MockGrallocAllocator : public GrallocAllocator { +public: + MockGrallocAllocator(); + ~MockGrallocAllocator() override; + + MOCK_METHOD(bool, isLoaded, (), (const, override)); + MOCK_METHOD(std::string, dumpDebugInfo, (), (const, override)); + MOCK_METHOD(status_t, allocate, + (uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, + uint64_t usage, uint32_t bufferCount, uint32_t* outStride, + buffer_handle_t* outBufferHandles), + (const, override)); +}; + +} // namespace mock +} // namespace android diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp index 6a7f2797f4..ef1a2247e9 100644 --- a/services/inputflinger/InputClassifier.cpp +++ b/services/inputflinger/InputClassifier.cpp @@ -82,7 +82,7 @@ static bool isTouchEvent(const NotifyMotionArgs& args) { // Check if the "deep touch" feature is on. static bool deepPressEnabled() { std::string flag_value = server_configurable_flags::GetServerConfigurableFlag( - INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "false"); + INPUT_NATIVE_BOOT, DEEP_PRESS_ENABLED, "true"); std::transform(flag_value.begin(), flag_value.end(), flag_value.begin(), ::tolower); if (flag_value == "1" || flag_value == "true") { ALOGI("Deep press feature enabled."); diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index 359325faed..7d3067242a 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -119,10 +119,6 @@ void InputManager::setInputWindows(const std::vector<InputWindowInfo>& infos, } } -void InputManager::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) { - mDispatcher->transferTouchFocus(fromToken, toToken); -} - // Used by tests only. void InputManager::registerInputChannel(const sp<InputChannel>& channel) { IPCThreadState* ipc = IPCThreadState::self(); diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index f3da324ba4..40f66d82f4 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -96,7 +96,6 @@ public: virtual void setInputWindows(const std::vector<InputWindowInfo>& handles, const sp<ISetInputWindowsListener>& setInputWindowsListener); - virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken); virtual void registerInputChannel(const sp<InputChannel>& channel); virtual void unregisterInputChannel(const sp<InputChannel>& channel); diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp index 8d05640b38..a4d9e4edc2 100644 --- a/services/inputflinger/dispatcher/Entry.cpp +++ b/services/inputflinger/dispatcher/Entry.cpp @@ -18,10 +18,12 @@ #include "Connection.h" +#include <android-base/properties.h> #include <android-base/stringprintf.h> #include <cutils/atomic.h> #include <inttypes.h> +using android::base::GetBoolProperty; using android::base::StringPrintf; namespace android::inputdispatcher { @@ -133,7 +135,11 @@ KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, ui KeyEntry::~KeyEntry() {} void KeyEntry::appendDescription(std::string& msg) const { - msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, " + msg += StringPrintf("KeyEvent"); + if (!GetBoolProperty("ro.debuggable", false)) { + return; + } + msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, " "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, " "repeatCount=%d), policyFlags=0x%08x", deviceId, source, displayId, keyActionToString(action).c_str(), flags, @@ -186,7 +192,11 @@ MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t device MotionEntry::~MotionEntry() {} void MotionEntry::appendDescription(std::string& msg) const { - msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 + msg += StringPrintf("MotionEvent"); + if (!GetBoolProperty("ro.debuggable", false)) { + return; + } + msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, " "buttonState=0x%08x, " "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, " diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index d8b352cbc6..973b4f92fa 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -42,7 +42,6 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); void setInputWindows(const std::vector<InputWindowInfo>&, const sp<ISetInputWindowsListener>&) {} - void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {} void registerInputChannel(const sp<InputChannel>&) {} void unregisterInputChannel(const sp<InputChannel>&) {} diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 7927fa95b6..e33bedbfce 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -35,11 +35,7 @@ bool ContainerLayer::isVisible() const { return false; } -bool ContainerLayer::canReceiveInput() const { - return !isHiddenByPolicy(); -} void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&, const ui::Transform&, const Rect&, int32_t, const ui::Dataspace) {} - } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 7222a3e15a..e6dbfcce4e 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -31,8 +31,6 @@ public: const char* getTypeId() const override { return "ContainerLayer"; } bool isVisible() const override; - bool canReceiveInput() const override; - void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform, const Rect& viewport, int32_t supportedPerFrameMetadata, const ui::Dataspace targetDataspace) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index dda15e9e1e..3e6ddedf48 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2106,7 +2106,7 @@ std::shared_ptr<compositionengine::Layer> Layer::getCompositionLayer() const { } bool Layer::canReceiveInput() const { - return isVisible(); + return !isHiddenByPolicy(); } compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 60b3a11754..7047710e85 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3029,7 +3029,7 @@ void SurfaceFlinger::updateInputFlinger() { setInputWindowsFinished(); } - executeInputWindowCommands(); + mInputWindowCommands.clear(); } void SurfaceFlinger::updateInputWindowInfo() { @@ -3053,19 +3053,6 @@ void SurfaceFlinger::commitInputWindowCommands() { mPendingInputWindowCommands.clear(); } -void SurfaceFlinger::executeInputWindowCommands() { - for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) { - if (transferTouchFocusCommand.fromToken != nullptr && - transferTouchFocusCommand.toToken != nullptr && - transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) { - mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken, - transferTouchFocusCommand.toToken); - } - } - - mInputWindowCommands.clear(); -} - void SurfaceFlinger::updateCursorAsync() { for (const auto& [token, display] : mDisplays) { @@ -6236,7 +6223,7 @@ status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToke return NO_ERROR; } - postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS { + postMessageSync(new LambdaMessage([&]() { const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("Attempt to set allowed display configs for invalid display token %p", @@ -6244,6 +6231,7 @@ status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToke } else if (display->isVirtual()) { ALOGW("Attempt to set allowed display configs for virtual display"); } else { + Mutex::Autolock lock(mStateLock); setAllowedDisplayConfigsInternal(display, allowedConfigs); } })); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 49bb574147..8e4203aed5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -554,7 +554,6 @@ private: void updateInputFlinger(); void updateInputWindowInfo(); void commitInputWindowCommands() REQUIRES(mStateLock); - void executeInputWindowCommands(); void setInputWindowsFinished(); void updateCursorAsync(); |