Refactor VmLauncherService
No change in functionality.
Bug: N/A
Test: N/A
Change-Id: Ic66e432821c4bf038bfc7d835ee6bcce8735fc9b
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index 01528bb..7ec1115 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -64,6 +64,7 @@
class VmLauncherService : Service() {
private lateinit var executorService: ExecutorService
+ private lateinit var image: InstalledImage
// TODO: using lateinit for some fields to avoid null
private var virtualMachine: VirtualMachine? = null
@@ -89,51 +90,65 @@
override fun onCreate() {
super.onCreate()
executorService = Executors.newCachedThreadPool(TerminalThreadFactory(applicationContext))
+ image = InstalledImage.getDefault(this)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val resultReceiver =
- intent.getParcelableExtra<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.
+ when (intent.action) {
+ ACTION_START_VM -> {
+ val notification =
+ intent.getParcelableExtra<Notification>(
+ EXTRA_NOTIFICATION,
+ Notification::class.java,
+ )!!
+
+ val displayInfo =
+ intent.getParcelableExtra(EXTRA_DISPLAY_INFO, DisplayInfo::class.java)!!
+
+ // Note: this doesn't always do the resizing. If the current image size is the same
+ // as the requested size which is rounded up to the page alignment, resizing is not
+ // done.
+ val diskSize = intent.getLongExtra(EXTRA_DISK_SIZE, image.getSize())
+
+ doStart(notification, displayInfo, diskSize, resultReceiver)
+ }
+ ACTION_SHUTDOWN_VM -> doShutdown(resultReceiver)
+ else -> {
+ Log.e(TAG, "Unknown command " + intent.action)
stopSelf()
}
- return START_NOT_STICKY
}
+
+ return START_NOT_STICKY
+ }
+
+ private fun doStart(
+ notification: Notification,
+ displayInfo: DisplayInfo,
+ diskSize: Long,
+ resultReceiver: ResultReceiver,
+ ) {
if (virtualMachine != null) {
Log.d(TAG, "VM instance is already started")
- return START_NOT_STICKY
+ return
}
val image = InstalledImage.getDefault(this)
val json = ConfigJson.from(this, image.configPath)
val configBuilder = json.toConfigBuilder(this)
val customImageConfigBuilder = json.toCustomImageConfigBuilder(this)
- val displaySize = intent.getParcelableExtra(EXTRA_DISPLAY_INFO, DisplayInfo::class.java)
-
- // Note: this doesn't always do the resizing. If the current image size is the same as the
- // requested size which is rounded up to the page alignment, resizing is not done.
- val diskSize = intent.getLongExtra(EXTRA_DISK_SIZE, image.getSize())
image.resize(diskSize)
customImageConfigBuilder.setAudioConfig(
AudioConfig.Builder().setUseSpeaker(true).setUseMicrophone(true).build()
)
- if (overrideConfigIfNecessary(customImageConfigBuilder, displaySize)) {
+ if (overrideConfigIfNecessary(customImageConfigBuilder, displayInfo)) {
configBuilder.setCustomImageConfig(customImageConfigBuilder.build())
}
val config = configBuilder.build()
@@ -157,9 +172,6 @@
val logDir = getFileStreamPath(virtualMachine!!.name + ".log").toPath()
Logger.setup(virtualMachine!!, logDir, executorService)
- val notification =
- intent.getParcelableExtra<Notification?>(EXTRA_NOTIFICATION, Notification::class.java)
-
startForeground(this.hashCode(), notification)
resultReceiver!!.send(RESULT_START, null)
@@ -188,8 +200,6 @@
},
executorService,
)
-
- return START_NOT_STICKY
}
private fun getTerminalServiceInfo(): CompletableFuture<NsdServiceInfo> {
@@ -374,6 +384,28 @@
}
}
+ private fun doShutdown(resultReceiver: ResultReceiver) {
+ 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()
+ }
+ }
+
+ private fun stopDebianServer() {
+ debianService?.killForwarderHost()
+ debianService?.closeStorageBalloonRequestQueue()
+ server?.shutdown()
+ }
+
override fun onDestroy() {
portNotifier?.stop()
getSystemService<NotificationManager?>(NotificationManager::class.java).cancelAll()
@@ -393,16 +425,9 @@
super.onDestroy()
}
- private fun stopDebianServer() {
- debianService?.killForwarderHost()
- debianService?.closeStorageBalloonRequestQueue()
- server?.shutdown()
- }
-
companion object {
private const val EXTRA_NOTIFICATION = "EXTRA_NOTIFICATION"
- private const val ACTION_START_VM_LAUNCHER_SERVICE =
- "android.virtualization.START_VM_LAUNCHER_SERVICE"
+ 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"
@@ -428,24 +453,11 @@
}
}()
- private fun getMyIntent(context: Context): Intent {
- return Intent(context.getApplicationContext(), VmLauncherService::class.java)
- }
-
- fun run(
- context: Context,
- callback: VmLauncherServiceCallback?,
- notification: Notification?,
- displayInfo: DisplayInfo,
- diskSize: Long?,
- ): Result<Unit> {
- val i = getMyIntent(context)
- val resultReceiver: ResultReceiver =
+ private fun prepareIntent(context: Context, callback: VmLauncherServiceCallback): Intent {
+ val intent = Intent(context.getApplicationContext(), VmLauncherService::class.java)
+ val resultReceiver =
object : ResultReceiver(Handler(Looper.myLooper()!!)) {
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
- if (callback == null) {
- return
- }
when (resultCode) {
RESULT_START -> callback.onVmStart()
RESULT_TERMINAL_AVAIL -> {
@@ -455,10 +467,30 @@
}
RESULT_STOP -> callback.onVmStop()
RESULT_ERROR -> callback.onVmError()
+ else -> Log.e(TAG, "unknown result code: " + resultCode)
}
}
}
- i.putExtra(Intent.EXTRA_RESULT_RECEIVER, getResultReceiverForIntent(resultReceiver))
+
+ val parcel = Parcel.obtain()
+ resultReceiver.writeToParcel(parcel, 0)
+ parcel.setDataPosition(0)
+ intent.putExtra(
+ Intent.EXTRA_RESULT_RECEIVER,
+ ResultReceiver.CREATOR.createFromParcel(parcel).also { parcel.recycle() },
+ )
+ return intent
+ }
+
+ fun run(
+ context: Context,
+ callback: VmLauncherServiceCallback,
+ notification: Notification?,
+ displayInfo: DisplayInfo,
+ diskSize: Long?,
+ ): Result<Unit> {
+ val i = prepareIntent(context, callback)
+ i.setAction(ACTION_START_VM)
i.putExtra(EXTRA_NOTIFICATION, notification)
i.putExtra(EXTRA_DISPLAY_INFO, displayInfo)
if (diskSize != null) {
@@ -472,28 +504,9 @@
}
}
- private fun getResultReceiverForIntent(r: ResultReceiver): ResultReceiver {
- val parcel = Parcel.obtain()
- r.writeToParcel(parcel, 0)
- parcel.setDataPosition(0)
- return ResultReceiver.CREATOR.createFromParcel(parcel).also { parcel.recycle() }
- }
-
- fun stop(context: Context, callback: VmLauncherServiceCallback?) {
- val i = getMyIntent(context)
+ fun stop(context: Context, callback: VmLauncherServiceCallback) {
+ val i = prepareIntent(context, callback)
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)
}
}