Wait for the vm to stop before resize activity finishes am: 827eab2598

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Virtualization/+/3543960

Change-Id: I950651191fad76a1431b933e426e7565e6c84fdf
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
index 7502415..80f403b 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
@@ -253,7 +253,7 @@
         executorService.shutdown()
         getSystemService<AccessibilityManager>(AccessibilityManager::class.java)
             .removeAccessibilityStateChangeListener(this)
-        stop(this)
+        stop(this, this)
         super.onDestroy()
     }
 
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
index 8ea4b25..68da45f 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
@@ -31,6 +31,7 @@
 import android.widget.TextView
 import androidx.appcompat.app.AppCompatActivity
 import androidx.core.view.isVisible
+import com.android.virtualization.terminal.VmLauncherService.VmLauncherServiceCallback
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import java.util.Locale
 import java.util.regex.Pattern
@@ -140,12 +141,32 @@
         diskSizeMb = progressToMb(diskSizeSlider.progress)
         buttons.isVisible = false
 
-        // Restart terminal
-        val intent = baseContext.packageManager.getLaunchIntentForPackage(baseContext.packageName)
-        intent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
-        intent?.putExtra(MainActivity.KEY_DISK_SIZE, mbToBytes(diskSizeMb))
-        finish()
-        startActivity(intent)
+        // Note: we first stop the VM, and wait for it to fully stop. Then we (re) start the Main
+        // Activity with an extra argument specifying the new size. The actual resizing will be done
+        // there.
+        // TODO: show progress until the stop is confirmed
+        VmLauncherService.stop(
+            this,
+            object : VmLauncherServiceCallback {
+                override fun onVmStart() {}
+
+                override fun onTerminalAvailable(info: TerminalInfo) {}
+
+                override fun onVmStop() {
+                    finish()
+
+                    val intent =
+                        baseContext.packageManager.getLaunchIntentForPackage(
+                            baseContext.packageName
+                        )!!
+                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+                    intent.putExtra(MainActivity.KEY_DISK_SIZE, mbToBytes(diskSizeMb))
+                    startActivity(intent)
+                }
+
+                override fun onVmError() {}
+            },
+        )
     }
 
     fun updateSliderText(sizeMb: Long) {
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index 2d7dde9..deccae5 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -69,10 +69,10 @@
 
     // TODO: using lateinit for some fields to avoid null
     private var virtualMachine: VirtualMachine? = null
-    private var resultReceiver: ResultReceiver? = null
     private var server: Server? = null
     private var debianService: DebianServiceImpl? = null
     private var portNotifier: PortNotifier? = null
+    private var runner: Runner? = null
 
     interface VmLauncherServiceCallback {
         fun onVmStart()
@@ -94,12 +94,22 @@
     }
 
     override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
+        val resultReceiver =
+            intent.getParcelableExtra<ResultReceiver?>(
+                Intent.EXTRA_RESULT_RECEIVER,
+                ResultReceiver::class.java,
+            )
+
         if (intent.action == ACTION_SHUTDOWN_VM) {
             if (debianService != null && debianService!!.shutdownDebian()) {
                 // During shutdown, change the notification content to indicate that it's closing
                 val notification = createNotificationForTerminalClose()
                 getSystemService<NotificationManager?>(NotificationManager::class.java)
                     .notify(this.hashCode(), notification)
+                runner?.exitStatus?.thenAcceptAsync { success: Boolean ->
+                    resultReceiver?.send(if (success) RESULT_STOP else RESULT_ERROR, null)
+                    stopSelf()
+                }
             } else {
                 // If there is no Debian service or it fails to shutdown, just stop the service.
                 stopSelf()
@@ -125,24 +135,18 @@
         }
         val config = configBuilder.build()
 
-        val runner: Runner =
+        runner =
             try {
                 create(this, config)
             } catch (e: VirtualMachineException) {
                 throw RuntimeException("cannot create runner", e)
             }
 
-        virtualMachine = runner.vm
-        resultReceiver =
-            intent.getParcelableExtra<ResultReceiver?>(
-                Intent.EXTRA_RESULT_RECEIVER,
-                ResultReceiver::class.java,
-            )
-
+        virtualMachine = runner!!.vm
         val mbc = MemBalloonController(this, virtualMachine!!)
         mbc.start()
 
-        runner.exitStatus.thenAcceptAsync { success: Boolean ->
+        runner!!.exitStatus.thenAcceptAsync { success: Boolean ->
             mbc.stop()
             resultReceiver?.send(if (success) RESULT_STOP else RESULT_ERROR, null)
             stopSelf()
@@ -462,9 +466,21 @@
             return ResultReceiver.CREATOR.createFromParcel(parcel).also { parcel.recycle() }
         }
 
-        fun stop(context: Context) {
+        fun stop(context: Context, callback: VmLauncherServiceCallback?) {
             val i = getMyIntent(context)
             i.setAction(ACTION_SHUTDOWN_VM)
+            val resultReceiver: ResultReceiver =
+                object : ResultReceiver(Handler(Looper.myLooper()!!)) {
+                    override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
+                        if (callback == null) {
+                            return
+                        }
+                        when (resultCode) {
+                            RESULT_STOP -> callback.onVmStop()
+                        }
+                    }
+                }
+            i.putExtra(Intent.EXTRA_RESULT_RECEIVER, getResultReceiverForIntent(resultReceiver))
             context.startService(i)
         }
     }