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.tests.rollback.host; 18 19 import static org.junit.Assert.assertTrue; 20 import static org.junit.Assert.fail; 21 import static org.junit.Assume.assumeTrue; 22 23 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 24 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 25 26 import org.junit.After; 27 import org.junit.Before; 28 import org.junit.Ignore; 29 import org.junit.Rule; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 33 import java.util.concurrent.TimeUnit; 34 35 /** 36 * Runs rollback tests for multiple users. 37 */ 38 @RunWith(DeviceJUnit4ClassRunner.class) 39 public class MultiUserRollbackTest extends BaseHostJUnit4Test { 40 private boolean mSupportMultiUsers; 41 // The user that was running originally when the test starts. 42 private int mOriginalUserId; 43 private int mSecondaryUserId = -1; 44 private static final long SWITCH_USER_COMPLETED_NUMBER_OF_POLLS = 60; 45 private static final long SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS = 1000; 46 47 @Rule 48 public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this); 49 50 @After tearDown()51 public void tearDown() throws Exception { 52 if (mSupportMultiUsers) { 53 removeSecondaryUserIfNecessary(); 54 runPhaseForUsers("cleanUp", mOriginalUserId); 55 uninstallPackage("com.android.cts.install.lib.testapp.A"); 56 uninstallPackage("com.android.cts.install.lib.testapp.B"); 57 } 58 } 59 60 @Before setup()61 public void setup() throws Exception { 62 assumeTrue("Device does not support multiple users", 63 getDevice().isMultiUserSupported()); 64 65 mSupportMultiUsers = true; 66 mOriginalUserId = getDevice().getCurrentUser(); 67 createAndStartSecondaryUser(); 68 installPackage("RollbackTest.apk", "--user all"); 69 runPhaseForUsers("cleanUp", mOriginalUserId); 70 } 71 72 @Test testBasicForSecondaryUser()73 public void testBasicForSecondaryUser() throws Exception { 74 runPhaseForUsers("testBasic", mSecondaryUserId); 75 } 76 77 /** 78 * Tests staged install/rollback works correctly on the 2nd user. 79 */ 80 @Test testStagedRollback()81 public void testStagedRollback() throws Exception { 82 runPhaseForUsers("testStagedRollback_Phase1", mSecondaryUserId); 83 getDevice().reboot(); 84 85 // Need to unlock the user for device tests to run successfully 86 getDevice().startUser(mSecondaryUserId); 87 awaitUserUnlocked(mSecondaryUserId); 88 runPhaseForUsers("testStagedRollback_Phase2", mSecondaryUserId); 89 getDevice().reboot(); 90 91 getDevice().startUser(mSecondaryUserId); 92 awaitUserUnlocked(mSecondaryUserId); 93 runPhaseForUsers("testStagedRollback_Phase3", mSecondaryUserId); 94 getDevice().reboot(); 95 96 getDevice().startUser(mSecondaryUserId); 97 awaitUserUnlocked(mSecondaryUserId); 98 runPhaseForUsers("testStagedRollback_Phase4", mSecondaryUserId); 99 } 100 101 @Test 102 @Ignore testBadUpdateRollback()103 public void testBadUpdateRollback() throws Exception { 104 // Need to switch user in order to send broadcasts in device tests 105 assertTrue(getDevice().switchUser(mSecondaryUserId)); 106 runPhaseForUsers("testBadUpdateRollback", mSecondaryUserId); 107 } 108 109 @Test testMultipleUsers()110 public void testMultipleUsers() throws Exception { 111 runPhaseForUsers("testMultipleUsersInstallV1", mOriginalUserId, mSecondaryUserId); 112 runPhaseForUsers("testMultipleUsersUpgradeToV2", mOriginalUserId); 113 runPhaseForUsers("testMultipleUsersUpdateUserData", mOriginalUserId, mSecondaryUserId); 114 getDevice().executeShellCommand("pm rollback-app com.android.cts.install.lib.testapp.A"); 115 runPhaseForUsers("testMultipleUsersVerifyUserdataRollback", mOriginalUserId, 116 mSecondaryUserId); 117 } 118 119 /** 120 * Run the phase for the given user ids, in the order they are given. 121 */ runPhaseForUsers(String phase, int... userIds)122 private void runPhaseForUsers(String phase, int... userIds) throws Exception { 123 final long timeout = TimeUnit.MINUTES.toMillis(10); 124 for (int userId: userIds) { 125 assertTrue(runDeviceTests(getDevice(), "com.android.tests.rollback", 126 "com.android.tests.rollback.MultiUserRollbackTest", 127 phase, userId, timeout)); 128 } 129 } 130 removeSecondaryUserIfNecessary()131 private void removeSecondaryUserIfNecessary() throws Exception { 132 if (mSecondaryUserId != -1) { 133 // Can't remove the 2nd user without switching out of it 134 assertTrue(getDevice().switchUser(mOriginalUserId)); 135 getDevice().removeUser(mSecondaryUserId); 136 mSecondaryUserId = -1; 137 } 138 } 139 awaitUserUnlocked(int userId)140 private void awaitUserUnlocked(int userId) throws Exception { 141 for (int i = 0; i < SWITCH_USER_COMPLETED_NUMBER_OF_POLLS; ++i) { 142 String userState = getDevice().executeShellCommand("am get-started-user-state " 143 + userId); 144 if (userState.contains("RUNNING_UNLOCKED")) { 145 return; 146 } 147 Thread.sleep(SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS); 148 } 149 fail("Timed out in unlocking user: " + userId); 150 } 151 createAndStartSecondaryUser()152 private void createAndStartSecondaryUser() throws Exception { 153 String name = "MultiUserRollbackTest_User" + System.currentTimeMillis(); 154 mSecondaryUserId = getDevice().createUser(name); 155 getDevice().startUser(mSecondaryUserId); 156 // Note we can't install apps on a locked user 157 awaitUserUnlocked(mSecondaryUserId); 158 } 159 } 160