Merge "Add multi-device tests to dispatcher" into main
diff --git a/include/input/Input.h b/include/input/Input.h
index 64ee473..567361d 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -285,6 +285,16 @@
// This policy flag prevents key events from changing touch mode state.
POLICY_FLAG_GESTURE = 0x00000008,
+ // Indicates that key usage mapping represents a fallback mapping.
+ // Fallback mappings cannot be used to definitively determine whether a device
+ // supports a key code. For example, a HID device can report a key press
+ // as a HID usage code if it is not mapped to any linux key code in the kernel.
+ // However, we cannot know which HID usage codes that device supports from
+ // userspace through the evdev. We can use fallback mappings to convert HID
+ // usage codes to Android key codes without needing to know if a device can
+ // actually report the usage code.
+ POLICY_FLAG_FALLBACK_USAGE_MAPPING = 0x00000010,
+
POLICY_FLAG_RAW_MASK = 0x0000ffff,
#ifdef __linux__
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 038764b..8a57f92 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1227,7 +1227,7 @@
flags |= ISurfaceComposer::eEarlyWakeupEnd;
}
- sp<IBinder> applyToken = mApplyToken ? mApplyToken : sApplyToken;
+ sp<IBinder> applyToken = mApplyToken ? mApplyToken : getDefaultApplyToken();
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
@@ -1249,11 +1249,15 @@
sp<IBinder> SurfaceComposerClient::Transaction::sApplyToken = new BBinder();
+std::mutex SurfaceComposerClient::Transaction::sApplyTokenMutex;
+
sp<IBinder> SurfaceComposerClient::Transaction::getDefaultApplyToken() {
+ std::scoped_lock lock{sApplyTokenMutex};
return sApplyToken;
}
void SurfaceComposerClient::Transaction::setDefaultApplyToken(sp<IBinder> applyToken) {
+ std::scoped_lock lock{sApplyTokenMutex};
sApplyToken = applyToken;
}
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 42e3c16..26b1fbd 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -422,6 +422,7 @@
class Transaction : public Parcelable {
private:
static sp<IBinder> sApplyToken;
+ static std::mutex sApplyTokenMutex;
void releaseBufferIfOverwriting(const layer_state_t& state);
static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other);
diff --git a/libs/input/InputEventLabels.cpp b/libs/input/InputEventLabels.cpp
index c218e1e..0e627e5 100644
--- a/libs/input/InputEventLabels.cpp
+++ b/libs/input/InputEventLabels.cpp
@@ -430,7 +430,8 @@
DEFINE_FLAG(VIRTUAL), \
DEFINE_FLAG(FUNCTION), \
DEFINE_FLAG(GESTURE), \
- DEFINE_FLAG(WAKE)
+ DEFINE_FLAG(WAKE), \
+ DEFINE_FLAG(FALLBACK_USAGE_MAPPING)
// clang-format on
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index ddc9ea4..3c1ae3e 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -250,7 +250,7 @@
std::vector<int32_t> KeyLayoutMap::findUsageCodesForKey(int32_t keyCode) const {
std::vector<int32_t> usageCodes;
for (const auto& [usageCode, key] : mKeysByUsageCode) {
- if (keyCode == key.keyCode) {
+ if (keyCode == key.keyCode && !(key.flags & POLICY_FLAG_FALLBACK_USAGE_MAPPING)) {
usageCodes.push_back(usageCode);
}
}
diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp
index a0ec6ad..fe5490c 100644
--- a/libs/input/tests/InputDevice_test.cpp
+++ b/libs/input/tests/InputDevice_test.cpp
@@ -167,6 +167,41 @@
ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath;
}
+TEST(InputDeviceKeyLayoutTest, HidUsageCodesFallbackMapping) {
+ std::string klPath = base::GetExecutableDirectory() + "/data/hid_fallback_mapping.kl";
+ base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
+ ASSERT_TRUE(ret.ok()) << "Unable to load KeyLayout at " << klPath;
+ const std::shared_ptr<KeyLayoutMap>& keyLayoutMap = *ret;
+
+ static constexpr std::array<int32_t, 5> hidUsageCodesWithoutFallback = {0x0c0067, 0x0c0070,
+ 0x0c006F, 0x0c0079,
+ 0x0c007A};
+ for (int32_t hidUsageCode : hidUsageCodesWithoutFallback) {
+ int32_t outKeyCode;
+ uint32_t outFlags;
+ keyLayoutMap->mapKey(0, hidUsageCode, &outKeyCode, &outFlags);
+ ASSERT_FALSE(outFlags & POLICY_FLAG_FALLBACK_USAGE_MAPPING)
+ << "HID usage code should not be marked as fallback";
+ std::vector<int32_t> usageCodes = keyLayoutMap->findUsageCodesForKey(outKeyCode);
+ ASSERT_NE(std::find(usageCodes.begin(), usageCodes.end(), hidUsageCode), usageCodes.end())
+ << "Fallback usage code should be mapped to key";
+ }
+
+ static constexpr std::array<int32_t, 6> hidUsageCodesWithFallback = {0x0c007C, 0x0c0173,
+ 0x0c019C, 0x0c01A2,
+ 0x0d0044, 0x0d005a};
+ for (int32_t hidUsageCode : hidUsageCodesWithFallback) {
+ int32_t outKeyCode;
+ uint32_t outFlags;
+ keyLayoutMap->mapKey(0, hidUsageCode, &outKeyCode, &outFlags);
+ ASSERT_TRUE(outFlags & POLICY_FLAG_FALLBACK_USAGE_MAPPING)
+ << "HID usage code should be marked as fallback";
+ std::vector<int32_t> usageCodes = keyLayoutMap->findUsageCodesForKey(outKeyCode);
+ ASSERT_EQ(std::find(usageCodes.begin(), usageCodes.end(), hidUsageCode), usageCodes.end())
+ << "Fallback usage code should not be mapped to key";
+ }
+}
+
TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) {
#if !defined(__ANDROID__)
GTEST_SKIP() << "Can't check kernel configs on host";
diff --git a/libs/input/tests/data/hid_fallback_mapping.kl b/libs/input/tests/data/hid_fallback_mapping.kl
new file mode 100644
index 0000000..b4ca9ef
--- /dev/null
+++ b/libs/input/tests/data/hid_fallback_mapping.kl
@@ -0,0 +1,32 @@
+# Copyright 2023 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.
+
+#
+# test key layout file for InputDeviceKeyMapTest#HidUsageCodesUseFallbackMapping
+#
+
+# Keys defined by HID usages without fallback mapping flag
+key usage 0x0c0067 WINDOW
+key usage 0x0c006F BRIGHTNESS_UP
+key usage 0x0c0070 BRIGHTNESS_DOWN
+key usage 0x0c0079 KEYBOARD_BACKLIGHT_UP
+key usage 0x0c007A KEYBOARD_BACKLIGHT_DOWN
+
+# Keys defined by HID usages with fallback mapping flag
+key usage 0x0c007C KEYBOARD_BACKLIGHT_TOGGLE FALLBACK_USAGE_MAPPING
+key usage 0x0c0173 MEDIA_AUDIO_TRACK FALLBACK_USAGE_MAPPING
+key usage 0x0c019C PROFILE_SWITCH FALLBACK_USAGE_MAPPING
+key usage 0x0c01A2 ALL_APPS FALLBACK_USAGE_MAPPING
+key usage 0x0d0044 STYLUS_BUTTON_PRIMARY FALLBACK_USAGE_MAPPING
+key usage 0x0d005a STYLUS_BUTTON_SECONDARY FALLBACK_USAGE_MAPPING
\ No newline at end of file
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index 475dc15..7289fe7 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -98,7 +98,6 @@
}
TEST_F(RenderEngineThreadedTest, PostRenderCleanup_skipped) {
- EXPECT_CALL(*mRenderEngine, canSkipPostRenderCleanup()).WillOnce(Return(true));
EXPECT_CALL(*mRenderEngine, cleanupPostRender()).Times(0);
mThreadedRE->cleanupPostRender();
@@ -107,8 +106,25 @@
}
TEST_F(RenderEngineThreadedTest, PostRenderCleanup_notSkipped) {
- EXPECT_CALL(*mRenderEngine, canSkipPostRenderCleanup()).WillOnce(Return(false));
+ renderengine::DisplaySettings settings;
+ std::vector<renderengine::LayerSettings> layers;
+ std::shared_ptr<renderengine::ExternalTexture> buffer = std::make_shared<
+ renderengine::impl::
+ ExternalTexture>(sp<GraphicBuffer>::make(), *mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
+ base::unique_fd bufferFence;
+
+ EXPECT_CALL(*mRenderEngine, useProtectedContext(false));
+ EXPECT_CALL(*mRenderEngine, drawLayersInternal)
+ .WillOnce([&](const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
+ const renderengine::DisplaySettings&,
+ const std::vector<renderengine::LayerSettings>&,
+ const std::shared_ptr<renderengine::ExternalTexture>&,
+ base::unique_fd&&) { resultPromise->set_value(Fence::NO_FENCE); });
EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return());
+ ftl::Future<FenceResult> future =
+ mThreadedRE->drawLayers(settings, layers, buffer, std::move(bufferFence));
mThreadedRE->cleanupPostRender();
// call ANY synchronous function to ensure that cleanupPostRender has completed.
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 2cb66cb..786a6fe 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -231,13 +231,13 @@
ATRACE_NAME("REThreaded::cleanupPostRender");
instance.cleanupPostRender();
});
+ mNeedsPostRenderCleanup = false;
}
mCondition.notify_one();
}
bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
- waitUntilInitialized();
- return mRenderEngine->canSkipPostRenderCleanup();
+ return !mNeedsPostRenderCleanup;
}
void RenderEngineThreaded::drawLayersInternal(
@@ -257,6 +257,7 @@
int fd = bufferFence.release();
{
std::lock_guard lock(mThreadMutex);
+ mNeedsPostRenderCleanup = true;
mFunctionCalls.push(
[resultPromise, display, layers, buffer, fd](renderengine::RenderEngine& instance) {
ATRACE_NAME("REThreaded::drawLayers");
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 43ec011..1093f5f 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -89,6 +89,7 @@
mutable std::mutex mThreadMutex;
std::thread mThread GUARDED_BY(mThreadMutex);
std::atomic<bool> mRunning = true;
+ std::atomic<bool> mNeedsPostRenderCleanup = false;
using Work = std::function<void(renderengine::RenderEngine&)>;
mutable std::queue<Work> mFunctionCalls GUARDED_BY(mThreadMutex);
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
index ed95de7..f304712 100644
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ b/services/inputflinger/dispatcher/Connection.cpp
@@ -38,13 +38,4 @@
return "?";
}
-std::deque<DispatchEntry*>::iterator Connection::findWaitQueueEntry(uint32_t seq) {
- for (std::deque<DispatchEntry*>::iterator it = waitQueue.begin(); it != waitQueue.end(); it++) {
- if ((*it)->seq == seq) {
- return it;
- }
- }
- return waitQueue.end();
-}
-
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
index 2929d61..c17baea 100644
--- a/services/inputflinger/dispatcher/Connection.h
+++ b/services/inputflinger/dispatcher/Connection.h
@@ -53,11 +53,11 @@
bool responsive = true;
// Queue of events that need to be published to the connection.
- std::deque<DispatchEntry*> outboundQueue;
+ std::deque<std::unique_ptr<DispatchEntry>> outboundQueue;
// Queue of events that have been published to the connection but that have not
// yet received a "finished" response from the application.
- std::deque<DispatchEntry*> waitQueue;
+ std::deque<std::unique_ptr<DispatchEntry>> waitQueue;
Connection(const std::shared_ptr<InputChannel>& inputChannel, bool monitor,
const IdGenerator& idGenerator);
@@ -65,8 +65,6 @@
inline const std::string getInputChannelName() const { return inputChannel->getName(); }
const std::string getWindowName() const;
-
- std::deque<DispatchEntry*>::iterator findWaitQueueEntry(uint32_t seq);
};
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index dd4aab8..98e2507 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -226,7 +226,7 @@
const uint32_t seq; // unique sequence number, never 0
std::shared_ptr<EventEntry> eventEntry; // the event to dispatch
- ftl::Flags<InputTarget::Flags> targetFlags;
+ const ftl::Flags<InputTarget::Flags> targetFlags;
ui::Transform transform;
ui::Transform rawTransform;
float globalScaleFactor;
@@ -244,6 +244,8 @@
DispatchEntry(std::shared_ptr<EventEntry> eventEntry,
ftl::Flags<InputTarget::Flags> targetFlags, const ui::Transform& transform,
const ui::Transform& rawTransform, float globalScaleFactor);
+ DispatchEntry(const DispatchEntry&) = delete;
+ DispatchEntry& operator=(const DispatchEntry&) = delete;
inline bool hasForegroundTarget() const {
return targetFlags.test(InputTarget::Flags::FOREGROUND);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 8e20eaf..4251682 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -271,7 +271,8 @@
return dump;
}
-std::string dumpQueue(const std::deque<DispatchEntry*>& queue, nsecs_t currentTime) {
+std::string dumpQueue(const std::deque<std::unique_ptr<DispatchEntry>>& queue,
+ nsecs_t currentTime) {
constexpr size_t maxEntries = 50; // max events to print
constexpr size_t skipBegin = maxEntries / 2;
const size_t skipEnd = queue.size() - maxEntries / 2;
@@ -492,8 +493,8 @@
*/
bool isConnectionResponsive(const Connection& connection) {
const nsecs_t currentTime = now();
- for (const DispatchEntry* entry : connection.waitQueue) {
- if (entry->timeoutTime < currentTime) {
+ for (const auto& dispatchEntry : connection.waitQueue) {
+ if (dispatchEntry->timeoutTime < currentTime) {
return false;
}
}
@@ -3415,7 +3416,7 @@
}
// Enqueue the dispatch entry.
- connection->outboundQueue.push_back(dispatchEntry.release());
+ connection->outboundQueue.emplace_back(std::move(dispatchEntry));
traceOutboundQueueLength(*connection);
}
@@ -3584,7 +3585,7 @@
}
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
- DispatchEntry* dispatchEntry = connection->outboundQueue.front();
+ std::unique_ptr<DispatchEntry>& dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection);
dispatchEntry->timeoutTime = currentTime + timeout.count();
@@ -3699,14 +3700,12 @@
}
// Re-enqueue the event on the wait queue.
- connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
- connection->outboundQueue.end(),
- dispatchEntry));
+ const nsecs_t timeoutTime = dispatchEntry->timeoutTime;
+ connection->waitQueue.emplace_back(std::move(dispatchEntry));
+ connection->outboundQueue.erase(connection->outboundQueue.begin());
traceOutboundQueueLength(*connection);
- connection->waitQueue.push_back(dispatchEntry);
if (connection->responsive) {
- mAnrTracker.insert(dispatchEntry->timeoutTime,
- connection->inputChannel->getConnectionToken());
+ mAnrTracker.insert(timeoutTime, connection->inputChannel->getConnectionToken());
}
traceWaitQueueLength(*connection);
}
@@ -3805,19 +3804,17 @@
}
}
-void InputDispatcher::drainDispatchQueue(std::deque<DispatchEntry*>& queue) {
+void InputDispatcher::drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>>& queue) {
while (!queue.empty()) {
- DispatchEntry* dispatchEntry = queue.front();
+ releaseDispatchEntry(std::move(queue.front()));
queue.pop_front();
- releaseDispatchEntry(dispatchEntry);
}
}
-void InputDispatcher::releaseDispatchEntry(DispatchEntry* dispatchEntry) {
+void InputDispatcher::releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry) {
if (dispatchEntry->hasForegroundTarget()) {
decrementPendingForegroundDispatches(*(dispatchEntry->eventEntry));
}
- delete dispatchEntry;
}
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
@@ -6065,43 +6062,52 @@
uint32_t seq, bool handled,
nsecs_t consumeTime) {
// Handle post-event policy actions.
- std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq);
- if (dispatchEntryIt == connection->waitQueue.end()) {
- return;
- }
- DispatchEntry* dispatchEntry = *dispatchEntryIt;
- const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
- if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
- ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(),
- ns2ms(eventDuration), dispatchEntry->eventEntry->getDescription().c_str());
- }
- if (shouldReportFinishedEvent(*dispatchEntry, *connection)) {
- mLatencyTracker.trackFinishedEvent(dispatchEntry->eventEntry->id,
- connection->inputChannel->getConnectionToken(),
- dispatchEntry->deliveryTime, consumeTime, finishTime);
- }
-
bool restartEvent;
- if (dispatchEntry->eventEntry->type == EventEntry::Type::KEY) {
- KeyEntry& keyEntry = static_cast<KeyEntry&>(*(dispatchEntry->eventEntry));
- restartEvent =
- afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled);
- } else if (dispatchEntry->eventEntry->type == EventEntry::Type::MOTION) {
- MotionEntry& motionEntry = static_cast<MotionEntry&>(*(dispatchEntry->eventEntry));
- restartEvent = afterMotionEventLockedInterruptable(connection, dispatchEntry, motionEntry,
- handled);
- } else {
- restartEvent = false;
- }
+
+ { // Start critical section
+ auto dispatchEntryIt =
+ std::find_if(connection->waitQueue.begin(), connection->waitQueue.end(),
+ [seq](auto& e) { return e->seq == seq; });
+ if (dispatchEntryIt == connection->waitQueue.end()) {
+ return;
+ }
+
+ DispatchEntry& dispatchEntry = **dispatchEntryIt;
+
+ const nsecs_t eventDuration = finishTime - dispatchEntry.deliveryTime;
+ if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
+ ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(),
+ ns2ms(eventDuration), dispatchEntry.eventEntry->getDescription().c_str());
+ }
+ if (shouldReportFinishedEvent(dispatchEntry, *connection)) {
+ mLatencyTracker.trackFinishedEvent(dispatchEntry.eventEntry->id,
+ connection->inputChannel->getConnectionToken(),
+ dispatchEntry.deliveryTime, consumeTime, finishTime);
+ }
+
+ if (dispatchEntry.eventEntry->type == EventEntry::Type::KEY) {
+ KeyEntry& keyEntry = static_cast<KeyEntry&>(*(dispatchEntry.eventEntry));
+ restartEvent =
+ afterKeyEventLockedInterruptable(connection, dispatchEntry, keyEntry, handled);
+ } else if (dispatchEntry.eventEntry->type == EventEntry::Type::MOTION) {
+ MotionEntry& motionEntry = static_cast<MotionEntry&>(*(dispatchEntry.eventEntry));
+ restartEvent = afterMotionEventLockedInterruptable(connection, dispatchEntry,
+ motionEntry, handled);
+ } else {
+ restartEvent = false;
+ }
+ } // End critical section: The -LockedInterruptable methods may have released the lock.
// Dequeue the event and start the next cycle.
// Because the lock might have been released, it is possible that the
// contents of the wait queue to have been drained, so we need to double-check
// a few things.
- dispatchEntryIt = connection->findWaitQueueEntry(seq);
- if (dispatchEntryIt != connection->waitQueue.end()) {
- dispatchEntry = *dispatchEntryIt;
- connection->waitQueue.erase(dispatchEntryIt);
+ auto entryIt = std::find_if(connection->waitQueue.begin(), connection->waitQueue.end(),
+ [seq](auto& e) { return e->seq == seq; });
+ if (entryIt != connection->waitQueue.end()) {
+ std::unique_ptr<DispatchEntry> dispatchEntry = std::move(*entryIt);
+ connection->waitQueue.erase(entryIt);
+
const sp<IBinder>& connectionToken = connection->inputChannel->getConnectionToken();
mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken);
if (!connection->responsive) {
@@ -6113,10 +6119,10 @@
}
traceWaitQueueLength(*connection);
if (restartEvent && connection->status == Connection::Status::NORMAL) {
- connection->outboundQueue.push_front(dispatchEntry);
+ connection->outboundQueue.emplace_front(std::move(dispatchEntry));
traceOutboundQueueLength(*connection);
} else {
- releaseDispatchEntry(dispatchEntry);
+ releaseDispatchEntry(std::move(dispatchEntry));
}
}
@@ -6160,13 +6166,13 @@
* processes the events linearly. So providing information about the oldest entry seems to be
* most useful.
*/
- DispatchEntry* oldestEntry = *connection->waitQueue.begin();
- const nsecs_t currentWait = now() - oldestEntry->deliveryTime;
+ DispatchEntry& oldestEntry = *connection->waitQueue.front();
+ const nsecs_t currentWait = now() - oldestEntry.deliveryTime;
std::string reason =
android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s",
connection->inputChannel->getName().c_str(),
ns2ms(currentWait),
- oldestEntry->eventEntry->getDescription().c_str());
+ oldestEntry.eventEntry->getDescription().c_str());
sp<IBinder> connectionToken = connection->inputChannel->getConnectionToken();
updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
@@ -6303,7 +6309,7 @@
}
bool InputDispatcher::afterKeyEventLockedInterruptable(
- const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
+ const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
KeyEntry& keyEntry, bool handled) {
if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) {
if (!handled) {
@@ -6321,7 +6327,7 @@
connection->inputState.removeFallbackKey(originalKeyCode);
}
- if (handled || !dispatchEntry->hasForegroundTarget()) {
+ if (handled || !dispatchEntry.hasForegroundTarget()) {
// If the application handles the original key for which we previously
// generated a fallback or if the window is not a foreground window,
// then cancel the associated fallback key, if any.
@@ -6488,7 +6494,7 @@
}
bool InputDispatcher::afterMotionEventLockedInterruptable(
- const std::shared_ptr<Connection>& connection, DispatchEntry* dispatchEntry,
+ const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
MotionEntry& motionEntry, bool handled) {
return false;
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 67705b9..62e2d58 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -598,8 +598,8 @@
void abortBrokenDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection, bool notify)
REQUIRES(mLock);
- void drainDispatchQueue(std::deque<DispatchEntry*>& queue);
- void releaseDispatchEntry(DispatchEntry* dispatchEntry);
+ void drainDispatchQueue(std::deque<std::unique_ptr<DispatchEntry>>& queue);
+ void releaseDispatchEntry(std::unique_ptr<DispatchEntry> dispatchEntry);
int handleReceiveCallback(int events, sp<IBinder> connectionToken);
// The action sent should only be of type AMOTION_EVENT_*
void dispatchPointerDownOutsideFocus(uint32_t source, int32_t action,
@@ -664,10 +664,10 @@
REQUIRES(mLock);
std::map<int32_t /*displayId*/, InputVerifier> mVerifiersByDisplay;
bool afterKeyEventLockedInterruptable(const std::shared_ptr<Connection>& connection,
- DispatchEntry* dispatchEntry, KeyEntry& keyEntry,
+ DispatchEntry& dispatchEntry, KeyEntry& keyEntry,
bool handled) REQUIRES(mLock);
bool afterMotionEventLockedInterruptable(const std::shared_ptr<Connection>& connection,
- DispatchEntry* dispatchEntry, MotionEntry& motionEntry,
+ DispatchEntry& dispatchEntry, MotionEntry& motionEntry,
bool handled) REQUIRES(mLock);
// Find touched state and touched window by token.
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index d059f8f..c073579 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -74,6 +74,7 @@
filename_(filename),
dlhandle_(nullptr),
native_bridge_(false),
+ opened_with_native_loader_(false),
refcount_(0) {}
LayerLibrary(LayerLibrary&& other) noexcept
@@ -81,6 +82,7 @@
filename_(std::move(other.filename_)),
dlhandle_(other.dlhandle_),
native_bridge_(other.native_bridge_),
+ opened_with_native_loader_(other.opened_with_native_loader_),
refcount_(other.refcount_) {
other.dlhandle_ = nullptr;
other.refcount_ = 0;
@@ -120,6 +122,7 @@
std::mutex mutex_;
void* dlhandle_;
bool native_bridge_;
+ bool opened_with_native_loader_;
size_t refcount_;
};
@@ -136,7 +139,7 @@
if (app_namespace &&
!android::base::StartsWith(path_, kSystemLayerLibraryDir)) {
char* error_msg = nullptr;
- dlhandle_ = OpenNativeLibraryInNamespace(
+ dlhandle_ = android::OpenNativeLibraryInNamespace(
app_namespace, path_.c_str(), &native_bridge_, &error_msg);
if (!dlhandle_) {
ALOGE("failed to load layer library '%s': %s", path_.c_str(), error_msg);
@@ -144,14 +147,16 @@
refcount_ = 0;
return false;
}
+ opened_with_native_loader_ = true;
} else {
- dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+ dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
if (!dlhandle_) {
ALOGE("failed to load layer library '%s': %s", path_.c_str(),
dlerror());
refcount_ = 0;
return false;
}
+ opened_with_native_loader_ = false;
}
}
return true;
@@ -161,14 +166,25 @@
std::lock_guard<std::mutex> lock(mutex_);
if (--refcount_ == 0) {
ALOGV("closing layer library '%s'", path_.c_str());
- char* error_msg = nullptr;
- if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
- ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg);
- android::NativeLoaderFreeErrorMessage(error_msg);
- refcount_++;
+ // we close the .so same way as we opened. It's importain, because
+ // android::CloseNativeLibrary lives in libnativeloader.so, which is
+ // not accessible for early loaded services like SurfaceFlinger
+ if (opened_with_native_loader_) {
+ char* error_msg = nullptr;
+ if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
+ ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg);
+ android::NativeLoaderFreeErrorMessage(error_msg);
+ refcount_++;
+ return;
+ }
} else {
- dlhandle_ = nullptr;
+ if (dlclose(dlhandle_) != 0) {
+ ALOGE("failed to unload library '%s': %s", path_.c_str(), dlerror());
+ refcount_++;
+ return;
+ }
}
+ dlhandle_ = nullptr;
}
}