Merge "Fixing model thread priority getting set to background while loading" into main
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index b8f6424..119a6b1 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.icons.cache.CacheLookupFlag.DEFAULT_LOOKUP_FLAG;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LooperExecutor.CALLER_ICON_CACHE;
import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
import static java.util.stream.Collectors.groupingBy;
@@ -35,7 +36,6 @@
import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.os.Looper;
-import android.os.Process;
import android.os.Trace;
import android.os.UserHandle;
import android.text.TextUtils;
@@ -204,7 +204,7 @@
Runnable endRunnable;
if (Looper.myLooper() == Looper.getMainLooper()) {
if (mPendingIconRequestCount <= 0) {
- MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+ MODEL_EXECUTOR.elevatePriority(CALLER_ICON_CACHE);
}
mPendingIconRequestCount++;
endRunnable = this::onIconRequestEnd;
@@ -221,7 +221,7 @@
private void onIconRequestEnd() {
mPendingIconRequestCount--;
if (mPendingIconRequestCount <= 0) {
- MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+ MODEL_EXECUTOR.restorePriority(CALLER_ICON_CACHE);
}
}
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 3ee8b87..a2ca6b6 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -28,7 +28,6 @@
import static java.util.Collections.emptyList;
-import android.os.Process;
import android.os.Trace;
import android.util.Log;
import android.util.Pair;
@@ -352,14 +351,8 @@
onCompleteSignal.executeAllAndDestroy();
}
- executeCallbacksTask(
- c -> {
- if (!enableWorkspaceInflation()) {
- MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- }
- c.onInitialBindComplete(currentScreenIds, pendingTasks, onCompleteSignal,
- workspaceItemCount, isBindSync);
- }, mUiExecutor);
+ executeCallbacksTask(c -> c.onInitialBindComplete(currentScreenIds, pendingTasks,
+ onCompleteSignal, workspaceItemCount, isBindSync), mUiExecutor);
}
private void setupPendingBind(
@@ -369,12 +362,8 @@
executeCallbacksTask(c -> c.bindStringCache(cacheClone), pendingExecutor);
executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor);
- pendingExecutor.execute(
- () -> {
- MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
- ItemInstallQueue.INSTANCE.get(mApp.getContext())
- .resumeModelPush(FLAG_LOADER_RUNNING);
- });
+ pendingExecutor.execute(() -> ItemInstallQueue.INSTANCE.get(mApp.getContext())
+ .resumeModelPush(FLAG_LOADER_RUNNING));
}
/**
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index c1ee69b..d44b289 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -36,6 +36,7 @@
import static com.android.launcher3.model.ModelUtils.currentScreenContentFilter;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LooperExecutor.CALLER_LOADER_TASK;
import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission;
import android.appwidget.AppWidgetProviderInfo;
@@ -251,6 +252,7 @@
}
TraceHelper.INSTANCE.beginSection(TAG);
+ MODEL_EXECUTOR.elevatePriority(CALLER_LOADER_TASK);
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
mIsRestoreFromBackup =
LauncherPrefs.get(mApp.getContext()).get(IS_FIRST_LOAD_AFTER_RESTORE);
@@ -403,6 +405,7 @@
memoryLogger.printLogs();
throw e;
}
+ MODEL_EXECUTOR.restorePriority(CALLER_LOADER_TASK);
TraceHelper.INSTANCE.endSection();
}
diff --git a/src/com/android/launcher3/util/LooperExecutor.kt b/src/com/android/launcher3/util/LooperExecutor.kt
index f5ba906..6ff528d 100644
--- a/src/com/android/launcher3/util/LooperExecutor.kt
+++ b/src/com/android/launcher3/util/LooperExecutor.kt
@@ -19,8 +19,11 @@
import android.os.HandlerThread
import android.os.Looper
import android.os.Process
+import android.os.Process.THREAD_PRIORITY_FOREGROUND
+import androidx.annotation.IntDef
import java.util.concurrent.AbstractExecutorService
import java.util.concurrent.TimeUnit
+import kotlin.annotation.AnnotationRetention.SOURCE
/** Extension of [AbstractExecutorService] which executed on a provided looper. */
class LooperExecutor(looper: Looper, private val defaultPriority: Int) : AbstractExecutorService() {
@@ -40,6 +43,8 @@
val looper: Looper
get() = handler.looper
+ @ElevationCaller private var elevationFlags: Int = 0
+
override fun execute(runnable: Runnable) {
if (handler.looper == Looper.myLooper()) {
runnable.run()
@@ -73,16 +78,31 @@
}
/**
- * 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
+ * Increases the priority of the thread for the [caller]. Multiple calls with same caller are
+ * ignored. The priority is reset once wall callers have restored priority
*/
- fun setThreadPriority(priority: Int) {
- Process.setThreadPriority((thread as HandlerThread).threadId, priority)
+ fun elevatePriority(@ElevationCaller caller: Int) {
+ val wasElevated = elevationFlags != 0
+ elevationFlags = elevationFlags.or(caller)
+ if (elevationFlags != 0 && !wasElevated)
+ Process.setThreadPriority(
+ (thread as HandlerThread).threadId,
+ THREAD_PRIORITY_FOREGROUND,
+ )
}
+ /** Restores to default priority if it was previously elevated */
+ fun restorePriority(@ElevationCaller caller: Int) {
+ val wasElevated = elevationFlags != 0
+ elevationFlags = elevationFlags.and(caller.inv())
+ if (elevationFlags == 0 && wasElevated)
+ Process.setThreadPriority((thread as HandlerThread).threadId, defaultPriority)
+ }
+
+ @Retention(SOURCE)
+ @IntDef(value = [CALLER_LOADER_TASK, CALLER_ICON_CACHE], flag = true)
+ annotation class ElevationCaller
+
companion object {
/** Utility method to get a started handler thread statically with the provided priority */
@JvmOverloads
@@ -91,5 +111,8 @@
name: String,
priority: Int = Process.THREAD_PRIORITY_DEFAULT,
): Looper = HandlerThread(name, priority).apply { start() }.looper
+
+ const val CALLER_LOADER_TASK = 1 shl 0
+ const val CALLER_ICON_CACHE = 1 shl 1
}
}