Moving various common executors to a single location

Change-Id: I44bca49b8adb6fa22c3b48d10f674e42c28d792c
This commit is contained in:
Sunny Goyal 2019-08-15 14:53:41 -07:00
parent 4fa6f63ffd
commit 6fe3eec95c
59 changed files with 434 additions and 441 deletions

View File

@ -15,8 +15,8 @@
*/
package com.android.quickstep;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi;
import android.content.Context;
@ -25,7 +25,6 @@ import android.os.SystemClock;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
@ -43,7 +42,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@ -51,7 +49,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@ -63,19 +60,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
mMainThreadExecutor.execute(new ShowRecentsCommand());
MAIN_EXECUTOR.execute(new ShowRecentsCommand());
}
public void onOverviewHidden() {
mMainThreadExecutor.execute(new HideRecentsCommand());
MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
mMainThreadExecutor.execute(() ->
MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@ -161,7 +158,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(provider::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
provider, mContext, mMainThreadExecutor.getHandler(),
provider, mContext, MAIN_EXECUTOR.getHandler(),
provider.getRecentsLaunchDuration());
}

View File

@ -34,8 +34,6 @@ import android.view.MotionEvent;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@ -139,9 +137,6 @@ public class TouchInteractionService extends Service {
return sConnected;
}
public static final LooperExecutor BACKGROUND_EXECUTOR =
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
private RecentsModel mRecentsModel;
private OverviewComponentObserver mOverviewComponentObserver;
private OverviewCommandHelper mOverviewCommandHelper;

View File

@ -17,6 +17,8 @@ package com.android.launcher3.appprediction;
import static android.content.pm.PackageManager.MATCH_INSTANT;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@ -30,8 +32,12 @@ import android.os.Message;
import android.util.ArrayMap;
import android.util.Log;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
@ -45,11 +51,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
/**
* Utility class which loads and caches predicted items like instant apps and shortcuts, before
* they can be displayed on the UI
@ -77,7 +78,7 @@ public class DynamicItemCache {
public DynamicItemCache(Context context, Runnable onUpdateCallback) {
mContext = context;
mWorker = new Handler(LauncherModel.getWorkerLooper(), this::handleWorkerMessage);
mWorker = new Handler(MODEL_EXECUTOR.getLooper(), this::handleWorkerMessage);
mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
mInstantAppResolver = InstantAppResolver.newInstance(context);
mOnUpdateCallback = onUpdateCallback;

View File

@ -15,6 +15,9 @@
*/
package com.android.launcher3.appprediction;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
@ -38,9 +41,6 @@ import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.util.UiThreadHelper;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
/**
* Subclass of app tracker which publishes the data to the prediction engine and gets back results.
@ -65,7 +65,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
public PredictionAppTracker(Context context) {
mContext = context;
mMessageHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleMessage);
mMessageHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessage);
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
mMessageHandler.sendEmptyMessage(MSG_INIT);

View File

@ -22,9 +22,9 @@ import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import android.animation.Animator;
@ -47,6 +47,8 @@ import android.view.View;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import androidx.annotation.UiThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
@ -54,7 +56,6 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
@ -75,8 +76,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
/**
* Base class for swipe up handler with some utility methods
*/
@ -126,7 +125,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
protected Runnable mGestureEndCallback;
protected final Handler mMainThreadHandler = MAIN_THREAD_EXECUTOR.getHandler();
protected final Handler mMainThreadHandler = MAIN_EXECUTOR.getHandler();
protected MultiStateCallback mStateCallback;
protected boolean mCanceled;
@ -174,7 +173,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
if (effect == null) {
return;
}
BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
UI_HELPER_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
}
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {

View File

@ -15,8 +15,8 @@
*/
package com.android.quickstep;
import static com.android.systemui.shared.system.ActivityManagerWrapper
.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -28,7 +28,6 @@ import android.os.SystemClock;
import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
@ -47,7 +46,6 @@ public class OverviewCommandHelper {
private final Context mContext;
private final ActivityManagerWrapper mAM;
private final RecentsModel mRecentsModel;
private final MainThreadExecutor mMainThreadExecutor;
private final OverviewComponentObserver mOverviewComponentObserver;
private long mLastToggleTime;
@ -55,7 +53,6 @@ public class OverviewCommandHelper {
public OverviewCommandHelper(Context context, OverviewComponentObserver observer) {
mContext = context;
mAM = ActivityManagerWrapper.getInstance();
mMainThreadExecutor = new MainThreadExecutor();
mRecentsModel = RecentsModel.INSTANCE.get(mContext);
mOverviewComponentObserver = observer;
}
@ -67,19 +64,19 @@ public class OverviewCommandHelper {
}
mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mMainThreadExecutor.execute(new RecentsActivityCommand<>());
MAIN_EXECUTOR.execute(new RecentsActivityCommand<>());
}
public void onOverviewShown(boolean triggeredFromAltTab) {
mMainThreadExecutor.execute(new ShowRecentsCommand(triggeredFromAltTab));
MAIN_EXECUTOR.execute(new ShowRecentsCommand(triggeredFromAltTab));
}
public void onOverviewHidden() {
mMainThreadExecutor.execute(new HideRecentsCommand());
MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) {
mMainThreadExecutor.execute(() ->
MAIN_EXECUTOR.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
}
@ -178,7 +175,7 @@ public class OverviewCommandHelper {
// Otherwise, start overview.
mListener = mHelper.createActivityInitListener(this::onActivityReady);
mListener.registerAndStartActivity(mOverviewComponentObserver.getOverviewIntent(),
this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(),
this::createWindowAnimation, mContext, MAIN_EXECUTOR.getHandler(),
mAnimationProvider.getRecentsLaunchDuration());
}

View File

@ -1,9 +1,10 @@
package com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.os.Bundle;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.testing.TestInformationHandler;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.states.OverviewState;
@ -52,7 +53,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_LEFT_GESTURE_MARGIN: {
try {
final int leftMargin = new MainThreadExecutor().submit(() ->
final int leftMargin = MAIN_EXECUTOR.submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getLeftGestureMargin()).get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, leftMargin);
} catch (ExecutionException e) {
@ -65,7 +66,7 @@ public class QuickstepTestInformationHandler extends TestInformationHandler {
case TestProtocol.REQUEST_OVERVIEW_RIGHT_GESTURE_MARGIN: {
try {
final int rightMargin = new MainThreadExecutor().submit(() ->
final int rightMargin = MAIN_EXECUTOR.submit(() ->
mLauncher.<RecentsView>getOverviewPanel().getRightGestureMargin()).
get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, rightMargin);

View File

@ -15,7 +15,7 @@
*/
package com.android.quickstep;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.util.Log;
@ -25,6 +25,7 @@ import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import java.io.PrintWriter;
/**
@ -77,7 +78,7 @@ public class SwipeSharedState implements SwipeAnimationListener {
mRecentsAnimationListener.removeListener(this);
mRecentsAnimationListener.cancelListener();
if (mLastAnimationRunning && mLastAnimationTarget != null) {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(),
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
finishAnimation
? mLastAnimationTarget::finishAnimation
: mLastAnimationTarget::cancelAnimation);

View File

@ -23,6 +23,8 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_HINTS_IN_OVERVIEW
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.FAKE_LANDSCAPE_UI;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@ -72,7 +74,6 @@ import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
@ -82,8 +83,6 @@ import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
@ -106,8 +105,8 @@ import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.shared.system.RecentsAnimationListener;
import com.android.systemui.shared.system.SystemGestureExclusionListenerCompat;
import com.android.systemui.shared.system.TaskInfoCompat;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
@ -138,10 +137,6 @@ class ArgList extends LinkedList<String> {
public class TouchInteractionService extends Service implements
NavigationModeChangeListener, DisplayListener {
public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
public static final LooperExecutor BACKGROUND_EXECUTOR =
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
public static final EventLogArray TOUCH_INTERACTION_LOG =
new EventLogArray("touch_interaction_log", 40);
@ -161,9 +156,9 @@ public class TouchInteractionService extends Service implements
public void onInitialize(Bundle bundle) {
mISystemUiProxy = ISystemUiProxy.Stub
.asInterface(bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
MAIN_THREAD_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
MAIN_EXECUTOR.execute(TouchInteractionService.this::initInputMonitor);
MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiProxySet);
MAIN_EXECUTOR.execute(() -> preloadOverview(true /* fromInit */));
sIsInitialized = true;
}
@ -198,7 +193,7 @@ public class TouchInteractionService extends Service implements
@Override
public void onAssistantVisibilityChanged(float visibility) {
mLastAssistantVisibility = visibility;
MAIN_THREAD_EXECUTOR.execute(
MAIN_EXECUTOR.execute(
TouchInteractionService.this::onAssistantVisibilityChanged);
}
@ -214,13 +209,13 @@ public class TouchInteractionService extends Service implements
isButton, gestureSwipeLeft, activityControl.getContainerType());
if (completed && !isButton && shouldNotifyBackGesture()) {
BACKGROUND_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
UI_HELPER_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
}
}
public void onSystemUiStateChanged(int stateFlags) {
mSystemUiStateFlags = stateFlags;
MAIN_THREAD_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
MAIN_EXECUTOR.execute(TouchInteractionService.this::onSystemUiFlagsChanged);
}
/** Deprecated methods **/
@ -439,7 +434,7 @@ public class TouchInteractionService extends Service implements
if (mMode.hasGestures != newMode.hasGestures) {
if (newMode.hasGestures) {
getSystemService(DisplayManager.class).registerDisplayListener(
this, MAIN_THREAD_EXECUTOR.getHandler());
this, MAIN_EXECUTOR.getHandler());
} else {
getSystemService(DisplayManager.class).unregisterDisplayListener(this);
}
@ -897,7 +892,7 @@ public class TouchInteractionService extends Service implements
}
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(intent, null, listener, null, null));
}
}

View File

@ -15,11 +15,13 @@
*/
package com.android.quickstep.util;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.graphics.Rect;
import android.util.ArraySet;
import androidx.annotation.UiThread;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
@ -31,8 +33,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
/**
* Wrapper around {@link RecentsAnimationListener} which delegates callbacks to multiple listeners
* on the main thread
@ -82,7 +82,7 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
if (mCancelled) {
targetSet.cancelAnimation();
} else {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);
}
@ -92,14 +92,14 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
@Override
public final void onAnimationCanceled(ThumbnailData thumbnailData) {
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationCanceled();
}
});
// TODO: handle the transition better instead of simply using a transition delay.
if (thumbnailData != null) {
MAIN_THREAD_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
MAIN_EXECUTOR.getHandler().postDelayed(() -> mController.cleanupScreenshot(),
TRANSITION_DELAY);
}
}

View File

@ -15,8 +15,8 @@
*/
package com.android.quickstep.util;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.graphics.Rect;
@ -68,25 +68,25 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) {
mOnFinishListener.accept(this);
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
controller.setInputConsumerEnabled(false);
controller.finish(toRecents, sendUserLeaveHint);
if (callback != null) {
MAIN_THREAD_EXECUTOR.execute(callback);
MAIN_EXECUTOR.execute(callback);
}
});
}
public void enableInputConsumer() {
BACKGROUND_EXECUTOR.submit(() -> {
UI_HELPER_EXECUTOR.submit(() -> {
controller.hideCurrentInputMethod();
controller.setInputConsumerEnabled(true);
});
}
public void setWindowThresholdCrossed(boolean thresholdCrossed) {
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
if (mShouldMinimizeSplitScreen && thresholdCrossed) {
// NOTE: As a workaround for conflicting animations (Launcher animating the task

View File

@ -19,6 +19,7 @@ package com.android.quickstep.views;
import static android.provider.Settings.ACTION_APP_USAGE_SETTINGS;
import static com.android.launcher3.Utilities.prefixTextWithIcon;
import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
@ -41,7 +42,6 @@ import androidx.annotation.StringRes;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.systemui.shared.recents.model.Task;
@ -117,7 +117,7 @@ public final class DigitalWellBeingToast {
return;
}
Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
THREAD_POOL_EXECUTOR.execute(() -> {
final AppUsageLimit usageLimit = mLauncherApps.getAppUsageLimit(
task.getTopComponent().getPackageName(),
UserHandle.of(task.key.userId));

View File

@ -35,9 +35,9 @@ import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorSet;
@ -228,7 +228,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return;
}
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
TaskView taskView = getTaskView(taskId);
if (taskView == null) {
return;

View File

@ -14,16 +14,17 @@
package com.android.launcher3.uioverrides.plugins;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.os.Looper;
import com.android.launcher3.LauncherModel;
import com.android.systemui.shared.plugins.PluginInitializer;
public class PluginInitializerImpl implements PluginInitializer {
@Override
public Looper getBgLooper() {
return LauncherModel.getWorkerLooper();
return MODEL_EXECUTOR.getLooper();
}
@Override

View File

@ -15,20 +15,21 @@
*/
package com.android.quickstep;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import androidx.annotation.WorkerThread;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.ISystemUiProxy;
import androidx.annotation.WorkerThread;
/**
* Sets alpha for the back button
*/
@ -62,7 +63,7 @@ public class OverviewInteractionState {
// because of its high send frequency and data may be very different than the previous value
// For example, send back alpha on uihandler to avoid flickering when setting its visibility
mUiHandler = new Handler(this::handleUiMessage);
mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage);
mBgHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleBgMessage);
onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context)
.addModeChangeListener(this::onNavigationModeChanged));

View File

@ -16,7 +16,7 @@
package com.android.quickstep;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@ -26,11 +26,12 @@ import android.util.SparseBooleanArray;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.LooperExecutor;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -43,7 +44,7 @@ import java.util.function.Consumer;
public class RecentTasksList extends TaskStackChangeListener {
private final KeyguardManagerCompat mKeyguardManager;
private final MainThreadExecutor mMainThreadExecutor;
private final LooperExecutor mMainThreadExecutor;
private final ActivityManagerWrapper mActivityManagerWrapper;
// The list change id, increments as the task list changes in the system
@ -55,8 +56,7 @@ public class RecentTasksList extends TaskStackChangeListener {
ArrayList<Task> mTasks = new ArrayList<>();
public RecentTasksList(MainThreadExecutor mainThreadExecutor,
public RecentTasksList(LooperExecutor mainThreadExecutor,
KeyguardManagerCompat keyguardManager, ActivityManagerWrapper activityManagerWrapper) {
mMainThreadExecutor = mainThreadExecutor;
mKeyguardManager = keyguardManager;
@ -70,7 +70,7 @@ public class RecentTasksList extends TaskStackChangeListener {
*/
public void getTaskKeys(int numTasks, Consumer<ArrayList<Task>> callback) {
// Kick off task loading in the background
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
ArrayList<Task> tasks = loadTasksInBackground(numTasks, true /* loadKeysOnly */);
mMainThreadExecutor.execute(() -> callback.accept(tasks));
});
@ -92,12 +92,12 @@ public class RecentTasksList extends TaskStackChangeListener {
if (mLastLoadedId == mChangeId && (!mLastLoadHadKeysOnly || loadKeysOnly)) {
// The list is up to date, send the callback on the next frame,
// so that requestID can be returned first.
mMainThreadExecutor.getHandler().post(resultCallback);
mMainThreadExecutor.post(resultCallback);
return requestLoadId;
}
// Kick off task loading in the background
BACKGROUND_EXECUTOR.execute(() -> {
UI_HELPER_EXECUTOR.execute(() -> {
ArrayList<Task> tasks = loadTasksInBackground(Integer.MAX_VALUE, loadKeysOnly);
mMainThreadExecutor.execute(() -> {

View File

@ -15,6 +15,8 @@
*/
package com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
@ -22,7 +24,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import com.android.launcher3.MainThreadExecutor;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.util.RemoteAnimationProvider;
@ -92,14 +93,10 @@ public class RecentsActivityTracker<T extends BaseRecentsActivity> implements Ac
private static class Scheduler implements Runnable {
private WeakReference<RecentsActivityTracker> mPendingTracker = new WeakReference<>(null);
private MainThreadExecutor mMainThreadExecutor;
public synchronized void schedule(RecentsActivityTracker tracker) {
mPendingTracker = new WeakReference<>(tracker);
if (mMainThreadExecutor == null) {
mMainThreadExecutor = new MainThreadExecutor();
}
mMainThreadExecutor.execute(this);
MAIN_EXECUTOR.execute(this);
}
@Override

View File

@ -15,6 +15,10 @@
*/
package com.android.quickstep;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.createAndStartNewLooper;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
import android.annotation.TargetApi;
@ -22,13 +26,12 @@ import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.os.Build;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.LauncherAppsCompat.OnAppsChangedCallbackCompat;
import com.android.launcher3.util.MainThreadInitializedObject;
@ -66,13 +69,12 @@ public class RecentsModel extends TaskStackChangeListener {
private RecentsModel(Context context) {
mContext = context;
HandlerThread loaderThread = new HandlerThread("TaskThumbnailIconCache",
Process.THREAD_PRIORITY_BACKGROUND);
loaderThread.start();
mTaskList = new RecentTasksList(new MainThreadExecutor(),
Looper looper =
createAndStartNewLooper("TaskThumbnailIconCache", THREAD_PRIORITY_BACKGROUND);
mTaskList = new RecentTasksList(MAIN_EXECUTOR,
new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance());
mIconCache = new TaskIconCache(context, loaderThread.getLooper());
mThumbnailCache = new TaskThumbnailCache(context, loaderThread.getLooper());
mIconCache = new TaskIconCache(context, looper);
mThumbnailCache = new TaskThumbnailCache(context, looper);
ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
setupPackageListener();
}

View File

@ -16,6 +16,7 @@
package com.android.quickstep;
import static com.android.launcher3.uioverrides.RecentsUiFactory.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.ComponentName;
import android.content.Context;
@ -27,7 +28,6 @@ import android.os.Looper;
import android.util.LruCache;
import android.view.accessibility.AccessibilityManager;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.cache.HandlerRunnable;
@ -47,7 +47,6 @@ import java.util.function.Consumer;
public class TaskIconCache {
private final Handler mBackgroundHandler;
private final MainThreadExecutor mMainThreadExecutor;
private final AccessibilityManager mAccessibilityManager;
private final NormalizedIconLoader mIconLoader;
@ -68,7 +67,6 @@ public class TaskIconCache {
public TaskIconCache(Context context, Looper backgroundLooper) {
mBackgroundHandler = new Handler(backgroundLooper);
mMainThreadExecutor = new MainThreadExecutor();
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
Resources res = context.getResources();
@ -104,7 +102,7 @@ public class TaskIconCache {
// We don't call back to the provided callback in this case
return;
}
mMainThreadExecutor.execute(() -> {
MAIN_EXECUTOR.execute(() -> {
task.icon = icon;
task.titleDescription = contentDescription;
callback.accept(task);

View File

@ -15,12 +15,14 @@
*/
package com.android.quickstep;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.cache.HandlerRunnable;
@ -30,13 +32,13 @@ import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import java.util.ArrayList;
import java.util.function.Consumer;
public class TaskThumbnailCache {
private final Handler mBackgroundHandler;
private final MainThreadExecutor mMainThreadExecutor;
private final int mCacheSize;
private final ThumbnailCache mCache;
@ -94,7 +96,6 @@ public class TaskThumbnailCache {
public TaskThumbnailCache(Context context, Looper backgroundLooper) {
mBackgroundHandler = new Handler(backgroundLooper);
mMainThreadExecutor = new MainThreadExecutor();
mHighResLoadingState = new HighResLoadingState(context);
Resources res = context.getResources();
@ -168,7 +169,7 @@ public class TaskThumbnailCache {
// We don't call back to the provided callback in this case
return;
}
mMainThreadExecutor.execute(() -> {
MAIN_EXECUTOR.execute(() -> {
mCache.put(key, thumbnail);
callback.accept(thumbnail);
onEnd();

View File

@ -16,11 +16,20 @@
package com.android.quickstep;
import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import androidx.test.filters.SmallTest;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.LooperExecutor;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.KeyguardManagerCompat;
@ -31,14 +40,6 @@ import org.junit.Test;
import java.util.Collections;
import java.util.List;
import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SmallTest
public class RecentTasksListTest {
@ -49,7 +50,7 @@ public class RecentTasksListTest {
@Before
public void setup() {
MainThreadExecutor mockMainThreadExecutor = mock(MainThreadExecutor.class);
LooperExecutor mockMainThreadExecutor = mock(LooperExecutor.class);
KeyguardManagerCompat mockKeyguardManagerCompat = mock(KeyguardManagerCompat.class);
mockActivityManagerWrapper = mock(ActivityManagerWrapper.class);
mRecentTasksList = new RecentTasksList(mockMainThreadExecutor, mockKeyguardManagerCompat,

View File

@ -16,6 +16,8 @@
package com.android.launcher3;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
@ -28,9 +30,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
@ -39,6 +39,8 @@ import android.util.Base64;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.WorkerThread;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.BitmapInfo;
@ -65,9 +67,6 @@ import java.util.Set;
public class InstallShortcutReceiver extends BroadcastReceiver {
private static final int MSG_ADD_TO_QUEUE = 1;
private static final int MSG_FLUSH_QUEUE = 2;
public static final int FLAG_ACTIVITY_PAUSED = 1;
public static final int FLAG_LOADER_RUNNING = 2;
public static final int FLAG_DRAG_AND_DROP = 4;
@ -100,65 +99,56 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
private static final Handler sHandler = new Handler(LauncherModel.getWorkerLooper()) {
@WorkerThread
private static void addToQueue(Context context, PendingInstallShortcutInfo info) {
String encoded = info.encodeToString();
SharedPreferences prefs = Utilities.getPrefs(context);
Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
strings = (strings != null) ? new HashSet<>(strings) : new HashSet<>(1);
strings.add(encoded);
prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ADD_TO_QUEUE: {
Pair<Context, PendingInstallShortcutInfo> pair =
(Pair<Context, PendingInstallShortcutInfo>) msg.obj;
String encoded = pair.second.encodeToString();
SharedPreferences prefs = Utilities.getPrefs(pair.first);
Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
strings.add(encoded);
prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
return;
}
case MSG_FLUSH_QUEUE: {
Context context = (Context) msg.obj;
LauncherModel model = LauncherAppState.getInstance(context).getModel();
if (model.getCallback() == null) {
// Launcher not loaded
return;
}
ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
SharedPreferences prefs = Utilities.getPrefs(context);
Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
if (strings == null) {
return;
}
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
for (String encoded : strings) {
PendingInstallShortcutInfo info = decode(encoded, context);
if (info == null) {
continue;
}
String pkg = getIntentPackage(info.launchIntent);
if (!TextUtils.isEmpty(pkg)
&& !launcherApps.isPackageEnabledForProfile(pkg, info.user)) {
if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
+ info.launchIntent);
continue;
}
// Generate a shortcut info to add into the model
installQueue.add(info.getItemInfo());
}
prefs.edit().remove(APPS_PENDING_INSTALL).apply();
if (!installQueue.isEmpty()) {
model.addAndBindAddedWorkspaceItems(installQueue);
}
return;
}
}
@WorkerThread
private static void flushQueueInBackground(Context context) {
LauncherModel model = LauncherAppState.getInstance(context).getModel();
if (model.getCallback() == null) {
// Launcher not loaded
return;
}
};
ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
SharedPreferences prefs = Utilities.getPrefs(context);
Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
if (strings == null) {
return;
}
LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
for (String encoded : strings) {
PendingInstallShortcutInfo info = decode(encoded, context);
if (info == null) {
continue;
}
String pkg = getIntentPackage(info.launchIntent);
if (!TextUtils.isEmpty(pkg)
&& !launcherApps.isPackageEnabledForProfile(pkg, info.user)) {
if (DBG) {
Log.d(TAG, "Ignoring shortcut for absent package: " + info.launchIntent);
}
continue;
}
// Generate a shortcut info to add into the model
installQueue.add(info.getItemInfo());
}
prefs.edit().remove(APPS_PENDING_INSTALL).apply();
if (!installQueue.isEmpty()) {
model.addAndBindAddedWorkspaceItems(installQueue);
}
}
public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
UserHandle user) {
@ -288,7 +278,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
// Queue the item up for adding if launcher has not loaded properly yet
Message.obtain(sHandler, MSG_ADD_TO_QUEUE, Pair.create(context, info)).sendToTarget();
MODEL_EXECUTOR.post(() -> addToQueue(context, info));
flushInstallQueue(context);
}
@ -304,7 +294,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
if (sInstallQueueDisabledFlags != 0) {
return;
}
Message.obtain(sHandler, MSG_FLUSH_QUEUE, context.getApplicationContext()).sendToTarget();
MODEL_EXECUTOR.post(() -> flushQueueInBackground(context));
}
/**
@ -484,7 +474,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
appInfo.title = "";
appInfo.applyFrom(app.getIconCache().getDefaultIcon(user));
final WorkspaceItemInfo si = appInfo.makeWorkspaceItem();
if (Looper.myLooper() == LauncherModel.getWorkerLooper()) {
if (Looper.myLooper() == MODEL_EXECUTOR.getLooper()) {
app.getIconCache().getTitleAndIcon(si, activityInfo, false /* useLowResIcon */);
} else {
app.getModel().updateAndBindWorkspaceItem(() -> {

View File

@ -18,6 +18,7 @@ package com.android.launcher3;
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
import android.annotation.TargetApi;
@ -42,6 +43,9 @@ import android.util.Xml;
import android.view.Display;
import android.view.WindowManager;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.util.ConfigMonitor;
import com.android.launcher3.util.IntArray;
@ -55,9 +59,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
public class InvariantDeviceProfile {
public static final String TAG = "IDP";
@ -280,7 +281,7 @@ public class InvariantDeviceProfile {
public void setCurrentGrid(Context context, String gridName) {
Context appContext = context.getApplicationContext();
Utilities.getPrefs(appContext).edit().putString(KEY_IDP_GRID_NAME, gridName).apply();
new MainThreadExecutor().execute(() -> onConfigChanged(appContext));
MAIN_EXECUTOR.execute(() -> onConfigChanged(appContext));
}
private void onConfigChanged(Context context) {

View File

@ -18,20 +18,21 @@ package com.android.launcher3;
import static com.android.launcher3.LauncherAppState.ACTION_FORCE_ROLOAD;
import static com.android.launcher3.config.FeatureFlags.IS_DOGFOOD_BUILD;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import androidx.annotation.Nullable;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserManagerCompat;
@ -65,8 +66,6 @@ import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import androidx.annotation.Nullable;
/**
* Maintains in-memory state of the Launcher. It is expected that there should be only one
* LauncherModel object held in a static. Also provide APIs for updating the database state
@ -78,21 +77,12 @@ public class LauncherModel extends BroadcastReceiver
static final String TAG = "Launcher.Model";
private final MainThreadExecutor mUiExecutor = new MainThreadExecutor();
@Thunk final LauncherAppState mApp;
@Thunk final Object mLock = new Object();
@Thunk
LoaderTask mLoaderTask;
@Thunk boolean mIsLoaderTaskRunning;
@Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
private static final Looper mWorkerLooper;
static {
sWorkerThread.start();
mWorkerLooper = sWorkerThread.getLooper();
}
@Thunk static final Handler sWorker = new Handler(mWorkerLooper);
// Indicates whether the current model data is valid or not.
// We start off with everything not loaded. After that, we assume that
// our monitoring of the package manager provides all updates and we never
@ -318,7 +308,7 @@ public class LauncherModel extends BroadcastReceiver
if (mCallbacks != null && mCallbacks.get() != null) {
final Callbacks oldCallbacks = mCallbacks.get();
// Clear any pending bind-runnables from the synchronized load process.
mUiExecutor.execute(oldCallbacks::clearPendingBinds);
MAIN_EXECUTOR.execute(oldCallbacks::clearPendingBinds);
// If there is already one running, tell it to stop.
stopLoader();
@ -362,7 +352,7 @@ public class LauncherModel extends BroadcastReceiver
// Always post the loader task, instead of running directly (even on same thread) so
// that we exit any nested synchronized blocks
sWorker.post(mLoaderTask);
MODEL_EXECUTOR.post(mLoaderTask);
}
}
@ -429,8 +419,8 @@ public class LauncherModel extends BroadcastReceiver
* use partial updates similar to {@link UserManagerCompat}
*/
public void refreshShortcutsIfRequired() {
sWorker.removeCallbacks(mShortcutPermissionCheckRunnable);
sWorker.post(mShortcutPermissionCheckRunnable);
MODEL_EXECUTOR.getHandler().removeCallbacks(mShortcutPermissionCheckRunnable);
MODEL_EXECUTOR.post(mShortcutPermissionCheckRunnable);
}
/**
@ -457,14 +447,8 @@ public class LauncherModel extends BroadcastReceiver
}
public void enqueueModelUpdateTask(ModelUpdateTask task) {
task.init(mApp, this, sBgDataModel, mBgAllAppsList, mUiExecutor);
if (sWorkerThread.getThreadId() == Process.myTid()) {
task.run();
} else {
// If we are not on the worker thread, then post to the worker handler
sWorker.post(task);
}
task.init(mApp, this, sBgDataModel, mBgAllAppsList, MAIN_EXECUTOR);
MODEL_EXECUTOR.execute(task);
}
/**
@ -540,14 +524,4 @@ public class LauncherModel extends BroadcastReceiver
return mCallbacks != null ? mCallbacks.get() : null;
}
/**
* @return the looper for the worker thread which can be used to start background tasks.
*/
public static Looper getWorkerLooper() {
return mWorkerLooper;
}
public static void setWorkerPriority(final int priority) {
Process.setThreadPriority(sWorkerThread.getThreadId(), priority);
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.launcher3;
import android.os.Looper;
import com.android.launcher3.util.LooperExecutor;
/**
* An executor service that executes its tasks on the main thread.
*
* Shutting down this executor is not supported.
*/
public class MainThreadExecutor extends LooperExecutor {
public MainThreadExecutor() {
super(Looper.getMainLooper());
}
}

View File

@ -30,13 +30,13 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.util.Executors;
import java.util.List;
@ -103,7 +103,7 @@ public class SessionCommitReceiver extends BroadcastReceiver {
// grid.
prefs.edit().putBoolean(ADD_ICON_PREFERENCE_KEY, true).apply();
} else if (!prefs.contains(ADD_ICON_PREFERENCE_INITIALIZED_KEY)) {
new PrefInitTask(context).executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
new PrefInitTask(context).executeOnExecutor(Executors.THREAD_POOL_EXECUTOR);
}
}

View File

@ -76,10 +76,6 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -112,8 +108,6 @@ public final class Utilities {
public static final boolean ATLEAST_OREO =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
public static final int SINGLE_FRAME_MS = 16;
/**
* Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
*/
@ -136,18 +130,6 @@ public final class Utilities {
public static final String EXTRA_WALLPAPER_OFFSET = "com.android.launcher3.WALLPAPER_OFFSET";
public static final String EXTRA_WALLPAPER_FLAVOR = "com.android.launcher3.WALLPAPER_FLAVOR";
// These values are same as that in {@link AsyncTask}.
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
/**
* An {@link Executor} to be used with async task with no limit on the queue size.
*/
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, new LinkedBlockingQueue<>());
public static boolean IS_RUNNING_IN_TEST_HARNESS =
ActivityManager.isRunningInTestHarness();

View File

@ -1,5 +1,8 @@
package com.android.launcher3;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
@ -23,21 +26,23 @@ import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
import android.util.LongSparseArray;
import androidx.annotation.Nullable;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SQLiteCacheHelper;
@ -50,11 +55,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import androidx.annotation.Nullable;
public class WidgetPreviewLoader {
private static final String TAG = "WidgetPreviewLoader";
@ -68,23 +70,18 @@ public class WidgetPreviewLoader {
* Note: synchronized block used for this variable is expensive and the block should always
* be posted to a background thread.
*/
@Thunk final Set<Bitmap> mUnusedBitmaps =
Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>());
@Thunk final Set<Bitmap> mUnusedBitmaps = Collections.newSetFromMap(new WeakHashMap<>());
private final Context mContext;
private final IconCache mIconCache;
private final UserManagerCompat mUserManager;
private final CacheDb mDb;
private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
@Thunk final Handler mWorkerHandler;
public WidgetPreviewLoader(Context context, IconCache iconCache) {
mContext = context;
mIconCache = iconCache;
mUserManager = UserManagerCompat.getInstance(context);
mDb = new CacheDb(context);
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
}
/**
@ -99,7 +96,7 @@ public class WidgetPreviewLoader {
WidgetCacheKey key = new WidgetCacheKey(item.componentName, item.user, size);
PreviewLoadTask task = new PreviewLoadTask(key, item, previewWidth, previewHeight, caller);
task.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
task.executeOnExecutor(Executors.THREAD_POOL_EXECUTOR);
CancellationSignal signal = new CancellationSignal();
signal.setOnCancelListener(task);
@ -494,12 +491,7 @@ public class WidgetPreviewLoader {
private Drawable mutateOnMainThread(final Drawable drawable) {
try {
return mMainThreadExecutor.submit(new Callable<Drawable>() {
@Override
public Drawable call() throws Exception {
return drawable.mutate();
}
}).get();
return MAIN_EXECUTOR.submit(drawable::mutate).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
@ -607,7 +599,7 @@ public class WidgetPreviewLoader {
// Write the generated preview to the DB in the worker thread
if (mVersions != null) {
mWorkerHandler.post(new Runnable() {
MODEL_EXECUTOR.post(new Runnable() {
@Override
public void run() {
if (!isCancelled()) {
@ -637,7 +629,7 @@ public class WidgetPreviewLoader {
// recycled set immediately. Otherwise, it will be recycled after the preview is written
// to disk.
if (preview != null) {
mWorkerHandler.post(new Runnable() {
MODEL_EXECUTOR.post(new Runnable() {
@Override
public void run() {
synchronized (mUnusedBitmaps) {
@ -658,7 +650,7 @@ public class WidgetPreviewLoader {
// in the tasks's onCancelled() call, and if cancelled while the task is writing to
// disk, it will be cancelled in the task's onPostExecute() call.
if (mBitmapToRecycle != null) {
mWorkerHandler.post(new Runnable() {
MODEL_EXECUTOR.post(new Runnable() {
@Override
public void run() {
synchronized (mUnusedBitmaps) {

View File

@ -90,6 +90,7 @@ import com.android.launcher3.touch.WorkspaceTouchListener;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.IntSparseArrayMap;
@ -1159,7 +1160,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
}
protected void setWallpaperDimension() {
Utilities.THREAD_POOL_EXECUTOR.execute(new Runnable() {
Executors.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
final Point size = LauncherAppState.getIDP(getContext()).defaultWallpaperSize;

View File

@ -16,6 +16,8 @@
package com.android.launcher3.compat;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
@ -30,19 +32,17 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
@TargetApi(26)
public class LauncherAppsCompatVO extends LauncherAppsCompatVL {
@ -120,7 +120,7 @@ public class LauncherAppsCompatVO extends LauncherAppsCompatVL {
}
} else {
// Block the worker thread until the accept() is called.
new LooperExecutor(LauncherModel.getWorkerLooper()).execute(new Runnable() {
MODEL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
try {

View File

@ -16,22 +16,22 @@
package com.android.launcher3.compat;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionCallback;
import android.content.pm.PackageInstaller.SessionInfo;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.SparseArray;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@ -47,7 +47,6 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
@Thunk final PackageInstaller mInstaller;
private final IconCache mCache;
private final Handler mWorker;
private final Context mAppContext;
private final HashMap<String,Boolean> mSessionVerifiedMap = new HashMap<>();
private final LauncherAppsCompat mLauncherApps;
@ -56,8 +55,7 @@ public class PackageInstallerCompatVL extends PackageInstallerCompat {
mAppContext = context.getApplicationContext();
mInstaller = context.getPackageManager().getPackageInstaller();
mCache = LauncherAppState.getInstance(context).getIconCache();
mWorker = new Handler(LauncherModel.getWorkerLooper());
mInstaller.registerSessionCallback(mCallback, mWorker);
mInstaller.registerSessionCallback(mCallback, MODEL_EXECUTOR.getHandler());
mLauncherApps = LauncherAppsCompat.getInstance(context);
}

View File

@ -20,6 +20,7 @@ import static com.android.launcher3.logging.LoggerUtils.newCommandAction;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.logging.LoggerUtils.newItemTarget;
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityOptions;
@ -47,7 +48,6 @@ import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetHost;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.R;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompatVO;
@ -55,7 +55,6 @@ import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
@ -234,7 +233,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener
mWidgetCell.applyFromCellItem(item, mApp.getWidgetCache());
mWidgetCell.ensurePreview();
}
}.executeOnExecutor(new LooperExecutor(LauncherModel.getWorkerLooper()));
}.executeOnExecutor(MODEL_EXECUTOR);
// TODO: Create a worker looper executor and reuse that everywhere.
}

View File

@ -17,6 +17,7 @@
package com.android.launcher3.dragndrop;
import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -41,16 +42,19 @@ import android.os.Handler;
import android.os.Looper;
import android.view.View;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.FirstFrameAnimatorHelper;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.FirstFrameAnimatorHelper;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.util.Themes;
@ -58,10 +62,6 @@ import com.android.launcher3.util.Thunk;
import java.util.Arrays;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
public class DragView extends View implements LauncherStateManager.StateListener {
private static final ColorMatrix sTempMatrix1 = new ColorMatrix();
private static final ColorMatrix sTempMatrix2 = new ColorMatrix();
@ -210,7 +210,7 @@ public class DragView extends View implements LauncherStateManager.StateListener
return;
}
// Load the adaptive icon on a background thread and add the view in ui thread.
new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(new Runnable() {
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
Object[] outObj = new Object[1];

View File

@ -16,6 +16,8 @@
package com.android.launcher3.dragndrop;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@ -31,7 +33,6 @@ import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.Launcher;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.PreviewBackground;
@ -85,7 +86,7 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable {
// Create the actual drawable on the UI thread to avoid race conditions with
// FolderIcon draw pass
try {
return new MainThreadExecutor().submit(() -> {
return MAIN_EXECUTOR.submit(() -> {
FolderIcon icon = launcher.findFolderIcon(folderId);
return icon == null ? null : createDrawableOnUiThread(icon, badge, dragViewSize);
}).get();

View File

@ -16,6 +16,8 @@
package com.android.launcher3.graphics;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
@ -25,7 +27,6 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.View;
import com.android.launcher3.BubbleTextView;
@ -35,7 +36,6 @@ import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.PendingAppWidgetHostView;
@ -157,7 +157,7 @@ public class DragPreviewProvider {
}
mOutlineGeneratorCallback = new OutlineGeneratorCallback(preview);
new Handler(UiThreadHelper.getBackgroundLooper()).post(mOutlineGeneratorCallback);
UI_HELPER_EXECUTOR.post(mOutlineGeneratorCallback);
}
protected static Rect getDrawableBounds(Drawable d) {

View File

@ -1,5 +1,7 @@
package com.android.launcher3.graphics;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.XmlResourceParser;
@ -17,8 +19,6 @@ import android.util.Xml;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.InvariantDeviceProfile.GridOption;
import com.android.launcher3.R;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -180,10 +180,10 @@ public class GridOptionsProvider extends ContentProvider {
throw new FileNotFoundException(e.getMessage());
}
LooperExecutor executor = new LooperExecutor(UiThreadHelper.getBackgroundLooper());
try {
return openPipeHelper(uri, MIME_TYPE_PNG, null,
executor.submit(new LauncherPreviewRenderer(getContext(), idp)), BITMAP_WRITER);
UI_HELPER_EXECUTOR.submit(new LauncherPreviewRenderer(getContext(), idp)),
BITMAP_WRITER);
} catch (Exception e) {
throw new FileNotFoundException(e.getMessage());
}

View File

@ -16,6 +16,9 @@
package com.android.launcher3.icons;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@ -36,8 +39,6 @@ import com.android.launcher3.IconProvider;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.Utilities;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.compat.LauncherAppsCompat;
@ -59,8 +60,6 @@ public class IconCache extends BaseIconCache {
private static final String TAG = "Launcher.IconCache";
private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
private final CachingLogic<ComponentWithLabel> mComponentWithLabelCachingLogic;
private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic;
@ -72,7 +71,7 @@ public class IconCache extends BaseIconCache {
private int mPendingIconRequestCount = 0;
public IconCache(Context context, InvariantDeviceProfile inv) {
super(context, LauncherFiles.APP_ICONS_DB, LauncherModel.getWorkerLooper(),
super(context, LauncherFiles.APP_ICONS_DB, MODEL_EXECUTOR.getLooper(),
inv.fillResIconDpi, inv.iconBitmapSize, true /* inMemoryCache */);
mComponentWithLabelCachingLogic = new ComponentCachingLogic(context);
mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.newInstance(context);
@ -123,7 +122,7 @@ public class IconCache extends BaseIconCache {
final ItemInfoWithIcon info) {
Preconditions.assertUIThread();
if (mPendingIconRequestCount <= 0) {
LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_FOREGROUND);
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
}
mPendingIconRequestCount ++;
@ -135,7 +134,7 @@ public class IconCache extends BaseIconCache {
} else if (info instanceof PackageItemInfo) {
getTitleAndIconForApp((PackageItemInfo) info, false);
}
mMainThreadExecutor.execute(() -> {
MAIN_EXECUTOR.execute(() -> {
caller.reapplyItemInfo(info);
onEnd();
});
@ -148,7 +147,7 @@ public class IconCache extends BaseIconCache {
private void onIconRequestEnd() {
mPendingIconRequestCount --;
if (mPendingIconRequestCount <= 0) {
LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_BACKGROUND);
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}

View File

@ -1,5 +1,7 @@
package com.android.launcher3.logging;
import static com.android.launcher3.util.Executors.createAndStartNewLooper;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@ -92,9 +94,8 @@ public final class FileLog {
private static Handler getHandler() {
synchronized (DATE_FORMAT) {
if (sHandler == null) {
HandlerThread thread = new HandlerThread("file-logger");
thread.start();
sHandler = new Handler(thread.getLooper(), new LogWriterCallback());
sHandler = new Handler(createAndStartNewLooper("file-logger"),
new LogWriterCallback());
}
}
return sHandler;

View File

@ -16,6 +16,8 @@
package com.android.launcher3.model;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.os.Looper;
import android.util.Log;
@ -25,11 +27,10 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.PagedView;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperIdleLock;
@ -64,7 +65,7 @@ public abstract class BaseLoaderResults {
public BaseLoaderResults(LauncherAppState app, BgDataModel dataModel,
AllAppsList allAppsList, int pageToBindFirst, WeakReference<Callbacks> callbacks) {
mUiExecutor = new MainThreadExecutor();
mUiExecutor = MAIN_EXECUTOR;
mApp = app;
mBgDataModel = dataModel;
mBgAllAppsList = allAppsList;

View File

@ -20,6 +20,7 @@ import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
import static com.android.launcher3.model.LoaderResults.filterCurrentWorkspaceItems;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.isSystemApp;
import android.appwidget.AppWidgetProviderInfo;
@ -32,7 +33,6 @@ import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.ShortcutInfo;
import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
@ -772,7 +772,7 @@ public class LoaderTask implements Runnable {
new SdCardAvailableReceiver(mApp, pendingPackages),
new IntentFilter(Intent.ACTION_BOOT_COMPLETED),
null,
new Handler(LauncherModel.getWorkerLooper()));
MODEL_EXECUTOR.getHandler());
}
}
}

View File

@ -16,6 +16,8 @@
package com.android.launcher3.model;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
@ -31,17 +33,16 @@ import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetHost;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.LauncherProvider;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.Settings;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LooperExecutor;
import java.util.ArrayList;
import java.util.Arrays;
@ -61,7 +62,6 @@ public class ModelWriter {
private final BgDataModel mBgDataModel;
private final Handler mUiHandler;
private final Executor mWorkerExecutor;
private final boolean mHasVerticalHotseat;
private final boolean mVerifyChanges;
@ -74,7 +74,6 @@ public class ModelWriter {
mContext = context;
mModel = model;
mBgDataModel = dataModel;
mWorkerExecutor = new LooperExecutor(LauncherModel.getWorkerLooper());
mHasVerticalHotseat = hasVerticalHotseat;
mVerifyChanges = verifyChanges;
mUiHandler = new Handler(Looper.getMainLooper());
@ -194,7 +193,7 @@ public class ModelWriter {
item.spanX = spanX;
item.spanY = spanY;
mWorkerExecutor.execute(new UpdateItemRunnable(item, () ->
((Executor) MODEL_EXECUTOR).execute(new UpdateItemRunnable(item, () ->
new ContentWriter(mContext)
.put(Favorites.CONTAINER, item.container)
.put(Favorites.CELLX, item.cellX)
@ -209,7 +208,7 @@ public class ModelWriter {
* Update an item to the database in a specified container.
*/
public void updateItemInDatabase(ItemInfo item) {
mWorkerExecutor.execute(new UpdateItemRunnable(item, () -> {
((Executor) MODEL_EXECUTOR).execute(new UpdateItemRunnable(item, () -> {
ContentWriter writer = new ContentWriter(mContext);
item.onAddToDatabase(writer);
return writer;
@ -229,7 +228,7 @@ public class ModelWriter {
ModelVerifier verifier = new ModelVerifier();
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
mWorkerExecutor.execute(() -> {
((Executor) MODEL_EXECUTOR).execute(() -> {
// Write the item on background thread, as some properties might have been updated in
// the background.
final ContentWriter writer = new ContentWriter(mContext);
@ -333,14 +332,14 @@ public class ModelWriter {
if (mPreparingToUndo) {
mDeleteRunnables.add(r);
} else {
mWorkerExecutor.execute(r);
((Executor) MODEL_EXECUTOR).execute(r);
}
}
public void commitDelete() {
mPreparingToUndo = false;
for (Runnable runnable : mDeleteRunnables) {
mWorkerExecutor.execute(runnable);
((Executor) MODEL_EXECUTOR).execute(runnable);
}
mDeleteRunnables.clear();
}

View File

@ -16,6 +16,7 @@
package com.android.launcher3.notification;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
import android.annotation.TargetApi;
@ -31,7 +32,8 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import com.android.launcher3.LauncherModel;
import androidx.annotation.Nullable;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.SecureSettingsObserver;
@ -43,8 +45,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.Nullable;
/**
* A {@link NotificationListenerService} that sends updates to its
* {@link NotificationsChangedListener} when notifications are posted or canceled,
@ -141,7 +141,7 @@ public class NotificationListener extends NotificationListenerService {
public NotificationListener() {
super();
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper(), mWorkerCallback);
mWorkerHandler = new Handler(MODEL_EXECUTOR.getLooper(), mWorkerCallback);
mUiHandler = new Handler(Looper.getMainLooper(), mUiCallback);
sNotificationListenerInstance = this;
}

View File

@ -24,6 +24,7 @@ import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFI
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
@ -36,7 +37,6 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
@ -51,9 +51,7 @@ import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
import com.android.launcher3.dot.DotInfo;
@ -65,10 +63,8 @@ import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationItemView;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.popup.PopupDataProvider.PopupDataChangeListener;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.PackageUserKey;
@ -307,8 +303,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
setLayoutTransition(new LayoutTransition());
// Load the shortcuts on a background thread and update the container as it animates.
final Looper workerLooper = LauncherModel.getWorkerLooper();
new Handler(workerLooper).postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
mLauncher, originalItemInfo, new Handler(Looper.getMainLooper()),
this, mShortcuts, notificationKeys));
}

View File

@ -15,6 +15,8 @@
*/
package com.android.launcher3.states;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
@ -23,7 +25,6 @@ import android.os.IBinder;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.MainThreadExecutor;
import java.lang.ref.WeakReference;
@ -94,16 +95,12 @@ public abstract class InternalStateHandler extends Binder {
private static class Scheduler implements Runnable {
private WeakReference<InternalStateHandler> mPendingHandler = new WeakReference<>(null);
private MainThreadExecutor mMainThreadExecutor;
public void schedule(InternalStateHandler handler) {
synchronized (this) {
mPendingHandler = new WeakReference<>(handler);
if (mMainThreadExecutor == null) {
mMainThreadExecutor = new MainThreadExecutor();
}
}
mMainThreadExecutor.execute(this);
MAIN_EXECUTOR.execute(this);
}
@Override

View File

@ -15,6 +15,8 @@
*/
package com.android.launcher3.testing;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.os.Bundle;
@ -23,7 +25,6 @@ import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherState;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.util.ResourceBasedOverride;
@ -88,20 +89,20 @@ public class TestInformationHandler implements ResourceBasedOverride {
break;
case TestProtocol.REQUEST_FREEZE_APP_LIST:
new MainThreadExecutor().execute(() ->
MAIN_EXECUTOR.execute(() ->
mLauncher.getAppsView().getAppsStore().enableDeferUpdates(
AllAppsStore.DEFER_UPDATES_TEST));
break;
case TestProtocol.REQUEST_UNFREEZE_APP_LIST:
new MainThreadExecutor().execute(() ->
MAIN_EXECUTOR.execute(() ->
mLauncher.getAppsView().getAppsStore().disableDeferUpdates(
AllAppsStore.DEFER_UPDATES_TEST));
break;
case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: {
try {
final int deferUpdatesFlags = new MainThreadExecutor().submit(() ->
final int deferUpdatesFlags = MAIN_EXECUTOR.submit(() ->
mLauncher.getAppsView().getAppsStore().getDeferUpdatesFlags()).get();
response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD,
deferUpdatesFlags);

View File

@ -16,6 +16,9 @@ package com.android.launcher3.util;
* limitations under the License.
*/
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -24,13 +27,10 @@ import android.content.res.Configuration;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import com.android.launcher3.MainThreadExecutor;
import java.util.function.Consumer;
/**
@ -78,7 +78,7 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener
// Listen for display manager change
mContext.getSystemService(DisplayManager.class)
.registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
}
@Override
@ -122,7 +122,7 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener
if (mCallback != null) {
Consumer<Context> callback = mCallback;
mCallback = null;
new MainThreadExecutor().execute(() -> callback.accept(mContext));
MAIN_EXECUTOR.execute(() -> callback.accept(mContext));
}
}

View File

@ -15,6 +15,8 @@
*/
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.content.Context;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
@ -54,7 +56,7 @@ public class DefaultDisplay implements DisplayListener {
mChangeHandler = new Handler(this::onChange);
context.getSystemService(DisplayManager.class)
.registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
}
@Override

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.util;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Various different executors used in Launcher
*/
public class Executors {
// These values are same as that in {@link AsyncTask}.
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
/**
* An {@link Executor} to be used with async task with no limit on the queue size.
*/
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, new LinkedBlockingQueue<>());
/**
* Returns the executor for running tasks on the main thread.
*/
public static final LooperExecutor MAIN_EXECUTOR =
new LooperExecutor(Looper.getMainLooper());
/**
* A background executor for using time sensitive actions where user is waiting for response.
*/
public static final LooperExecutor UI_HELPER_EXECUTOR =
new LooperExecutor(createAndStartNewForegroundLooper("UiThreadHelper"));
/**
* Utility method to get a started handler thread statically
*/
public static Looper createAndStartNewLooper(String name) {
return createAndStartNewLooper(name, Process.THREAD_PRIORITY_DEFAULT);
}
/**
* Utility method to get a started handler thread statically with the provided priority
*/
public static Looper createAndStartNewLooper(String name, int priority) {
HandlerThread thread = new HandlerThread(name, priority);
thread.start();
return thread.getLooper();
}
/**
* Similar to {@link #createAndStartNewLooper(String)}, but starts the thread with
* foreground priority.
* Think before using
*/
public static Looper createAndStartNewForegroundLooper(String name) {
return createAndStartNewLooper(name, Process.THREAD_PRIORITY_FOREGROUND);
}
/**
* Executor used for running Launcher model related tasks (eg loading icons or updated db)
*/
public static final LooperExecutor MODEL_EXECUTOR =
new LooperExecutor(createAndStartNewLooper("launcher-loader"));
}

View File

@ -16,7 +16,9 @@
package com.android.launcher3.util;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import java.util.List;
import java.util.concurrent.AbstractExecutorService;
@ -46,6 +48,13 @@ public class LooperExecutor extends AbstractExecutorService {
}
}
/**
* Same as execute, but never runs the action inline.
*/
public void post(Runnable runnable) {
mHandler.post(runnable);
}
/**
* Not supported and throws an exception when used.
*/
@ -79,7 +88,31 @@ public class LooperExecutor extends AbstractExecutorService {
*/
@Override
@Deprecated
public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException {
public boolean awaitTermination(long l, TimeUnit timeUnit) {
throw new UnsupportedOperationException();
}
/**
* Returns the thread for this executor
*/
public Thread getThread() {
return mHandler.getLooper().getThread();
}
/**
* Returns the looper for this executor
*/
public Looper getLooper() {
return mHandler.getLooper();
}
/**
* Set the priority of a thread, based on Linux priorities.
* @param priority Linux priority level, from -20 for highest scheduling priority
* to 19 for lowest scheduling priority.
* @see Process#setThreadPriority(int, int)
*/
public void setThreadPriority(int priority) {
Process.setThreadPriority(((HandlerThread) getThread()).getThreadId(), priority);
}
}

View File

@ -15,12 +15,13 @@
*/
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import android.content.Context;
import android.os.Looper;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.ResourceBasedOverride.Overrides;
import java.util.concurrent.ExecutionException;
@ -43,7 +44,7 @@ public class MainThreadInitializedObject<T> {
mValue = mProvider.get(context.getApplicationContext());
} else {
try {
return new MainThreadExecutor().submit(() -> get(context)).get();
return MAIN_EXECUTOR.submit(() -> get(context)).get();
} catch (InterruptedException|ExecutionException e) {
throw new RuntimeException(e);
}

View File

@ -16,9 +16,10 @@
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.os.Looper;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.config.FeatureFlags;
/**
@ -33,7 +34,7 @@ public class Preconditions {
}
public static void assertWorkerThread() {
if (FeatureFlags.IS_DOGFOOD_BUILD && !isSameLooper(LauncherModel.getWorkerLooper())) {
if (FeatureFlags.IS_DOGFOOD_BUILD && !isSameLooper(MODEL_EXECUTOR.getLooper())) {
throw new IllegalStateException();
}
}

View File

@ -15,14 +15,13 @@
*/
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.view.inputmethod.InputMethodManager;
/**
@ -30,25 +29,15 @@ import android.view.inputmethod.InputMethodManager;
*/
public class UiThreadHelper {
private static HandlerThread sHandlerThread;
private static Handler sHandler;
private static final int MSG_HIDE_KEYBOARD = 1;
private static final int MSG_SET_ORIENTATION = 2;
private static final int MSG_RUN_COMMAND = 3;
public static Looper getBackgroundLooper() {
if (sHandlerThread == null) {
sHandlerThread =
new HandlerThread("UiThreadHelper", Process.THREAD_PRIORITY_FOREGROUND);
sHandlerThread.start();
}
return sHandlerThread.getLooper();
}
private static Handler getHandler(Context context) {
if (sHandler == null) {
sHandler = new Handler(getBackgroundLooper(),
sHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(),
new UiCallbacks(context.getApplicationContext()));
}
return sHandler;

View File

@ -16,13 +16,14 @@
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.os.Process;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewTreeObserver.OnDrawListener;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherModel;
import java.util.ArrayList;
import java.util.concurrent.Executor;
@ -66,7 +67,7 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable,
@Override
public void execute(Runnable command) {
mTasks.add(command);
LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_BACKGROUND);
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
@Override
@ -108,7 +109,7 @@ public class ViewOnDrawExecutor implements Executor, OnDrawListener, Runnable,
if (mLauncher != null) {
mLauncher.clearPendingExecutor(this);
}
LauncherModel.setWorkerPriority(Process.THREAD_PRIORITY_DEFAULT);
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
}
protected boolean isCompleted() {

View File

@ -1,5 +1,7 @@
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -198,7 +200,7 @@ public class WallpaperOffsetInterpolator extends BroadcastReceiver {
private float mOffsetX;
public OffsetHandler(Context context) {
super(UiThreadHelper.getBackgroundLooper());
super(UI_HELPER_EXECUTOR.getLooper());
mInterpolator = Interpolators.DEACCEL_1_5;
mWM = WallpaperManager.getInstance(context);
}

View File

@ -18,11 +18,11 @@ package com.android.launcher3.views;
import static com.android.launcher3.LauncherAnimUtils.DRAWABLE_ALPHA;
import static com.android.launcher3.Utilities.getBadge;
import static com.android.launcher3.Utilities.getFullDrawable;
import static com.android.launcher3.Utilities.isRtl;
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -42,7 +42,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@ -51,11 +50,17 @@ import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
@ -67,13 +72,6 @@ import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.shortcuts.DeepShortcutView;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
/**
* A view that is created to look like another view with the purpose of creating fluid animations.
*/
@ -717,7 +715,7 @@ public class FloatingIconView extends View implements
@UiThread
public static IconLoadResult fetchIcon(Launcher l, View v, ItemInfo info, boolean isOpening) {
IconLoadResult result = new IconLoadResult();
new Handler(LauncherModel.getWorkerLooper()).postAtFrontOfQueue(() -> {
MODEL_EXECUTOR.getHandler().postAtFrontOfQueue(() -> {
RectF position = new RectF();
getLocationBoundsForView(l, v, isOpening, position);
getIconResult(l, v, info, position, result);

View File

@ -44,6 +44,7 @@ import com.android.launcher3.SimpleOnStylusPressListener;
import com.android.launcher3.StylusEventHelper;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer.TouchCompleteListener;
@ -96,7 +97,7 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
setBackgroundResource(R.drawable.widget_internal_focus_bg);
if (Utilities.ATLEAST_OREO) {
setExecutor(Utilities.THREAD_POOL_EXECUTOR);
setExecutor(Executors.THREAD_POOL_EXECUTOR);
}
if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
setOnLightBackground(true);
@ -332,12 +333,7 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
if (shouldRegisterAutoAdvance != mIsAutoAdvanceRegistered) {
mIsAutoAdvanceRegistered = shouldRegisterAutoAdvance;
if (mAutoAdvanceRunnable == null) {
mAutoAdvanceRunnable = new Runnable() {
@Override
public void run() {
runAutoAdvance();
}
};
mAutoAdvanceRunnable = this::runAutoAdvance;
}
handler.removeCallbacks(mAutoAdvanceRunnable);

View File

@ -19,12 +19,12 @@ import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static com.android.launcher3.tapl.LauncherInstrumentation.ContainerType;
import static com.android.launcher3.ui.TaplTestsLauncher3.getAppPackageName;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static org.junit.Assert.assertTrue;
import static java.lang.System.exit;
import android.app.Instrumentation;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@ -48,7 +48,6 @@ import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.model.AppLaunchTracker;
@ -56,6 +55,7 @@ import com.android.launcher3.tapl.LauncherInstrumentation;
import com.android.launcher3.tapl.TestHelpers;
import com.android.launcher3.testcomponent.TestCommandReceiver;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.rule.FailureWatcher;
@ -90,7 +90,7 @@ public abstract class AbstractLauncherUiTest {
public static final long DEFAULT_UI_TIMEOUT = 60000; // b/136278866
private static final String TAG = "AbstractLauncherUiTest";
protected MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
protected LooperExecutor mMainThreadExecutor = MAIN_EXECUTOR;
protected final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());
protected final LauncherInstrumentation mLauncher =
new LauncherInstrumentation(getInstrumentation());

View File

@ -1,8 +1,8 @@
package com.android.launcher3.util;
import androidx.test.uiautomator.UiObject2;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import com.android.launcher3.MainThreadExecutor;
import androidx.test.uiautomator.UiObject2;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -16,7 +16,7 @@ public interface Condition {
* Converts the condition to be run on UI thread.
*/
static Condition runOnUiThread(final Condition condition) {
final MainThreadExecutor executor = new MainThreadExecutor();
final LooperExecutor executor = MAIN_EXECUTOR;
return () -> {
final AtomicBoolean value = new AtomicBoolean(false);
final Throwable[] exceptions = new Throwable[1];

View File

@ -16,6 +16,7 @@
package com.android.launcher3.util;
import static com.android.launcher3.util.Executors.createAndStartNewLooper;
import static com.android.launcher3.util.RaceConditionTracker.ENTER_POSTFIX;
import static com.android.launcher3.util.RaceConditionTracker.EXIT_POSTFIX;
@ -23,7 +24,6 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import java.util.ArrayList;
@ -72,9 +72,7 @@ public class RaceConditionReproducer implements RaceConditionTracker.EventProces
private static final Handler POSTPONED_EVENT_RESUME_HANDLER = createEventResumeHandler();
private static Handler createEventResumeHandler() {
final HandlerThread thread = new HandlerThread("RaceConditionEventResumer");
thread.start();
return new Handler(thread.getLooper());
return new Handler(createAndStartNewLooper("RaceConditionEventResumer"));
}
/**