1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.rollback.host; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.hamcrest.CoreMatchers.endsWith; 22 import static org.hamcrest.CoreMatchers.equalTo; 23 import static org.hamcrest.CoreMatchers.not; 24 import static org.junit.Assume.assumeThat; 25 import static org.junit.Assume.assumeTrue; 26 import static org.junit.Assume.assumeThat; 27 28 import android.cts.install.lib.host.InstallUtilsHost; 29 30 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 31 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 32 33 import org.junit.After; 34 import org.junit.Before; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 /** 39 * CTS host tests for RollbackManager APIs. 40 */ 41 @RunWith(DeviceJUnit4ClassRunner.class) 42 public class RollbackManagerHostTest extends BaseHostJUnit4Test { 43 44 private static final String TAG = "RollbackManagerHostTest"; 45 private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this); 46 47 /** 48 * Runs the helper app test method on device. 49 * Throws an exception if the test method fails. 50 * <p> 51 * For example, <code>run("testApkOnlyEnableRollback");</code> 52 */ run(String method)53 private void run(String method) throws Exception { 54 assertThat(runDeviceTests("com.android.cts.rollback.host.app", 55 "com.android.cts.rollback.host.app.HostTestHelper", 56 method)).isTrue(); 57 } 58 59 /** 60 * Runs the helper app test method on device targeted for 61 * com.android.cts.rollback.host.app2.HostTestHelper. 62 */ run2(String method)63 private void run2(String method) throws Exception { 64 assertThat(runDeviceTests("com.android.cts.rollback.host.app2", 65 "com.android.cts.rollback.host.app2.HostTestHelper", 66 method)).isTrue(); 67 } 68 69 /** 70 * Uninstalls any version greater than 1 of shim apex and reboots the device if necessary 71 * to complete the uninstall. 72 * 73 * <p>This is needed because the apex cannot be deleted using PackageInstaller API. 74 * 75 * Also abandon sessions left by previous tests so staged-installs won't fail. 76 */ 77 @Before 78 @After cleanUp()79 public void cleanUp() throws Exception { 80 getDevice().executeShellCommand("for i in $(pm list staged-sessions --only-sessionid " 81 + "--only-parent); do pm install-abandon $i; done"); 82 getDevice().executeShellCommand("pm uninstall com.android.cts.install.lib.testapp.A"); 83 getDevice().executeShellCommand("pm uninstall com.android.cts.install.lib.testapp.B"); 84 run("cleanUp"); 85 mHostUtils.uninstallShimApexIfNecessary(); 86 } 87 88 /** 89 * Tests staged rollbacks involving only apks. 90 */ 91 @Test testApkOnlyStagedRollback()92 public void testApkOnlyStagedRollback() throws Exception { 93 run("testApkOnlyStagedRollback_Phase1_Install"); 94 getDevice().reboot(); 95 run("testApkOnlyStagedRollback_Phase2_RollBack"); 96 getDevice().reboot(); 97 run("testApkOnlyStagedRollback_Phase3_Confirm"); 98 } 99 100 /** 101 * Tests multiple staged rollbacks involving only apks. 102 */ 103 @Test testApkOnlyMultipleStagedRollback()104 public void testApkOnlyMultipleStagedRollback() throws Exception { 105 assumeTrue("Device does not support file-system checkpoint", 106 mHostUtils.isCheckpointSupported()); 107 108 run("testApkOnlyMultipleStagedRollback_Phase1_Install"); 109 getDevice().reboot(); 110 run("testApkOnlyMultipleStagedRollback_Phase2_RollBack"); 111 getDevice().reboot(); 112 run("testApkOnlyMultipleStagedRollback_Phase3_Confirm"); 113 } 114 115 /** 116 * Tests multiple staged partial rollbacks involving only apks. 117 */ 118 @Test testApkOnlyMultipleStagedPartialRollback()119 public void testApkOnlyMultipleStagedPartialRollback() throws Exception { 120 assumeTrue("Device does not support file-system checkpoint", 121 mHostUtils.isCheckpointSupported()); 122 123 run("testApkOnlyMultipleStagedPartialRollback_Phase1_Install"); 124 getDevice().reboot(); 125 run("testApkOnlyMultipleStagedPartialRollback_Phase2_RollBack"); 126 getDevice().reboot(); 127 run("testApkOnlyMultipleStagedPartialRollback_Phase3_Confirm"); 128 } 129 130 /** 131 * Tests staged rollbacks involving only apex. 132 */ 133 @Test testApexOnlyStagedRollback()134 public void testApexOnlyStagedRollback() throws Exception { 135 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 136 137 run("testApexOnlyStagedRollback_Phase1_InstallFirst"); 138 getDevice().reboot(); 139 run("testApexOnlyStagedRollback_Phase2_InstallSecond"); 140 getDevice().reboot(); 141 run("testApexOnlyStagedRollback_Phase3_RollBack"); 142 getDevice().reboot(); 143 run("testApexOnlyStagedRollback_Phase4_Confirm"); 144 } 145 146 /** 147 * Tests staged rollbacks to system version involving only apex. 148 */ 149 @Test testApexOnlySystemVersionStagedRollback()150 public void testApexOnlySystemVersionStagedRollback() throws Exception { 151 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 152 153 run("testApexOnlySystemVersionStagedRollback_Phase1_Install"); 154 getDevice().reboot(); 155 run("testApexOnlySystemVersionStagedRollback_Phase2_RollBack"); 156 getDevice().reboot(); 157 run("testApexOnlySystemVersionStagedRollback_Phase3_Confirm"); 158 } 159 160 /** 161 * Tests staged rollbacks involving apex and apk. 162 */ 163 @Test testApexAndApkStagedRollback()164 public void testApexAndApkStagedRollback() throws Exception { 165 assumeSystemUser(); 166 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 167 168 run("testApexAndApkStagedRollback_Phase1_InstallFirst"); 169 getDevice().reboot(); 170 run("testApexAndApkStagedRollback_Phase2_InstallSecond"); 171 getDevice().reboot(); 172 run("testApexAndApkStagedRollback_Phase3_RollBack"); 173 getDevice().reboot(); 174 run("testApexAndApkStagedRollback_Phase4_Confirm"); 175 } 176 assumeSystemUser()177 private void assumeSystemUser() throws Exception { 178 String systemUser = "0"; 179 assumeThat("Current user is not system user", 180 getDevice().executeShellCommand("am get-current-user").trim(), equalTo(systemUser)); 181 } 182 183 /** 184 * Tests that apex update expires existing rollbacks for that apex. 185 */ 186 @Test testApexRollbackExpiration()187 public void testApexRollbackExpiration() throws Exception { 188 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 189 190 run("testApexRollbackExpiration_Phase1_InstallFirst"); 191 getDevice().reboot(); 192 run("testApexRollbackExpiration_Phase2_InstallSecond"); 193 getDevice().reboot(); 194 run("testApexRollbackExpiration_Phase3_Confirm"); 195 } 196 197 /** 198 * Tests staged rollbacks involving apex with rotated keys. 199 */ 200 @Test testApexKeyRotationStagedRollback()201 public void testApexKeyRotationStagedRollback() throws Exception { 202 assumeTrue("Device does not support updating APEX", mHostUtils.isApexUpdateSupported()); 203 204 run("testApexKeyRotationStagedRollback_Phase1_Install"); 205 getDevice().reboot(); 206 run("testApexKeyRotationStagedRollback_Phase2_RollBack"); 207 getDevice().reboot(); 208 run("testApexKeyRotationStagedRollback_Phase3_Confirm"); 209 } 210 211 /** 212 * Tests installer B can't rollback a package installed by A. 213 */ 214 @Test testApkRollbackByAnotherInstaller()215 public void testApkRollbackByAnotherInstaller() throws Exception { 216 run("testApkRollbackByAnotherInstaller_Phase1_FirstInstaller"); 217 run2("testApkRollbackByAnotherInstaller_Phase2_SecondInstaller"); 218 } 219 220 /** 221 * Tests that existing staged sessions are failed when rollback is committed 222 */ 223 @Test testRollbackFailsOtherSessions()224 public void testRollbackFailsOtherSessions() throws Exception { 225 assumeTrue("Device does not support file-system checkpoint", 226 mHostUtils.isCheckpointSupported()); 227 228 run("testRollbackFailsOtherSessions_Phase1_Install"); 229 getDevice().reboot(); 230 run("testRollbackFailsOtherSessions_Phase2_RollBack"); 231 getDevice().reboot(); 232 run("testRollbackFailsOtherSessions_Phase3_Confirm"); 233 } 234 235 /** 236 * Tests that simultaneous rollbacks both succeed - neither causes the other to fail. 237 */ 238 @Test testSimultaneousRollbacksBothSucceed()239 public void testSimultaneousRollbacksBothSucceed() throws Exception { 240 assumeTrue("Device does not support file-system checkpoint", 241 mHostUtils.isCheckpointSupported()); 242 243 run("testSimultaneousRollbacksBothSucceed_Phase1_Install"); 244 getDevice().reboot(); 245 run("testSimultaneousRollbacksBothSucceed_Phase2_RollBack"); 246 getDevice().reboot(); 247 run("testSimultaneousRollbacksBothSucceed_Phase3_Confirm"); 248 } 249 250 /** 251 * Tests that rollbacks are invalidated upon fingerprint changes. 252 */ 253 @Test testFingerprintChange()254 public void testFingerprintChange() throws Exception { 255 assumeThat(getDevice().getBuildFlavor(), not(endsWith("-user"))); 256 257 try { 258 getDevice().executeShellCommand("setprop persist.pm.mock-upgrade true"); 259 260 run("testFingerprintChange_Phase1_Install"); 261 getDevice().reboot(); 262 run("testFingerprintChange_Phase2_Confirm"); 263 } finally { 264 getDevice().executeShellCommand("setprop persist.pm.mock-upgrade false"); 265 } 266 } 267 } 268