Merge "Remove search bar in the settings page" into main
diff --git a/android/TerminalApp/generate_assets.sh b/android/TerminalApp/generate_assets.sh
index ff7444e..4001bfd 100755
--- a/android/TerminalApp/generate_assets.sh
+++ b/android/TerminalApp/generate_assets.sh
@@ -6,14 +6,15 @@
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 "$1" ${tempdir}
-tar czvS -f images.tar.gz $(basename $1)
+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}
diff --git a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
index bd35f51..2a87348 100644
--- a/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
+++ b/android/TerminalApp/java/com/android/virtualization/terminal/MainActivity.java
@@ -15,8 +15,6 @@
*/
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;
@@ -346,17 +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", VM_ADDR));
- return true;
- } else if (id == R.id.stop_vm) {
- VmLauncherServices.stopVmLauncherService(this);
- mWebView.setVisibility(View.INVISIBLE);
- 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;
@@ -388,7 +376,6 @@
}
private void startVm() {
- Toast.makeText(this, R.string.vm_creation_message, Toast.LENGTH_SHORT).show();
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/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 736b45a..7baaf5c 100644
--- a/android/TerminalApp/res/layout/activity_headless.xml
+++ b/android/TerminalApp/res/layout/activity_headless.xml
@@ -12,15 +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"
- android:visibility="invisible"/>
+ <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/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 6ae5b7b..1cbaee8 100644
--- a/android/TerminalApp/res/values/strings.xml
+++ b/android/TerminalApp/res/values/strings.xml
@@ -20,6 +20,9 @@
<!-- 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] -->
@@ -33,10 +36,10 @@
<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>
- <!-- Settings menu option description for the current disk size, followed by a text box with the actual number [CHAR LIMIT=none] -->
- <string name="settings_disk_resize_resize_gb_assigned">GB Assigned</string>
- <!-- Settings menu option description for the maximum resizable disk size. [CHAR LIMIT=none] -->
- <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] -->
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/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/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() {