Merge "Reimplement ApkVerityTest" into main
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index ea21d51..ab669cc 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -48,9 +48,6 @@
"name":"CarrierAppIntegrationTestCases"
},
{
- "name":"ApkVerityTest"
- },
- {
"name":"CtsSilentUpdateHostTestCases"
},
{
diff --git a/core/java/com/android/internal/security/TEST_MAPPING b/core/java/com/android/internal/security/TEST_MAPPING
index 2d598dc..0af3b03 100644
--- a/core/java/com/android/internal/security/TEST_MAPPING
+++ b/core/java/com/android/internal/security/TEST_MAPPING
@@ -12,10 +12,6 @@
]
},
{
- "name": "ApkVerityTest",
- "file_patterns": ["VerityUtils\\.java"]
- },
- {
"name": "UpdatableSystemFontTest",
"file_patterns": ["VerityUtils\\.java"]
},
@@ -23,5 +19,11 @@
"name": "CtsApkVerityInstallHostTestCases",
"file_patterns": ["VerityUtils\\.java"]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "FsVerityTest",
+ "file_patterns": ["VerityUtils\\.java"]
+ }
]
}
diff --git a/tests/ApkVerityTest/Android.bp b/tests/ApkVerityTest/Android.bp
index f026bea..53606a3 100644
--- a/tests/ApkVerityTest/Android.bp
+++ b/tests/ApkVerityTest/Android.bp
@@ -22,7 +22,7 @@
}
java_test_host {
- name: "ApkVerityTest",
+ name: "FsVerityTest",
srcs: ["src/**/*.java"],
libs: [
"tradefed",
@@ -30,8 +30,10 @@
"compatibility-host-util",
],
static_libs: [
+ "android.security.flags-aconfig-java-host",
"block_device_writer_jar",
"frameworks-base-hostutils",
+ "flag-junit-host",
],
test_suites: [
"general-tests",
@@ -41,14 +43,6 @@
"block_device_writer",
],
data: [
- ":ApkVerityTestCertDer",
- ":ApkVerityTestApp",
- ":ApkVerityTestAppFsvSig",
- ":ApkVerityTestAppDm",
- ":ApkVerityTestAppDmFsvSig",
- ":ApkVerityTestAppSplit",
- ":ApkVerityTestAppSplitFsvSig",
- ":ApkVerityTestAppSplitDm",
- ":ApkVerityTestAppSplitDmFsvSig",
+ ":FsVerityTestApp",
],
}
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/ApkVerityTest/AndroidTest.xml
index 4487cef..49cbde0 100644
--- a/tests/ApkVerityTest/AndroidTest.xml
+++ b/tests/ApkVerityTest/AndroidTest.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="APK fs-verity integration/regression test">
+<configuration description="fs-verity end-to-end test">
<option name="test-suite-tag" value="apct" />
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController">
@@ -24,19 +24,9 @@
<!-- This test requires root to write against block device. -->
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
- <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
- <!-- Disable package verifier prevents it holding the target APK's fd that prevents cache
- eviction. -->
- <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
- <option name="restore-settings" value="true" />
-
- <!-- Skip in order to prevent reboot that confuses the test flow. -->
- <option name="force-skip-system-props" value="true" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="ApkVerityTestCert.der->/data/local/tmp/ApkVerityTestCert.der" />
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="FsVerityTestApp.apk"/>
+ <option name="cleanup-apks" value="true"/>
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
@@ -48,9 +38,7 @@
<option name="push" value="block_device_writer->/data/local/tmp/block_device_writer" />
</target_preparer>
- <!-- Skip on HWASan. TODO(b/232288278): Re-enable -->
- <object type="module_controller" class="com.android.tradefed.testtype.suite.module.SkipHWASanModuleController" />
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
- <option name="jar" value="ApkVerityTest.jar" />
+ <option name="jar" value="FsVerityTest.jar" />
</test>
</configuration>
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml b/tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml
deleted file mode 100644
index 3f1a4f3..0000000
--- a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/AndroidManifest.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2019 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.apkverity"
- android:isFeatureSplit="true"
- split="feature_x">
- <application>
- <activity android:name=".feature_x.DummyActivity"/>
- </application>
-</manifest>
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/src/com/android/apkverity/feature_x/DummyActivity.java b/tests/ApkVerityTest/ApkVerityTestApp/feature_split/src/com/android/apkverity/feature_x/DummyActivity.java
deleted file mode 100644
index fe91260..0000000
--- a/tests/ApkVerityTest/ApkVerityTestApp/feature_split/src/com/android/apkverity/feature_x/DummyActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package com.android.apkverity.feature_x;
-
-import android.app.Activity;
-
-/** Placeholder class just to generate some dex */
-public class DummyActivity extends Activity {}
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/src/com/android/apkverity/DummyActivity.java b/tests/ApkVerityTest/ApkVerityTestApp/src/com/android/apkverity/DummyActivity.java
deleted file mode 100644
index a7bd771..0000000
--- a/tests/ApkVerityTest/ApkVerityTestApp/src/com/android/apkverity/DummyActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package com.android.apkverity;
-
-import android.app.Activity;
-
-/** Placeholder class just to generate some dex */
-public class DummyActivity extends Activity {}
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp b/tests/ApkVerityTest/FsVerityTestApp/Android.bp
similarity index 74%
rename from tests/ApkVerityTest/ApkVerityTestApp/Android.bp
rename to tests/ApkVerityTest/FsVerityTestApp/Android.bp
index adf8f9f..43da3ff 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/Android.bp
+++ b/tests/ApkVerityTest/FsVerityTestApp/Android.bp
@@ -22,17 +22,8 @@
}
android_test_helper_app {
- name: "ApkVerityTestApp",
- manifest: "AndroidManifest.xml",
- srcs: ["src/**/*.java"],
-}
-
-android_test_helper_app {
- name: "ApkVerityTestAppSplit",
- manifest: "feature_split/AndroidManifest.xml",
- srcs: ["src/**/*.java"],
- aaptflags: [
- "--custom-package com.android.apkverity.feature_x",
- "--package-id 0x80",
- ],
+ name: "FsVerityTestApp",
+ manifest: "AndroidManifest.xml",
+ srcs: ["src/**/*.java"],
+ static_libs: ["compatibility-device-util-axt"],
}
diff --git a/tests/ApkVerityTest/ApkVerityTestApp/AndroidManifest.xml b/tests/ApkVerityTest/FsVerityTestApp/AndroidManifest.xml
similarity index 75%
rename from tests/ApkVerityTest/ApkVerityTestApp/AndroidManifest.xml
rename to tests/ApkVerityTest/FsVerityTestApp/AndroidManifest.xml
index 0b3ff77..42fe49b 100644
--- a/tests/ApkVerityTest/ApkVerityTestApp/AndroidManifest.xml
+++ b/tests/ApkVerityTest/FsVerityTestApp/AndroidManifest.xml
@@ -16,8 +16,12 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.apkverity">
+ package="com.android.fsverity">
<application>
<activity android:name=".DummyActivity"/>
</application>
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.fsverity"
+ android:label="Helper app of fs-verity test">
+ </instrumentation>/>
</manifest>
diff --git a/tests/ApkVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java b/tests/ApkVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
new file mode 100644
index 0000000..2ed4fec
--- /dev/null
+++ b/tests/ApkVerityTest/FsVerityTestApp/src/com/android/fsverity/Helper.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package com.android.fsverity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import android.content.Context;
+import android.security.FileIntegrityManager;
+import android.util.Log;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Test;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Test helper that works with the host-side test to set up a test file, and to verify fs-verity
+ * verification is done expectedly.
+ */
+public class Helper {
+ private static final String TAG = "FsVerityTest";
+
+ private static final String FILENAME = "test.file";
+
+ private static final long BLOCK_SIZE = 4096;
+
+ @Test
+ public void prepareTest() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+ android.os.Bundle testArgs = InstrumentationRegistry.getArguments();
+
+ String basename = testArgs.getString("basename");
+ context.deleteFile(basename);
+
+ assertThat(testArgs).isNotNull();
+ int fileSize = Integer.parseInt(testArgs.getString("fileSize"));
+ Log.d(TAG, "Preparing test file with size " + fileSize);
+
+ byte[] bytes = new byte[8192];
+ Arrays.fill(bytes, (byte) '1');
+ try (FileOutputStream os = context.openFileOutput(basename, Context.MODE_PRIVATE)) {
+ for (int i = 0; i < fileSize; i += bytes.length) {
+ if (i + bytes.length > fileSize) {
+ os.write(bytes, 0, fileSize % bytes.length);
+ } else {
+ os.write(bytes);
+ }
+ }
+ }
+
+ // Enable fs-verity
+ FileIntegrityManager fim = context.getSystemService(FileIntegrityManager.class);
+ fim.setupFsVerity(context.getFileStreamPath(basename));
+ }
+
+ @Test
+ public void verifyFileRead() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+
+ // Collect indices that the backing blocks are supposed to be corrupted.
+ android.os.Bundle testArgs = InstrumentationRegistry.getArguments();
+ assertThat(testArgs).isNotNull();
+ String filePath = testArgs.getString("filePath");
+ String csv = testArgs.getString("brokenBlockIndicesCsv");
+ Log.d(TAG, "brokenBlockIndicesCsv: " + csv);
+ String[] strings = csv.split(",");
+ var corrupted = new ArrayList(strings.length);
+ for (int i = 0; i < strings.length; i++) {
+ corrupted.add(Integer.parseInt(strings[i]));
+ }
+
+ // Expect the read to succeed or fail per the prior.
+ try (var file = new RandomAccessFile(filePath, "r")) {
+ long total_blocks = (file.length() + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ for (int i = 0; i < (int) total_blocks; i++) {
+ file.seek(i * BLOCK_SIZE);
+ if (corrupted.contains(i)) {
+ Log.d(TAG, "Expecting read at block #" + i + " to fail");
+ assertThrows(IOException.class, () -> file.read());
+ } else {
+ assertThat(file.readByte()).isEqualTo('1');
+ }
+ }
+ }
+ }
+}
diff --git a/tests/ApkVerityTest/TEST_MAPPING b/tests/ApkVerityTest/TEST_MAPPING
index 72d9614..39944be 100644
--- a/tests/ApkVerityTest/TEST_MAPPING
+++ b/tests/ApkVerityTest/TEST_MAPPING
@@ -1,11 +1,11 @@
{
- "presubmit": [
+ "postsubmit": [
{
- "name": "ApkVerityTest"
+ "name": "FsVerityTest"
},
// nextgen test only runs during postsubmit.
{
- "name": "ApkVerityTest",
+ "name": "FsVerityTest",
"keywords": ["nextgen"]
}
]
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
deleted file mode 100644
index 482f633..0000000
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
+++ /dev/null
@@ -1,579 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package com.android.apkverity;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.platform.test.annotations.RootPermissionTest;
-
-import com.android.blockdevicewriter.BlockDeviceWriter;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This test makes sure app installs with fs-verity signature, and on-access verification works.
- *
- * <p>When an app is installed, all or none of the files should have their corresponding .fsv_sig
- * signature file. Otherwise, install will fail.
- *
- * <p>Once installed, file protected by fs-verity is verified by kernel every time a block is loaded
- * from disk to memory. The file is immutable by design, enforced by filesystem.
- *
- * <p>In order to make sure a block of the file is readable only if the underlying block on disk
- * stay intact, the test needs to bypass the filesystem and tampers with the corresponding physical
- * address against the block device.
- *
- * <p>Requirements to run this test:
- * <ul>
- * <li>Device is rootable</li>
- * <li>The filesystem supports fs-verity</li>
- * <li>The feature flag is enabled</li>
- * </ul>
- */
-@RootPermissionTest
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class ApkVerityTest extends BaseHostJUnit4Test {
- private static final String TARGET_PACKAGE = "com.android.apkverity";
-
- private static final String BASE_APK = "ApkVerityTestApp.apk";
- private static final String BASE_APK_DM = "ApkVerityTestApp.dm";
- private static final String SPLIT_APK = "ApkVerityTestAppSplit.apk";
- private static final String SPLIT_APK_DM = "ApkVerityTestAppSplit.dm";
-
- private static final String INSTALLED_BASE_APK = "base.apk";
- private static final String INSTALLED_BASE_DM = "base.dm";
- private static final String INSTALLED_SPLIT_APK = "split_feature_x.apk";
- private static final String INSTALLED_SPLIT_DM = "split_feature_x.dm";
- private static final String INSTALLED_BASE_APK_FSV_SIG = "base.apk.fsv_sig";
- private static final String INSTALLED_BASE_DM_FSV_SIG = "base.dm.fsv_sig";
- private static final String INSTALLED_SPLIT_APK_FSV_SIG = "split_feature_x.apk.fsv_sig";
- private static final String INSTALLED_SPLIT_DM_FSV_SIG = "split_feature_x.dm.fsv_sig";
-
- private static final String DAMAGING_EXECUTABLE = "/data/local/tmp/block_device_writer";
- private static final String CERT_PATH = "/data/local/tmp/ApkVerityTestCert.der";
-
- /** Only 4K page is supported by fs-verity currently. */
- private static final int FSVERITY_PAGE_SIZE = 4096;
-
- private ITestDevice mDevice;
- private boolean mDmRequireFsVerity;
-
- @Before
- public void setUp() throws DeviceNotAvailableException {
- mDevice = getDevice();
- mDmRequireFsVerity = "true".equals(
- mDevice.getProperty("pm.dexopt.dm.require_fsverity"));
-
- expectRemoteCommandToSucceed("cmd file_integrity append-cert " + CERT_PATH);
- uninstallPackage(TARGET_PACKAGE);
- }
-
- @After
- public void tearDown() throws DeviceNotAvailableException {
- expectRemoteCommandToSucceed("cmd file_integrity remove-last-cert");
- uninstallPackage(TARGET_PACKAGE);
- }
-
- @Test
- public void testFsverityKernelSupports() throws DeviceNotAvailableException {
- ITestDevice.MountPointInfo mountPoint = mDevice.getMountPointInfo("/data");
- expectRemoteCommandToSucceed("test -f /sys/fs/" + mountPoint.type + "/features/verity");
- }
-
- @Test
- public void testInstallBase() throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity(INSTALLED_BASE_APK);
- }
-
- @Test
- public void testInstallBaseWithWrongSignature()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .addFile(SPLIT_APK_DM + ".fsv_sig",
- BASE_APK + ".fsv_sig")
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallBaseWithSplit()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(SPLIT_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_SPLIT_APK);
- }
-
- @Test
- public void testInstallBaseWithDm() throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM);
- }
-
- @Test
- public void testInstallEverything() throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFileAndSignature(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG,
- INSTALLED_SPLIT_DM,
- INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM);
- }
-
- @Test
- public void testInstallSplitOnly()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
-
- new InstallMultiple()
- .inheritFrom(TARGET_PACKAGE)
- .addFileAndSignature(SPLIT_APK)
- .run();
-
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_APK,
- INSTALLED_SPLIT_APK);
- }
-
- @Test
- public void testInstallSplitOnlyMissingSignature()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
-
- new InstallMultiple()
- .inheritFrom(TARGET_PACKAGE)
- .addFile(SPLIT_APK)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallSplitOnlyWithoutBaseSignature()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(INSTALLED_BASE_APK);
-
- new InstallMultiple()
- .inheritFrom(TARGET_PACKAGE)
- .addFileAndSignature(SPLIT_APK)
- .run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_APK_FSV_SIG);
- }
-
- @Test
- public void testInstallOnlyDmHasFsvSig()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM,
- INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(
- INSTALLED_BASE_DM,
- INSTALLED_SPLIT_DM);
- }
-
- @Test
- public void testInstallDmWithoutFsvSig_Base()
- throws DeviceNotAvailableException, FileNotFoundException {
- InstallMultiple installer = new InstallMultiple()
- .addFile(BASE_APK)
- .addFile(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM);
- if (mDmRequireFsVerity) {
- installer.runExpectingFailure();
- } else {
- installer.run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM,
- INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity(INSTALLED_SPLIT_DM);
- }
- }
-
- @Test
- public void testInstallDmWithoutFsvSig_Split()
- throws DeviceNotAvailableException, FileNotFoundException {
- InstallMultiple installer = new InstallMultiple()
- .addFile(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFile(SPLIT_APK_DM);
- if (mDmRequireFsVerity) {
- installer.runExpectingFailure();
- } else {
- installer.run();
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_DM,
- INSTALLED_BASE_DM_FSV_SIG,
- INSTALLED_SPLIT_APK,
- INSTALLED_SPLIT_DM);
- verifyInstalledFilesHaveFsverity(INSTALLED_BASE_DM);
- }
- }
-
- @Test
- public void testInstallSomeApkIsMissingFsvSig_Base()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFile(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallSomeApkIsMissingFsvSig_Split()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .addFileAndSignature(BASE_APK_DM)
- .addFileAndSignature(SPLIT_APK)
- .addFileAndSignature(SPLIT_APK_DM)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallBaseWithFsvSigThenSplitWithout()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFileAndSignature(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(
- INSTALLED_BASE_APK,
- INSTALLED_BASE_APK_FSV_SIG);
-
- new InstallMultiple()
- .addFile(SPLIT_APK)
- .runExpectingFailure();
- }
-
- @Test
- public void testInstallBaseWithoutFsvSigThenSplitWith()
- throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
- .addFile(BASE_APK)
- .run();
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- verifyInstalledFiles(INSTALLED_BASE_APK);
-
- new InstallMultiple()
- .addFileAndSignature(SPLIT_APK)
- .runExpectingFailure();
- }
-
- @Test
- public void testFsverityFileIsImmutableAndReadable() throws DeviceNotAvailableException {
- new InstallMultiple().addFileAndSignature(BASE_APK).run();
- String apkPath = getApkPath(TARGET_PACKAGE);
-
- assertNotNull(getDevice().getAppPackageInfo(TARGET_PACKAGE));
- expectRemoteCommandToFail("echo -n '' >> " + apkPath);
- expectRemoteCommandToSucceed("cat " + apkPath + " > /dev/null");
- }
-
- @Test
- public void testFsverityFailToReadModifiedBlockAtFront() throws DeviceNotAvailableException {
- new InstallMultiple().addFileAndSignature(BASE_APK).run();
- String apkPath = getApkPath(TARGET_PACKAGE);
-
- long apkSize = getFileSizeInBytes(apkPath);
- long offsetFirstByte = 0;
-
- // The first two pages should be both readable at first.
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, offsetFirstByte));
- if (apkSize > offsetFirstByte + FSVERITY_PAGE_SIZE) {
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath,
- offsetFirstByte + FSVERITY_PAGE_SIZE));
- }
-
- // Damage the file directly against the block device.
- damageFileAgainstBlockDevice(apkPath, offsetFirstByte);
-
- // Expect actual read from disk to fail but only at damaged page.
- expectReadFromBlockDeviceToFail(apkPath, offsetFirstByte);
- if (apkSize > offsetFirstByte + FSVERITY_PAGE_SIZE) {
- long lastByteOfTheSamePage =
- offsetFirstByte % FSVERITY_PAGE_SIZE + FSVERITY_PAGE_SIZE - 1;
- assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, lastByteOfTheSamePage));
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, lastByteOfTheSamePage + 1));
- }
- }
-
- @Test
- public void testFsverityFailToReadModifiedBlockAtBack() throws DeviceNotAvailableException {
- new InstallMultiple().addFileAndSignature(BASE_APK).run();
- String apkPath = getApkPath(TARGET_PACKAGE);
-
- long apkSize = getFileSizeInBytes(apkPath);
- long offsetOfLastByte = apkSize - 1;
-
- // The first two pages should be both readable at first.
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, offsetOfLastByte));
- if (offsetOfLastByte - FSVERITY_PAGE_SIZE > 0) {
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath,
- offsetOfLastByte - FSVERITY_PAGE_SIZE));
- }
-
- // Damage the file directly against the block device.
- damageFileAgainstBlockDevice(apkPath, offsetOfLastByte);
-
- // Expect actual read from disk to fail but only at damaged page.
- expectReadFromBlockDeviceToFail(apkPath, offsetOfLastByte);
- if (offsetOfLastByte - FSVERITY_PAGE_SIZE > 0) {
- long firstByteOfTheSamePage = offsetOfLastByte - offsetOfLastByte % FSVERITY_PAGE_SIZE;
- assertFalse(BlockDeviceWriter.canReadByte(mDevice, apkPath, firstByteOfTheSamePage));
- assertTrue(BlockDeviceWriter.canReadByte(mDevice, apkPath, firstByteOfTheSamePage - 1));
- }
- }
-
- private void verifyInstalledFilesHaveFsverity(String... filenames)
- throws DeviceNotAvailableException {
- // Verify that all files are protected by fs-verity
- String apkPath = getApkPath(TARGET_PACKAGE);
- String appDir = apkPath.substring(0, apkPath.lastIndexOf("/"));
- long kTargetOffset = 0;
- for (String basename : filenames) {
- String path = appDir + "/" + basename;
- damageFileAgainstBlockDevice(path, kTargetOffset);
-
- expectReadFromBlockDeviceToFail(path, kTargetOffset);
- }
- }
-
- private void expectReadFromBlockDeviceToFail(String readPath, long offset)
- throws DeviceNotAvailableException {
- // Retry is sometimes needed to pass the test. Package manager may have FD leaks
- // (see b/122744005 as example) that prevents the file in question to be evicted
- // from filesystem cache. Forcing GC workarounds the problem.
- int retry = 5;
- for (; retry > 0; retry--) {
- BlockDeviceWriter.dropCaches(mDevice);
- if (!BlockDeviceWriter.canReadByte(mDevice, readPath, offset)) {
- break;
- }
- try {
- String openFiles = expectRemoteCommandToSucceed("lsof " + readPath);
- CLog.d("lsof: " + openFiles);
- Thread.sleep(1000);
- forceGCOnOpenFilesProcess(getOpenFilesPIDs(openFiles));
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return;
- }
- }
- assertTrue("Read from " + readPath + " should fail", retry > 0);
- }
-
- /**
- * This is a helper method that parses the lsof output to get PIDs of process holding FD.
- * Here is an example output of lsof. This method extracts the second columns(PID).
- *
- * Example lsof output:
- * COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
- * .example.app 1063 u0_a38 mem REG 253,6 8599 12826 example.apk
- * .example.app 1063 u0_a38 99r REG 253,6 8599 12826 example.apk
- */
- private Set<String> getOpenFilesPIDs(String lsof) {
- Set<String> openFilesPIDs = new HashSet<>();
- String[] lines = lsof.split("\n");
- for (int i = 1; i < lines.length; i++) {
- openFilesPIDs.add(lines[i].split("\\s+")[1]);
- }
- return openFilesPIDs;
- }
-
- /**
- * This is a helper method that forces GC on processes given their PIDs.
- * That is to execute shell command "kill -10" on PIDs.
- */
- private void forceGCOnOpenFilesProcess(Set<String> openFilesPIDs)
- throws DeviceNotAvailableException {
- for (String openFilePID : openFilesPIDs) {
- mDevice.executeShellV2Command("kill -10 " + openFilePID);
- }
- }
-
- private void verifyInstalledFiles(String... filenames) throws DeviceNotAvailableException {
- String apkPath = getApkPath(TARGET_PACKAGE);
- String appDir = apkPath.substring(0, apkPath.lastIndexOf("/"));
- // Exclude directories since we only care about files.
- HashSet<String> actualFiles = new HashSet<>(Arrays.asList(
- expectRemoteCommandToSucceed("ls -p " + appDir + " | grep -v '/'").split("\n")));
-
- HashSet<String> expectedFiles = new HashSet<>(Arrays.asList(filenames));
- assertEquals(expectedFiles, actualFiles);
- }
-
- private void damageFileAgainstBlockDevice(String path, long offsetOfTargetingByte)
- throws DeviceNotAvailableException {
- assertTrue(path.startsWith("/data/"));
- ITestDevice.MountPointInfo mountPoint = mDevice.getMountPointInfo("/data");
- ArrayList<String> args = new ArrayList<>();
- args.add(DAMAGING_EXECUTABLE);
- if ("f2fs".equals(mountPoint.type)) {
- args.add("--use-f2fs-pinning");
- }
- args.add(mountPoint.filesystem);
- args.add(path);
- args.add(Long.toString(offsetOfTargetingByte));
- expectRemoteCommandToSucceed(String.join(" ", args));
- }
-
- private String getApkPath(String packageName) throws DeviceNotAvailableException {
- String line = expectRemoteCommandToSucceed("pm path " + packageName + " | grep base.apk");
- int index = line.trim().indexOf(":");
- assertTrue(index >= 0);
- return line.substring(index + 1);
- }
-
- private long getFileSizeInBytes(String packageName) throws DeviceNotAvailableException {
- return Long.parseLong(expectRemoteCommandToSucceed("stat -c '%s' " + packageName).trim());
- }
-
- private String expectRemoteCommandToSucceed(String cmd) throws DeviceNotAvailableException {
- CommandResult result = mDevice.executeShellV2Command(cmd);
- assertEquals("`" + cmd + "` failed: " + result.getStderr(), CommandStatus.SUCCESS,
- result.getStatus());
- return result.getStdout();
- }
-
- private void expectRemoteCommandToFail(String cmd) throws DeviceNotAvailableException {
- CommandResult result = mDevice.executeShellV2Command(cmd);
- assertTrue("Unexpected success from `" + cmd + "`: " + result.getStderr(),
- result.getStatus() != CommandStatus.SUCCESS);
- }
-
- private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
- InstallMultiple() {
- super(getDevice(), getBuild());
- }
-
- InstallMultiple addFileAndSignature(String filename) {
- try {
- addFile(filename);
- addFile(filename + ".fsv_sig");
- } catch (FileNotFoundException e) {
- fail("Missing test file: " + e);
- }
- return this;
- }
- }
-}
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java b/tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java
deleted file mode 100644
index 02e73d1..0000000
--- a/tests/ApkVerityTest/src/com/android/apkverity/BaseInstallMultiple.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-package com.android.apkverity;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-
-import junit.framework.TestCase;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
- *
- * <code> private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> { public
- * InstallMultiple() { super(getDevice(), null); } } </code>
- */
-/*package*/ class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
-
- private final ITestDevice mDevice;
- private final IBuildInfo mBuild;
-
- private final List<String> mArgs = new ArrayList<>();
- private final Map<File, String> mFileToRemoteMap = new HashMap<>();
-
- /*package*/ BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo) {
- mDevice = device;
- mBuild = buildInfo;
- addArg("-g");
- }
-
- T addArg(String arg) {
- mArgs.add(arg);
- return (T) this;
- }
-
- T addFile(String filename) throws FileNotFoundException {
- return addFile(filename, filename);
- }
-
- T addFile(String filename, String remoteName) throws FileNotFoundException {
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
- mFileToRemoteMap.put(buildHelper.getTestFile(filename), remoteName);
- return (T) this;
- }
-
- T inheritFrom(String packageName) {
- addArg("-r");
- addArg("-p " + packageName);
- return (T) this;
- }
-
- void run() throws DeviceNotAvailableException {
- run(true);
- }
-
- void runExpectingFailure() throws DeviceNotAvailableException {
- run(false);
- }
-
- private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
- final ITestDevice device = mDevice;
-
- // Create an install session
- final StringBuilder cmd = new StringBuilder();
- cmd.append("pm install-create");
- for (String arg : mArgs) {
- cmd.append(' ').append(arg);
- }
-
- String result = device.executeShellCommand(cmd.toString());
- TestCase.assertTrue(result, result.startsWith("Success"));
-
- final int start = result.lastIndexOf("[");
- final int end = result.lastIndexOf("]");
- int sessionId = -1;
- try {
- if (start != -1 && end != -1 && start < end) {
- sessionId = Integer.parseInt(result.substring(start + 1, end));
- }
- } catch (NumberFormatException e) {
- throw new IllegalStateException("Failed to parse install session: " + result);
- }
- if (sessionId == -1) {
- throw new IllegalStateException("Failed to create install session: " + result);
- }
-
- // Push our files into session. Ideally we'd use stdin streaming,
- // but ddmlib doesn't support it yet.
- for (final Map.Entry<File, String> entry : mFileToRemoteMap.entrySet()) {
- final File file = entry.getKey();
- final String remoteName = entry.getValue();
- final String remotePath = "/data/local/tmp/" + file.getName();
- if (!device.pushFile(file, remotePath)) {
- throw new IllegalStateException("Failed to push " + file);
- }
-
- cmd.setLength(0);
- cmd.append("pm install-write");
- cmd.append(' ').append(sessionId);
- cmd.append(' ').append(remoteName);
- cmd.append(' ').append(remotePath);
-
- result = device.executeShellCommand(cmd.toString());
- TestCase.assertTrue(result, result.startsWith("Success"));
- }
-
- // Everything staged; let's pull trigger
- cmd.setLength(0);
- cmd.append("pm install-commit");
- cmd.append(' ').append(sessionId);
-
- result = device.executeShellCommand(cmd.toString());
- if (expectingSuccess) {
- TestCase.assertTrue(result, result.contains("Success"));
- } else {
- TestCase.assertFalse(result, result.contains("Success"));
- }
- }
-}
diff --git a/tests/ApkVerityTest/src/com/android/fsverity/FsVerityHostTest.java b/tests/ApkVerityTest/src/com/android/fsverity/FsVerityHostTest.java
new file mode 100644
index 0000000..be479f2
--- /dev/null
+++ b/tests/ApkVerityTest/src/com/android/fsverity/FsVerityHostTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+package com.android.fsverity;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.annotations.RootPermissionTest;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.host.HostFlagsValueProvider;
+import android.security.Flags;
+
+import com.android.blockdevicewriter.BlockDeviceWriter;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This test verifies fs-verity works end-to-end. There is a corresponding helper app.
+ *
+ * <p>The helper app uses a FileIntegrityManager API to enable fs-verity to a file. The host test
+ * here * tampers with the file's backing storage, then tells the helper app to read and expect
+ * success/failure on read.
+ *
+ * <p>In order to make sure a block of the file is readable only if the underlying block on disk
+ * stay intact, the test needs to bypass the filesystem and tampers with the corresponding physical
+ * address against the block device.
+ */
+@RootPermissionTest
+@RunWith(DeviceJUnit4ClassRunner.class)
+@RequiresFlagsEnabled(Flags.FLAG_FSVERITY_API)
+public class FsVerityHostTest extends BaseHostJUnit4Test {
+ private static final String TARGET_PACKAGE = "com.android.fsverity";
+
+ private static final String BASENAME = "test.file";
+ private static final String TARGET_PATH = "/data/data/" + TARGET_PACKAGE + "/files/" + BASENAME;
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ HostFlagsValueProvider.createCheckFlagsRule(this::getDevice);
+
+ @Test
+ public void testFsVeritySmallFile() throws Exception {
+ prepareTest(10000);
+
+ ITestDevice device = getDevice();
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 0);
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 8192);
+ BlockDeviceWriter.dropCaches(device);
+
+ verifyRead(TARGET_PATH, "0,2");
+ }
+
+ @Test
+ public void testFsVerityLargerFileWithOneMoreMerkleTreeLevel() throws Exception {
+ prepareTest(128 * 4096 + 1);
+
+ ITestDevice device = getDevice();
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 4096);
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 100 * 4096);
+ BlockDeviceWriter.damageFileAgainstBlockDevice(device, TARGET_PATH, 128 * 4096 + 1);
+ BlockDeviceWriter.dropCaches(device);
+
+ verifyRead(TARGET_PATH, "1,100,128");
+ }
+
+ private void prepareTest(int fileSize) throws Exception {
+ DeviceTestRunOptions options = new DeviceTestRunOptions(TARGET_PACKAGE);
+ options.setTestClassName(TARGET_PACKAGE + ".Helper");
+ options.setTestMethodName("prepareTest");
+ options.addInstrumentationArg("basename", BASENAME);
+ options.addInstrumentationArg("fileSize", String.valueOf(fileSize));
+ assertThat(runDeviceTests(options)).isTrue();
+ }
+
+ private void verifyRead(String path, String indicesCsv) throws Exception {
+ DeviceTestRunOptions options = new DeviceTestRunOptions(TARGET_PACKAGE);
+ options.setTestClassName(TARGET_PACKAGE + ".Helper");
+ options.setTestMethodName("verifyFileRead");
+ options.addInstrumentationArg("brokenBlockIndicesCsv", indicesCsv);
+ options.addInstrumentationArg("filePath", TARGET_PATH);
+ assertThat(runDeviceTests(options)).isTrue();
+ }
+}
diff --git a/tests/ApkVerityTest/testdata/Android.bp b/tests/ApkVerityTest/testdata/Android.bp
index ccfc4c9..2d578d3 100644
--- a/tests/ApkVerityTest/testdata/Android.bp
+++ b/tests/ApkVerityTest/testdata/Android.bp
@@ -37,51 +37,3 @@
name: "ApkVerityTestCertDer",
srcs: ["ApkVerityTestCert.der"],
}
-
-filegroup {
- name: "ApkVerityTestAppDm",
- srcs: ["ApkVerityTestApp.dm"],
-}
-
-filegroup {
- name: "ApkVerityTestAppSplitDm",
- srcs: ["ApkVerityTestAppSplit.dm"],
-}
-
-genrule_defaults {
- name: "apk_verity_sig_gen_default",
- tools: ["fsverity"],
- tool_files: [":ApkVerityTestKeyPem", ":ApkVerityTestCertPem"],
- cmd: "$(location fsverity) sign $(in) $(out) " +
- "--key=$(location :ApkVerityTestKeyPem) " +
- "--cert=$(location :ApkVerityTestCertPem) " +
- "> /dev/null",
-}
-
-genrule {
- name: "ApkVerityTestAppFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestApp"],
- out: ["ApkVerityTestApp.apk.fsv_sig"],
-}
-
-genrule {
- name: "ApkVerityTestAppDmFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestAppDm"],
- out: ["ApkVerityTestApp.dm.fsv_sig"],
-}
-
-genrule {
- name: "ApkVerityTestAppSplitFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestAppSplit"],
- out: ["ApkVerityTestAppSplit.apk.fsv_sig"],
-}
-
-genrule {
- name: "ApkVerityTestAppSplitDmFsvSig",
- defaults: ["apk_verity_sig_gen_default"],
- srcs: [":ApkVerityTestAppSplitDm"],
- out: ["ApkVerityTestAppSplit.dm.fsv_sig"],
-}
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestApp.dm b/tests/ApkVerityTest/testdata/ApkVerityTestApp.dm
deleted file mode 100644
index e53a861..0000000
--- a/tests/ApkVerityTest/testdata/ApkVerityTestApp.dm
+++ /dev/null
Binary files differ
diff --git a/tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dm b/tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dm
deleted file mode 100644
index 75396f1..0000000
--- a/tests/ApkVerityTest/testdata/ApkVerityTestAppSplit.dm
+++ /dev/null
Binary files differ
diff --git a/tests/ApkVerityTest/testdata/README.md b/tests/ApkVerityTest/testdata/README.md
deleted file mode 100644
index 163cb18..0000000
--- a/tests/ApkVerityTest/testdata/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-This test only runs on rooted / debuggable device.
-
-The test tries to install subsets of base.{apk,dm}, split.{apk,dm} and their
-corresponding .fsv_sig files (generated by build rule). If installed, the
-tests also tries to tamper with the file at absolute disk offset to verify
-if fs-verity is effective.
-
-How to generate dex metadata (.dm)
-==================================
-
- adb shell profman --generate-test-profile=/data/local/tmp/primary.prof
- adb pull /data/local/tmp/primary.prof
- zip foo.dm primary.prof