diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java index 7cdba8607d860..cc6d607a60cf7 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java @@ -83,17 +83,19 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor by default. */ @Provides + @Singleton public static Executor provideExecutor(@Background Looper looper) { - return new ExecutorImpl(new Handler(looper)); + return new ExecutorImpl(looper); } /** * Provide a Background-Thread Executor. */ @Provides + @Singleton @Background public static Executor provideBackgroundExecutor(@Background Looper looper) { - return new ExecutorImpl(new Handler(looper)); + return new ExecutorImpl(looper); } /** @@ -109,26 +111,29 @@ public abstract class ConcurrencyModule { * Provide a Background-Thread Executor by default. */ @Provides + @Singleton public static DelayableExecutor provideDelayableExecutor(@Background Looper looper) { - return new ExecutorImpl(new Handler(looper)); + return new ExecutorImpl(looper); } /** * Provide a Background-Thread Executor. */ @Provides + @Singleton @Background public static DelayableExecutor provideBackgroundDelayableExecutor(@Background Looper looper) { - return new ExecutorImpl(new Handler(looper)); + return new ExecutorImpl(looper); } /** * Provide a Main-Thread Executor. */ @Provides + @Singleton @Main public static DelayableExecutor provideMainDelayableExecutor(@Main Looper looper) { - return new ExecutorImpl(new Handler(looper)); + return new ExecutorImpl(looper); } /** diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java index 7e7732135e3a9..2bbf9507122a5 100644 --- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ExecutorImpl.java @@ -17,37 +17,69 @@ package com.android.systemui.util.concurrency; import android.os.Handler; -import android.os.HandlerExecutor; +import android.os.Looper; import android.os.Message; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; /** * Implementations of {@link DelayableExecutor} for SystemUI. */ -public class ExecutorImpl extends HandlerExecutor implements DelayableExecutor { +public class ExecutorImpl implements DelayableExecutor { private final Handler mHandler; - public ExecutorImpl(Handler handler) { - super(handler); - mHandler = handler; + ExecutorImpl(Looper looper) { + mHandler = new Handler(looper, this::onHandleMessage); + } + + @Override + public void execute(Runnable command) { + if (!mHandler.post(command)) { + throw new RejectedExecutionException(mHandler + " is shutting down"); + } } @Override public Runnable executeDelayed(Runnable r, long delay, TimeUnit unit) { - Object token = new Object(); - Message m = mHandler.obtainMessage(0, token); + ExecutionToken token = new ExecutionToken(r); + Message m = mHandler.obtainMessage(MSG_EXECUTE_RUNNABLE, token); mHandler.sendMessageDelayed(m, unit.toMillis(delay)); - return () -> mHandler.removeCallbacksAndMessages(token); + return token; } @Override public Runnable executeAtTime(Runnable r, long uptimeMillis, TimeUnit unit) { - Object token = new Object(); - Message m = mHandler.obtainMessage(0, token); + ExecutionToken token = new ExecutionToken(r); + Message m = mHandler.obtainMessage(MSG_EXECUTE_RUNNABLE, token); mHandler.sendMessageAtTime(m, unit.toMillis(uptimeMillis)); - return () -> mHandler.removeCallbacksAndMessages(token); + return token; } + + private boolean onHandleMessage(Message msg) { + if (msg.what == MSG_EXECUTE_RUNNABLE) { + ExecutionToken token = (ExecutionToken) msg.obj; + token.runnable.run(); + } else { + throw new IllegalStateException("Unrecognized message: " + msg.what); + } + return true; + } + + private class ExecutionToken implements Runnable { + public final Runnable runnable; + + private ExecutionToken(Runnable runnable) { + this.runnable = runnable; + } + + @Override + public void run() { + mHandler.removeCallbacksAndMessages(this); + } + } + + private static final int MSG_EXECUTE_RUNNABLE = 0; }