Merge "Update rialto_test to incorporate RkpInstance in session" into main
diff --git a/OWNERS b/OWNERS
index afd2555..81217f3 100644
--- a/OWNERS
+++ b/OWNERS
@@ -30,8 +30,6 @@
victorhsieh@google.com
# Ferrochrome
-per-file android/FerrochromeApp/**=jiyong@google.com,jeongik@google.com
-per-file android/LinuxInstaller/**=jiyong@google.com,jeongik@google.com
per-file android/TerminalApp/**=jiyong@google.com,jeongik@google.com
per-file android/VmLauncherApp/**=jiyong@google.com,jeongik@google.com
per-file libs/vm_launcher_lib/**=jiyong@google.com,jeongik@google.com
diff --git a/android/LinuxInstaller/Android.bp b/android/LinuxInstaller/Android.bp
deleted file mode 100644
index f7994ef..0000000
--- a/android/LinuxInstaller/Android.bp
+++ /dev/null
@@ -1,62 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_defaults {
- name: "LinuxVmPayloadInstaller",
- init_rc: [":linux_vm_setup.rc"],
- required: ["linux_vm_setup"],
- system_ext_specific: true,
- platform_apis: true,
- privileged: true,
-}
-
-android_app {
- name: "LinuxInstallerApp",
- srcs: ["java/**/*.java"],
- resource_dirs: ["res"],
- asset_dirs: ["assets"],
- manifest: "AndroidManifest.xml",
- defaults: ["LinuxVmPayloadInstaller"],
- overrides: ["LinuxInstallerAppStub"],
- required: [
- "privapp-permissions-linuxinstaller.xml",
- ],
- certificate: ":com.android.virtualization.linuxinstaller_certificate",
-}
-
-android_app {
- name: "LinuxInstallerAppStub",
- srcs: ["java/**/*.java"],
- resource_dirs: ["res"],
- manifest: "AndroidManifest_stub.xml",
- defaults: ["LinuxVmPayloadInstaller"],
- required: [
- "privapp-permissions-linuxinstaller.xml",
- ],
- certificate: ":com.android.virtualization.linuxinstaller_certificate",
-}
-
-prebuilt_etc {
- name: "privapp-permissions-linuxinstaller.xml",
- src: "privapp-permissions-linuxinstaller.xml",
- sub_dir: "permissions",
- system_ext_specific: true,
-}
-
-android_app_certificate {
- name: "com.android.virtualization.linuxinstaller_certificate",
- certificate: "com_android_virtualization_linuxinstaller",
-}
-
-filegroup {
- name: "linux_vm_setup.rc",
- srcs: ["linux_vm_setup.rc"],
-}
-
-sh_binary {
- name: "linux_vm_setup",
- src: "linux_vm_setup.sh",
- system_ext_specific: true,
- host_supported: false,
-}
diff --git a/android/LinuxInstaller/AndroidManifest.xml b/android/LinuxInstaller/AndroidManifest.xml
deleted file mode 100644
index e5653f6..0000000
--- a/android/LinuxInstaller/AndroidManifest.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.virtualization.linuxinstaller"
- android:versionCode="2100000000" >
- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
- <queries>
- <intent>
- <action android:name="android.virtualization.VM_TERMINAL" />
- </intent>
- </queries>
- <application
- android:label="LinuxInstaller">
- <activity android:name=".MainActivity"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
diff --git a/android/LinuxInstaller/AndroidManifest_stub.xml b/android/LinuxInstaller/AndroidManifest_stub.xml
deleted file mode 100644
index 49365ea..0000000
--- a/android/LinuxInstaller/AndroidManifest_stub.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.virtualization.linuxinstaller" >
- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
- <queries>
- <intent>
- <action android:name="android.virtualization.VM_TERMINAL" />
- </intent>
- </queries>
- <application
- android:label="LinuxInstaller">
- <activity android:name=".MainActivity"
- android:exported="true">
- </activity>
- </application>
-
-</manifest>
diff --git a/android/LinuxInstaller/com_android_virtualization_linuxinstaller.pk8 b/android/LinuxInstaller/com_android_virtualization_linuxinstaller.pk8
deleted file mode 100644
index 3f74303..0000000
--- a/android/LinuxInstaller/com_android_virtualization_linuxinstaller.pk8
+++ /dev/null
Binary files differ
diff --git a/android/LinuxInstaller/com_android_virtualization_linuxinstaller.x509.pem b/android/LinuxInstaller/com_android_virtualization_linuxinstaller.x509.pem
deleted file mode 100644
index 3ca64b7..0000000
--- a/android/LinuxInstaller/com_android_virtualization_linuxinstaller.x509.pem
+++ /dev/null
@@ -1,24 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIEETCCAvmgAwIBAgIUfBxyELS+ri3QErq8DXHu+47xx4EwDQYJKoZIhvcNAQEL
-BQAwgZYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKDAtHb29nbGUgSW5jLjEQMA4GA1UECwwH
-QW5kcm9pZDEyMDAGA1UEAwwpY29tX2FuZHJvaWRfdmlydHVhbGl6YXRpb25fbGlu
-dXhpbnN0YWxsZXIwIBcNMjQwODMwMTIyNjU2WhgPMjA1MjAxMTYxMjI2NTZaMIGW
-MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91
-bnRhaW4gVmlldzEUMBIGA1UECgwLR29vZ2xlIEluYy4xEDAOBgNVBAsMB0FuZHJv
-aWQxMjAwBgNVBAMMKWNvbV9hbmRyb2lkX3ZpcnR1YWxpemF0aW9uX2xpbnV4aW5z
-dGFsbGVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8V/rH9ju6Wce
-1BdWuxfWaLmZJHGShXeDO6MB86Wrm10m26j9PFzd8/8FRKsZaujZphwNZsqBsdlt
-pWeNKts9T9luZn19Ci4E8A2EtgSxmfI8Fjwj/OJHHO0hG5+JcwIlUnmFQPcGtu/r
-EL3i7SfcF2ok+IC6aKYohnSbo+YkjyCSwb39i6POe6v6cPIZJtmOnecThS+fYCYR
-2yoMSSr3Bf8ayySrG0pJp7xZ1I5NixK6hUFZhQRLusyiv/KYTpAElMd+n1YJEYbf
-pW30DYAu+31S0hx8JXncFmI0uG3Zxx+LgNQwY8OPV6NPFfVwMPluZR6ep0tZ6q7e
-KIV2w5uC7QIDAQABo1MwUTAdBgNVHQ4EFgQU6FBYv7mW+9DR9q0c9uS4NNdX4Acw
-HwYDVR0jBBgwFoAU6FBYv7mW+9DR9q0c9uS4NNdX4AcwDwYDVR0TAQH/BAUwAwEB
-/zANBgkqhkiG9w0BAQsFAAOCAQEAj3bvUpwKjvpCggXzjMNkn7fAaQ0s1BubnkFe
-ge4zwz4tObP3OGRcxt5V9R5EZ7UY6bPcybA/rfg9FCzjcUQOBjmuepcQpbNHFW2I
-lasFa42UHkHSUFzeg2n9UC5iO3B+sclOr4EPaEE4HbG4B2vj++BYMW3C7PDyHc7R
-fq5ZsEEWcYUa8qZCO46I8AbMZ8iv1HpR4mZeQMkSxhD3uVHDQW+VqDTpzne/YBkJ
-yNfjpgFVZ/Y1E6BvvjzWZpBfj668fo7P3DekWHbvPPr/DiZ7OA6PCmAH1FBsi2c+
-xPgb9clDc2Zjb2Cd9lAoZdeB14zDOh6ZCF1c/i+qYt5tA9t+GA==
------END CERTIFICATE-----
diff --git a/android/LinuxInstaller/privapp-permissions-linuxinstaller.xml b/android/LinuxInstaller/privapp-permissions-linuxinstaller.xml
deleted file mode 100644
index e46ec97..0000000
--- a/android/LinuxInstaller/privapp-permissions-linuxinstaller.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<permissions>
- <privapp-permissions package="com.android.virtualization.linuxinstaller">
- <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
- </privapp-permissions>
-</permissions>
\ No newline at end of file
diff --git a/android/LinuxInstaller/.gitignore b/android/TerminalApp/.gitignore
similarity index 100%
rename from android/LinuxInstaller/.gitignore
rename to android/TerminalApp/.gitignore
diff --git a/android/TerminalApp/Android.bp b/android/TerminalApp/Android.bp
index d91af2f..e5e8b0a 100644
--- a/android/TerminalApp/Android.bp
+++ b/android/TerminalApp/Android.bp
@@ -9,6 +9,7 @@
"java/**/*.kt",
],
resource_dirs: ["res"],
+ asset_dirs: ["assets"],
static_libs: [
"vm_launcher_lib",
"androidx-constraintlayout_constraintlayout",
@@ -25,3 +26,15 @@
"com.android.virt",
],
}
+
+filegroup {
+ name: "linux_vm_setup.rc",
+ srcs: ["linux_vm_setup.rc"],
+}
+
+sh_binary {
+ name: "linux_vm_setup",
+ src: "linux_vm_setup.sh",
+ init_rc: [":linux_vm_setup.rc"],
+ host_supported: false,
+}
diff --git a/android/TerminalApp/AndroidManifest.xml b/android/TerminalApp/AndroidManifest.xml
index f09412e..105e454 100644
--- a/android/TerminalApp/AndroidManifest.xml
+++ b/android/TerminalApp/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.virtualization.terminal">
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
<uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
<uses-permission android:name="android.permission.INTERNET" />
@@ -12,15 +13,18 @@
<uses-feature android:name="android.software.virtualization_framework" android:required="true" />
<application
- android:label="@string/app_name"
+ android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/Theme.Material3.DayNight.NoActionBar"
- android:usesCleartextTraffic="true">
+ android:usesCleartextTraffic="true"
+ android:enabled="false">
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboard|keyboardHidden|navigation|uiMode|screenLayout|smallestScreenSize"
android:exported="true">
<intent-filter>
+ <action android:name="android.intent.action.MAIN" />
<action android:name="android.virtualization.VM_TERMINAL" />
+ <category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -44,20 +48,15 @@
android:name="${applicationId}.SplitInitializer"
android:value="androidx.startup" />
</provider>
- <activity-alias
- android:name=".MainActivityAlias"
- android:targetActivity="com.android.virtualization.terminal.MainActivity"
- android:exported="true"
- android:enabled="false" >
+ <activity android:name=".InstallerActivity"
+ android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- </activity-alias>
+ </activity>
<service
android:name="com.android.virtualization.vmlauncher.VmLauncherService"
- android:enabled="true"
android:exported="false"
android:foregroundServiceType="specialUse">
<property
diff --git a/android/LinuxInstaller/assets/.gitkeep b/android/TerminalApp/assets/.gitkeep
similarity index 100%
rename from android/LinuxInstaller/assets/.gitkeep
rename to android/TerminalApp/assets/.gitkeep
diff --git a/android/TerminalApp/assets/client.p12 b/android/TerminalApp/assets/client.p12
new file mode 100644
index 0000000..f1f5820
--- /dev/null
+++ b/android/TerminalApp/assets/client.p12
Binary files differ
diff --git a/android/TerminalApp/generate_assets.sh b/android/TerminalApp/generate_assets.sh
new file mode 100755
index 0000000..4001bfd
--- /dev/null
+++ b/android/TerminalApp/generate_assets.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+set -e
+
+if [ "$#" -ne 1 ]; then
+ echo "$0 <image.raw path>"
+ echo "image.raw can be built with packages/modules/Virtualization/build/debian/build.sh"
+ exit 1
+fi
+image_raw_path=$(realpath $1)
+pushd $(dirname $0) > /dev/null
+tempdir=$(mktemp -d)
+asset_dir=./assets/linux
+mkdir -p ${asset_dir}
+echo Copy files...
+pushd ${tempdir} > /dev/null
+cp "${image_raw_path}" ${tempdir}
+tar czvS -f images.tar.gz $(basename ${image_raw_path})
+popd > /dev/null
+cp vm_config.json ${asset_dir}
+mv ${tempdir}/images.tar.gz ${asset_dir}
+echo Calculating hash...
+hash=$(cat ${asset_dir}/images.tar.gz ${asset_dir}/vm_config.json | sha1sum | cut -d' ' -f 1)
+echo ${hash} > ${asset_dir}/hash
+popd > /dev/null
+echo Cleaning up...
+rm -rf ${tempdir}
+
diff --git a/android/LinuxInstaller/java/com/android/virtualization/linuxinstaller/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.java
similarity index 76%
rename from android/LinuxInstaller/java/com/android/virtualization/linuxinstaller/MainActivity.java
rename to android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.java
index 0351f97..1c739e2 100644
--- a/android/LinuxInstaller/java/com/android/virtualization/linuxinstaller/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/InstallerActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2024 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,15 +14,10 @@
* limitations under the License.
*/
-package com.android.virtualization.linuxinstaller;
+package com.android.virtualization.terminal;
import android.annotation.WorkerThread;
import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemProperties;
@@ -39,13 +34,11 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
-import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-public class MainActivity extends Activity {
+public class InstallerActivity extends Activity {
private static final String TAG = "LinuxInstaller";
- private static final String ACTION_VM_TERMINAL = "android.virtualization.VM_TERMINAL";
private static final Path DEST_DIR =
Path.of(Environment.getExternalStorageDirectory().getPath(), "linux");
@@ -59,20 +52,17 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ setResult(RESULT_CANCELED);
+
+ setContentView(R.layout.activity_installer);
executorService.execute(this::installLinuxImage);
}
private void installLinuxImage() {
- ComponentName vmTerminalComponent = resolve(getPackageManager(), ACTION_VM_TERMINAL);
- if (vmTerminalComponent == null) {
- updateStatus("Failed to resolve VM terminal");
- return;
- }
-
if (!hasLocalAssets()) {
updateStatus("No local assets");
+ setResult(RESULT_CANCELED, null);
return;
}
try {
@@ -81,13 +71,9 @@
Log.e(TAG, "failed to update image", e);
return;
}
- updateStatus("Enabling terminal app...");
- getPackageManager()
- .setComponentEnabledSetting(
- vmTerminalComponent,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP);
updateStatus("Done.");
+ setResult(RESULT_OK);
+ finish();
}
@WorkerThread
@@ -190,18 +176,4 @@
statusView.append(line + "\n");
});
}
-
- private ComponentName resolve(PackageManager pm, String action) {
- Intent intent = new Intent(action);
- List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, PackageManager.MATCH_ALL);
- if (resolveInfos.size() != 1) {
- Log.w(
- TAG,
- "Failed to resolve activity, action=" + action + ", resolved=" + resolveInfos);
- return null;
- }
- ActivityInfo activityInfo = resolveInfos.getFirst().activityInfo;
- // MainActivityAlias shows in Launcher
- return new ComponentName(activityInfo.packageName, activityInfo.name + "Alias");
- }
}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index 84c3eee..2a87348 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -15,21 +15,24 @@
*/
package com.android.virtualization.terminal;
-import android.content.ClipData;
-import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
+import android.net.http.SslError;
import android.os.Bundle;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.View;
import android.view.accessibility.AccessibilityManager;
+import android.webkit.ClientCertRequest;
+import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
+import android.webkit.WebResourceError;
+import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
-import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
@@ -42,19 +45,37 @@
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.io.RandomAccessFile;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
public class MainActivity extends AppCompatActivity
implements VmLauncherServices.VmLauncherServiceCallback,
AccessibilityManager.TouchExplorationStateChangeListener {
+
private static final String TAG = "VmTerminalApp";
- private String mVmIpAddr;
+ private static final String VM_ADDR = "192.168.0.2";
+ private static final int TTYD_PORT = 7681;
+ private static final int REQUEST_CODE_INSTALLER = 0x33;
+
+ private X509Certificate[] mCertificates;
+ private PrivateKey mPrivateKey;
private WebView mWebView;
+ private AccessibilityManager mAccessibilityManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ checkForUpdate();
try {
// No resize for now.
long newSizeInBytes = 0;
@@ -65,10 +86,6 @@
.show();
}
- Toast.makeText(this, R.string.vm_creation_message, Toast.LENGTH_SHORT).show();
- android.os.Trace.beginAsyncSection("executeTerminal", 0);
- VmLauncherServices.startVmLauncherService(this, this);
-
setContentView(R.layout.activity_headless);
MaterialToolbar toolbar = (MaterialToolbar) findViewById(R.id.toolbar);
@@ -78,21 +95,113 @@
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new WebChromeClient());
+
+ mAccessibilityManager = getSystemService(AccessibilityManager.class);
+ mAccessibilityManager.addTouchExplorationStateChangeListener(this);
+
+ connectToTerminalService();
+ readClientCertificate();
+ }
+
+ private URL getTerminalServiceUrl() {
+ boolean needsAccessibility = mAccessibilityManager.isTouchExplorationEnabled();
+ String file = "/";
+ String query = needsAccessibility ? "?screenReaderMode=true" : "";
+
+ try {
+ return new URL("https", VM_ADDR, TTYD_PORT, file + query);
+ } catch (MalformedURLException e) {
+ // this cannot happen
+ return null;
+ }
+ }
+
+ private void readClientCertificate() {
+ // TODO(b/363235314): instead of using the key in asset, it should be generated in runtime
+ // and then provisioned in the vm via virtio-fs
+ try (InputStream keystoreFileStream =
+ getClass().getResourceAsStream("/assets/client.p12")) {
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ String password = "1234";
+ String alias = "1";
+
+ keyStore.load(keystoreFileStream, password != null ? password.toCharArray() : null);
+ Key key = keyStore.getKey(alias, password.toCharArray());
+ if (key instanceof PrivateKey) {
+ mPrivateKey = (PrivateKey) key;
+ Certificate cert = keyStore.getCertificate(alias);
+ mCertificates = new X509Certificate[1];
+ mCertificates[0] = (X509Certificate) cert;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+ }
+
+ private void connectToTerminalService() {
+ Log.i(TAG, "URL=" + getTerminalServiceUrl().toString());
mWebView.setWebViewClient(
new WebViewClient() {
@Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- view.loadUrl(url);
- return true;
+ public boolean shouldOverrideUrlLoading(
+ WebView view, WebResourceRequest request) {
+ return false;
+ }
+
+ @Override
+ public void onReceivedError(
+ WebView view, WebResourceRequest request, WebResourceError error) {
+ switch (error.getErrorCode()) {
+ case WebViewClient.ERROR_CONNECT:
+ case WebViewClient.ERROR_HOST_LOOKUP:
+ view.reload();
+ return;
+ default:
+ String url = request.getUrl().toString();
+ CharSequence msg = error.getDescription();
+ Log.e(TAG, "Failed to load " + url + ": " + msg);
+ }
}
@Override
public void onPageFinished(WebView view, String url) {
- android.os.Trace.endAsyncSection("executeTerminal", 0);
+ URL loadedUrl = null;
+ try {
+ loadedUrl = new URL(url);
+ } catch (MalformedURLException e) {
+ // cannot happen.
+ }
+ Log.i(TAG, "on page finished. URL=" + loadedUrl);
+ if (getTerminalServiceUrl().toString().equals(url)) {
+ android.os.Trace.endAsyncSection("executeTerminal", 0);
+ view.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public void onReceivedClientCertRequest(
+ WebView view, ClientCertRequest request) {
+ if (mPrivateKey != null && mCertificates != null) {
+ request.proceed(mPrivateKey, mCertificates);
+ return;
+ }
+ super.onReceivedClientCertRequest(view, request);
+ }
+
+ @Override
+ public void onReceivedSslError(
+ WebView view, SslErrorHandler handler, SslError error) {
+ // ttyd uses self-signed certificate
+ handler.proceed();
}
});
-
- getSystemService(AccessibilityManager.class).addTouchExplorationStateChangeListener(this);
+ new Thread(
+ () -> {
+ waitUntilVmStarts();
+ runOnUiThread(
+ () -> mWebView.loadUrl(getTerminalServiceUrl().toString()));
+ })
+ .start();
}
private void diskResize(Context context, long sizeInBytes) throws IOException {
@@ -179,6 +288,22 @@
}
}
+ private static void waitUntilVmStarts() {
+ InetAddress addr = null;
+ try {
+ addr = InetAddress.getByName(VM_ADDR);
+ } catch (UnknownHostException e) {
+ // this can never happen.
+ }
+ try {
+ while (!addr.isReachable(10000)) {}
+ } catch (IOException e) {
+ // give up on network error
+ throw new RuntimeException(e);
+ }
+ return;
+ }
+
@Override
protected void onDestroy() {
getSystemService(AccessibilityManager.class).removeTouchExplorationStateChangeListener(this);
@@ -186,23 +311,6 @@
super.onDestroy();
}
- private void gotoTerminalURL() {
- if (mVmIpAddr == null) {
- Log.d(TAG, "ip addr is not set yet");
- return;
- }
-
- boolean isTouchExplorationEnabled =
- getSystemService(AccessibilityManager.class).isTouchExplorationEnabled();
-
- String url =
- "http://"
- + mVmIpAddr
- + ":7681/"
- + (isTouchExplorationEnabled ? "?screenReaderMode=true" : "");
- runOnUiThread(() -> mWebView.loadUrl(url));
- }
-
@Override
public void onVmStart() {
Log.i(TAG, "onVmStart()");
@@ -224,9 +332,7 @@
@Override
public void onIpAddrAvailable(String ipAddr) {
- mVmIpAddr = ipAddr;
- ((TextView) findViewById(R.id.ip_addr_textview)).setText(mVmIpAddr);
- gotoTerminalURL();
+ // TODO: remove this
}
@Override
@@ -238,16 +344,7 @@
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
- if (id == R.id.copy_ip_addr) {
- // TODO(b/340126051): remove this menu item when port forwarding is supported.
- getSystemService(ClipboardManager.class)
- .setPrimaryClip(ClipData.newPlainText("A VM's IP address", mVmIpAddr));
- return true;
- } else if (id == R.id.stop_vm) {
- VmLauncherServices.stopVmLauncherService(this);
- return true;
-
- } else if (id == R.id.menu_item_settings) {
+ if (id == R.id.menu_item_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
this.startActivity(intent);
return true;
@@ -257,6 +354,29 @@
@Override
public void onTouchExplorationStateChanged(boolean enabled) {
- gotoTerminalURL();
+ connectToTerminalService();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == REQUEST_CODE_INSTALLER) {
+ if (resultCode != RESULT_OK) {
+ Log.e(TAG, "Failed to start VM. Installer returned error.");
+ finish();
+ }
+ startVm();
+ }
+ }
+
+ private void checkForUpdate() {
+ Intent intent = new Intent(this, InstallerActivity.class);
+ startActivityForResult(intent, REQUEST_CODE_INSTALLER);
+ }
+
+ private void startVm() {
+ android.os.Trace.beginAsyncSection("executeTerminal", 0);
+ VmLauncherServices.startVmLauncherService(this, this);
}
}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
index 4be291f..1b14ef2 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/SettingsDiskResizeActivity.kt
@@ -16,27 +16,49 @@
package com.android.virtualization.terminal
import android.os.Bundle
+import android.os.FileUtils
import android.widget.TextView
import android.widget.Toast
+import android.text.style.RelativeSizeSpan
+import android.text.Spannable
+import android.text.SpannableString
+import android.text.Spanned
+import android.text.format.Formatter
+import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import com.google.android.material.button.MaterialButton
import com.google.android.material.slider.Slider
+import java.util.regex.Matcher
+import java.util.regex.Pattern
+
class SettingsDiskResizeActivity : AppCompatActivity() {
+ private val maxDiskSize: Float = 256F
+ private val numberPattern: Pattern = Pattern.compile("[\\d]*[\\٫.,]?[\\d]+");
private var diskSize: Float = 104F
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.settings_disk_resize)
- val diskSizeText = findViewById<TextView>(R.id.settings_disk_resize_disk_size)
+ val diskSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_assigned)
+ val diskMaxSizeText = findViewById<TextView>(R.id.settings_disk_resize_resize_gb_max)
+ diskMaxSizeText.text = getString(R.string.settings_disk_resize_resize_gb_max_format,
+ localizedFileSize(maxDiskSize));
+
val diskSizeSlider = findViewById<Slider>(R.id.settings_disk_resize_disk_size_slider)
+ diskSizeSlider.setValueTo(maxDiskSize)
val cancelButton = findViewById<MaterialButton>(R.id.settings_disk_resize_cancel_button)
val resizeButton = findViewById<MaterialButton>(R.id.settings_disk_resize_resize_button)
- diskSizeText.text = diskSize.toInt().toString()
diskSizeSlider.value = diskSize
+ diskSizeText.text = enlargeFontOfNumber(
+ getString(R.string.settings_disk_resize_resize_gb_assigned_format,
+ localizedFileSize(diskSize)))
diskSizeSlider.addOnChangeListener { _, value, _ ->
- diskSizeText.text = value.toInt().toString()
+ diskSizeText.text = enlargeFontOfNumber(
+ getString(R.string.settings_disk_resize_resize_gb_assigned_format,
+ localizedFileSize(value)))
cancelButton.isVisible = true
resizeButton.isVisible = true
}
@@ -54,4 +76,29 @@
.show()
}
}
+
+ fun localizedFileSize(sizeGb: Float): String {
+ // formatShortFileSize() uses SI unit (i.e. kB = 1000 bytes),
+ // so covert sizeGb with "GB" instead of "GIB".
+ val bytes = FileUtils.parseSize(sizeGb.toLong().toString() + "GB")
+ return Formatter.formatShortFileSize(this, bytes)
+ }
+
+ fun enlargeFontOfNumber(summary: CharSequence): CharSequence {
+ if (TextUtils.isEmpty(summary)) {
+ return ""
+ }
+
+ val matcher = numberPattern.matcher(summary);
+ if (matcher.find()) {
+ val spannableSummary = SpannableString(summary)
+ spannableSummary.setSpan(
+ RelativeSizeSpan(2f),
+ matcher.start(),
+ matcher.end(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
+ return spannableSummary
+ }
+ return summary
+ }
}
\ No newline at end of file
diff --git a/android/LinuxInstaller/linux_vm_setup.rc b/android/TerminalApp/linux_vm_setup.rc
similarity index 92%
rename from android/LinuxInstaller/linux_vm_setup.rc
rename to android/TerminalApp/linux_vm_setup.rc
index 9264d96..ac91532 100644
--- a/android/LinuxInstaller/linux_vm_setup.rc
+++ b/android/TerminalApp/linux_vm_setup.rc
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-service linux_vm_setup /system_ext/bin/linux_vm_setup
+service linux_vm_setup /system/bin/linux_vm_setup
user shell
group shell media_rw
disabled
diff --git a/android/LinuxInstaller/linux_vm_setup.sh b/android/TerminalApp/linux_vm_setup.sh
similarity index 100%
rename from android/LinuxInstaller/linux_vm_setup.sh
rename to android/TerminalApp/linux_vm_setup.sh
diff --git a/android/TerminalApp/res/drawable/ic_settings.xml b/android/TerminalApp/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..4bcd4aa
--- /dev/null
+++ b/android/TerminalApp/res/drawable/ic_settings.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M370,880L354,752Q341,747 329.5,740Q318,733 307,725L188,775L78,585L181,507Q180,500 180,493.5Q180,487 180,480Q180,473 180,466.5Q180,460 181,453L78,375L188,185L307,235Q318,227 330,220Q342,213 354,208L370,80L590,80L606,208Q619,213 630.5,220Q642,227 653,235L772,185L882,375L779,453Q780,460 780,466.5Q780,473 780,480Q780,487 780,493.5Q780,500 778,507L881,585L771,775L653,725Q642,733 630,740Q618,747 606,752L590,880L370,880ZM440,800L519,800L533,694Q564,686 590.5,670.5Q617,655 639,633L738,674L777,606L691,541Q696,527 698,511.5Q700,496 700,480Q700,464 698,448.5Q696,433 691,419L777,354L738,286L639,328Q617,305 590.5,289.5Q564,274 533,266L520,160L441,160L427,266Q396,274 369.5,289.5Q343,305 321,327L222,286L183,354L269,418Q264,433 262,448Q260,463 260,480Q260,496 262,511Q264,526 269,541L183,606L222,674L321,632Q343,655 369.5,670.5Q396,686 427,694L440,800ZM482,620Q540,620 581,579Q622,538 622,480Q622,422 581,381Q540,340 482,340Q423,340 382.5,381Q342,422 342,480Q342,538 382.5,579Q423,620 482,620ZM480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480L480,480L480,480L480,480Q480,480 480,480Q480,480 480,480L480,480Z"/>
+</vector>
diff --git a/android/TerminalApp/res/layout/activity_headless.xml b/android/TerminalApp/res/layout/activity_headless.xml
index f786a0f..7baaf5c 100644
--- a/android/TerminalApp/res/layout/activity_headless.xml
+++ b/android/TerminalApp/res/layout/activity_headless.xml
@@ -12,14 +12,32 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"/>
- <TextView
- android:id="@+id/ip_addr_textview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- <WebView
- android:id="@+id/webview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginBottom="5dp" />
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <LinearLayout
+ android:orientation="vertical"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <com.google.android.material.textview.MaterialTextView
+ android:text="@string/vm_creation_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="5dp"/>
+ <com.google.android.material.progressindicator.CircularProgressIndicator
+ android:indeterminate="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+ <WebView
+ android:id="@+id/webview"
+ android:layout_marginBottom="5dp"
+ android:layout_gravity="fill"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"/>
+ </FrameLayout>
</LinearLayout>
diff --git a/android/LinuxInstaller/res/layout/activity_main.xml b/android/TerminalApp/res/layout/activity_installer.xml
similarity index 100%
rename from android/LinuxInstaller/res/layout/activity_main.xml
rename to android/TerminalApp/res/layout/activity_installer.xml
diff --git a/android/TerminalApp/res/layout/settings_activity.xml b/android/TerminalApp/res/layout/settings_activity.xml
index b1acf23..4fc6229 100644
--- a/android/TerminalApp/res/layout/settings_activity.xml
+++ b/android/TerminalApp/res/layout/settings_activity.xml
@@ -5,10 +5,6 @@
android:orientation="vertical"
android:fitsSystemWindows="true">
- <com.google.android.material.search.SearchBar
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/settings_list_recycler_view"
android:layout_marginHorizontal="16dp"
diff --git a/android/TerminalApp/res/layout/settings_disk_resize.xml b/android/TerminalApp/res/layout/settings_disk_resize.xml
index 3c09f52..f868b28 100644
--- a/android/TerminalApp/res/layout/settings_disk_resize.xml
+++ b/android/TerminalApp/res/layout/settings_disk_resize.xml
@@ -21,27 +21,19 @@
android:layout_height="match_parent">
<TextView
- android:id="@+id/settings_disk_resize_disk_size"
+ android:id="@+id/settings_disk_resize_resize_gb_assigned"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:textSize="36sp"
- app:layout_constraintLeft_toLeftOf="parent"
+ android:textSize="14sp"
+ app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/settings_disk_resize_disk_size_slider"/>
<TextView
+ android:id="@+id/settings_disk_resize_resize_gb_max"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:text="@string/settings_disk_resize_resize_gb_assigned"
android:textSize="14sp"
- app:layout_constraintLeft_toRightOf="@+id/settings_disk_resize_disk_size"
- app:layout_constraintBottom_toTopOf="@+id/settings_disk_resize_disk_size_slider"/>
-
- <TextView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:text="@string/settings_disk_resize_resize_gb_total"
- android:textSize="14sp"
- app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@+id/settings_disk_resize_disk_size_slider"/>
<com.google.android.material.slider.Slider
@@ -51,7 +43,6 @@
android:layout_marginBottom="36dp"
app:tickVisible="false"
android:valueFrom="0"
- android:valueTo="256"
android:stepSize="4"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
@@ -65,7 +56,7 @@
android:layout_marginHorizontal="8dp"
app:layout_constraintTop_toTopOf="@+id/settings_disk_resize_disk_size_slider"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintRight_toLeftOf="@+id/settings_disk_resize_resize_button" />
+ app:layout_constraintEnd_toStartOf="@+id/settings_disk_resize_resize_button" />
<com.google.android.material.button.MaterialButton
android:id="@+id/settings_disk_resize_resize_button"
@@ -76,6 +67,6 @@
android:layout_marginHorizontal="8dp"
app:layout_constraintTop_toTopOf="@+id/settings_disk_resize_disk_size_slider"
app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintRight_toRightOf="parent" />
+ app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/android/TerminalApp/res/menu/main_menu.xml b/android/TerminalApp/res/menu/main_menu.xml
index 9c83923..0fee90e 100644
--- a/android/TerminalApp/res/menu/main_menu.xml
+++ b/android/TerminalApp/res/menu/main_menu.xml
@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/copy_ip_addr"
- android:title="Copy the IP address"/>
- <item android:id="@+id/stop_vm"
- android:title="Stop the existing VM instance"/>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_item_settings"
- android:title="Settings"/>
-</menu>
\ No newline at end of file
+ android:icon="@drawable/ic_settings"
+ android:title="@string/action_settings"
+ app:showAsAction="always"/>
+</menu>
diff --git a/android/TerminalApp/res/values/strings.xml b/android/TerminalApp/res/values/strings.xml
index c3a3348..1cbaee8 100644
--- a/android/TerminalApp/res/values/strings.xml
+++ b/android/TerminalApp/res/values/strings.xml
@@ -16,25 +16,48 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name">Terminal</string>
- <string name="vm_creation_message">Virtual machine is booting. Please wait.</string>
- <string name="vm_stop_message">Virtual machine is stopped. Exiting.</string>
- <string name="vm_error_message">Virtual machine crashed. Exiting.</string>
+ <!-- Application name of this terminal app shown in the launcher. This app provides computer terminal to connect to virtual machine. [CHAR LIMIT=16] -->
+ <string name="app_name">Terminal</string>
+
+ <!-- Action bar icon name for the settings view CHAR LIMIT=none] -->
+ <string name="action_settings">Settings</string>
+
+ <!-- Toast message to notify that preparing terminal to start [CHAR LIMIT=none] -->
+ <string name="vm_creation_message">Preparing terminal</string>
+ <!-- Toast message to notify that terminal is stopping [CHAR LIMIT=none] -->
+ <string name="vm_stop_message">Stopping terminal</string>
+ <!-- Toast message to notify that terminal is crashed [CHAR LIMIT=none] -->
+ <string name="vm_error_message">Terminal crashed</string>
+
+ <!-- Settings memu title for resizing disk of the virtual machine. [CHAR LIMIT=none] -->
<string name="settings_disk_resize_title">Disk Resize</string>
+ <!-- Settings memu subtitle for resizing disk of the virtual machine. [CHAR LIMIT=none] -->
<string name="settings_disk_resize_sub_title">Resize / Rootfs</string>
+ <!-- Toast message after new disk size is set. [CHAR LIMIT=none] -->
<string name="settings_disk_resize_resize_message">Disk size set</string>
- <string name="settings_disk_resize_resize_gb_assigned">GB Assigned</string>
- <string name="settings_disk_resize_resize_gb_total">256 GB total</string>
+ <!-- Settings menu option description format of the current disk size. [CHAR LIMIT=none] -->
+ <string name="settings_disk_resize_resize_gb_assigned_format"><xliff:g id="assigned_size" example="10GB">%1$s</xliff:g> assigned</string>
+ <!-- Settings menu option description format of the maximum resizable disk size. [CHAR LIMIT=none] -->
+ <string name="settings_disk_resize_resize_gb_max_format"><xliff:g id="max_size" example="256GB">%1$s</xliff:g> max</string>
+ <!-- Settings menu button to cancel disk resize. [CHAR LIMIT=32] -->
<string name="settings_disk_resize_resize_cancel">Cancel</string>
+ <!-- Settings menu button to apply change that requires to restart VM (abbrev of virtual machine). [CHAR LIMIT=64] -->
<string name="settings_disk_resize_resize_restart_vm_to_apply">Restart VM to apply</string>
+ <!-- Settings menu title for 'port forwarding' [CHAR LIMIT=none] -->
<string name="settings_port_forwarding_title">Port Forwarding</string>
+ <!-- Settings menu subtitle for 'port forwarding' [CHAR LIMIT=none] -->
<string name="settings_port_forwarding_sub_title">Configure port forwarding</string>
+ <!-- Settings menu title for recoverying image [CHAR LIMIT=none] -->
<string name="settings_recovery_title">Recovery</string>
+ <!-- Settings menu subtitle for recoverying image [CHAR LIMIT=none] -->
<string name="settings_recovery_sub_title">Partition Recovery options</string>
+ <!-- Settings menu title for resetting the virtual machine image [CHAR LIMIT=none] -->
<string name="settings_recovery_reset_title">Change to Initial version</string>
+ <!-- Settings menu subtitle for resetting the virtual machine image [CHAR LIMIT=none] -->
<string name="settings_recovery_reset_sub_title">Remove all</string>
+ <!-- Toast message for reset is completed [CHAR LIMIT=none] -->
<string name="settings_recovery_reset_message">VM reset</string>
</resources>
diff --git a/android/TerminalApp/vm_config.json b/android/TerminalApp/vm_config.json
new file mode 100644
index 0000000..474e9c3
--- /dev/null
+++ b/android/TerminalApp/vm_config.json
@@ -0,0 +1,21 @@
+
+{
+ "name": "debian",
+ "disks": [
+ {
+ "image": "/data/local/tmp/image.raw",
+ "partitions": [],
+ "writable": true
+ }
+ ],
+ "protected": false,
+ "cpu_topology": "match_host",
+ "platform_version": "~1.0",
+ "memory_mib": 4096,
+ "debuggable": true,
+ "console_out": true,
+ "connect_console": true,
+ "console_input_device": "ttyS0",
+ "network": true
+}
+
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index f794239..4b69660 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -175,6 +175,10 @@
"true": ["virtualizationservice.xml"],
default: unset,
}),
+ required: select(release_flag("RELEASE_AVF_SUPPORT_CUSTOM_VM_WITH_PARAVIRTUALIZED_DEVICES"), {
+ true: ["linux_vm_setup"],
+ default: [],
+ }),
}
apex_defaults {
diff --git a/build/apex/product_packages.mk b/build/apex/product_packages.mk
index c678693..0646e67 100644
--- a/build/apex/product_packages.mk
+++ b/build/apex/product_packages.mk
@@ -73,7 +73,3 @@
$(error RELEASE_AVF_ENABLE_EARLY_VM can only be enabled in trunk_staging until b/357025924 is fixed)
endif
endif
-
-ifdef RELEASE_AVF_SUPPORT_CUSTOM_VM_WITH_PARAVIRTUALIZED_DEVICES
- PRODUCT_PACKAGES += LinuxInstallerAppStub
-endif
diff --git a/build/debian/build.sh b/build/debian/build.sh
index 97d9373..71a9d3b 100755
--- a/build/debian/build.sh
+++ b/build/debian/build.sh
@@ -103,6 +103,17 @@
wget -O - "${url}" | tar xz -C "${outdir}" --strip-components=1
}
+build_rust_binary_and_copy() {
+ pushd "$(dirname "$0")/../../guest/$1" > /dev/null
+ RUSTFLAGS="-C linker=${arch}-linux-gnu-gcc" cargo build \
+ --target "${arch}-unknown-linux-gnu" \
+ --target-dir "${workdir}/$1"
+ mkdir -p "${dst}/files/usr/local/bin/$1"
+ cp "${workdir}/$1/${arch}-unknown-linux-gnu/debug/$1" "${dst}/files/usr/local/bin/$1/AVF"
+ chmod 777 "${dst}/files/usr/local/bin/$1/AVF"
+ popd > /dev/null
+}
+
copy_android_config() {
local src="$(dirname "$0")/fai_config"
local dst="${config_space}"
@@ -116,23 +127,9 @@
wget "${url}" -O "${dst}/files/usr/local/bin/ttyd/AVF"
chmod 777 "${dst}/files/usr/local/bin/ttyd/AVF"
- pushd "$(dirname "$0")/../../guest/forwarder_guest" > /dev/null
- RUSTFLAGS="-C linker=${arch}-linux-gnu-gcc" cargo build \
- --target "${arch}-unknown-linux-gnu" \
- --target-dir "${workdir}/forwarder_guest"
- mkdir -p "${dst}/files/usr/local/bin/forwarder_guest"
- cp "${workdir}/forwarder_guest/${arch}-unknown-linux-gnu/debug/forwarder_guest" "${dst}/files/usr/local/bin/forwarder_guest/AVF"
- chmod 777 "${dst}/files/usr/local/bin/forwarder_guest/AVF"
- popd > /dev/null
-
- pushd $(dirname $0)/../../guest/ip_addr_reporter > /dev/null
- RUSTFLAGS="-C linker=aarch64-linux-gnu-gcc" cargo build \
- --target aarch64-unknown-linux-gnu \
- --target-dir ${workdir}/ip_addr_reporter
- mkdir -p ${dst}/files/usr/local/bin/ip_addr_reporter
- cp ${workdir}/ip_addr_reporter/aarch64-unknown-linux-gnu/debug/ip_addr_reporter ${dst}/files/usr/local/bin/ip_addr_reporter/AVF
- chmod 777 ${dst}/files/usr/local/bin/ip_addr_reporter/AVF
- popd > /dev/null
+ build_rust_binary_and_copy forwarder_guest
+ build_rust_binary_and_copy forwarder_guest_launcher
+ build_rust_binary_and_copy ip_addr_reporter
}
run_fai() {
diff --git a/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF b/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
index 6b932e9..0aab770 100644
--- a/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
+++ b/build/debian/fai_config/files/etc/systemd/system/ttyd.service/AVF
@@ -3,7 +3,7 @@
After=syslog.target
After=network.target
[Service]
-ExecStart=/usr/local/bin/ttyd -W screen -aAxR -S main login -f droid
+ExecStart=/usr/local/bin/ttyd --ssl --ssl-cert /etc/ttyd/server.crt --ssl-key /etc/ttyd/server.key --ssl-ca /etc/ttyd/ca.crt -W screen -aAxR -S main login -f droid
Type=simple
Restart=always
User=root
diff --git a/build/debian/fai_config/files/etc/ttyd/ca.crt/AVF b/build/debian/fai_config/files/etc/ttyd/ca.crt/AVF
new file mode 100644
index 0000000..90d8c0e
--- /dev/null
+++ b/build/debian/fai_config/files/etc/ttyd/ca.crt/AVF
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDhzCCAm+gAwIBAgIUQkvURjf6sU5aJ7oK9usHnJHsc/owDQYJKoZIhvcNAQEL
+BQAwUzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjETMBEG
+A1UECgwKQWNtZSwgSW5jLjEVMBMGA1UEAwwMQWNtZSBSb290IENBMB4XDTI0MTAx
+NDAxMjgzN1oXDTI1MTAxNDAxMjgzN1owUzELMAkGA1UEBhMCQ04xCzAJBgNVBAgM
+AkdEMQswCQYDVQQHDAJTWjETMBEGA1UECgwKQWNtZSwgSW5jLjEVMBMGA1UEAwwM
+QWNtZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtjgS
+ePtWI6xARLzM1bUMvqtWwY4ci4TzcOcfLfV5Eqbb135NSBKQ+Q2IAguc2Bl3ZVRE
+08GhQ9XJOo+mp2SUY/8+SJpCVhVlWvF6LwXd8X5pZ9GCem0FXY02kMr5ZiTs/CN2
+LZIyJKgXCT/5208on+BbiNp0pk2Pz1nDOdpxvkDJ8UKRWLwqCAEM/rcN1Lc00aln
+N/Rfi/CQE+MDAmhuy/nxr37ldqhkN+xM4bhNs1bjyVposKtbmFUY/SD3ca5CMawU
+E3l5hZ5kfua7lelEPVhvNYJcxffVO0fPNEbUKr1WsPLrnidqegcU8bml1BoCphgA
+qzoxD0rZniqMsom/vwIDAQABo1MwUTAdBgNVHQ4EFgQUZOHF7/arn8ODqEj1Wifk
+dEA5TFkwHwYDVR0jBBgwFoAUZOHF7/arn8ODqEj1WifkdEA5TFkwDwYDVR0TAQH/
+BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVets3IybnIycAtajxpJygdji/95t
+ikdyWbi8lrszC0E5bCR9XPQKnqx/svKYrEVQNihH/nZ6TlTv0f3b77+92sVlmQfl
+a3KKI6qIgcqNEO2lHYsS+cPeBmaM6WXcEPe6gEnan1i5N16B9g9ntY4lOg8Z4roR
+2lVVCCNwabyBxb5oQDsN1IDeJ7JRRZqGGduDSZTvdd36GqNhMvXQjluyJCCFd1Hv
+IwwJmAR2GMUQU8Eoa+zGzW1Inf1YJytTu8SeQ+hYy2QCG88vZigJdifmhETDDz9Q
+xQjp1SCNIBxFHY2voqtiJtfupN5pVieECZS42pbVHMIAUOk7BmNcEWnSKw==
+-----END CERTIFICATE-----
diff --git a/build/debian/fai_config/files/etc/ttyd/server.crt/AVF b/build/debian/fai_config/files/etc/ttyd/server.crt/AVF
new file mode 100644
index 0000000..b4ca829
--- /dev/null
+++ b/build/debian/fai_config/files/etc/ttyd/server.crt/AVF
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIUasfD1K/4tJHwNRXL2kdSD9VbeSwwDQYJKoZIhvcNAQEL
+BQAwUzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkdEMQswCQYDVQQHDAJTWjETMBEG
+A1UECgwKQWNtZSwgSW5jLjEVMBMGA1UEAwwMQWNtZSBSb290IENBMB4XDTI0MTAx
+NDAxMjgzOFoXDTI1MTAxNDAxMjgzOFowUDELMAkGA1UEBhMCQ04xCzAJBgNVBAgM
+AkdEMQswCQYDVQQHDAJTWjETMBEGA1UECgwKQWNtZSwgSW5jLjESMBAGA1UEAwwJ
+bG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+uVF4TP
+jUjfL8vJlECAN1rLFK8lDuOUv52VCrW7MXMfGYlA4nk1OKDjygnZIpET6I9cTfCG
+Xiwad6bU6Oqy4MZ2i338F+eERrGpkitSQ7QRqZannjBIDFxXZvJpMTJDIWNCmz+P
+K2VcvCh8im2tJA66wJogUcVmJBugNqleqxFcxPvXOdBdWBK7JYOcb4J643eLX6+D
+X6v2QTlKXfihouVC8wAzbw9HHmOVb7ono1rV7xpcFrOyBiDGVSgEteiB8l26iXA9
+fExkb0rUzHjlgvb/l8/nGAaQHd0eE+/SGd4tXvs9KHX6XJh/PI0ExTsDIBDcuVOt
+2YzXeuM6zzrKLQIDAQABo1gwVjAUBgNVHREEDTALgglsb2NhbGhvc3QwHQYDVR0O
+BBYEFHpFYqFC/AEOfWfdZmpy5YBZfgR2MB8GA1UdIwQYMBaAFGThxe/2q5/Dg6hI
+9Von5HRAOUxZMA0GCSqGSIb3DQEBCwUAA4IBAQBQspP3wo3yzcPWuFk4lRyo7zpF
+JfBBX0UU1Z0MQfIGxLC2YtRvxobRqwLcKUKQjBqUuRdukleOaVVFeXb/HI9vY3ji
+9PfUb2UJ4O3z3pdSK0EwXbkCidtUflRLvPG6dgBrXyLOqxBqA5lWR2ds5HRAMRAi
+eXfDkJTmNOAQAnPgM+35FBgmhh6axG+bUudvvVoA8ca+zW9i1R6/vblxYJ6bhmw0
+8s+uoAX6FXcZ0YFOGdhcpJmnbiRd3D0VVacjc3b9pjFOI8d3bh9pR47p0kVOaRsh
+aAG3gZhyMPOgbYceCjfzND5YhycDI+MzPo/JOYdhHGGJawoh1nP94QNPan6J
+-----END CERTIFICATE-----
diff --git a/build/debian/fai_config/files/etc/ttyd/server.key/AVF b/build/debian/fai_config/files/etc/ttyd/server.key/AVF
new file mode 100644
index 0000000..37933b2
--- /dev/null
+++ b/build/debian/fai_config/files/etc/ttyd/server.key/AVF
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDf65UXhM+NSN8v
+y8mUQIA3WssUryUO45S/nZUKtbsxcx8ZiUDieTU4oOPKCdkikRPoj1xN8IZeLBp3
+ptTo6rLgxnaLffwX54RGsamSK1JDtBGplqeeMEgMXFdm8mkxMkMhY0KbP48rZVy8
+KHyKba0kDrrAmiBRxWYkG6A2qV6rEVzE+9c50F1YErslg5xvgnrjd4tfr4Nfq/ZB
+OUpd+KGi5ULzADNvD0ceY5VvuiejWtXvGlwWs7IGIMZVKAS16IHyXbqJcD18TGRv
+StTMeOWC9v+Xz+cYBpAd3R4T79IZ3i1e+z0odfpcmH88jQTFOwMgENy5U63ZjNd6
+4zrPOsotAgMBAAECggEAARJYlD12ch5WM2aDrPOGOAtREOfP7CCwWcMiOfBP72iR
+Y9Vipxmuz16nwTJ22F7HvPsdPOUo1cFtWhim2Aqr/ZxuT4Ce9oVrk6iDwRdeuYdY
+cIhtChvJi+p0ggMcuyzp90+3AYXxynsOlCufMjSNGaqvYUsNEXnJFSgiKr7mgbIO
+J0VU1Wrquw7N58RKL+T3xEvE7uO3QpLOim2MbfRSVq/JGNxqAGw0/uxtjFs7Vtf9
+z44e/ULeYDS7zMj6cMggxQp5nfzcboGoNVUEDgYjOzqXCe4cG0n3XfN7GJhaS1ZF
+tPd8l4Ch0IrT4hs5uVFaMdFbj+er7mvmqfTVytrRmQKBgQD2kVB53EKhqxgvz2N7
+bAJglOLd6FWKsWlLMSdER0/4dRVRMIBxnYWgQ0gaRc4TM7oyKOl3MDF9jdDne5KJ
+cnfzFoH2GD6VBQRr0mFmV1UV6oHEjDJBasMo/1Vw3TJ4oZgZpYpJjrDmPWZqHUs4
+I79TdvJrNFSmk3MGVFjatLIq5QKBgQDofHpHfBeRCn2Z3OOkiAN5V53n5deZl6Jt
+lGTsrXKpEzRTre4LWZojoB9hiGjptZkXHA2HW90RiV9OHhTa8W9ZntLnOnWc5RUn
+Tzh14KupjsBQm/gE8SuqHSDx1mxTnIUo0W28d/Beecri5KfaoEY+wxZXOeQy5JFR
+ec/AhU4FqQKBgGhVzUwDnF502+M/SsVrSwY7elSUf74UnI2o2wjVdE2anc6hS3jI
+Q0cxsU0MxMrzVJLtJP2+cvLCE+ggLj3jJkbC+3N7ht/gI6LMf1KjGeoQNaFKAeoU
+l0i94xXDRBwvpQEVP5MowkprKO82PiIfXlKfPq2Gk1t5gW7oOkExvULRAoGBAK7R
+051nec0uJ06I5IE3ae1X7jyP//TWKmTeHpo+vybWcxWth3/va9H4OUC9M67ySGEx
+ThcIBA+IzirOwf31aTbqEEuiEQje1m5NyvYQ8OS6nHDBJ9qHg78S0lAoXiLtYtBT
+04HSauSQDvlY2cOzm77cMjN7K9b9Oy0aPRfW5dmpAoGAGesq4Ojky4crpi0H1O7n
+cMuIAzaPozsMx7iSrhUe69fwVFiMkEKR6ems01DmjYwPb6DtxCieaRlGbd9E8oIZ
+y6n+Uh9Qbc5sDhPMsys6NyKOv/A6rkn49/etr40f0Z5g9g/d2+qtwoAXjo3sSPuW
+7iqbruRjbKUaJKzdpIqOKD0=
+-----END PRIVATE KEY-----
diff --git a/build/debian/fai_config/scripts/AVF/10-systemd b/build/debian/fai_config/scripts/AVF/10-systemd
index 09d1bd1..6a106c6 100755
--- a/build/debian/fai_config/scripts/AVF/10-systemd
+++ b/build/debian/fai_config/scripts/AVF/10-systemd
@@ -1,7 +1,8 @@
#!/bin/bash
chmod +x $target/usr/local/bin/forwarder_guest
+chmod +x $target/usr/local/bin/forwarder_guest_launcher
chmod +x $target/usr/local/bin/ip_addr_reporter
chmod +x $target/usr/local/bin/ttyd
ln -s /etc/systemd/system/ttyd.service $target/etc/systemd/system/multi-user.target.wants/ttyd.service
-ln -s /etc/systemd/system/ip_addr_reporter.service $target/etc/systemd/system/multi-user.target.wants/ip_addr_reporter.service
\ No newline at end of file
+ln -s /etc/systemd/system/ip_addr_reporter.service $target/etc/systemd/system/multi-user.target.wants/ip_addr_reporter.service
diff --git a/build/debian/fai_config/scripts/AVF/20-useradd b/build/debian/fai_config/scripts/AVF/20-useradd
index b5887c5..9fbcd43 100755
--- a/build/debian/fai_config/scripts/AVF/20-useradd
+++ b/build/debian/fai_config/scripts/AVF/20-useradd
@@ -1,4 +1,4 @@
#!/bin/bash
-$ROOTCMD useradd -m -u 1000 -g 1000 -N -G sudo droid
+$ROOTCMD useradd -m -u 1000 -N -G sudo droid
$ROOTCMD echo 'droid ALL=(ALL) NOPASSWD:ALL' >> $target/etc/sudoers
\ No newline at end of file
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/build.sh b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh
similarity index 100%
rename from build/debian/kokoro/gcp_ubuntu_docker/build.sh
rename to build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/continuous.cfg
similarity index 83%
copy from build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
copy to build/debian/kokoro/gcp_ubuntu_docker/aarch64/continuous.cfg
index a41c032..e836eea 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
+++ b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/continuous.cfg
@@ -4,7 +4,7 @@
# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
+build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh"
action {
define_artifacts {
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/hourly.cfg
similarity index 83%
copy from build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
copy to build/debian/kokoro/gcp_ubuntu_docker/aarch64/hourly.cfg
index a41c032..e836eea 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
+++ b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/hourly.cfg
@@ -4,7 +4,7 @@
# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
+build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh"
action {
define_artifacts {
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/presubmit.cfg
similarity index 83%
copy from build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
copy to build/debian/kokoro/gcp_ubuntu_docker/aarch64/presubmit.cfg
index a41c032..e836eea 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
+++ b/build/debian/kokoro/gcp_ubuntu_docker/aarch64/presubmit.cfg
@@ -4,7 +4,7 @@
# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
+build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/aarch64/build.sh"
action {
define_artifacts {
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/hourly.cfg b/build/debian/kokoro/gcp_ubuntu_docker/hourly.cfg
deleted file mode 100644
index a41c032..0000000
--- a/build/debian/kokoro/gcp_ubuntu_docker/hourly.cfg
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- protobuffer -*-
-# proto-file: google3/devtools/kokoro/config/proto/build.proto
-# proto-message: BuildConfig
-
-# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
-# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
-
-action {
- define_artifacts {
- regex: "images.tar.gz"
- regex: "logs/**"
- }
-}
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/presubmit.cfg b/build/debian/kokoro/gcp_ubuntu_docker/presubmit.cfg
deleted file mode 100644
index a41c032..0000000
--- a/build/debian/kokoro/gcp_ubuntu_docker/presubmit.cfg
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- protobuffer -*-
-# proto-file: google3/devtools/kokoro/config/proto/build.proto
-# proto-message: BuildConfig
-
-# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
-# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
-
-action {
- define_artifacts {
- regex: "images.tar.gz"
- regex: "logs/**"
- }
-}
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh
new file mode 100644
index 0000000..ab675f0
--- /dev/null
+++ b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set -e
+
+cd "${KOKORO_ARTIFACTS_DIR}/git/avf/build/debian/"
+sudo losetup -D
+grep vmx /proc/cpuinfo || true
+sudo ./build.sh -a x86_64
+tar czvS -f ${KOKORO_ARTIFACTS_DIR}/images.tar.gz image.raw
+
+mkdir -p ${KOKORO_ARTIFACTS_DIR}/logs
+sudo cp -r /var/log/fai/* ${KOKORO_ARTIFACTS_DIR}/logs || true
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/continuous.cfg
similarity index 83%
rename from build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
rename to build/debian/kokoro/gcp_ubuntu_docker/x86_64/continuous.cfg
index a41c032..a5e8aeb 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
+++ b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/continuous.cfg
@@ -4,7 +4,7 @@
# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
+build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh"
action {
define_artifacts {
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/hourly.cfg
similarity index 83%
copy from build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
copy to build/debian/kokoro/gcp_ubuntu_docker/x86_64/hourly.cfg
index a41c032..a5e8aeb 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
+++ b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/hourly.cfg
@@ -4,7 +4,7 @@
# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
+build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh"
action {
define_artifacts {
diff --git a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/presubmit.cfg
similarity index 83%
copy from build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
copy to build/debian/kokoro/gcp_ubuntu_docker/x86_64/presubmit.cfg
index a41c032..a5e8aeb 100644
--- a/build/debian/kokoro/gcp_ubuntu_docker/continuous.cfg
+++ b/build/debian/kokoro/gcp_ubuntu_docker/x86_64/presubmit.cfg
@@ -4,7 +4,7 @@
# Location of the bash script. Should have value <git_on_borg_scm.name>/<path_from_repository_root>.
# git_on_borg_scm.name is specified in the job configuration (next section).
-build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/build.sh"
+build_file: "avf/build/debian/kokoro/gcp_ubuntu_docker/x86_64/build.sh"
action {
define_artifacts {
diff --git a/docs/vm_remote_attestation.md b/docs/vm_remote_attestation.md
index ee20591..2ee0fae 100644
--- a/docs/vm_remote_attestation.md
+++ b/docs/vm_remote_attestation.md
@@ -126,7 +126,7 @@
To support VM remote attestation, vendors must include an RKP VM marker in their
DICE certificates. This marker should be present from the early boot stage
-within the TEE and continue through to the last DICE certificate before
+within the TEE and continue through to the leaf DICE certificate before
[pvmfw][pvmfw] takes over.
![RKP VM DICE chain][rkpvm-dice-chain]
@@ -140,6 +140,20 @@
server because it will lack the RKP VM marker that pvmfw would have added in a
genuine RKP VM boot process.
+### Testing
+
+To ensure the correct implementation and usage of RKP VM markers, we've
+incorporated comprehensive checks into various xTS tests (e.g.,
+`VtsHalRemotelyProvisionedComponentTargetTest`).
+
+These tests validate the following conditions:
+
+- The RKP VM DICE chain must have a continuous presence of at least two RKP VM
+ markers, extending to the leaf DICE certificate.
+- Non-RKP VM DICE chains must not have a continuous presence of two or more RKP
+ VM markers, preventing non-RKP VM chains from being incorrectly identified as
+ RKP VM chains.
+
[pvmfw]: ../guest/pvmfw/README.md
[rkpvm-dice-chain]: img/rkpvm-dice-chain.png
diff --git a/guest/forwarder_guest_launcher/Cargo.toml b/guest/forwarder_guest_launcher/Cargo.toml
new file mode 100644
index 0000000..bf0c0ed
--- /dev/null
+++ b/guest/forwarder_guest_launcher/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "forwarder_guest_launcher"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+clap = { version = "4.5.20", features = ["derive"] }
+prost = "0.13.3"
+tokio = { version = "1.40.0", features = ["rt-multi-thread"] }
+tonic = "0.12.3"
+
+[build-dependencies]
+tonic-build = "0.12.3"
diff --git a/guest/forwarder_guest_launcher/build.rs b/guest/forwarder_guest_launcher/build.rs
new file mode 100644
index 0000000..c923747
--- /dev/null
+++ b/guest/forwarder_guest_launcher/build.rs
@@ -0,0 +1,18 @@
+// Copyright 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ tonic_build::compile_protos("../../libs/debian_service/proto/DebianService.proto")?;
+ Ok(())
+}
diff --git a/guest/forwarder_guest_launcher/src/main.rs b/guest/forwarder_guest_launcher/src/main.rs
new file mode 100644
index 0000000..4042fe5
--- /dev/null
+++ b/guest/forwarder_guest_launcher/src/main.rs
@@ -0,0 +1,50 @@
+// Copyright 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Launcher of forwarder_guest
+
+use clap::Parser;
+use debian_service::debian_service_client::DebianServiceClient;
+use debian_service::Empty;
+use tonic::transport::Endpoint;
+use tonic::Request;
+
+mod debian_service {
+ tonic::include_proto!("com.android.virtualization.vmlauncher.proto");
+}
+
+#[derive(Parser)]
+/// Flags for running command
+pub struct Args {
+ /// Host IP address
+ #[arg(long)]
+ #[arg(alias = "host")]
+ host_addr: String,
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let args = Args::parse();
+ let addr = format!("https://{}:12000", args.host_addr);
+
+ let channel = Endpoint::from_shared(addr)?.connect().await?;
+ let mut client = DebianServiceClient::new(channel);
+ let mut res_stream =
+ client.open_forwarding_request_queue(Request::new(Empty {})).await?.into_inner();
+
+ while let Some(response) = res_stream.message().await? {
+ println!("Response from the host: {:?}", response);
+ }
+ Ok(())
+}
diff --git a/guest/microdroid_manager/Android.bp b/guest/microdroid_manager/Android.bp
index 9c9a3d0..1824c20 100644
--- a/guest/microdroid_manager/Android.bp
+++ b/guest/microdroid_manager/Android.bp
@@ -43,7 +43,6 @@
"libmicrodroid_payload_config",
"libmicrodroid_uids",
"libnix",
- "libonce_cell",
"libopenssl",
"libprotobuf",
"librpcbinder_rs",
diff --git a/guest/pvmfw/Android.bp b/guest/pvmfw/Android.bp
index d0d309b..bcd3e42 100644
--- a/guest/pvmfw/Android.bp
+++ b/guest/pvmfw/Android.bp
@@ -21,7 +21,6 @@
"libfdtpci",
"liblibfdt_nostd",
"liblog_rust_nostd",
- "libonce_cell_nostd",
"libpvmfw_avb_nostd",
"libpvmfw_embedded_key",
"libpvmfw_fdt_template",
diff --git a/libs/debian_service/proto/DebianService.proto b/libs/debian_service/proto/DebianService.proto
index 5adf615..5e3286a 100644
--- a/libs/debian_service/proto/DebianService.proto
+++ b/libs/debian_service/proto/DebianService.proto
@@ -23,12 +23,20 @@
service DebianService {
rpc ReportVmIpAddr (IpAddr) returns (ReportVmIpAddrResponse) {}
+ rpc OpenForwardingRequestQueue (Empty) returns (stream ForwardingRequestItem) {}
}
+message Empty {}
+
message IpAddr {
string addr = 1;
}
message ReportVmIpAddrResponse {
- bool success = 1;
-}
\ No newline at end of file
+ bool success = 1;
+}
+
+message ForwardingRequestItem {
+ int32 guest_tcp_port = 1;
+ int32 vsock_port = 2;
+}
diff --git a/libs/dice/driver/Android.bp b/libs/dice/driver/Android.bp
index c93bd7d..baed21d 100644
--- a/libs/dice/driver/Android.bp
+++ b/libs/dice/driver/Android.bp
@@ -22,7 +22,6 @@
"liblibc",
"liblog_rust",
"libnix",
- "libonce_cell",
"libopenssl",
"libthiserror",
"libserde_cbor",
diff --git a/libs/libvmbase/src/entry.rs b/libs/libvmbase/src/entry.rs
index 99f28fc..f442a32 100644
--- a/libs/libvmbase/src/entry.rs
+++ b/libs/libvmbase/src/entry.rs
@@ -56,8 +56,7 @@
/// This is the entry point to the Rust code, called from the binary entry point in `entry.S`.
#[no_mangle]
extern "C" fn rust_entry(x0: u64, x1: u64, x2: u64, x3: u64) -> ! {
- // SAFETY: Only called once, from here, and inaccessible to client code.
- unsafe { heap::init() };
+ heap::init();
if try_console_init().is_err() {
// Don't panic (or log) here to avoid accessing the console.
diff --git a/libs/libvmbase/src/heap.rs b/libs/libvmbase/src/heap.rs
index 99c06aa..3a4e198 100644
--- a/libs/libvmbase/src/heap.rs
+++ b/libs/libvmbase/src/heap.rs
@@ -22,39 +22,78 @@
use core::ffi::c_void;
use core::mem;
use core::num::NonZeroUsize;
+use core::ops::Range;
use core::ptr;
use core::ptr::NonNull;
use buddy_system_allocator::LockedHeap;
+use spin::{
+ mutex::{SpinMutex, SpinMutexGuard},
+ Once,
+};
/// Configures the size of the global allocator.
#[macro_export]
macro_rules! configure_heap {
($len:expr) => {
- static mut __HEAP_ARRAY: [u8; $len] = [0; $len];
- #[export_name = "HEAP"]
- // SAFETY: HEAP will only be accessed once as mut, from init().
- static mut __HEAP: &'static mut [u8] = unsafe { &mut __HEAP_ARRAY };
+ static __HEAP: $crate::heap::HeapArray<{ $len }> = $crate::heap::HeapArray::new();
+ #[export_name = "get_heap"]
+ fn __get_heap() -> &'static mut [u8] {
+ __HEAP.get()
+ }
};
}
+/// An array to be used as a heap.
+///
+/// This should be stored in a static variable to have the appropriate lifetime.
+pub struct HeapArray<const SIZE: usize> {
+ array: SpinMutex<[u8; SIZE]>,
+}
+
+impl<const SIZE: usize> HeapArray<SIZE> {
+ /// Creates a new empty heap array.
+ #[allow(clippy::new_without_default)]
+ pub const fn new() -> Self {
+ Self { array: SpinMutex::new([0; SIZE]) }
+ }
+
+ /// Gets the heap as a slice.
+ ///
+ /// Panics if called more than once.
+ pub fn get(&self) -> &mut [u8] {
+ SpinMutexGuard::leak(self.array.try_lock().expect("Page heap was already taken"))
+ .as_mut_slice()
+ }
+}
+
extern "Rust" {
- /// Slice used by the global allocator, configured using configure_heap!().
- static mut HEAP: &'static mut [u8];
+ /// Gets slice used by the global allocator, configured using configure_heap!().
+ ///
+ /// Panics if called more than once.
+ fn get_heap() -> &'static mut [u8];
}
#[global_allocator]
static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
+/// The range of addresses used for the heap.
+static HEAP_RANGE: Once<Range<usize>> = Once::new();
+
/// Initialize the global allocator.
///
-/// # Safety
-///
-/// Must be called no more than once.
-pub(crate) unsafe fn init() {
- // SAFETY: Nothing else accesses this memory, and we hand it over to the heap to manage and
- // never touch it again. The heap is locked, so there cannot be any races.
- let (start, size) = unsafe { (HEAP.as_mut_ptr() as usize, HEAP.len()) };
+/// Panics if called more than once.
+pub(crate) fn init() {
+ // SAFETY: This is in fact a safe Rust function.
+ let heap = unsafe { get_heap() };
+
+ HEAP_RANGE.call_once(|| {
+ let range = heap.as_ptr_range();
+ range.start as usize..range.end as usize
+ });
+
+ let start = heap.as_mut_ptr() as usize;
+ let size = heap.len();
let mut heap = HEAP_ALLOCATOR.lock();
// SAFETY: We are supplying a valid memory range, and we only do this once.
@@ -107,10 +146,9 @@
/// errors.
unsafe extern "C" fn free(ptr: *mut c_void) {
let Some(ptr) = NonNull::new(ptr) else { return };
- // SAFETY: The contents of the HEAP slice may change, but the address range never does.
- let heap_range = unsafe { HEAP.as_ptr_range() };
+ let heap_range = HEAP_RANGE.get().expect("free called before heap was initialised");
assert!(
- heap_range.contains(&(ptr.as_ptr() as *const u8)),
+ heap_range.contains(&(ptr.as_ptr() as usize)),
"free() called on a pointer that is not part of the HEAP: {ptr:?}"
);
// SAFETY: ptr is non-null and was allocated by allocate, which prepends a correctly aligned
diff --git a/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java b/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java
index 241eef4..998389b 100644
--- a/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java
+++ b/libs/service-virtualization/src/com/android/system/virtualmachine/VirtualizationSystemService.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.LinkAddress;
import android.net.TetheringManager;
import android.net.TetheringManager.StartTetheringCallback;
import android.net.TetheringManager.TetheringRequest;
@@ -157,8 +158,11 @@
@Override
public void enableVmTethering() {
+ LinkAddress local = new LinkAddress("192.168.0.1/24");
+ LinkAddress client = new LinkAddress("192.168.0.2/24");
final TetheringRequest tr =
new TetheringRequest.Builder(TetheringManager.TETHERING_VIRTUAL)
+ .setStaticIpv4Addresses(local, client)
.setConnectivityScope(TetheringManager.CONNECTIVITY_SCOPE_GLOBAL)
.build();
diff --git a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
index 2f7666a..ccc0ed6 100644
--- a/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
+++ b/libs/vm_launcher_lib/java/com/android/virtualization/vmlauncher/DebianServiceImpl.java
@@ -19,6 +19,8 @@
import android.util.Log;
import com.android.virtualization.vmlauncher.proto.DebianServiceGrpc;
+import com.android.virtualization.vmlauncher.proto.Empty;
+import com.android.virtualization.vmlauncher.proto.ForwardingRequestItem;
import com.android.virtualization.vmlauncher.proto.IpAddr;
import com.android.virtualization.vmlauncher.proto.ReportVmIpAddrResponse;
@@ -43,6 +45,16 @@
responseObserver.onCompleted();
}
+ @Override
+ public void openForwardingRequestQueue(
+ Empty request, StreamObserver<ForwardingRequestItem> responseObserver) {
+ Log.d(DebianServiceImpl.TAG, "OpenForwardingRequestQueue");
+
+ // TODO(b/340126051): Bring information from forwarder_host.
+
+ responseObserver.onCompleted();
+ }
+
protected interface DebianServiceCallback {
void onIpAddressAvailable(String ipAddr);
}
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 2d55d66..ffcf338 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -36,6 +36,7 @@
import android.cts.statsdatom.lib.ReportUtils;
import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.PropertyUtil;
import com.android.compatibility.common.util.VsrTest;
import com.android.microdroid.test.common.ProcessUtil;
import com.android.microdroid.test.host.CommandRunner;
@@ -437,9 +438,8 @@
@VsrTest(requirements = {"VSR-7.1-001.008"})
public void UpgradedPackageIsAcceptedWithSecretkeeper() throws Exception {
// Preconditions
- assumeVmTypeSupported(true);
- assumeUpdatableVmSupported();
-
+ assumeVmTypeSupported(true); // Non-protected VMs may not support upgrades
+ ensureUpdatableVmSupported();
getDevice().uninstallPackage(PACKAGE_NAME);
getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ true);
ensureProtectedMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
@@ -1392,10 +1392,16 @@
&& device.doesFileExist("/sys/bus/platform/drivers/vfio-platform"));
}
- private void assumeUpdatableVmSupported() throws DeviceNotAvailableException {
- assumeTrue(
- "This test is only applicable if if Updatable VMs are supported",
- isUpdatableVmSupported());
+ private void ensureUpdatableVmSupported() throws DeviceNotAvailableException {
+ if (PropertyUtil.isVendorApiLevelAtLeast(getAndroidDevice(), 202504)) {
+ assertTrue(
+ "Missing Updatable VM support, have you declared Secretkeeper interface?",
+ isUpdatableVmSupported());
+ } else {
+ assumeTrue(
+ "Vendor API lower than 202504 may not support Updatable VM",
+ isUpdatableVmSupported());
+ }
}
private TestDevice getAndroidDevice() {