diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.java
deleted file mode 100644
index aeae5dd..0000000
--- a/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2024 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.virtualization.terminal;
-
-import android.Manifest;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-
-import androidx.appcompat.app.AppCompatActivity;
-
-public abstract class BaseActivity extends AppCompatActivity {
-    private static final int POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE = 101;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        NotificationManager notificationManager = getSystemService(NotificationManager.class);
-        if (notificationManager.getNotificationChannel(this.getPackageName()) == null) {
-            NotificationChannel channel =
-                    new NotificationChannel(
-                            this.getPackageName(),
-                            getString(R.string.app_name),
-                            NotificationManager.IMPORTANCE_HIGH);
-            notificationManager.createNotificationChannel(channel);
-        }
-
-        if (!(this instanceof ErrorActivity)) {
-            Thread currentThread = Thread.currentThread();
-            if (!(currentThread.getUncaughtExceptionHandler()
-                    instanceof TerminalExceptionHandler)) {
-                currentThread.setUncaughtExceptionHandler(
-                        new TerminalExceptionHandler(getApplicationContext()));
-            }
-        }
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-
-        if (getApplicationContext().checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)
-                != PackageManager.PERMISSION_GRANTED) {
-            requestPermissions(
-                    new String[] {Manifest.permission.POST_NOTIFICATIONS},
-                    POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE);
-        }
-    }
-}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt
new file mode 100644
index 0000000..e7ac8d9
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2024 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.virtualization.terminal
+
+import android.Manifest
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.pm.PackageManager
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+
+abstract class BaseActivity : AppCompatActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        val notificationManager =
+            getSystemService<NotificationManager>(NotificationManager::class.java)
+        if (notificationManager.getNotificationChannel(this.packageName) == null) {
+            val channel =
+                NotificationChannel(
+                    this.packageName,
+                    getString(R.string.app_name),
+                    NotificationManager.IMPORTANCE_HIGH,
+                )
+            notificationManager.createNotificationChannel(channel)
+        }
+
+        if (this !is ErrorActivity) {
+            val currentThread = Thread.currentThread()
+            if (currentThread.uncaughtExceptionHandler !is TerminalExceptionHandler) {
+                currentThread.uncaughtExceptionHandler =
+                    TerminalExceptionHandler(applicationContext)
+            }
+        }
+    }
+
+    public override fun onResume() {
+        super.onResume()
+
+        if (
+            applicationContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) !=
+                PackageManager.PERMISSION_GRANTED
+        ) {
+            requestPermissions(
+                arrayOf<String>(Manifest.permission.POST_NOTIFICATIONS),
+                POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE,
+            )
+        }
+    }
+
+    companion object {
+        private const val POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE = 101
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.java
deleted file mode 100644
index 1c62572..0000000
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright 2024 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.virtualization.terminal;
-
-import static com.android.virtualization.terminal.MainActivity.TAG;
-
-import android.annotation.MainThread;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.ConditionVariable;
-import android.os.FileUtils;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.text.format.Formatter;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.TextView;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import com.google.android.material.progressindicator.LinearProgressIndicator;
-import com.google.android.material.snackbar.Snackbar;
-
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-
-public class InstallerActivity extends BaseActivity {
-    private static final long ESTIMATED_IMG_SIZE_BYTES = FileUtils.parseSize("550MB");
-
-    private CheckBox mWaitForWifiCheckbox;
-    private TextView mInstallButton;
-
-    private IInstallerService mService;
-    private ServiceConnection mInstallerServiceConnection;
-    private InstallProgressListener mInstallProgressListener;
-    private boolean mInstallRequested;
-    private ConditionVariable mInstallCompleted = new ConditionVariable();
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setResult(RESULT_CANCELED);
-
-        mInstallProgressListener = new InstallProgressListener(this);
-
-        setContentView(R.layout.activity_installer);
-        updateSizeEstimation(ESTIMATED_IMG_SIZE_BYTES);
-        measureImageSizeAndUpdateDescription();
-
-        mWaitForWifiCheckbox = (CheckBox) findViewById(R.id.installer_wait_for_wifi_checkbox);
-        mInstallButton = (TextView) findViewById(R.id.installer_install_button);
-
-        mInstallButton.setOnClickListener(
-                (event) -> {
-                    requestInstall();
-                });
-
-        Intent intent = new Intent(this, InstallerService.class);
-        mInstallerServiceConnection = new InstallerServiceConnection(this);
-        if (!bindService(intent, mInstallerServiceConnection, Context.BIND_AUTO_CREATE)) {
-            handleInternalError(new Exception("Failed to connect to installer service"));
-        }
-    }
-
-    private void updateSizeEstimation(long est) {
-        String desc =
-                getString(
-                        R.string.installer_desc_text_format,
-                        Formatter.formatShortFileSize(this, est));
-        runOnUiThread(
-                () -> {
-                    TextView view = (TextView) findViewById(R.id.installer_desc);
-                    view.setText(desc);
-                });
-    }
-
-    private void measureImageSizeAndUpdateDescription() {
-        new Thread(
-                        () -> {
-                            long est;
-                            try {
-                                est = ImageArchive.getDefault().getSize();
-                            } catch (IOException e) {
-                                Log.w(TAG, "Failed to measure image size.", e);
-                                return;
-                            }
-                            updateSizeEstimation(est);
-                        })
-                .start();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-
-        if (Build.isDebuggable() && ImageArchive.fromSdCard().exists()) {
-            showSnackbar("Auto installing", Snackbar.LENGTH_LONG);
-            requestInstall();
-        }
-    }
-
-    @Override
-    public void onDestroy() {
-        if (mInstallerServiceConnection != null) {
-            unbindService(mInstallerServiceConnection);
-            mInstallerServiceConnection = null;
-        }
-
-        super.onDestroy();
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BUTTON_START) {
-            requestInstall();
-            return true;
-        }
-        return super.onKeyUp(keyCode, event);
-    }
-
-    @VisibleForTesting
-    public boolean waitForInstallCompleted(long timeoutMillis) {
-        return mInstallCompleted.block(timeoutMillis);
-    }
-
-    private void showSnackbar(String message, int length) {
-        Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), message, length);
-        snackbar.setAnchorView(mWaitForWifiCheckbox);
-        snackbar.show();
-    }
-
-    public void handleInternalError(Exception e) {
-        if (Build.isDebuggable()) {
-            showSnackbar(
-                    e.getMessage() + ". File a bugreport to go/ferrochrome-bug",
-                    Snackbar.LENGTH_INDEFINITE);
-        }
-        Log.e(TAG, "Internal error", e);
-        finishWithResult(RESULT_CANCELED);
-    }
-
-    private void finishWithResult(int resultCode) {
-        if (resultCode == RESULT_OK) {
-            mInstallCompleted.open();
-        }
-        setResult(resultCode);
-        finish();
-    }
-
-    private void setInstallEnabled(boolean enable) {
-        mInstallButton.setEnabled(enable);
-        mWaitForWifiCheckbox.setEnabled(enable);
-        LinearProgressIndicator progressBar = findViewById(R.id.installer_progress);
-        if (enable) {
-            progressBar.setVisibility(View.INVISIBLE);
-        } else {
-            progressBar.setVisibility(View.VISIBLE);
-        }
-
-        int resId =
-                enable
-                        ? R.string.installer_install_button_enabled_text
-                        : R.string.installer_install_button_disabled_text;
-        mInstallButton.setText(getString(resId));
-    }
-
-    @MainThread
-    private void requestInstall() {
-        setInstallEnabled(/* enable= */ false);
-
-        if (mService != null) {
-            try {
-                mService.requestInstall(mWaitForWifiCheckbox.isChecked());
-            } catch (RemoteException e) {
-                handleInternalError(e);
-            }
-        } else {
-            Log.d(TAG, "requestInstall() is called, but not yet connected");
-            mInstallRequested = true;
-        }
-    }
-
-    @MainThread
-    public void handleInstallerServiceConnected() {
-        try {
-            mService.setProgressListener(mInstallProgressListener);
-            if (mService.isInstalled()) {
-                // Finishing this activity will trigger MainActivity::onResume(),
-                // and VM will be started from there.
-                finishWithResult(RESULT_OK);
-                return;
-            }
-
-            if (mInstallRequested) {
-                requestInstall();
-            } else if (mService.isInstalling()) {
-                setInstallEnabled(false);
-            }
-        } catch (RemoteException e) {
-            handleInternalError(e);
-        }
-    }
-
-    @MainThread
-    public void handleInstallerServiceDisconnected() {
-        handleInternalError(new Exception("InstallerService is destroyed while in use"));
-    }
-
-    @MainThread
-    private void handleInstallError(String displayText) {
-        showSnackbar(displayText, Snackbar.LENGTH_LONG);
-        setInstallEnabled(true);
-    }
-
-    private static class InstallProgressListener extends IInstallProgressListener.Stub {
-        private final WeakReference<InstallerActivity> mActivity;
-
-        InstallProgressListener(InstallerActivity activity) {
-            mActivity = new WeakReference<>(activity);
-        }
-
-        @Override
-        public void onCompleted() {
-            InstallerActivity activity = mActivity.get();
-            if (activity == null) {
-                // Ignore incoming connection or disconnection after activity is destroyed.
-                return;
-            }
-
-            // MainActivity will be resume and handle rest of progress.
-            activity.finishWithResult(RESULT_OK);
-        }
-
-        @Override
-        public void onError(String displayText) {
-            InstallerActivity context = mActivity.get();
-            if (context == null) {
-                // Ignore incoming connection or disconnection after activity is destroyed.
-                return;
-            }
-
-            context.runOnUiThread(
-                    () -> {
-                        InstallerActivity activity = mActivity.get();
-                        if (activity == null) {
-                            // Ignore incoming connection or disconnection after activity is
-                            // destroyed.
-                            return;
-                        }
-
-                        activity.handleInstallError(displayText);
-                    });
-        }
-    }
-
-    @MainThread
-    public static final class InstallerServiceConnection implements ServiceConnection {
-        private final WeakReference<InstallerActivity> mActivity;
-
-        InstallerServiceConnection(InstallerActivity activity) {
-            mActivity = new WeakReference<>(activity);
-        }
-
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            InstallerActivity activity = mActivity.get();
-            if (activity == null || activity.mInstallerServiceConnection == null) {
-                // Ignore incoming connection or disconnection after activity is destroyed.
-                return;
-            }
-            if (service == null) {
-                activity.handleInternalError(new Exception("service shouldn't be null"));
-            }
-
-            activity.mService = IInstallerService.Stub.asInterface(service);
-            activity.handleInstallerServiceConnected();
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            InstallerActivity activity = mActivity.get();
-            if (activity == null || activity.mInstallerServiceConnection == null) {
-                // Ignore incoming connection or disconnection after activity is destroyed.
-                return;
-            }
-
-            if (activity.mInstallerServiceConnection != null) {
-                activity.unbindService(activity.mInstallerServiceConnection);
-                activity.mInstallerServiceConnection = null;
-            }
-            activity.handleInstallerServiceDisconnected();
-        }
-    }
-}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.kt
new file mode 100644
index 0000000..3eff09b
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.kt
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2024 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.virtualization.terminal
+
+import android.annotation.MainThread
+import android.content.ComponentName
+import android.content.Intent
+import android.content.ServiceConnection
+import android.os.Build
+import android.os.Bundle
+import android.os.ConditionVariable
+import android.os.FileUtils
+import android.os.IBinder
+import android.os.RemoteException
+import android.text.format.Formatter
+import android.util.Log
+import android.view.KeyEvent
+import android.view.View
+import android.widget.CheckBox
+import android.widget.TextView
+import com.android.internal.annotations.VisibleForTesting
+import com.android.virtualization.terminal.ImageArchive.Companion.fromSdCard
+import com.android.virtualization.terminal.ImageArchive.Companion.getDefault
+import com.android.virtualization.terminal.InstallerActivity.InstallProgressListener
+import com.android.virtualization.terminal.InstallerActivity.InstallerServiceConnection
+import com.android.virtualization.terminal.MainActivity.TAG
+import com.google.android.material.progressindicator.LinearProgressIndicator
+import com.google.android.material.snackbar.Snackbar
+import java.io.IOException
+import java.lang.Exception
+import java.lang.ref.WeakReference
+
+class InstallerActivity : BaseActivity() {
+    private lateinit var waitForWifiCheckbox: CheckBox
+    private lateinit var installButton: TextView
+
+    private var service: IInstallerService? = null
+    private var installerServiceConnection: ServiceConnection? = null
+    private lateinit var installProgressListener: InstallProgressListener
+    private var installRequested = false
+    private val installCompleted = ConditionVariable()
+
+    public override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setResult(RESULT_CANCELED)
+
+        installProgressListener = InstallProgressListener(this)
+
+        setContentView(R.layout.activity_installer)
+        updateSizeEstimation(ESTIMATED_IMG_SIZE_BYTES)
+        measureImageSizeAndUpdateDescription()
+
+        waitForWifiCheckbox = findViewById<CheckBox>(R.id.installer_wait_for_wifi_checkbox)
+        installButton = findViewById<TextView>(R.id.installer_install_button)
+
+        installButton.setOnClickListener(View.OnClickListener { requestInstall() })
+
+        val intent = Intent(this, InstallerService::class.java)
+        installerServiceConnection = InstallerServiceConnection(this)
+        if (!bindService(intent, installerServiceConnection!!, BIND_AUTO_CREATE)) {
+            handleInternalError(Exception("Failed to connect to installer service"))
+        }
+    }
+
+    private fun updateSizeEstimation(est: Long) {
+        val desc =
+            getString(R.string.installer_desc_text_format, Formatter.formatShortFileSize(this, est))
+        runOnUiThread {
+            val view = findViewById<TextView>(R.id.installer_desc)
+            view.text = desc
+        }
+    }
+
+    private fun measureImageSizeAndUpdateDescription() {
+        Thread {
+                val est: Long =
+                    try {
+                        getDefault().getSize()
+                    } catch (e: IOException) {
+                        Log.w(TAG, "Failed to measure image size.", e)
+                        return@Thread
+                    }
+                updateSizeEstimation(est)
+            }
+            .start()
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        if (Build.isDebuggable() && fromSdCard().exists()) {
+            showSnackBar("Auto installing", Snackbar.LENGTH_LONG)
+            requestInstall()
+        }
+    }
+
+    public override fun onDestroy() {
+        if (installerServiceConnection != null) {
+            unbindService(installerServiceConnection!!)
+            installerServiceConnection = null
+        }
+
+        super.onDestroy()
+    }
+
+    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
+        if (keyCode == KeyEvent.KEYCODE_BUTTON_START) {
+            requestInstall()
+            return true
+        }
+        return super.onKeyUp(keyCode, event)
+    }
+
+    @VisibleForTesting
+    fun waitForInstallCompleted(timeoutMillis: Long): Boolean {
+        return installCompleted.block(timeoutMillis)
+    }
+
+    private fun showSnackBar(message: String, length: Int) {
+        val snackBar = Snackbar.make(findViewById<View>(R.id.content), message, length)
+        snackBar.anchorView = waitForWifiCheckbox
+        snackBar.show()
+    }
+
+    fun handleInternalError(e: Exception) {
+        if (Build.isDebuggable()) {
+            showSnackBar(
+                e.message + ". File a bugreport to go/ferrochrome-bug",
+                Snackbar.LENGTH_INDEFINITE,
+            )
+        }
+        Log.e(TAG, "Internal error", e)
+        finishWithResult(RESULT_CANCELED)
+    }
+
+    private fun finishWithResult(resultCode: Int) {
+        if (resultCode == RESULT_OK) {
+            installCompleted.open()
+        }
+        setResult(resultCode)
+        finish()
+    }
+
+    private fun setInstallEnabled(enabled: Boolean) {
+        installButton.setEnabled(enabled)
+        waitForWifiCheckbox.setEnabled(enabled)
+        val progressBar = findViewById<LinearProgressIndicator>(R.id.installer_progress)
+        progressBar.visibility = if (enabled) View.INVISIBLE else View.VISIBLE
+
+        val resId =
+            if (enabled) R.string.installer_install_button_enabled_text
+            else R.string.installer_install_button_disabled_text
+        installButton.text = getString(resId)
+    }
+
+    @MainThread
+    private fun requestInstall() {
+        setInstallEnabled(/* enabled= */ false)
+
+        if (service != null) {
+            try {
+                service!!.requestInstall(waitForWifiCheckbox.isChecked)
+            } catch (e: RemoteException) {
+                handleInternalError(e)
+            }
+        } else {
+            Log.d(TAG, "requestInstall() is called, but not yet connected")
+            installRequested = true
+        }
+    }
+
+    @MainThread
+    fun handleInstallerServiceConnected() {
+        try {
+            service!!.setProgressListener(installProgressListener)
+            if (service!!.isInstalled()) {
+                // Finishing this activity will trigger MainActivity::onResume(),
+                // and VM will be started from there.
+                finishWithResult(RESULT_OK)
+                return
+            }
+
+            if (installRequested) {
+                requestInstall()
+            } else if (service!!.isInstalling()) {
+                setInstallEnabled(false)
+            }
+        } catch (e: RemoteException) {
+            handleInternalError(e)
+        }
+    }
+
+    @MainThread
+    fun handleInstallerServiceDisconnected() {
+        handleInternalError(Exception("InstallerService is destroyed while in use"))
+    }
+
+    @MainThread
+    private fun handleInstallError(displayText: String) {
+        showSnackBar(displayText, Snackbar.LENGTH_LONG)
+        setInstallEnabled(true)
+    }
+
+    private class InstallProgressListener(activity: InstallerActivity) :
+        IInstallProgressListener.Stub() {
+        private val activity: WeakReference<InstallerActivity> =
+            WeakReference<InstallerActivity>(activity)
+
+        override fun onCompleted() {
+            val activity = activity.get()
+            if (activity == null) {
+                // Ignore incoming connection or disconnection after activity is destroyed.
+                return
+            }
+
+            // MainActivity will be resume and handle rest of progress.
+            activity.finishWithResult(RESULT_OK)
+        }
+
+        override fun onError(displayText: String) {
+            val context = activity.get()
+            if (context == null) {
+                // Ignore incoming connection or disconnection after activity is destroyed.
+                return
+            }
+
+            context.runOnUiThread {
+                val activity = activity.get()
+                if (activity == null) {
+                    // Ignore incoming connection or disconnection after activity is
+                    // destroyed.
+                    return@runOnUiThread
+                }
+                activity.handleInstallError(displayText)
+            }
+        }
+    }
+
+    @MainThread
+    class InstallerServiceConnection internal constructor(activity: InstallerActivity) :
+        ServiceConnection {
+        private val activity: WeakReference<InstallerActivity> =
+            WeakReference<InstallerActivity>(activity)
+
+        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
+            val activity = activity.get()
+            if (activity == null || activity.installerServiceConnection == null) {
+                // Ignore incoming connection or disconnection after activity is destroyed.
+                return
+            }
+            if (service == null) {
+                activity.handleInternalError(Exception("service shouldn't be null"))
+            }
+
+            activity.service = IInstallerService.Stub.asInterface(service)
+            activity.handleInstallerServiceConnected()
+        }
+
+        override fun onServiceDisconnected(name: ComponentName?) {
+            val activity = activity.get()
+            if (activity == null || activity.installerServiceConnection == null) {
+                // Ignore incoming connection or disconnection after activity is destroyed.
+                return
+            }
+
+            activity.unbindService(activity.installerServiceConnection!!)
+            activity.installerServiceConnection = null
+            activity.handleInstallerServiceDisconnected()
+        }
+    }
+
+    companion object {
+        private val ESTIMATED_IMG_SIZE_BYTES = FileUtils.parseSize("550MB")
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.java b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.java
deleted file mode 100644
index 66ab414..0000000
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.java
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright 2024 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.virtualization.terminal;
-
-import static com.android.virtualization.terminal.MainActivity.TAG;
-
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.ServiceInfo;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.os.Build;
-import android.os.IBinder;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.annotations.GuardedBy;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.nio.file.Path;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-public class InstallerService extends Service {
-    private static final int NOTIFICATION_ID = 1313; // any unique number among notifications
-
-    private final Object mLock = new Object();
-
-    private Notification mNotification;
-
-    @GuardedBy("mLock")
-    private boolean mIsInstalling;
-
-    @GuardedBy("mLock")
-    private boolean mHasWifi;
-
-    @GuardedBy("mLock")
-    private IInstallProgressListener mListener;
-
-    private ExecutorService mExecutorService;
-    private ConnectivityManager mConnectivityManager;
-    private MyNetworkCallback mNetworkCallback;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-
-        Intent intent = new Intent(this, MainActivity.class);
-        PendingIntent pendingIntent =
-                PendingIntent.getActivity(
-                        this, /* requestCode= */ 0, intent, PendingIntent.FLAG_IMMUTABLE);
-        mNotification =
-                new Notification.Builder(this, this.getPackageName())
-                        .setSilent(true)
-                        .setSmallIcon(R.drawable.ic_launcher_foreground)
-                        .setContentTitle(getString(R.string.installer_notif_title_text))
-                        .setContentText(getString(R.string.installer_notif_desc_text))
-                        .setOngoing(true)
-                        .setContentIntent(pendingIntent)
-                        .build();
-
-        mExecutorService =
-                Executors.newSingleThreadExecutor(
-                        new TerminalThreadFactory(getApplicationContext()));
-
-        mConnectivityManager = getSystemService(ConnectivityManager.class);
-        Network defaultNetwork = mConnectivityManager.getBoundNetworkForProcess();
-        if (defaultNetwork != null) {
-            NetworkCapabilities capability =
-                    mConnectivityManager.getNetworkCapabilities(defaultNetwork);
-            if (capability != null) {
-                mHasWifi = capability.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
-            }
-        }
-        mNetworkCallback = new MyNetworkCallback();
-        mConnectivityManager.registerDefaultNetworkCallback(mNetworkCallback);
-    }
-
-    @Nullable
-    @Override
-    public IBinder onBind(Intent intent) {
-        return new InstallerServiceImpl(this);
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        super.onStartCommand(intent, flags, startId);
-
-        Log.d(TAG, "Starting service ...");
-
-        return START_STICKY;
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-
-        Log.d(TAG, "Service is destroyed");
-        if (mExecutorService != null) {
-            mExecutorService.shutdown();
-        }
-        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
-    }
-
-    private void requestInstall(boolean isWifiOnly) {
-        synchronized (mLock) {
-            if (mIsInstalling) {
-                Log.i(TAG, "already installing..");
-                return;
-            } else {
-                Log.i(TAG, "installing..");
-                mIsInstalling = true;
-            }
-        }
-
-        // Make service to be long running, even after unbind() when InstallerActivity is destroyed
-        // The service will still be destroyed if task is remove.
-        startService(new Intent(this, InstallerService.class));
-        startForeground(
-                NOTIFICATION_ID, mNotification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
-
-        mExecutorService.execute(
-                () -> {
-                    boolean success = downloadFromSdcard() || downloadFromUrl(isWifiOnly);
-                    stopForeground(STOP_FOREGROUND_REMOVE);
-
-                    synchronized (mLock) {
-                        mIsInstalling = false;
-                    }
-                    if (success) {
-                        notifyCompleted();
-                    }
-                });
-    }
-
-    private boolean downloadFromSdcard() {
-        ImageArchive archive = ImageArchive.fromSdCard();
-
-        // Installing from sdcard is preferred, but only supported only in debuggable build.
-        if (Build.isDebuggable() && archive.exists()) {
-            Log.i(TAG, "trying to install /sdcard/linux/images.tar.gz");
-
-            Path dest = InstalledImage.getDefault(this).getInstallDir();
-            try {
-                archive.installTo(dest, null);
-                Log.i(TAG, "image is installed from /sdcard/linux/images.tar.gz");
-                return true;
-            } catch (IOException e) {
-                Log.i(TAG, "Failed to install /sdcard/linux/images.tar.gz", e);
-            }
-        } else {
-            Log.i(TAG, "Non-debuggable build doesn't support installation from /sdcard/linux");
-        }
-        return false;
-    }
-
-    private boolean checkForWifiOnly(boolean isWifiOnly) {
-        if (!isWifiOnly) {
-            return true;
-        }
-        synchronized (mLock) {
-            return mHasWifi;
-        }
-    }
-
-    // TODO(b/374015561): Support pause/resume download
-    private boolean downloadFromUrl(boolean isWifiOnly) {
-        if (!checkForWifiOnly(isWifiOnly)) {
-            Log.e(TAG, "Install isn't started because Wifi isn't available");
-            notifyError(getString(R.string.installer_error_no_wifi));
-            return false;
-        }
-
-        Path dest = InstalledImage.getDefault(this).getInstallDir();
-        try {
-            ImageArchive.fromInternet()
-                    .installTo(
-                            dest,
-                            is -> {
-                                WifiCheckInputStream filter = new WifiCheckInputStream(is);
-                                filter.setWifiOnly(isWifiOnly);
-                                return filter;
-                            });
-        } catch (WifiCheckInputStream.NoWifiException e) {
-            Log.e(TAG, "Install failed because of Wi-Fi is gone");
-            notifyError(getString(R.string.installer_error_no_wifi));
-            return false;
-        } catch (UnknownHostException | SocketException e) {
-            // Log.e() doesn't print stack trace for UnknownHostException
-            Log.e(TAG, "Install failed: " + e.getMessage(), e);
-            notifyError(getString(R.string.installer_error_network));
-            return false;
-        } catch (IOException e) {
-            Log.e(TAG, "Installation failed", e);
-            notifyError(getString(R.string.installer_error_unknown));
-            return false;
-        }
-        return true;
-    }
-
-    private void notifyError(String displayText) {
-        IInstallProgressListener listener;
-        synchronized (mLock) {
-            listener = mListener;
-        }
-
-        try {
-            listener.onError(displayText);
-        } catch (Exception e) {
-            // ignore. Activity may not exist.
-        }
-    }
-
-    private void notifyCompleted() {
-        IInstallProgressListener listener;
-        synchronized (mLock) {
-            listener = mListener;
-        }
-
-        try {
-            listener.onCompleted();
-        } catch (Exception e) {
-            // ignore. Activity may not exist.
-        }
-    }
-
-    private static final class InstallerServiceImpl extends IInstallerService.Stub {
-        // Holds weak reference to avoid Context leak
-        private final WeakReference<InstallerService> mService;
-
-        public InstallerServiceImpl(InstallerService service) {
-            mService = new WeakReference<>(service);
-        }
-
-        private InstallerService ensureServiceConnected() throws RuntimeException {
-            InstallerService service = mService.get();
-            if (service == null) {
-                throw new RuntimeException(
-                        "Internal error: Installer service is being accessed after destroyed");
-            }
-            return service;
-        }
-
-        @Override
-        public void requestInstall(boolean isWifiOnly) {
-            InstallerService service = ensureServiceConnected();
-            synchronized (service.mLock) {
-                service.requestInstall(isWifiOnly);
-            }
-        }
-
-        @Override
-        public void setProgressListener(IInstallProgressListener listener) {
-            InstallerService service = ensureServiceConnected();
-            synchronized (service.mLock) {
-                service.mListener = listener;
-            }
-        }
-
-        @Override
-        public boolean isInstalling() {
-            InstallerService service = ensureServiceConnected();
-            synchronized (service.mLock) {
-                return service.mIsInstalling;
-            }
-        }
-
-        @Override
-        public boolean isInstalled() {
-            InstallerService service = ensureServiceConnected();
-            synchronized (service.mLock) {
-                return !service.mIsInstalling && InstalledImage.getDefault(service).isInstalled();
-            }
-        }
-    }
-
-    private final class WifiCheckInputStream extends InputStream {
-        private static final int READ_BYTES = 1024;
-
-        private final InputStream mInputStream;
-        private boolean mIsWifiOnly;
-
-        public WifiCheckInputStream(InputStream is) {
-            super();
-            mInputStream = is;
-        }
-
-        public void setWifiOnly(boolean isWifiOnly) {
-            mIsWifiOnly = isWifiOnly;
-        }
-
-        @Override
-        public int read(byte[] buf, int offset, int numToRead) throws IOException {
-            int totalRead = 0;
-            while (numToRead > 0) {
-                if (!checkForWifiOnly(mIsWifiOnly)) {
-                    throw new NoWifiException();
-                }
-                int read =
-                        mInputStream.read(buf, offset + totalRead, Math.min(READ_BYTES, numToRead));
-                if (read <= 0) {
-                    break;
-                }
-                totalRead += read;
-                numToRead -= read;
-            }
-            return totalRead;
-        }
-
-        @Override
-        public int read() throws IOException {
-            if (!checkForWifiOnly(mIsWifiOnly)) {
-                throw new NoWifiException();
-            }
-            return mInputStream.read();
-        }
-
-        private static final class NoWifiException extends SocketException {
-            // empty
-        }
-    }
-
-    private final class MyNetworkCallback extends ConnectivityManager.NetworkCallback {
-        @Override
-        public void onCapabilitiesChanged(
-                @NonNull Network network, @NonNull NetworkCapabilities capability) {
-            synchronized (mLock) {
-                mHasWifi = capability.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
-            }
-        }
-    }
-}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
new file mode 100644
index 0000000..9bd6a13
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2024 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.virtualization.terminal
+
+import android.app.Notification
+import android.app.PendingIntent
+import android.app.Service
+import android.content.Intent
+import android.content.pm.ServiceInfo
+import android.net.ConnectivityManager
+import android.net.Network
+import android.net.NetworkCapabilities
+import android.os.Build
+import android.os.IBinder
+import android.util.Log
+import com.android.internal.annotations.GuardedBy
+import com.android.virtualization.terminal.ImageArchive.Companion.fromInternet
+import com.android.virtualization.terminal.ImageArchive.Companion.fromSdCard
+import com.android.virtualization.terminal.InstalledImage.Companion.getDefault
+import com.android.virtualization.terminal.InstallerService.InstallerServiceImpl
+import com.android.virtualization.terminal.InstallerService.WifiCheckInputStream.NoWifiException
+import com.android.virtualization.terminal.MainActivity.TAG
+import java.io.IOException
+import java.io.InputStream
+import java.lang.Exception
+import java.lang.RuntimeException
+import java.lang.ref.WeakReference
+import java.net.SocketException
+import java.net.UnknownHostException
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import kotlin.math.min
+
+class InstallerService : Service() {
+    private val lock = Any()
+
+    private lateinit var notification: Notification
+
+    @GuardedBy("lock") private var isInstalling = false
+
+    @GuardedBy("lock") private var hasWifi = false
+
+    @GuardedBy("lock") private var listener: IInstallProgressListener? = null
+
+    private lateinit var executorService: ExecutorService
+    private lateinit var connectivityManager: ConnectivityManager
+    private lateinit var networkCallback: MyNetworkCallback
+
+    override fun onCreate() {
+        super.onCreate()
+
+        val intent = Intent(this, MainActivity::class.java)
+        val pendingIntent =
+            PendingIntent.getActivity(
+                this,
+                /* requestCode= */ 0,
+                intent,
+                PendingIntent.FLAG_IMMUTABLE,
+            )
+        notification =
+            Notification.Builder(this, this.packageName)
+                .setSilent(true)
+                .setSmallIcon(R.drawable.ic_launcher_foreground)
+                .setContentTitle(getString(R.string.installer_notif_title_text))
+                .setContentText(getString(R.string.installer_notif_desc_text))
+                .setOngoing(true)
+                .setContentIntent(pendingIntent)
+                .build()
+
+        executorService =
+            Executors.newSingleThreadExecutor(TerminalThreadFactory(applicationContext))
+
+        connectivityManager = getSystemService<ConnectivityManager>(ConnectivityManager::class.java)
+        val defaultNetwork = connectivityManager.boundNetworkForProcess
+        if (defaultNetwork != null) {
+            val capability = connectivityManager.getNetworkCapabilities(defaultNetwork)
+            if (capability != null) {
+                hasWifi = capability.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
+            }
+        }
+        networkCallback = MyNetworkCallback()
+        connectivityManager.registerDefaultNetworkCallback(networkCallback)
+    }
+
+    override fun onBind(intent: Intent?): IBinder? {
+        return InstallerServiceImpl(this)
+    }
+
+    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+        super.onStartCommand(intent, flags, startId)
+
+        Log.d(TAG, "Starting service ...")
+
+        return START_STICKY
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+
+        Log.d(TAG, "Service is destroyed")
+        executorService.shutdown()
+        connectivityManager.unregisterNetworkCallback(networkCallback)
+    }
+
+    private fun requestInstall(isWifiOnly: Boolean) {
+        synchronized(lock) {
+            if (isInstalling) {
+                Log.i(TAG, "already installing..")
+                return
+            } else {
+                Log.i(TAG, "installing..")
+                isInstalling = true
+            }
+        }
+
+        // Make service to be long running, even after unbind() when InstallerActivity is destroyed
+        // The service will still be destroyed if task is remove.
+        startService(Intent(this, InstallerService::class.java))
+        startForeground(
+            NOTIFICATION_ID,
+            notification,
+            ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE,
+        )
+
+        executorService.execute(
+            Runnable {
+                val success = downloadFromSdcard() || downloadFromUrl(isWifiOnly)
+                stopForeground(STOP_FOREGROUND_REMOVE)
+
+                synchronized(lock) { isInstalling = false }
+                if (success) {
+                    notifyCompleted()
+                }
+            }
+        )
+    }
+
+    private fun downloadFromSdcard(): Boolean {
+        val archive = fromSdCard()
+
+        // Installing from sdcard is preferred, but only supported only in debuggable build.
+        if (Build.isDebuggable() && archive.exists()) {
+            Log.i(TAG, "trying to install /sdcard/linux/images.tar.gz")
+
+            val dest = getDefault(this).installDir
+            try {
+                archive.installTo(dest, null)
+                Log.i(TAG, "image is installed from /sdcard/linux/images.tar.gz")
+                return true
+            } catch (e: IOException) {
+                Log.i(TAG, "Failed to install /sdcard/linux/images.tar.gz", e)
+            }
+        } else {
+            Log.i(TAG, "Non-debuggable build doesn't support installation from /sdcard/linux")
+        }
+        return false
+    }
+
+    private fun checkForWifiOnly(isWifiOnly: Boolean): Boolean {
+        if (!isWifiOnly) {
+            return true
+        }
+        synchronized(lock) {
+            return hasWifi
+        }
+    }
+
+    // TODO(b/374015561): Support pause/resume download
+    private fun downloadFromUrl(isWifiOnly: Boolean): Boolean {
+        if (!checkForWifiOnly(isWifiOnly)) {
+            Log.e(TAG, "Install isn't started because Wifi isn't available")
+            notifyError(getString(R.string.installer_error_no_wifi))
+            return false
+        }
+
+        val dest = getDefault(this).installDir
+        try {
+            fromInternet().installTo(dest) {
+                val filter = WifiCheckInputStream(it)
+                filter.setWifiOnly(isWifiOnly)
+                filter
+            }
+        } catch (e: NoWifiException) {
+            Log.e(TAG, "Install failed because of Wi-Fi is gone")
+            notifyError(getString(R.string.installer_error_no_wifi))
+            return false
+        } catch (e: UnknownHostException) {
+            // Log.e() doesn't print stack trace for UnknownHostException
+            Log.e(TAG, "Install failed: " + e.message, e)
+            notifyError(getString(R.string.installer_error_network))
+            return false
+        } catch (e: SocketException) {
+            Log.e(TAG, "Install failed: " + e.message, e)
+            notifyError(getString(R.string.installer_error_network))
+            return false
+        } catch (e: IOException) {
+            Log.e(TAG, "Installation failed", e)
+            notifyError(getString(R.string.installer_error_unknown))
+            return false
+        }
+        return true
+    }
+
+    private fun notifyError(displayText: String?) {
+        var listener: IInstallProgressListener
+        synchronized(lock) { listener = this@InstallerService.listener!! }
+
+        try {
+            listener.onError(displayText)
+        } catch (e: Exception) {
+            // ignore. Activity may not exist.
+        }
+    }
+
+    private fun notifyCompleted() {
+        var listener: IInstallProgressListener
+        synchronized(lock) { listener = this@InstallerService.listener!! }
+
+        try {
+            listener.onCompleted()
+        } catch (e: Exception) {
+            // ignore. Activity may not exist.
+        }
+    }
+
+    private class InstallerServiceImpl(service: InstallerService?) : IInstallerService.Stub() {
+        // Holds weak reference to avoid Context leak
+        private val mService: WeakReference<InstallerService> =
+            WeakReference<InstallerService>(service)
+
+        @Throws(RuntimeException::class)
+        fun ensureServiceConnected(): InstallerService {
+            val service: InstallerService? = mService.get()
+            if (service == null) {
+                throw RuntimeException(
+                    "Internal error: Installer service is being accessed after destroyed"
+                )
+            }
+            return service
+        }
+
+        override fun requestInstall(isWifiOnly: Boolean) {
+            val service = ensureServiceConnected()
+            synchronized(service.lock) { service.requestInstall(isWifiOnly) }
+        }
+
+        override fun setProgressListener(listener: IInstallProgressListener) {
+            val service = ensureServiceConnected()
+            synchronized(service.lock) { service.listener = listener }
+        }
+
+        override fun isInstalling(): Boolean {
+            val service = ensureServiceConnected()
+            synchronized(service.lock) {
+                return service.isInstalling
+            }
+        }
+
+        override fun isInstalled(): Boolean {
+            val service = ensureServiceConnected()
+            synchronized(service.lock) {
+                return !service.isInstalling && getDefault(service).isInstalled()
+            }
+        }
+    }
+
+    private inner class WifiCheckInputStream(private val inputStream: InputStream) : InputStream() {
+        private var isWifiOnly = false
+
+        fun setWifiOnly(isWifiOnly: Boolean) {
+            this@WifiCheckInputStream.isWifiOnly = isWifiOnly
+        }
+
+        @Throws(IOException::class)
+        override fun read(buf: ByteArray?, offset: Int, numToRead: Int): Int {
+            var remaining = numToRead
+            var totalRead = 0
+            while (remaining > 0) {
+                if (!checkForWifiOnly(isWifiOnly)) {
+                    throw NoWifiException()
+                }
+                val read =
+                    this@WifiCheckInputStream.inputStream.read(
+                        buf,
+                        offset + totalRead,
+                        min(READ_BYTES, remaining),
+                    )
+                if (read <= 0) {
+                    break
+                }
+                totalRead += read
+                remaining -= read
+            }
+            return totalRead
+        }
+
+        @Throws(IOException::class)
+        override fun read(): Int {
+            if (!checkForWifiOnly(isWifiOnly)) {
+                throw NoWifiException()
+            }
+            return this@WifiCheckInputStream.inputStream.read()
+        }
+
+        inner class NoWifiException : SocketException()
+    }
+
+    private inner class MyNetworkCallback : ConnectivityManager.NetworkCallback() {
+        override fun onCapabilitiesChanged(network: Network, capability: NetworkCapabilities) {
+            synchronized(lock) {
+                hasWifi = capability.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
+            }
+        }
+    }
+
+    companion object {
+        private const val NOTIFICATION_ID = 1313 // any unique number among notifications
+        private const val READ_BYTES = 1024
+    }
+}
