Loading cmds/installd/InstalldNativeService.cpp +23 −8 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ #include <fstream> #include <functional> #include <regex> #include <thread> #include <unordered_set> #include <android-base/file.h> Loading Loading @@ -555,12 +556,14 @@ static int restorecon_app_data_lazy(const std::string& path, const std::string& // If the initial top-level restorecon above changed the label, then go // back and restorecon everything recursively if (inProgress || before != after) { ScopedTrace tracer("label-change"); if (existing) { LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path << "; running recursive restorecon"; } auto restorecon = [path, seInfo, uid]() { ScopedTrace tracer("label-change"); // Temporary mark the folder as "in-progress" to resume in case of reboot/other failure. RestoreconInProgress fence(path); Loading @@ -569,6 +572,18 @@ static int restorecon_app_data_lazy(const std::string& path, const std::string& PLOG(ERROR) << "Failed recursive restorecon for " << path; return -1; } return 0; }; if (inProgress) { // The previous restorecon was interrupted. It's either crashed (unlikely), or the phone // was rebooted. Possibly because it took too much time. This time let's move it to a // separate thread - so it won't block the rest of the OS. std::thread(restorecon).detach(); } else { if (int result = restorecon(); result) { return result; } } } return 0; Loading cmds/lshal/Timeout.h +7 −3 Original line number Diff line number Diff line Loading @@ -72,10 +72,14 @@ bool timeout(std::chrono::duration<R, P> delay, std::function<void(void)> &&func return false; } bool success = state.wait(now + delay); if (!success) { pthread_kill(thread, SIGINT); } if (success) { pthread_join(thread, nullptr); } else { // b/311143089: Abandon this background thread. Resources for a detached // thread are cleaned up when it is terminated. If the background thread // is stalled, it will be terminated when returning from main(). pthread_detach(thread); } return success; } Loading cmds/lshal/main.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -18,5 +18,6 @@ int main(int argc, char **argv) { using namespace ::android::lshal; // Background pthreads from timeout() are destroyed upon returning from main(). return Lshal{}.main(Arg{argc, argv}); } services/inputflinger/dispatcher/InputDispatcher.cpp +10 −1 Original line number Diff line number Diff line Loading @@ -1090,8 +1090,17 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) { // The event is stale. However, only drop stale events if there isn't an ongoing // gesture. That would allow us to complete the processing of the current stroke. const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId); if (touchStateIt != mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; if (!touchState.hasTouchingPointers(motionEntry->deviceId) && !touchState.hasHoveringPointers(motionEntry->deviceId)) { dropReason = DropReason::STALE; } } } if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) { dropReason = DropReason::BLOCKED; } Loading services/inputflinger/tests/InputDispatcher_test.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -3412,6 +3412,44 @@ TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) { window->assertNoEvents(); } /** * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be * rejected. But since we already have an ongoing gesture, this event should be processed. * This prevents inconsistent events being handled inside the dispatcher. */ TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 200, 200)); mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); // Start hovering with stylus mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) .build()); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) .build(); // Make this 'hoverExit' event stale mFakePolicy->setStaleEventTimeout(100ms); std::this_thread::sleep_for(100ms); // It shouldn't be dropped by the dispatcher, even though it's stale. mDispatcher->notifyMotion(hoverExit); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); // Stylus starts hovering again! There should be no crash. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51)) .build()); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); } /** * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream. * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse Loading Loading
cmds/installd/InstalldNativeService.cpp +23 −8 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ #include <fstream> #include <functional> #include <regex> #include <thread> #include <unordered_set> #include <android-base/file.h> Loading Loading @@ -555,12 +556,14 @@ static int restorecon_app_data_lazy(const std::string& path, const std::string& // If the initial top-level restorecon above changed the label, then go // back and restorecon everything recursively if (inProgress || before != after) { ScopedTrace tracer("label-change"); if (existing) { LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path << "; running recursive restorecon"; } auto restorecon = [path, seInfo, uid]() { ScopedTrace tracer("label-change"); // Temporary mark the folder as "in-progress" to resume in case of reboot/other failure. RestoreconInProgress fence(path); Loading @@ -569,6 +572,18 @@ static int restorecon_app_data_lazy(const std::string& path, const std::string& PLOG(ERROR) << "Failed recursive restorecon for " << path; return -1; } return 0; }; if (inProgress) { // The previous restorecon was interrupted. It's either crashed (unlikely), or the phone // was rebooted. Possibly because it took too much time. This time let's move it to a // separate thread - so it won't block the rest of the OS. std::thread(restorecon).detach(); } else { if (int result = restorecon(); result) { return result; } } } return 0; Loading
cmds/lshal/Timeout.h +7 −3 Original line number Diff line number Diff line Loading @@ -72,10 +72,14 @@ bool timeout(std::chrono::duration<R, P> delay, std::function<void(void)> &&func return false; } bool success = state.wait(now + delay); if (!success) { pthread_kill(thread, SIGINT); } if (success) { pthread_join(thread, nullptr); } else { // b/311143089: Abandon this background thread. Resources for a detached // thread are cleaned up when it is terminated. If the background thread // is stalled, it will be terminated when returning from main(). pthread_detach(thread); } return success; } Loading
cmds/lshal/main.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -18,5 +18,6 @@ int main(int argc, char **argv) { using namespace ::android::lshal; // Background pthreads from timeout() are destroyed upon returning from main(). return Lshal{}.main(Arg{argc, argv}); }
services/inputflinger/dispatcher/InputDispatcher.cpp +10 −1 Original line number Diff line number Diff line Loading @@ -1090,8 +1090,17 @@ void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) { } } if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) { // The event is stale. However, only drop stale events if there isn't an ongoing // gesture. That would allow us to complete the processing of the current stroke. const auto touchStateIt = mTouchStatesByDisplay.find(motionEntry->displayId); if (touchStateIt != mTouchStatesByDisplay.end()) { const TouchState& touchState = touchStateIt->second; if (!touchState.hasTouchingPointers(motionEntry->deviceId) && !touchState.hasHoveringPointers(motionEntry->deviceId)) { dropReason = DropReason::STALE; } } } if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) { dropReason = DropReason::BLOCKED; } Loading
services/inputflinger/tests/InputDispatcher_test.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -3412,6 +3412,44 @@ TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) { window->assertNoEvents(); } /** * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be * rejected. But since we already have an ongoing gesture, this event should be processed. * This prevents inconsistent events being handled inside the dispatcher. */ TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 200, 200)); mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0}); // Start hovering with stylus mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) .build()); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS) .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50)) .build(); // Make this 'hoverExit' event stale mFakePolicy->setStaleEventTimeout(100ms); std::this_thread::sleep_for(100ms); // It shouldn't be dropped by the dispatcher, even though it's stale. mDispatcher->notifyMotion(hoverExit); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT)); // Stylus starts hovering again! There should be no crash. mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS) .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51)) .build()); window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)); } /** * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream. * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse Loading