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