From be9f42d83645781b78f9448475156ad44bec23a8 Mon Sep 17 00:00:00 2001 From: Michael Hoogasian Date: Sat, 21 Mar 2020 12:14:22 -0400 Subject: [PATCH] Prevent HandlerThread from losing interrupted flag I spent forever trying to figure out why one of my threads was losing its interrupted flag, and eventually chased the problem to this. This change keeps the behavior of blocking until the looper is intialized (i.e, any InterruptedExceptions are still eaten), BUT it will restore the thread's interrupted flag before returning, if needed. Test: calling getLooper() from a thread with the interrupted flag set, then verifying that the interrupted flag was still set after the call returned. Change-Id: If1b1a0812fa672c02510b70faf4d813b82ae8589 Signed-off-by: Michael Hoogasian --- core/java/android/os/HandlerThread.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java index 92fcbb65b1064..4dd797a70fcb3 100644 --- a/core/java/android/os/HandlerThread.java +++ b/core/java/android/os/HandlerThread.java @@ -71,23 +71,35 @@ public class HandlerThread extends Thread { /** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason isAlive() returns false, this method will return null. If this thread - * has been started, this method will block until the looper has been initialized. + * has been started, this method will block until the looper has been initialized. * @return The looper. */ public Looper getLooper() { if (!isAlive()) { return null; } - + + boolean wasInterrupted = false; + // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { + wasInterrupted = true; } } } + + /* + * We may need to restore the thread's interrupted flag, because it may + * have been cleared above since we eat InterruptedExceptions + */ + if (wasInterrupted) { + Thread.currentThread().interrupt(); + } + return mLooper; }