1 /*
2  * Copyright (C) 2014 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 android.appsecurity.cts;
18 
19 import static org.junit.Assert.assertNotNull;
20 
21 import android.platform.test.annotations.AppModeFull;
22 import android.platform.test.annotations.AppModeInstant;
23 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
24 
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 
30 import java.util.HashMap;
31 
32 /**
33  * Tests that verify installing of various split APKs from host side.
34  */
35 @RunWith(DeviceJUnit4ClassRunner.class)
36 public class SplitTests extends BaseAppSecurityTest {
37     static final String PKG_NO_RESTART = "com.android.cts.norestart";
38     static final String APK_NO_RESTART_BASE = "CtsNoRestartBase.apk";
39     static final String APK_NO_RESTART_FEATURE = "CtsNoRestartFeature.apk";
40 
41     static final String APK_NEED_SPLIT_BASE = "CtsNeedSplitApp.apk";
42     static final String APK_NEED_SPLIT_FEATURE = "CtsNeedSplitFeature.apk";
43     static final String APK_NEED_SPLIT_CONFIG = "CtsNeedSplitApp_xxhdpi-v4.apk";
44 
45     static final String PKG = "com.android.cts.splitapp";
46     static final String CLASS = PKG + ".SplitAppTest";
47 
48     static final String APK = "CtsSplitApp.apk";
49 
50     static final String APK_mdpi = "CtsSplitApp_mdpi-v4.apk";
51     static final String APK_hdpi = "CtsSplitApp_hdpi-v4.apk";
52     static final String APK_xhdpi = "CtsSplitApp_xhdpi-v4.apk";
53     static final String APK_xxhdpi = "CtsSplitApp_xxhdpi-v4.apk";
54 
55     private static final String APK_v7 = "CtsSplitApp_v7.apk";
56     private static final String APK_fr = "CtsSplitApp_fr.apk";
57     private static final String APK_de = "CtsSplitApp_de.apk";
58 
59     private static final String APK_x86 = "CtsSplitApp_x86.apk";
60     private static final String APK_x86_64 = "CtsSplitApp_x86_64.apk";
61     private static final String APK_armeabi_v7a = "CtsSplitApp_armeabi-v7a.apk";
62     private static final String APK_armeabi = "CtsSplitApp_armeabi.apk";
63     private static final String APK_arm64_v8a = "CtsSplitApp_arm64-v8a.apk";
64     private static final String APK_mips64 = "CtsSplitApp_mips64.apk";
65     private static final String APK_mips = "CtsSplitApp_mips.apk";
66 
67     private static final String APK_DIFF_REVISION = "CtsSplitAppDiffRevision.apk";
68     private static final String APK_DIFF_REVISION_v7 = "CtsSplitAppDiffRevision_v7.apk";
69 
70     private static final String APK_DIFF_VERSION = "CtsSplitAppDiffVersion.apk";
71     private static final String APK_DIFF_VERSION_v7 = "CtsSplitAppDiffVersion_v7.apk";
72 
73     private static final String APK_DIFF_CERT = "CtsSplitAppDiffCert.apk";
74     private static final String APK_DIFF_CERT_v7 = "CtsSplitAppDiffCert_v7.apk";
75 
76     private static final String APK_FEATURE = "CtsSplitAppFeature.apk";
77     private static final String APK_FEATURE_v7 = "CtsSplitAppFeature_v7.apk";
78 
79     static final HashMap<String, String> ABI_TO_APK = new HashMap<>();
80 
81     static {
82         ABI_TO_APK.put("x86", APK_x86);
83         ABI_TO_APK.put("x86_64", APK_x86_64);
84         ABI_TO_APK.put("armeabi-v7a", APK_armeabi_v7a);
85         ABI_TO_APK.put("armeabi", APK_armeabi);
86         ABI_TO_APK.put("arm64-v8a", APK_arm64_v8a);
87         ABI_TO_APK.put("mips64", APK_mips64);
88         ABI_TO_APK.put("mips", APK_mips);
89     }
90 
91     @Before
setUp()92     public void setUp() throws Exception {
93         Utils.prepareSingleUser(getDevice());
94         getDevice().uninstallPackage(PKG);
95         getDevice().uninstallPackage(PKG_NO_RESTART);
96     }
97 
98     @After
tearDown()99     public void tearDown() throws Exception {
100         getDevice().uninstallPackage(PKG);
101         getDevice().uninstallPackage(PKG_NO_RESTART);
102     }
103 
104     @Test
105     @AppModeFull(reason = "'full' portion of the hostside test")
testSingleBase_full()106     public void testSingleBase_full() throws Exception {
107         testSingleBase(false);
108     }
109     @Test
110     @AppModeInstant(reason = "'instant' portion of the hostside test")
testSingleBase_instant()111     public void testSingleBase_instant() throws Exception {
112         testSingleBase(true);
113     }
testSingleBase(boolean instant)114     private void testSingleBase(boolean instant) throws Exception {
115         new InstallMultiple(instant).addApk(APK).run();
116         runDeviceTests(PKG, CLASS, "testSingleBase");
117     }
118 
119     @Test
120     @AppModeFull(reason = "'full' portion of the hostside test")
testDensitySingle_full()121     public void testDensitySingle_full() throws Exception {
122         testDensitySingle(false);
123     }
124     @Test
125     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDensitySingle_instant()126     public void testDensitySingle_instant() throws Exception {
127         testDensitySingle(true);
128     }
testDensitySingle(boolean instant)129     private void testDensitySingle(boolean instant) throws Exception {
130         new InstallMultiple(instant).addApk(APK).addApk(APK_mdpi).run();
131         runDeviceTests(PKG, CLASS, "testDensitySingle");
132     }
133 
134     @Test
135     @AppModeFull(reason = "'full' portion of the hostside test")
testDensityAll_full()136     public void testDensityAll_full() throws Exception {
137         testDensityAll(false);
138     }
139     @Test
140     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDensityAll_instant()141     public void testDensityAll_instant() throws Exception {
142         testDensityAll(true);
143     }
testDensityAll(boolean instant)144     private void testDensityAll(boolean instant) throws Exception {
145         new InstallMultiple(instant).addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
146                 .addApk(APK_xxhdpi).run();
147         runDeviceTests(PKG, CLASS, "testDensityAll");
148     }
149 
150     /**
151      * Install first with low-resolution resources, then add a split that offers
152      * higher-resolution resources.
153      */
154     @Test
155     @AppModeFull(reason = "'full' portion of the hostside test")
testDensityBest_full()156     public void testDensityBest_full() throws Exception {
157         testDensityBest(false);
158     }
159     @Test
160     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDensityBest_instant()161     public void testDensityBest_instant() throws Exception {
162         testDensityBest(true);
163     }
testDensityBest(boolean instant)164     private void testDensityBest(boolean instant) throws Exception {
165         new InstallMultiple(instant).addApk(APK).addApk(APK_mdpi).run();
166         runDeviceTests(PKG, CLASS, "testDensityBest1");
167 
168         // Now splice in an additional split which offers better resources
169         new InstallMultiple(instant).inheritFrom(PKG).addApk(APK_xxhdpi).run();
170         runDeviceTests(PKG, CLASS, "testDensityBest2");
171     }
172 
173     /**
174      * Verify that an API-based split can change enabled/disabled state of
175      * manifest elements.
176      */
177     @Test
178     @AppModeFull(reason = "'full' portion of the hostside test")
testApi_full()179     public void testApi_full() throws Exception {
180         testApi(false);
181     }
182     @Test
183     @AppModeInstant(reason = "'instant' portion of the hostside test")
testApi_instant()184     public void testApi_instant() throws Exception {
185         testApi(true);
186     }
testApi(boolean instant)187     private void testApi(boolean instant) throws Exception {
188         new InstallMultiple(instant).addApk(APK).addApk(APK_v7).run();
189         runDeviceTests(PKG, CLASS, "testApi");
190     }
191 
192     @Test
193     @AppModeFull(reason = "'full' portion of the hostside test")
testLocale_full()194     public void testLocale_full() throws Exception {
195         testLocale(false);
196     }
197     @Test
198     @AppModeInstant(reason = "'instant' portion of the hostside test")
testLocale_instant()199     public void testLocale_instant() throws Exception {
200         testLocale(true);
201     }
testLocale(boolean instant)202     private void testLocale(boolean instant) throws Exception {
203         new InstallMultiple(instant).addApk(APK).addApk(APK_de).addApk(APK_fr).run();
204         runDeviceTests(PKG, CLASS, "testLocale");
205     }
206 
207     /**
208      * Install test app with <em>single</em> split that exactly matches the
209      * currently active ABI. This also explicitly forces ABI when installing.
210      */
211     @Test
212     @AppModeFull(reason = "'full' portion of the hostside test")
testNativeSingle_full()213     public void testNativeSingle_full() throws Exception {
214         testNativeSingle(false);
215     }
216     @Test
217     @AppModeInstant(reason = "'instant' portion of the hostside test")
testNativeSingle_instant()218     public void testNativeSingle_instant() throws Exception {
219         testNativeSingle(true);
220     }
testNativeSingle(boolean instant)221     private void testNativeSingle(boolean instant) throws Exception {
222         final String abi = getAbi().getName();
223         final String apk = ABI_TO_APK.get(abi);
224         assertNotNull("Failed to find APK for ABI " + abi, apk);
225 
226         new InstallMultiple(instant).addApk(APK).addApk(apk).run();
227         runDeviceTests(PKG, CLASS, "testNative");
228     }
229 
230     /**
231      * Install test app with <em>single</em> split that exactly matches the
232      * currently active ABI. This variant <em>does not</em> force the ABI when
233      * installing, instead exercising the system's ability to choose the ABI
234      * through inspection of the installed app.
235      */
236     @Test
237     @AppModeFull(reason = "'full' portion of the hostside test")
testNativeSingleNatural_full()238     public void testNativeSingleNatural_full() throws Exception {
239         testNativeSingleNatural(false);
240     }
241     @Test
242     @AppModeInstant(reason = "'instant' portion of the hostside test")
testNativeSingleNatural_instant()243     public void testNativeSingleNatural_instant() throws Exception {
244         testNativeSingleNatural(true);
245     }
testNativeSingleNatural(boolean instant)246     private void testNativeSingleNatural(boolean instant) throws Exception {
247         final String abi = getAbi().getName();
248         final String apk = ABI_TO_APK.get(abi);
249         assertNotNull("Failed to find APK for ABI " + abi, apk);
250 
251         new InstallMultiple(instant).useNaturalAbi().addApk(APK).addApk(apk).run();
252         runDeviceTests(PKG, CLASS, "testNative");
253     }
254 
255     /**
256      * Install test app with <em>all</em> possible ABI splits. This also
257      * explicitly forces ABI when installing.
258      */
259     @Test
260     @AppModeFull(reason = "'full' portion of the hostside test")
testNativeAll_full()261     public void testNativeAll_full() throws Exception {
262         testNativeAll(false);
263     }
264     @Test
265     @AppModeInstant(reason = "'instant' portion of the hostside test")
testNativeAll_instant()266     public void testNativeAll_instant() throws Exception {
267         testNativeAll(true);
268     }
testNativeAll(boolean instant)269     private void testNativeAll(boolean instant) throws Exception {
270         final InstallMultiple inst = new InstallMultiple(instant).addApk(APK);
271         for (String apk : ABI_TO_APK.values()) {
272             inst.addApk(apk);
273         }
274         inst.run();
275         runDeviceTests(PKG, CLASS, "testNative");
276     }
277 
278     /**
279      * Install test app with <em>all</em> possible ABI splits. This variant
280      * <em>does not</em> force the ABI when installing, instead exercising the
281      * system's ability to choose the ABI through inspection of the installed
282      * app.
283      */
284     @Test
285     @AppModeFull(reason = "'full' portion of the hostside test")
testNativeAllNatural_full()286     public void testNativeAllNatural_full() throws Exception {
287         testNativeAllNatural(false);
288     }
289     @Test
290     @AppModeInstant(reason = "'instant' portion of the hostside test")
testNativeAllNatural_instant()291     public void testNativeAllNatural_instant() throws Exception {
292         testNativeAllNatural(true);
293     }
testNativeAllNatural(boolean instant)294     private void testNativeAllNatural(boolean instant) throws Exception {
295         final InstallMultiple inst = new InstallMultiple(instant).useNaturalAbi().addApk(APK);
296         for (String apk : ABI_TO_APK.values()) {
297             inst.addApk(apk);
298         }
299         inst.run();
300         runDeviceTests(PKG, CLASS, "testNative");
301     }
302 
303     @Test
304     @AppModeFull(reason = "'full' portion of the hostside test")
testDuplicateBase_full()305     public void testDuplicateBase_full() throws Exception {
306         testDuplicateBase(false);
307     }
308     @Test
309     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDuplicateBase_instant()310     public void testDuplicateBase_instant() throws Exception {
311         testDuplicateBase(true);
312     }
testDuplicateBase(boolean instant)313     private void testDuplicateBase(boolean instant) throws Exception {
314         new InstallMultiple(instant).addApk(APK).addApk(APK).runExpectingFailure();
315     }
316 
317     @Test
318     @AppModeFull(reason = "'full' portion of the hostside test")
testDuplicateSplit_full()319     public void testDuplicateSplit_full() throws Exception {
320         testDuplicateSplit(false);
321     }
322     @Test
323     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDuplicateSplit_instant()324     public void testDuplicateSplit_instant() throws Exception {
325         testDuplicateSplit(true);
326     }
testDuplicateSplit(boolean instant)327     private void testDuplicateSplit(boolean instant) throws Exception {
328         new InstallMultiple(instant).addApk(APK).addApk(APK_v7).addApk(APK_v7).runExpectingFailure();
329     }
330 
331     @Test
332     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffCert_full()333     public void testDiffCert_full() throws Exception {
334         testDiffCert(false);
335     }
336     @Test
337     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffCert_instant()338     public void testDiffCert_instant() throws Exception {
339         testDiffCert(true);
340     }
testDiffCert(boolean instant)341     private void testDiffCert(boolean instant) throws Exception {
342         new InstallMultiple(instant).addApk(APK).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
343     }
344 
345     @Test
346     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffCertInherit_full()347     public void testDiffCertInherit_full() throws Exception {
348         testDiffCertInherit(false);
349     }
350     @Test
351     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffCertInherit_instant()352     public void testDiffCertInherit_instant() throws Exception {
353         testDiffCertInherit(true);
354     }
testDiffCertInherit(boolean instant)355     private void testDiffCertInherit(boolean instant) throws Exception {
356         new InstallMultiple(instant).addApk(APK).run();
357         new InstallMultiple(instant).inheritFrom(PKG).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
358     }
359 
360     @Test
361     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffVersion_full()362     public void testDiffVersion_full() throws Exception {
363         testDiffVersion(false);
364     }
365     @Test
366     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffVersion_instant()367     public void testDiffVersion_instant() throws Exception {
368         testDiffVersion(true);
369     }
testDiffVersion(boolean instant)370     private void testDiffVersion(boolean instant) throws Exception {
371         new InstallMultiple(instant).addApk(APK).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
372     }
373 
374     @Test
375     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffVersionInherit_full()376     public void testDiffVersionInherit_full() throws Exception {
377         testDiffVersionInherit(false);
378     }
379     @Test
380     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffVersionInherit_instant()381     public void testDiffVersionInherit_instant() throws Exception {
382         testDiffVersionInherit(true);
383     }
testDiffVersionInherit(boolean instant)384     private void testDiffVersionInherit(boolean instant) throws Exception {
385         new InstallMultiple(instant).addApk(APK).run();
386         new InstallMultiple(instant).inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
387     }
388 
389     @Test
390     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffRevision_full()391     public void testDiffRevision_full() throws Exception {
392         testDiffRevision(false);
393     }
394     @Test
395     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffRevision_instant()396     public void testDiffRevision_instant() throws Exception {
397         testDiffRevision(true);
398     }
testDiffRevision(boolean instant)399     private void testDiffRevision(boolean instant) throws Exception {
400         new InstallMultiple(instant).addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
401         runDeviceTests(PKG, CLASS, "testRevision0_12");
402     }
403 
404     @Test
405     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffRevisionInheritBase_full()406     public void testDiffRevisionInheritBase_full() throws Exception {
407         testDiffRevisionInheritBase(false);
408     }
409     @Test
410     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffRevisionInheritBase_instant()411     public void testDiffRevisionInheritBase_instant() throws Exception {
412         testDiffRevisionInheritBase(true);
413     }
testDiffRevisionInheritBase(boolean instant)414     private void testDiffRevisionInheritBase(boolean instant) throws Exception {
415         new InstallMultiple(instant).addApk(APK).addApk(APK_v7).run();
416         runDeviceTests(PKG, CLASS, "testRevision0_0");
417         new InstallMultiple(instant).inheritFrom(PKG).addApk(APK_DIFF_REVISION_v7).run();
418         runDeviceTests(PKG, CLASS, "testRevision0_12");
419     }
420 
421     @Test
422     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffRevisionInheritSplit_full()423     public void testDiffRevisionInheritSplit_full() throws Exception {
424         testDiffRevisionInheritSplit(false);
425     }
426     @Test
427     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffRevisionInheritSplit_instant()428     public void testDiffRevisionInheritSplit_instant() throws Exception {
429         testDiffRevisionInheritSplit(true);
430     }
testDiffRevisionInheritSplit(boolean instant)431     private void testDiffRevisionInheritSplit(boolean instant) throws Exception {
432         new InstallMultiple(instant).addApk(APK).addApk(APK_v7).run();
433         runDeviceTests(PKG, CLASS, "testRevision0_0");
434         new InstallMultiple(instant).inheritFrom(PKG).addApk(APK_DIFF_REVISION).run();
435         runDeviceTests(PKG, CLASS, "testRevision12_0");
436     }
437 
438     @Test
439     @AppModeFull(reason = "'full' portion of the hostside test")
testDiffRevisionDowngrade_full()440     public void testDiffRevisionDowngrade_full() throws Exception {
441         testDiffRevisionDowngrade(false);
442     }
443     @Test
444     @AppModeInstant(reason = "'instant' portion of the hostside test")
testDiffRevisionDowngrade_instant()445     public void testDiffRevisionDowngrade_instant() throws Exception {
446         testDiffRevisionDowngrade(true);
447     }
testDiffRevisionDowngrade(boolean instant)448     private void testDiffRevisionDowngrade(boolean instant) throws Exception {
449         new InstallMultiple(instant).addApk(APK).addApk(APK_DIFF_REVISION_v7).run();
450         new InstallMultiple(instant).inheritFrom(PKG).addApk(APK_v7).runExpectingFailure();
451     }
452 
453     @Test
454     @AppModeFull(reason = "'full' portion of the hostside test")
testFeatureBase_full()455     public void testFeatureBase_full() throws Exception {
456         testFeatureBase(false);
457     }
458     @Test
459     @AppModeInstant(reason = "'instant' portion of the hostside test")
testFeatureBase_instant()460     public void testFeatureBase_instant() throws Exception {
461         testFeatureBase(true);
462     }
testFeatureBase(boolean instant)463     private void testFeatureBase(boolean instant) throws Exception {
464         new InstallMultiple(instant).addApk(APK).addApk(APK_FEATURE).run();
465         runDeviceTests(PKG, CLASS, "testFeatureBase");
466     }
467 
468     @Test
469     @AppModeFull(reason = "'full' portion of the hostside test")
testFeatureApi_full()470     public void testFeatureApi_full() throws Exception {
471         testFeatureApi(false);
472     }
473     @Test
474     @AppModeInstant(reason = "'instant' portion of the hostside test")
testFeatureApi_instant()475     public void testFeatureApi_instant() throws Exception {
476         testFeatureApi(true);
477     }
testFeatureApi(boolean instant)478     private void testFeatureApi(boolean instant) throws Exception {
479         new InstallMultiple(instant).addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
480         runDeviceTests(PKG, CLASS, "testFeatureApi");
481     }
482 
483     @Test
484     @AppModeFull(reason = "'full' portion of the hostside test")
testInheritUpdatedBase()485     public void testInheritUpdatedBase() throws Exception {
486         // TODO: flesh out this test
487     }
488 
489     @Test
490     @AppModeFull(reason = "'full' portion of the hostside test")
testInheritUpdatedSplit()491     public void testInheritUpdatedSplit() throws Exception {
492         // TODO: flesh out this test
493     }
494 
495     @Test
496     @AppModeFull(reason = "'full' portion of the hostside test")
testFeatureWithoutRestart_full()497     public void testFeatureWithoutRestart_full() throws Exception {
498         testFeatureWithoutRestart(false);
499     }
500     @Test
501     @AppModeInstant(reason = "'instant' portion of the hostside test")
testFeatureWithoutRestart_instant()502     public void testFeatureWithoutRestart_instant() throws Exception {
503         testFeatureWithoutRestart(true);
504     }
testFeatureWithoutRestart(boolean instant)505     private void testFeatureWithoutRestart(boolean instant) throws Exception {
506         // always install as a full app; we're testing that the instant app can be
507         // updated without restarting and need a broadcast receiver to ensure the
508         // correct behaviour. So, this component must be visible to instant apps.
509         new InstallMultiple().addApk(APK).run();
510 
511         new InstallMultiple(instant).addApk(APK_NO_RESTART_BASE).run();
512         runDeviceTests(PKG, CLASS, "testBaseInstalled", instant);
513         new InstallMultiple(instant)
514                 .addArg("--dont-kill")
515                 .inheritFrom(PKG_NO_RESTART)
516                 .addApk(APK_NO_RESTART_FEATURE)
517                 .run();
518         runDeviceTests(PKG, CLASS, "testFeatureInstalled", instant);
519     }
520 
521     @Test
522     @AppModeFull(reason = "'full' portion of the hostside test")
testRequiredSplitMissing_full()523     public void testRequiredSplitMissing_full() throws Exception {
524         testSingleBase(false);
525     }
526     @Test
527     @AppModeInstant(reason = "'instant' portion of the hostside test")
testRequiredSplitMissing_instant()528     public void testRequiredSplitMissing_instant() throws Exception {
529         testSingleBase(true);
530     }
testRequiredSplitMissing(boolean instant)531     private void testRequiredSplitMissing(boolean instant) throws Exception {
532         new InstallMultiple(instant).addApk(APK_NEED_SPLIT_BASE)
533                 .runExpectingFailure("INSTALL_FAILED_MISSING_SPLIT");
534     }
535 
536     @Test
537     @AppModeFull(reason = "'full' portion of the hostside test")
testRequiredSplitInstalledFeature_full()538     public void testRequiredSplitInstalledFeature_full() throws Exception {
539         testSingleBase(false);
540     }
541     @Test
542     @AppModeInstant(reason = "'instant' portion of the hostside test")
testRequiredSplitInstalledFeature_instant()543     public void testRequiredSplitInstalledFeature_instant() throws Exception {
544         testSingleBase(true);
545     }
testRequiredSplitInstalledFeature(boolean instant)546     private void testRequiredSplitInstalledFeature(boolean instant) throws Exception {
547         new InstallMultiple(instant).addApk(APK_NEED_SPLIT_BASE).addApk(APK_NEED_SPLIT_FEATURE)
548                 .run();
549     }
550 
551     @Test
552     @AppModeFull(reason = "'full' portion of the hostside test")
testRequiredSplitInstalledConfig_full()553     public void testRequiredSplitInstalledConfig_full() throws Exception {
554         testSingleBase(false);
555     }
556     @Test
557     @AppModeInstant(reason = "'instant' portion of the hostside test")
testRequiredSplitInstalledConfig_instant()558     public void testRequiredSplitInstalledConfig_instant() throws Exception {
559         testSingleBase(true);
560     }
testRequiredSplitInstalledConfig(boolean instant)561     private void testRequiredSplitInstalledConfig(boolean instant) throws Exception {
562         new InstallMultiple(instant).addApk(APK_NEED_SPLIT_BASE).addApk(APK_NEED_SPLIT_CONFIG)
563                 .run();
564     }
565 
566     @Test
567     @AppModeFull(reason = "'full' portion of the hostside test")
testRequiredSplitRemoved_full()568     public void testRequiredSplitRemoved_full() throws Exception {
569         testSingleBase(false);
570     }
571     @Test
572     @AppModeInstant(reason = "'instant' portion of the hostside test")
testRequiredSplitRemoved_instant()573     public void testRequiredSplitRemoved_instant() throws Exception {
574         testSingleBase(true);
575     }
testRequiredSplitRemoved(boolean instant)576     private void testRequiredSplitRemoved(boolean instant) throws Exception {
577         // start with a base and two splits
578         new InstallMultiple(instant)
579                 .addApk(APK_NEED_SPLIT_BASE)
580                 .addApk(APK_NEED_SPLIT_FEATURE)
581                 .addApk(APK_NEED_SPLIT_CONFIG)
582                 .run();
583         // it's okay to remove one of the splits
584         new InstallMultiple(instant).inheritFrom(PKG).removeSplit("split_feature").run();
585         // but, not to remove all of them
586         new InstallMultiple(instant).inheritFrom(PKG).removeSplit("split_config.xxhdpi")
587                 .runExpectingFailure("INSTALL_FAILED_MISSING_SPLIT");
588     }
589 
590     /**
591      * Verify that installing a new version of app wipes code cache.
592      */
593     @Test
594     @AppModeFull(reason = "'full' portion of the hostside test")
testClearCodeCache_full()595     public void testClearCodeCache_full() throws Exception {
596         testClearCodeCache(false);
597     }
598     @Test
599     @AppModeInstant(reason = "'instant' portion of the hostside test")
testClearCodeCache_instant()600     public void testClearCodeCache_instant() throws Exception {
601         testClearCodeCache(true);
602     }
testClearCodeCache(boolean instant)603     private void testClearCodeCache(boolean instant) throws Exception {
604         new InstallMultiple(instant).addApk(APK).run();
605         runDeviceTests(PKG, CLASS, "testCodeCacheWrite");
606         new InstallMultiple(instant).addArg("-r").addApk(APK_DIFF_VERSION).run();
607         runDeviceTests(PKG, CLASS, "testCodeCacheRead");
608     }
609 }
610