Don't fall back to copy during rollback tests (5/n)
1. 'persist.rollback.is_test' is set to 1 during rollback tests
2. don't fall back to copy if hardlink fails during rollback tests
3. This gives us insight into how enable-rollback-by-hardlink works
and how it fails in the field
Bug: 168562373
Test: atest MultiUserRollbackTest \
NetworkStagedRollbackTest \
RollbackTest \
StagedRollbackTest
Change-Id: If1590fdf96e25105936a930b3ec7225ecec4bf0d
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 3a08ddc..fc62f5b 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -24,6 +24,7 @@
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.PackageRollbackInfo.RestoreInfo;
import android.content.rollback.RollbackInfo;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
@@ -227,6 +228,15 @@
packageSessionIds, extensionVersions);
}
+ private static boolean isLinkPossible(File oldFile, File newFile) {
+ try {
+ return Os.stat(oldFile.getAbsolutePath()).st_dev
+ == Os.stat(newFile.getAbsolutePath()).st_dev;
+ } catch (ErrnoException ignore) {
+ return false;
+ }
+ }
+
/**
* Creates a backup copy of an apk or apex for a package.
* For packages containing splits, this method should be called for each
@@ -239,16 +249,29 @@
targetDir.mkdirs();
File targetFile = new File(targetDir, sourceFile.getName());
- try {
- // Create a hard link to avoid copy
- // TODO(b/168562373)
- // Linking between non-encrypted and encrypted is not supported and we have
- // encrypted /data/rollback and non-encrypted /data/apex/active. For now this works
- // because we happen to store encrypted files under /data/apex/active which is no
- // longer the case when compressed apex rolls out. We have to handle this case in
- // order not to fall back to copy.
- Os.link(sourceFile.getAbsolutePath(), targetFile.getAbsolutePath());
- } catch (ErrnoException ignore) {
+ boolean fallbackToCopy = !isLinkPossible(sourceFile, targetFile);
+ if (!fallbackToCopy) {
+ try {
+ // Create a hard link to avoid copy
+ // TODO(b/168562373)
+ // Linking between non-encrypted and encrypted is not supported and we have
+ // encrypted /data/rollback and non-encrypted /data/apex/active. For now this works
+ // because we happen to store encrypted files under /data/apex/active which is no
+ // longer the case when compressed apex rolls out. We have to handle this case in
+ // order not to fall back to copy.
+ Os.link(sourceFile.getAbsolutePath(), targetFile.getAbsolutePath());
+ } catch (ErrnoException e) {
+ boolean isRollbackTest =
+ SystemProperties.getBoolean("persist.rollback.is_test", false);
+ if (isRollbackTest) {
+ throw new IOException(e);
+ } else {
+ fallbackToCopy = true;
+ }
+ }
+ }
+
+ if (fallbackToCopy) {
// Fall back to copy if hardlink can't be created
Files.copy(sourceFile.toPath(), targetFile.toPath());
}
diff --git a/tests/RollbackTest/MultiUserRollbackTest.xml b/tests/RollbackTest/MultiUserRollbackTest.xml
index 2f62af1..8fa0510 100644
--- a/tests/RollbackTest/MultiUserRollbackTest.xml
+++ b/tests/RollbackTest/MultiUserRollbackTest.xml
@@ -20,6 +20,8 @@
<option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
<option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
<option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
+ <option name="run-command" value="setprop persist.rollback.is_test 1" />
+ <option name="teardown-command" value="setprop persist.rollback.is_test 0" />
</target_preparer>
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="com.android.tests.rollback.host.MultiUserRollbackTest" />
diff --git a/tests/RollbackTest/NetworkStagedRollbackTest.xml b/tests/RollbackTest/NetworkStagedRollbackTest.xml
index 2ab907a..13f6031 100644
--- a/tests/RollbackTest/NetworkStagedRollbackTest.xml
+++ b/tests/RollbackTest/NetworkStagedRollbackTest.xml
@@ -24,6 +24,8 @@
<option name="run-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es package "com.google.android.gms.platformconfigurator" --es user '\\*' --esa flags "ModuleConfig__versioned_immediate_commit_packages" --esa types "bytes" --esa values "Cm5vdGFwYWNrYWdlOgA=" com.google.android.gms" />
<option name="teardown-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es action delete --es package "com.google.android.gms.platformconfigurator" --es user '\*' --esa flag "ModuleConfig__immediate_commit_packages" com.google.android.gms" />
<option name="teardown-command" value="am broadcast -a 'com.google.android.gms.phenotype.FLAG_OVERRIDE' --es action delete --es package "com.google.android.gms.platformconfigurator" --es user '\*' --esa flag "ModuleConfig__versioned_immediate_commit_packages" com.google.android.gms" />
+ <option name="run-command" value="setprop persist.rollback.is_test 1" />
+ <option name="teardown-command" value="setprop persist.rollback.is_test 0" />
</target_preparer>
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="com.android.tests.rollback.host.NetworkStagedRollbackTest" />
diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml
index 7b85cc8..fbb6e46 100644
--- a/tests/RollbackTest/RollbackTest.xml
+++ b/tests/RollbackTest/RollbackTest.xml
@@ -27,6 +27,8 @@
<option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
<option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
<option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
+ <option name="run-command" value="setprop persist.rollback.is_test 1" />
+ <option name="teardown-command" value="setprop persist.rollback.is_test 0" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.tests.rollback" />
diff --git a/tests/RollbackTest/StagedRollbackTest.xml b/tests/RollbackTest/StagedRollbackTest.xml
index 83fef8e..0ca4daf 100644
--- a/tests/RollbackTest/StagedRollbackTest.xml
+++ b/tests/RollbackTest/StagedRollbackTest.xml
@@ -24,6 +24,8 @@
<option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
<option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.A" />
<option name="teardown-command" value="pm uninstall com.android.cts.install.lib.testapp.B" />
+ <option name="run-command" value="setprop persist.rollback.is_test 1" />
+ <option name="teardown-command" value="setprop persist.rollback.is_test 0" />
</target_preparer>
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="com.android.tests.rollback.host.StagedRollbackTest" />