• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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;
18 
19 import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat;
20 import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import android.Manifest;
25 import android.content.ComponentName;
26 import android.content.Intent;
27 import android.content.pm.PackageManager;
28 import android.content.rollback.RollbackManager;
29 import android.os.ParcelFileDescriptor;
30 import android.provider.DeviceConfig;
31 
32 import androidx.test.platform.app.InstrumentationRegistry;
33 
34 import com.android.cts.install.lib.Install;
35 import com.android.cts.install.lib.InstallUtils;
36 import com.android.cts.install.lib.TestApp;
37 import com.android.cts.rollback.lib.RollbackUtils;
38 
39 import libcore.io.IoUtils;
40 
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.junit.runners.JUnit4;
46 
47 import java.io.File;
48 import java.util.concurrent.TimeUnit;
49 
50 @RunWith(JUnit4.class)
51 public class NetworkStagedRollbackTest {
52     private static final String NETWORK_STACK_CONNECTOR_CLASS =
53             "android.net.INetworkStackConnector";
54     private static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS =
55             "watchdog_request_timeout_millis";
56 
57     private static final String[] NETWORK_STACK_APK_NAMES = {
58             "NetworkStack", "NetworkStackGoogle", "NetworkStackNext", "NetworkStackNextGoogle"
59     };
60 
61     private static final TestApp NETWORK_STACK = new TestApp("NetworkStack",
62             getNetworkStackPackageName(), -1, false, findNetworkStackApk());
63 
findNetworkStackApk()64     private static File[] findNetworkStackApk() {
65         for (String name : NETWORK_STACK_APK_NAMES) {
66             final File apk = new File("/system/priv-app/" + name + "/" + name + ".apk");
67             if (apk.isFile()) {
68                 final File dir = new File("/system/priv-app/" + name);
69                 return dir.listFiles((d, f) -> f.startsWith(name));
70             }
71         }
72         throw new RuntimeException("Can't find NetworkStackApk");
73     }
74 
75     /**
76      * Adopts common shell permissions needed for rollback tests.
77      */
78     @Before
adoptShellPermissions()79     public void adoptShellPermissions() {
80         InstallUtils.adoptShellPermissionIdentity(
81                 Manifest.permission.INSTALL_PACKAGES,
82                 Manifest.permission.DELETE_PACKAGES,
83                 Manifest.permission.TEST_MANAGE_ROLLBACKS,
84                 Manifest.permission.FORCE_STOP_PACKAGES,
85                 Manifest.permission.WRITE_DEVICE_CONFIG);
86     }
87 
88     /**
89      * Drops shell permissions needed for rollback tests.
90      */
91     @After
dropShellPermissions()92     public void dropShellPermissions() {
93         InstallUtils.dropShellPermissionIdentity();
94     }
95 
96     @Test
cleanUp()97     public void cleanUp() {
98         RollbackManager rm = RollbackUtils.getRollbackManager();
99         rm.getAvailableRollbacks().stream().flatMap(info -> info.getPackages().stream())
100                 .map(info -> info.getPackageName()).forEach(rm::expireRollbackForPackage);
101         rm.getRecentlyCommittedRollbacks().stream().flatMap(info -> info.getPackages().stream())
102                 .map(info -> info.getPackageName()).forEach(rm::expireRollbackForPackage);
103         assertThat(rm.getAvailableRollbacks()).isEmpty();
104         assertThat(rm.getRecentlyCommittedRollbacks()).isEmpty();
105         uninstallNetworkStackPackage();
106     }
107 
108     @Test
testNetworkFailedRollback_Phase1()109     public void testNetworkFailedRollback_Phase1() throws Exception {
110         // Remove available rollbacks and uninstall NetworkStack on /data/
111         RollbackManager rm = RollbackUtils.getRollbackManager();
112         String networkStack = getNetworkStackPackageName();
113 
114         assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
115                 networkStack)).isNull();
116 
117         // Reduce health check deadline
118         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
119                 PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS,
120                 Integer.toString(120000), false);
121         // Simulate re-installation of new NetworkStack with rollbacks enabled
122         installNetworkStackPackage();
123     }
124 
125     @Test
testNetworkFailedRollback_Phase2()126     public void testNetworkFailedRollback_Phase2() throws Exception {
127         RollbackManager rm = RollbackUtils.getRollbackManager();
128         assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
129                 getNetworkStackPackageName())).isNotNull();
130 
131         // Sleep for < health check deadline
132         Thread.sleep(TimeUnit.SECONDS.toMillis(5));
133         // Verify rollback was not executed before health check deadline
134         assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
135                 getNetworkStackPackageName())).isNull();
136     }
137 
138     @Test
testNetworkFailedRollback_Phase3()139     public void testNetworkFailedRollback_Phase3() throws Exception {
140         RollbackManager rm = RollbackUtils.getRollbackManager();
141         assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
142                 getNetworkStackPackageName())).isNotNull();
143     }
144 
getNetworkStackPackageName()145     private static String getNetworkStackPackageName() {
146         Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
147         ComponentName comp = intent.resolveSystemService(
148                 InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(), 0);
149         return comp.getPackageName();
150     }
151 
installNetworkStackPackage()152     private static void installNetworkStackPackage() throws Exception {
153         Install.single(NETWORK_STACK).setStaged().setEnableRollback()
154                 .addInstallFlags(PackageManager.INSTALL_REPLACE_EXISTING).commit();
155     }
156 
uninstallNetworkStackPackage()157     private static void uninstallNetworkStackPackage() {
158         // Uninstall the package as a privileged user so we won't fail due to permission.
159         runShellCommand("pm uninstall " + getNetworkStackPackageName());
160     }
161 
162     @Test
testNetworkPassedDoesNotRollback_Phase1()163     public void testNetworkPassedDoesNotRollback_Phase1() throws Exception {
164         // Remove available rollbacks and uninstall NetworkStack on /data/
165         RollbackManager rm = RollbackUtils.getRollbackManager();
166         String networkStack = getNetworkStackPackageName();
167 
168         assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
169                 networkStack)).isNull();
170 
171         // Reduce health check deadline, here unlike the network failed case, we use
172         // a longer deadline because joining a network can take a much longer time for
173         // reasons external to the device than 'not joining'
174         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
175                 PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS,
176                 Integer.toString(300000), false);
177         // Simulate re-installation of new NetworkStack with rollbacks enabled
178         installNetworkStackPackage();
179     }
180 
181     @Test
testNetworkPassedDoesNotRollback_Phase2()182     public void testNetworkPassedDoesNotRollback_Phase2() throws Exception {
183         RollbackManager rm = RollbackUtils.getRollbackManager();
184         assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
185                 getNetworkStackPackageName())).isNotNull();
186     }
187 
188     @Test
testNetworkPassedDoesNotRollback_Phase3()189     public void testNetworkPassedDoesNotRollback_Phase3() throws Exception {
190         // Sleep for > health check deadline. We expect no rollback should happen during sleeping.
191         // If the device reboots for rollback, this device test will fail as well as the host test.
192         Thread.sleep(TimeUnit.SECONDS.toMillis(310));
193         RollbackManager rm = RollbackUtils.getRollbackManager();
194         assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
195                 getNetworkStackPackageName())).isNull();
196     }
197 
runShellCommand(String cmd)198     private static void runShellCommand(String cmd) {
199         ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
200                 .executeShellCommand(cmd);
201         IoUtils.closeQuietly(pfd);
202     }
203 }
204