Moving LooperExecutor to kotlin

> Will improve priority changes in a followup cl

Bug: 396250724
Flag: EXEMPT refactor
Test: Presubmit
Change-Id: Ic9646e9b1b8faf80996f6e63159e8abbf00fc0b7
diff --git a/src/com/android/launcher3/LauncherModel.kt b/src/com/android/launcher3/LauncherModel.kt
index 6e4276d..7871cce 100644
--- a/src/com/android/launcher3/LauncherModel.kt
+++ b/src/com/android/launcher3/LauncherModel.kt
@@ -304,7 +304,7 @@
                     launcherBinder.bindWidgets()
                     return true
                 } else {
-                    mLoaderTask =
+                    val task =
                         LoaderTask(
                             mApp,
                             mBgAllAppsList,
@@ -313,10 +313,11 @@
                             launcherBinder,
                             widgetsFilterDataProvider,
                         )
+                    mLoaderTask = task
 
                     // Always post the loader task, instead of running directly
                     // (even on same thread) so that we exit any nested synchronized blocks
-                    MODEL_EXECUTOR.post(mLoaderTask)
+                    MODEL_EXECUTOR.post(task)
                 }
             }
         }
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 9f99e8f..f09cd75 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -199,7 +199,7 @@
     private void onIconRequestEnd() {
         mPendingIconRequestCount--;
         if (mPendingIconRequestCount <= 0) {
-            MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+            MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
         }
     }
 
diff --git a/src/com/android/launcher3/logging/FileLog.java b/src/com/android/launcher3/logging/FileLog.java
index 924a440..5b25418 100644
--- a/src/com/android/launcher3/logging/FileLog.java
+++ b/src/com/android/launcher3/logging/FileLog.java
@@ -1,6 +1,6 @@
 package com.android.launcher3.logging;
 
-import static com.android.launcher3.util.Executors.createAndStartNewLooper;
+import static com.android.launcher3.util.LooperExecutor.createAndStartNewLooper;
 
 import android.os.Handler;
 import android.os.HandlerThread;
diff --git a/src/com/android/launcher3/util/Executors.java b/src/com/android/launcher3/util/Executors.java
index c622b71..296fc8a 100644
--- a/src/com/android/launcher3/util/Executors.java
+++ b/src/com/android/launcher3/util/Executors.java
@@ -16,8 +16,8 @@
 package com.android.launcher3.util;
 
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
 
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Process;
 
@@ -51,21 +51,20 @@
     /**
      * An {@link LooperExecutor} to be used with async task where order is important.
      */
-    public static final LooperExecutor ORDERED_BG_EXECUTOR = new LooperExecutor(
-            createAndStartNewLooper("BackgroundExecutor", THREAD_PRIORITY_BACKGROUND));
+    public static final LooperExecutor ORDERED_BG_EXECUTOR =
+            new LooperExecutor("BackgroundExecutor", THREAD_PRIORITY_BACKGROUND);
 
     /**
      * Returns the executor for running tasks on the main thread.
      */
     public static final LooperExecutor MAIN_EXECUTOR =
-            new LooperExecutor(Looper.getMainLooper());
+            new LooperExecutor(Looper.getMainLooper(), THREAD_PRIORITY_FOREGROUND);
 
     /**
      * A background executor for using time sensitive actions where user is waiting for response.
      */
     public static final LooperExecutor UI_HELPER_EXECUTOR =
-            new LooperExecutor(
-                    createAndStartNewLooper("UiThreadHelper", Process.THREAD_PRIORITY_FOREGROUND));
+            new LooperExecutor("UiThreadHelper", Process.THREAD_PRIORITY_FOREGROUND);
 
 
     /** A background executor to preinflate views. */
@@ -75,26 +74,9 @@
                             "preinflate-allapps-icons", THREAD_PRIORITY_BACKGROUND));
 
     /**
-     * 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();
-    }
-
-    /**
      * 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"));
+    public static final LooperExecutor MODEL_EXECUTOR = new LooperExecutor("launcher-loader");
 
     /**
      * Returns and caches a single thread executor for a given package.
@@ -102,9 +84,7 @@
      * @param packageName Package associated with the executor.
      */
     public static LooperExecutor getPackageExecutor(String packageName) {
-        return PACKAGE_EXECUTORS.computeIfAbsent(
-                packageName, p -> new LooperExecutor(
-                        createAndStartNewLooper(p, Process.THREAD_PRIORITY_DEFAULT)));
+        return PACKAGE_EXECUTORS.computeIfAbsent(packageName, LooperExecutor::new);
     }
 
     /**
diff --git a/src/com/android/launcher3/util/LooperExecutor.java b/src/com/android/launcher3/util/LooperExecutor.java
deleted file mode 100644
index 3a8a13c..0000000
--- a/src/com/android/launcher3/util/LooperExecutor.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2017 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.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Process;
-
-import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Extension of {@link AbstractExecutorService} which executed on a provided looper.
- */
-public class LooperExecutor extends AbstractExecutorService {
-
-    private final Handler mHandler;
-
-    public LooperExecutor(Looper looper) {
-        mHandler = new Handler(looper);
-    }
-
-    public Handler getHandler() {
-        return mHandler;
-    }
-
-    @Override
-    public void execute(Runnable runnable) {
-        if (getHandler().getLooper() == Looper.myLooper()) {
-            runnable.run();
-        } else {
-            getHandler().post(runnable);
-        }
-    }
-
-    /**
-     * Same as execute, but never runs the action inline.
-     */
-    public void post(Runnable runnable) {
-        getHandler().post(runnable);
-    }
-
-    /**
-     * Not supported and throws an exception when used.
-     */
-    @Override
-    @Deprecated
-    public void shutdown() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Not supported and throws an exception when used.
-     */
-    @Override
-    @Deprecated
-    public List<Runnable> shutdownNow() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public boolean isShutdown() {
-        return false;
-    }
-
-    @Override
-    public boolean isTerminated() {
-        return false;
-    }
-
-    /**
-     * Not supported and throws an exception when used.
-     */
-    @Override
-    @Deprecated
-    public boolean awaitTermination(long l, TimeUnit timeUnit) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Returns the thread for this executor
-     */
-    public Thread getThread() {
-        return getHandler().getLooper().getThread();
-    }
-
-    /**
-     * Returns the looper for this executor
-     */
-    public Looper getLooper() {
-        return getHandler().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);
-    }
-}
diff --git a/src/com/android/launcher3/util/LooperExecutor.kt b/src/com/android/launcher3/util/LooperExecutor.kt
new file mode 100644
index 0000000..f5ba906
--- /dev/null
+++ b/src/com/android/launcher3/util/LooperExecutor.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 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.Handler
+import android.os.HandlerThread
+import android.os.Looper
+import android.os.Process
+import java.util.concurrent.AbstractExecutorService
+import java.util.concurrent.TimeUnit
+
+/** Extension of [AbstractExecutorService] which executed on a provided looper. */
+class LooperExecutor(looper: Looper, private val defaultPriority: Int) : AbstractExecutorService() {
+    val handler: Handler = Handler(looper)
+
+    @JvmOverloads
+    constructor(
+        name: String,
+        defaultPriority: Int = Process.THREAD_PRIORITY_DEFAULT,
+    ) : this(createAndStartNewLooper(name, defaultPriority), defaultPriority)
+
+    /** Returns the thread for this executor */
+    val thread: Thread
+        get() = handler.looper.thread
+
+    /** Returns the looper for this executor */
+    val looper: Looper
+        get() = handler.looper
+
+    override fun execute(runnable: Runnable) {
+        if (handler.looper == Looper.myLooper()) {
+            runnable.run()
+        } else {
+            handler.post(runnable)
+        }
+    }
+
+    /** Same as execute, but never runs the action inline. */
+    fun post(runnable: Runnable) {
+        handler.post(runnable)
+    }
+
+    @Deprecated("Not supported and throws an exception when used")
+    override fun shutdown() {
+        throw UnsupportedOperationException()
+    }
+
+    @Deprecated("Not supported and throws an exception when used.")
+    override fun shutdownNow(): List<Runnable> {
+        throw UnsupportedOperationException()
+    }
+
+    override fun isShutdown() = false
+
+    override fun isTerminated() = false
+
+    @Deprecated("Not supported and throws an exception when used.")
+    override fun awaitTermination(l: Long, timeUnit: TimeUnit): Boolean {
+        throw UnsupportedOperationException()
+    }
+
+    /**
+     * 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
+     */
+    fun setThreadPriority(priority: Int) {
+        Process.setThreadPriority((thread as HandlerThread).threadId, priority)
+    }
+
+    companion object {
+        /** Utility method to get a started handler thread statically with the provided priority */
+        @JvmOverloads
+        @JvmStatic
+        fun createAndStartNewLooper(
+            name: String,
+            priority: Int = Process.THREAD_PRIORITY_DEFAULT,
+        ): Looper = HandlerThread(name, priority).apply { start() }.looper
+    }
+}