Add more utitlities to ThreadFactory.

Add the ability to create Handlers in TheadFactory, as well
as the ability to create Executors from Handlers.

Use these in ScreenDecorations. Also, use the executor rather than
then handler in ScreenDecorations where possible.

Bug: 177323724
Test: atest SystemUITests
Change-Id: Icaedbfe3dc89f5bbc00c780533cb46279c2d2088
This commit is contained in:
Dave Mankoff
2021-05-07 15:39:00 -04:00
parent 4b419f08d5
commit 047161d25c
5 changed files with 72 additions and 39 deletions

View File

@@ -55,8 +55,6 @@ import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Secure;
@@ -91,11 +89,13 @@ import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.ThreadFactory;
import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -122,7 +122,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@VisibleForTesting
protected boolean mIsRegistered;
private final BroadcastDispatcher mBroadcastDispatcher;
private final Handler mMainHandler;
private final Executor mMainExecutor;
private final TunerService mTunerService;
private final SecureSettings mSecureSettings;
private DisplayManager.DisplayListener mDisplayListener;
@@ -153,6 +153,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private WindowManager mWindowManager;
private int mRotation;
private SecureSetting mColorInversionSetting;
private DelayableExecutor mExecutor;
private Handler mHandler;
private boolean mPendingRotationChange;
private boolean mIsRoundedCornerMultipleRadius;
@@ -212,7 +213,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Inject
public ScreenDecorations(Context context,
@Main Handler handler,
@Main Executor mainExecutor,
SecureSettings secureSettings,
BroadcastDispatcher broadcastDispatcher,
TunerService tunerService,
@@ -220,7 +221,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
PrivacyDotViewController dotViewController,
ThreadFactory threadFactory) {
super(context);
mMainHandler = handler;
mMainExecutor = mainExecutor;
mSecureSettings = secureSettings;
mBroadcastDispatcher = broadcastDispatcher;
mTunerService = tunerService;
@@ -235,17 +236,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
Log.i(TAG, "ScreenDecorations is disabled");
return;
}
mHandler = startHandlerThread();
mHandler.post(this::startOnScreenDecorationsThread);
mDotViewController.setUiExecutor(
mThreadFactory.buildDelayableExecutorOnLooper(mHandler.getLooper()));
}
@VisibleForTesting
Handler startHandlerThread() {
HandlerThread thread = new HandlerThread("ScreenDecorations");
thread.start();
return thread.getThreadHandler();
mHandler = mThreadFactory.builderHandlerOnNewThread("ScreenDecorations");
mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler);
mExecutor.execute(this::startOnScreenDecorationsThread);
mDotViewController.setUiExecutor(mExecutor);
}
private void startOnScreenDecorationsThread() {
@@ -332,7 +326,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
mDisplayManager.getDisplay(DEFAULT_DISPLAY).getMetrics(metrics);
mDensity = metrics.density;
mMainHandler.post(() -> mTunerService.addTunable(this, SIZE));
mExecutor.execute(() -> mTunerService.addTunable(this, SIZE));
// Watch color inversion and invert the overlay as needed.
if (mColorInversionSetting == null) {
@@ -351,10 +345,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
mBroadcastDispatcher.registerReceiver(mUserSwitchIntentReceiver, filter,
new HandlerExecutor(mHandler), UserHandle.ALL);
mExecutor, UserHandle.ALL);
mIsRegistered = true;
} else {
mMainHandler.post(() -> mTunerService.removeTunable(this));
mMainExecutor.execute(() -> mTunerService.removeTunable(this));
if (mColorInversionSetting != null) {
mColorInversionSetting.setListening(false);
@@ -567,7 +561,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
Resources res = mContext.getResources();
boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
if (enabled) {
mCameraListener = CameraAvailabilityListener.Factory.build(mContext, mHandler::post);
mCameraListener = CameraAvailabilityListener.Factory.build(mContext, mExecutor);
mCameraListener.addTransitionCallback(mCameraTransitionCallback);
mCameraListener.startListening();
}
@@ -624,7 +618,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
Log.i(TAG, "ScreenDecorations is disabled");
return;
}
mHandler.post(() -> {
mExecutor.execute(() -> {
int oldRotation = mRotation;
mPendingRotationChange = false;
updateOrientation();
@@ -825,7 +819,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
Log.i(TAG, "ScreenDecorations is disabled");
return;
}
mHandler.post(() -> {
mExecutor.execute(() -> {
if (mOverlays == null) return;
if (SIZE.equals(key)) {
Point size = mRoundedDefault;

View File

@@ -16,6 +16,7 @@
package com.android.systemui.util.concurrency;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
@@ -28,6 +29,14 @@ import java.util.concurrent.Executor;
* threads; there are no singletons here. Use responsibly.
*/
public interface ThreadFactory {
/**
* Returns a {@link Handler} running on a named thread.
*
* The thread is implicitly started and may be left running indefinitely, depending on the
* implementation. Assume this is the case and use responsibly.
*/
Handler builderHandlerOnNewThread(String threadName);
/**
* Return an {@link java.util.concurrent.Executor} running on a named thread.
*
@@ -44,6 +53,11 @@ public interface ThreadFactory {
**/
DelayableExecutor buildDelayableExecutorOnNewThread(String threadName);
/**
* Return an {@link DelayableExecutor} running on the given HandlerThread.
**/
DelayableExecutor buildDelayableExecutorOnHandler(Handler handler);
/**
* Return an {@link DelayableExecutor} running the given Looper
**/

View File

@@ -16,6 +16,7 @@
package com.android.systemui.util.concurrency;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -27,16 +28,31 @@ class ThreadFactoryImpl implements ThreadFactory {
@Inject
ThreadFactoryImpl() {}
@Override
public Handler builderHandlerOnNewThread(String threadName) {
HandlerThread handlerThread = new HandlerThread(threadName);
handlerThread.start();
return new Handler(handlerThread.getLooper());
}
@Override
public Executor buildExecutorOnNewThread(String threadName) {
return buildDelayableExecutorOnNewThread(threadName);
}
@Override
public DelayableExecutor buildDelayableExecutorOnNewThread(String threadName) {
HandlerThread handlerThread = new HandlerThread(threadName);
handlerThread.start();
return new ExecutorImpl(handlerThread.getLooper());
return buildDelayableExecutorOnLooper(handlerThread.getLooper());
}
@Override
public DelayableExecutor buildDelayableExecutorOnHandler(Handler handler) {
return buildDelayableExecutorOnLooper(handler.getLooper());
}
@Override
public DelayableExecutor buildDelayableExecutorOnLooper(Looper looper) {
return new ExecutorImpl(looper);
}

View File

@@ -67,7 +67,6 @@ import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.concurrency.FakeThreadFactory;
import com.android.systemui.util.concurrency.ThreadFactory;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
import com.android.systemui.util.time.FakeSystemClock;
@@ -87,13 +86,12 @@ public class ScreenDecorationsTest extends SysuiTestCase {
private static final Rect ZERO_RECT = new Rect();
private TestableLooper mTestableLooper;
private ScreenDecorations mScreenDecorations;
private WindowManager mWindowManager;
private DisplayManager mDisplayManager;
private SecureSettings mSecureSettings;
private Handler mMainHandler;
private ThreadFactory mThreadFactory;
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
private FakeThreadFactory mThreadFactory;
@Mock
private TunerService mTunerService;
@Mock
@@ -107,10 +105,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void setup() {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
mMainHandler = new Handler(mTestableLooper.getLooper());
Handler mainHandler = new Handler(TestableLooper.get(this).getLooper());
mSecureSettings = new FakeSettings();
mThreadFactory = new FakeThreadFactory(new FakeExecutor(new FakeSystemClock()));
mThreadFactory = new FakeThreadFactory(mExecutor);
mThreadFactory.setHandler(mainHandler);
mWindowManager = mock(WindowManager.class);
WindowMetrics metrics = mContext.getSystemService(WindowManager.class)
@@ -124,30 +122,25 @@ public class ScreenDecorationsTest extends SysuiTestCase {
when(mDisplayManager.getDisplay(anyInt())).thenReturn(display);
mContext.addMockSystemService(DisplayManager.class, mDisplayManager);
mScreenDecorations = spy(new ScreenDecorations(mContext, mMainHandler, mSecureSettings,
mScreenDecorations = spy(new ScreenDecorations(mContext, mExecutor, mSecureSettings,
mBroadcastDispatcher, mTunerService, mUserTracker, mDotViewController,
mThreadFactory) {
@Override
public void start() {
super.start();
mTestableLooper.processAllMessages();
}
@Override
Handler startHandlerThread() {
return new Handler(mTestableLooper.getLooper());
mExecutor.runAllReady();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mTestableLooper.processAllMessages();
mExecutor.runAllReady();
}
@Override
public void onTuningChanged(String key, String newValue) {
super.onTuningChanged(key, newValue);
mTestableLooper.processAllMessages();
mExecutor.runAllReady();
}
});
reset(mTunerService);

View File

@@ -16,6 +16,7 @@
package com.android.systemui.util.concurrency;
import android.os.Handler;
import android.os.Looper;
import java.util.concurrent.Executor;
@@ -25,11 +26,21 @@ import java.util.concurrent.Executor;
*/
public class FakeThreadFactory implements ThreadFactory {
private final FakeExecutor mFakeExecutor;
private Handler mHandler;
public FakeThreadFactory(FakeExecutor fakeExecutor) {
mFakeExecutor = fakeExecutor;
}
public void setHandler(Handler handler) {
mHandler = handler;
}
@Override
public Handler builderHandlerOnNewThread(String threadName) {
return mHandler;
}
@Override
public Executor buildExecutorOnNewThread(String threadName) {
return mFakeExecutor;
@@ -40,6 +51,11 @@ public class FakeThreadFactory implements ThreadFactory {
return mFakeExecutor;
}
@Override
public DelayableExecutor buildDelayableExecutorOnHandler(Handler handler) {
return mFakeExecutor;
}
@Override
public DelayableExecutor buildDelayableExecutorOnLooper(Looper looper) {
return mFakeExecutor;