• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.sdksandbox.host;
18 
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
23 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
24 
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 
29 @RunWith(DeviceJUnit4ClassRunner.class)
30 public final class SdkSandboxLifecycleHostTest extends BaseHostJUnit4Test {
31 
32     private static final String APP_PACKAGE = "com.android.sdksandbox.app";
33     private static final String APP_2_PACKAGE = "com.android.sdksandbox.app2";
34 
35     private static final String APP_ACTIVITY = "SdkSandboxTestActivity";
36     private static final String APP_2_ACTIVITY = "SdkSandboxTestActivity2";
37 
38     private static final String CODE_APK = "TestCodeProvider.apk";
39     private static final String CODE_APK_2 = "TestCodeProvider2.apk";
40 
clearProcess(String pkg)41     private void clearProcess(String pkg) throws Exception {
42         getDevice().executeShellCommand(String.format("pm clear %s", pkg));
43     }
44 
startActivity(String pkg, String activity)45     private void startActivity(String pkg, String activity) throws Exception {
46         getDevice().executeShellCommand(String.format("am start -W -n %s/.%s", pkg, activity));
47     }
48 
killApp(String pkg)49     private void killApp(String pkg) throws Exception {
50         getDevice().executeShellCommand(String.format("am force-stop %s", pkg));
51     }
52 
getUidForPackage(String pkg)53     private String getUidForPackage(String pkg) throws Exception {
54         String pid = getDevice().getProcessPid(pkg);
55         if (pid == null) {
56             throw new Exception(String.format("Could not find PID for %s", pkg));
57         }
58         String result = getDevice().executeAdbCommand("shell", "ps", "-p", pid, "-o", "uid");
59         String[] sections = result.split("\n");
60         return sections[sections.length - 1];
61     }
62 
63     // TODO(b/216302023): Update sdk sandbox process name format
getSdkSandboxNameForPackage(String pkg)64     private String getSdkSandboxNameForPackage(String pkg) throws Exception {
65         String appUid = getUidForPackage(pkg);
66         return String.format("sdk_sandbox_%s", appUid);
67     }
68 
69     @Before
setUp()70     public void setUp() throws Exception {
71         assertThat(getBuild()).isNotNull();
72         assertThat(getDevice()).isNotNull();
73 
74         // Ensure neither app is currently running
75         for (String pkg : new String[]{APP_PACKAGE, APP_2_PACKAGE}) {
76             clearProcess(pkg);
77         }
78 
79         // Workaround for autoTeardown which removes packages installed in test
80         for (String apk : new String[]{CODE_APK, CODE_APK_2}) {
81             if (!isPackageInstalled(apk)) {
82                 installPackage(apk, "-d");
83             }
84         }
85     }
86 
87     @Test
testSdkSandboxIsDestroyedOnAppDestroy()88     public void testSdkSandboxIsDestroyedOnAppDestroy() throws Exception {
89         startActivity(APP_PACKAGE, APP_ACTIVITY);
90         String processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
91         assertThat(processDump).contains(APP_PACKAGE);
92         String sdkSandbox = getSdkSandboxNameForPackage(APP_PACKAGE);
93         assertThat(processDump).contains(sdkSandbox);
94 
95         killApp(APP_PACKAGE);
96         processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
97         assertThat(processDump).doesNotContain(APP_PACKAGE);
98         assertThat(processDump).doesNotContain(sdkSandbox);
99     }
100 
101     @Test
testSdkSandboxIsCreatedPerApp()102     public void testSdkSandboxIsCreatedPerApp() throws Exception {
103         startActivity(APP_PACKAGE, APP_ACTIVITY);
104         String processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
105         assertThat(processDump).contains(APP_PACKAGE);
106         String sdkSandbox1 = getSdkSandboxNameForPackage(APP_PACKAGE);
107         assertThat(processDump).contains(sdkSandbox1);
108 
109         startActivity(APP_2_PACKAGE, APP_2_ACTIVITY);
110         processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
111         assertThat(processDump).contains(APP_2_PACKAGE);
112         String sdkSandbox2 = getSdkSandboxNameForPackage(APP_2_PACKAGE);
113         assertThat(processDump).contains(sdkSandbox2);
114         assertThat(processDump).contains(APP_PACKAGE);
115         assertThat(processDump).contains(sdkSandbox1);
116 
117         killApp(APP_2_PACKAGE);
118         processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
119         assertThat(processDump).doesNotContain(APP_2_PACKAGE);
120         assertThat(processDump).doesNotContain(sdkSandbox2);
121         assertThat(processDump).contains(APP_PACKAGE);
122         assertThat(processDump).contains(sdkSandbox1);
123     }
124 
125     @Test
testAppAndSdkSandboxAreKilledOnLoadedSdkUpdate()126     public void testAppAndSdkSandboxAreKilledOnLoadedSdkUpdate() throws Exception {
127         startActivity(APP_PACKAGE, APP_ACTIVITY);
128 
129         // Should see app/sdk sandbox running
130         String processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
131         assertThat(processDump).contains(APP_PACKAGE);
132 
133         String sdkSandbox = getSdkSandboxNameForPackage(APP_PACKAGE);
134         assertThat(processDump).contains(sdkSandbox);
135 
136         // Update package loaded by app
137         installPackage(CODE_APK, "-d");
138 
139         // Should no longer see app/sdk sandbox running
140         processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
141         assertThat(processDump).doesNotContain(APP_PACKAGE);
142         assertThat(processDump).doesNotContain(sdkSandbox);
143     }
144 
145     @Test
testAppAndSdkSandboxAreNotKilledForNonLoadedSdkUpdate()146     public void testAppAndSdkSandboxAreNotKilledForNonLoadedSdkUpdate() throws Exception {
147         startActivity(APP_PACKAGE, APP_ACTIVITY);
148 
149         // Should see app/sdk sandbox running
150         String processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
151         assertThat(processDump).contains(APP_PACKAGE);
152 
153         String sdkSandbox = getSdkSandboxNameForPackage(APP_PACKAGE);
154         assertThat(processDump).contains(sdkSandbox);
155 
156         // Simulate update of package not loaded by app
157         installPackage(CODE_APK_2, "-d");
158 
159         // Should still see app/sdk sandbox running
160         processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
161         assertThat(processDump).contains(APP_PACKAGE);
162         assertThat(processDump).contains(sdkSandbox);
163     }
164 
165     @Test
testOnlyRelevantAppIsKilledForLoadedSdkUpdate()166     public void testOnlyRelevantAppIsKilledForLoadedSdkUpdate() throws Exception {
167         startActivity(APP_PACKAGE, APP_ACTIVITY);
168         startActivity(APP_2_PACKAGE, APP_2_ACTIVITY);
169 
170         // See processes for both apps
171         String processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
172         assertThat(processDump).contains(APP_PACKAGE);
173 
174         String sdkSandbox = getSdkSandboxNameForPackage(APP_PACKAGE);
175         assertThat(processDump).contains(sdkSandbox);
176 
177         assertThat(processDump).contains(APP_2_PACKAGE);
178 
179         String sdkSandbox2 = getSdkSandboxNameForPackage(APP_PACKAGE);
180         assertThat(processDump).contains(sdkSandbox2);
181 
182         installPackage(CODE_APK_2, "-d");
183 
184         processDump = getDevice().executeAdbCommand("shell", "ps", "-A");
185         assertThat(processDump).contains(APP_PACKAGE);
186         assertThat(processDump).doesNotContain(APP_2_PACKAGE);
187 
188         // TODO(b/215012578) check that sdk sandbox for app 1 is still running
189     }
190 }
191