Snap for 13197820 from dc2cb4c5198cb80c860a180fe1ec8df2f95fa640 to 25Q2-release
Change-Id: I727fded3f3ae62ed03c0bd53c095ad077ddaab28
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/Logger.kt b/android/TerminalApp/java/com/android/virtualization/terminal/Logger.kt
index d02491b..4162247 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/Logger.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/Logger.kt
@@ -51,8 +51,7 @@
deleteOldLogs(dir, 10)
val logPath = dir.resolve(LocalDateTime.now().toString() + ".txt")
val console = vm.getConsoleOutput()
- val file =
- Files.newOutputStream(logPath, StandardOpenOption.CREATE)
+ val file = Files.newOutputStream(logPath, StandardOpenOption.CREATE)
executor.submit<Int?> {
console.use { console ->
LineBufferedOutputStream(file).use { fileOutput ->
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 aa1898f..345e8dd 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/VmLauncherService.kt
@@ -55,11 +55,12 @@
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
-import java.lang.RuntimeException
import java.lang.Math.min
+import java.lang.RuntimeException
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
@@ -78,43 +79,47 @@
private var debianService: DebianServiceImpl? = null
private var portNotifier: PortNotifier? = null
private var mLock = Object()
- @GuardedBy("mLock")
- private var currentMemBalloonPercent = 0;
+ @GuardedBy("mLock") private var currentMemBalloonPercent = 0
- @GuardedBy("mLock")
- private val inflateMemBalloonHandler = Handler(Looper.getMainLooper())
- private val inflateMemBalloonTask: Runnable = object : Runnable {
- override fun run() {
- synchronized(mLock) {
- if (currentMemBalloonPercent < INITIAL_MEM_BALLOON_PERCENT
- || currentMemBalloonPercent > MAX_MEM_BALLOON_PERCENT
- ) {
- Log.e(
- TAG, "currentBalloonPercent=$currentMemBalloonPercent is invalid," +
+ @GuardedBy("mLock") private val inflateMemBalloonHandler = Handler(Looper.getMainLooper())
+ private val inflateMemBalloonTask: Runnable =
+ object : Runnable {
+ override fun run() {
+ synchronized(mLock) {
+ if (
+ currentMemBalloonPercent < INITIAL_MEM_BALLOON_PERCENT ||
+ currentMemBalloonPercent > MAX_MEM_BALLOON_PERCENT
+ ) {
+ Log.e(
+ TAG,
+ "currentBalloonPercent=$currentMemBalloonPercent is invalid," +
" should be in range: " +
- "$INITIAL_MEM_BALLOON_PERCENT~$MAX_MEM_BALLOON_PERCENT"
- )
- return
- }
- // Increases the balloon size by MEM_BALLOON_PERCENT_STEP% every time
- if (currentMemBalloonPercent < MAX_MEM_BALLOON_PERCENT) {
- currentMemBalloonPercent =
- min(
- MAX_MEM_BALLOON_PERCENT,
- currentMemBalloonPercent + MEM_BALLOON_PERCENT_STEP
+ "$INITIAL_MEM_BALLOON_PERCENT~$MAX_MEM_BALLOON_PERCENT",
)
- virtualMachine?.setMemoryBalloonByPercent(currentMemBalloonPercent)
- inflateMemBalloonHandler.postDelayed(this,
- MEM_BALLOON_INFLATE_INTERVAL_MILLIS)
+ return
+ }
+ // Increases the balloon size by MEM_BALLOON_PERCENT_STEP% every time
+ if (currentMemBalloonPercent < MAX_MEM_BALLOON_PERCENT) {
+ currentMemBalloonPercent =
+ min(
+ MAX_MEM_BALLOON_PERCENT,
+ currentMemBalloonPercent + MEM_BALLOON_PERCENT_STEP,
+ )
+ virtualMachine?.setMemoryBalloonByPercent(currentMemBalloonPercent)
+ inflateMemBalloonHandler.postDelayed(
+ this,
+ MEM_BALLOON_INFLATE_INTERVAL_MILLIS,
+ )
+ }
}
}
}
- }
-
interface VmLauncherServiceCallback {
fun onVmStart()
+ fun onTerminalAvailable(info: TerminalInfo)
+
fun onVmStop()
fun onVmError()
@@ -136,8 +141,8 @@
// This gives the app maximum available memory.
ApplicationLifeCycleEvent.APP_ON_START -> {
synchronized(mLock) {
- inflateMemBalloonHandler.removeCallbacks(inflateMemBalloonTask);
- currentMemBalloonPercent = 0;
+ inflateMemBalloonHandler.removeCallbacks(inflateMemBalloonTask)
+ currentMemBalloonPercent = 0
virtualMachine?.setMemoryBalloonByPercent(currentMemBalloonPercent)
}
}
@@ -148,12 +153,12 @@
// MAX_MEM_BALLOON_PERCENT of total memory. This allows the system to reclaim
// memory while the app is in the background.
synchronized(mLock) {
- currentMemBalloonPercent = INITIAL_MEM_BALLOON_PERCENT;
+ currentMemBalloonPercent = INITIAL_MEM_BALLOON_PERCENT
virtualMachine?.setMemoryBalloonByPercent(currentMemBalloonPercent)
inflateMemBalloonHandler.postDelayed(
inflateMemBalloonTask,
- MEM_BALLOON_INFLATE_INTERVAL_MILLIS
- );
+ MEM_BALLOON_INFLATE_INTERVAL_MILLIS,
+ )
}
}
else -> {
@@ -228,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 {
@@ -436,11 +462,15 @@
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
private const val MEM_BALLOON_INFLATE_INTERVAL_MILLIS = 60000L
- private const val MEM_BALLOON_PERCENT_STEP = 5;
+ private const val MEM_BALLOON_PERCENT_STEP = 5
private fun getMyIntent(context: Context): Intent {
return Intent(context.getApplicationContext(), VmLauncherService::class.java)
@@ -461,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()
}
@@ -487,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(
diff --git a/guest/trusty/test_vm/Android.bp b/guest/trusty/test_vm/Android.bp
index 06b7d9d..676e231 100644
--- a/guest/trusty/test_vm/Android.bp
+++ b/guest/trusty/test_vm/Android.bp
@@ -34,6 +34,30 @@
filename: "trusty-test_vm-config.json",
}
+prebuilt_etc {
+ name: "trusty_vm_launcher_sh",
+ enabled: false,
+ arch: {
+ arm64: {
+ enabled: true,
+ },
+ },
+ src: "trusty-vm-launcher.sh",
+ filename: "trusty-vm-launcher.sh",
+}
+
+prebuilt_etc {
+ name: "trusty_wait_ready_sh",
+ enabled: false,
+ arch: {
+ arm64: {
+ enabled: true,
+ },
+ },
+ src: "trusty-wait-ready.sh",
+ filename: "trusty-wait-ready.sh",
+}
+
sh_test {
// VTS tests for all Trusted HALs defined
// under hardware/interfaces/security/see
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
index 40050c0..ad63206 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachine.java
@@ -1807,7 +1807,7 @@
* {@linkplain #connectToVsockServer binder request}, and wait for {@link
* VirtualMachineCallback#onPayloadFinished} to be called.
*
- * <p>A stopped virtual machine can be re-started by calling {@link #run()}.
+ * <p>A stopped virtual machine cannot be re-started.
*
* <p>NOTE: This method may block and should not be called on the main thread.
*
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 5513af6..2434ed0 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -101,7 +101,7 @@
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_FULL = "full";
private static final String DEBUG_LEVEL_NONE = "none";
private static final int MIN_MEM_ARM64 = 170;
@@ -555,6 +555,7 @@
throws Exception {
// Preconditions
assumeKernelSupported(os);
+ assumeVmTypeSupported(os, false);
File key = findTestFile("test.com.android.virt.pem");
Map<String, File> keyOverrides = Map.of();
@@ -582,6 +583,7 @@
public void testBootFailsWhenVbMetaDigestDoesNotMatchBootconfig(String os) throws Exception {
// protectedVmWithImageSignedWithDifferentKeyRunsPvmfw() is the protected case.
assumeKernelSupported(os);
+ assumeVmTypeSupported(os, false);
// Sign everything with key1 except vbmeta
File key = findTestFile("test.com.android.virt.pem");
@@ -1155,6 +1157,8 @@
@Test
@CddTest
public void testRunEmptyPayload() throws Exception {
+ assumeVmTypeSupported("microdroid", false);
+
CommandRunner android = new CommandRunner(getDevice());
// Create the idsig file for the APK