More refactoring

* use reverse domain name notation for all actions and extras
* fix NPE when stopping via notification
* mandate non-nullability on resultreceiver
* VmLauncherService.run/stop are replaced with
  getIntentForStart/Shutdown
* stop importing functions from companion objects

Bug: N/A
Test: run, rerun, resize, stop from notification
Change-Id: I569379f9a41441d7ca67e1e19f5c632dcf0c6bed
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/ConfigJson.kt b/android/TerminalApp/java/com/android/virtualization/terminal/ConfigJson.kt
index 1fd58cd..5d22790 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/ConfigJson.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/ConfigJson.kt
@@ -29,7 +29,6 @@
 import com.android.virtualization.terminal.ConfigJson.InputJson
 import com.android.virtualization.terminal.ConfigJson.PartitionJson
 import com.android.virtualization.terminal.ConfigJson.SharedPathJson
-import com.android.virtualization.terminal.InstalledImage.Companion.getDefault
 import com.google.gson.Gson
 import com.google.gson.annotations.SerializedName
 import java.io.BufferedReader
@@ -313,7 +312,7 @@
         private fun replaceKeywords(r: Reader, context: Context): String {
             val rules: Map<String, String> =
                 mapOf(
-                    "\\\$PAYLOAD_DIR" to getDefault(context).installDir.toString(),
+                    "\\\$PAYLOAD_DIR" to InstalledImage.getDefault(context).installDir.toString(),
                     "\\\$USER_ID" to context.userId.toString(),
                     "\\\$PACKAGE_NAME" to context.getPackageName(),
                     "\\\$APP_DATA_DIR" to context.getDataDir().toString(),
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt b/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt
index e81be7f..2c52283 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/DebianServiceImpl.kt
@@ -21,7 +21,6 @@
 import com.android.internal.annotations.GuardedBy
 import com.android.system.virtualmachine.flags.Flags
 import com.android.virtualization.terminal.MainActivity.Companion.TAG
-import com.android.virtualization.terminal.PortsStateManager.Companion.getInstance
 import com.android.virtualization.terminal.proto.DebianServiceGrpc.DebianServiceImplBase
 import com.android.virtualization.terminal.proto.ForwardingRequestItem
 import com.android.virtualization.terminal.proto.QueueOpeningRequest
@@ -35,7 +34,7 @@
 import io.grpc.stub.StreamObserver
 
 internal class DebianServiceImpl(context: Context) : DebianServiceImplBase() {
-    private val portsStateManager: PortsStateManager = getInstance(context)
+    private val portsStateManager = PortsStateManager.getInstance(context)
     private var portsStateListener: PortsStateManager.Listener? = null
     private var shutdownRunnable: Runnable? = null
     private val mLock = Object()
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
index 390ae00..487b7e8 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
@@ -15,6 +15,7 @@
  */
 package com.android.virtualization.terminal
 
+import android.app.ForegroundServiceStartNotAllowedException
 import android.app.Notification
 import android.app.PendingIntent
 import android.content.Context
@@ -49,10 +50,6 @@
 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.ErrorActivity.Companion.start
-import com.android.virtualization.terminal.InstalledImage.Companion.getDefault
-import com.android.virtualization.terminal.VmLauncherService.Companion.run
-import com.android.virtualization.terminal.VmLauncherService.Companion.stop
 import com.android.virtualization.terminal.VmLauncherService.VmLauncherServiceCallback
 import com.google.android.material.tabs.TabLayout
 import com.google.android.material.tabs.TabLayoutMediator
@@ -85,7 +82,7 @@
         super.onCreate(savedInstanceState)
         lockOrientationIfNecessary()
 
-        image = getDefault(this)
+        image = InstalledImage.getDefault(this)
 
         val launchInstaller = installIfNecessary()
 
@@ -198,7 +195,7 @@
     override fun dispatchKeyEvent(event: KeyEvent): Boolean {
         if (Build.isDebuggable() && event.keyCode == KeyEvent.KEYCODE_UNKNOWN) {
             if (event.action == KeyEvent.ACTION_UP) {
-                start(this, Exception("Debug: KeyEvent.KEYCODE_UNKNOWN"))
+                ErrorActivity.start(this, Exception("Debug: KeyEvent.KEYCODE_UNKNOWN"))
             }
             return true
         }
@@ -252,7 +249,8 @@
         executorService.shutdown()
         getSystemService<AccessibilityManager>(AccessibilityManager::class.java)
             .removeAccessibilityStateChangeListener(this)
-        stop(this, this)
+        val intent = VmLauncherService.getIntentForShutdown(this, this)
+        startService(intent)
         super.onDestroy()
     }
 
@@ -272,7 +270,7 @@
     override fun onVmError() {
         Log.i(TAG, "onVmError()")
         // TODO: error cause is too simple.
-        start(this, Exception("onVmError"))
+        ErrorActivity.start(this, Exception("onVmError"))
     }
 
     override fun onAccessibilityStateChanged(enabled: Boolean) {
@@ -307,7 +305,7 @@
     }
 
     private fun startVm() {
-        val image = getDefault(this)
+        val image = InstalledImage.getDefault(this)
         if (!image.isInstalled()) {
             return
         }
@@ -322,9 +320,7 @@
         val settingsPendingIntent =
             PendingIntent.getActivity(this, 0, settingsIntent, PendingIntent.FLAG_IMMUTABLE)
 
-        val stopIntent = Intent()
-        stopIntent.setClass(this, VmLauncherService::class.java)
-        stopIntent.setAction(VmLauncherService.ACTION_SHUTDOWN_VM)
+        val stopIntent = VmLauncherService.getIntentForShutdown(this, this)
         val stopPendingIntent =
             PendingIntent.getService(
                 this,
@@ -359,9 +355,20 @@
                 )
                 .build()
 
-        val diskSize = intent.getLongExtra(KEY_DISK_SIZE, image.getSize())
-        run(this, this, notification, getDisplayInfo(), diskSize).onFailure {
-            Log.e(TAG, "Failed to start VM.", it)
+        val diskSize = intent.getLongExtra(EXTRA_DISK_SIZE, image.getSize())
+
+        val intent =
+            VmLauncherService.getIntentForStart(
+                this,
+                this,
+                notification,
+                getDisplayInfo(),
+                diskSize,
+            )
+        try {
+            startForegroundService(intent)
+        } catch (e: ForegroundServiceStartNotAllowedException) {
+            Log.e(TAG, "Failed to start VM", e)
             finish()
         }
     }
@@ -373,7 +380,8 @@
 
     companion object {
         const val TAG: String = "VmTerminalApp"
-        const val KEY_DISK_SIZE: String = "disk_size"
+        const val PREFIX: String = "com.android.virtualization.terminal."
+        const val EXTRA_DISK_SIZE: String = PREFIX + "EXTRA_DISK_SIZE"
         private val TERMINAL_CONNECTION_TIMEOUT_MS: Int
         private const val REQUEST_CODE_INSTALLER = 0x33
         private const val FONT_SIZE_DEFAULT = 13
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
index 68da45f..af1ae95 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
@@ -145,28 +145,30 @@
         // 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() {}
+        val intent =
+            VmLauncherService.getIntentForShutdown(
+                this,
+                object : VmLauncherServiceCallback {
+                    override fun onVmStart() {}
 
-                override fun onTerminalAvailable(info: TerminalInfo) {}
+                    override fun onTerminalAvailable(info: TerminalInfo) {}
 
-                override fun onVmStop() {
-                    finish()
+                    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)
-                }
+                        val intent =
+                            baseContext.packageManager.getLaunchIntentForPackage(
+                                baseContext.packageName
+                            )!!
+                        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
+                        intent.putExtra(MainActivity.EXTRA_DISK_SIZE, mbToBytes(diskSizeMb))
+                        startActivity(intent)
+                    }
 
-                override fun onVmError() {}
-            },
-        )
+                    override fun onVmError() {}
+                },
+            )
+        startService(intent)
     }
 
     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 052916f..e5cabbf 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -15,7 +15,6 @@
  */
 package com.android.virtualization.terminal
 
-import android.app.ForegroundServiceStartNotAllowedException
 import android.app.Notification
 import android.app.NotificationManager
 import android.app.PendingIntent
@@ -41,8 +40,8 @@
 import android.widget.Toast
 import androidx.annotation.WorkerThread
 import com.android.system.virtualmachine.flags.Flags
+import com.android.virtualization.terminal.MainActivity.Companion.PREFIX
 import com.android.virtualization.terminal.MainActivity.Companion.TAG
-import com.android.virtualization.terminal.Runner.Companion.create
 import io.grpc.Grpc
 import io.grpc.InsecureServerCredentials
 import io.grpc.Metadata
@@ -159,7 +158,7 @@
 
         runner =
             try {
-                create(this, config)
+                Runner.create(this, config)
             } catch (e: VirtualMachineException) {
                 throw RuntimeException("cannot create runner", e)
             }
@@ -170,7 +169,7 @@
 
         runner!!.exitStatus.thenAcceptAsync { success: Boolean ->
             mbc.stop()
-            resultReceiver?.send(if (success) RESULT_STOP else RESULT_ERROR, null)
+            resultReceiver.send(if (success) RESULT_STOP else RESULT_ERROR, null)
             stopSelf()
         }
         val logDir = getFileStreamPath(virtualMachine!!.name + ".log").toPath()
@@ -178,7 +177,7 @@
 
         startForeground(this.hashCode(), notification)
 
-        resultReceiver!!.send(RESULT_START, null)
+        resultReceiver.send(RESULT_START, null)
 
         portNotifier = PortNotifier(this)
 
@@ -190,7 +189,7 @@
                     val bundle = Bundle()
                     bundle.putString(KEY_TERMINAL_IPADDRESS, ipAddress)
                     bundle.putInt(KEY_TERMINAL_PORT, port)
-                    resultReceiver!!.send(RESULT_TERMINAL_AVAIL, bundle)
+                    resultReceiver.send(RESULT_TERMINAL_AVAIL, bundle)
                     startDebianServer(ipAddress)
                 },
                 executorService,
@@ -198,7 +197,7 @@
             .exceptionallyAsync(
                 { e ->
                     Log.e(TAG, "Failed to start VM", e)
-                    resultReceiver!!.send(RESULT_ERROR, null)
+                    resultReceiver.send(RESULT_ERROR, null)
                     stopSelf()
                     null
                 },
@@ -396,7 +395,7 @@
             getSystemService<NotificationManager?>(NotificationManager::class.java)
                 .notify(this.hashCode(), notification)
             runner?.exitStatus?.thenAcceptAsync { success: Boolean ->
-                resultReceiver?.send(if (success) RESULT_STOP else RESULT_ERROR, null)
+                resultReceiver.send(if (success) RESULT_STOP else RESULT_ERROR, null)
                 stopSelf()
             }
         } else {
@@ -431,11 +430,12 @@
     }
 
     companion object {
-        private const val EXTRA_NOTIFICATION = "EXTRA_NOTIFICATION"
-        private const val ACTION_START_VM: String = "android.virtualization.ACTION_START_VM"
-        const val EXTRA_DISPLAY_INFO = "EXTRA_DISPLAY_INFO"
-        const val EXTRA_DISK_SIZE = "EXTRA_DISK_SIZE"
-        const val ACTION_SHUTDOWN_VM: String = "android.virtualization.ACTION_SHUTDOWN_VM"
+        private const val ACTION_START_VM: String = PREFIX + "ACTION_START_VM"
+        private const val EXTRA_NOTIFICATION = PREFIX + "EXTRA_NOTIFICATION"
+        private const val EXTRA_DISPLAY_INFO = PREFIX + "EXTRA_DISPLAY_INFO"
+        private const val EXTRA_DISK_SIZE = PREFIX + "EXTRA_DISK_SIZE"
+
+        private const val ACTION_SHUTDOWN_VM: String = PREFIX + "ACTION_SHUTDOWN_VM"
 
         private const val RESULT_START = 0
         private const val RESULT_STOP = 1
@@ -487,13 +487,13 @@
             return intent
         }
 
-        fun run(
+        fun getIntentForStart(
             context: Context,
             callback: VmLauncherServiceCallback,
             notification: Notification?,
             displayInfo: DisplayInfo,
             diskSize: Long?,
-        ): Result<Unit> {
+        ): Intent {
             val i = prepareIntent(context, callback)
             i.setAction(ACTION_START_VM)
             i.putExtra(EXTRA_NOTIFICATION, notification)
@@ -501,18 +501,13 @@
             if (diskSize != null) {
                 i.putExtra(EXTRA_DISK_SIZE, diskSize)
             }
-            return try {
-                context.startForegroundService(i)
-                Result.success(Unit)
-            } catch (e: ForegroundServiceStartNotAllowedException) {
-                Result.failure<Unit>(e)
-            }
+            return i
         }
 
-        fun stop(context: Context, callback: VmLauncherServiceCallback) {
+        fun getIntentForShutdown(context: Context, callback: VmLauncherServiceCallback): Intent {
             val i = prepareIntent(context, callback)
             i.setAction(ACTION_SHUTDOWN_VM)
-            context.startService(i)
+            return i
         }
     }
 }