Merge "Retrieve terminal info in a more robust way" into main
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
index f6eeff9..662fef5 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.kt
@@ -24,8 +24,6 @@
import android.graphics.drawable.Icon
import android.graphics.fonts.FontStyle
import android.net.Uri
-import android.net.nsd.NsdManager
-import android.net.nsd.NsdServiceInfo
import android.os.Build
import android.os.Bundle
import android.os.ConditionVariable
@@ -62,6 +60,7 @@
import java.io.IOException
import java.net.MalformedURLException
import java.net.URL
+import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@@ -78,12 +77,11 @@
private lateinit var image: InstalledImage
private lateinit var accessibilityManager: AccessibilityManager
private lateinit var manageExternalStorageActivityResultLauncher: ActivityResultLauncher<Intent>
- private var ipAddress: String? = null
- private var port: Int? = null
private lateinit var terminalViewModel: TerminalViewModel
private lateinit var viewPager: ViewPager2
private lateinit var tabLayout: TabLayout
private lateinit var terminalTabAdapter: TerminalTabAdapter
+ private val terminalInfo = CompletableFuture<TerminalInfo>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -243,40 +241,12 @@
}
fun connectToTerminalService(terminalView: TerminalView) {
- if (ipAddress != null && port != null) {
- val url = getTerminalServiceUrl(ipAddress, port!!)
- terminalView.loadUrl(url.toString())
- return
- }
- // TODO: refactor this block as a method
- val nsdManager = getSystemService<NsdManager>(NsdManager::class.java)
- val info = NsdServiceInfo()
- info.serviceType = "_http._tcp"
- info.serviceName = "ttyd"
- nsdManager.registerServiceInfoCallback(
- info,
- executorService,
- object : NsdManager.ServiceInfoCallback {
- var loaded: Boolean = false
-
- override fun onServiceInfoCallbackRegistrationFailed(errorCode: Int) {}
-
- override fun onServiceInfoCallbackUnregistered() {}
-
- override fun onServiceLost() {}
-
- override fun onServiceUpdated(info: NsdServiceInfo) {
- Log.i(TAG, "Service found: $info")
- if (!loaded) {
- ipAddress = info.hostAddresses[0].hostAddress
- port = info.port
- val url = getTerminalServiceUrl(ipAddress, port!!)
- loaded = true
- nsdManager.unregisterServiceInfoCallback(this)
- runOnUiThread(Runnable { terminalView.loadUrl(url.toString()) })
- }
- }
+ terminalInfo.thenAcceptAsync(
+ { info ->
+ val url = getTerminalServiceUrl(info.ipAddress, info.port)
+ runOnUiThread({ terminalView.loadUrl(url.toString()) })
},
+ executorService,
)
}
@@ -292,6 +262,10 @@
Log.i(TAG, "onVmStart()")
}
+ override fun onTerminalAvailable(info: TerminalInfo) {
+ terminalInfo.complete(info)
+ }
+
override fun onVmStop() {
Log.i(TAG, "onVmStop()")
finish()
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
index 5f3fd49..345e8dd 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -60,6 +60,7 @@
import java.net.InetSocketAddress
import java.net.SocketAddress
import java.nio.file.Files
+import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
@@ -117,6 +118,8 @@
interface VmLauncherServiceCallback {
fun onVmStart()
+ fun onTerminalAvailable(info: TerminalInfo)
+
fun onVmStop()
fun onVmError()
@@ -230,35 +233,56 @@
portNotifier = PortNotifier(this)
- // TODO: dedup this part
+ getTerminalServiceInfo()
+ .thenAcceptAsync(
+ { info ->
+ val ipAddress = info.hostAddresses[0].hostAddress
+ val port = info.port
+ val bundle = Bundle()
+ bundle.putString(KEY_TERMINAL_IPADDRESS, ipAddress)
+ bundle.putInt(KEY_TERMINAL_PORT, port)
+ resultReceiver!!.send(RESULT_TERMINAL_AVAIL, bundle)
+ startDebianServer(ipAddress)
+ },
+ executorService,
+ )
+
+ return START_NOT_STICKY
+ }
+
+ private fun getTerminalServiceInfo(): CompletableFuture<NsdServiceInfo> {
+ val executor = Executors.newSingleThreadExecutor(TerminalThreadFactory(applicationContext))
val nsdManager = getSystemService<NsdManager?>(NsdManager::class.java)
- val info = NsdServiceInfo()
- info.serviceType = "_http._tcp"
- info.serviceName = "ttyd"
+ val queryInfo = NsdServiceInfo()
+ queryInfo.serviceType = "_http._tcp"
+ queryInfo.serviceName = "ttyd"
+ var resolvedInfo = CompletableFuture<NsdServiceInfo>()
+
nsdManager.registerServiceInfoCallback(
- info,
- executorService!!,
+ queryInfo,
+ executor,
object : NsdManager.ServiceInfoCallback {
- var started: Boolean = false
+ var found: Boolean = false
override fun onServiceInfoCallbackRegistrationFailed(errorCode: Int) {}
- override fun onServiceInfoCallbackUnregistered() {}
+ override fun onServiceInfoCallbackUnregistered() {
+ executor.shutdown()
+ }
override fun onServiceLost() {}
override fun onServiceUpdated(info: NsdServiceInfo) {
Log.i(TAG, "Service found: $info")
- if (!started) {
- started = true
+ if (!found) {
+ found = true
nsdManager.unregisterServiceInfoCallback(this)
- startDebianServer(info.hostAddresses[0].hostAddress)
+ resolvedInfo.complete(info)
}
}
},
)
-
- return START_NOT_STICKY
+ return resolvedInfo
}
private fun createNotificationForTerminalClose(): Notification {
@@ -438,6 +462,10 @@
private const val RESULT_START = 0
private const val RESULT_STOP = 1
private const val RESULT_ERROR = 2
+ private const val RESULT_TERMINAL_AVAIL = 3
+
+ private const val KEY_TERMINAL_IPADDRESS = "address"
+ private const val KEY_TERMINAL_PORT = "port"
private const val INITIAL_MEM_BALLOON_PERCENT = 10
private const val MAX_MEM_BALLOON_PERCENT = 50
@@ -463,6 +491,11 @@
}
when (resultCode) {
RESULT_START -> callback.onVmStart()
+ RESULT_TERMINAL_AVAIL -> {
+ val ipAddress = resultData!!.getString(KEY_TERMINAL_IPADDRESS)
+ val port = resultData!!.getInt(KEY_TERMINAL_PORT)
+ callback.onTerminalAvailable(TerminalInfo(ipAddress!!, port))
+ }
RESULT_STOP -> callback.onVmStop()
RESULT_ERROR -> callback.onVmError()
}
@@ -489,6 +522,8 @@
}
}
+data class TerminalInfo(val ipAddress: String, val port: Int)
+
data class DisplayInfo(val width: Int, val height: Int, val dpi: Int, val refreshRate: Int) :
Parcelable {
constructor(