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