Merge "Implement message handling in ExecutorImpl"

This commit is contained in:
TreeHugger Robot
2020-01-10 21:29:30 +00:00
committed by Android (Google) Code Review
2 changed files with 53 additions and 16 deletions

View File

@@ -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);
}
/**

View File

@@ -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;
}