Merge "rpDataTest: Assume UpdatableVM" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 8cb01d7..5dd060a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -49,6 +49,12 @@
     },
     {
       "name": "vm_accessor_test"
+    },
+    {
+      "name": "avf_backcompat_tests"
+    },
+    {
+      "name": "old_images_avf_test"
     }
   ],
   "avf-postsubmit": [
diff --git a/android/TerminalApp/Android.bp b/android/TerminalApp/Android.bp
index 59f18df..2bac412 100644
--- a/android/TerminalApp/Android.bp
+++ b/android/TerminalApp/Android.bp
@@ -11,12 +11,17 @@
     asset_dirs: ["assets"],
     resource_dirs: ["res"],
     static_libs: [
+        // TODO(b/330257000): will be removed when binder RPC is used
+        "android.system.virtualizationservice_internal-java",
         "androidx-constraintlayout_constraintlayout",
         "androidx.window_window",
         "apache-commons-compress",
+        "avf_aconfig_flags_java",
         "com.google.android.material_material",
         "debian-service-grpclib-lite",
         "gson",
+        // TODO(b/331708504): will be removed when AVF framework handles surface
+        "libcrosvm_android_display_service-java",
         "VmTerminalApp.aidl-java",
         "MicrodroidTestHelper", // for DeviceProperties class
     ],
@@ -36,6 +41,7 @@
         //optimize: true,
         proguard_flags_files: ["proguard.flags"],
         shrink_resources: true,
+        keep_runtime_invisible_annotations: true,
     },
     apex_available: [
         "com.android.virt",
diff --git a/android/TerminalApp/AndroidManifest.xml b/android/TerminalApp/AndroidManifest.xml
index 726004c..c11b1a0 100644
--- a/android/TerminalApp/AndroidManifest.xml
+++ b/android/TerminalApp/AndroidManifest.xml
@@ -35,7 +35,8 @@
         android:theme="@style/VmTerminalAppTheme"
         android:usesCleartextTraffic="true"
         android:supportsRtl="true"
-        android:enabled="false">
+        android:enabled="false"
+        android:name=".Application">
         <activity android:name=".MainActivity"
                   android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation|uiMode|screenLayout|smallestScreenSize"
                   android:exported="true">
@@ -46,6 +47,11 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+        <activity android:name=".DisplayActivity"
+            android:screenOrientation="landscape"
+            android:resizeableActivity="false"
+            android:theme="@style/FullscreenTheme"
+            android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation|uiMode|screenLayout|smallestScreenSize" />
         <activity android:name=".SettingsActivity"
             android:label="@string/action_settings" />
         <activity android:name=".SettingsDiskResizeActivity"
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt b/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt
new file mode 100644
index 0000000..efe651e
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/Application.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2025 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.Application as AndroidApplication
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+
+public class Application : AndroidApplication() {
+    override fun onCreate() {
+        super.onCreate()
+        setupNotificationChannels()
+    }
+
+    private fun setupNotificationChannels() {
+        val nm = getSystemService<NotificationManager>(NotificationManager::class.java)
+
+        nm.createNotificationChannel(
+            NotificationChannel(
+                CHANNEL_LONG_RUNNING_ID,
+                getString(R.string.notification_channel_long_running_name),
+                NotificationManager.IMPORTANCE_DEFAULT,
+            )
+        )
+
+        nm.createNotificationChannel(
+            NotificationChannel(
+                CHANNEL_SYSTEM_EVENTS_ID,
+                getString(R.string.notification_channel_system_events_name),
+                NotificationManager.IMPORTANCE_HIGH,
+            )
+        )
+    }
+
+    companion object {
+        const val CHANNEL_LONG_RUNNING_ID = "long_running"
+        const val CHANNEL_SYSTEM_EVENTS_ID = "system_events"
+
+        fun getInstance(c: Context): Application = c.getApplicationContext() as Application
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt
index e7ac8d9..70bc5e4 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/BaseActivity.kt
@@ -16,8 +16,6 @@
 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
@@ -25,18 +23,6 @@
 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) {
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/DisplayActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/DisplayActivity.kt
new file mode 100644
index 0000000..290cf5a
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/DisplayActivity.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2025 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.os.Bundle
+import android.system.virtualmachine.VirtualMachineManager
+import android.view.SurfaceView
+import android.view.WindowInsets
+import android.view.WindowInsetsController
+
+class DisplayActivity : BaseActivity() {
+    private lateinit var displayProvider: DisplayProvider
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_display)
+        val mainView = findViewById<SurfaceView>(R.id.surface_view)
+        val cursorView = findViewById<SurfaceView>(R.id.cursor_surface_view)
+        makeFullscreen()
+        // Connect the views to the VM
+        displayProvider = DisplayProvider(mainView, cursorView)
+        val vmm =
+            applicationContext.getSystemService<VirtualMachineManager>(
+                VirtualMachineManager::class.java
+            )
+        val debianVm = vmm.get("debian")
+        if (debianVm != null) {
+            InputForwarder(
+                this,
+                debianVm,
+                findViewById(R.id.background_touch_view),
+                findViewById(R.id.surface_view),
+                findViewById(R.id.surface_view),
+            )
+        }
+    }
+
+    override fun onPause() {
+        super.onPause()
+        displayProvider.notifyDisplayIsGoingToInvisible()
+    }
+
+    private fun makeFullscreen() {
+        val w = window
+        w.setDecorFitsSystemWindows(false)
+        val insetsCtrl = w.insetsController
+        insetsCtrl?.hide(WindowInsets.Type.systemBars())
+        insetsCtrl?.setSystemBarsBehavior(
+            WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+        )
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/DisplayProvider.kt b/android/TerminalApp/java/com/android/virtualization/terminal/DisplayProvider.kt
new file mode 100644
index 0000000..a04e056
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/DisplayProvider.kt
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 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.crosvm.ICrosvmAndroidDisplayService
+import android.graphics.PixelFormat
+import android.os.ParcelFileDescriptor
+import android.os.RemoteException
+import android.os.ServiceManager
+import android.system.virtualizationservice_internal.IVirtualizationServiceInternal
+import android.util.Log
+import android.view.SurfaceControl
+import android.view.SurfaceHolder
+import android.view.SurfaceView
+import com.android.virtualization.terminal.DisplayProvider.CursorHandler
+import com.android.virtualization.terminal.MainActivity.Companion.TAG
+import java.io.IOException
+import java.lang.Exception
+import java.lang.RuntimeException
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+import libcore.io.IoBridge
+
+/** Provides Android-side surface from given SurfaceView to a VM instance as a display for that */
+internal class DisplayProvider(
+    private val mainView: SurfaceView,
+    private val cursorView: SurfaceView,
+) {
+    private val virtService: IVirtualizationServiceInternal by lazy {
+        val b = ServiceManager.waitForService("android.system.virtualizationservice")
+        IVirtualizationServiceInternal.Stub.asInterface(b)
+    }
+    private var cursorHandler: CursorHandler? = null
+
+    init {
+        mainView.setSurfaceLifecycle(SurfaceView.SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT)
+        mainView.holder.addCallback(Callback(SurfaceKind.MAIN))
+        cursorView.setSurfaceLifecycle(SurfaceView.SURFACE_LIFECYCLE_FOLLOWS_ATTACHMENT)
+        cursorView.holder.addCallback(Callback(SurfaceKind.CURSOR))
+        cursorView.holder.setFormat(PixelFormat.RGBA_8888)
+        // TODO: do we need this z-order?
+        cursorView.setZOrderMediaOverlay(true)
+    }
+
+    fun notifyDisplayIsGoingToInvisible() {
+        // When the display is going to be invisible (by putting in the background), save the frame
+        // of the main surface so that we can re-draw it next time the display becomes visible. This
+        // is to save the duration of time where nothing is drawn by VM.
+        try {
+            getDisplayService().saveFrameForSurface(false /* forCursor */)
+        } catch (e: RemoteException) {
+            throw RuntimeException("Failed to save frame for the main surface", e)
+        }
+    }
+
+    @Synchronized
+    private fun getDisplayService(): ICrosvmAndroidDisplayService {
+        try {
+            val b = virtService.waitDisplayService()
+            return ICrosvmAndroidDisplayService.Stub.asInterface(b)
+        } catch (e: Exception) {
+            throw RuntimeException("Error while getting display service", e)
+        }
+    }
+
+    enum class SurfaceKind {
+        MAIN,
+        CURSOR,
+    }
+
+    inner class Callback(private val surfaceKind: SurfaceKind) : SurfaceHolder.Callback {
+        fun isForCursor(): Boolean {
+            return surfaceKind == SurfaceKind.CURSOR
+        }
+
+        override fun surfaceCreated(holder: SurfaceHolder) {
+            try {
+                getDisplayService().setSurface(holder.getSurface(), isForCursor())
+            } catch (e: Exception) {
+                // TODO: don't consume this exception silently. For some unknown reason, setSurface
+                // call above throws IllegalArgumentException and that fails the surface
+                // configuration.
+                Log.e(TAG, "Failed to present surface $surfaceKind to VM", e)
+            }
+            try {
+                when (surfaceKind) {
+                    SurfaceKind.MAIN -> getDisplayService().drawSavedFrameForSurface(isForCursor())
+                    SurfaceKind.CURSOR -> {
+                        val stream = createNewCursorStream()
+                        getDisplayService().setCursorStream(stream)
+                    }
+                }
+            } catch (e: Exception) {
+                // TODO: don't consume exceptions here too
+                Log.e(TAG, "Failed to configure surface $surfaceKind", e)
+            }
+        }
+
+        override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
+            // TODO: support resizeable display. We could actually change the display size that the
+            // VM sees, or keep the size and render it by fitting it in the new surface.
+        }
+
+        override fun surfaceDestroyed(holder: SurfaceHolder) {
+            try {
+                getDisplayService().removeSurface(isForCursor())
+            } catch (e: RemoteException) {
+                throw RuntimeException("Error while destroying surface for $surfaceKind", e)
+            }
+        }
+    }
+
+    private fun createNewCursorStream(): ParcelFileDescriptor? {
+        cursorHandler?.interrupt()
+        var pfds: Array<ParcelFileDescriptor> =
+            try {
+                ParcelFileDescriptor.createSocketPair()
+            } catch (e: IOException) {
+                throw RuntimeException("Failed to create socketpair for cursor stream", e)
+            }
+        cursorHandler = CursorHandler(pfds[0]).also { it.start() }
+        return pfds[1]
+    }
+
+    /**
+     * Thread reading cursor coordinate from a stream, and updating the position of the cursor
+     * surface accordingly.
+     */
+    private inner class CursorHandler(private val stream: ParcelFileDescriptor) : Thread() {
+        private val cursor: SurfaceControl = this@DisplayProvider.cursorView.surfaceControl
+        private val transaction: SurfaceControl.Transaction = SurfaceControl.Transaction()
+
+        init {
+            val main = this@DisplayProvider.mainView.surfaceControl
+            transaction.reparent(cursor, main).apply()
+        }
+
+        override fun run() {
+            try {
+                val byteBuffer = ByteBuffer.allocate(8 /* (x: u32, y: u32) */)
+                byteBuffer.order(ByteOrder.LITTLE_ENDIAN)
+                while (true) {
+                    if (interrupted()) {
+                        Log.d(TAG, "CursorHandler thread interrupted!")
+                        return
+                    }
+                    byteBuffer.clear()
+                    val bytes =
+                        IoBridge.read(
+                            stream.fileDescriptor,
+                            byteBuffer.array(),
+                            0,
+                            byteBuffer.array().size,
+                        )
+                    if (bytes == -1) {
+                        Log.e(TAG, "cannot read from cursor stream, stop the handler")
+                        return
+                    }
+                    val x = (byteBuffer.getInt() and -0x1).toFloat()
+                    val y = (byteBuffer.getInt() and -0x1).toFloat()
+                    transaction.setPosition(cursor, x, y).apply()
+                }
+            } catch (e: IOException) {
+                Log.e(TAG, "failed to run CursorHandler", e)
+            }
+        }
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InputForwarder.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InputForwarder.kt
new file mode 100644
index 0000000..117ce94
--- /dev/null
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InputForwarder.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 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.content.Context
+import android.hardware.input.InputManager
+import android.os.Handler
+import android.system.virtualmachine.VirtualMachine
+import android.util.Log
+import android.view.InputDevice
+import android.view.KeyEvent
+import android.view.MotionEvent
+import android.view.View
+import com.android.virtualization.terminal.MainActivity.Companion.TAG
+
+/** Forwards input events (touch, mouse, ...) from Android to VM */
+internal class InputForwarder(
+    private val context: Context,
+    vm: VirtualMachine,
+    touchReceiver: View,
+    mouseReceiver: View,
+    keyReceiver: View,
+) {
+    private val virtualMachine: VirtualMachine = vm
+    private var inputDeviceListener: InputManager.InputDeviceListener? = null
+    private var isTabletMode = false
+
+    init {
+        val config = vm.config.customImageConfig
+
+        checkNotNull(config)
+
+        if (config.useTouch() == true) {
+            setupTouchReceiver(touchReceiver)
+        }
+        if (config.useMouse() || config.useTrackpad()) {
+            setupMouseReceiver(mouseReceiver)
+        }
+        if (config.useKeyboard()) {
+            setupKeyReceiver(keyReceiver)
+        }
+        if (config.useSwitches()) {
+            // Any view's handler is fine.
+            setupTabletModeHandler(touchReceiver.getHandler())
+        }
+    }
+
+    fun cleanUp() {
+        if (inputDeviceListener != null) {
+            val im = context.getSystemService<InputManager>(InputManager::class.java)
+            im.unregisterInputDeviceListener(inputDeviceListener)
+            inputDeviceListener = null
+        }
+    }
+
+    private fun setupTouchReceiver(receiver: View) {
+        receiver.setOnTouchListener(
+            View.OnTouchListener { v: View?, event: MotionEvent? ->
+                virtualMachine.sendMultiTouchEvent(event)
+            }
+        )
+    }
+
+    private fun setupMouseReceiver(receiver: View) {
+        receiver.requestUnbufferedDispatch(InputDevice.SOURCE_ANY)
+        receiver.setOnCapturedPointerListener { v: View?, event: MotionEvent? ->
+            val eventSource = event!!.source
+            if ((eventSource and InputDevice.SOURCE_CLASS_POSITION) != 0) {
+                return@setOnCapturedPointerListener virtualMachine.sendTrackpadEvent(event)
+            }
+            virtualMachine.sendMouseEvent(event)
+        }
+    }
+
+    private fun setupKeyReceiver(receiver: View) {
+        receiver.setOnKeyListener { v: View?, code: Int, event: KeyEvent? ->
+            // TODO: this is guest-os specific. It shouldn't be handled here.
+            if (isVolumeKey(code)) {
+                return@setOnKeyListener false
+            }
+            virtualMachine.sendKeyEvent(event)
+        }
+    }
+
+    private fun setupTabletModeHandler(handler: Handler?) {
+        val im = context.getSystemService<InputManager?>(InputManager::class.java)
+        inputDeviceListener =
+            object : InputManager.InputDeviceListener {
+                override fun onInputDeviceAdded(deviceId: Int) {
+                    setTabletModeConditionally()
+                }
+
+                override fun onInputDeviceRemoved(deviceId: Int) {
+                    setTabletModeConditionally()
+                }
+
+                override fun onInputDeviceChanged(deviceId: Int) {
+                    setTabletModeConditionally()
+                }
+            }
+        im!!.registerInputDeviceListener(inputDeviceListener, handler)
+    }
+
+    fun setTabletModeConditionally() {
+        val tabletModeNeeded = !hasPhysicalKeyboard()
+        if (tabletModeNeeded != isTabletMode) {
+            val mode = if (tabletModeNeeded) "tablet mode" else "desktop mode"
+            Log.d(TAG, "switching to $mode")
+            isTabletMode = tabletModeNeeded
+            virtualMachine.sendTabletModeEvent(tabletModeNeeded)
+        }
+    }
+
+    companion object {
+        private fun isVolumeKey(keyCode: Int): Boolean {
+            return keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
+                keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
+                keyCode == KeyEvent.KEYCODE_VOLUME_MUTE
+        }
+
+        private fun hasPhysicalKeyboard(): Boolean {
+            for (id in InputDevice.getDeviceIds()) {
+                val d = InputDevice.getDevice(id)
+                if (!d!!.isVirtual && d.isEnabled && d.isFullKeyboard) {
+                    return true
+                }
+            }
+            return false
+        }
+    }
+}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
index 423d66b..7180e87 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerService.kt
@@ -71,7 +71,7 @@
                 PendingIntent.FLAG_IMMUTABLE,
             )
         notification =
-            Notification.Builder(this, this.packageName)
+            Notification.Builder(this, Application.CHANNEL_LONG_RUNNING_ID)
                 .setSilent(true)
                 .setSmallIcon(R.drawable.ic_launcher_foreground)
                 .setContentTitle(getString(R.string.installer_notif_title_text))
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
index bf2f573..1daeadb 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
@@ -35,12 +35,14 @@
 import android.os.SystemProperties
 import android.os.Trace
 import android.provider.Settings
+import android.util.DisplayMetrics
 import android.util.Log
 import android.view.KeyEvent
 import android.view.Menu
 import android.view.MenuItem
 import android.view.View
 import android.view.ViewGroup
+import android.view.WindowManager
 import android.view.accessibility.AccessibilityManager
 import android.webkit.ClientCertRequest
 import android.webkit.SslErrorHandler
@@ -56,6 +58,7 @@
 import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
 import com.android.internal.annotations.VisibleForTesting
 import com.android.microdroid.test.common.DeviceProperties
+import com.android.system.virtualmachine.flags.Flags.terminalGuiSupport
 import com.android.virtualization.terminal.CertificateUtils.createOrGetKey
 import com.android.virtualization.terminal.CertificateUtils.writeCertificateToFile
 import com.android.virtualization.terminal.ErrorActivity.Companion.start
@@ -87,6 +90,7 @@
     private val bootCompleted = ConditionVariable()
     private lateinit var manageExternalStorageActivityResultLauncher: ActivityResultLauncher<Intent>
     private lateinit var modifierKeysController: ModifierKeysController
+    private var displayMenu: MenuItem? = null
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -209,7 +213,10 @@
                     view: WebView?,
                     request: WebResourceRequest?,
                 ): Boolean {
-                    return false
+                    val intent = Intent(Intent.ACTION_VIEW, request?.url)
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                    startActivity(intent)
+                    return true
                 }
 
                 override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
@@ -253,6 +260,10 @@
                                     Trace.endAsyncSection("executeTerminal", 0)
                                     findViewById<View?>(R.id.boot_progress).visibility = View.GONE
                                     terminalContainer.visibility = View.VISIBLE
+                                    if (terminalGuiSupport()) {
+                                        displayMenu?.setVisible(true)
+                                        displayMenu?.setEnabled(true)
+                                    }
                                     bootCompleted.open()
                                     modifierKeysController.update()
                                     terminalView.mapTouchToMouseEvent()
@@ -293,6 +304,8 @@
             info,
             executorService,
             object : NsdManager.ServiceInfoCallback {
+                var loaded: Boolean = false
+
                 override fun onServiceInfoCallbackRegistrationFailed(errorCode: Int) {}
 
                 override fun onServiceInfoCallbackUnregistered() {}
@@ -300,13 +313,15 @@
                 override fun onServiceLost() {}
 
                 override fun onServiceUpdated(info: NsdServiceInfo) {
-                    nsdManager.unregisterServiceInfoCallback(this)
-
                     Log.i(TAG, "Service found: $info")
                     val ipAddress = info.hostAddresses[0].hostAddress
                     val port = info.port
                     val url = getTerminalServiceUrl(ipAddress, port)
-                    runOnUiThread(Runnable { terminalView.loadUrl(url.toString()) })
+                    if (!loaded) {
+                        loaded = true
+                        nsdManager.unregisterServiceInfoCallback(this)
+                        runOnUiThread(Runnable { terminalView.loadUrl(url.toString()) })
+                    }
                 }
             },
         )
@@ -337,6 +352,11 @@
 
     override fun onCreateOptionsMenu(menu: Menu?): Boolean {
         menuInflater.inflate(R.menu.main_menu, menu)
+        displayMenu =
+            menu?.findItem(R.id.menu_item_display).also {
+                it?.setVisible(terminalGuiSupport())
+                it?.setEnabled(false)
+            }
         return true
     }
 
@@ -346,6 +366,10 @@
             val intent = Intent(this, SettingsActivity::class.java)
             this.startActivity(intent)
             return true
+        } else if (id == R.id.menu_item_display) {
+            val intent = Intent(this, DisplayActivity::class.java)
+            this.startActivity(intent)
+            return true
         }
         return super.onOptionsItemSelected(item)
     }
@@ -409,7 +433,7 @@
             )
         val icon = Icon.createWithResource(resources, R.drawable.ic_launcher_foreground)
         val notification: Notification =
-            Notification.Builder(this, this.packageName)
+            Notification.Builder(this, Application.CHANNEL_LONG_RUNNING_ID)
                 .setSilent(true)
                 .setSmallIcon(R.drawable.ic_launcher_foreground)
                 .setContentTitle(resources.getString(R.string.service_notification_title))
@@ -435,7 +459,7 @@
                 .build()
 
         Trace.beginAsyncSection("executeTerminal", 0)
-        run(this, this, notification)
+        run(this, this, notification, getDisplayInfo())
         connectToTerminalService()
     }
 
@@ -489,4 +513,18 @@
                 R.id.btn_pgdn to KeyEvent.KEYCODE_PAGE_DOWN,
             )
     }
+
+    fun getDisplayInfo(): DisplayInfo {
+        val wm = getSystemService<WindowManager>(WindowManager::class.java)
+        val metrics = wm.currentWindowMetrics
+        val dispBounds = metrics.bounds
+
+        // For now, display activity runs as landscape mode
+        val height = Math.min(dispBounds.right, dispBounds.bottom)
+        val width = Math.max(dispBounds.right, dispBounds.bottom)
+        var dpi = (DisplayMetrics.DENSITY_DEFAULT * metrics.density).toInt()
+        var refreshRate = display.refreshRate.toInt()
+
+        return DisplayInfo(width, height, dpi, refreshRate)
+    }
 }
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/PortNotifier.kt b/android/TerminalApp/java/com/android/virtualization/terminal/PortNotifier.kt
index 7c48303..7e58b36 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/PortNotifier.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/PortNotifier.kt
@@ -100,7 +100,7 @@
                 )
                 .build()
         val notification: Notification =
-            Notification.Builder(context, context.getPackageName())
+            Notification.Builder(context, Application.CHANNEL_SYSTEM_EVENTS_ID)
                 .setSmallIcon(R.drawable.ic_launcher_foreground)
                 .setContentTitle(title)
                 .setContentText(content)
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index 8c0368d..ecb01c0 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -29,6 +29,7 @@
 import android.os.IBinder
 import android.os.Looper
 import android.os.Parcel
+import android.os.Parcelable
 import android.os.ResultReceiver
 import android.os.Trace
 import android.system.virtualmachine.VirtualMachine
@@ -36,6 +37,7 @@
 import android.system.virtualmachine.VirtualMachineException
 import android.util.Log
 import android.widget.Toast
+import com.android.system.virtualmachine.flags.Flags.terminalGuiSupport
 import com.android.virtualization.terminal.MainActivity.Companion.TAG
 import com.android.virtualization.terminal.Runner.Companion.create
 import com.android.virtualization.terminal.VmLauncherService.VmLauncherServiceCallback
@@ -102,7 +104,8 @@
         val json = ConfigJson.from(this, image.configPath)
         val configBuilder = json.toConfigBuilder(this)
         val customImageConfigBuilder = json.toCustomImageConfigBuilder(this)
-        if (overrideConfigIfNecessary(customImageConfigBuilder)) {
+        val displaySize = intent.getParcelableExtra(EXTRA_DISPLAY_INFO, DisplayInfo::class.java)
+        if (overrideConfigIfNecessary(customImageConfigBuilder, displaySize)) {
             configBuilder.setCustomImageConfig(customImageConfigBuilder.build())
         }
         val config = configBuilder.build()
@@ -149,6 +152,8 @@
             info,
             executorService!!,
             object : NsdManager.ServiceInfoCallback {
+                var started: Boolean = false
+
                 override fun onServiceInfoCallbackRegistrationFailed(errorCode: Int) {}
 
                 override fun onServiceInfoCallbackUnregistered() {}
@@ -156,9 +161,12 @@
                 override fun onServiceLost() {}
 
                 override fun onServiceUpdated(info: NsdServiceInfo) {
-                    nsdManager.unregisterServiceInfoCallback(this)
                     Log.i(TAG, "Service found: $info")
-                    startDebianServer(info.hostAddresses[0].hostAddress)
+                    if (!started) {
+                        started = true
+                        nsdManager.unregisterServiceInfoCallback(this)
+                        startDebianServer(info.hostAddresses[0].hostAddress)
+                    }
                 }
             },
         )
@@ -182,7 +190,7 @@
             resources.getString(R.string.service_notification_force_quit_action)
         val stopNotificationTitle: String? =
             resources.getString(R.string.service_notification_close_title)
-        return Notification.Builder(this, this.packageName)
+        return Notification.Builder(this, Application.CHANNEL_SYSTEM_EVENTS_ID)
             .setSmallIcon(R.drawable.ic_launcher_foreground)
             .setContentTitle(stopNotificationTitle)
             .setOngoing(true)
@@ -192,7 +200,8 @@
     }
 
     private fun overrideConfigIfNecessary(
-        builder: VirtualMachineCustomImageConfig.Builder
+        builder: VirtualMachineCustomImageConfig.Builder,
+        displayInfo: DisplayInfo?,
     ): Boolean {
         var changed = false
         // TODO: check if ANGLE is enabled for the app.
@@ -212,6 +221,25 @@
             changed = true
         }
 
+        // Set the initial display size
+        // TODO(jeongik): set up the display size on demand
+        if (terminalGuiSupport() && displayInfo != null) {
+            builder
+                .setDisplayConfig(
+                    VirtualMachineCustomImageConfig.DisplayConfig.Builder()
+                        .setWidth(displayInfo.width)
+                        .setHeight(displayInfo.height)
+                        .setHorizontalDpi(displayInfo.dpi)
+                        .setVerticalDpi(displayInfo.dpi)
+                        .setRefreshRate(displayInfo.refreshRate)
+                        .build()
+                )
+                .useKeyboard(true)
+                .useMouse(true)
+                .useTouch(true)
+            changed = true
+        }
+
         val image = InstalledImage.getDefault(this)
         if (image.hasBackup()) {
             val backup = image.backupFile
@@ -301,7 +329,7 @@
         private const val EXTRA_NOTIFICATION = "EXTRA_NOTIFICATION"
         private const val ACTION_START_VM_LAUNCHER_SERVICE =
             "android.virtualization.START_VM_LAUNCHER_SERVICE"
-
+        const val EXTRA_DISPLAY_INFO = "EXTRA_DISPLAY_INFO"
         const val ACTION_STOP_VM_LAUNCHER_SERVICE: String =
             "android.virtualization.STOP_VM_LAUNCHER_SERVICE"
 
@@ -317,6 +345,7 @@
             context: Context,
             callback: VmLauncherServiceCallback?,
             notification: Notification?,
+            displayInfo: DisplayInfo,
         ) {
             val i = getMyIntent(context)
             val resultReceiver: ResultReceiver =
@@ -334,6 +363,7 @@
                 }
             i.putExtra(Intent.EXTRA_RESULT_RECEIVER, getResultReceiverForIntent(resultReceiver))
             i.putExtra(EXTRA_NOTIFICATION, notification)
+            i.putExtra(EXTRA_DISPLAY_INFO, displayInfo)
             context.startForegroundService(i)
         }
 
@@ -351,3 +381,29 @@
         }
     }
 }
+
+data class DisplayInfo(val width: Int, val height: Int, val dpi: Int, val refreshRate: Int) :
+    Parcelable {
+    constructor(
+        source: Parcel
+    ) : this(source.readInt(), source.readInt(), source.readInt(), source.readInt())
+
+    override fun describeContents(): Int = 0
+
+    override fun writeToParcel(dest: Parcel, flags: Int) {
+        dest.writeInt(width)
+        dest.writeInt(height)
+        dest.writeInt(dpi)
+        dest.writeInt(refreshRate)
+    }
+
+    companion object {
+        @JvmField
+        val CREATOR =
+            object : Parcelable.Creator<DisplayInfo> {
+                override fun createFromParcel(source: Parcel): DisplayInfo = DisplayInfo(source)
+
+                override fun newArray(size: Int) = arrayOfNulls<DisplayInfo>(size)
+            }
+    }
+}
diff --git a/android/TerminalApp/proguard.flags b/android/TerminalApp/proguard.flags
index 88b8a9c..04a2140 100644
--- a/android/TerminalApp/proguard.flags
+++ b/android/TerminalApp/proguard.flags
@@ -4,7 +4,10 @@
 -keepattributes Signature
 
 # For using GSON @Expose annotation
--keepattributes *Annotation*
+-keepattributes RuntimeVisibleAnnotations,
+                RuntimeVisibleParameterAnnotations,
+                RuntimeVisibleTypeAnnotations,
+                AnnotationDefault
 
 # Gson specific classes
 -dontwarn sun.misc.**
diff --git a/android/TerminalApp/res/drawable/ic_display.xml b/android/TerminalApp/res/drawable/ic_display.xml
new file mode 100644
index 0000000..86bdb5d
--- /dev/null
+++ b/android/TerminalApp/res/drawable/ic_display.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright 2025 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="960"
+    android:viewportHeight="960"
+    android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M240,840L240,760L280,720L160,720Q127,720 103.5,696.5Q80,673 80,640L80,200Q80,167 103.5,143.5Q127,120 160,120L800,120Q833,120 856.5,143.5Q880,167 880,200L880,640Q880,673 856.5,696.5Q833,720 800,720L680,720L720,760L720,840L240,840ZM160,640L800,640Q800,640 800,640Q800,640 800,640L800,200Q800,200 800,200Q800,200 800,200L160,200Q160,200 160,200Q160,200 160,200L160,640Q160,640 160,640Q160,640 160,640ZM160,640Q160,640 160,640Q160,640 160,640L160,200Q160,200 160,200Q160,200 160,200L160,200Q160,200 160,200Q160,200 160,200L160,640Q160,640 160,640Q160,640 160,640Z" />
+</vector>
\ No newline at end of file
diff --git a/android/TerminalApp/res/layout/activity_display.xml b/android/TerminalApp/res/layout/activity_display.xml
new file mode 100644
index 0000000..2d7d847
--- /dev/null
+++ b/android/TerminalApp/res/layout/activity_display.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  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.
+ -->
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".DisplayActivity">
+    <View
+        android:id="@+id/background_touch_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        />
+    <!-- the size should be match_parent -->
+    <SurfaceView
+        android:id="@+id/surface_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        android:focusedByDefault="true"
+        android:defaultFocusHighlightEnabled="true">
+        <requestFocus />
+    </SurfaceView>
+    <!-- A cursor size in virtio-gpu spec is always 64x64 -->
+    <SurfaceView
+        android:id="@+id/cursor_surface_view"
+        android:layout_width="64px"
+        android:layout_height="64px">
+    </SurfaceView>
+
+</merge>
\ No newline at end of file
diff --git a/android/TerminalApp/res/menu/main_menu.xml b/android/TerminalApp/res/menu/main_menu.xml
index 42ba85d..dbb788c 100644
--- a/android/TerminalApp/res/menu/main_menu.xml
+++ b/android/TerminalApp/res/menu/main_menu.xml
@@ -20,4 +20,9 @@
         android:icon="@drawable/ic_settings"
         android:title="@string/action_settings"
         app:showAsAction="always"/>
+    <item android:id="@+id/menu_item_display"
+        android:icon="@drawable/ic_display"
+        android:enabled="false"
+        android:title="@string/action_display"
+        app:showAsAction="always"/>
 </menu>
diff --git a/android/TerminalApp/res/values-af/strings.xml b/android/TerminalApp/res/values-af/strings.xml
index eae5281..e8871fd 100644
--- a/android/TerminalApp/res/values-af/strings.xml
+++ b/android/TerminalApp/res/values-af/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Kon nie installeer nie omdat wi-fi nie beskikbaar is nie"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Kon nie installeer nie. Probeer asseblief weer"</string>
     <string name="action_settings" msgid="5729342767795123227">"Instellings"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Maak terminaal gereed"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stop tans terminaal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminaal het omgeval"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Poortkontrole"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Laat luisterpoorte toe of weier hulle"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Luisterpoorte"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Het toegelate poorte gestoor"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Voeg by"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Vee <xliff:g id="PORT_NUMBER">%d</xliff:g> uit"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ongeldige poortnommer"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Poort bestaan reeds"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminaal probeer om ’n nuwe poort oop te maak"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Poort versoek: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Aanvaar"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Weier"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Herwin"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminaal maak toe"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Verplig toemaak"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> is geaktiveer"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Take wat lank neem"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Stelselgebeurtenisse"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-am/strings.xml b/android/TerminalApp/res/values-am/strings.xml
index f76eab8..d388d49 100644
--- a/android/TerminalApp/res/values-am/strings.xml
+++ b/android/TerminalApp/res/values-am/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi ስለማይገኝ መጫን አልተሳካም"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"መጫን አልተሳካም። እባክዎ እንደገና ይሞክሩ"</string>
     <string name="action_settings" msgid="5729342767795123227">"ቅንብሮች"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ተርሚናልን በማዘጋጀት ላይ"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ተርሚናልን በማቆም ላይ"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ተርሚናል ተበላሽቷል"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"የወደብ ቁጥጥር"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"የማዳመጫ ወደቦችን ይፍቀዱ/ይከልክሉ"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"የማዳመጫ ወደቦች"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"የተቀመጡ የሚፈቀዱ ወደቦች"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"አክል"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g>ን ሰርዝ"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ልክ ያልሆነ የወደብ ቁጥር"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ወደብ ቀድሞውኑ ይገኛል"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ተርሚናል አዲስ ወደብ ለመክፈት እየጠየቀ ነው"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"የተጠየቀ ወደብ፦ <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ተቀበል"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ከልክል"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"መልሶ ማግኘት"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ተርሚናል በመዝጋት ላይ ነው"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"በግድ ዝጋ"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ነቅቷል"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ረዥም የሚያሄዱ ተግባሮች"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"የሥርዓት ክስተቶች"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ar/strings.xml b/android/TerminalApp/res/values-ar/strings.xml
index c01460d..4df4afc 100644
--- a/android/TerminalApp/res/values-ar/strings.xml
+++ b/android/TerminalApp/res/values-ar/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"تعذَّر التثبيت لأنّ شبكة Wi-Fi غير متاحة"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"تعذَّر التثبيت. يُرجى إعادة المحاولة"</string>
     <string name="action_settings" msgid="5729342767795123227">"الإعدادات"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"جارٍ تحضير Terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"جارٍ إيقاف Terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"تعطَّل Terminal"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"التحكّم في المنافذ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"السماح بمنافذ الاستماع أو حظرها"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"منافذ الاستماع"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"‫<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"المنافذ المسموح بها المحفوظة"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"إضافة"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"حذف <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"رقم المنفذ غير صالح"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"المنفذ متوفِّر حاليًا"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"تطلُب الوحدة الطرفية فتح منفذ جديد"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"المنفذ المطلوب: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"قبول"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"رفض"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"الاسترداد"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"جارٍ إغلاق الوحدة الطرفية"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"فرض الإغلاق"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"تم تفعيل <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"المهام الطويلة المدى"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"أحداث النظام"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-as/strings.xml b/android/TerminalApp/res/values-as/strings.xml
index a773fad..e4a4a50 100644
--- a/android/TerminalApp/res/values-as/strings.xml
+++ b/android/TerminalApp/res/values-as/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ৱাই-ফাই উপলব্ধ নোহোৱাৰ কাৰণে ইনষ্টল কৰিব পৰা নগ’ল"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ইনষ্টল কৰিব পৰা নগ’ল। অনুগ্ৰহ কৰি পুনৰ চেষ্টা কৰক"</string>
     <string name="action_settings" msgid="5729342767795123227">"ছেটিং"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"টাৰ্মিনেল সাজু কৰি থকা হৈছে"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"টাৰ্মিনেল বন্ধ কৰি থকা হৈছে"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"টাৰ্মিনেল ক্ৰেশ্ব হৈছে"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"প’ৰ্ট নিয়ন্ত্ৰণ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"শুনা প’ৰ্টৰ অনুমতি দিয়ক/অস্বীকাৰ কৰক"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"শুনা প’ৰ্ট"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"ছেভ কৰা অনুমোদিত প’ৰ্ট"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"যোগ দিয়ক"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> মচক"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"অমান্য প’ৰ্টৰ নম্বৰ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"প’ৰ্ট ইতিমধ্যে আছে"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"টাৰ্মিনেলটোৱে এটা নতুন প’ৰ্ট খুলিবলৈ অনুৰোধ কৰি আছে"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"প’ৰ্ট অনুৰোধ কৰা হৈছে: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"গ্ৰহণ কৰক"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"অস্বীকাৰ কৰক"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"পুনৰুদ্ধাৰ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"টাৰ্মিনেলটো বন্ধ কৰি থকা হৈছে"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"বলেৰে বন্ধ কৰক"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> সক্ষম কৰা আছে"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"দীঘলীয়া সময় জুৰি চলা কাৰ্য"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"ছিষ্টেমৰ ঘটনা"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-az/strings.xml b/android/TerminalApp/res/values-az/strings.xml
index 0e52500..2b33cd8 100644
--- a/android/TerminalApp/res/values-az/strings.xml
+++ b/android/TerminalApp/res/values-az/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi əlçatan olmadığı üçün quraşdırmaq alınmadı"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Quraşdırmaq alınmadı. Yenidən cəhd edin"</string>
     <string name="action_settings" msgid="5729342767795123227">"Ayarlar"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminal hazırlanır"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminal dayandırılır"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal çökdü"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Port nəzarəti"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Dinləmə portlarına icazə verin/imtina edin"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Dinləmə portları"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Yadda saxlanılmış icazə verilən portlar"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Əlavə edin"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Silin: <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Yanlış port nömrəsi"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port artıq mövcuddur"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal yeni port açmağı tələb edir"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port tələb edildi: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Qəbul edin"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Rədd edin"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Bərpa"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal bağlanır"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Məcburi bağlanma"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> aktivləşdirilib"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Uzunmüddətli tapşırıqlar"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistem tədbirləri"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-b+sr+Latn/strings.xml b/android/TerminalApp/res/values-b+sr+Latn/strings.xml
index fdbd9c0..1778e4c 100644
--- a/android/TerminalApp/res/values-b+sr+Latn/strings.xml
+++ b/android/TerminalApp/res/values-b+sr+Latn/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Instaliranje nije uspelo jer WiFi nije dostupan"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Instaliranje nije uspelo. Probajte ponovo"</string>
     <string name="action_settings" msgid="5729342767795123227">"Podešavanja"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminal se priprema"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminal se zaustavlja"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal je otkazao"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kontrola porta"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Dozvolite ili zabranite portove za slušanje"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Portovi za slušanje"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Sačuvani dozvoljeni portovi"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Dodaj"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Izbriši <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nevažeći broj porta"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port već postoji"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal traži da otvori novi port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Obavezan port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Prihvati"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Odbij"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Oporavak"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal se zatvara"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Prinudno zatvori"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> je omogućen"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dugotrajni zadaci"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemski događaji"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-be/strings.xml b/android/TerminalApp/res/values-be/strings.xml
index 77a6538..9b0dd00 100644
--- a/android/TerminalApp/res/values-be/strings.xml
+++ b/android/TerminalApp/res/values-be/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Не ўдалося ўсталяваць, бо сетка Wi-Fi недаступная"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Не ўдалося ўсталяваць. Паўтарыце спробу."</string>
     <string name="action_settings" msgid="5729342767795123227">"Налады"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Ідзе падрыхтоўка тэрмінала"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Спыненне тэрмінала"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Збой тэрмінала"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Кіраванне портам"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Дазволіць (адмовіць) доступ да партоў праслухоўвання"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Парты праслухоўвання"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Захаваць дазволеныя парты"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Дадаць"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Выдаліць порт <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Няправільны нумар порта"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт ужо існуе"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Тэрмінал запытвае адкрыць новы порт"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Запытаны порт: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Прыняць"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Адмовіць"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Аднаўленне"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Тэрмінал закрываецца"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Закрыць прымусова"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Модуль <xliff:g id="ID_1">VirGL</xliff:g> уключаны"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Працяглыя задачы"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Сістэмныя падзеі"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-bg/strings.xml b/android/TerminalApp/res/values-bg/strings.xml
index d9c16df..d9efb58 100644
--- a/android/TerminalApp/res/values-bg/strings.xml
+++ b/android/TerminalApp/res/values-bg/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Инсталирането не бе успешно, защото не е налице Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Инсталирането не бе успешно. Моля, опитайте отново"</string>
     <string name="action_settings" msgid="5729342767795123227">"Настройки"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминалът се подготвя"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Терминалът спира"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Терминалът претърпя срив"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Контрол на портовете"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Разрешаване/отхвърляне на портовете за слушане"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Портове за слушане"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Запазени разрешени портове"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Добавяне"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Изтриване на <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Невалиден номер на порт"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Портът вече съществува"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминалът заявява отварянето на нов порт"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Заявен порт: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Приемам"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Отказ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Възстановя­ване"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминалът се затваря"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Принудително затваряне"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> е активирано"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Продължителни задачи"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системни събития"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-bn/strings.xml b/android/TerminalApp/res/values-bn/strings.xml
index b25bc02..5f23dbd 100644
--- a/android/TerminalApp/res/values-bn/strings.xml
+++ b/android/TerminalApp/res/values-bn/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ওয়াই-ফাই উপলভ্য না থাকায় ইনস্টল করা যায়নি"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ইনস্টল করা যায়নি। আবার চেষ্টা করুন"</string>
     <string name="action_settings" msgid="5729342767795123227">"সেটিংস"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"টার্মিনাল তৈরি করা হচ্ছে"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"টার্মিনাল বন্ধ করা হচ্ছে"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"টার্মিনাল ক্র্যাশ করেছে"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"পোর্ট কন্ট্রোল"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"লিসিনিং পোর্টের অনুমতি দিন/অনুমতি দেবেন না"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"লিসিনিং পোর্ট"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"অনুমতি দেওয়া পোর্ট সেভ করা হয়েছে"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"যোগ করুন"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> মুছুন"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"পোর্ট নম্বর ভুল আছে"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"পোর্ট আগে থেকেই রয়েছে"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"টার্মিনাল নতুন পোর্ট খোলার অনুরোধ করছে"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"পোর্টের অনুরোধ করা হয়েছে: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"সম্মতি দিন"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"বাতিল করুন"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"আগের অবস্থায় ফেরানো"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"টার্মিনাল বন্ধ হচ্ছে"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"জোর করে বন্ধ করুন"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> চালু করা আছে"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"দীর্ঘ সময় ধরে চালানো টাস্ক"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"সিস্টেম ইভেন্ট"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-bs/strings.xml b/android/TerminalApp/res/values-bs/strings.xml
index 8dcfe6f..df1cfbb 100644
--- a/android/TerminalApp/res/values-bs/strings.xml
+++ b/android/TerminalApp/res/values-bs/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Instaliranje nije uspjelo jer WiFi nije dostupan"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Instaliranje nije uspjelo. Pokušajte ponovo"</string>
     <string name="action_settings" msgid="5729342767795123227">"Postavke"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Priprema terminala"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Zaustavljanje terminala"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal je pao"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Upravljanje priključkom"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Dozvoli/odbij priključke za slušanje"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Priključci za slušanje"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Sačuvani dozvoljeni priključci"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Dodavanje"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Brisanje priključka <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nevažeći broj priključka"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Priključak već postoji"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal zahtijeva otvaranje novog priključka"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Zatražen je priključak: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Prihvati"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Odbij"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Oporavak"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal je zatvoren"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Prisilno zatvori"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Omogućeno: <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dugotrajni zadaci"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Događaji sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ca/strings.xml b/android/TerminalApp/res/values-ca/strings.xml
index 0737ffe..bab288f 100644
--- a/android/TerminalApp/res/values-ca/strings.xml
+++ b/android/TerminalApp/res/values-ca/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"No s\'ha pogut instal·lar perquè la Wi‑Fi no està disponible"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"No s\'ha pogut instal·lar. Torna-ho a provar."</string>
     <string name="action_settings" msgid="5729342767795123227">"Configuració"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"S\'està preparant el terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"S\'està aturant el terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"El terminal s\'ha bloquejat"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Control de ports"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permet o denega els ports d\'escolta"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Ports d\'escolta"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Ports permesos desats"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Afegeix"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Suprimeix <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"El número de port no és vàlid"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"El port ja existeix"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"El terminal està sol·licitant obrir un port nou"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port sol·licitat: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accepta"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Denega"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperació"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"El terminal s\'està tancant"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Força el tancament"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> està activat"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tasques de llarga durada"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Esdeveniments del sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-cs/strings.xml b/android/TerminalApp/res/values-cs/strings.xml
index 2ab202e..bf036f1 100644
--- a/android/TerminalApp/res/values-cs/strings.xml
+++ b/android/TerminalApp/res/values-cs/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Instalace se nezdařila, protože není k dispozici Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Instalace se nezdařila. Zkuste to znovu"</string>
     <string name="action_settings" msgid="5729342767795123227">"Nastavení"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Probíhá příprava terminálu"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Ukončování terminálu"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminál selhal"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Ovládání portů"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Povolit/zakázat naslouchající porty"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Naslouchající porty"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Uložené povolené porty"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Přidat"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Smazat port <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Neplatné číslo portu"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port už existuje"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminál se pokouší otevřít nový port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Požadovaný port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Přijmout"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Zamítnout"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Obnovení"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminál se zavírá"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Vynutit ukončení"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Modul <xliff:g id="ID_1">VirGL</xliff:g> je aktivován"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dlouho spuštěné úlohy"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systémové události"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-da/strings.xml b/android/TerminalApp/res/values-da/strings.xml
index 6ef382f..772f040 100644
--- a/android/TerminalApp/res/values-da/strings.xml
+++ b/android/TerminalApp/res/values-da/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Installationen mislykkedes, fordi Wi-Fi ikke er tilgængeligt"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Installationen mislykkedes. Prøv igen"</string>
     <string name="action_settings" msgid="5729342767795123227">"Indstillinger"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Forbereder terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stopper terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminalen er gået ned"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portstyring"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Tillad/afvis aktive porte"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Aktive porte"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Gemte tilladte porte"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Tilføj"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Slet <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ugyldigt portnummer"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Porten findes allerede"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminalen anmoder om at åbne en ny port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port, der anmodes om: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Acceptér"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Afvis"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Gendannelse"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminalen lukker"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Tving til at lukke"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> er aktiveret"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Længerevarende opgaver"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systemhændelser"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-de/strings.xml b/android/TerminalApp/res/values-de/strings.xml
index deb3db3..5248d02 100644
--- a/android/TerminalApp/res/values-de/strings.xml
+++ b/android/TerminalApp/res/values-de/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Die Installation ist fehlgeschlagen, weil kein WLAN verfügbar ist"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Die Installation ist fehlgeschlagen. Bitte versuche es noch einmal."</string>
     <string name="action_settings" msgid="5729342767795123227">"Einstellungen"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminal wird vorbereitet"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminal wird beendet"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal ist abgestürzt"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portsteuerung"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Überwachungsports zulassen / ablehnen"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Überwachungsports"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Gespeicherte zulässige Ports"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Hinzufügen"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"„<xliff:g id="PORT_NUMBER">%d</xliff:g>“ löschen"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ungültige Portnummer"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port ist bereits vorhanden"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal fordert an, einen neuen Port zu öffnen"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Angeforderter Port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Akzeptieren"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Ablehnen"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Wieder­herstellung"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal wird geschlossen"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Schließen erzwingen"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ist aktiviert"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Aufgaben mit langer Ausführungszeit"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systemereignisse"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-el/strings.xml b/android/TerminalApp/res/values-el/strings.xml
index 78cf235..8e2f628 100644
--- a/android/TerminalApp/res/values-el/strings.xml
+++ b/android/TerminalApp/res/values-el/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Η εγκατάσταση απέτυχε, επειδή το Wi-Fi δεν είναι διαθέσιμο"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Η εγκατάσταση απέτυχε. Δοκιμάστε ξανά"</string>
     <string name="action_settings" msgid="5729342767795123227">"Ρυθμίσεις"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Προετοιμασία τερματικού σε εξέλιξη"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Διακοπή τερματικού σε εξέλιξη"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Το τερματικό παρουσίασε σφάλμα"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Έλεγχος θυρών"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Να επιτρέπονται/μην επιτρέπονται οι θύρες ακρόασης"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Θύρες ακρόασης"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Αποθηκευμένες επιτρεπόμενες θύρες"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Προσθήκη"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Διαγραφή θύρας <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Μη έγκυρος αριθμός θύρας"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Η θύρα υπάρχει ήδη"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Το τερματικό ζητά να ανοίξει μια νέα θύρα"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Ζητήθηκε θύρα: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Αποδοχή"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Απόρριψη"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Ανάκτηση"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Το τερματικό κλείνει"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Αναγκαστικό κλείσιμο"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Το <xliff:g id="ID_1">VirGL</xliff:g> είναι ενεργοποιημένο"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Εργασίες μεγάλης διάρκειας"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Συμβάντα συστήματος"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-en-rAU/strings.xml b/android/TerminalApp/res/values-en-rAU/strings.xml
index 805257f..387eb2b 100644
--- a/android/TerminalApp/res/values-en-rAU/strings.xml
+++ b/android/TerminalApp/res/values-en-rAU/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Failed to install because Wi-Fi is not available"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Failed to install. Please try again"</string>
     <string name="action_settings" msgid="5729342767795123227">"Settings"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparing terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stopping terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal crashed"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Port control"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Allow/deny listening ports"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Listening ports"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Saved allowed ports"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Add"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Delete <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Invalid port number"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port already exists"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal is requesting to open a new port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port requested: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accept"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Deny"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recovery"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal is closing"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Force close"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> is enabled"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Long-running tasks"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"System events"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-en-rCA/strings.xml b/android/TerminalApp/res/values-en-rCA/strings.xml
index f208e38..5842cb2 100644
--- a/android/TerminalApp/res/values-en-rCA/strings.xml
+++ b/android/TerminalApp/res/values-en-rCA/strings.xml
@@ -33,6 +33,7 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Failed to install because Wi-Fi is not available"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Failed to install. Please try again"</string>
     <string name="action_settings" msgid="5729342767795123227">"Settings"</string>
+    <string name="action_display" msgid="8487008779926038139">"Display"</string>
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparing terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stopping terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal crashed"</string>
@@ -87,4 +88,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal is closing"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Force close"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> is enabled"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Long running tasks"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"System events"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-en-rGB/strings.xml b/android/TerminalApp/res/values-en-rGB/strings.xml
index 805257f..387eb2b 100644
--- a/android/TerminalApp/res/values-en-rGB/strings.xml
+++ b/android/TerminalApp/res/values-en-rGB/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Failed to install because Wi-Fi is not available"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Failed to install. Please try again"</string>
     <string name="action_settings" msgid="5729342767795123227">"Settings"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparing terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stopping terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal crashed"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Port control"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Allow/deny listening ports"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Listening ports"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Saved allowed ports"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Add"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Delete <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Invalid port number"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port already exists"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal is requesting to open a new port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port requested: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accept"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Deny"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recovery"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal is closing"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Force close"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> is enabled"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Long-running tasks"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"System events"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-en-rIN/strings.xml b/android/TerminalApp/res/values-en-rIN/strings.xml
index 805257f..387eb2b 100644
--- a/android/TerminalApp/res/values-en-rIN/strings.xml
+++ b/android/TerminalApp/res/values-en-rIN/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Failed to install because Wi-Fi is not available"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Failed to install. Please try again"</string>
     <string name="action_settings" msgid="5729342767795123227">"Settings"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparing terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stopping terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal crashed"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Port control"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Allow/deny listening ports"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Listening ports"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Saved allowed ports"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Add"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Delete <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Invalid port number"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port already exists"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal is requesting to open a new port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port requested: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accept"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Deny"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recovery"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal is closing"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Force close"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> is enabled"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Long-running tasks"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"System events"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-es-rUS/strings.xml b/android/TerminalApp/res/values-es-rUS/strings.xml
index ba758ac..fe907df 100644
--- a/android/TerminalApp/res/values-es-rUS/strings.xml
+++ b/android/TerminalApp/res/values-es-rUS/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"La instalación falló porque no hay una conexión Wi-Fi disponible"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"No se pudo instalar; vuelve a intentarlo"</string>
     <string name="action_settings" msgid="5729342767795123227">"Configuración"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparando la terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Deteniendo la terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Se produjo un error en la terminal"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Control del puerto"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permitir o denegar los puertos de escucha"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Puertos de escucha"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Puertos permitidos guardados"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Agregar"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Borrar <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"El número de puerto no es válido"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"El puerto ya existe"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"La terminal está solicitando abrir un puerto nuevo"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Puerto solicitado: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Aceptar"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Rechazar"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperación"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Se está cerrando la terminal"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forzar cierre"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Se habilitó <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tareas extensas"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos del sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-es/strings.xml b/android/TerminalApp/res/values-es/strings.xml
index 5a2629c..3ac451a 100644
--- a/android/TerminalApp/res/values-es/strings.xml
+++ b/android/TerminalApp/res/values-es/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"No se ha podido instalar porque no hay conexión Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"No se ha podido instalar. Vuelve a intentarlo."</string>
     <string name="action_settings" msgid="5729342767795123227">"Ajustes"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparando terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Deteniendo terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Fallo del terminal"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Control de puerto"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permitir/Denegar puertos de escucha"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Puertos de escucha"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Puertos permitidos guardados"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Añadir"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Eliminar <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Número de puerto no válido"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"El puerto ya existe"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"El terminal está solicitando abrir un nuevo puerto"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Puerto solicitado: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Aceptar"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Denegar"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperación"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"El terminal se está cerrando"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forzar cierre"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> se ha habilitado"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tareas de larga duración"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos del sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-et/strings.xml b/android/TerminalApp/res/values-et/strings.xml
index e64729c..eeb17ef 100644
--- a/android/TerminalApp/res/values-et/strings.xml
+++ b/android/TerminalApp/res/values-et/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Installimine ebaõnnestus, kuna WiFi pole saadaval"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Installimine ebaõnnestus. Proovige uuesti"</string>
     <string name="action_settings" msgid="5729342767795123227">"Seaded"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminali ettevalmistamine"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminali peatamine"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal jooksis kokku"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portide haldamine"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Kuulamisportide lubamine/keelamine"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Kuulamispordid"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Salvestatud lubatud pordid"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Lisa"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Kustuta <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Sobimatu pordi number"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port on juba olemas"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal taotleb uue pordi avamist"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Taotletud port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Nõustu"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Keela"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Taastamine"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal suletakse"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Rakenda sulgemine"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> on lubatud"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Pikalt kestvad ülesanded"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Süsteemisündmused"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-eu/strings.xml b/android/TerminalApp/res/values-eu/strings.xml
index fde1d1d..a983e26 100644
--- a/android/TerminalApp/res/values-eu/strings.xml
+++ b/android/TerminalApp/res/values-eu/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Ezin izan da instalatu, wifi-sarerik erabilgarri ez dagoelako"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Ezin izan da instalatu. Saiatu berriro"</string>
     <string name="action_settings" msgid="5729342767795123227">"Ezarpenak"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminala prestatzen"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminala geldiarazten"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminalak huts egin du"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Ataka kontrolatzeko aukerak"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Onartu/Baztertu ataka aktiboak"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Ataka aktiboak"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Gorde dira onartutako atakak"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Gehitu"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Ezabatu <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ataka-zenbakiak ez du balio"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Ataka jada badago"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminalak beste ataka bat irekitzeko eskatu du"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Ataka hau eskatu da: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Onartu"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Ukatu"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Berreskuratzea"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal ixten ari da"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Behartu ixtera"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> gaituta dago"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Luze exekutatzen diren zereginak"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemako gertaerak"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-fa/strings.xml b/android/TerminalApp/res/values-fa/strings.xml
index b040c24..d6dc255 100644
--- a/android/TerminalApp/res/values-fa/strings.xml
+++ b/android/TerminalApp/res/values-fa/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"نصب نشد چون Wi-Fi دردسترس نیست"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"نصب نشد. لطفاً دوباره امتحان کنید"</string>
     <string name="action_settings" msgid="5729342767795123227">"تنظیمات"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"درحال آماده‌سازی پایانه"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"پایانه درحال توقف است"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"پایانه ازکار افتاد"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"کنترل درگاه"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"مجاز/ رد کردن درگاه‌های گوش کردن"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"درگاه‌های گوش کردن"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"‫<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"درگاه‌های مجاز ذخیره شدند"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"افزودن"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"حذف کردن <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"شماره درگاه نامعتبر است"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"درگاه ازقبل موجود است"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"پایانه می‌خواهد درگاه جدیدی باز کند"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"درگاه درخواست‌شده: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"پذیرفتن"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"رد کردن"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"بازیابی"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"پایانه درحال بسته شدن است"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"بستن اجباری"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"‫<xliff:g id="ID_1">VirGL</xliff:g> فعال شد"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"تکالیف بلندمدت"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"رویدادهای سیستم"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-fi/strings.xml b/android/TerminalApp/res/values-fi/strings.xml
index 5dcfadf..63b91a5 100644
--- a/android/TerminalApp/res/values-fi/strings.xml
+++ b/android/TerminalApp/res/values-fi/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Asennus epäonnistui, koska Wi-Fi ei ole käytettävissä"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Asennus epäonnistui. Yritä uudelleen"</string>
     <string name="action_settings" msgid="5729342767795123227">"Asetukset"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Valmistellaan päätettä"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Pysäytetään terminaalia"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminaali kaatui"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Porttien ohjaus"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Salli/kiellä kuunteluportit"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Kuunteluportit"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Tallennetut sallitut portit"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Lisää"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Poista <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Virheellinen portin numero"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Portti on jo olemassa"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Pääte yrittää avata uuden portin"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Pyydetty portti: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Hyväksy"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Hylkää"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Palautus"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal sulkeutuu"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Pakota sulkeutumaan"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> on käytössä"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Pitkäkestoiset tehtävät"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Järjestelmätapahtumat"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-fr-rCA/strings.xml b/android/TerminalApp/res/values-fr-rCA/strings.xml
index a320c62..684cc28 100644
--- a/android/TerminalApp/res/values-fr-rCA/strings.xml
+++ b/android/TerminalApp/res/values-fr-rCA/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Échec de l\'installation parce que le Wi-Fi n\'est pas disponible"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Échec de l\'installation. Veuillez réessayer"</string>
     <string name="action_settings" msgid="5729342767795123227">"Paramètres"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Préparation du terminal en cours…"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Arrêt du terminal en cours…"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Le terminal a planté"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Contrôle du port"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Autoriser/Refuser les ports en mode Réception"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Ports en mode Réception"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Ports autorisés enregistrés"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Ajouter"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Supprimer le port <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Numéro de port incorrect"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Le port existe déjà"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Le terminal demande d\'ouvrir un nouveau port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port demandé : <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accepter"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Refuser"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Récupération"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Le terminal se fermera"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forcer la fermeture"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> est activé"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tâches de longue durée"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Événements système"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-fr/strings.xml b/android/TerminalApp/res/values-fr/strings.xml
index edb91b4..94beb27 100644
--- a/android/TerminalApp/res/values-fr/strings.xml
+++ b/android/TerminalApp/res/values-fr/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Échec de l\'installation, car le Wi-Fi n\'est pas disponible"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Échec de l\'installation. Veuillez réessayer."</string>
     <string name="action_settings" msgid="5729342767795123227">"Paramètres"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Préparation du terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Arrêt du terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Le terminal a planté"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Contrôle de port"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Autoriser/refuser les ports d\'écoute"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Ports d\'écoute"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Ports autorisés enregistrés"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Ajouter"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Supprimer <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Numéro de port incorrect"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Le port existe déjà"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Le terminal demande l\'ouverture d\'un nouveau port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port demandé : <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accepter"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Refuser"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Récupération"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal se ferme"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forcer la fermeture"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> est activé"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tâches de longue durée"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Événements système"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-gl/strings.xml b/android/TerminalApp/res/values-gl/strings.xml
index c1d4f82..9bc7fbd 100644
--- a/android/TerminalApp/res/values-gl/strings.xml
+++ b/android/TerminalApp/res/values-gl/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Produciuse un erro durante a instalación porque non hai ningunha wifi dispoñible"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Produciuse un erro durante a instalación. Téntao de novo"</string>
     <string name="action_settings" msgid="5729342767795123227">"Configuración"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparando terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Parando terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Produciuse un fallo no terminal"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Control de portos"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permitir ou rexeitar portos de escoita"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Portos de escoita"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Gardáronse os portos permitidos"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Engadir"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Eliminar <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"O número de porto non é válido"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Xa existe o porto"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"O terminal está solicitando que se abra outro porto"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Porto solicitado: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Aceptar"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Denegar"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperación"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"A aplicación Terminal estase pechando"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forzar peche"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Activouse <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tarefas de longa duración"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos do sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-gu/strings.xml b/android/TerminalApp/res/values-gu/strings.xml
index b1a452f..2f11bf7 100644
--- a/android/TerminalApp/res/values-gu/strings.xml
+++ b/android/TerminalApp/res/values-gu/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"વાઇ-ફાઇ ઉપલબ્ધ ન હોવાથી ઇન્સ્ટૉલ કરવામાં નિષ્ફળ રહ્યાં"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ઇન્સ્ટૉલ કરવામાં નિષ્ફળ રહ્યાં. કૃપા કરીને ફરી પ્રયાસ કરો"</string>
     <string name="action_settings" msgid="5729342767795123227">"સેટિંગ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ટર્મિનલ તૈયાર કરી રહ્યાં છીએ"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ટર્મિનલ બંધ કરી રહ્યાં છીએ"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ટર્મિનલ ક્રૅશ થયું"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"પોર્ટ નિયંત્રણ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"સાંભળનાર પોર્ટને મંજૂરી આપો/નકારો"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"સાંભળનાર પોર્ટ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"સાચવેલા મંજૂરીપ્રાપ્ત પોર્ટ"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ઉમેરો"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> ડિલીટ કરો"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"પોર્ટ નંબર અમાન્ય છે"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"પોર્ટ પહેલેથી અસ્તિત્વમાં છે"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ટર્મિનલ નવું પોર્ટ ખોલવા માટે વિનંતી કરી રહ્યું છે"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"પોર્ટ કરવાની વિનંતી કરવામાં આવી: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"સ્વીકારો"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"નકારો"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"રિકવરી"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ટર્મિનલ ઍપ બંધ થઈ રહી છે"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"ફરજિયાત બંધ કરો"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ચાલુ કરેલું છે"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"લાંબો સમય ચાલનારા કાર્યો"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"સિસ્ટમ ઇવેન્ટ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-hi/strings.xml b/android/TerminalApp/res/values-hi/strings.xml
index af2ddaa..f54ff86 100644
--- a/android/TerminalApp/res/values-hi/strings.xml
+++ b/android/TerminalApp/res/values-hi/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"वाई-फ़ाई उपलब्ध न होने की वजह से, इंस्टॉल नहीं किया जा सका"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"इंस्टॉल नहीं किया जा सका. कृपया फिर से कोशिश करें"</string>
     <string name="action_settings" msgid="5729342767795123227">"सेटिंग"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"टर्मिनल तैयार किया जा रहा है"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"टर्मिनल को रोका जा रहा है"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"टर्मिनल क्रैश हो गया"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"पोर्ट कंट्रोल"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"लिसनिंग पोर्ट को अनुमति दें या अनुमति न दें"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"लिसनिंग पोर्ट"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"अनुमति पा चुके सभी पोर्ट को सेव किया गया"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"जोड़ें"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> को मिटाएं"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"अमान्य पोर्ट संख्या"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"पोर्ट पहले से मौजूद है"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"टर्मिनल, एक नया पोर्ट खोलने का अनुरोध कर रहा है"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"पोर्ट खोलने का अनुरोध किया गया: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"स्वीकार करें"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"अस्वीकार करें"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"इमेज रिकवर करें"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"टर्मिनल ऐप्लिकेशन बंद हो रहा है"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"ज़बरदस्ती बंद करें"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> चालू है"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"लंबे समय तक चलने वाले टास्क"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"सिस्टम इवेंट"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-hr/strings.xml b/android/TerminalApp/res/values-hr/strings.xml
index 87d4798..4ff5fd4 100644
--- a/android/TerminalApp/res/values-hr/strings.xml
+++ b/android/TerminalApp/res/values-hr/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Instaliranje nije uspjelo jer Wi-Fi nije dostupan"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Instaliranje nije uspjelo. Pokušajte ponovo"</string>
     <string name="action_settings" msgid="5729342767795123227">"Postavke"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Priprema terminala"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Zaustavljanje terminala"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal se srušio"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kontrola priključka"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Dopusti/odbij priključke za slušanje"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Priključci za slušanje"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Spremljeni dopušteni priključci"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Dodaj"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Izbriši priključak <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nevažeći broj priključka"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Priključak već postoji"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal zahtijeva da se otvori novi priključak"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Zatraženi priključak: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Prihvati"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Odbij"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Oporavak"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal se zatvara"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Prisilno zatvori"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Omogućeno je: <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dugotrajni zadaci"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Događaji sustava"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-hu/strings.xml b/android/TerminalApp/res/values-hu/strings.xml
index e1b17e6..6af50ee 100644
--- a/android/TerminalApp/res/values-hu/strings.xml
+++ b/android/TerminalApp/res/values-hu/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Nem sikerült a telepítés, mert nincs Wi-Fi-kapcsolat"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Nem sikerült a telepítés. Próbálkozzon újra."</string>
     <string name="action_settings" msgid="5729342767795123227">"Beállítások"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"A terminál előkészítése…"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"A terminál leállítása…"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"A terminál összeomlott"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portvezérlés"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Figyelő portok engedélyezése/letiltása"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Figyelő portok"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Mentett engedélyezett portok"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Hozzáadás"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> törlése"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Érvénytelen a portszám"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"A port már létezik"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"A terminál új port megnyitását kéri"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Kért port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Elfogadás"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Elutasítás"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Helyreállítás"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"A terminál bezárul"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Bezárás kényszerítése"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"A(z) <xliff:g id="ID_1">VirGL</xliff:g> engedélyezve van"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Hosszan futó feladatok"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Rendszeresemények"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-hy/strings.xml b/android/TerminalApp/res/values-hy/strings.xml
index 06ae4cb..3369b7e 100644
--- a/android/TerminalApp/res/values-hy/strings.xml
+++ b/android/TerminalApp/res/values-hy/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Չհաջողվեց տեղադրել, քանի որ Wi-Fi ցանցը հասանելի չէ"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Չհաջողվեց տեղադրել: Նորից փորձեք"</string>
     <string name="action_settings" msgid="5729342767795123227">"Կարգավորումներ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Տերմինալի նախապատրաստում"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Տերմինալը կանգնեցվում է"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Տերմինալը խափանվել է"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Միացքների կառավարում"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Թույլատրել/մերժել ունկնդրման միացքները"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Ունկնդրման միացքներ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Պահված թույլատրված միացքներ"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Ավելացնել"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Ջնջել <xliff:g id="PORT_NUMBER">%d</xliff:g> համարի միացքը"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Միացքի անվավեր համար"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Միացքն արդեն գոյություն ունի"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Տերմինալը խնդրում է նոր միացք բացել"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Հարցված միացքը՝ <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Ընդունել"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Մերժել"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Վերականգ­նում"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Տերմինալը փակվում է"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Ստիպողաբար փակել"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>-ը միացված է"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Երկար աշխատող առաջադրանքներ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Համակարգի իրադարձություններ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-in/strings.xml b/android/TerminalApp/res/values-in/strings.xml
index 1a844b1..9c2be8d 100644
--- a/android/TerminalApp/res/values-in/strings.xml
+++ b/android/TerminalApp/res/values-in/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Gagal menginstal karena Wi-Fi tidak tersedia"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Gagal menginstal. Coba lagi"</string>
     <string name="action_settings" msgid="5729342767795123227">"Setelan"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Menyiapkan terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Menghentikan terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal error"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kontrol port"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Izinkan/tolak port yang sedang dalam proses"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Port yang sedang dalam proses"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Port yang diizinkan tersimpan"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Tambahkan"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Hapus <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nomor port tidak valid"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port sudah ada"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal meminta untuk membuka port baru"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port yang diminta: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Terima"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Tolak"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Pemulihan"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal ditutup"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Tutup paksa"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> diaktifkan"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tugas yang berjalan lama"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Peristiwa sistem"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-is/strings.xml b/android/TerminalApp/res/values-is/strings.xml
index 638da38..3cb32e0 100644
--- a/android/TerminalApp/res/values-is/strings.xml
+++ b/android/TerminalApp/res/values-is/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Uppsetning tókst ekki vegna þess að Wi-Fi er ekki tiltækt"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Uppsetning tókst ekki. Reyndu aftur"</string>
     <string name="action_settings" msgid="5729342767795123227">"Stillingar"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Undirbýr útstöð"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stöðvar tengi"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Tengi hrundi"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Gáttarstýring"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Leyfa hlustunargáttir/hafna hlustunargáttum"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Hlustunargáttir"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Vistaðar leyfðar gáttir"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Bæta við"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Eyða <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ógilt númer tengis"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Tengi er þegar til"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Útstöðin bað um að opna nýja gátt"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Gátt sem beðið var um: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Samþykkja"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Hafna"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Endurheimt"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal er að loka"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Þvinga fram lokun"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Kveikt er á <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Langvarandi verkefni"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Kerfistilvik"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-it/strings.xml b/android/TerminalApp/res/values-it/strings.xml
index 5660cc3..b375706 100644
--- a/android/TerminalApp/res/values-it/strings.xml
+++ b/android/TerminalApp/res/values-it/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Impossibile installare: Wi-Fi non disponibile"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Installazione non riuscita. Riprova"</string>
     <string name="action_settings" msgid="5729342767795123227">"Impostazioni"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparazione terminale in corso…"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Arresto del terminale in corso…"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Arresto anomalo del terminale"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Controllo porte"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Consenti/rifiuta porte di ascolto"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Porte di ascolto"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Porte consentite salvate"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Aggiungi"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Elimina <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Numero di porta non valido"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"La porta esiste già"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Il terminale sta chiedendo di aprire una nuova porta"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Porta richiesta: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accetta"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Rifiuta"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Ripristino"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Chiusura del terminale in corso…"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Termina"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> è abilitata"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Attività di lunga durata"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventi di sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-iw/strings.xml b/android/TerminalApp/res/values-iw/strings.xml
index 3ea2227..45f9162 100644
--- a/android/TerminalApp/res/values-iw/strings.xml
+++ b/android/TerminalApp/res/values-iw/strings.xml
@@ -20,7 +20,7 @@
     <string name="terminal_display" msgid="4810127497644015237">"תצוגת טרמינל"</string>
     <string name="terminal_input" msgid="4602512831433433551">"סמן"</string>
     <string name="empty_line" msgid="5012067143408427178">"שורה ריקה"</string>
-    <string name="double_tap_to_edit_text" msgid="2344363097580051316">"כדי להקליד טקסט צריך להקיש הקשה כפולה"</string>
+    <string name="double_tap_to_edit_text" msgid="2344363097580051316">"כדי להקליד טקסט צריך ללחוץ לחיצה כפולה"</string>
     <string name="installer_title_text" msgid="500663060973466805">"התקנה של טרמינל Linux"</string>
     <string name="installer_desc_text_format" msgid="5935117404303982823">"כדי להפעיל את טרמינל Linux, צריך להוריד נתונים בנפח של בערך <xliff:g id="EXPECTED_SIZE">%1$s</xliff:g> דרך הרשת.\nלהמשיך?"</string>
     <string name="installer_wait_for_wifi_checkbox_text" msgid="5812378362605046639">"הורדה רק באמצעות Wi-Fi"</string>
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ההתקנה נכשלה כי אין חיבור ל-Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ההתקנה נכשלה. אפשר לנסות שוב."</string>
     <string name="action_settings" msgid="5729342767795123227">"הגדרות"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"הטרמינל בהכנה"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"המערכת עוצרת את הטרמינל"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"הטרמינל קרס"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"בקרת יציאות"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"אישור או דחייה של יציאות להאזנה"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"יציאות להאזנה"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"‫<xliff:g id="PORT_NUMBER">%1$d</xliff:g> ‏(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"יציאות מורשות שנשמרו"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"הוספה"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"מחיקה של <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"מספר היציאה לא תקין"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"היציאה כבר קיימת"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"הטרמינל מבקש לפתוח יציאה חדשה"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"נשלחה בקשה ליציאה: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> ‏(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"אישור"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"דחייה"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"שחזור"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"הטרמינל בתהליך סגירה"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"אילוץ סגירה"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"‫<xliff:g id="ID_1">VirGL</xliff:g> מופעל"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"משימות ממושכות"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"אירועי מערכת"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ja/strings.xml b/android/TerminalApp/res/values-ja/strings.xml
index bcc3378..30be359 100644
--- a/android/TerminalApp/res/values-ja/strings.xml
+++ b/android/TerminalApp/res/values-ja/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi が利用できないためインストールできませんでした"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"インストールできませんでした。もう一度お試しください"</string>
     <string name="action_settings" msgid="5729342767795123227">"設定"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ターミナルを準備しています"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ターミナルを停止しています"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ターミナルがクラッシュしました"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ポートの管理"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"リスニング ポートの許可 / 拒否"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"リスニング ポート"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g>(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"保存済みの許可ポート"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"追加"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> を削除"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ポート番号が無効です"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ポートはすでに存在します"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ターミナルが新しいポートを開くリクエストをしました"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"リクエストされたポート: <xliff:g id="PORT_NUMBER">%1$d</xliff:g>(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"許可する"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"許可しない"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"リカバリ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ターミナルを閉じています"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"強制終了"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>は有効です"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"長時間実行タスク"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"システム イベント"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ka/strings.xml b/android/TerminalApp/res/values-ka/strings.xml
index 51960f6..600ce7f 100644
--- a/android/TerminalApp/res/values-ka/strings.xml
+++ b/android/TerminalApp/res/values-ka/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi მიუწვდომელია, ამიტომ ინსტალაცია ვერ მოხერხდა"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ვერ მოახერხდა ინსტალაცია. გთხოვთ, ცადოთ ხელახლა"</string>
     <string name="action_settings" msgid="5729342767795123227">"პარამეტრები"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"მიმდინარეობს ტერმინალის მომზადება"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"მიმდინარეობს ტერმინალის შეწყვეტა"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ტერმინალი გაჭედილია"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"პორტის მართვა"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"მოსმენის პორტების დაშვება/აკრძალვა"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"მოსმენის პორტები"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"შენახული დაშვებული პორტები"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"დამატება"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g>-ის წაშლა"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"პორტის არასწორი ნომერი"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"პორტი უკვე არსებობს"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ტერმინალი ითხოვს ახალი პორტის გახსნას"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"მოთხოვნილი პორტი: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"დათანხმება"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"უარყოფა"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"აღდგენა"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ტერმინალი იხურება"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"იძულებით დახურვა"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ჩართულია"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ხანგრძლივად გაშვებული ამოცანები"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"სისტემური მოვლენები"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-kk/strings.xml b/android/TerminalApp/res/values-kk/strings.xml
index ea12254..d4a246d 100644
--- a/android/TerminalApp/res/values-kk/strings.xml
+++ b/android/TerminalApp/res/values-kk/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Орнатылмады, себебі Wi-Fi желісі жоқ."</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Орнату мүмкін болмады. Қайталап көріңіз."</string>
     <string name="action_settings" msgid="5729342767795123227">"Параметрлер"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминал дайындалып жатыр."</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Терминал тоқтатылып жатыр."</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Терминал бұзылды."</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Портты басқару"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Тыңдау порттарына рұқсат беру/тыйым салу"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Тыңдау порттары"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Рұқсат берілген порттар сақталды"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Қосу"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> портты жою"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Порт нөмірі жарамсыз."</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт бұрыннан бар."</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминал жаңа порт ашуды сұрайды"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Қажетті порт: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Қабылдау"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Қабылдамау"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Қалпына келтіру"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминал жабылып жатыр"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Қолмен жабу"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> қосылды."</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Ұзақ орындалатын тапсырмалар"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Жүйе оқиғалары"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-km/strings.xml b/android/TerminalApp/res/values-km/strings.xml
index d85ead9..72316ae 100644
--- a/android/TerminalApp/res/values-km/strings.xml
+++ b/android/TerminalApp/res/values-km/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"មិនអាចដំឡើងបានទេ ដោយសារមិនមាន Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"មិនអាច​ដំឡើងបានទេ។ សូមព្យាយាមម្ដងទៀត"</string>
     <string name="action_settings" msgid="5729342767795123227">"ការកំណត់"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"កំពុងរៀបចំទែមីណាល់"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"កំពុងបញ្ឈប់ទែមីណាល់"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ទែមីណាល់បានគាំង"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ការគ្រប់គ្រងច្រក"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"អនុញ្ញាត/បដិសេធច្រកស្ដាប់"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ច្រកស្ដាប់"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"បានរក្សាទុកច្រកដែលត្រូវបានអនុញ្ញាត"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"បញ្ចូល"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"លុប <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"លេខច្រកមិនត្រឹមត្រូវ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"មានច្រករួចហើយ"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ទែមីណាល់កំពុងស្នើសុំបើកច្រកថ្មី"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"បានស្នើសុំច្រក៖ <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ទទួលយក"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"បដិសេធ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ស្ដារ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ទែមីណាល់កំពុងបិទ"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"បង្ខំ​ឱ្យ​បិទ"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ត្រូវបានបើក"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"កិច្ចការដែលដំណើរការរយៈពេលយូរ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"ព្រឹត្តិការណ៍ប្រព័ន្ធ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-kn/strings.xml b/android/TerminalApp/res/values-kn/strings.xml
index 8010e73..5f63626 100644
--- a/android/TerminalApp/res/values-kn/strings.xml
+++ b/android/TerminalApp/res/values-kn/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ವೈ-ಫೈ ಲಭ್ಯವಿಲ್ಲದ ಕಾರಣ ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="action_settings" msgid="5729342767795123227">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ಟರ್ಮಿನಲ್‌ ಅನ್ನು ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ಟರ್ಮಿನಲ್ ಅನ್ನು ನಿಲ್ಲಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ಟರ್ಮಿನಲ್ ಕ್ರ್ಯಾಶ್ ಆಗಿದೆ"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ಪೋರ್ಟ್ ನಿಯಂತ್ರಣ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"ಆಲಿಸುವ ಪೋರ್ಟ್‌ಗಳನ್ನು ಅನುಮತಿಸಿ/ನಿರಾಕರಿಸಿ"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ಆಲಿಸುವ ಪೋರ್ಟ್‌ಗಳು"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"ಅನುಮತಿಸಲಾದ ಪೋರ್ಟ್‌ಗಳನ್ನು ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ಸೇರಿಸಿ"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> ಅನ್ನು ಅಳಿಸಿ"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ಅಮಾನ್ಯ ಪೋರ್ಟ್ ಸಂಖ್ಯೆ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ಪೋರ್ಟ್ ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ಟರ್ಮಿನಲ್‌ ಹೊಸ ಪೋರ್ಟ್‌ ಅನ್ನು ತೆರೆಯಲು ವಿನಂತಿಸುತ್ತಿದೆ"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"ಪೋರ್ಟ್ ಅನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ಸಮ್ಮತಿಸಿ"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ನಿರಾಕರಿಸಿ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ರಿಕವರಿ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ಟರ್ಮಿನಲ್ ಮುಚ್ಚಲಾಗುತ್ತಿದೆ"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"ಬಲವಂತವಾಗಿ ಮುಚ್ಚಿ"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ದೀರ್ಘಾವಧಿಯ ಕಾರ್ಯಗಳು"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"ಸಿಸ್ಟಮ್ ಈವೆಂಟ್‌ಗಳು"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ko/strings.xml b/android/TerminalApp/res/values-ko/strings.xml
index 173cade..404c1d9 100644
--- a/android/TerminalApp/res/values-ko/strings.xml
+++ b/android/TerminalApp/res/values-ko/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi를 사용할 수 없어 설치하지 못했습니다."</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"설치할 수 없습니다. 다시 시도해 보세요."</string>
     <string name="action_settings" msgid="5729342767795123227">"설정"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"터미널 준비 중"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"터미널 중지 중"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"터미널 다운됨"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"포트 제어"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"리스닝 포트 허용/거부"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"리스닝 포트"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g>(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"저장된 허용 포트"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"추가"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> 삭제"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"포트 번호가 잘못되었습니다."</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"포트가 이미 존재합니다."</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"터미널에서 새 포트를 열려고 합니다"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"요청된 포트: <xliff:g id="PORT_NUMBER">%1$d</xliff:g>(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"수락"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"거부"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"복구"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"터미널 앱 종료 중"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"강제 종료"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>이(가) 사용 설정되었습니다."</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"장기 실행 태스크"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"시스템 이벤트"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ky/strings.xml b/android/TerminalApp/res/values-ky/strings.xml
index 21d0e2a..53cdc3b 100644
--- a/android/TerminalApp/res/values-ky/strings.xml
+++ b/android/TerminalApp/res/values-ky/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi жеткиликсиз болгондуктан, орнотулбай калды"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Орнотулган жок. Кайталап көрүңүз"</string>
     <string name="action_settings" msgid="5729342767795123227">"Параметрлер"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминал даярдалууда"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Терминал токтотулууда"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Терминал бузулду"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Портту көзөмөлдөө"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Угуу портторуна уруксат берүү/тыюу салуу"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Угуу порттору"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Уруксат берилген порттор сакталды"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Кошуу"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Өчүрүү: <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Порттун номери жараксыз"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт бар"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминал жаңы оюкчаны ачууну суранып жатат"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Оюкча суралды: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Кабыл алуу"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Четке кагуу"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Калыбына келтирүү"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминал жабылып жатат"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Мажбурлап жабуу"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> иштетилди"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Узак тапшырмалар"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Тутумдук иш-чаралар"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-lo/strings.xml b/android/TerminalApp/res/values-lo/strings.xml
index 109a304..e8f1993 100644
--- a/android/TerminalApp/res/values-lo/strings.xml
+++ b/android/TerminalApp/res/values-lo/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ຕິດຕັ້ງບໍ່ສຳເລັດເນື່ອງຈາກບໍ່ມີ Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ຕິດຕັ້ງບໍ່ສໍາເລັດ. ກະລຸນາລອງໃໝ່"</string>
     <string name="action_settings" msgid="5729342767795123227">"ການຕັ້ງຄ່າ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ກຳລັງກະກຽມເທີມິນອນ"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ກຳລັງຢຸດເທີມິນອນ"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ເທີມິນອນຫຼົ້ມ"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ການຄວບຄຸມຜອດ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"ອະນຸຍາດ/ປະຕິເສດຜອດການຟັງ"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ຜອດການຟັງ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"ຜອດທີ່ອະນຸຍາດເຊິ່ງບັນທຶກໄວ້"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ເພີ່ມ"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"ລຶບ <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ໝາຍເລກຜອດບໍ່ຖືກຕ້ອງ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ມີຜອດຢູ່ກ່ອນແລ້ວ"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ເທີມິນອນກຳລັງສົ່ງຄຳຮ້ອງຂໍໃຫ້ເປີດຜອດໃໝ່"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"ຜອດທີ່ຮ້ອງຂໍ: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ຍອມຮັບ"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ປະຕິເສດ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ການກູ້ຄືນ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ເທີມິນອນກຳລັງຈະປິດ"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"ບັງຄັບປິດ"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"ເປີດການນຳໃຊ້ <xliff:g id="ID_1">VirGL</xliff:g> ແລ້ວ"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ວຽກທີ່ດຳເນີນເປັນເວລາດົນ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"ກິດຈະກຳລະບົບ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-lt/strings.xml b/android/TerminalApp/res/values-lt/strings.xml
index beefadd..aabd487 100644
--- a/android/TerminalApp/res/values-lt/strings.xml
+++ b/android/TerminalApp/res/values-lt/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Nepavyko įdiegti, nes „Wi-Fi“ nepasiekiamas"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Nepavyko įdiegti. Bandykite dar kartą"</string>
     <string name="action_settings" msgid="5729342767795123227">"Nustatymai"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Ruošiamas terminalas"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminalas sustabdomas"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminalas užstrigo"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Prievado valdymas"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Leisti klausymo prievadus / neleisti jų"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Klausymo prievadai"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Išsaugoti leidžiami prievadai"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Pridėti"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Ištrinti <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Netinkamas prievado numeris"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Prievadas jau yra"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminalas bando atidaryti naują prievadą"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Prievadas, kurio užklausa pateikta: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Sutikti"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Atmesti"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Atkūrimas"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminalas uždaromas"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Priverstinai uždaryti"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"„<xliff:g id="ID_1">VirGL</xliff:g>“ įgalinta"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Ilgai vykdomos užduotys"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemos įvykiai"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-lv/strings.xml b/android/TerminalApp/res/values-lv/strings.xml
index d45aeb3..9f0d902 100644
--- a/android/TerminalApp/res/values-lv/strings.xml
+++ b/android/TerminalApp/res/values-lv/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Instalēšana neizdevās, jo nav pieejams Wi‑Fi savienojums"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Neizdevās instalēt — mēģiniet vēlreiz"</string>
     <string name="action_settings" msgid="5729342767795123227">"Iestatījumi"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Notiek termināļa sagatavošana."</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Notiek termināļa apturēšana."</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminālis avarēja."</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portu kontrole"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Atļaut/aizliegt klausīšanās portus"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Klausīšanās porti"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Saglabātie atļautie porti"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Pievienot"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Dzēst <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nederīgs porta numurs"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Ports jau pastāv"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminālis pieprasa jauna porta atvēršanu"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Pieprasītais ports: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Piekrist"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Noraidīt"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Atkopšana"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminālis tiek aizvērts"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Veikt piespiedu aizvēršanu"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ir iespējots"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Ilgstoši uzdevumi"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistēmas notikumi"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-mk/strings.xml b/android/TerminalApp/res/values-mk/strings.xml
index 99cc48c..0a14e42 100644
--- a/android/TerminalApp/res/values-mk/strings.xml
+++ b/android/TerminalApp/res/values-mk/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Не можеше да се инсталира бидејќи не е достапна Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Не можеше да се инсталира. Обидете се повторно"</string>
     <string name="action_settings" msgid="5729342767795123227">"Поставки"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминалот се подготвува"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Терминалот се сопира"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Терминалот падна"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Контрола на портите"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Дозволете/одбијте порти за примање барања"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Порти за примање барања"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Дозволените порти се зачувани"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Додај"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Избриши <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Неважечки број на порта"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Портата веќе постои"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминалот бара да отвори нова порта"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Побарана е порта: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Прифати"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Одбиј"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Враќање"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминалот се затвора"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Затвори присилно"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Овозможено: <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Задачи што се извршуваат долго"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системски настани"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ml/strings.xml b/android/TerminalApp/res/values-ml/strings.xml
index c2bab30..4f8ec14 100644
--- a/android/TerminalApp/res/values-ml/strings.xml
+++ b/android/TerminalApp/res/values-ml/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"വൈഫൈ ലഭ്യമല്ലാത്തതിനാൽ ഇൻസ്‌റ്റാൾ ചെയ്യാനായില്ല"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ഇൻസ്റ്റാൾ ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="action_settings" msgid="5729342767795123227">"ക്രമീകരണം"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ടെർമിനൽ തയ്യാറാക്കുന്നു"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ടെർമിനൽ നിർത്തുന്നു"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ടെർമിനൽ ക്രാഷായി"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"പോർട്ട് നിയന്ത്രണം"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"ശ്രവണ പോർട്ടുകൾ അനുവദിക്കുക/നിരസിക്കുക"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ശ്രവണ പോർട്ടുകൾ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"സംരക്ഷിച്ച അനുവദനീയമായ പോർട്ടുകൾ"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ചേർക്കുക"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> ഇല്ലാതാക്കുക"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"പോർട്ട് നമ്പർ അസാധുവാണ്"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"പോർട്ട് ഇതിനകം നിലവിലുണ്ട്"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ഒരു പുതിയ പോർട്ട് തുറക്കാൻ ടെർമിനൽ അഭ്യർത്ഥിക്കുന്നു"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"അഭ്യർത്ഥിച്ച പോർട്ട്: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"അംഗീകരിക്കുക"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"നിരസിക്കുക"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"വീണ്ടെടുക്കുക"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ടെർമിനൽ അടയ്ക്കുകയാണ്"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"നിർബന്ധിതമായി അടയ്ക്കുക"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> പ്രവർത്തനക്ഷമമാക്കി"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ദീർഘസമയം റൺ ചെയ്യുന്ന ടാസ്ക്കുകൾ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"സിസ്റ്റം ഇവന്റുകൾ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-mn/strings.xml b/android/TerminalApp/res/values-mn/strings.xml
index 4849006..75983d4 100644
--- a/android/TerminalApp/res/values-mn/strings.xml
+++ b/android/TerminalApp/res/values-mn/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi боломжгүй тул суулгаж чадсангүй"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Суулгаж чадсангүй. Дахин оролдоно уу"</string>
     <string name="action_settings" msgid="5729342767795123227">"Тохиргоо"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминалыг бэлтгэж байна"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Терминалыг зогсоож байна"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Терминал гэмтсэн"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Портын тохиргоо"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Сүлжээний хүсэлт хүлээж буй портуудыг зөвшөөрөх/татгалзах"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Сүлжээний хүсэлт хүлээж буй портууд"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Хадгалсан зөвшөөрөгдсөн портууд"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Нэмэх"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g>-г устгах"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Портын дугаар буруу байна"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт аль хэдийн байна"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминал шинэ порт нээхийг хүсэж байна"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Хүссэн порт: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Зөвшөөрөх"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Татгалзах"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Сэргээх"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминал хаагдаж байна"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Хүчээр хаах"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> идэвхэжсэн"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Удаан ажиллаж буй ажил"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системийн үйл явдал"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-mr/strings.xml b/android/TerminalApp/res/values-mr/strings.xml
index 70a093e..19c27f5 100644
--- a/android/TerminalApp/res/values-mr/strings.xml
+++ b/android/TerminalApp/res/values-mr/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"वाय-फाय उपलब्ध नसल्यामुळे इंस्टॉल करता आले नाही"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"इंस्टॉल करता आले नाही. कृपया पुन्हा प्रयत्न करा"</string>
     <string name="action_settings" msgid="5729342767795123227">"सेटिंग्ज"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"टर्मिनल तयार करत आहे"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"टर्मिनल थांबवत आहे"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"टर्मिनल क्रॅश झाले आहे"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"पोर्ट नियंत्रण"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"ऐकण्याच्या पोर्टना अनुमती द्या/नाकारा"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ऐकण्याचे पोर्ट"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"सेव्ह केलेले व अनुमती असलेले पोर्ट"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"जोडा"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> हटवा"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"पोर्ट नंबर चुकीचा आहे"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"पोर्ट आधीपासून अस्तित्वात आहे"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"टर्मिनल नवीन पोर्ट उघडण्याची विनंती करत आहे"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"पोर्टसंबंधित विनंती केली: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"स्वीकारा"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"नकार द्या"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"रिकव्हरी"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"टर्मिनल बंद होत आहे"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"सक्तीने बंद करा"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> सुरू केले आहे"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"दीर्घवेळ रन होणाऱ्या टास्क"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"सिस्टीम इव्‍हेंट"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ms/strings.xml b/android/TerminalApp/res/values-ms/strings.xml
index a14d938..1a97ac0 100644
--- a/android/TerminalApp/res/values-ms/strings.xml
+++ b/android/TerminalApp/res/values-ms/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Gagal melakukan pemasangan kerana Wi-Fi tidak tersedia"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Gagal melakukan pemasangan. Sila cuba lagi"</string>
     <string name="action_settings" msgid="5729342767795123227">"Tetapan"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Menyediakan terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Menghentikan terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal ranap"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kawalan port"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Benarkan/tolak port mendengar"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Port mendengar"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Port yang dibenarkan disimpan"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Tambah"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Padamkan <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nombor port tidak sah"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port sudah wujud"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal membuat permintaan untuk membuka port baharu"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port diminta: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Terima"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Tolak"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Pemulihan"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal ditutup"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Tutup paksa"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> didayakan"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tugasan yang memakan masa yang lama"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Peristiwa sistem"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-my/strings.xml b/android/TerminalApp/res/values-my/strings.xml
index eda6e90..a723a0a 100644
--- a/android/TerminalApp/res/values-my/strings.xml
+++ b/android/TerminalApp/res/values-my/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi မရနိုင်သောကြောင့် ထည့်သွင်း၍မရလိုက်ပါ"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ထည့်သွင်း၍ မရလိုက်ပါ။ ထပ်စမ်းကြည့်ပါ"</string>
     <string name="action_settings" msgid="5729342767795123227">"ဆက်တင်များ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"တာမီနယ်ကို ပြင်ဆင်နေသည်"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"တာမီနယ်ကို ရပ်နေသည်"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"တာမီနယ် ရပ်တန့်သွားသည်"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ပို့တ်ထိန်းချုပ်မှု"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"စောင့်နေသောပို့တ်များကို ခွင့်ပြုရန်/ငြင်းပယ်ရန်"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"စောင့်နေသောပို့တ်များ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"ခွင့်ပြုထားသောပို့တ်များ သိမ်းပြီးပြီ"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ထည့်ရန်"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> ကို ဖျက်ရန်"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ပို့တ်နံပါတ် မမှန်ပါ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ပို့တ်ရှိပြီးသားဖြစ်သည်"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"တာမီနယ်က ပို့တ်အသစ်ဖွင့်ရန် တောင်းဆိုနေသည်"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"တောင်းဆိုထားသော ပို့တ်- <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"လက်ခံရန်"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ငြင်းပယ်ရန်"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ပြန်လည်ရယူခြင်း"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"တာမီနယ် ပိတ်နေသည်"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"မဖြစ်မနေပိတ်ရန်"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ဖွင့်ထားသည်"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"အချိန်ကြာသော လုပ်ဆောင်စရာများ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"စနစ်ဖြစ်စဉ်များ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-nb/strings.xml b/android/TerminalApp/res/values-nb/strings.xml
index b2492db..7041a85 100644
--- a/android/TerminalApp/res/values-nb/strings.xml
+++ b/android/TerminalApp/res/values-nb/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Kunne ikke installere fordi wifi ikke er tilgjengelig"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Installasjonen mislyktes. Prøv igjen"</string>
     <string name="action_settings" msgid="5729342767795123227">"Innstillinger"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Forbereder terminalen"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stopper terminalen"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminalen krasjet"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portkontroll"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Tillat/avslå lytteporter"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Lytteporter"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Lagrede tillatte porter"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Legg til"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Slett <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ugyldig portnummer"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Porten finnes allerede"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminalen prøver å åpne en ny port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Ønsket port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Godta"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Avvis"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Gjenoppretting"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminalen lukkes"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Tving avslutning"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> er aktivert"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Langvarige oppgaver"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systemhendelser"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ne/strings.xml b/android/TerminalApp/res/values-ne/strings.xml
index 714dcf3..23ee146 100644
--- a/android/TerminalApp/res/values-ne/strings.xml
+++ b/android/TerminalApp/res/values-ne/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi उपलब्ध नभएकाले इन्स्टल गर्न सकिएन"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"इन्स्टल गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्"</string>
     <string name="action_settings" msgid="5729342767795123227">"सेटिङ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"टर्मिनल तयार पारिँदै छ"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"टर्मिनल रोकिँदै छ"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"टर्मिनल क्र्यास भयो"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"पोर्टसम्बन्धी कन्ट्रोल"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"लिसनिङ पोर्टहरू हाल्ने अनुमति दिनुहोस्/नदिनुहोस्"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"लिसनिङ पोर्टहरू"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"सेभ गरिएका अनुमति दिइएका पोर्टहरू"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"हाल्नुहोस्"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> मेटाउनुहोस्"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"अवैध पोर्ट नम्बर"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"पोर्ट पहिल्यैदेखि छ"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"टर्मिनलले एउटा नयाँ पोर्ट खोल्न अनुरोध गरिरहेको छ"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"निम्न पोर्ट खोल्न अनुरोध गरिएको छ: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"स्वीकार गर्नुहोस्"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"अस्वीकार गर्नुहोस्"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"रिकभरी"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"टर्मिनल एप बन्द हुँदै छ"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"बलपूर्वक बन्द गर्नुहोस्"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> अन गरिएको छ"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"लामो समयसम्म चलिरहने कार्यहरू"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"सिस्टमसम्बन्धी गतिविधिहरू"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-nl/strings.xml b/android/TerminalApp/res/values-nl/strings.xml
index 6c1e42a..f6c0c7b 100644
--- a/android/TerminalApp/res/values-nl/strings.xml
+++ b/android/TerminalApp/res/values-nl/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Kan niet installeren omdat wifi niet beschikbaar is"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Installatie mislukt. Probeer het opnieuw."</string>
     <string name="action_settings" msgid="5729342767795123227">"Instellingen"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminal voorbereiden"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminal stoppen"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal gecrasht"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Poortcontrole"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Luisterende poorten toestaan/weigeren"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Luisterende poorten"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Toegestane poorten opgeslagen"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Toevoegen"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> verwijderen"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ongeldig poortnummer"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Poort bestaat al"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal verzoekt om een nieuwe poort te openen"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Poort aangevraagd: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Accepteren"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Weigeren"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Herstel"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal wordt gesloten"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Geforceerd sluiten"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> staat aan"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Langlopende taken"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systeemgebeurtenissen"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-or/strings.xml b/android/TerminalApp/res/values-or/strings.xml
index 29855af..5918183 100644
--- a/android/TerminalApp/res/values-or/strings.xml
+++ b/android/TerminalApp/res/values-or/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ୱାଇ-ଫାଇ ଉପଲବ୍ଧ ନଥିବା ଯୋଗୁଁ ଇନଷ୍ଟଲ କରିବାରେ ବିଫଳ ହୋଇଛି"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ଇନଷ୍ଟଲ କରିବାରେ ବିଫଳ ହୋଇଛି। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="action_settings" msgid="5729342767795123227">"ସେଟିଂସ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ଟର୍ମିନାଲକୁ ପ୍ରସ୍ତୁତ କରାଯାଉଛି"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminalକୁ ବନ୍ଦ କରାଯାଉଛି"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ଟର୍ମିନାଲ କ୍ରାସ ହୋଇଛି"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ପୋର୍ଟ ନିୟନ୍ତ୍ରଣ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"ଶୁଣିବା ପୋର୍ଟଗୁଡ଼ିକୁ ଅନୁମତି ଦିଅନ୍ତୁ/ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ଶୁଣିବା ପୋର୍ଟ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"ଅନୁମତି ଦିଆଯାଇଥିବା ପୋର୍ଟଗୁଡ଼ିକୁ ସେଭ କରାଯାଇଛି"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ଯୋଗ କରନ୍ତୁ"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g>କୁ ଡିଲିଟ କରନ୍ତୁ"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ଅବୈଧ ପୋର୍ଟ ନମ୍ବର"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ପୋର୍ଟ ପୂର୍ବରୁ ଉପଲବ୍ଧ ଅଛି"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ଏକ ନୂଆ ପୋର୍ଟ ଖୋଲିବାକୁ ଟର୍ମିନାଲ ଅନୁରୋଧ କରୁଛି"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"ପୋର୍ଟ ପାଇଁ ଅନୁରୋଧ କରାଯାଇଛି: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ଗ୍ରହଣ କରନ୍ତୁ"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ରିକଭରି"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ଟର୍ମିନାଲ ବନ୍ଦ ହେବାକୁ ଯାଉଛି"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"ଫୋର୍ସ କ୍ଲୋଜ କରନ୍ତୁ"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>କୁ ସକ୍ଷମ କରାଯାଇଛି"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ଅଧିକ ସମୟ ଚାଲୁଥିବା ଟାସ୍କ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"ସିଷ୍ଟମ ଇଭେଣ୍ଟ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-pa/strings.xml b/android/TerminalApp/res/values-pa/strings.xml
index a4279ce..904f0e2 100644
--- a/android/TerminalApp/res/values-pa/strings.xml
+++ b/android/TerminalApp/res/values-pa/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਾ ਹੋਣ ਕਰਕੇ ਸਥਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ਸਥਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="action_settings" msgid="5729342767795123227">"ਸੈਟਿੰਗਾਂ"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ਟਰਮੀਨਲ ਨੂੰ ਤਿਆਰ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ਟਰਮੀਨਲ ਨੂੰ ਬੰਦ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ਟਰਮੀਨਲ ਕ੍ਰੈਸ਼ ਹੋ ਗਿਆ"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"ਪੋਰਟ ਕੰਟਰੋਲ"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"ਲਿਸਨਿੰਗ ਪੋਰਟਾਂ ਨੂੰ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"ਲਿਸਨਿੰਗ ਪੋਰਟ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"ਮਨਜ਼ੂਰਸ਼ੁਦਾ ਪੋਰਟ ਰੱਖਿਅਤ ਕੀਤੇ ਗਏ"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> ਨੂੰ ਮਿਟਾਓ"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"ਅਵੈਧ ਪੋਰਟ ਨੰਬਰ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"ਪੋਰਟ ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਮੌਜੂਦ ਹੈ"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ਟਰਮੀਨਲ ਇੱਕ ਨਵੇਂ ਪੋਰਟ ਨੂੰ ਖੋਲ੍ਹਣ ਦੀ ਬੇਨਤੀ ਕਰ ਰਿਹਾ ਹੈ"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"ਪੋਰਟ ਸੰਬੰਧੀ ਬੇਨਤੀ ਕੀਤੀ ਗਈ: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ਸਵੀਕਾਰ ਕਰੋ"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ਰਿਕਵਰੀ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ਟਰਮੀਨਲ ਬੰਦ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"ਜ਼ਬਰਦਸਤੀ ਬੰਦ ਕਰੋ"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ਚਾਲੂ ਹੈ"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ਲੰਬੇ ਸਮੇਂ ਤੱਕ ਚੱਲਣ ਵਾਲੇ ਕਾਰਜ"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"ਸਿਸਟਮ ਇਵੈਂਟ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-pl/strings.xml b/android/TerminalApp/res/values-pl/strings.xml
index 924c14c..fc2c879 100644
--- a/android/TerminalApp/res/values-pl/strings.xml
+++ b/android/TerminalApp/res/values-pl/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Nie udało się zainstalować, ponieważ Wi-Fi jest niedostępne"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Nie udało się zainstalować. Spróbuj jeszcze raz"</string>
     <string name="action_settings" msgid="5729342767795123227">"Ustawienia"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Przygotowuję terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Zatrzymuję terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal uległ awarii"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kontrola portów"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Zezwalaj/odrzucaj porty nasłuchujące"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Porty nasłuchujące"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Zapisane dozwolone porty"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Dodaj"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Usuń port <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Nieprawidłowy numer portu"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port już istnieje"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal wysłał żądanie otwarcia nowego portu"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Żądany port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Zaakceptuj"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Odrzuć"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Odzyskiwanie"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal się zamyka"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Wymuś zamknięcie"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Układ <xliff:g id="ID_1">VirGL</xliff:g> jest włączony"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Długotrwałe zadania"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Zdarzenia systemowe"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-pt-rPT/strings.xml b/android/TerminalApp/res/values-pt-rPT/strings.xml
index 3a57ba6..b1660e5 100644
--- a/android/TerminalApp/res/values-pt-rPT/strings.xml
+++ b/android/TerminalApp/res/values-pt-rPT/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Falha ao instalar porque o Wi-Fi não está disponível"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Falha ao instalar. Tente novamente"</string>
     <string name="action_settings" msgid="5729342767795123227">"Definições"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"A preparar o terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"A parar o terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"O terminal falhou"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Controlo de portas"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permitir/negar portas de audição"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Portas de audição"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Portas permitidas guardadas"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Adicionar"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Eliminar <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Número de porta inválido"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"A porta já existe"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"O terminal está a pedir para abrir uma nova porta"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Porta pedida: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Aceitar"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Recusar"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperação"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"A app Terminal está a ser fechada"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forçar fecho"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"A <xliff:g id="ID_1">VirGL</xliff:g> está ativada"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tarefas de longa duração"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos do sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-pt/strings.xml b/android/TerminalApp/res/values-pt/strings.xml
index 9d6a16f..6afd19a 100644
--- a/android/TerminalApp/res/values-pt/strings.xml
+++ b/android/TerminalApp/res/values-pt/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Falha ao instalar porque o Wi-Fi não está disponível"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Falha ao instalar. Tente de novo"</string>
     <string name="action_settings" msgid="5729342767795123227">"Configurações"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Preparando o terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Interrompendo o terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"O terminal falhou"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Controle de portas"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permitir/negar portas de detecção"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Portas de detecção"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"As portas permitidas foram salvas"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Adicionar"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Excluir <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Número de porta inválido"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"A porta já existe"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"O terminal está pedindo para abrir uma nova porta"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Porta solicitada: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Aceitar"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Negar"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperação"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"O terminal está fechando"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forçar fechamento"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"O <xliff:g id="ID_1">VirGL</xliff:g> está ativado"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tarefas de longa duração"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Eventos do sistema"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ro/strings.xml b/android/TerminalApp/res/values-ro/strings.xml
index 779277e..cd8697f 100644
--- a/android/TerminalApp/res/values-ro/strings.xml
+++ b/android/TerminalApp/res/values-ro/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Nu s-a putut instala deoarece nu este disponibilă o conexiune Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Nu s-a instalat. Încearcă din nou."</string>
     <string name="action_settings" msgid="5729342767795123227">"Setări"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Se pregătește terminalul"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Se oprește terminalul"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminalul s-a blocat"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Controlul porturilor"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Permite / refuză porturile active"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Porturi active"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Porturi permise salvate"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Adaugă"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Șterge <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Număr de port nevalid"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Portul există deja"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminalul solicită să deschidă un nou port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Portul solicitat: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Acceptă"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Refuză"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Recuperare"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminalul se închide"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Forțează închiderea"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> este activat"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Activități de durată"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Evenimente de sistem"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ru/strings.xml b/android/TerminalApp/res/values-ru/strings.xml
index ffdcaf6..036baea 100644
--- a/android/TerminalApp/res/values-ru/strings.xml
+++ b/android/TerminalApp/res/values-ru/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Не удалось выполнить установку, так как сеть Wi-Fi недоступна."</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Сбой установки. Повторите попытку."</string>
     <string name="action_settings" msgid="5729342767795123227">"Настройки"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминал подготавливается."</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Работа терминала останавливается."</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Произошел сбой терминала."</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Управление портами"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Открыть/закрыть доступ к портам прослушивания"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Порты прослушивания"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Сохраненные порты с открытым доступом"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Добавить"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Удалить <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Неверный номер порта."</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт уже существует."</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминал просит открыть новый порт"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Запрашиваемый порт: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Разрешить"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Не разрешать"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Восста­но­вле­ние"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминал закрывается"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Закрыть принудительно"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g>: включено."</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Длительные задачи"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системные события"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-si/strings.xml b/android/TerminalApp/res/values-si/strings.xml
index cc67088..8987cac 100644
--- a/android/TerminalApp/res/values-si/strings.xml
+++ b/android/TerminalApp/res/values-si/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi නොමැති නිසා ස්ථාපනය කිරීමට අසමත් විය"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ස්ථාපනය කිරීමට අසමත් විය. නැවත උත්සාහ කරන්න"</string>
     <string name="action_settings" msgid="5729342767795123227">"සැකසීම්"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ටර්මිනලය සූදානම් කිරීම"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ටර්මිනලය නතර කිරීම"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ටර්මිනලය බිඳ වැටුණි"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"පෝටය පාලනය"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"සවන්දීමේ පෝටයන්ට ඉඩ දෙන්න/ප්‍රතික්ෂේප කරන්න"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"සවන්දීමේ පෝටයන්"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> <xliff:g id="PROCESS_NAME">%2$s</xliff:g>"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"සුරකින ලද ඉඩ දුන් පෝටයන්"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"එක් කරන්න"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> මකන්න"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"වලංගු නොවන පෝට අංකය"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"පෝටය දැනටමත් පවතී"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ටර්මිනලය නව පෝටයක් විවෘත කිරීමට ඉල්ලීම් කරයි"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"පෝටය ඉල්ලා ඇත: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"පිළිගන්න"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ප්‍රතික්ෂේප කරන්න"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"ප්‍රතිසාධනය"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ටර්මිනලය වැසෙමින් පවතී"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"බලෙන් වසන්න"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> සබලයි"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"දිගු කාලයක් ධාවනය වන කාර්යයන්"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"පද්ධති සිදුවීම්"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sk/strings.xml b/android/TerminalApp/res/values-sk/strings.xml
index 64abba6..b975f75 100644
--- a/android/TerminalApp/res/values-sk/strings.xml
+++ b/android/TerminalApp/res/values-sk/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Inštalácia sa nepodarila, pretože nie je k dispozícii Wi‑Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Nepodarilo sa nainštalovať. Skúste to znova."</string>
     <string name="action_settings" msgid="5729342767795123227">"Nastavenia"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminál sa pripravuje"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminál sa zastavuje"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminál spadol"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Ovládanie portov"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Povoliť alebo zakázať porty počúvania"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Porty počúvania"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Uložené povolené porty"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Pridať"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Odstrániť <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Neplatné číslo portu"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port už existuje"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminál požaduje otvoriť nový port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Požadovaný port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Prijať"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Zamietnuť"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Obnovenie"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminál sa zatvára"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Vynútiť zavretie"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Procesor <xliff:g id="ID_1">VirGL</xliff:g> je aktivovaný"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dlho spustené úlohy"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systémové udalosti"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sl/strings.xml b/android/TerminalApp/res/values-sl/strings.xml
index 8d8dc3a..bd20f4e 100644
--- a/android/TerminalApp/res/values-sl/strings.xml
+++ b/android/TerminalApp/res/values-sl/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Namestitev ni uspela, ker Wi-Fi ni na voljo"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Namestitev ni uspela. Poskusite znova."</string>
     <string name="action_settings" msgid="5729342767795123227">"Nastavitve"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Pripravljanje terminala"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Ustavljanje terminala"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal se je zrušil"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Nadzor vrat"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Dovoli/zavrni vrata za poslušanje"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Vrata za poslušanje"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Shranjena dovoljena vrata"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Dodaj"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Izbriši <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Neveljavna številka vrat"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Vrata že obstajajo"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal zahteva odpiranje novih vrat"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Zahtevana vrata: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Sprejmi"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Zavrni"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Obnovitev"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal se zapira"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Vsili zapiranje"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> je omogočen"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Dolgotrajna opravila"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistemski dogodki"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sq/strings.xml b/android/TerminalApp/res/values-sq/strings.xml
index 871671d..efcecc9 100644
--- a/android/TerminalApp/res/values-sq/strings.xml
+++ b/android/TerminalApp/res/values-sq/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Instalimi dështoi për shkak se Wi-Fi nuk ofrohet"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Instalimi dështoi. Provo përsëri"</string>
     <string name="action_settings" msgid="5729342767795123227">"Cilësimet"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminali po përgatitet"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminali po ndalohet"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminali u ndërpre aksidentalisht"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kontrolli i portës"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Lejo/refuzo portat e dëgjimit"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Portat e dëgjimit"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Portat e lejuara të ruajtura"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Shto"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Fshi <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Numër i pavlefshëm i portës"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Porta ekziston tashmë"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminali po përpiqet të hapë një portë të re"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Porta e kërkuar: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Prano"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Refuzo"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Rikuperimi"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"\"Terminali\" po mbyllet"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Ndalo me forcë"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> është aktivizuar"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Detyrat afatgjata"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Ngjarjet e sistemit"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sr/strings.xml b/android/TerminalApp/res/values-sr/strings.xml
index 76e790d..41d8d84 100644
--- a/android/TerminalApp/res/values-sr/strings.xml
+++ b/android/TerminalApp/res/values-sr/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Инсталирање није успело јер WiFi није доступан"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Инсталирање није успело. Пробајте поново"</string>
     <string name="action_settings" msgid="5729342767795123227">"Подешавања"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Терминал се припрема"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Терминал се зауставља"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Терминал је отказао"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Контрола порта"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Дозволите или забраните портове за слушање"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Портови за слушање"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Сачувани дозвољени портови"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Додај"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Избриши <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Неважећи број порта"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт већ постоји"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Терминал тражи да отвори нови порт"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Обавезан порт: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Прихвати"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Одбиј"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Опоравак"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Терминал се затвара"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Принудно затвори"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> је омогућен"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Дуготрајни задаци"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Системски догађаји"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sv/strings.xml b/android/TerminalApp/res/values-sv/strings.xml
index 33b00d8..9829814 100644
--- a/android/TerminalApp/res/values-sv/strings.xml
+++ b/android/TerminalApp/res/values-sv/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Det gick inte att installera eftersom att wifi inte är tillgängligt"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Installationen misslyckades. Försök igen"</string>
     <string name="action_settings" msgid="5729342767795123227">"Inställningar"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminalen förbereds"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Stoppar terminalen"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminalen kraschade"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portkontroll"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Tillåt/neka lyssningsportar"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Lyssningsportar"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Sparade tillåtna portar"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Lägg till"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Radera <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Ogiltigt portnummer"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Porten finns redan"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminalen begär att öppna en ny port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Port som begärs: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Godkänn"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Neka"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Återställning"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminalen stängs av"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Tvinga avstängning"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> har aktiverats"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Långvariga uppgifter"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Systemhändelser"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-sw/strings.xml b/android/TerminalApp/res/values-sw/strings.xml
index 2affb51..2da2dbf 100644
--- a/android/TerminalApp/res/values-sw/strings.xml
+++ b/android/TerminalApp/res/values-sw/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Imeshindwa kuweka kwenye kifaa kwa sababu Wi-Fi haipatikani"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Imeshindwa kuweka kwenye kifaa. Tafadhali jaribu tena"</string>
     <string name="action_settings" msgid="5729342767795123227">"Mipangilio"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Inaandaa temino"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Inafunga temino"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Temino imeacha kufanya kazi"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Udhibiti wa mlango"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Ruhusu au kataa milango ya usikilizaji"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Milango ya usikilizaji"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Umehifadhi milango inayoruhusiwa"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Weka"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Futa <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Namba ya mlango si sahihi"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Tayari mlango upo"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Temino inatuma ombi la kufungua mlango mpya"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Ombi la mlango: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Kubali"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Kataa"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Kurejesha"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Kituo kinafungwa"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Lazimisha kufunga"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> imewashwa"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Majukumu yanayodumu zaidi"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Matukio ya mfumo"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ta/strings.xml b/android/TerminalApp/res/values-ta/strings.xml
index a0e56d5..b6e7715 100644
--- a/android/TerminalApp/res/values-ta/strings.xml
+++ b/android/TerminalApp/res/values-ta/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"வைஃபை கிடைக்காததால் நிறுவ முடியவில்லை"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"நிறுவ முடியவில்லை. மீண்டும் முயலவும்."</string>
     <string name="action_settings" msgid="5729342767795123227">"அமைப்புகள்"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"டெர்மினலைத் தயார்செய்கிறது"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"டெர்மினல் நிறுத்தப்படுகிறது"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"டெர்மினல் சிதைவடைந்தது"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"போர்ட் கட்டுப்பாடு"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"லிஸனிங் போர்ட்டுகளை அனுமதித்தல்/நிராகரித்தல்"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"லிஸனிங் போர்ட்டுகள்"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"சேமித்த அனுமதிக்கப்பட்ட போர்ட்டுகள்"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"சேர்க்கும்"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> ஐ நீக்கும்"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"தவறான போர்ட் எண்"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"போர்ட் ஏற்கெனவே உள்ளது"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"டெர்மினல் புதிய போர்ட்டைத் திறக்குமாறு கேட்கிறது"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"போர்ட் கேட்கப்பட்டுள்ளது: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ஏற்கிறேன்"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"நிராகரி"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"மீட்டெடுத்தல்"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"டெர்மினல் மூடப்படுகிறது"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"உடனே மூடு"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> இயக்கப்பட்டது"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"நீண்ட நேரம் இயங்கும் பணிகள்"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"சிஸ்டம் நிகழ்வுகள்"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-te/strings.xml b/android/TerminalApp/res/values-te/strings.xml
index 7eab5da..fd48d50 100644
--- a/android/TerminalApp/res/values-te/strings.xml
+++ b/android/TerminalApp/res/values-te/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi అందుబాటులో లేని కారణంగా ఇన్‌స్టాల్ చేయడం విఫలమైంది"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ఇన్‌స్టాల్ చేయడం విఫలమైంది. దయచేసి మళ్లీ ట్రై చేయండి"</string>
     <string name="action_settings" msgid="5729342767795123227">"సెట్టింగ్‌లు"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"టెర్మినల్‌ను సిద్ధం చేస్తోంది"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"టెర్మినల్‌ను ఆపివేస్తోంది"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"టెర్మినల్ క్రాష్ అయింది"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"పోర్ట్ కంట్రోల్"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"వినే పోర్ట్‌లకు అనుమతినివ్వండి/తిరస్కరించండి"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"వినే పోర్ట్‌లు"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"సేవ్ చేసిన, అనుమతి ఉన్న పోర్ట్‌లు"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"జోడించండి"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g>‌ను తొలగించండి"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"చెల్లుబాటు కాని పోర్ట్ నంబర్"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"పోర్ట్ ఇప్పటికే ఉంది"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"టెర్మినల్ ఒక కొత్త పోర్ట్‌ను తెరవడానికి రిక్వెస్ట్ చేస్తోంది"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"రిక్వెస్ట్ చేయబడిన పోర్ట్: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ఆమోదించండి"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"తిరస్కరించండి"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"రికవరీ"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal మూసివేయబడుతోంది"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"బలవంతంగా మూసివేయండి"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> ప్రారంభించబడింది"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"ఎక్కువసేపు రన్ అయ్యే టాస్క్‌లు"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"సిస్టమ్ ఈవెంట్‌లు"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-th/strings.xml b/android/TerminalApp/res/values-th/strings.xml
index 77e0e5f..6ff2595 100644
--- a/android/TerminalApp/res/values-th/strings.xml
+++ b/android/TerminalApp/res/values-th/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"ติดตั้งไม่สำเร็จเนื่องจากไม่มี Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"ติดตั้งไม่สำเร็จ โปรดลองอีกครั้ง"</string>
     <string name="action_settings" msgid="5729342767795123227">"การตั้งค่า"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"กำลังเตรียมเทอร์มินัล"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"กำลังหยุดเทอร์มินัล"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"เทอร์มินัลขัดข้อง"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"การควบคุมพอร์ต"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"อนุญาต/ปฏิเสธพอร์ตที่กำลังรอการเชื่อมต่อ"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"พอร์ตที่กำลังรอการเชื่อมต่อ"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"บันทึกพอร์ตที่อนุญาตแล้ว"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"เพิ่ม"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"ลบ <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"หมายเลขพอร์ตไม่ถูกต้อง"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"มีพอร์ตอยู่แล้ว"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"เทอร์มินัลกำลังส่งคำขอเปิดพอร์ตใหม่"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"พอร์ตที่ขอ: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"ยอมรับ"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"ปฏิเสธ"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"การกู้คืน"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"เทอร์มินัลกำลังจะปิด"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"บังคับปิด"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"เปิดใช้งาน <xliff:g id="ID_1">VirGL</xliff:g> แล้ว"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"งานที่ใช้เวลานาน"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"เหตุการณ์ของระบบ"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-tl/strings.xml b/android/TerminalApp/res/values-tl/strings.xml
index c11620e..16be869 100644
--- a/android/TerminalApp/res/values-tl/strings.xml
+++ b/android/TerminalApp/res/values-tl/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Hindi na-install dahil walang Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Hindi na-install. Pakisubukan ulit"</string>
     <string name="action_settings" msgid="5729342767795123227">"Mga Setting"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Inihahanda ang terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Hinihinto ang terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Nag-crash ang terminal"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kontrol ng port"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Payagan/tanggihan ang mga port ng pakikinig"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Mga port sa pakikinig"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"I-save ang mga pinayagang port"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Magdagdag"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"I-delete ang <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Invalid na numero ng port"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Mayroon na ng port na ito"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Nag-request ang terminal na magbukas ng bagong port"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Ni-request na port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Tanggapin"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Tanggihan"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Pag-recover"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Nagsasara ang terminal"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Sapilitang isara"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"Na-enable ang <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Mga gawaing matagal gawin"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Mga event ng system"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-tr/strings.xml b/android/TerminalApp/res/values-tr/strings.xml
index 3b2bf0b..30cf1a1 100644
--- a/android/TerminalApp/res/values-tr/strings.xml
+++ b/android/TerminalApp/res/values-tr/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Kablosuz bağlantı olmadığından yükleme işlemi başarısız oldu"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Yüklenemedi. Lütfen tekrar deneyin"</string>
     <string name="action_settings" msgid="5729342767795123227">"Ayarlar"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminal hazırlanıyor"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminal durduruluyor"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal kilitlendi"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Bağlantı noktası kontrolü"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Dinelenen bağlantı noktalarına izin ver/izin verme"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Dinlenen bağlantı noktaları"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"İzin verilen kayıtlı bağlantı noktaları"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Ekle"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Sil: <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Bağlantı noktası numarası geçersiz"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Bağlantı noktası zaten mevcut"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal yeni bir bağlantı noktası açmak istiyor"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"İstenilen bağlantı noktası: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Kabul et"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Reddet"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Kurtarma"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal kapanıyor"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Uygulamayı kapat"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> etkinleştirildi"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Uzun süredir çalışan görevler"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sistem etkinlikleri"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-uk/strings.xml b/android/TerminalApp/res/values-uk/strings.xml
index f3a4906..748b3a5 100644
--- a/android/TerminalApp/res/values-uk/strings.xml
+++ b/android/TerminalApp/res/values-uk/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Не вдалося встановити, оскільки немає Wi-Fi-з’єднання"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Не вдалося встановити. Повторіть спробу."</string>
     <string name="action_settings" msgid="5729342767795123227">"Налаштування"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Підготовка термінала"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Зупинка термінала"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Збій термінала"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Керування портами"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Дозволити/заборонити порти прослуховування"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Порти прослуховування"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Збережені дозволені порти"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Додати"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Видалити <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Недійсний номер порту"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Порт уже існує"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Термінал просить відкрити новий порт"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Порт, указаний у запиті: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Прийняти"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Відхилити"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Відновлення"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Термінал закривається"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Примусово закрити"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> увімкнено"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Довготривалі завдання"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Події системи"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-ur/strings.xml b/android/TerminalApp/res/values-ur/strings.xml
index f0e5351..e5552c3 100644
--- a/android/TerminalApp/res/values-ur/strings.xml
+++ b/android/TerminalApp/res/values-ur/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"‫Wi-Fi دستیاب نہ ہونے کی وجہ سے انسٹال نہیں کیا جا سکا"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"انسٹال نہیں کیا جا سکا۔ براہ کرم دوبارہ کوشش کریں"</string>
     <string name="action_settings" msgid="5729342767795123227">"ترتیبات"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"ٹرمینل تیار ہو رہا ہے"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"ٹرمینل کو روکا جا رہا ہے"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"ٹرمینل کریش ہو گیا"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"پورٹ کنٹرول"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"لسننگ پورٹس کو اجازت دیں/مسترد کریں"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"لسننگ پورٹس"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"اجازت یافتہ پورٹس کو محفوظ کیا گیا"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"شامل کریں"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> حذف کریں"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"غلط پورٹ نمبر"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"پورٹ پہلے سے موجود ہے"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"ٹرمینل ایک نیا پورٹ کھولنے کی درخواست کر رہا ہے"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"پورٹ کی درخواست کی گئی: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"قبول کریں"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"مسترد کریں"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"بازیابی"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"ٹرمینل بند ہو رہا ہے"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"زبردستی بند کریں"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"‫<xliff:g id="ID_1">VirGL</xliff:g> فعال ہے"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"لمبے وقت تک چلنے والے ٹاسکس"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"سسٹم ایونٹس"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-uz/strings.xml b/android/TerminalApp/res/values-uz/strings.xml
index 5c65633..85ce628 100644
--- a/android/TerminalApp/res/values-uz/strings.xml
+++ b/android/TerminalApp/res/values-uz/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Wi-Fi mavjud emasligi sababli oʻrnatilmadi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Oʻrnatilmadi. Qayta urining"</string>
     <string name="action_settings" msgid="5729342767795123227">"Sozlamalar"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Terminal tayyorlanmoqda"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Terminal toʻxtatilmoqda"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal ishdan chiqdi"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Portlar boshqaruvi"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Uzatish portlariga ruxsat berish/ularni taqiqlash"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Uzatish postlari"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Ruxsat etilgan portlar saqlandi"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Qoʻshish"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"<xliff:g id="PORT_NUMBER">%d</xliff:g> hisobini oʻchirish"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Port raqami yaroqsiz"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Port allaqachon mavjud"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Terminal yangi port ochishni talab qilmoqda"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Talab qilingan port: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Qabul qilish"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Rad etish"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Tiklash"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal yopilmoqda"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Majburiy yopish"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> yoniq"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Uzoq davom etuvchi vazifalar"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Tizim tadbirlari"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-vi/strings.xml b/android/TerminalApp/res/values-vi/strings.xml
index 5013918..de91f41 100644
--- a/android/TerminalApp/res/values-vi/strings.xml
+++ b/android/TerminalApp/res/values-vi/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Không cài đặt được do không có Wi-Fi"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Không cài đặt được. Vui lòng thử lại"</string>
     <string name="action_settings" msgid="5729342767795123227">"Cài đặt"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Đang chuẩn bị Terminal"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Đang dừng Terminal"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Terminal gặp sự cố"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Kiểm soát cổng"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Cho phép/từ chối cổng nghe"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Cổng nghe"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Đã lưu các cổng được cho phép"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Thêm"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Xoá <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Số cổng không hợp lệ"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Cổng đã tồn tại"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Ứng dụng Terminal đang yêu cầu mở một cổng mới"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Cổng được yêu cầu: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Chấp nhận"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Từ chối"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Khôi phục"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Terminal đang đóng"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Buộc đóng"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> đã được bật"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Tác vụ chạy trong thời gian dài"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Sự kiện hệ thống"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-zh-rCN/strings.xml b/android/TerminalApp/res/values-zh-rCN/strings.xml
index 4d424ed..c7ae604 100644
--- a/android/TerminalApp/res/values-zh-rCN/strings.xml
+++ b/android/TerminalApp/res/values-zh-rCN/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"由于 WLAN 不可用,安装失败"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"安装失败,请重试"</string>
     <string name="action_settings" msgid="5729342767795123227">"设置"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"正在准备终端"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"正在停止终端"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"终端已崩溃"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"端口控制"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"允许/拒绝使用监听端口"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"监听端口"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g>(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"已保存的获准端口"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"添加"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"删除“<xliff:g id="PORT_NUMBER">%d</xliff:g>”"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"端口号无效"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"端口已存在"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"终端正在请求打开新端口"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"请求的端口:<xliff:g id="PORT_NUMBER">%1$d</xliff:g>(<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"接受"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"拒绝"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"恢复"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"终端即将关闭"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"强行关闭"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> 已启用"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"长时间运行的任务"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"系统事件"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-zh-rHK/strings.xml b/android/TerminalApp/res/values-zh-rHK/strings.xml
index 317ec3a..8cb447e 100644
--- a/android/TerminalApp/res/values-zh-rHK/strings.xml
+++ b/android/TerminalApp/res/values-zh-rHK/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"由於沒有可用的 Wi-Fi,因此無法安裝"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"無法安裝,請再試一次"</string>
     <string name="action_settings" msgid="5729342767795123227">"設定"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"正在準備終端機"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"正在停止終端機"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"終端機當機"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"連接埠控制項"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"允許/拒絕聆聽連接埠"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"聆聽連接埠"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"已儲存許可的連接埠"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"新增"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"刪除 <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"連接埠號碼無效"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"連接埠已存在"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"終端機正在要求開啟新的連接埠"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"已要求連接埠:<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"接受"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"拒絕"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"復原"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"終端機正在關閉"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"強制關閉"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"已啟用 <xliff:g id="ID_1">VirGL</xliff:g>"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"長時間執行的工作"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"系統活動"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-zh-rTW/strings.xml b/android/TerminalApp/res/values-zh-rTW/strings.xml
index d3576d5..bab47d3 100644
--- a/android/TerminalApp/res/values-zh-rTW/strings.xml
+++ b/android/TerminalApp/res/values-zh-rTW/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"無法連上 Wi-Fi,因此無法安裝"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"無法安裝,請再試一次"</string>
     <string name="action_settings" msgid="5729342767795123227">"設定"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"正在準備終端機"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"正在停止終端機"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"終端機當機"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"通訊埠控制"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"允許/拒絕監聽通訊埠"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"監聽通訊埠"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"已儲存允許的通訊埠"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"新增"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"刪除 <xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"通訊埠號碼無效"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"已有這個通訊埠"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"終端機正在要求開啟新的通訊埠"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"要求的通訊埠:<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"接受"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"拒絕"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"復原"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"終端機正在關閉"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"強制關閉"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"<xliff:g id="ID_1">VirGL</xliff:g> 已啟用"</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"長時間執行的工作"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"系統事件"</string>
 </resources>
diff --git a/android/TerminalApp/res/values-zu/strings.xml b/android/TerminalApp/res/values-zu/strings.xml
index 8b81522..111db1a 100644
--- a/android/TerminalApp/res/values-zu/strings.xml
+++ b/android/TerminalApp/res/values-zu/strings.xml
@@ -33,6 +33,8 @@
     <string name="installer_error_no_wifi" msgid="1180164894845030969">"Yehlulekile ukufaka ngoba i-Wi-Fi ayitholakali"</string>
     <string name="installer_error_unknown" msgid="5657920711470180224">"Yehlulekile ukufaka. Sicela uzame futhi"</string>
     <string name="action_settings" msgid="5729342767795123227">"Amasethingi"</string>
+    <!-- no translation found for action_display (8487008779926038139) -->
+    <skip />
     <string name="vm_creation_message" msgid="6594953532721367502">"Ilungiselela itheminali"</string>
     <string name="vm_stop_message" msgid="3978349856095529255">"Itheminali yokumisa"</string>
     <string name="vm_error_message" msgid="5231867246177661525">"Itheminali iphahlazekile"</string>
@@ -48,8 +50,7 @@
     <string name="settings_port_forwarding_title" msgid="4971368519093858377">"Ulawulo lwembobo"</string>
     <string name="settings_port_forwarding_sub_title" msgid="6547942778715654953">"Vumela/nqabela izimbobo zokulalela"</string>
     <string name="settings_port_forwarding_active_ports_title" msgid="1841436780635889858">"Izimbobo zokulalela"</string>
-    <!-- no translation found for settings_port_forwarding_active_ports_content (1818090784030797758) -->
-    <skip />
+    <string name="settings_port_forwarding_active_ports_content" msgid="1818090784030797758">"<xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_other_enabled_ports_title" msgid="2644381842623436676">"Izimbobo ezivunyelwe ezilondoloziwe"</string>
     <string name="settings_port_forwarding_other_enabled_port_add_button" msgid="4402301203801949152">"Engeza"</string>
     <string name="settings_port_forwarding_other_enabled_port_close_button" msgid="8475029060852721339">"Sula i-<xliff:g id="PORT_NUMBER">%d</xliff:g>"</string>
@@ -61,8 +62,7 @@
     <string name="settings_port_forwarding_dialog_error_invalid_port_range" msgid="6682935312557379651">"Inombolo engasebenzi yembobo"</string>
     <string name="settings_port_forwarding_dialog_error_existing_port" msgid="768426750758769928">"Imbobo isikhona"</string>
     <string name="settings_port_forwarding_notification_title" msgid="6950621555592547524">"Itheminali icela ukuvula imbobo entsha"</string>
-    <!-- no translation found for settings_port_forwarding_notification_content (779450349212040908) -->
-    <skip />
+    <string name="settings_port_forwarding_notification_content" msgid="779450349212040908">"Imbobo iceliwe: <xliff:g id="PORT_NUMBER">%1$d</xliff:g> (<xliff:g id="PROCESS_NAME">%2$s</xliff:g>)"</string>
     <string name="settings_port_forwarding_notification_accept" msgid="3571520986524038185">"Yamukela"</string>
     <string name="settings_port_forwarding_notification_deny" msgid="636848749634710403">"Yenqaba"</string>
     <string name="settings_recovery_title" msgid="6586840079226383285">"Ukuthola"</string>
@@ -89,4 +89,6 @@
     <string name="service_notification_close_title" msgid="1442526433361428844">"Itheminali iyavalwa"</string>
     <string name="service_notification_force_quit_action" msgid="3462226330416157775">"Phoqelela ukuvala"</string>
     <string name="virgl_enabled" msgid="5242525588039698086">"I-<xliff:g id="ID_1">VirGL</xliff:g> inikwe amandla."</string>
+    <string name="notification_channel_long_running_name" msgid="7916541360369402952">"Imisebenzi esebenza isikhathi eside"</string>
+    <string name="notification_channel_system_events_name" msgid="1004951444029742137">"Imicimbi yesistimu"</string>
 </resources>
diff --git a/android/TerminalApp/res/values/strings.xml b/android/TerminalApp/res/values/strings.xml
index d3440d3..44009c3 100644
--- a/android/TerminalApp/res/values/strings.xml
+++ b/android/TerminalApp/res/values/strings.xml
@@ -55,6 +55,9 @@
     <!-- Action bar icon name for the settings view CHAR LIMIT=none] -->
     <string name="action_settings">Settings</string>
 
+    <!-- Action bar icon name for showing the display activity CHAR LIMIT=none] -->
+    <string name="action_display">Display</string>
+
     <!-- Toast message to notify that preparing terminal to start [CHAR LIMIT=none] -->
     <string name="vm_creation_message">Preparing terminal</string>
     <!-- Toast message to notify that terminal is stopping [CHAR LIMIT=none] -->
@@ -172,4 +175,10 @@
 
     <!-- This string is for toast message to notify that VirGL is enabled. [CHAR LIMIT=40] -->
     <string name="virgl_enabled"><xliff:g>VirGL</xliff:g> is enabled</string>
+
+    <!-- This is the name of the notification channel for long-runnint tasks [CHAR LIMIT=none] -->
+    <string name="notification_channel_long_running_name">Long running tasks</string>
+
+    <!-- This is the name of the notification channel for system events [CHAR LIMIT=none] -->
+    <string name="notification_channel_system_events_name">System events</string>
 </resources>
diff --git a/android/TerminalApp/res/values/styles.xml b/android/TerminalApp/res/values/styles.xml
index 3fb8e7d..13f070f 100644
--- a/android/TerminalApp/res/values/styles.xml
+++ b/android/TerminalApp/res/values/styles.xml
@@ -27,4 +27,15 @@
     <style name="VmTerminalAppTheme" parent="@style/Theme.Material3.DayNight.NoActionBar">
         <item name="android:windowLightStatusBar" tools:targetApi="m">?android:attr/isLightTheme</item>
     </style>
+    <style name="FullscreenTheme" parent="@style/Theme.Material3.DayNight.NoActionBar">
+        <item name="android:navigationBarColor">
+            @android:color/transparent
+        </item>
+        <item name="android:statusBarColor">
+            @android:color/transparent
+        </item>
+        <item name="android:windowLayoutInDisplayCutoutMode">
+            always
+        </item>
+    </style>
 </resources>
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 57779bf..33f3be1 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -2033,7 +2033,7 @@
     Owned(T),
 }
 
-impl<'a, T> AsRef<T> for BorrowedOrOwned<'a, T> {
+impl<T> AsRef<T> for BorrowedOrOwned<'_, T> {
     fn as_ref(&self) -> &T {
         match self {
             Self::Borrowed(b) => b,
diff --git a/build/avf_flags.aconfig b/build/avf_flags.aconfig
index 9815c60..921c374 100644
--- a/build/avf_flags.aconfig
+++ b/build/avf_flags.aconfig
@@ -9,3 +9,11 @@
   bug: "383347947"
   is_fixed_read_only: true
 }
+
+flag {
+  name: "terminal_gui_support"
+  is_exported: true
+  namespace: "virtualization"
+  description: "Flag for GUI support in terminal"
+  bug: "386296118"
+}
\ No newline at end of file
diff --git a/build/debian/build.sh b/build/debian/build.sh
index a426d22..da01695 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -218,35 +218,55 @@
 		return
 	fi
 
+	local deb_base_url="https://deb.debian.org/debian"
+	local deb_security_base_url="https://security.debian.org/debian-security"
+
+	local pool_dir="pool/main/l/linux"
+	local ksrc_base_url="${deb_base_url}/${pool_dir}"
+	local ksrc_security_base_url="${deb_security_base_url}/${pool_dir}"
+
 	# NOTE: 6.1 is the latest LTS kernel for which Debian's kernel build scripts
 	#       work on Python 3.10, the default version on our Ubuntu 22.04 builders.
-	local debian_kver="6.1.119-1"
-	local custom_flavour="avf"
-	local ksrc_base_url="https://deb.debian.org/debian/pool/main/l/linux"
+	#
+	#       We track the latest Debian stable kernel version for the 6.1 branch,
+	#       which can be found at:
+	#       https://packages.debian.org/stable/linux-source-6.1
+	local debian_kver="6.1.123-1"
 
-	local dsc_url="${ksrc_base_url}/linux_${debian_kver}.dsc"
-	local debian_ksrc_url="${ksrc_base_url}/linux_${debian_kver}.debian.tar.xz"
-	local orig_ksrc_url="${ksrc_base_url}/linux_${debian_kver%-*}.orig.tar.xz"
+	local dsc_file="linux_${debian_kver}.dsc"
+	local orig_ksrc_file="linux_${debian_kver%-*}.orig.tar.xz"
+	local debian_ksrc_file="linux_${debian_kver}.debian.tar.xz"
 
 	# 0. Grab the kernel sources, and the latest debian keyrings
 	mkdir -p "${workdir}/kernel"
 	pushd "${workdir}/kernel" > /dev/null
-	wget "$dsc_url"
-	wget "$orig_ksrc_url"
-	wget "$debian_ksrc_url"
+
+	wget "${ksrc_security_base_url}/${dsc_file}" || \
+	wget "${ksrc_base_url}/${dsc_file}"
+
+	wget "${ksrc_security_base_url}/${orig_ksrc_file}" || \
+	wget "${ksrc_base_url}/${orig_ksrc_file}"
+
+	wget "${ksrc_security_base_url}/${debian_ksrc_file}" || \
+	wget "${ksrc_base_url}/${debian_ksrc_file}"
+
 	rsync -az --progress keyring.debian.org::keyrings/keyrings/ /usr/share/keyrings/
 
 	# 1. Verify, extract and merge patches into the original kernel sources
 	dpkg-source --require-strong-checksums \
 	            --require-valid-signature \
-	            --extract linux_${debian_kver}.dsc
+	            --extract "${dsc_file}"
 	pushd "linux-${debian_kver%-*}" > /dev/null
-	# TODO: Copy our own kernel patches to debian/patches
-	#       and add patch file names in the desired order to debian/patches/series
+
+	local kpatches_src="$(dirname "$0")/kernel_patches"
+	cp -r "${kpatches_src}/avf" debian/patches/
+	cat "${kpatches_src}/series" >> debian/patches/series
 	./debian/rules orig
 
-	local abi_kver="$(sed -nE 's;Package: linux-support-(.*);\1;p' debian/control)"
+	local custom_flavour="avf"
 	local debarch_flavour="${custom_flavour}-${debian_arch}"
+
+	local abi_kver="$(sed -nE 's;Package: linux-support-(.*);\1;p' debian/control)"
 	local abi_flavour="${abi_kver}-${debarch_flavour}"
 
 	# 2. Define our custom flavour and regenerate control file
diff --git a/build/debian/fai_config/files/etc/avahi/services/ttyd.service/AVF b/build/debian/fai_config/files/etc/avahi/services/ttyd.service/AVF
deleted file mode 100644
index 64f9d0a..0000000
--- a/build/debian/fai_config/files/etc/avahi/services/ttyd.service/AVF
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
-<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
-
-<service-group>
-
-  <name>ttyd</name>
-
-  <service protocol="ipv4">
-    <type>_http._tcp</type>
-    <port>7681</port>
-  </service>
-
-</service-group>
diff --git a/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF b/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
index 4a32f2b..d86bab0 100644
--- a/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
+++ b/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
@@ -3,11 +3,14 @@
 After=syslog.target
 After=network.target
 After=virtiofs_internal.service
+
 [Service]
 ExecStart=/usr/local/bin/ttyd --ssl --ssl-cert /etc/ttyd/server.crt --ssl-key /etc/ttyd/server.key --ssl-ca /mnt/internal/ca.crt -t disableLeaveAlert=true -W login -f droid
+ExecStartPost=/usr/bin/avahi-publish-service ttyd _http._tcp 7681
 Type=simple
 Restart=always
 User=root
 Group=root
+
 [Install]
 WantedBy=multi-user.target
diff --git a/build/debian/fai_config/package_config/AVF b/build/debian/fai_config/package_config/AVF
index 98b558b..bf51fdb 100644
--- a/build/debian/fai_config/package_config/AVF
+++ b/build/debian/fai_config/package_config/AVF
@@ -8,3 +8,5 @@
 forwarder-guest
 forwarder-guest-launcher
 shutdown-runner
+weston
+xwayland
diff --git a/build/debian/kernel_patches/avf/arm64-balloon.patch b/build/debian/kernel_patches/avf/arm64-balloon.patch
new file mode 100644
index 0000000..3877ebb
--- /dev/null
+++ b/build/debian/kernel_patches/avf/arm64-balloon.patch
@@ -0,0 +1,550 @@
+From 71b755110581e7cab93f839c4617735fc682c679 Mon Sep 17 00:00:00 2001
+From: Keir Fraser <keirf@google.com>
+Date: Tue, 10 Dec 2024 08:28:12 +0000
+Subject: [PATCH 1/6] KVM: arm64: Define guest hypercalls
+
+---
+ include/linux/arm-smccc.h | 56 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 56 insertions(+)
+
+diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
+index 220c8c60e021..02dc0957ec2d 100644
+--- a/include/linux/arm-smccc.h
++++ b/include/linux/arm-smccc.h
+@@ -112,6 +112,14 @@
+ /* KVM "vendor specific" services */
+ #define ARM_SMCCC_KVM_FUNC_FEATURES		0
+ #define ARM_SMCCC_KVM_FUNC_PTP			1
++#define ARM_SMCCC_KVM_FUNC_HYP_MEMINFO		2
++#define ARM_SMCCC_KVM_FUNC_MEM_SHARE		3
++#define ARM_SMCCC_KVM_FUNC_MEM_UNSHARE		4
++#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD_INFO	5
++#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD_ENROLL	6
++#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD_MAP	7
++#define ARM_SMCCC_KVM_FUNC_MMIO_GUARD_UNMAP	8
++#define ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH	9
+ #define ARM_SMCCC_KVM_FUNC_FEATURES_2		127
+ #define ARM_SMCCC_KVM_NUM_FUNCS			128
+
+@@ -134,6 +142,54 @@
+ 			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
+ 			   ARM_SMCCC_KVM_FUNC_PTP)
+
++#define ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID			\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_HYP_MEMINFO)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID			\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MEM_SHARE)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID			\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MEM_UNSHARE)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MEM_RELINQUISH_FUNC_ID			\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID		\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MMIO_GUARD_INFO)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_ENROLL_FUNC_ID		\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MMIO_GUARD_ENROLL)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID			\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MMIO_GUARD_MAP)
++
++#define ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID		\
++	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,				\
++			   ARM_SMCCC_SMC_64,				\
++			   ARM_SMCCC_OWNER_VENDOR_HYP,			\
++			   ARM_SMCCC_KVM_FUNC_MMIO_GUARD_UNMAP)
++
+ /* ptp_kvm counter type ID */
+ #define KVM_PTP_VIRT_COUNTER			0
+ #define KVM_PTP_PHYS_COUNTER			1
+--
+2.47.0.338.g60cca15819-goog
+
+
+From 14104b188b1ce2b2e227a9f5426fc8cb4d777461 Mon Sep 17 00:00:00 2001
+From: Keir Fraser <keirf@google.com>
+Date: Thu, 26 May 2022 14:22:34 +0000
+Subject: [PATCH 2/6] ANDROID: Define mem_relinquish interface for releasing
+ memory to a hypervisor.
+
+On PKVM/ARM64 this uses the ARM SMCCC relinquish hypercall when available.
+
+Bug: 240239989
+Change-Id: Ifa85b641a48f348a2364cf8c6b06b6417f1eeedb
+Signed-off-by: Keir Fraser <keirf@google.com>
+Signed-off-by: Quentin Perret <qperret@google.com>
+---
+ arch/Kconfig                            |  3 ++
+ arch/arm64/Kconfig                      |  1 +
+ arch/arm64/include/asm/hypervisor.h     |  7 +++
+ arch/arm64/include/asm/mem_relinquish.h | 12 +++++
+ arch/arm64/kernel/setup.c               |  6 +++
+ arch/arm64/mm/Makefile                  |  1 +
+ arch/arm64/mm/mem_relinquish.c          | 58 +++++++++++++++++++++++++
+ drivers/firmware/smccc/kvm_guest.c      |  2 +
+ include/linux/mem_relinquish.h          | 20 +++++++++
+ 9 files changed, 110 insertions(+)
+ create mode 100644 arch/arm64/include/asm/mem_relinquish.h
+ create mode 100644 arch/arm64/mm/mem_relinquish.c
+ create mode 100644 include/linux/mem_relinquish.h
+
+diff --git a/arch/Kconfig b/arch/Kconfig
+index 8f138e580d1a..b5fb130a07e2 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -1316,6 +1316,9 @@ config RELR
+ config ARCH_HAS_MEM_ENCRYPT
+ 	bool
+
++config ARCH_HAS_MEM_RELINQUISH
++	bool
++
+ config ARCH_HAS_CC_PLATFORM
+ 	bool
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index 505c8a1ccbe0..935c16e89677 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -31,6 +31,7 @@ config ARM64
+ 	select ARCH_HAS_KCOV
+ 	select ARCH_HAS_KEEPINITRD
+ 	select ARCH_HAS_MEMBARRIER_SYNC_CORE
++	select ARCH_HAS_MEM_RELINQUISH
+ 	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
+ 	select ARCH_HAS_PTE_DEVMAP
+ 	select ARCH_HAS_PTE_SPECIAL
+diff --git a/arch/arm64/include/asm/hypervisor.h b/arch/arm64/include/asm/hypervisor.h
+index 0ae427f352c8..88f42d688eb0 100644
+--- a/arch/arm64/include/asm/hypervisor.h
++++ b/arch/arm64/include/asm/hypervisor.h
+@@ -5,6 +5,13 @@
+ #include <asm/xen/hypervisor.h>
+
+ void kvm_init_hyp_services(void);
++void kvm_arm_init_hyp_services(void);
+ bool kvm_arm_hyp_service_available(u32 func_id);
+
++#ifdef CONFIG_MEMORY_BALLOON
++void kvm_init_memrelinquish_services(void);
++#else
++static inline void kvm_init_memrelinquish_services(void) {}
++#endif
++
+ #endif
+diff --git a/arch/arm64/include/asm/mem_relinquish.h b/arch/arm64/include/asm/mem_relinquish.h
+new file mode 100644
+index 000000000000..a4ace9e6e413
+--- /dev/null
++++ b/arch/arm64/include/asm/mem_relinquish.h
+@@ -0,0 +1,12 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2022 Google LLC
++ * Author: Keir Fraser <keirf@google.com>
++ */
++
++#ifndef __ASM_MEM_RELINQUISH_H
++#define __ASM_MEM_RELINQUISH_H
++
++void page_relinquish(struct page *page);
++
++#endif	/* __ASM_MEM_RELINQUISH_H */
+diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
+index fea3223704b6..f55477b6c02e 100644
+--- a/arch/arm64/kernel/setup.c
++++ b/arch/arm64/kernel/setup.c
+@@ -40,6 +40,7 @@
+ #include <asm/elf.h>
+ #include <asm/cpufeature.h>
+ #include <asm/cpu_ops.h>
++#include <asm/hypervisor.h>
+ #include <asm/kasan.h>
+ #include <asm/numa.h>
+ #include <asm/sections.h>
+@@ -438,3 +439,8 @@ static int __init register_arm64_panic_block(void)
+ 	return 0;
+ }
+ device_initcall(register_arm64_panic_block);
++
++void kvm_arm_init_hyp_services(void)
++{
++	kvm_init_memrelinquish_services();
++}
+diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
+index ff1e800ba7a1..f6c1f3511907 100644
+--- a/arch/arm64/mm/Makefile
++++ b/arch/arm64/mm/Makefile
+@@ -3,6 +3,7 @@ obj-y				:= dma-mapping.o extable.o fault.o init.o \
+ 				   cache.o copypage.o flush.o \
+ 				   ioremap.o mmap.o pgd.o mmu.o \
+ 				   context.o proc.o pageattr.o
++obj-$(CONFIG_MEMORY_BALLOON)	+= mem_relinquish.o
+ obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
+ obj-$(CONFIG_PTDUMP_CORE)	+= ptdump.o
+ obj-$(CONFIG_PTDUMP_DEBUGFS)	+= ptdump_debugfs.o
+diff --git a/arch/arm64/mm/mem_relinquish.c b/arch/arm64/mm/mem_relinquish.c
+new file mode 100644
+index 000000000000..c95bcbb14d92
+--- /dev/null
++++ b/arch/arm64/mm/mem_relinquish.c
+@@ -0,0 +1,58 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2022 Google LLC
++ * Author: Keir Fraser <keirf@google.com>
++ */
++
++#include <linux/arm-smccc.h>
++#include <linux/memory.h>
++#include <linux/mm.h>
++#include <linux/types.h>
++
++#include <asm/hypervisor.h>
++
++static unsigned long memshare_granule_sz;
++
++void kvm_init_memrelinquish_services(void)
++{
++	int i;
++	struct arm_smccc_res res;
++	const u32 funcs[] = {
++		ARM_SMCCC_KVM_FUNC_HYP_MEMINFO,
++		ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH,
++	};
++
++	for (i = 0; i < ARRAY_SIZE(funcs); ++i) {
++		if (!kvm_arm_hyp_service_available(funcs[i]))
++			return;
++	}
++
++	arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID,
++			     0, 0, 0, &res);
++	if (res.a0 > PAGE_SIZE) /* Includes error codes */
++		return;
++
++	memshare_granule_sz = res.a0;
++}
++
++void page_relinquish(struct page *page)
++{
++	phys_addr_t phys, end;
++	u32 func_id = ARM_SMCCC_VENDOR_HYP_KVM_MEM_RELINQUISH_FUNC_ID;
++
++	if (!memshare_granule_sz)
++		return;
++
++	phys = page_to_phys(page);
++	end = phys + PAGE_SIZE;
++
++	while (phys < end) {
++		struct arm_smccc_res res;
++
++		arm_smccc_1_1_invoke(func_id, phys, 0, 0, &res);
++		BUG_ON(res.a0 != SMCCC_RET_SUCCESS);
++
++		phys += memshare_granule_sz;
++	}
++}
++EXPORT_SYMBOL_GPL(page_relinquish);
+diff --git a/drivers/firmware/smccc/kvm_guest.c b/drivers/firmware/smccc/kvm_guest.c
+index 89a68e7eeaa6..0b6a1b2a0857 100644
+--- a/drivers/firmware/smccc/kvm_guest.c
++++ b/drivers/firmware/smccc/kvm_guest.c
+@@ -39,6 +39,8 @@ void __init kvm_init_hyp_services(void)
+
+ 	pr_info("hypervisor services detected (0x%08lx 0x%08lx 0x%08lx 0x%08lx)\n",
+ 		 res.a3, res.a2, res.a1, res.a0);
++
++	kvm_arm_init_hyp_services();
+ }
+
+ bool kvm_arm_hyp_service_available(u32 func_id)
+diff --git a/include/linux/mem_relinquish.h b/include/linux/mem_relinquish.h
+new file mode 100644
+index 000000000000..6b7bf861d92d
+--- /dev/null
++++ b/include/linux/mem_relinquish.h
+@@ -0,0 +1,20 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2022 Google LLC
++ * Author: Keir Fraser <keirf@google.com>
++ */
++
++#ifndef __MEM_RELINQUISH_H__
++#define __MEM_RELINQUISH_H__
++
++#ifdef CONFIG_ARCH_HAS_MEM_RELINQUISH
++
++#include <asm/mem_relinquish.h>
++
++#else	/* !CONFIG_ARCH_HAS_MEM_RELINQUISH */
++
++static inline void page_relinquish(struct page *page) { }
++
++#endif	/* CONFIG_ARCH_HAS_MEM_RELINQUISH */
++
++#endif	/* __MEM_RELINQUISH_H__ */
+--
+2.47.0.338.g60cca15819-goog
+
+
+From 4de68c3d8410bef6a5544caf3835eba8357e08d1 Mon Sep 17 00:00:00 2001
+From: Keir Fraser <keirf@google.com>
+Date: Wed, 9 Nov 2022 13:53:28 +0000
+Subject: [PATCH 3/6] ANDROID: KVM: arm64: memory balloon: Notify hyp when
+ ballooning
+
+When running as a protected VM, the hypervisor isolates the VM's
+memory pages from the host. Returning ownership of a VM page
+therefore requires hypervisor involvement, and acknowledgement from
+the protected VM that it is voluntarily cooperating.
+
+To this end, notify pages via the new relinquish hypercall when they
+are entered into the memory balloon.
+
+Bug: 240239989
+Change-Id: Ic89b45312a7478ddff081a934d99e693eded92dc
+Signed-off-by: Keir Fraser <keirf@google.com>
+Signed-off-by: Quentin Perret <qperret@google.com>
+---
+ include/linux/balloon_compaction.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
+index 5ca2d5699620..318cfe8b57a6 100644
+--- a/include/linux/balloon_compaction.h
++++ b/include/linux/balloon_compaction.h
+@@ -43,6 +43,7 @@
+ #include <linux/err.h>
+ #include <linux/fs.h>
+ #include <linux/list.h>
++#include <linux/mem_relinquish.h>
+
+ /*
+  * Balloon device information descriptor.
+@@ -95,6 +96,7 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
+ 	__SetPageMovable(page, &balloon_mops);
+ 	set_page_private(page, (unsigned long)balloon);
+ 	list_add(&page->lru, &balloon->pages);
++	page_relinquish(page);
+ }
+
+ /*
+@@ -139,6 +141,7 @@ static inline void balloon_page_insert(struct balloon_dev_info *balloon,
+ {
+ 	__SetPageOffline(page);
+ 	list_add(&page->lru, &balloon->pages);
++	page_relinquish(page);
+ }
+
+ static inline void balloon_page_delete(struct page *page)
+--
+2.47.0.338.g60cca15819-goog
+
+
+From f34713f8af1fe2ed50297743315606f880fcbd03 Mon Sep 17 00:00:00 2001
+From: Keir Fraser <keirf@google.com>
+Date: Thu, 18 Aug 2022 10:41:35 +0000
+Subject: [PATCH 4/6] ANDROID: KVM: arm64: balloon: Notify hyp before reporting
+ free pages to host
+
+When running as a protected VM, the hypervisor isolates the VM's
+memory pages from the host. Returning ownership of a VM page therefore
+requires hypervisor involvement, and acknowledgement from the
+protected VM that it is voluntarily cooperating.
+
+To this end, notify pages via the new relinquish hypercall when they
+are being reported to the host as free and available for temporary
+reclaim.
+
+Bug: 240239989
+Change-Id: I8718e468be63c3aacb2f79ff141fbcedd6d19b56
+Signed-off-by: Keir Fraser <keirf@google.com>
+Signed-off-by: Quentin Perret <qperret@google.com>
+---
+ mm/page_reporting.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/mm/page_reporting.c b/mm/page_reporting.c
+index 382958eef8a9..5c4b1fb73187 100644
+--- a/mm/page_reporting.c
++++ b/mm/page_reporting.c
+@@ -7,6 +7,7 @@
+ #include <linux/module.h>
+ #include <linux/delay.h>
+ #include <linux/scatterlist.h>
++#include <linux/mem_relinquish.h>
+
+ #include "page_reporting.h"
+ #include "internal.h"
+@@ -120,7 +121,7 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
+ 	unsigned int page_len = PAGE_SIZE << order;
+ 	struct page *page, *next;
+ 	long budget;
+-	int err = 0;
++	int i, err = 0;
+
+ 	/*
+ 	 * Perform early check, if free area is empty there is
+@@ -175,6 +176,10 @@ page_reporting_cycle(struct page_reporting_dev_info *prdev, struct zone *zone,
+ 			--(*offset);
+ 			sg_set_page(&sgl[*offset], page, page_len, 0);
+
++			/* Notify hyp that these pages are reclaimable. */
++			for (i = 0; i < (1<<order); i++)
++				page_relinquish(page+i);
++
+ 			continue;
+ 		}
+
+--
+2.47.0.338.g60cca15819-goog
+
+
+From 429502a582c1c900681a82fb94f9078d0569c731 Mon Sep 17 00:00:00 2001
+From: Keir Fraser <keirf@google.com>
+Date: Thu, 18 Aug 2022 11:20:25 +0000
+Subject: [PATCH 5/6] ANDROID: virtio_balloon: Do not translate reported pages
+ through DMA API
+
+The free-page reporting and hinting queues do not pass arrays of page
+addresses (like the basic inflate queue) but instead pass the free page
+ranges as buffers. This does not work well with DMA API: The host wants
+to know the GPA, not an IOVA.
+
+For these two virtqueues, disable DMA API and pass through buffers untranslated.
+
+Bug: 240239989
+Change-Id: I2d13a8b7e8f6775819de7fe96f4579afa08b1300
+Signed-off-by: Keir Fraser <keirf@google.com>
+[ qperret@: Fixed minor context conflict in virtio.h ]
+Signed-off-by: Quentin Perret <qperret@google.com>
+---
+ drivers/virtio/virtio_balloon.c |  8 ++++++--
+ drivers/virtio/virtio_ring.c    | 10 ++++++++++
+ include/linux/virtio.h          |  2 ++
+ 3 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
+index 3f78a3a1eb75..4c85349024c1 100644
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -553,11 +553,15 @@ static int init_vqs(struct virtio_balloon *vb)
+ 		virtqueue_kick(vb->stats_vq);
+ 	}
+
+-	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
++	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
+ 		vb->free_page_vq = vqs[VIRTIO_BALLOON_VQ_FREE_PAGE];
++		virtqueue_disable_dma_api_for_buffers(vb->free_page_vq);
++	}
+
+-	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING))
++	if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_REPORTING)) {
+ 		vb->reporting_vq = vqs[VIRTIO_BALLOON_VQ_REPORTING];
++		virtqueue_disable_dma_api_for_buffers(vb->reporting_vq);
++	}
+
+ 	return 0;
+ }
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index 2e7689bb933b..3eca7140bd80 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -2863,4 +2863,14 @@ const struct vring *virtqueue_get_vring(struct virtqueue *vq)
+ }
+ EXPORT_SYMBOL_GPL(virtqueue_get_vring);
+
++/*
++ * Prevents use of DMA API for buffers passed via the specified virtqueue.
++ * DMA API may still be used for the vrings themselves.
++ */
++void virtqueue_disable_dma_api_for_buffers(struct virtqueue *vq)
++{
++	to_vvq(vq)->use_dma_api = false;
++}
++EXPORT_SYMBOL_GPL(virtqueue_disable_dma_api_for_buffers);
++
+ MODULE_LICENSE("GPL");
+diff --git a/include/linux/virtio.h b/include/linux/virtio.h
+index dcab9c7e8784..34e936343ae4 100644
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -96,6 +96,8 @@ dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
+ int virtqueue_resize(struct virtqueue *vq, u32 num,
+ 		     void (*recycle)(struct virtqueue *vq, void *buf));
+
++void virtqueue_disable_dma_api_for_buffers(struct virtqueue *vq);
++
+ /**
+  * struct virtio_device - representation of a device using virtio
+  * @index: unique position on the virtio bus
+--
+2.47.0.338.g60cca15819-goog
+
+
+From 49de3a1d0bb478858eb66a5b853f0d0a5b1909dc Mon Sep 17 00:00:00 2001
+From: Keir Fraser <keirf@google.com>
+Date: Thu, 17 Nov 2022 14:59:38 +0000
+Subject: [PATCH 6/6] ANDROID: virtio_balloon: Do not clear
+ VIRTIO_F_ACCESS_PLATFORM
+
+This essentially reverts commit e41b1355508debe45fda33
+"virtio_balloon: disable VIOMMU support".
+
+Although the virtio_balloon driver does not translate through a
+VIOMMU (or bounce buffer) the pages that it sends to the device,
+it *does* need to perform these translations on the virtio rings
+themselves.
+
+This fixes virtio_balloon initialisation inside a PKVM/ARM64
+protected virtual machine.
+
+Bug: 240239989
+Change-Id: I2a84eec870fd638223b231e5c4d1c27216dc40a2
+Signed-off-by: Keir Fraser <keirf@google.com>
+Signed-off-by: Quentin Perret <qperret@google.com>
+---
+ drivers/virtio/virtio_balloon.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
+index 4c85349024c1..72fe24005bc0 100644
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -1097,7 +1097,6 @@ static int virtballoon_validate(struct virtio_device *vdev)
+ 	else if (!virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON))
+ 		__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_REPORTING);
+
+-	__virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
+ 	return 0;
+ }
+
+--
+2.47.0.338.g60cca15819-goog
diff --git a/build/debian/kernel_patches/series b/build/debian/kernel_patches/series
new file mode 100644
index 0000000..573a1fb
--- /dev/null
+++ b/build/debian/kernel_patches/series
@@ -0,0 +1,2 @@
+# AVF patches
+avf/arm64-balloon.patch
diff --git a/docs/microdroid_vendor_modules.md b/docs/microdroid_vendor_modules.md
index 6ead195..11ce611 100644
--- a/docs/microdroid_vendor_modules.md
+++ b/docs/microdroid_vendor_modules.md
@@ -78,7 +78,7 @@
 `/apex/com.android.virt/bin/vm run-microdroid` CLI commands, e.g.:
 
 ```
-adb shell /apex/com.android.virt/bin/vm/run-microdroid \
+adb shell /apex/com.android.virt/bin/vm run-microdroid \
   --debug full \
   --vendor /vendor/etc/avf/microdroid/microdroid_vendor.img
 ```
@@ -103,7 +103,7 @@
 Microdroid vendor partition, e.g.:
 
 ```
-adb shell /apex/com.android.virt/bin/vm/run-microdroid \
+adb shell /apex/com.android.virt/bin/vm run-microdroid \
   --debug full \
   --protected \
   --vendor /vendor/etc/avf/microdroid/microdroid_vendor.img
diff --git a/guest/apkdmverity/src/main.rs b/guest/apkdmverity/src/main.rs
index d2f88ae..2fc964b 100644
--- a/guest/apkdmverity/src/main.rs
+++ b/guest/apkdmverity/src/main.rs
@@ -27,6 +27,7 @@
 use apkverify::{HashAlgorithm, V4Signature};
 use clap::{arg, Arg, ArgAction, Command};
 use dm::loopdevice;
+use dm::loopdevice::LoopConfigOptions;
 use dm::util;
 use dm::verity::{DmVerityHashAlgorithm, DmVerityTargetBuilder};
 use itertools::Itertools;
@@ -109,9 +110,13 @@
         }
         (
             loopdevice::attach(
-                &apk, 0, apk_size, /* direct_io */ true, /* writable */ false,
+                &apk,
+                0,
+                apk_size,
+                &LoopConfigOptions { direct_io: true, ..Default::default() },
             )
-            .context("Failed to attach APK to a loop device")?,
+            .context("Failed to attach APK to a loop device")?
+            .path,
             apk_size,
         )
     };
@@ -125,10 +130,9 @@
     // Due to unknown reason(b/191344832), we can't enable "direct IO" for the IDSIG file (backing
     // the hash). For now we don't use "direct IO" but it seems OK since the IDSIG file is very
     // small and the benefit of direct-IO would be negliable.
-    let hash_device = loopdevice::attach(
-        &idsig, offset, size, /* direct_io */ false, /* writable */ false,
-    )
-    .context("Failed to attach idsig to a loop device")?;
+    let hash_device = loopdevice::attach(&idsig, offset, size, &LoopConfigOptions::default())
+        .context("Failed to attach idsig to a loop device")?
+        .path;
 
     // Build a dm-verity target spec from the information from the idsig file. The apk and the
     // idsig files are used as the data device and the hash device, respectively.
@@ -347,18 +351,17 @@
         // of the data device is done in the scopeguard for the return value of `enable_verity`
         // below. Only the idsig_loop_device needs detatching.
         let apk_loop_device = loopdevice::attach(
-            &apk_path, 0, apk_size, /* direct_io */ true, /* writable */ false,
+            &apk_path,
+            0,
+            apk_size,
+            &LoopConfigOptions { direct_io: true, ..Default::default() },
         )
-        .unwrap();
+        .unwrap()
+        .path;
         let idsig_loop_device = scopeguard::guard(
-            loopdevice::attach(
-                &idsig_path,
-                0,
-                idsig_size,
-                /* direct_io */ false,
-                /* writable */ false,
-            )
-            .unwrap(),
+            loopdevice::attach(&idsig_path, 0, idsig_size, &LoopConfigOptions::default())
+                .unwrap()
+                .path,
             |dev| loopdevice::detach(dev).unwrap(),
         );
 
diff --git a/guest/authfs/src/common.rs b/guest/authfs/src/common.rs
index 6556fde..fc5af89 100644
--- a/guest/authfs/src/common.rs
+++ b/guest/authfs/src/common.rs
@@ -18,7 +18,7 @@
 pub const CHUNK_SIZE: u64 = 4096;
 
 pub fn divide_roundup(dividend: u64, divisor: u64) -> u64 {
-    (dividend + divisor - 1) / divisor
+    dividend.div_ceil(divisor)
 }
 
 /// Given `offset` and `length`, generates (offset, size) tuples that together form the same length,
diff --git a/guest/authfs/src/fsverity/metadata/metadata.rs b/guest/authfs/src/fsverity/metadata/metadata.rs
index 54d0145..2e78190 100644
--- a/guest/authfs/src/fsverity/metadata/metadata.rs
+++ b/guest/authfs/src/fsverity/metadata/metadata.rs
@@ -131,8 +131,7 @@
     };
 
     // merkle tree is at the next 4K boundary
-    let merkle_tree_offset =
-        (metadata_file.stream_position()? + CHUNK_SIZE - 1) / CHUNK_SIZE * CHUNK_SIZE;
+    let merkle_tree_offset = (metadata_file.stream_position()?).div_ceil(CHUNK_SIZE) * CHUNK_SIZE;
 
     Ok(Box::new(FSVerityMetadata { header, digest, signature, metadata_file, merkle_tree_offset }))
 }
diff --git a/guest/authfs/src/fusefs.rs b/guest/authfs/src/fusefs.rs
index fa4076d..9e49046 100644
--- a/guest/authfs/src/fusefs.rs
+++ b/guest/authfs/src/fusefs.rs
@@ -816,7 +816,7 @@
                     // FUSE ioctl is limited, thus we can't implement fs-verity ioctls without a
                     // kernel change (see b/196635431). Until it's possible, use
                     // xattr to expose what we need as an authfs specific API.
-                    if name != CStr::from_bytes_with_nul(b"authfs.fsverity.digest\0").unwrap() {
+                    if name != c"authfs.fsverity.digest" {
                         return Err(io::Error::from_raw_os_error(libc::ENODATA));
                     }
 
diff --git a/guest/forwarder_guest/.gitignore b/guest/forwarder_guest/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/guest/forwarder_guest/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/guest/forwarder_guest_launcher/.gitignore b/guest/forwarder_guest_launcher/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/guest/forwarder_guest_launcher/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/guest/microdroid_launcher/Android.bp b/guest/microdroid_launcher/Android.bp
index 42c18cb..893ee98 100644
--- a/guest/microdroid_launcher/Android.bp
+++ b/guest/microdroid_launcher/Android.bp
@@ -12,5 +12,10 @@
         "libdl_android",
         "liblog",
     ],
+    static_libs: [
+        "libapexutil",
+        "libprotobuf-cpp-lite",
+        "lib_apex_manifest_proto_lite",
+    ],
     header_libs: ["vm_payload_headers"],
 }
diff --git a/guest/microdroid_launcher/main.cpp b/guest/microdroid_launcher/main.cpp
index 5ae9956..8e3d4e4 100644
--- a/guest/microdroid_launcher/main.cpp
+++ b/guest/microdroid_launcher/main.cpp
@@ -16,7 +16,9 @@
 
 #include <android-base/logging.h>
 #include <android-base/result.h>
+#include <android-base/strings.h>
 #include <android/dlext.h>
+#include <apexutil.h>
 #include <dlfcn.h>
 
 #include <cstdlib>
@@ -25,8 +27,11 @@
 
 #include "vm_main.h"
 
+using android::apex::GetActivePackages;
 using android::base::Error;
+using android::base::Join;
 using android::base::Result;
+using android::base::StringReplace;
 
 extern "C" {
 enum {
@@ -43,6 +48,8 @@
 extern bool android_link_namespaces(struct android_namespace_t* from,
                                     struct android_namespace_t* to,
                                     const char* shared_libs_sonames);
+
+extern struct android_namespace_t* android_get_exported_namespace(const char* name);
 } // extern "C"
 
 static Result<void*> load(const std::string& libname);
@@ -108,6 +115,32 @@
         return Error() << "Failed to link namespace: " << dlerror();
     }
 
+    // Make libraries provided by APEXes available to the payload
+    for (const auto& [_path, manifest] : GetActivePackages("/apex")) {
+        std::string namespace_name = StringReplace(manifest.name(), ".", "_", /* all */ true);
+        android_namespace_t* apex_ns = android_get_exported_namespace(namespace_name.c_str());
+        if (apex_ns == nullptr) {
+            // This means the namespace is configured as 'visible=false'. We can't link to an
+            // invisible namespace.
+            continue;
+        }
+
+        std::vector<std::string> libs = {manifest.providenativelibs().begin(),
+                                         manifest.providenativelibs().end()};
+        if (libs.size() == 0) {
+            continue;
+        }
+        std::string shared_lib_sonames = Join(libs, ':');
+
+        if (!android_link_namespaces(new_ns, apex_ns, shared_lib_sonames.c_str())) {
+            return Error() << "Failed to link APEX namespace " << namespace_name << ": "
+                           << dlerror();
+        }
+
+        LOG(INFO) << "Linked APEX namespace " << namespace_name << " with shared libs "
+                  << shared_lib_sonames;
+    }
+
     const android_dlextinfo info = {
             .flags = ANDROID_DLEXT_USE_NAMESPACE,
             .library_namespace = new_ns,
diff --git a/guest/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl b/guest/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
index 30c4299..8d02d97 100644
--- a/guest/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
+++ b/guest/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
@@ -130,4 +130,13 @@
      *         certification chain.
      */
     AttestationResult requestAttestation(in byte[] challenge, in boolean testMode);
+
+    /**
+     * Checks whether the VM instance is new - i.e., if this is the first run of an instance.
+     * This is an indication of fresh new VM secrets. Payload can use this to setup the fresh
+     * instance if needed.
+     *
+     * @return true on the first boot of the instance & false on subsequent boot.
+     */
+    boolean isNewInstance();
 }
diff --git a/guest/microdroid_manager/src/main.rs b/guest/microdroid_manager/src/main.rs
index 451c3c8..57ad35d 100644
--- a/guest/microdroid_manager/src/main.rs
+++ b/guest/microdroid_manager/src/main.rs
@@ -250,7 +250,7 @@
 
     if is_strict_boot() {
         // Provisioning must happen on the first boot and never again.
-        if is_new_instance() {
+        if is_new_instance_legacy() {
             ensure!(
                 saved_data.is_none(),
                 MicrodroidError::PayloadInvalidConfig(
@@ -297,6 +297,17 @@
     Ok(instance_data)
 }
 
+// The VM instance run can be
+// 1. Either Newly created - which can happen if this is really a new VM instance (or a malicious
+//    Android has deleted relevant secrets)
+// 2. Or Re-run from an already seen VM instance.
+#[derive(PartialEq, Eq)]
+enum VmInstanceState {
+    Unknown,
+    NewlyCreated,
+    PreviouslySeen,
+}
+
 fn try_run_payload(
     service: &Strong<dyn IVirtualMachineService>,
     vm_payload_service_fd: OwnedFd,
@@ -326,8 +337,25 @@
     // To minimize the exposure to untrusted data, derive dice profile as soon as possible.
     info!("DICE derivation for payload");
     let dice_artifacts = dice_derivation(dice, &instance_data, &payload_metadata)?;
-    let vm_secret =
-        VmSecret::new(dice_artifacts, service).context("Failed to create VM secrets")?;
+    let mut state = VmInstanceState::Unknown;
+    let vm_secret = VmSecret::new(dice_artifacts, service, &mut state)
+        .context("Failed to create VM secrets")?;
+
+    let is_new_instance = match state {
+        VmInstanceState::NewlyCreated => true,
+        VmInstanceState::PreviouslySeen => false,
+        VmInstanceState::Unknown => {
+            // VmSecret instantiation was not able to determine the state. This should only happen
+            // for legacy secret mechanism (V1) - in which case fallback to legacy
+            // instance.img based determination of state.
+            ensure!(
+                !should_defer_rollback_protection(),
+                "VmInstanceState is Unknown whilst guest is expected to use V2 based secrets.
+                This should've never happened"
+            );
+            is_new_instance_legacy()
+        }
+    };
 
     if cfg!(dice_changes) {
         // Now that the DICE derivation is done, it's ok to allow payload code to run.
@@ -387,6 +415,7 @@
         service.clone(),
         vm_secret,
         vm_payload_service_fd,
+        is_new_instance,
     )?;
 
     // Set export_tombstones if enabled
@@ -488,7 +517,7 @@
     Path::new(AVF_STRICT_BOOT).exists()
 }
 
-fn is_new_instance() -> bool {
+fn is_new_instance_legacy() -> bool {
     Path::new(AVF_NEW_INSTANCE).exists()
 }
 
diff --git a/guest/microdroid_manager/src/vm_payload_service.rs b/guest/microdroid_manager/src/vm_payload_service.rs
index c4a9111..fb57812 100644
--- a/guest/microdroid_manager/src/vm_payload_service.rs
+++ b/guest/microdroid_manager/src/vm_payload_service.rs
@@ -33,6 +33,7 @@
     allow_restricted_apis: bool,
     virtual_machine_service: Strong<dyn IVirtualMachineService>,
     secret: VmSecret,
+    is_new_instance: bool,
 }
 
 impl IVmPayloadService for VmPayloadService {
@@ -116,6 +117,10 @@
             .or_service_specific_exception(-1)?;
         Ok(())
     }
+
+    fn isNewInstance(&self) -> binder::Result<bool> {
+        Ok(self.is_new_instance)
+    }
 }
 
 impl Interface for VmPayloadService {}
@@ -126,8 +131,9 @@
         allow_restricted_apis: bool,
         vm_service: Strong<dyn IVirtualMachineService>,
         secret: VmSecret,
+        is_new_instance: bool,
     ) -> VmPayloadService {
-        Self { allow_restricted_apis, virtual_machine_service: vm_service, secret }
+        Self { allow_restricted_apis, virtual_machine_service: vm_service, secret, is_new_instance }
     }
 
     fn check_restricted_apis_allowed(&self) -> binder::Result<()> {
@@ -147,9 +153,10 @@
     vm_service: Strong<dyn IVirtualMachineService>,
     secret: VmSecret,
     vm_payload_service_fd: OwnedFd,
+    is_new_instance: bool,
 ) -> Result<()> {
     let vm_payload_binder = BnVmPayloadService::new_binder(
-        VmPayloadService::new(allow_restricted_apis, vm_service, secret),
+        VmPayloadService::new(allow_restricted_apis, vm_service, secret, is_new_instance),
         BinderFeatures::default(),
     );
 
diff --git a/guest/microdroid_manager/src/vm_secret.rs b/guest/microdroid_manager/src/vm_secret.rs
index 5489751..5999122 100644
--- a/guest/microdroid_manager/src/vm_secret.rs
+++ b/guest/microdroid_manager/src/vm_secret.rs
@@ -38,6 +38,7 @@
 use zeroize::Zeroizing;
 use std::sync::Mutex;
 use std::sync::Arc;
+use crate::VmInstanceState;
 
 const ENCRYPTEDSTORE_KEY_IDENTIFIER: &str = "encryptedstore_key";
 const AUTHORITY_HASH: i64 = -4670549;
@@ -99,6 +100,7 @@
     pub fn new(
         dice_artifacts: OwnedDiceArtifacts,
         vm_service: &Strong<dyn IVirtualMachineService>,
+        state: &mut VmInstanceState,
     ) -> Result<Self> {
         ensure!(dice_artifacts.bcc().is_some(), "Dice chain missing");
         if !crate::should_defer_rollback_protection() {
@@ -116,11 +118,13 @@
         let session = SkVmSession::new(vm_service, &explicit_dice, policy)?;
         let mut skp_secret = Zeroizing::new([0u8; SECRET_SIZE]);
         if let Some(secret) = session.get_secret(id)? {
-            *skp_secret = secret
+            *skp_secret = secret;
+            *state = VmInstanceState::PreviouslySeen;
         } else {
             log::warn!("No entry found in Secretkeeper for this VM instance, creating new secret.");
             *skp_secret = rand::random();
             session.store_secret(id, skp_secret.clone())?;
+            *state = VmInstanceState::NewlyCreated;
         }
         Ok(Self::V2 {
             instance_id: id,
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index da056d6..4ef57a6 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -113,6 +113,7 @@
         "libcbor_util",
         "libciborium",
         "libdiced_open_dice_nostd",
+        "libhwtrust",
         "libpvmfw_avb_nostd",
         "libdiced_sample_inputs_nostd",
         "libzerocopy_nostd",
diff --git a/guest/pvmfw/avb/tests/api_test.rs b/guest/pvmfw/avb/tests/api_test.rs
index 23e05d4..29a6277 100644
--- a/guest/pvmfw/avb/tests/api_test.rs
+++ b/guest/pvmfw/avb/tests/api_test.rs
@@ -23,7 +23,6 @@
 use std::{
     fs,
     mem::{offset_of, size_of},
-    ptr,
 };
 use utils::*;
 
@@ -414,9 +413,9 @@
     // vbmeta_header is unaligned; copy flags to local variable
     let vbmeta_header_flags = vbmeta_header.flags;
     assert_eq!(0, vbmeta_header_flags, "The disable flag should not be set in the latest kernel.");
-    let flags_addr = ptr::addr_of!(vbmeta_header.flags) as *const u8;
+    let flags_addr = (&raw const vbmeta_header.flags).cast::<u8>();
     // SAFETY: It is safe as both raw pointers `flags_addr` and `vbmeta_header` are not null.
-    let flags_offset = unsafe { flags_addr.offset_from(ptr::addr_of!(vbmeta_header) as *const u8) };
+    let flags_offset = unsafe { flags_addr.offset_from((&raw const vbmeta_header).cast::<u8>()) };
     let flags_offset = usize::try_from(footer.vbmeta_offset)? + usize::try_from(flags_offset)?;
 
     // Act.
diff --git a/guest/pvmfw/src/dice.rs b/guest/pvmfw/src/dice.rs
index a72c1fc..4df10b3 100644
--- a/guest/pvmfw/src/dice.rs
+++ b/guest/pvmfw/src/dice.rs
@@ -156,9 +156,7 @@
     fn generate_config_descriptor(&self, instance_hash: Option<Hash>) -> Result<Vec<u8>> {
         let mut config = Vec::with_capacity(4);
         config.push((cbor!(COMPONENT_NAME_KEY)?, cbor!("vm_entry")?));
-        if cfg!(dice_changes) {
-            config.push((cbor!(SECURITY_VERSION_KEY)?, cbor!(self.security_version)?));
-        }
+        config.push((cbor!(SECURITY_VERSION_KEY)?, cbor!(self.security_version)?));
         if self.rkp_vm_marker {
             config.push((cbor!(RKP_VM_MARKER_KEY)?, Value::Null))
         }
@@ -185,6 +183,7 @@
     use diced_open_dice::KeyAlgorithm;
     use diced_open_dice::HIDDEN_SIZE;
     use diced_sample_inputs::make_sample_bcc_and_cdis;
+    use hwtrust::{dice, session::Session};
     use pvmfw_avb::Capability;
     use pvmfw_avb::DebugLevel;
     use pvmfw_avb::Digest;
@@ -244,14 +243,7 @@
         assert_eq!(config_map.get(&COMPONENT_NAME_KEY).unwrap().as_text().unwrap(), "vm_entry");
         assert_eq!(config_map.get(&COMPONENT_VERSION_KEY), None);
         assert_eq!(config_map.get(&RESETTABLE_KEY), None);
-        if cfg!(dice_changes) {
-            assert_eq!(
-                config_map.get(&SECURITY_VERSION_KEY).unwrap().as_integer().unwrap(),
-                42.into()
-            );
-        } else {
-            assert_eq!(config_map.get(&SECURITY_VERSION_KEY), None);
-        }
+        assert_eq!(config_map.get(&SECURITY_VERSION_KEY).unwrap().as_integer().unwrap(), 42.into());
         assert_eq!(config_map.get(&RKP_VM_MARKER_KEY), None);
     }
 
@@ -426,14 +418,11 @@
                 },
             )
             .expect("Failed to derive EcdsaP384 -> Ed25519 BCC");
-        let _bcc_handover3 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
+        let bcc_handover3 = diced_open_dice::bcc_handover_parse(&buffer).unwrap();
 
-        // TODO(b/378813154): Check the DICE chain with `hwtrust` once the profile version
-        // is updated.
-        // The check cannot be done now because parsing the chain causes the following error:
-        // Invalid payload at index 3. Caused by:
-        // 0: opendice.example.p256
-        // 1: unknown profile version
+        let mut session = Session::default();
+        session.set_allow_any_mode(true);
+        let _chain = dice::Chain::from_cbor(&session, bcc_handover3.bcc().unwrap()).unwrap();
     }
 
     fn to_bcc_handover(dice_artifacts: &dyn DiceArtifacts) -> Vec<u8> {
diff --git a/guest/pvmfw/src/fdt.rs b/guest/pvmfw/src/fdt.rs
index 29212f9..818d342 100644
--- a/guest/pvmfw/src/fdt.rs
+++ b/guest/pvmfw/src/fdt.rs
@@ -112,6 +112,24 @@
     Ok(None)
 }
 
+/// Read /avf/untrusted/instance-id, if present.
+pub fn read_instance_id(fdt: &Fdt) -> libfdt::Result<Option<&[u8]>> {
+    read_avf_untrusted_prop(fdt, c"instance-id")
+}
+
+/// Read /avf/untrusted/defer-rollback-protection, if present.
+pub fn read_defer_rollback_protection(fdt: &Fdt) -> libfdt::Result<Option<&[u8]>> {
+    read_avf_untrusted_prop(fdt, c"defer-rollback-protection")
+}
+
+fn read_avf_untrusted_prop<'a>(fdt: &'a Fdt, prop: &CStr) -> libfdt::Result<Option<&'a [u8]>> {
+    if let Some(node) = fdt.node(c"/avf/untrusted")? {
+        node.getprop(prop)
+    } else {
+        Ok(None)
+    }
+}
+
 fn patch_initrd_range(fdt: &mut Fdt, initrd_range: &Range<usize>) -> libfdt::Result<()> {
     let start = u32::try_from(initrd_range.start).unwrap();
     let end = u32::try_from(initrd_range.end).unwrap();
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 0a3dca6..afa64e0 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -35,22 +35,20 @@
 use crate::bcc::Bcc;
 use crate::dice::PartialInputs;
 use crate::entry::RebootReason;
-use crate::fdt::{modify_for_next_stage, sanitize_device_tree};
+use crate::fdt::{modify_for_next_stage, read_instance_id, sanitize_device_tree};
 use crate::rollback::perform_rollback_protection;
 use alloc::borrow::Cow;
 use alloc::boxed::Box;
 use bssl_avf::Digester;
 use diced_open_dice::{bcc_handover_parse, DiceArtifacts, DiceContext, Hidden, VM_KEY_ALGORITHM};
-use libfdt::{Fdt, FdtNode};
+use libfdt::Fdt;
 use log::{debug, error, info, trace, warn};
 use pvmfw_avb::verify_payload;
 use pvmfw_avb::DebugLevel;
 use pvmfw_embedded_key::PUBLIC_KEY;
-use vmbase::fdt::pci::{PciError, PciInfo};
 use vmbase::heap;
-use vmbase::memory::{flush, init_shared_pool, SIZE_4KB};
+use vmbase::memory::{flush, SIZE_4KB};
 use vmbase::rand;
-use vmbase::virtio::pci;
 
 fn main<'a>(
     untrusted_fdt: &mut Fdt,
@@ -77,8 +75,6 @@
     })?;
     trace!("BCC: {bcc_handover:x?}");
 
-    let cdi_seal = bcc_handover.cdi_seal();
-
     let bcc = Bcc::new(bcc_handover.bcc()).map_err(|e| {
         error!("{e}");
         RebootReason::InvalidBcc
@@ -102,19 +98,8 @@
     }
 
     let guest_page_size = verified_boot_data.page_size.unwrap_or(SIZE_4KB);
-    let fdt_info = sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt, guest_page_size)?;
+    let _ = sanitize_device_tree(untrusted_fdt, vm_dtbo, vm_ref_dt, guest_page_size)?;
     let fdt = untrusted_fdt; // DT has now been sanitized.
-    let pci_info = PciInfo::from_fdt(fdt).map_err(handle_pci_error)?;
-    debug!("PCI: {:#x?}", pci_info);
-    // Set up PCI bus for VirtIO devices.
-    let mut pci_root = pci::initialize(pci_info).map_err(|e| {
-        error!("Failed to initialize PCI: {e}");
-        RebootReason::InternalError
-    })?;
-    init_shared_pool(fdt_info.swiotlb_info.fixed_range()).map_err(|e| {
-        error!("Failed to initialize shared pool: {e}");
-        RebootReason::InternalError
-    })?;
 
     let next_bcc_size = guest_page_size;
     let next_bcc = heap::aligned_boxed_slice(next_bcc_size, guest_page_size).ok_or_else(|| {
@@ -129,13 +114,12 @@
         RebootReason::InternalError
     })?;
 
-    let instance_hash = Some(salt_from_instance_id(fdt)?);
+    let instance_hash = salt_from_instance_id(fdt)?;
     let (new_instance, salt, defer_rollback_protection) = perform_rollback_protection(
         fdt,
         &verified_boot_data,
         &dice_inputs,
-        &mut pci_root,
-        cdi_seal,
+        bcc_handover.cdi_seal(),
         instance_hash,
     )?;
     trace!("Got salt for instance: {salt:x?}");
@@ -204,8 +188,14 @@
 
 // Get the "salt" which is one of the input for DICE derivation.
 // This provides differentiation of secrets for different VM instances with same payloads.
-fn salt_from_instance_id(fdt: &Fdt) -> Result<Hidden, RebootReason> {
-    let id = instance_id(fdt)?;
+fn salt_from_instance_id(fdt: &Fdt) -> Result<Option<Hidden>, RebootReason> {
+    let Some(id) = read_instance_id(fdt).map_err(|e| {
+        error!("Failed to get instance-id in DT: {e}");
+        RebootReason::InvalidFdt
+    })?
+    else {
+        return Ok(None);
+    };
     let salt = Digester::sha512()
         .digest(&[&b"InstanceId:"[..], id].concat())
         .map_err(|e| {
@@ -214,46 +204,5 @@
         })?
         .try_into()
         .map_err(|_| RebootReason::InternalError)?;
-    Ok(salt)
-}
-
-fn instance_id(fdt: &Fdt) -> Result<&[u8], RebootReason> {
-    let node = avf_untrusted_node(fdt)?;
-    let id = node.getprop(c"instance-id").map_err(|e| {
-        error!("Failed to get instance-id in DT: {e}");
-        RebootReason::InvalidFdt
-    })?;
-    id.ok_or_else(|| {
-        error!("Missing instance-id");
-        RebootReason::InvalidFdt
-    })
-}
-
-fn avf_untrusted_node(fdt: &Fdt) -> Result<FdtNode, RebootReason> {
-    let node = fdt.node(c"/avf/untrusted").map_err(|e| {
-        error!("Failed to get /avf/untrusted node: {e}");
-        RebootReason::InvalidFdt
-    })?;
-    node.ok_or_else(|| {
-        error!("/avf/untrusted node is missing in DT");
-        RebootReason::InvalidFdt
-    })
-}
-
-/// Logs the given PCI error and returns the appropriate `RebootReason`.
-fn handle_pci_error(e: PciError) -> RebootReason {
-    error!("{}", e);
-    match e {
-        PciError::FdtErrorPci(_)
-        | PciError::FdtNoPci
-        | PciError::FdtErrorReg(_)
-        | PciError::FdtMissingReg
-        | PciError::FdtRegEmpty
-        | PciError::FdtRegMissingSize
-        | PciError::CamWrongSize(_)
-        | PciError::FdtErrorRanges(_)
-        | PciError::FdtMissingRanges
-        | PciError::RangeAddressMismatch { .. }
-        | PciError::NoSuitableRange => RebootReason::InvalidFdt,
-    }
+    Ok(Some(salt))
 }
diff --git a/guest/pvmfw/src/rollback.rs b/guest/pvmfw/src/rollback.rs
index f7723d7..74b2cd8 100644
--- a/guest/pvmfw/src/rollback.rs
+++ b/guest/pvmfw/src/rollback.rs
@@ -16,16 +16,20 @@
 
 use crate::dice::PartialInputs;
 use crate::entry::RebootReason;
+use crate::fdt::read_defer_rollback_protection;
 use crate::instance::EntryBody;
 use crate::instance::Error as InstanceError;
 use crate::instance::{get_recorded_entry, record_instance_entry};
 use diced_open_dice::Hidden;
-use libfdt::{Fdt, FdtNode};
+use libfdt::Fdt;
 use log::{error, info};
 use pvmfw_avb::Capability;
 use pvmfw_avb::VerifiedBootData;
 use virtio_drivers::transport::pci::bus::PciRoot;
+use vmbase::fdt::{pci::PciInfo, SwiotlbInfo};
+use vmbase::memory::init_shared_pool;
 use vmbase::rand;
+use vmbase::virtio::pci;
 
 /// Performs RBP based on the input payload, current DICE chain, and host-controlled platform.
 ///
@@ -37,7 +41,6 @@
     fdt: &Fdt,
     verified_boot_data: &VerifiedBootData,
     dice_inputs: &PartialInputs,
-    pci_root: &mut PciRoot,
     cdi_seal: &[u8],
     instance_hash: Option<Hidden>,
 ) -> Result<(bool, Hidden, bool), RebootReason> {
@@ -53,7 +56,7 @@
         skip_rollback_protection()?;
         Ok((false, instance_hash.unwrap(), false))
     } else {
-        perform_legacy_rollback_protection(dice_inputs, pci_root, cdi_seal, instance_hash)
+        perform_legacy_rollback_protection(fdt, dice_inputs, cdi_seal, instance_hash)
     }
 }
 
@@ -92,17 +95,18 @@
 
 /// Performs RBP using instance.img where updates require clearing old entries, causing new CDIs.
 fn perform_legacy_rollback_protection(
+    fdt: &Fdt,
     dice_inputs: &PartialInputs,
-    pci_root: &mut PciRoot,
     cdi_seal: &[u8],
     instance_hash: Option<Hidden>,
 ) -> Result<(bool, Hidden, bool), RebootReason> {
     info!("Fallback to instance.img based rollback checks");
-    let (recorded_entry, mut instance_img, header_index) = get_recorded_entry(pci_root, cdi_seal)
-        .map_err(|e| {
-        error!("Failed to get entry from instance.img: {e}");
-        RebootReason::InternalError
-    })?;
+    let mut pci_root = initialize_instance_img_device(fdt)?;
+    let (recorded_entry, mut instance_img, header_index) =
+        get_recorded_entry(&mut pci_root, cdi_seal).map_err(|e| {
+            error!("Failed to get entry from instance.img: {e}");
+            RebootReason::InternalError
+        })?;
     let (new_instance, salt) = if let Some(entry) = recorded_entry {
         check_dice_measurements_match_entry(dice_inputs, &entry)?;
         let salt = instance_hash.unwrap_or(entry.salt);
@@ -155,24 +159,34 @@
 }
 
 fn should_defer_rollback_protection(fdt: &Fdt) -> Result<bool, RebootReason> {
-    let node = avf_untrusted_node(fdt)?;
-    let defer_rbp = node
-        .getprop(c"defer-rollback-protection")
-        .map_err(|e| {
-            error!("Failed to get defer-rollback-protection property in DT: {e}");
-            RebootReason::InvalidFdt
-        })?
-        .is_some();
-    Ok(defer_rbp)
-}
-
-fn avf_untrusted_node(fdt: &Fdt) -> Result<FdtNode, RebootReason> {
-    let node = fdt.node(c"/avf/untrusted").map_err(|e| {
-        error!("Failed to get /avf/untrusted node: {e}");
+    let defer_rbp = read_defer_rollback_protection(fdt).map_err(|e| {
+        error!("Failed to get defer-rollback-protection property in DT: {e}");
         RebootReason::InvalidFdt
     })?;
-    node.ok_or_else(|| {
-        error!("/avf/untrusted node is missing in DT");
+    Ok(defer_rbp.is_some())
+}
+
+/// Set up PCI bus and VirtIO-blk device containing the instance.img partition.
+fn initialize_instance_img_device(fdt: &Fdt) -> Result<PciRoot, RebootReason> {
+    let pci_info = PciInfo::from_fdt(fdt).map_err(|e| {
+        error!("Failed to detect PCI from DT: {e}");
         RebootReason::InvalidFdt
-    })
+    })?;
+    let swiotlb_range = SwiotlbInfo::new_from_fdt(fdt)
+        .map_err(|e| {
+            error!("Failed to detect swiotlb from DT: {e}");
+            RebootReason::InvalidFdt
+        })?
+        .and_then(|info| info.fixed_range());
+
+    let pci_root = pci::initialize(pci_info).map_err(|e| {
+        error!("Failed to initialize PCI: {e}");
+        RebootReason::InternalError
+    })?;
+    init_shared_pool(swiotlb_range).map_err(|e| {
+        error!("Failed to initialize shared pool: {e}");
+        RebootReason::InternalError
+    })?;
+
+    Ok(pci_root)
 }
diff --git a/guest/rialto/tests/test.rs b/guest/rialto/tests/test.rs
index c94a0e3..d68c568 100644
--- a/guest/rialto/tests/test.rs
+++ b/guest/rialto/tests/test.rs
@@ -54,13 +54,9 @@
 const INSTANCE_IMG_PATH: &str = "/data/local/tmp/rialto_test/arm64/instance.img";
 const TEST_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
 
-#[cfg(dice_changes)]
 #[test]
 fn process_requests_in_protected_vm() -> Result<()> {
     if hypervisor_props::is_protected_vm_supported()? {
-        // The test is skipped if the feature flag |dice_changes| is not enabled, because when
-        // the flag is off, the DICE chain is truncated in the pvmfw, and the service VM cannot
-        // verify the chain due to the missing entries in the chain.
         check_processing_requests(VmType::ProtectedVm, None)
     } else {
         warn!("pVMs are not supported on device, skipping test");
diff --git a/guest/trusty/security_vm/launcher/Android.bp b/guest/trusty/security_vm/launcher/Android.bp
index fea8873..ff628fd 100644
--- a/guest/trusty/security_vm/launcher/Android.bp
+++ b/guest/trusty/security_vm/launcher/Android.bp
@@ -18,56 +18,3 @@
         false: false,
     }),
 }
-
-prebuilt_etc {
-    name: "lk_trusty.elf",
-    system_ext_specific: true,
-    relative_install_path: "vm/trusty_vm",
-    filename: "lk_trusty.elf",
-    arch: {
-        x86_64: {
-            src: ":trusty_security_vm_signed",
-        },
-        arm64: {
-            src: ":trusty_security_vm_signed",
-        },
-    },
-    src: ":empty_file",
-}
-
-filegroup {
-    name: "trusty_vm_sign_key",
-    srcs: [":avb_testkey_rsa4096"],
-}
-
-// python -c "import hashlib; print(hashlib.sha256(b'trusty_security_vm_salt').hexdigest())"
-trusty_security_vm_salt = "75a71e967c1a1e0f805cca20465e7acf83e6a04e567a67c426d8b5a94f8d61c5"
-
-TRUSTY_SECURITY_VM_VERSION = 1
-
-avb_add_hash_footer {
-    name: "trusty_security_vm_signed",
-    filename: "trusty_security_vm_signed",
-    partition_name: "boot",
-    private_key: ":trusty_vm_sign_key",
-    salt: trusty_security_vm_salt,
-    rollback_index: TRUSTY_SECURITY_VM_VERSION,
-    props: [
-        {
-            name: "com.android.virt.cap",
-            value: "trusty_security_vm",
-        },
-    ],
-    src: ":empty_file",
-    enabled: false,
-    arch: {
-        x86_64: {
-            src: ":trusty-lk.elf",
-            enabled: true,
-        },
-        arm64: {
-            src: ":trusty-test-lk.elf",
-            enabled: true,
-        },
-    },
-}
diff --git a/guest/trusty/security_vm/vm/Android.bp b/guest/trusty/security_vm/vm/Android.bp
new file mode 100644
index 0000000..ee64095
--- /dev/null
+++ b/guest/trusty/security_vm/vm/Android.bp
@@ -0,0 +1,136 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+prebuilt_etc {
+    name: "lk_trusty.elf",
+    system_ext_specific: true,
+    relative_install_path: "vm/trusty_vm",
+    filename: "lk_trusty.elf",
+    arch: {
+        x86_64: {
+            src: ":trusty_security_vm_signed",
+        },
+        arm64: {
+            src: ":security_vm_elf",
+        },
+    },
+    src: ":empty_file",
+}
+
+cc_binary {
+    name: "security_vm_elf",
+    srcs: [
+        ":security_vm_signed_obj",
+    ],
+    linker_scripts: [
+        "security_vm_sections.ld",
+    ],
+    ldflags: [
+        // Prevent the `trusty_security_vm_signed` segment from being garbage collected.
+        "-Wl,--no-gc-sections",
+        // Prevent the build ID segments from being added, as it would corrupt the integrity
+        // of the original signed image.
+        "-Wl,--build-id=none",
+        // Use a standard page size of 4096, smaller than the default 16384, to avoid padding
+        // with extra bytes.
+        "-Wl,-z,max-page-size=4096",
+    ],
+    nocrt: true,
+    no_libcrt: true,
+    static_executable: true,
+    system_shared_libs: [],
+    enabled: false,
+    target: {
+        android_arm64: {
+            enabled: true,
+        },
+    },
+    strip: {
+        none: true,
+    },
+}
+
+cc_genrule {
+    name: "security_vm.S",
+    arch: {
+        arm64: {
+            srcs: [":trusty_security_vm_signed"],
+        },
+    },
+    out: ["security_vm.S"],
+    cmd: "(" +
+        "    echo '.section .security_vm_signed.bin';" +
+        "    echo '.globl security_vm_signed';" +
+        "    echo 'security_vm_signed:';" +
+        "    echo '.incbin \"'$(in)'\"';" +
+        ") > $(out)",
+    visibility: ["//visibility:private"],
+}
+
+cc_object {
+    name: "security_vm_signed_obj",
+    srcs: [
+        ":security_vm.S",
+    ],
+    static_libs: ["trusty_security_vm_signed"],
+    crt: false,
+    system_shared_libs: [],
+    enabled: false,
+    target: {
+        android_arm64: {
+            enabled: true,
+        },
+    },
+    visibility: ["//visibility:private"],
+}
+
+filegroup {
+    name: "trusty_vm_sign_key",
+    srcs: [":avb_testkey_rsa4096"],
+}
+
+// python -c "import hashlib; print(hashlib.sha256(b'trusty_security_vm_salt').hexdigest())"
+trusty_security_vm_salt = "75a71e967c1a1e0f805cca20465e7acf83e6a04e567a67c426d8b5a94f8d61c5"
+
+TRUSTY_SECURITY_VM_VERSION = 1
+
+avb_add_hash_footer {
+    name: "trusty_security_vm_signed",
+    filename: "trusty_security_vm_signed",
+    partition_name: "boot",
+    private_key: ":trusty_vm_sign_key",
+    salt: trusty_security_vm_salt,
+    rollback_index: TRUSTY_SECURITY_VM_VERSION,
+    props: [
+        {
+            name: "com.android.virt.cap",
+            value: "trusty_security_vm",
+        },
+    ],
+    src: ":empty_file",
+    enabled: false,
+    arch: {
+        x86_64: {
+            src: ":trusty-lk.elf",
+            enabled: true,
+        },
+        arm64: {
+            src: ":trusty_security_vm_unsigned",
+            enabled: true,
+        },
+    },
+}
+
+// TODO(b/379646659): Take the binary generated by trusty instead of extracting
+// it from ELF here.
+raw_binary {
+    name: "trusty_security_vm_unsigned",
+    src: ":trusty-test-lk.elf",
+    enabled: false,
+    arch: {
+        arm64: {
+            enabled: true,
+        },
+    },
+}
diff --git a/guest/trusty/security_vm/vm/security_vm_sections.ld b/guest/trusty/security_vm/vm/security_vm_sections.ld
new file mode 100644
index 0000000..63e5f5d
--- /dev/null
+++ b/guest/trusty/security_vm/vm/security_vm_sections.ld
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2025 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
+ *
+ *     https://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.
+ */
+
+ENTRY(security_vm_signed)
+
+SECTIONS
+{
+    . = 0x0;
+    .text : {
+        *(.security_vm_signed.bin)
+    }
+}
diff --git a/guest/vmbase_example/Android.bp b/guest/vmbase_example/Android.bp
index ab21191..30d72bd 100644
--- a/guest/vmbase_example/Android.bp
+++ b/guest/vmbase_example/Android.bp
@@ -12,6 +12,7 @@
         "libdiced_open_dice_nostd",
         "liblibfdt_nostd",
         "liblog_rust_nostd",
+        "libspin_nostd",
         "libvirtio_drivers",
         "libvmbase",
     ],
@@ -39,6 +40,9 @@
         "-E",
         "-P",
         "-xassembler-with-cpp", // allow C preprocessor directives
+        // Soong passes an implicit -c before -E. Suppress the warning about -c
+        // being unused.
+        "-Wno-unused-command-line-argument",
     ],
     srcs: [":vmbase_image.ld.S.mm"],
     visibility: ["//visibility:private"],
diff --git a/guest/vmbase_example/src/main.rs b/guest/vmbase_example/src/main.rs
index f5b41bd..b7d2f95 100644
--- a/guest/vmbase_example/src/main.rs
+++ b/guest/vmbase_example/src/main.rs
@@ -26,9 +26,9 @@
 use crate::layout::print_addresses;
 use crate::pci::check_pci;
 use alloc::{vec, vec::Vec};
-use core::ptr::addr_of_mut;
 use libfdt::Fdt;
 use log::{debug, error, info, trace, warn, LevelFilter};
+use spin::mutex::SpinMutex;
 use vmbase::{
     bionic, configure_heap,
     fdt::pci::PciInfo,
@@ -39,8 +39,8 @@
 };
 
 static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
-static mut ZEROED_DATA: [u32; 10] = [0; 10];
-static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
+static ZEROED_DATA: SpinMutex<[u32; 10]> = SpinMutex::new([0; 10]);
+static MUTABLE_DATA: SpinMutex<[u32; 4]> = SpinMutex::new([1, 2, 3, 4]);
 
 generate_image_header!();
 main!(main);
@@ -103,22 +103,16 @@
 
 fn check_data() {
     info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
-    // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
-    info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
-    // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
-    info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
 
     assert_eq!(INITIALISED_DATA[0], 1);
     assert_eq!(INITIALISED_DATA[1], 2);
     assert_eq!(INITIALISED_DATA[2], 3);
     assert_eq!(INITIALISED_DATA[3], 4);
 
-    // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
-    // chance of concurrent access.
-    let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
-    // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
-    // chance of concurrent access.
-    let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
+    let zeroed_data = &mut *ZEROED_DATA.lock();
+    let mutable_data = &mut *MUTABLE_DATA.lock();
+    info!("ZEROED_DATA: {:?}", zeroed_data.as_ptr());
+    info!("MUTABLE_DATA: {:?}", mutable_data.as_ptr());
 
     for element in zeroed_data.iter() {
         assert_eq!(*element, 0);
diff --git a/libs/apkverify/src/hashtree.rs b/libs/apkverify/src/hashtree.rs
index 00d8292..54e879b 100644
--- a/libs/apkverify/src/hashtree.rs
+++ b/libs/apkverify/src/hashtree.rs
@@ -84,7 +84,7 @@
             let mut level0 = Cursor::new(&mut hash_tree[cur.start..cur.end]);
 
             let mut a_block = vec![0; block_size];
-            let mut num_blocks = (input_size + block_size - 1) / block_size;
+            let mut num_blocks = input_size.div_ceil(block_size);
             while num_blocks > 0 {
                 input.read_exact(&mut a_block)?;
                 let h = hash_one_block(&a_block, salt, block_size, algorithm)?;
@@ -138,7 +138,7 @@
         if input_size <= block_size {
             break;
         }
-        let num_blocks = (input_size + block_size - 1) / block_size;
+        let num_blocks = input_size.div_ceil(block_size);
         let hashes_size = round_to_multiple(num_blocks * digest_size, block_size);
         level_sizes.push(hashes_size);
     }
diff --git a/libs/bssl/src/cbb.rs b/libs/bssl/src/cbb.rs
index a48c714..282a77d 100644
--- a/libs/bssl/src/cbb.rs
+++ b/libs/bssl/src/cbb.rs
@@ -40,13 +40,13 @@
     }
 }
 
-impl<'a> AsRef<CBB> for CbbFixed<'a> {
+impl AsRef<CBB> for CbbFixed<'_> {
     fn as_ref(&self) -> &CBB {
         &self.cbb
     }
 }
 
-impl<'a> AsMut<CBB> for CbbFixed<'a> {
+impl AsMut<CBB> for CbbFixed<'_> {
     fn as_mut(&mut self) -> &mut CBB {
         &mut self.cbb
     }
diff --git a/libs/bssl/src/cbs.rs b/libs/bssl/src/cbs.rs
index 12671cf..166484c 100644
--- a/libs/bssl/src/cbs.rs
+++ b/libs/bssl/src/cbs.rs
@@ -42,13 +42,13 @@
     }
 }
 
-impl<'a> AsRef<CBS> for Cbs<'a> {
+impl AsRef<CBS> for Cbs<'_> {
     fn as_ref(&self) -> &CBS {
         &self.cbs
     }
 }
 
-impl<'a> AsMut<CBS> for Cbs<'a> {
+impl AsMut<CBS> for Cbs<'_> {
     fn as_mut(&mut self) -> &mut CBS {
         &mut self.cbs
     }
diff --git a/libs/bssl/src/ec_key.rs b/libs/bssl/src/ec_key.rs
index 3e2e382..da9eb77 100644
--- a/libs/bssl/src/ec_key.rs
+++ b/libs/bssl/src/ec_key.rs
@@ -471,7 +471,7 @@
 /// Wrapper of an `EC_GROUP` reference.
 struct EcGroup<'a>(&'a EC_GROUP);
 
-impl<'a> EcGroup<'a> {
+impl EcGroup<'_> {
     /// Returns the NID that identifies the EC group of the key.
     fn curve_nid(&self) -> i32 {
         // SAFETY: It is safe since the inner pointer is valid and points to an initialized
@@ -518,7 +518,7 @@
     }
 }
 
-impl<'a> AsRef<EC_GROUP> for EcGroup<'a> {
+impl AsRef<EC_GROUP> for EcGroup<'_> {
     fn as_ref(&self) -> &EC_GROUP {
         self.0
     }
diff --git a/libs/cstr/Android.bp b/libs/cstr/Android.bp
deleted file mode 100644
index 4ea87df..0000000
--- a/libs/cstr/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-rust_library_rlib {
-    name: "libcstr",
-    crate_name: "cstr",
-    defaults: ["avf_build_flags_rust"],
-    srcs: ["src/lib.rs"],
-    edition: "2021",
-    host_supported: true,
-    prefer_rlib: true,
-    target: {
-        android: {
-            no_stdlibs: true,
-            stdlibs: [
-                "libcompiler_builtins.rust_sysroot",
-                "libcore.rust_sysroot",
-            ],
-        },
-    },
-    apex_available: [
-        "//apex_available:platform",
-        "//apex_available:anyapex",
-    ],
-}
-
-rust_test {
-    name: "libcstr.tests",
-    crate_name: "libcstr_test",
-    defaults: ["avf_build_flags_rust"],
-    srcs: ["src/lib.rs"],
-    test_suites: ["general-tests"],
-    prefer_rlib: true,
-    rustlibs: ["libcstr"],
-}
diff --git a/libs/cstr/src/lib.rs b/libs/cstr/src/lib.rs
deleted file mode 100644
index ddf20fc..0000000
--- a/libs/cstr/src/lib.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2023, 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.
-
-//! Provide a safe const-compatible no_std macro for readable &'static CStr.
-
-#![no_std]
-
-/// Create &CStr out of &str literal
-#[macro_export]
-macro_rules! cstr {
-    ($str:literal) => {{
-        const S: &str = concat!($str, "\0");
-        const C: &::core::ffi::CStr = match ::core::ffi::CStr::from_bytes_with_nul(S.as_bytes()) {
-            Ok(v) => v,
-            Err(_) => panic!("string contains interior NUL"),
-        };
-        C
-    }};
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use std::ffi::CString;
-
-    #[test]
-    fn valid_input_string() {
-        let expected = CString::new("aaa").unwrap();
-        assert_eq!(cstr!("aaa"), expected.as_c_str());
-    }
-
-    #[test]
-    fn valid_empty_string() {
-        let expected = CString::new("").unwrap();
-        assert_eq!(cstr!(""), expected.as_c_str());
-    }
-
-    // As cstr!() panics at compile time, tests covering invalid inputs fail to compile!
-}
diff --git a/libs/devicemapper/Android.bp b/libs/devicemapper/Android.bp
index 5332469..6b7f680 100644
--- a/libs/devicemapper/Android.bp
+++ b/libs/devicemapper/Android.bp
@@ -8,7 +8,6 @@
     defaults: ["avf_build_flags_rust"],
     srcs: ["src/lib.rs"],
     edition: "2021",
-    prefer_rlib: true,
     rustlibs: [
         "libanyhow",
         "libbitflags",
@@ -18,16 +17,12 @@
         "libuuid",
         "libzerocopy",
     ],
-    multilib: {
-        lib32: {
-            enabled: false,
-        },
-    },
 }
 
 rust_library {
     name: "libdm_rust",
     defaults: ["libdm_rust.defaults"],
+    host_supported: true,
 }
 
 rust_test {
diff --git a/libs/devicemapper/src/crypt.rs b/libs/devicemapper/src/crypt.rs
index 75417ed..1326caf 100644
--- a/libs/devicemapper/src/crypt.rs
+++ b/libs/devicemapper/src/crypt.rs
@@ -87,7 +87,7 @@
     opt_params: Vec<&'a str>,
 }
 
-impl<'a> Default for DmCryptTargetBuilder<'a> {
+impl Default for DmCryptTargetBuilder<'_> {
     fn default() -> Self {
         DmCryptTargetBuilder {
             cipher: CipherType::AES256HCTR2,
diff --git a/libs/devicemapper/src/lib.rs b/libs/devicemapper/src/lib.rs
index a8f3049..a8c2833 100644
--- a/libs/devicemapper/src/lib.rs
+++ b/libs/devicemapper/src/lib.rs
@@ -235,6 +235,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::loopdevice::LoopConfigOptions;
     use crypt::{CipherType, DmCryptTargetBuilder};
     use rdroidtest::{ignore_if, rdroidtest};
     use rustutils::system_properties;
@@ -328,10 +329,10 @@
             backing_file,
             0,
             sz,
-            /* direct_io */ true,
-            /* writable */ true,
+            &LoopConfigOptions { direct_io: true, writable: true, ..Default::default() },
         )
-        .unwrap();
+        .unwrap()
+        .path;
         let device_diff = device.to_owned() + "_diff";
 
         scopeguard::defer! {
@@ -372,10 +373,10 @@
             backing_file,
             0,
             sz,
-            /* direct_io */ true,
-            /* writable */ true,
+            &LoopConfigOptions { direct_io: true, writable: true, ..Default::default() },
         )
-        .unwrap();
+        .unwrap()
+        .path;
         let device_diff = device.to_owned() + "_diff";
         scopeguard::defer! {
             loopdevice::detach(&data_device).unwrap();
diff --git a/libs/devicemapper/src/loopdevice.rs b/libs/devicemapper/src/loopdevice.rs
index 130c1c4..b830eda 100644
--- a/libs/devicemapper/src/loopdevice.rs
+++ b/libs/devicemapper/src/loopdevice.rs
@@ -59,14 +59,31 @@
     Ok(unsafe { _loop_clr_fd(device_file.as_raw_fd()) }?)
 }
 
+/// LOOP_CONFIGURE ioctl operation flags.
+#[derive(Default)]
+pub struct LoopConfigOptions {
+    /// Whether to use direct I/O
+    pub direct_io: bool,
+    /// Whether the device is writable
+    pub writable: bool,
+    /// Whether to autodestruct the device on last close
+    pub autoclear: bool,
+}
+
+pub struct LoopDevice {
+    /// The loop device file
+    pub file: File,
+    /// Path to the loop device
+    pub path: PathBuf,
+}
+
 /// Creates a loop device and attach the given file at `path` as the backing store.
 pub fn attach<P: AsRef<Path>>(
     path: P,
     offset: u64,
     size_limit: u64,
-    direct_io: bool,
-    writable: bool,
-) -> Result<PathBuf> {
+    options: &LoopConfigOptions,
+) -> Result<LoopDevice> {
     // Attaching a file to a loop device can make a race condition; a loop device number obtained
     // from LOOP_CTL_GET_FREE might have been used by another thread or process. In that case the
     // subsequent LOOP_CONFIGURE ioctl returns with EBUSY. Try until it succeeds.
@@ -80,8 +97,8 @@
 
     let begin = Instant::now();
     loop {
-        match try_attach(&path, offset, size_limit, direct_io, writable) {
-            Ok(loop_dev) => return Ok(loop_dev),
+        match try_attach(&path, offset, size_limit, options) {
+            Ok(loop_device) => return Ok(loop_device),
             Err(e) => {
                 if begin.elapsed() > TIMEOUT {
                     return Err(e);
@@ -102,9 +119,8 @@
     path: P,
     offset: u64,
     size_limit: u64,
-    direct_io: bool,
-    writable: bool,
-) -> Result<PathBuf> {
+    options: &LoopConfigOptions,
+) -> Result<LoopDevice> {
     // Get a free loop device
     wait_for_path(LOOP_CONTROL)?;
     let ctrl_file = OpenOptions::new()
@@ -117,8 +133,8 @@
     // Construct the loop_info64 struct
     let backing_file = OpenOptions::new()
         .read(true)
-        .write(writable)
-        .custom_flags(if direct_io { O_DIRECT } else { 0 })
+        .write(options.writable)
+        .custom_flags(if options.direct_io { O_DIRECT } else { 0 })
         .open(&path)
         .context(format!("failed to open {:?}", path.as_ref()))?;
     let mut config = loop_config::new_zeroed();
@@ -127,14 +143,18 @@
     config.info.lo_offset = offset;
     config.info.lo_sizelimit = size_limit;
 
-    if !writable {
+    if !options.writable {
         config.info.lo_flags = Flag::LO_FLAGS_READ_ONLY;
     }
 
-    if direct_io {
+    if options.direct_io {
         config.info.lo_flags.insert(Flag::LO_FLAGS_DIRECT_IO);
     }
 
+    if options.autoclear {
+        config.info.lo_flags.insert(Flag::LO_FLAGS_AUTOCLEAR);
+    }
+
     // Configure the loop device to attach the backing file
     let device_path = format!("{}{}", LOOP_DEV_PREFIX, num);
     wait_for_path(&device_path)?;
@@ -146,7 +166,7 @@
     loop_configure(&device_file, &config)
         .context(format!("Failed to configure {:?}", &device_path))?;
 
-    Ok(PathBuf::from(device_path))
+    Ok(LoopDevice { file: device_file, path: PathBuf::from(device_path) })
 }
 
 /// Detaches backing file from the loop device `path`.
@@ -185,7 +205,10 @@
         let a_file = a_dir.path().join("test");
         let a_size = 4096u64;
         create_empty_file(&a_file, a_size);
-        let dev = attach(a_file, 0, a_size, /* direct_io */ true, /* writable */ false).unwrap();
+        let dev =
+            attach(a_file, 0, a_size, &LoopConfigOptions { direct_io: true, ..Default::default() })
+                .unwrap()
+                .path;
         scopeguard::defer! {
             detach(&dev).unwrap();
         }
@@ -198,7 +221,7 @@
         let a_file = a_dir.path().join("test");
         let a_size = 4096u64;
         create_empty_file(&a_file, a_size);
-        let dev = attach(a_file, 0, a_size, /* direct_io */ false, /* writable */ false).unwrap();
+        let dev = attach(a_file, 0, a_size, &LoopConfigOptions::default()).unwrap().path;
         scopeguard::defer! {
             detach(&dev).unwrap();
         }
@@ -211,11 +234,34 @@
         let a_file = a_dir.path().join("test");
         let a_size = 4096u64;
         create_empty_file(&a_file, a_size);
-        let dev = attach(a_file, 0, a_size, /* direct_io */ true, /* writable */ true).unwrap();
+        let dev = attach(
+            a_file,
+            0,
+            a_size,
+            &LoopConfigOptions { direct_io: true, writable: true, ..Default::default() },
+        )
+        .unwrap()
+        .path;
         scopeguard::defer! {
             detach(&dev).unwrap();
         }
         assert!(is_direct_io(&dev));
         assert!(is_direct_io_writable(&dev));
     }
+
+    #[rdroidtest]
+    fn attach_loop_device_autoclear() {
+        let a_dir = tempfile::TempDir::new().unwrap();
+        let a_file = a_dir.path().join("test");
+        let a_size = 4096u64;
+        create_empty_file(&a_file, a_size);
+        let dev =
+            attach(a_file, 0, a_size, &LoopConfigOptions { autoclear: true, ..Default::default() })
+                .unwrap();
+        drop(dev.file);
+
+        let dev_size_path =
+            Path::new("/sys/block").join(dev.path.file_name().unwrap()).join("size");
+        assert_eq!("0", fs::read_to_string(dev_size_path).unwrap().trim());
+    }
 }
diff --git a/libs/devicemapper/src/verity.rs b/libs/devicemapper/src/verity.rs
index 09087da..100320b 100644
--- a/libs/devicemapper/src/verity.rs
+++ b/libs/devicemapper/src/verity.rs
@@ -66,7 +66,7 @@
     }
 }
 
-impl<'a> Default for DmVerityTargetBuilder<'a> {
+impl Default for DmVerityTargetBuilder<'_> {
     fn default() -> Self {
         DmVerityTargetBuilder {
             version: DmVerityVersion::V1,
diff --git a/libs/dice/driver/src/lib.rs b/libs/dice/driver/src/lib.rs
index b5c1f12..245bf11 100644
--- a/libs/dice/driver/src/lib.rs
+++ b/libs/dice/driver/src/lib.rs
@@ -185,7 +185,6 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use core::ffi::CStr;
     use diced_open_dice::{
         hash, retry_bcc_format_config_descriptor, DiceConfigValues, HIDDEN_SIZE,
     };
@@ -233,10 +232,7 @@
 
         let dice = DiceDriver::from_file(&file_path)?;
 
-        let values = DiceConfigValues {
-            component_name: Some(CStr::from_bytes_with_nul(b"test\0")?),
-            ..Default::default()
-        };
+        let values = DiceConfigValues { component_name: Some(c"test"), ..Default::default() };
         let desc = retry_bcc_format_config_descriptor(&values)?;
         let code_hash = hash(&String::from("test code hash").into_bytes())?;
         let authority_hash = hash(&String::from("test authority hash").into_bytes())?;
diff --git a/libs/dice/open_dice/Android.bp b/libs/dice/open_dice/Android.bp
index f799fb1..1870ab6 100644
--- a/libs/dice/open_dice/Android.bp
+++ b/libs/dice/open_dice/Android.bp
@@ -128,7 +128,7 @@
 
 rust_defaults {
     name: "libopen_dice_cbor_bindgen.rust_defaults",
-    wrapper_src: "bindgen/dice.h",
+    wrapper_src: "bindgen/dice/dice.h",
     crate_name: "open_dice_cbor_bindgen",
     source_stem: "bindings",
     bindgen_flags: [
@@ -184,7 +184,7 @@
 
 rust_defaults {
     name: "libopen_dice_android_bindgen.rust_defaults",
-    wrapper_src: "bindgen/android.h",
+    wrapper_src: "bindgen/android/android.h",
     crate_name: "open_dice_android_bindgen",
     source_stem: "bindings",
     bindgen_flags: [
@@ -264,3 +264,9 @@
     clippy_lints: "none",
     lints: "none",
 }
+
+dirgroup {
+    name: "trusty_dirgroup_packages_modules_virtualization_libs_open_dice",
+    visibility: ["//trusty/vendor/google/aosp/scripts"],
+    dirs: ["."],
+}
diff --git a/libs/dice/open_dice/bindgen/android.h b/libs/dice/open_dice/bindgen/android/android.h
similarity index 100%
rename from libs/dice/open_dice/bindgen/android.h
rename to libs/dice/open_dice/bindgen/android/android.h
diff --git a/libs/dice/open_dice/bindgen/android/lib.rs b/libs/dice/open_dice/bindgen/android/lib.rs
new file mode 100644
index 0000000..7c300de
--- /dev/null
+++ b/libs/dice/open_dice/bindgen/android/lib.rs
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 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.
+ */
+
+// Get the bindgen definitions.
+// The trusty build system doesn't have support for packaging generated
+// bindgen sources as a crate automatically. In the Android tree, this
+// entire file is not used.
+
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(unused)]
+
+include!(env!("BINDGEN_INC_FILE"));
diff --git a/libs/dice/open_dice/bindgen/android/rules.mk b/libs/dice/open_dice/bindgen/android/rules.mk
new file mode 100644
index 0000000..200ec52
--- /dev/null
+++ b/libs/dice/open_dice/bindgen/android/rules.mk
@@ -0,0 +1,54 @@
+# Copyright (C) 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := $(LOCAL_DIR)/lib.rs
+
+MODULE_CRATE_NAME := open_dice_android_bindgen
+
+MODULE_LIBRARY_DEPS += \
+	external/open-dice \
+	$(LOCAL_DIR)/../dice \
+	trusty/user/base/lib/trusty-sys \
+
+MODULE_BINDGEN_ALLOW_FUNCTIONS := \
+	DiceAndroidFormatConfigDescriptor \
+	DiceAndroidMainFlow \
+	DiceAndroidHandoverParse \
+
+MODULE_BINDGEN_ALLOW_VARS := \
+	DICE_ANDROID_CONFIG_.* \
+
+# Prevent DiceInputValues from being generated a second time and
+# import it instead from open_dice_cbor_bindgen.
+MODULE_BINDGEN_FLAGS += \
+	--blocklist-type="DiceInputValues_" \
+	--blocklist-type="DiceInputValues" \
+	--raw-line \
+	"pub use open_dice_cbor_bindgen::DiceInputValues;" \
+
+# Prevent DiceResult from being generated a second time and
+# import it instead from open_dice_cbor_bindgen.
+MODULE_BINDGEN_FLAGS += \
+	--blocklist-type="DiceResult" \
+	--raw-line \
+	"pub use open_dice_cbor_bindgen::DiceResult;" \
+
+MODULE_BINDGEN_SRC_HEADER := $(LOCAL_DIR)/android.h
+
+include make/library.mk
diff --git a/libs/dice/open_dice/bindgen/dice.h b/libs/dice/open_dice/bindgen/dice/dice.h
similarity index 100%
rename from libs/dice/open_dice/bindgen/dice.h
rename to libs/dice/open_dice/bindgen/dice/dice.h
diff --git a/libs/dice/open_dice/bindgen/dice/lib.rs b/libs/dice/open_dice/bindgen/dice/lib.rs
new file mode 100644
index 0000000..ed2fd23
--- /dev/null
+++ b/libs/dice/open_dice/bindgen/dice/lib.rs
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+// Get the bindgen definitions.
+// The trusty build system doesn't have support for packaging generated
+// bindgen sources as a crate automatically. In the Android tree, this
+// entire file is not used.
+
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(unused)]
+
+include!(env!("BINDGEN_INC_FILE"));
diff --git a/libs/dice/open_dice/bindgen/dice/rules.mk b/libs/dice/open_dice/bindgen/dice/rules.mk
new file mode 100644
index 0000000..0ea5c7c
--- /dev/null
+++ b/libs/dice/open_dice/bindgen/dice/rules.mk
@@ -0,0 +1,56 @@
+# Copyright (C) 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := $(LOCAL_DIR)/lib.rs
+
+MODULE_CRATE_NAME := open_dice_cbor_bindgen
+
+MODULE_LIBRARY_DEPS += \
+	external/open-dice \
+	trusty/user/base/lib/trusty-sys \
+
+MODULE_BINDGEN_FLAGS += \
+	--rustified-enum DiceConfigType \
+	--rustified-enum DiceMode \
+	--rustified-enum DiceResult \
+	--rustified-enum DicePrincipal \
+
+MODULE_BINDGEN_ALLOW_FUNCTIONS := \
+	DiceDeriveCdiPrivateKeySeed \
+	DiceDeriveCdiCertificateId \
+	DiceMainFlow \
+	DiceHash \
+	DiceKdf \
+	DiceKeypairFromSeed \
+	DiceSign \
+	DiceVerify \
+	DiceGenerateCertificate \
+
+MODULE_BINDGEN_ALLOW_VARS := \
+	DICE_CDI_SIZE \
+	DICE_HASH_SIZE \
+	DICE_HIDDEN_SIZE \
+	DICE_INLINE_CONFIG_SIZE \
+	DICE_PRIVATE_KEY_SEED_SIZE \
+	DICE_ID_SIZE \
+	DICE_PRIVATE_KEY_BUFFER_SIZE \
+
+MODULE_BINDGEN_SRC_HEADER := $(LOCAL_DIR)/dice.h
+
+include make/library.mk
diff --git a/libs/cstr/rules.mk b/libs/dice/open_dice/rules.mk
similarity index 75%
rename from libs/cstr/rules.mk
rename to libs/dice/open_dice/rules.mk
index 2309c30..d84468d 100644
--- a/libs/cstr/rules.mk
+++ b/libs/dice/open_dice/rules.mk
@@ -17,12 +17,14 @@
 
 MODULE := $(LOCAL_DIR)
 
-SRC_DIR := packages/modules/Virtualization/libs/cstr
+MODULE_SRCS := $(LOCAL_DIR)/src/lib.rs
 
-MODULE_SRCS := $(SRC_DIR)/src/lib.rs
+MODULE_CRATE_NAME := diced_open_dice
 
-MODULE_CRATE_NAME := cstr
-
-MODULE_RUST_EDITION := 2021
+MODULE_LIBRARY_DEPS += \
+	$(call FIND_CRATE,coset) \
+	$(call FIND_CRATE,zeroize) \
+	$(LOCAL_DIR)/bindgen/android \
+	$(LOCAL_DIR)/bindgen/dice \
 
 include make/library.mk
diff --git a/libs/dice/open_dice/src/bcc.rs b/libs/dice/open_dice/src/bcc.rs
index fabd7c7..1d9039d 100644
--- a/libs/dice/open_dice/src/bcc.rs
+++ b/libs/dice/open_dice/src/bcc.rs
@@ -41,7 +41,7 @@
 }
 
 /// Formats a configuration descriptor following the Android Profile for DICE specification.
-/// See https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md.
+/// See <https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md>.
 pub fn bcc_format_config_descriptor(values: &DiceConfigValues, buffer: &mut [u8]) -> Result<usize> {
     let mut configs = 0;
 
@@ -172,7 +172,7 @@
     bcc: Option<&'a [u8]>,
 }
 
-impl<'a> DiceArtifacts for BccHandover<'a> {
+impl DiceArtifacts for BccHandover<'_> {
     fn cdi_attest(&self) -> &[u8; CDI_SIZE] {
         self.cdi_attest
     }
diff --git a/libs/dice/open_dice/src/error.rs b/libs/dice/open_dice/src/error.rs
index 9089432..c9eb5cc 100644
--- a/libs/dice/open_dice/src/error.rs
+++ b/libs/dice/open_dice/src/error.rs
@@ -31,6 +31,8 @@
     PlatformError,
     /// Unsupported key algorithm.
     UnsupportedKeyAlgorithm(coset::iana::Algorithm),
+    /// A failed fallible allocation. Used in no_std environments.
+    MemoryAllocationError,
 }
 
 /// This makes `DiceError` accepted by anyhow.
@@ -48,6 +50,7 @@
             Self::UnsupportedKeyAlgorithm(algorithm) => {
                 write!(f, "Unsupported key algorithm: {algorithm:?}")
             }
+            Self::MemoryAllocationError => write!(f, "Memory allocation failed"),
         }
     }
 }
diff --git a/libs/dice/open_dice/src/retry.rs b/libs/dice/open_dice/src/retry.rs
index 6e75e91..803673d 100644
--- a/libs/dice/open_dice/src/retry.rs
+++ b/libs/dice/open_dice/src/retry.rs
@@ -13,9 +13,9 @@
 // limitations under the License.
 
 //! This module implements a retry version for multiple DICE functions that
-//! require preallocated output buffer. As the retry functions require
-//! memory allocation on heap, currently we only expose these functions in
-//! std environment.
+//! require preallocated output buffer. When running without std the allocation
+//! of this buffer may fail and callers will see Error::MemoryAllocationError.
+//! When running with std, allocation may fail.
 
 use crate::bcc::{bcc_format_config_descriptor, bcc_main_flow, DiceConfigValues};
 use crate::dice::{
@@ -62,6 +62,9 @@
     let mut buffer = Vec::new();
     match f(&mut buffer) {
         Err(DiceError::BufferTooSmall(actual_size)) => {
+            #[cfg(not(feature = "std"))]
+            buffer.try_reserve_exact(actual_size).map_err(|_| DiceError::MemoryAllocationError)?;
+
             buffer.resize(actual_size, 0);
             f(&mut buffer)?;
         }
diff --git a/libs/dice/open_dice/tests/api_test.rs b/libs/dice/open_dice/tests/api_test.rs
index a47265b..d3a91ff 100644
--- a/libs/dice/open_dice/tests/api_test.rs
+++ b/libs/dice/open_dice/tests/api_test.rs
@@ -14,94 +14,108 @@
  * limitations under the License.
  */
 
-use diced_open_dice::{
-    derive_cdi_certificate_id, derive_cdi_private_key_seed, hash, kdf, keypair_from_seed, sign,
-    verify, CDI_SIZE, HASH_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
-};
+#[cfg(test)]
+mod tests {
+    use diced_open_dice::{
+        derive_cdi_certificate_id, derive_cdi_private_key_seed, hash, kdf, keypair_from_seed, sign,
+        verify, CDI_SIZE, HASH_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
+    };
 
-#[test]
-fn hash_succeeds() {
-    const EXPECTED_HASH: [u8; HASH_SIZE] = [
-        0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02, 0xf2,
-        0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8, 0x6d, 0x4c,
-        0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda, 0x34, 0x25, 0x5b,
-        0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d, 0xc5, 0x54, 0x2e, 0x93,
-        0xae, 0x9c, 0xd7, 0x6f,
+    // This test initialization is only required for the trusty test harness.
+    #[cfg(feature = "trusty")]
+    test::init!();
+
+    #[test]
+    fn hash_succeeds() {
+        const EXPECTED_HASH: [u8; HASH_SIZE] = [
+            0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
+            0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
+            0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
+            0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
+            0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f,
+        ];
+        assert_eq!(EXPECTED_HASH, hash(b"hello world").expect("hash failed"));
+    }
+
+    #[test]
+    fn kdf_succeeds() {
+        let mut derived_key = [0u8; PRIVATE_KEY_SEED_SIZE];
+        kdf(b"myInitialKeyMaterial", b"mySalt", b"myInfo", &mut derived_key).unwrap();
+        const EXPECTED_DERIVED_KEY: [u8; PRIVATE_KEY_SEED_SIZE] = [
+            0x91, 0x9b, 0x8d, 0x29, 0xc4, 0x1b, 0x93, 0xd7, 0xeb, 0x09, 0xfa, 0xd7, 0xc9, 0x87,
+            0xb0, 0xd1, 0xcc, 0x26, 0xef, 0x07, 0x83, 0x42, 0xcf, 0xa3, 0x45, 0x0a, 0x57, 0xe9,
+            0x19, 0x86, 0xef, 0x48,
+        ];
+        assert_eq!(EXPECTED_DERIVED_KEY, derived_key);
+    }
+
+    #[test]
+    fn derive_cdi_certificate_id_succeeds() {
+        const EXPECTED_ID: [u8; ID_SIZE] = [
+            0x7a, 0x36, 0x45, 0x2c, 0x02, 0xf6, 0x2b, 0xec, 0xf9, 0x80, 0x06, 0x75, 0x87, 0xa5,
+            0xc1, 0x44, 0x0c, 0xd3, 0xc0, 0x6d,
+        ];
+        assert_eq!(EXPECTED_ID, derive_cdi_certificate_id(b"MyPubKey").unwrap());
+    }
+
+    const EXPECTED_SEED: &[u8] = &[
+        0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
+        0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
+        0x3a, 0x08, 0x84, 0x8a, 0x98, 0x85, 0x6d, 0xf5, 0x69, 0x21, 0x03, 0xcd, 0x09, 0xc3, 0x28,
+        0xd6, 0x06, 0xa7, 0x57, 0xbd, 0x48, 0x4b, 0x0f, 0x79, 0x0f, 0xf8, 0x2f, 0xf0, 0x0a, 0x41,
+        0x94, 0xd8, 0x8c, 0xa8,
     ];
-    assert_eq!(EXPECTED_HASH, hash(b"hello world").expect("hash failed"));
-}
 
-#[test]
-fn kdf_succeeds() {
-    let mut derived_key = [0u8; PRIVATE_KEY_SEED_SIZE];
-    kdf(b"myInitialKeyMaterial", b"mySalt", b"myInfo", &mut derived_key).unwrap();
-    const EXPECTED_DERIVED_KEY: [u8; PRIVATE_KEY_SEED_SIZE] = [
-        0x91, 0x9b, 0x8d, 0x29, 0xc4, 0x1b, 0x93, 0xd7, 0xeb, 0x09, 0xfa, 0xd7, 0xc9, 0x87, 0xb0,
-        0xd1, 0xcc, 0x26, 0xef, 0x07, 0x83, 0x42, 0xcf, 0xa3, 0x45, 0x0a, 0x57, 0xe9, 0x19, 0x86,
-        0xef, 0x48,
+    const EXPECTED_CDI_ATTEST: &[u8] = &[
+        0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
+        0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
+        0x3a, 0x08,
     ];
-    assert_eq!(EXPECTED_DERIVED_KEY, derived_key);
-}
 
-#[test]
-fn derive_cdi_certificate_id_succeeds() {
-    const EXPECTED_ID: [u8; ID_SIZE] = [
-        0x7a, 0x36, 0x45, 0x2c, 0x02, 0xf6, 0x2b, 0xec, 0xf9, 0x80, 0x06, 0x75, 0x87, 0xa5, 0xc1,
-        0x44, 0x0c, 0xd3, 0xc0, 0x6d,
+    const EXPECTED_CDI_PRIVATE_KEY_SEED: &[u8] = &[
+        0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe,
+        0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72,
+        0x02, 0x6e,
     ];
-    assert_eq!(EXPECTED_ID, derive_cdi_certificate_id(b"MyPubKey").unwrap());
-}
 
-const EXPECTED_SEED: &[u8] = &[
-    0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba, 0xaa,
-    0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5, 0x3a, 0x08,
-    0x84, 0x8a, 0x98, 0x85, 0x6d, 0xf5, 0x69, 0x21, 0x03, 0xcd, 0x09, 0xc3, 0x28, 0xd6, 0x06, 0xa7,
-    0x57, 0xbd, 0x48, 0x4b, 0x0f, 0x79, 0x0f, 0xf8, 0x2f, 0xf0, 0x0a, 0x41, 0x94, 0xd8, 0x8c, 0xa8,
-];
+    const EXPECTED_PUB_KEY: &[u8] = &[
+        0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23,
+        0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61,
+        0x06, 0x37,
+    ];
+    const EXPECTED_PRIV_KEY: &[u8] = &[
+        0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe,
+        0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72,
+        0x02, 0x6e, 0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b,
+        0xfc, 0x23, 0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52,
+        0xf1, 0x61, 0x06, 0x37,
+    ];
 
-const EXPECTED_CDI_ATTEST: &[u8] = &[
-    0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba, 0xaa,
-    0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5, 0x3a, 0x08,
-];
+    const EXPECTED_SIGNATURE: &[u8] = &[
+        0x44, 0xae, 0xcc, 0xe2, 0xb9, 0x96, 0x18, 0x39, 0x0e, 0x61, 0x0f, 0x53, 0x07, 0xbf, 0xf2,
+        0x32, 0x3d, 0x44, 0xd4, 0xf2, 0x07, 0x23, 0x30, 0x85, 0x32, 0x18, 0xd2, 0x69, 0xb8, 0x29,
+        0x3c, 0x26, 0xe6, 0x0d, 0x9c, 0xa5, 0xc2, 0x73, 0xcd, 0x8c, 0xb8, 0x3c, 0x3e, 0x5b, 0xfd,
+        0x62, 0x8d, 0xf6, 0xc4, 0x27, 0xa6, 0xe9, 0x11, 0x06, 0x5a, 0xb2, 0x2b, 0x64, 0xf7, 0xfc,
+        0xbb, 0xab, 0x4a, 0x0e,
+    ];
 
-const EXPECTED_CDI_PRIVATE_KEY_SEED: &[u8] = &[
-    0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe, 0x0d,
-    0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72, 0x02, 0x6e,
-];
-
-const EXPECTED_PUB_KEY: &[u8] = &[
-    0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23, 0xc9,
-    0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61, 0x06, 0x37,
-];
-const EXPECTED_PRIV_KEY: &[u8] = &[
-    0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe, 0x0d,
-    0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72, 0x02, 0x6e,
-    0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23, 0xc9,
-    0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61, 0x06, 0x37,
-];
-
-const EXPECTED_SIGNATURE: &[u8] = &[
-    0x44, 0xae, 0xcc, 0xe2, 0xb9, 0x96, 0x18, 0x39, 0x0e, 0x61, 0x0f, 0x53, 0x07, 0xbf, 0xf2, 0x32,
-    0x3d, 0x44, 0xd4, 0xf2, 0x07, 0x23, 0x30, 0x85, 0x32, 0x18, 0xd2, 0x69, 0xb8, 0x29, 0x3c, 0x26,
-    0xe6, 0x0d, 0x9c, 0xa5, 0xc2, 0x73, 0xcd, 0x8c, 0xb8, 0x3c, 0x3e, 0x5b, 0xfd, 0x62, 0x8d, 0xf6,
-    0xc4, 0x27, 0xa6, 0xe9, 0x11, 0x06, 0x5a, 0xb2, 0x2b, 0x64, 0xf7, 0xfc, 0xbb, 0xab, 0x4a, 0x0e,
-];
-
-#[test]
-fn hash_derive_sign_verify() {
-    let seed = hash(b"MySeedString").unwrap();
-    assert_eq!(seed, EXPECTED_SEED);
-    let cdi_attest = &seed[..CDI_SIZE];
-    assert_eq!(cdi_attest, EXPECTED_CDI_ATTEST);
-    let cdi_private_key_seed = derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
-    assert_eq!(cdi_private_key_seed.as_array(), EXPECTED_CDI_PRIVATE_KEY_SEED);
-    let (pub_key, priv_key) = keypair_from_seed(cdi_private_key_seed.as_array()).unwrap();
-    assert_eq!(&pub_key, EXPECTED_PUB_KEY);
-    assert_eq!(priv_key.as_array(), EXPECTED_PRIV_KEY);
-    let mut signature = sign(b"MyMessage", priv_key.as_array()).unwrap();
-    assert_eq!(&signature, EXPECTED_SIGNATURE);
-    assert!(verify(b"MyMessage", &signature, &pub_key).is_ok());
-    assert!(verify(b"MyMessage_fail", &signature, &pub_key).is_err());
-    signature[0] += 1;
-    assert!(verify(b"MyMessage", &signature, &pub_key).is_err());
+    #[test]
+    fn hash_derive_sign_verify() {
+        let seed = hash(b"MySeedString").unwrap();
+        assert_eq!(seed, EXPECTED_SEED);
+        let cdi_attest = &seed[..CDI_SIZE];
+        assert_eq!(cdi_attest, EXPECTED_CDI_ATTEST);
+        let cdi_private_key_seed =
+            derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
+        assert_eq!(cdi_private_key_seed.as_array(), EXPECTED_CDI_PRIVATE_KEY_SEED);
+        let (pub_key, priv_key) = keypair_from_seed(cdi_private_key_seed.as_array()).unwrap();
+        assert_eq!(&pub_key, EXPECTED_PUB_KEY);
+        assert_eq!(priv_key.as_array(), EXPECTED_PRIV_KEY);
+        let mut signature = sign(b"MyMessage", priv_key.as_array()).unwrap();
+        assert_eq!(&signature, EXPECTED_SIGNATURE);
+        assert!(verify(b"MyMessage", &signature, &pub_key).is_ok());
+        assert!(verify(b"MyMessage_fail", &signature, &pub_key).is_err());
+        signature[0] += 1;
+        assert!(verify(b"MyMessage", &signature, &pub_key).is_err());
+    }
 }
diff --git a/libs/dice/open_dice/tests/manifest.json b/libs/dice/open_dice/tests/manifest.json
new file mode 100644
index 0000000..28db874
--- /dev/null
+++ b/libs/dice/open_dice/tests/manifest.json
@@ -0,0 +1,9 @@
+{
+    "app_name": "diced_open_dice_tests",
+    "uuid": "0b772481-7c24-4b9b-9d7c-441ac10d969b",
+    "min_heap": 32768,
+    "min_stack": 32768,
+    "mgmt_flags": {
+        "non_critical_app": true
+    }
+}
diff --git a/libs/cstr/rules.mk b/libs/dice/open_dice/tests/rules.mk
similarity index 68%
copy from libs/cstr/rules.mk
copy to libs/dice/open_dice/tests/rules.mk
index 2309c30..a9d332c 100644
--- a/libs/cstr/rules.mk
+++ b/libs/dice/open_dice/tests/rules.mk
@@ -17,12 +17,19 @@
 
 MODULE := $(LOCAL_DIR)
 
-SRC_DIR := packages/modules/Virtualization/libs/cstr
+MODULE_SRCS := $(LOCAL_DIR)/api_test.rs
 
-MODULE_SRCS := $(SRC_DIR)/src/lib.rs
+MODULE_CRATE_NAME := diced_open_dice_tests
 
-MODULE_CRATE_NAME := cstr
+MODULE_LIBRARY_DEPS += \
+	packages/modules/Virtualization/libs/dice/open_dice \
 
-MODULE_RUST_EDITION := 2021
+MODULE_RUST_TESTS := true
+
+# Enables trusty test initialization
+MODULE_RUSTFLAGS += \
+	--cfg 'feature="trusty"' \
+
+MANIFEST := $(LOCAL_DIR)/manifest.json
 
 include make/library.mk
diff --git a/libs/dice/sample_inputs/src/sample_inputs.rs b/libs/dice/sample_inputs/src/sample_inputs.rs
index c323bc4..adca46b 100644
--- a/libs/dice/sample_inputs/src/sample_inputs.rs
+++ b/libs/dice/sample_inputs/src/sample_inputs.rs
@@ -18,7 +18,6 @@
 use alloc::vec;
 use alloc::vec::Vec;
 use ciborium::{de, ser, value::Value};
-use core::ffi::CStr;
 use coset::{iana, Algorithm, AsCborValue, CoseKey, KeyOperation, KeyType, Label};
 use diced_open_dice::{
     derive_cdi_private_key_seed, keypair_from_seed, retry_bcc_format_config_descriptor,
@@ -115,7 +114,7 @@
 
     // Gets the ABL certificate to as the root certificate of DICE chain.
     let config_values = DiceConfigValues {
-        component_name: Some(CStr::from_bytes_with_nul(b"ABL\0").unwrap()),
+        component_name: Some(c"ABL"),
         component_version: Some(1),
         resettable: true,
         security_version: Some(10),
@@ -148,7 +147,7 @@
 
     // Appends AVB certificate to DICE chain.
     let config_values = DiceConfigValues {
-        component_name: Some(CStr::from_bytes_with_nul(b"AVB\0").unwrap()),
+        component_name: Some(c"AVB"),
         component_version: Some(1),
         resettable: true,
         security_version: Some(11),
@@ -173,7 +172,7 @@
 
     // Appends Android certificate to DICE chain.
     let config_values = DiceConfigValues {
-        component_name: Some(CStr::from_bytes_with_nul(b"Android\0").unwrap()),
+        component_name: Some(c"Android"),
         component_version: Some(12),
         resettable: true,
         security_version: Some(12),
diff --git a/libs/libavf/Android.bp b/libs/libavf/Android.bp
index b583e21..c958796 100644
--- a/libs/libavf/Android.bp
+++ b/libs/libavf/Android.bp
@@ -10,7 +10,10 @@
     source_stem: "bindings",
     bindgen_flags: ["--default-enum-style rust"],
     apex_available: ["com.android.virt"],
-    visibility: ["//packages/modules/Virtualization/tests/vts"],
+    visibility: [
+        "//packages/modules/Virtualization/tests/vts",
+        "//packages/modules/Virtualization/tests/old_images_avf_test",
+    ],
 }
 
 rust_defaults {
diff --git a/libs/libfdt/rules.mk b/libs/libfdt/rules.mk
index 2b4e470..ce8aa51 100644
--- a/libs/libfdt/rules.mk
+++ b/libs/libfdt/rules.mk
@@ -27,7 +27,6 @@
 
 MODULE_LIBRARY_DEPS += \
 	external/dtc/libfdt \
-	packages/modules/Virtualization/libs/cstr \
 	packages/modules/Virtualization/libs/libfdt/bindgen \
 	$(call FIND_CRATE,zerocopy) \
 	$(call FIND_CRATE,static_assertions) \
diff --git a/libs/libfdt/src/iterators.rs b/libs/libfdt/src/iterators.rs
index 743c52b..1c66e4d 100644
--- a/libs/libfdt/src/iterators.rs
+++ b/libs/libfdt/src/iterators.rs
@@ -66,7 +66,7 @@
     }
 }
 
-impl<'a> Iterator for CellIterator<'a> {
+impl Iterator for CellIterator<'_> {
     type Item = u32;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -118,7 +118,7 @@
     }
 }
 
-impl<'a> Iterator for RegIterator<'a> {
+impl Iterator for RegIterator<'_> {
     type Item = Reg<u64>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -161,7 +161,7 @@
     }
 }
 
-impl<'a> Iterator for MemRegIterator<'a> {
+impl Iterator for MemRegIterator<'_> {
     type Item = Range<usize>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -215,8 +215,8 @@
     }
 }
 
-impl<'a, A: FromAddrCells, P: FromAddrCells, S: FromSizeCells> Iterator
-    for RangesIterator<'a, A, P, S>
+impl<A: FromAddrCells, P: FromAddrCells, S: FromSizeCells> Iterator
+    for RangesIterator<'_, A, P, S>
 {
     type Item = AddressRange<A, P, S>;
 
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index 0dcd31a..47f4817 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -344,7 +344,7 @@
     }
 }
 
-impl<'a> PartialEq for FdtNode<'a> {
+impl PartialEq for FdtNode<'_> {
     fn eq(&self, other: &Self) -> bool {
         self.fdt.as_ptr() == other.fdt.as_ptr() && self.offset == other.offset
     }
diff --git a/libs/libhypervisor_backends/Android.bp b/libs/libhypervisor_backends/Android.bp
index b001b8f..27e3fe5 100644
--- a/libs/libhypervisor_backends/Android.bp
+++ b/libs/libhypervisor_backends/Android.bp
@@ -14,6 +14,7 @@
     rustlibs: [
         "libonce_cell_nostd",
         "libsmccc",
+        "libthiserror_nostd",
         "libuuid_nostd",
     ],
     enabled: false,
diff --git a/libs/libhypervisor_backends/rules.mk b/libs/libhypervisor_backends/rules.mk
index 6fc9dea..1a48773 100644
--- a/libs/libhypervisor_backends/rules.mk
+++ b/libs/libhypervisor_backends/rules.mk
@@ -8,6 +8,7 @@
 	trusty/user/base/lib/liballoc-rust \
 	$(call FIND_CRATE,once_cell) \
 	$(call FIND_CRATE,smccc) \
+	$(call FIND_CRATE,thiserror) \
 	$(call FIND_CRATE,uuid) \
 
 include make/library.mk
\ No newline at end of file
diff --git a/libs/libhypervisor_backends/src/hypervisor/geniezone.rs b/libs/libhypervisor_backends/src/hypervisor/geniezone.rs
index fe56528..76e010b 100644
--- a/libs/libhypervisor_backends/src/hypervisor/geniezone.rs
+++ b/libs/libhypervisor_backends/src/hypervisor/geniezone.rs
@@ -14,8 +14,6 @@
 
 //! Wrappers around calls to the GenieZone hypervisor.
 
-use core::fmt::{self, Display, Formatter};
-
 use super::{Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor};
 use crate::{mem::page_4kb_of, Error, Result};
 
@@ -23,6 +21,7 @@
     error::{positive_or_error_64, success_or_error_64},
     hvc64,
 };
+use thiserror::Error;
 use uuid::{uuid, Uuid};
 
 pub(super) struct GeniezoneHypervisor;
@@ -44,15 +43,19 @@
 }
 
 /// Error from a GenieZone HVC call.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
 pub enum GeniezoneError {
     /// The call is not supported by the implementation.
+    #[error("GenieZone call not supported")]
     NotSupported,
     /// The call is not required to implement.
+    #[error("GenieZone call not required")]
     NotRequired,
     /// One of the call parameters has a invalid value.
+    #[error("GenieZone call received invalid value")]
     InvalidParameter,
     /// There was an unexpected return value.
+    #[error("Unknown return value from GenieZone {0} ({0:#x})")]
     Unknown(i64),
 }
 
@@ -73,17 +76,6 @@
     }
 }
 
-impl Display for GeniezoneError {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        match self {
-            Self::NotSupported => write!(f, "GenieZone call not supported"),
-            Self::NotRequired => write!(f, "GenieZone call not required"),
-            Self::InvalidParameter => write!(f, "GenieZone call received invalid value"),
-            Self::Unknown(e) => write!(f, "Unknown return value from GenieZone {} ({0:#x})", e),
-        }
-    }
-}
-
 impl Hypervisor for GeniezoneHypervisor {
     fn as_mmio_guard(&self) -> Option<&dyn MmioGuardedHypervisor> {
         Some(self)
diff --git a/libs/libhypervisor_backends/src/hypervisor/kvm.rs b/libs/libhypervisor_backends/src/hypervisor/kvm.rs
index e18c1f4..233097b 100644
--- a/libs/libhypervisor_backends/src/hypervisor/kvm.rs
+++ b/libs/libhypervisor_backends/src/hypervisor/kvm.rs
@@ -14,8 +14,6 @@
 
 //! Wrappers around calls to the KVM hypervisor.
 
-use core::fmt::{self, Display, Formatter};
-
 use super::{DeviceAssigningHypervisor, Hypervisor, MemSharingHypervisor, MmioGuardedHypervisor};
 use crate::{mem::page_4kb_of, Error, Result};
 
@@ -23,16 +21,20 @@
     error::{positive_or_error_64, success_or_error_32, success_or_error_64},
     hvc64,
 };
+use thiserror::Error;
 use uuid::{uuid, Uuid};
 
 /// Error from a KVM HVC call.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, Error, PartialEq)]
 pub enum KvmError {
     /// The call is not supported by the implementation.
+    #[error("KVM call not supported")]
     NotSupported,
     /// One of the call parameters has a non-supported value.
+    #[error("KVM call received non-supported value")]
     InvalidParameter,
     /// There was an unexpected return value.
+    #[error("Unknown return value from KVM {0} ({0:#x})")]
     Unknown(i64),
 }
 
@@ -52,16 +54,6 @@
     }
 }
 
-impl Display for KvmError {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        match self {
-            Self::NotSupported => write!(f, "KVM call not supported"),
-            Self::InvalidParameter => write!(f, "KVM call received non-supported value"),
-            Self::Unknown(e) => write!(f, "Unknown return value from KVM {} ({0:#x})", e),
-        }
-    }
-}
-
 const ARM_SMCCC_KVM_FUNC_HYP_MEMINFO: u32 = 0xc6000002;
 const ARM_SMCCC_KVM_FUNC_MEM_SHARE: u32 = 0xc6000003;
 const ARM_SMCCC_KVM_FUNC_MEM_UNSHARE: u32 = 0xc6000004;
diff --git a/libs/libservice_vm_requests/src/cert.rs b/libs/libservice_vm_requests/src/cert.rs
index e31d870..de5ae1a 100644
--- a/libs/libservice_vm_requests/src/cert.rs
+++ b/libs/libservice_vm_requests/src/cert.rs
@@ -58,7 +58,7 @@
     vm_components: Vec<VmComponent<'a>>,
 }
 
-impl<'a> AssociatedOid for AttestationExtension<'a> {
+impl AssociatedOid for AttestationExtension<'_> {
     const OID: ObjectIdentifier = AVF_ATTESTATION_EXTENSION_V1;
 }
 
diff --git a/libs/libvm_payload/include/vm_payload.h b/libs/libvm_payload/include/vm_payload.h
index 43fba82..e4609fa 100644
--- a/libs/libvm_payload/include/vm_payload.h
+++ b/libs/libvm_payload/include/vm_payload.h
@@ -118,6 +118,11 @@
  * byte sequences and do not need to be kept secret; typically they are
  * hardcoded in the calling code.
  *
+ * The secret is linked to the instance & will be created for a new instance.
+ * Callers should check `AVmPayload_isNewInstance()` to meaningfully use the secret.
+ * For ex, decryption of any old data is meaningless with the returned secret of a new
+ * VM instance with fresh keys.
+ *
  * \param identifier identifier of the secret to return.
  * \param identifier_size size of the secret identifier.
  * \param secret pointer to size bytes where the secret is written.
@@ -304,4 +309,13 @@
 int32_t AVmPayload_readRollbackProtectedSecret(void* _Nullable buf, size_t n) __INTRODUCED_IN(36);
 ;
 
+/**
+ * Checks whether the VM instance is new - i.e., if this is the first run of an instance.
+ * This is an indication of fresh new VM secrets. Payload can use this to setup the fresh
+ * instance if needed.
+ *
+ *  \return true if this is the first run of an instance, false otherwise.
+ */
+bool AVmPayload_isNewInstance() __INTRODUCED_IN(36);
+
 __END_DECLS
diff --git a/libs/libvm_payload/libvm_payload.map.txt b/libs/libvm_payload/libvm_payload.map.txt
index 0c6b56d..ca949d9 100644
--- a/libs/libvm_payload/libvm_payload.map.txt
+++ b/libs/libvm_payload/libvm_payload.map.txt
@@ -17,6 +17,7 @@
     AVmAttestationResult_getCertificateAt; # systemapi introduced=VanillaIceCream
     AVmPayload_writeRollbackProtectedSecret; # systemapi introduced=36
     AVmPayload_readRollbackProtectedSecret; # systemapi introduced=36
+    AVmPayload_isNewInstance;                # systemapi introduced=36
   local:
     *;
 };
diff --git a/libs/libvm_payload/src/lib.rs b/libs/libvm_payload/src/lib.rs
index 29b0cbd..14aff99 100644
--- a/libs/libvm_payload/src/lib.rs
+++ b/libs/libvm_payload/src/lib.rs
@@ -27,7 +27,7 @@
 use rpcbinder::{RpcServer, RpcSession};
 use openssl::{ec::EcKey, sha::sha256, ecdsa::EcdsaSig};
 use std::convert::Infallible;
-use std::ffi::{CString, CStr};
+use std::ffi::CString;
 use std::fmt::Debug;
 use std::os::raw::{c_char, c_void};
 use std::path::Path;
@@ -376,20 +376,16 @@
 #[no_mangle]
 pub extern "C" fn AVmAttestationStatus_toString(status: AVmAttestationStatus) -> *const c_char {
     let message = match status {
-        AVmAttestationStatus::ATTESTATION_OK => {
-            CStr::from_bytes_with_nul(b"The remote attestation completes successfully.\0").unwrap()
-        }
+        AVmAttestationStatus::ATTESTATION_OK => c"The remote attestation completes successfully.",
         AVmAttestationStatus::ATTESTATION_ERROR_INVALID_CHALLENGE => {
-            CStr::from_bytes_with_nul(b"The challenge size is not between 0 and 64.\0").unwrap()
+            c"The challenge size is not between 0 and 64."
         }
         AVmAttestationStatus::ATTESTATION_ERROR_ATTESTATION_FAILED => {
-            CStr::from_bytes_with_nul(b"Failed to attest the VM. Please retry at a later time.\0")
-                .unwrap()
+            c"Failed to attest the VM. Please retry at a later time."
         }
-        AVmAttestationStatus::ATTESTATION_ERROR_UNSUPPORTED => CStr::from_bytes_with_nul(
-            b"Remote attestation is not supported in the current environment.\0",
-        )
-        .unwrap(),
+        AVmAttestationStatus::ATTESTATION_ERROR_UNSUPPORTED => {
+            c"Remote attestation is not supported in the current environment."
+        }
     };
     message.as_ptr()
 }
@@ -652,3 +648,15 @@
         .context("Failed to read rollback protected data")?;
     Ok(rp)
 }
+
+/// Checks whether the VM instance is new - i.e., if this is the first run of an instance.
+///
+/// Panics on error (including unexpected server exit).
+#[no_mangle]
+pub extern "C" fn AVmPayload_isNewInstance() -> bool {
+    unwrap_or_abort(try_is_new_instance())
+}
+
+fn try_is_new_instance() -> Result<bool> {
+    get_vm_payload_service()?.isNewInstance().context("Cannot determine if the instance is new")
+}
diff --git a/libs/libvm_payload/wrapper/attestation.rs b/libs/libvm_payload/wrapper/attestation.rs
index e0055d5..69fef4f 100644
--- a/libs/libvm_payload/wrapper/attestation.rs
+++ b/libs/libvm_payload/wrapper/attestation.rs
@@ -265,7 +265,7 @@
     current: usize, // Invariant: current <= count
 }
 
-impl<'a> Iterator for CertIterator<'a> {
+impl Iterator for CertIterator<'_> {
     type Item = Vec<u8>;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -284,5 +284,5 @@
     }
 }
 
-impl<'a> ExactSizeIterator for CertIterator<'a> {}
-impl<'a> FusedIterator for CertIterator<'a> {}
+impl ExactSizeIterator for CertIterator<'_> {}
+impl FusedIterator for CertIterator<'_> {}
diff --git a/libs/libvm_payload/wrapper/lib.rs b/libs/libvm_payload/wrapper/lib.rs
index 133b14e..bf274b0 100644
--- a/libs/libvm_payload/wrapper/lib.rs
+++ b/libs/libvm_payload/wrapper/lib.rs
@@ -31,7 +31,7 @@
 use std::ptr;
 use vm_payload_bindgen::{
     AIBinder, AVmPayload_getApkContentsPath, AVmPayload_getEncryptedStoragePath,
-    AVmPayload_getVmInstanceSecret, AVmPayload_notifyPayloadReady,
+    AVmPayload_getVmInstanceSecret, AVmPayload_isNewInstance, AVmPayload_notifyPayloadReady,
     AVmPayload_readRollbackProtectedSecret, AVmPayload_runVsockRpcServer,
     AVmPayload_writeRollbackProtectedSecret,
 };
@@ -208,3 +208,11 @@
     // SAFETY: The function only writes to `[data]` within its bounds.
     unsafe { AVmPayload_writeRollbackProtectedSecret(data.as_ptr() as *const c_void, data.len()) }
 }
+
+/// Checks whether the VM instance is new - i.e., if this is the first run of an instance.
+/// This is an indication of fresh new VM secrets. Payload can use this to setup the fresh
+/// instance if needed.
+pub fn is_new_instance_status() -> bool {
+    // SAFETY: The function returns bool, no arguments are needed.
+    unsafe { AVmPayload_isNewInstance() }
+}
diff --git a/libs/libvmbase/Android.bp b/libs/libvmbase/Android.bp
index de347c7..7465508 100644
--- a/libs/libvmbase/Android.bp
+++ b/libs/libvmbase/Android.bp
@@ -87,6 +87,7 @@
         "libsmccc",
         "libspin_nostd",
         "libstatic_assertions",
+        "libthiserror_nostd",
         "libtinyvec_nostd",
         "libuuid_nostd",
         "libvirtio_drivers",
diff --git a/libs/libvmbase/src/bionic.rs b/libs/libvmbase/src/bionic.rs
index 37b6e45..2b59493 100644
--- a/libs/libvmbase/src/bionic.rs
+++ b/libs/libvmbase/src/bionic.rs
@@ -20,7 +20,6 @@
 use core::ffi::c_int;
 use core::ffi::c_void;
 use core::ffi::CStr;
-use core::ptr::addr_of_mut;
 use core::slice;
 use core::str;
 
@@ -71,11 +70,10 @@
 pub static mut ERRNO: c_int = 0;
 
 #[no_mangle]
-#[allow(unused_unsafe)]
+// SAFETY: C functions which call this are only called from the main thread, not from exception
+// handlers.
 unsafe extern "C" fn __errno() -> *mut c_int {
-    // SAFETY: C functions which call this are only called from the main thread, not from exception
-    // handlers.
-    unsafe { addr_of_mut!(ERRNO) as *mut _ }
+    (&raw mut ERRNO).cast()
 }
 
 fn set_errno(value: c_int) {
@@ -88,15 +86,20 @@
     unsafe { ERRNO }
 }
 
+/// # Safety
+///
+/// `buffer` must point to an allocation of at least `length` bytes which is valid to write to and
+/// has no concurrent access while this function is running.
 #[no_mangle]
-extern "C" fn getentropy(buffer: *mut c_void, length: usize) -> c_int {
+unsafe extern "C" fn getentropy(buffer: *mut c_void, length: usize) -> c_int {
     if length > 256 {
         // The maximum permitted value for the length argument is 256.
         set_errno(EIO);
         return -1;
     }
 
-    // SAFETY: Just like libc, we need to assume that `ptr` is valid.
+    // SAFETY: The caller promised that `buffer` is a valid pointer to at least `length` bytes with
+    // no concurrent access.
     let buffer = unsafe { slice::from_raw_parts_mut(buffer.cast::<u8>(), length) };
     fill_with_entropy(buffer).unwrap();
 
@@ -169,9 +172,13 @@
 #[no_mangle]
 static stderr: CFilePtr = CFilePtr::Stderr;
 
+/// # Safety
+///
+/// `c_str` must be a valid pointer to a NUL-terminated string which is not modified before this
+/// function returns.
 #[no_mangle]
-extern "C" fn fputs(c_str: *const c_char, stream: usize) -> c_int {
-    // SAFETY: Just like libc, we need to assume that `s` is a valid NULL-terminated string.
+unsafe extern "C" fn fputs(c_str: *const c_char, stream: usize) -> c_int {
+    // SAFETY: The caller promised that `c_str` is a valid NUL-terminated string.
     let c_str = unsafe { CStr::from_ptr(c_str) };
 
     if let (Ok(s), Ok(f)) = (c_str.to_str(), CFilePtr::try_from(stream)) {
@@ -183,11 +190,16 @@
     }
 }
 
+/// # Safety
+///
+/// `ptr` must be a valid pointer to an array of at least `size * nmemb` initialised bytes, which
+/// are not modified before this function returns.
 #[no_mangle]
-extern "C" fn fwrite(ptr: *const c_void, size: usize, nmemb: usize, stream: usize) -> usize {
+unsafe extern "C" fn fwrite(ptr: *const c_void, size: usize, nmemb: usize, stream: usize) -> usize {
     let length = size.saturating_mul(nmemb);
 
-    // SAFETY: Just like libc, we need to assume that `ptr` is valid.
+    // SAFETY: The caller promised that `ptr` is a valid pointer to at least `size * nmemb`
+    // initialised bytes, and `length` is no more than that.
     let bytes = unsafe { slice::from_raw_parts(ptr as *const u8, length) };
 
     if let (Ok(s), Ok(f)) = (str::from_utf8(bytes), CFilePtr::try_from(stream)) {
@@ -203,12 +215,16 @@
     cstr_error(n).as_ptr().cast_mut().cast()
 }
 
+/// # Safety
+///
+/// `s` must be a valid pointer to a NUL-terminated string which is not modified before this
+/// function returns.
 #[no_mangle]
-extern "C" fn perror(s: *const c_char) {
+unsafe extern "C" fn perror(s: *const c_char) {
     let prefix = if s.is_null() {
         None
     } else {
-        // SAFETY: Just like libc, we need to assume that `s` is a valid NULL-terminated string.
+        // SAFETY: The caller promised that `s` is a valid NUL-terminated string.
         let c_str = unsafe { CStr::from_ptr(s) };
         if c_str.is_empty() {
             None
diff --git a/libs/libvmbase/src/fdt/pci.rs b/libs/libvmbase/src/fdt/pci.rs
index ebaa671..44ad455 100644
--- a/libs/libvmbase/src/fdt/pci.rs
+++ b/libs/libvmbase/src/fdt/pci.rs
@@ -14,40 +14,47 @@
 
 //! Library for working with (VirtIO) PCI devices discovered from a device tree.
 
-use core::{
-    ffi::CStr,
-    fmt::{self, Display, Formatter},
-    ops::Range,
-};
+use core::{ffi::CStr, ops::Range};
 use libfdt::{AddressRange, Fdt, FdtError, FdtNode};
 use log::debug;
+use thiserror::Error;
 use virtio_drivers::transport::pci::bus::{Cam, PciRoot};
 
 /// PCI MMIO configuration region size.
 const PCI_CFG_SIZE: usize = 0x100_0000;
 
 /// An error parsing a PCI node from an FDT.
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, Error, PartialEq)]
 pub enum PciError {
     /// Error getting PCI node from FDT.
+    #[error("Error getting PCI node from FDT: {0}")]
     FdtErrorPci(FdtError),
     /// Failed to find PCI bus in FDT.
+    #[error("Failed to find PCI bus in FDT.")]
     FdtNoPci,
     /// Error getting `reg` property from PCI node.
+    #[error("Error getting reg property from PCI node: {0}")]
     FdtErrorReg(FdtError),
     /// PCI node missing `reg` property.
+    #[error("PCI node missing reg property.")]
     FdtMissingReg,
     /// Empty `reg property on PCI node.
+    #[error("Empty reg property on PCI node.")]
     FdtRegEmpty,
     /// PCI `reg` property missing size.
+    #[error("PCI reg property missing size.")]
     FdtRegMissingSize,
     /// PCI CAM size reported by FDT is not what we expected.
+    #[error("FDT says PCI CAM is {0} bytes but we expected {PCI_CFG_SIZE}.")]
     CamWrongSize(usize),
     /// Error getting `ranges` property from PCI node.
+    #[error("Error getting ranges property from PCI node: {0}")]
     FdtErrorRanges(FdtError),
     /// PCI node missing `ranges` property.
+    #[error("PCI node missing ranges property.")]
     FdtMissingRanges,
     /// Bus address is not equal to CPU physical address in `ranges` property.
+    #[error("bus address {bus_address:#018x} != CPU physical address {cpu_physical:#018x}")]
     RangeAddressMismatch {
         /// A bus address from the `ranges` property.
         bus_address: u64,
@@ -55,39 +62,10 @@
         cpu_physical: u64,
     },
     /// No suitable PCI memory range found.
+    #[error("No suitable PCI memory range found.")]
     NoSuitableRange,
 }
 
-impl Display for PciError {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        match self {
-            Self::FdtErrorPci(e) => write!(f, "Error getting PCI node from FDT: {}", e),
-            Self::FdtNoPci => write!(f, "Failed to find PCI bus in FDT."),
-            Self::FdtErrorReg(e) => write!(f, "Error getting reg property from PCI node: {}", e),
-            Self::FdtMissingReg => write!(f, "PCI node missing reg property."),
-            Self::FdtRegEmpty => write!(f, "Empty reg property on PCI node."),
-            Self::FdtRegMissingSize => write!(f, "PCI reg property missing size."),
-            Self::CamWrongSize(cam_size) => write!(
-                f,
-                "FDT says PCI CAM is {} bytes but we expected {}.",
-                cam_size, PCI_CFG_SIZE
-            ),
-            Self::FdtErrorRanges(e) => {
-                write!(f, "Error getting ranges property from PCI node: {}", e)
-            }
-            Self::FdtMissingRanges => write!(f, "PCI node missing ranges property."),
-            Self::RangeAddressMismatch { bus_address, cpu_physical } => {
-                write!(
-                    f,
-                    "bus address {:#018x} != CPU physical address {:#018x}",
-                    bus_address, cpu_physical
-                )
-            }
-            Self::NoSuitableRange => write!(f, "No suitable PCI memory range found."),
-        }
-    }
-}
-
 /// Information about the PCI bus parsed from the device tree.
 #[derive(Clone, Debug)]
 pub struct PciInfo {
diff --git a/libs/libvmbase/src/layout.rs b/libs/libvmbase/src/layout.rs
index cf3a8fc..4c45eb2 100644
--- a/libs/libvmbase/src/layout.rs
+++ b/libs/libvmbase/src/layout.rs
@@ -22,7 +22,6 @@
 use crate::memory::{max_stack_size, page_4kb_of, PAGE_SIZE};
 use aarch64_paging::paging::VirtualAddress;
 use core::ops::Range;
-use core::ptr::addr_of;
 use static_assertions::const_assert_eq;
 
 /// First address that can't be translated by a level 1 TTBR0_EL1.
@@ -44,9 +43,7 @@
 #[macro_export]
 macro_rules! linker_addr {
     ($symbol:ident) => {{
-        // SAFETY: We're just getting the address of an extern static symbol provided by the linker,
-        // not dereferencing it.
-        let addr = unsafe { addr_of!($crate::linker::$symbol) as usize };
+        let addr = (&raw const $crate::linker::$symbol) as usize;
         VirtualAddress(addr)
     }};
 }
@@ -132,5 +129,5 @@
     // SAFETY: __stack_chk_guard shouldn't have any mutable aliases unless the stack overflows. If
     // it does, then there could be undefined behaviour all over the program, but we want to at
     // least have a chance at catching it.
-    unsafe { addr_of!(__stack_chk_guard).read_volatile() }
+    unsafe { (&raw const __stack_chk_guard).read_volatile() }
 }
diff --git a/libs/statslog_virtualization/Android.bp b/libs/statslog_virtualization/Android.bp
index 2860e6c..f33a147 100644
--- a/libs/statslog_virtualization/Android.bp
+++ b/libs/statslog_virtualization/Android.bp
@@ -72,4 +72,7 @@
     rustlibs: [
         "libstatslog_virtualization_rust_header",
     ],
+    flags: [
+        "-A clippy::needless-lifetimes",
+    ],
 }
diff --git a/tests/aidl/Android.bp b/tests/aidl/Android.bp
index ed4e8ff..63db488 100644
--- a/tests/aidl/Android.bp
+++ b/tests/aidl/Android.bp
@@ -17,5 +17,8 @@
         cpp: {
             enabled: true,
         },
+        ndk: {
+            min_sdk_version: "UpsideDownCake",
+        },
     },
 }
diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
index 73e5c5c..6a413d6 100644
--- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
@@ -97,4 +97,11 @@
      * requests in flight to fail.
      */
     oneway void quit();
+
+    /**
+     * Checks whether the VM instance is new - i.e., if this is the first run of an instance.
+     *
+     * @return true on the first boot of the instance & false on subsequent boot.
+     */
+    boolean isNewInstance();
 }
diff --git a/tests/backcompat_test/src/main.rs b/tests/backcompat_test/src/main.rs
index 4113881..bf0afa6 100644
--- a/tests/backcompat_test/src/main.rs
+++ b/tests/backcompat_test/src/main.rs
@@ -152,6 +152,11 @@
         .arg("/chosen/kaslr-seed")
         .arg("--ignore-path-value")
         .arg("/chosen/rng-seed")
+        // TODO: b/391420337 Investigate if bootargs may mutate VM
+        .arg("--ignore-path-value")
+        .arg("/chosen/bootargs")
+        .arg("--ignore-path-value")
+        .arg("/config/kernel-size")
         .arg("--ignore-path-value")
         .arg("/avf/untrusted/instance-id")
         .arg("--ignore-path-value")
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index 538d14f..94f7ced 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -625,6 +625,7 @@
         public byte[] mInstanceSecret;
         public int mPageSize;
         public byte[] mPayloadRpData;
+        public boolean mIsNewInstance;
 
         public void assertNoException() {
             if (mException != null) {
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 4f9806a..e8673ce 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -101,6 +101,9 @@
     private static final String INSTANCE_IMG = TEST_ROOT + "instance.img";
     private static final String INSTANCE_ID_FILE = TEST_ROOT + "instance_id";
 
+    private static final String DEBUG_LEVEL_FULL = "full --enable-earlycon";
+    private static final String DEBUG_LEVEL_NONE = "none";
+
     private static final int MIN_MEM_ARM64 = 170;
     private static final int MIN_MEM_X86_64 = 196;
 
@@ -465,7 +468,7 @@
         try {
             microdroid =
                     MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                            .debugLevel("full")
+                            .debugLevel(DEBUG_LEVEL_FULL)
                             .memoryMib(minMemorySize())
                             .cpuTopology("match_host")
                             .protectedVm(true)
@@ -495,7 +498,7 @@
         // Act
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(true)
@@ -644,7 +647,7 @@
 
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
@@ -751,7 +754,7 @@
                                 VIRT_APEX + "bin/vm",
                                 "run-app",
                                 "--debug",
-                                debuggable ? "full" : "none",
+                                debuggable ? DEBUG_LEVEL_FULL : DEBUG_LEVEL_NONE,
                                 apkPath,
                                 idsigPath,
                                 instanceImgPath));
@@ -871,7 +874,7 @@
         final String configPath = "assets/vm_config_apex.json"; // path inside the APK
         ITestDevice microdroid =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
@@ -1023,7 +1026,7 @@
         final String configPath = "assets/vm_config.json"; // path inside the APK
         testMicrodroidBootsWithBuilder(
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
@@ -1061,7 +1064,7 @@
         final String configPath = "assets/vm_config.json";
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
@@ -1175,7 +1178,7 @@
                                 "shell",
                                 VIRT_APEX + "bin/vm",
                                 "run-app",
-                                "--debug full",
+                                "--debug " + DEBUG_LEVEL_FULL,
                                 "--console " + CONSOLE_PATH,
                                 "--payload-binary-name",
                                 "MicrodroidEmptyPayloadJniLib.so",
@@ -1357,7 +1360,7 @@
 
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
@@ -1403,7 +1406,7 @@
         final String configPath = "assets/vm_config.json";
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(minMemorySize())
                         .cpuTopology("match_host")
                         .protectedVm(protectedVm)
@@ -1434,7 +1437,7 @@
         // Start the VM with the dump DT option.
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(mem_size)
                         .cpuTopology("one_cpu")
                         .protectedVm(false)
@@ -1464,7 +1467,7 @@
         // Start the VM with the dump DT option.
         mMicrodroidDevice =
                 MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
-                        .debugLevel("full")
+                        .debugLevel(DEBUG_LEVEL_FULL)
                         .memoryMib(mem_size)
                         .cpuTopology("one_cpu")
                         .protectedVm(true)
diff --git a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts
index 095eb54..de9f7c5 100644
--- a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts
+++ b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_golden.dts
@@ -49,7 +49,7 @@
         };
 
         chosen {
-                bootargs = "panic=-1 crashkernel=17M";
+                bootargs = "panic=-1 crashkernel=17M earlycon=uart8250,mmio,0x3f8 keep_bootcon";
                 kaslr-seed = <>;
                 linux,initrd-end = <0x81200360>;
                 linux,initrd-start = <0x81000000>;
diff --git a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts
index f2ebdf9..f09e4ff 100644
--- a/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts
+++ b/tests/hostside/java/com/android/microdroid/test/goldens/dt_dump_protected_golden.dts
@@ -49,7 +49,7 @@
         };
 
         chosen {
-                bootargs = "panic=-1 crashkernel=31M";
+                bootargs = "panic=-1 crashkernel=31M earlycon=uart8250,mmio,0x3f8 keep_bootcon";
                 kaslr-seed = <>;
                 linux,initrd-end = <0x81202104>;
                 linux,initrd-start = <0x81000000>;
diff --git a/tests/old_images_avf_test/Android.bp b/tests/old_images_avf_test/Android.bp
new file mode 100644
index 0000000..b3d5baf
--- /dev/null
+++ b/tests/old_images_avf_test/Android.bp
@@ -0,0 +1,57 @@
+prebuilt_etc {
+    name: "backcompat_rialto_kernel",
+    filename: "rialto.bin",
+    src: ":empty_file",
+    target: {
+        android_arm64: {
+            src: ":rialto_signed",
+        },
+    },
+    installable: false,
+    visibility: ["//visibility:private"],
+}
+
+prebuilt_etc {
+    name: "android16_rialto_kernel",
+    filename: "android16_rialto.bin",
+    src: ":empty_file",
+    target: {
+        android_arm64: {
+            src: "images/android16_rialto.bin",
+        },
+    },
+    installable: false,
+    visibility: ["//visibility:private"],
+}
+
+rust_test {
+    name: "old_images_avf_test",
+    crate_name: "old_images_avf_test",
+    srcs: ["src/main.rs"],
+    rustlibs: [
+        "libanyhow",
+        "libavf_bindgen",
+        "libciborium",
+        "liblog_rust",
+        "libhypervisor_props",
+        "libscopeguard",
+        "libservice_vm_comm",
+        "libvsock",
+    ],
+    shared_libs: ["libavf"],
+    test_suites: [
+        "general-tests",
+    ],
+    data: [
+        ":android16_rialto_kernel",
+        ":backcompat_rialto_kernel",
+    ],
+    enabled: false,
+    target: {
+        android_arm64: {
+            enabled: true,
+        },
+    },
+    test_config: "AndroidTest.xml",
+    compile_multilib: "first",
+}
diff --git a/tests/old_images_avf_test/AndroidTest.xml b/tests/old_images_avf_test/AndroidTest.xml
new file mode 100644
index 0000000..089a424
--- /dev/null
+++ b/tests/old_images_avf_test/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2025 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.
+-->
+<configuration description="Runs old images on current AVF VM.">
+    <option name="test-suite-tag" value="general-tests" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="old_images_avf_test->/data/local/tmp/old_images_avf_test" />
+        <option name="push" value="rialto.bin->/data/local/tmp/rialto.bin" />
+        <option name="push" value="android16_rialto.bin->/data/local/tmp/android16_rialto.bin" />
+    </target_preparer>
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.ArchModuleController">
+        <option name="arch" value="arm64" />
+    </object>
+    <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+        <option name="test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="old_images_avf_test" />
+        <!-- rialto uses a fixed port number for the host, can't run two tests at the same time -->
+        <option name="native-test-flag" value="--test-threads=1" />
+    </test>
+</configuration>
diff --git a/tests/old_images_avf_test/images/android16_rialto.bin b/tests/old_images_avf_test/images/android16_rialto.bin
new file mode 100644
index 0000000..ff4c38e
--- /dev/null
+++ b/tests/old_images_avf_test/images/android16_rialto.bin
Binary files differ
diff --git a/tests/old_images_avf_test/src/main.rs b/tests/old_images_avf_test/src/main.rs
new file mode 100644
index 0000000..018a80e
--- /dev/null
+++ b/tests/old_images_avf_test/src/main.rs
@@ -0,0 +1,229 @@
+// Copyright 2025 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.
+
+//! Tests running a VM with older images
+
+use anyhow::{bail, ensure, Context, Result};
+use log::info;
+use std::ffi::CStr;
+use std::fs::File;
+use std::io::{self, BufWriter, Write};
+use std::os::fd::IntoRawFd;
+use std::time::{Duration, Instant};
+use vsock::{VsockListener, VsockStream, VMADDR_CID_HOST};
+
+use avf_bindgen::*;
+use service_vm_comm::{Request, Response, ServiceVmRequest, VmType};
+
+const VM_MEMORY_MB: i32 = 16;
+const WRITE_BUFFER_CAPACITY: usize = 512;
+
+const LISTEN_TIMEOUT: Duration = Duration::from_secs(10);
+const READ_TIMEOUT: Duration = Duration::from_secs(10);
+const WRITE_TIMEOUT: Duration = Duration::from_secs(10);
+const STOP_TIMEOUT: timespec = timespec { tv_sec: 10, tv_nsec: 0 };
+
+/// Processes the request in the service VM.
+fn process_request(vsock_stream: &mut VsockStream, request: Request) -> Result<Response> {
+    write_request(vsock_stream, &ServiceVmRequest::Process(request))?;
+    read_response(vsock_stream)
+}
+
+/// Sends the request to the service VM.
+fn write_request(vsock_stream: &mut VsockStream, request: &ServiceVmRequest) -> Result<()> {
+    let mut buffer = BufWriter::with_capacity(WRITE_BUFFER_CAPACITY, vsock_stream);
+    ciborium::into_writer(request, &mut buffer)?;
+    buffer.flush().context("Failed to flush the buffer")?;
+    Ok(())
+}
+
+/// Reads the response from the service VM.
+fn read_response(vsock_stream: &mut VsockStream) -> Result<Response> {
+    let response: Response = ciborium::from_reader(vsock_stream)
+        .context("Failed to read the response from the service VM")?;
+    Ok(response)
+}
+
+fn listen_from_guest(port: u32) -> Result<VsockStream> {
+    let vsock_listener =
+        VsockListener::bind_with_cid_port(VMADDR_CID_HOST, port).context("Failed to bind vsock")?;
+    vsock_listener.set_nonblocking(true).context("Failed to set nonblocking")?;
+    let start_time = Instant::now();
+    loop {
+        if start_time.elapsed() >= LISTEN_TIMEOUT {
+            bail!("Timeout while listening");
+        }
+        match vsock_listener.accept() {
+            Ok((vsock_stream, _peer_addr)) => return Ok(vsock_stream),
+            Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
+                std::thread::sleep(Duration::from_millis(100));
+            }
+            Err(e) => bail!("Failed to listen: {e:?}"),
+        }
+    }
+}
+
+fn run_vm(image_path: &str, test_name: &CStr, protected_vm: bool) -> Result<()> {
+    let kernel_file = File::open(image_path).context("Failed to open kernel file")?;
+    let kernel_fd = kernel_file.into_raw_fd();
+
+    // SAFETY: AVirtualMachineRawConfig_create() isn't unsafe but rust_bindgen forces it to be seen
+    // as unsafe
+    let config = unsafe { AVirtualMachineRawConfig_create() };
+
+    info!("raw config created");
+
+    // SAFETY: config is the only reference to a valid object
+    unsafe {
+        AVirtualMachineRawConfig_setName(config, test_name.as_ptr());
+        AVirtualMachineRawConfig_setKernel(config, kernel_fd);
+        AVirtualMachineRawConfig_setProtectedVm(config, protected_vm);
+        AVirtualMachineRawConfig_setMemoryMiB(config, VM_MEMORY_MB);
+    }
+
+    let mut vm = std::ptr::null_mut();
+    let mut service = std::ptr::null_mut();
+
+    ensure!(
+        // SAFETY: &mut service is a valid pointer to *AVirtualizationService
+        unsafe { AVirtualizationService_create(&mut service, false) } == 0,
+        "AVirtualizationService_create failed"
+    );
+
+    scopeguard::defer! {
+        // SAFETY: service is a valid pointer to AVirtualizationService
+        unsafe { AVirtualizationService_destroy(service); }
+    }
+
+    ensure!(
+        // SAFETY: &mut vm is a valid pointer to *AVirtualMachine
+        unsafe {
+            AVirtualMachine_createRaw(
+                service, config, -1, // console_in
+                -1, // console_out
+                -1, // log
+                &mut vm,
+            )
+        } == 0,
+        "AVirtualMachine_createRaw failed"
+    );
+
+    scopeguard::defer! {
+        // SAFETY: vm is a valid pointer to AVirtualMachine
+        unsafe { AVirtualMachine_destroy(vm); }
+    }
+
+    info!("vm created");
+
+    let vm_type = if protected_vm { VmType::ProtectedVm } else { VmType::NonProtectedVm };
+
+    let listener_thread = std::thread::spawn(move || listen_from_guest(vm_type.port()));
+
+    // SAFETY: vm is the only reference to a valid object
+    unsafe {
+        AVirtualMachine_start(vm);
+    }
+
+    info!("VM started");
+
+    let mut vsock_stream = listener_thread.join().unwrap()?;
+    vsock_stream.set_read_timeout(Some(READ_TIMEOUT))?;
+    vsock_stream.set_write_timeout(Some(WRITE_TIMEOUT))?;
+
+    info!("client connected");
+
+    let request_data = vec![1, 2, 3, 4, 5];
+    let expected_data = vec![5, 4, 3, 2, 1];
+    let response = process_request(&mut vsock_stream, Request::Reverse(request_data))
+        .context("Failed to process request")?;
+    let Response::Reverse(reversed_data) = response else {
+        bail!("Expected Response::Reverse but was {response:?}");
+    };
+    ensure!(reversed_data == expected_data, "Expected {expected_data:?} but was {reversed_data:?}");
+
+    info!("request processed");
+
+    write_request(&mut vsock_stream, &ServiceVmRequest::Shutdown)
+        .context("Failed to send shutdown")?;
+
+    info!("shutdown sent");
+
+    let mut stop_reason = AVirtualMachineStopReason::AVIRTUAL_MACHINE_UNRECOGNISED;
+    ensure!(
+        // SAFETY: vm is the only reference to a valid object
+        unsafe { AVirtualMachine_waitForStop(vm, &STOP_TIMEOUT, &mut stop_reason) },
+        "AVirtualMachine_waitForStop failed"
+    );
+    assert_eq!(stop_reason, AVirtualMachineStopReason::AVIRTUAL_MACHINE_SHUTDOWN);
+
+    info!("stopped");
+
+    Ok(())
+}
+
+#[test]
+fn test_run_rialto_protected() -> Result<()> {
+    if hypervisor_props::is_protected_vm_supported()? {
+        run_vm(
+            "/data/local/tmp/rialto.bin", /* image_path */
+            c"test_rialto",               /* test_name */
+            true,                         /* protected_vm */
+        )
+    } else {
+        info!("pVMs are not supported on device. skipping test");
+        Ok(())
+    }
+}
+
+#[test]
+fn test_run_rialto_non_protected() -> Result<()> {
+    if hypervisor_props::is_vm_supported()? {
+        run_vm(
+            "/data/local/tmp/rialto.bin", /* image_path */
+            c"test_rialto",               /* test_name */
+            false,                        /* protected_vm */
+        )
+    } else {
+        info!("VMs are not supported on device. skipping test");
+        Ok(())
+    }
+}
+
+#[test]
+fn test_run_android16_rialto_protected() -> Result<()> {
+    if hypervisor_props::is_protected_vm_supported()? {
+        run_vm(
+            "/data/local/tmp/android16_rialto.bin", /* image_path */
+            c"android16_test_rialto",               /* test_name */
+            true,                                   /* protected_vm */
+        )
+    } else {
+        info!("pVMs are not supported on device. skipping test");
+        Ok(())
+    }
+}
+
+#[test]
+fn test_run_android16_rialto_non_protected() -> Result<()> {
+    if hypervisor_props::is_vm_supported()? {
+        run_vm(
+            "/data/local/tmp/android16_rialto.bin", /* image_path */
+            c"android16_test_rialto",               /* test_name */
+            false,                                  /* protected_vm */
+        )
+    } else {
+        info!("VMs are not supported on device. skipping test");
+        Ok(())
+    }
+}
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index d0e045b..99300e2 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -173,6 +173,8 @@
         "liblog",
         "libprotobuf-cpp-lite-ndk",
     ],
+    // We've added support for updatable payloads in Android U.
+    min_sdk_version: "UpsideDownCake",
 }
 
 cc_library_shared {
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 193e9d3..3ece140 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -32,7 +32,6 @@
 import static com.google.common.truth.TruthJUnit.assume;
 
 import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
@@ -1868,22 +1867,14 @@
         return false;
     }
 
-    private void ensureUpdatableVmSupported() throws Exception {
-        if (getVendorApiLevel() >= 202504 && deviceCapableOfProtectedVm()) {
-            assertTrue(
-                    "Missing Updatable VM support, have you declared Secretkeeper interface?",
-                    isUpdatableVmSupported());
-        } else {
-            assumeTrue("Device does not support Updatable VM", isUpdatableVmSupported());
-        }
-    }
-
     @Test
+    @CddTest
     public void rollbackProtectedDataOfPayload() throws Exception {
         assumeSupportedDevice();
         // Rollback protected data is only possible if Updatable VMs is supported -
         // which implies Secretkeeper support.
-        ensureUpdatableVmSupported();
+        assumeTrue("Missing Updatable VM support", isUpdatableVmSupported());
+
         byte[] value1 = new byte[32];
         Arrays.fill(value1, (byte) 0xcc);
         byte[] value2 = new byte[32];
@@ -1996,6 +1987,49 @@
 
     @Test
     @CddTest
+    public void isNewInstanceTest() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setMemoryBytes(minMemoryRequired())
+                        .setDebugLevel(DEBUG_LEVEL_FULL)
+                        .build();
+        // TODO(b/325094712): Cuttlefish doesn't support device tree overlays which is required to
+        // find if the VM run is a new instance.
+        assumeFalse(
+                "Cuttlefish/Goldfish doesn't support device tree under /proc/device-tree",
+                isCuttlefish() || isGoldfish());
+        if (!isUpdatableVmSupported()) {
+            // TODO(b/389611249): Non protected VMs using legacy secret mechanisms do not reliably
+            // implement `AVmPayload_isNewInstance`.
+            assumeProtectedVM();
+        }
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_vm_a", config);
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mIsNewInstance = ts.isNewInstance();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mIsNewInstance).isTrue();
+
+        // Re-run the same VM & ensure isNewInstance is false.
+        testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mIsNewInstance = ts.isNewInstance();
+                        });
+        testResults.assertNoException();
+        assertThat(testResults.mIsNewInstance).isFalse();
+    }
+
+    @Test
+    @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
     public void canReadFileFromAssets_debugFull() throws Exception {
         assumeSupportedDevice();
 
@@ -2485,25 +2519,7 @@
     }
 
     @Test
-    public void kernelVersionRequirement() throws Exception {
-        assumeVsrCompliant();
-        int firstApiLevel = SystemProperties.getInt("ro.product.first_api_level", 0);
-        assume().withMessage("Skip on devices launched before Android 14 (API level 34)")
-                .that(firstApiLevel)
-                .isAtLeast(34);
-
-        String[] tokens = KERNEL_VERSION.split("\\.");
-        int major = Integer.parseInt(tokens[0]);
-        int minor = Integer.parseInt(tokens[1]);
-
-        // Check kernel version >= 5.15
-        assertTrue(major >= 5);
-        if (major == 5) {
-            assertTrue(minor >= 15);
-        }
-    }
-
-    @Test
+    @CddTest
     public void createAndRunRustVm() throws Exception {
         // This test is here mostly to exercise the Rust wrapper around the VM Payload API.
         // We're testing the same functionality as in other tests, the only difference is
@@ -2707,6 +2723,7 @@
     }
 
     @Test
+    @GmsTest(requirements = {"GMS-3-7.1-001.002"})
     public void pageSize() throws Exception {
         assumeSupportedDevice();
 
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 83b6d23..2ab73a4 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -348,20 +348,40 @@
         }
 
         ScopedAStatus insecurelyReadPayloadRpData(std::array<uint8_t, 32>* out) override {
-            int32_t ret = AVmPayload_readRollbackProtectedSecret(out->data(), 32);
-            if (ret != 32) {
-                return ScopedAStatus::fromServiceSpecificError(ret);
+            if (__builtin_available(android 36, *)) {
+                int32_t ret = AVmPayload_readRollbackProtectedSecret(out->data(), 32);
+                if (ret != 32) {
+                    return ScopedAStatus::fromServiceSpecificError(ret);
+                }
+                return ScopedAStatus::ok();
+            } else {
+                return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+                                                                   "not available before SDK 36");
             }
-            return ScopedAStatus::ok();
         }
 
         ScopedAStatus insecurelyWritePayloadRpData(
                 const std::array<uint8_t, 32>& inputData) override {
-            int32_t ret = AVmPayload_writeRollbackProtectedSecret(inputData.data(), 32);
-            if (ret != 32) {
-                return ScopedAStatus::fromServiceSpecificError(ret);
+            if (__builtin_available(android 36, *)) {
+                int32_t ret = AVmPayload_writeRollbackProtectedSecret(inputData.data(), 32);
+                if (ret != 32) {
+                    return ScopedAStatus::fromServiceSpecificError(ret);
+                }
+                return ScopedAStatus::ok();
+            } else {
+                return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+                                                                   "not available before SDK 36");
             }
-            return ScopedAStatus::ok();
+        }
+
+        ScopedAStatus isNewInstance(bool* is_new_instance_out) override {
+            if (__builtin_available(android 36, *)) {
+                *is_new_instance_out = AVmPayload_isNewInstance();
+                return ScopedAStatus::ok();
+            } else {
+                return ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+                                                                   "not available before SDK 36");
+            }
         }
 
         ScopedAStatus quit() override { exit(0); }
diff --git a/tests/testapk/src/native/testbinary.rs b/tests/testapk/src/native/testbinary.rs
index dee3b8e..c9d46b8 100644
--- a/tests/testapk/src/native/testbinary.rs
+++ b/tests/testapk/src/native/testbinary.rs
@@ -132,6 +132,9 @@
     fn insecurelyWritePayloadRpData(&self, _: &[u8; 32]) -> BinderResult<()> {
         unimplemented()
     }
+    fn isNewInstance(&self) -> BinderResult<bool> {
+        unimplemented()
+    }
 }
 
 fn unimplemented<T>() -> BinderResult<T> {
diff --git a/tests/vmshareapp/Android.bp b/tests/vmshareapp/Android.bp
index 5f6dc57..86c48f6 100644
--- a/tests/vmshareapp/Android.bp
+++ b/tests/vmshareapp/Android.bp
@@ -13,4 +13,8 @@
         "MicrodroidPayloadInOtherAppNativeLib",
     ],
     min_sdk_version: "34",
+    sdk_version: "system_current",
+    // Ideally we should set something "latest finalized sdk version" here.
+    // However, soong doesn't seem to provide such functionality.
+    target_sdk_version: "VanillaIceCream",
 }
diff --git a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
index 4465c5e..1f71888 100644
--- a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
+++ b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
@@ -286,5 +286,10 @@
         public void insecurelyWritePayloadRpData(byte[] data) {
             throw new UnsupportedOperationException("Not supported");
         }
+
+        @Override
+        public boolean isNewInstance() {
+            throw new UnsupportedOperationException("Not supported");
+        }
     }
 }
diff --git a/tests/vts/Android.bp b/tests/vts/Android.bp
index c8e2523..c570873 100644
--- a/tests/vts/Android.bp
+++ b/tests/vts/Android.bp
@@ -33,4 +33,5 @@
     data: [":vts_libavf_test_kernel"],
     test_config: "AndroidTest.xml",
     compile_multilib: "first",
+    vendor: true,
 }
diff --git a/tests/vts/AndroidTest.xml b/tests/vts/AndroidTest.xml
index 75c8d31..6926f9f 100644
--- a/tests/vts/AndroidTest.xml
+++ b/tests/vts/AndroidTest.xml
@@ -20,7 +20,7 @@
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push" value="vts_libavf_test->/data/local/tmp/vts_libavf_test" />
+        <option name="push" value="vts_libavf_test->/data/nativetest64/vendor/vts_libavf_test" />
         <option name="push" value="rialto.bin->/data/local/tmp/rialto.bin" />
     </target_preparer>
 
@@ -29,7 +29,7 @@
     </object>
 
     <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
-        <option name="test-device-path" value="/data/local/tmp" />
+        <option name="test-device-path" value="/data/nativetest64/vendor" />
         <option name="module-name" value="vts_libavf_test" />
         <!-- rialto uses a fixed port number for the host, can't run two tests at the same time -->
         <option name="native-test-flag" value="--test-threads=1" />
diff --git a/tests/vts/src/vts_libavf_test.rs b/tests/vts/src/vts_libavf_test.rs
index e30c175..dc37aad 100644
--- a/tests/vts/src/vts_libavf_test.rs
+++ b/tests/vts/src/vts_libavf_test.rs
@@ -16,7 +16,6 @@
 
 use anyhow::{bail, ensure, Context, Result};
 use log::info;
-use std::ffi::CStr;
 use std::fs::File;
 use std::io::{self, BufWriter, Write};
 use std::os::fd::IntoRawFd;
@@ -87,10 +86,7 @@
 
     // SAFETY: config is the only reference to a valid object
     unsafe {
-        AVirtualMachineRawConfig_setName(
-            config,
-            CStr::from_bytes_with_nul(b"vts_libavf_test_rialto\0").unwrap().as_ptr(),
-        );
+        AVirtualMachineRawConfig_setName(config, c"vts_libavf_test_rialto".as_ptr());
         AVirtualMachineRawConfig_setKernel(config, kernel_fd);
         AVirtualMachineRawConfig_setProtectedVm(config, protected_vm);
         AVirtualMachineRawConfig_setMemoryMiB(config, VM_MEMORY_MB);