1 /*
2  * Copyright (C) 2016 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 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.fail;
22 
23 import android.platform.test.annotations.AppModeFull;
24 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
25 import com.android.tradefed.log.LogUtil.CLog;
26 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
27 
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 
38 /**
39  * Tests for ephemeral packages.
40  */
41 @RunWith(DeviceJUnit4ClassRunner.class)
42 @AppModeFull(reason = "Already handles instant installs when needed")
43 public class EphemeralTest extends BaseAppSecurityTest {
44 
45     // a normally installed application
46     private static final String NORMAL_APK = "CtsEphemeralTestsNormalApp.apk";
47     private static final String NORMAL_PKG = "com.android.cts.normalapp";
48 
49     // the first ephemerally installed application
50     private static final String EPHEMERAL_1_APK = "CtsEphemeralTestsEphemeralApp1.apk";
51     private static final String EPHEMERAL_1_PKG = "com.android.cts.ephemeralapp1";
52 
53     // the second ephemerally installed application
54     private static final String EPHEMERAL_2_APK = "CtsEphemeralTestsEphemeralApp2.apk";
55     private static final String EPHEMERAL_2_PKG = "com.android.cts.ephemeralapp2";
56 
57     // a normally installed application with implicitly exposed components
58     private static final String IMPLICIT_APK = "CtsEphemeralTestsImplicitApp.apk";
59     private static final String IMPLICIT_PKG = "com.android.cts.implicitapp";
60 
61     // a normally installed application with no exposed components
62     private static final String UNEXPOSED_APK = "CtsEphemeralTestsUnexposedApp.apk";
63     private static final String UNEXPOSED_PKG = "com.android.cts.unexposedapp";
64 
65     // an application that gets upgraded from 'instant' to 'full'
66     private static final String UPGRADED_APK = "CtsInstantUpgradeApp.apk";
67     private static final String UPGRADED_PKG = "com.android.cts.instantupgradeapp";
68 
69     private static final String TEST_CLASS = ".ClientTest";
70     private static final String WEBVIEW_TEST_CLASS = ".WebViewTest";
71 
72     private static final List<Map<String, String>> EXPECTED_EXPOSED_INTENTS =
73             new ArrayList<>();
74     static {
75         // Framework intents we expect the system to expose to instant applications
76         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
77                 "android.intent.action.CHOOSER",
78                 null, null));
79         // Contact intents we expect the system to expose to instant applications
80         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
81                 "android.intent.action.PICK", null, "vnd.android.cursor.dir/contact"));
82         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
83                 "android.intent.action.PICK", null, "vnd.android.cursor.dir/phone_v2"));
84         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
85                 "android.intent.action.PICK", null, "vnd.android.cursor.dir/email_v2"));
86         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
87                 "android.intent.action.PICK", null, "vnd.android.cursor.dir/postal-address_v2"));
88         // Storage intents we expect the system to expose to instant applications
89         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
90                 "android.intent.action.OPEN_DOCUMENT",
91                 "android.intent.category.OPENABLE", "\\*/\\*"));
92         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
93                 "android.intent.action.OPEN_DOCUMENT", null, "\\*/\\*"));
94         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
95                 "android.intent.action.GET_CONTENT",
96                 "android.intent.category.OPENABLE", "\\*/\\*"));
97         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
98                 "android.intent.action.GET_CONTENT", null, "\\*/\\*"));
99         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
100                 "android.intent.action.OPEN_DOCUMENT_TREE", null, null));
101         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
102                 "android.intent.action.CREATE_DOCUMENT",
103                 "android.intent.category.OPENABLE", "text/plain"));
104         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
105                 "android.intent.action.CREATE_DOCUMENT", null, "text/plain"));
106         /** Camera intents we expect the system to expose to instant applications */
107         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
108                 "android.media.action.IMAGE_CAPTURE", null, null));
109         EXPECTED_EXPOSED_INTENTS.add(makeArgs(
110                 "android.media.action.VIDEO_CAPTURE", null, null));
111     }
112 
113     private String mOldVerifierValue;
114     private Boolean mIsUnsupportedDevice;
115 
116     @Before
setUp()117     public void setUp() throws Exception {
118         mIsUnsupportedDevice = isDeviceUnsupported();
119         if (mIsUnsupportedDevice) {
120             return;
121         }
122 
123         Utils.prepareSingleUser(getDevice());
124         assertNotNull(getAbi());
125         assertNotNull(getBuild());
126 
127         uninstallTestPackages();
128         installTestPackages();
129     }
130 
131     @After
tearDown()132     public void tearDown() throws Exception {
133         if (mIsUnsupportedDevice) {
134             return;
135         }
136         uninstallTestPackages();
137     }
138 
139     @Test
testNormalQuery()140     public void testNormalQuery() throws Exception {
141         if (mIsUnsupportedDevice) {
142             return;
143         }
144         Utils.runDeviceTestsAsCurrentUser(getDevice(), NORMAL_PKG, TEST_CLASS, "testQuery");
145     }
146 
147     @Test
testNormalStartNormal()148     public void testNormalStartNormal() throws Exception {
149         if (mIsUnsupportedDevice) {
150             return;
151         }
152         Utils.runDeviceTestsAsCurrentUser(getDevice(), NORMAL_PKG, TEST_CLASS, "testStartNormal");
153     }
154 
155     @Test
testNormalStartEphemeral()156     public void testNormalStartEphemeral() throws Exception {
157         if (mIsUnsupportedDevice) {
158             return;
159         }
160         Utils.runDeviceTestsAsCurrentUser(getDevice(), NORMAL_PKG, TEST_CLASS,
161                 "testStartEphemeral");
162     }
163 
164     @Test
testEphemeralQuery()165     public void testEphemeralQuery() throws Exception {
166         if (mIsUnsupportedDevice) {
167             return;
168         }
169         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS, "testQuery");
170     }
171 
172     @Test
testEphemeralStartNormal()173     public void testEphemeralStartNormal() throws Exception {
174         if (mIsUnsupportedDevice) {
175             return;
176         }
177         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
178                 "testStartNormal");
179     }
180 
181     // each connection to an exposed component needs to run in its own test to
182     // avoid sharing state. once an instant app is exposed to a component, it's
183     // exposed until the device restarts or the instant app is removed.
184     @Test
testEphemeralStartExposed01()185     public void testEphemeralStartExposed01() throws Exception {
186         if (mIsUnsupportedDevice) {
187             return;
188         }
189         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
190                 "testStartExposed01");
191     }
192     @Test
testEphemeralStartExposed02()193     public void testEphemeralStartExposed02() throws Exception {
194         if (mIsUnsupportedDevice) {
195             return;
196         }
197         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
198                 "testStartExposed02");
199     }
200     @Test
testEphemeralStartExposed03()201     public void testEphemeralStartExposed03() throws Exception {
202         if (mIsUnsupportedDevice) {
203             return;
204         }
205         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
206                 "testStartExposed03");
207     }
208     @Test
testEphemeralStartExposed04()209     public void testEphemeralStartExposed04() throws Exception {
210         if (mIsUnsupportedDevice) {
211             return;
212         }
213         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
214                 "testStartExposed04");
215     }
216     @Test
testEphemeralStartExposed05()217     public void testEphemeralStartExposed05() throws Exception {
218         if (mIsUnsupportedDevice) {
219             return;
220         }
221         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
222                 "testStartExposed05");
223     }
224     @Test
testEphemeralStartExposed06()225     public void testEphemeralStartExposed06() throws Exception {
226         if (mIsUnsupportedDevice) {
227             return;
228         }
229         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
230                 "testStartExposed06");
231     }
232     @Test
testEphemeralStartExposed07()233     public void testEphemeralStartExposed07() throws Exception {
234         if (mIsUnsupportedDevice) {
235             return;
236         }
237         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
238                 "testStartExposed07");
239     }
240     @Test
testEphemeralStartExposed08()241     public void testEphemeralStartExposed08() throws Exception {
242         if (mIsUnsupportedDevice) {
243             return;
244         }
245         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
246                 "testStartExposed08");
247     }
248     @Test
testEphemeralStartExposed09()249     public void testEphemeralStartExposed09() throws Exception {
250         if (mIsUnsupportedDevice) {
251             return;
252         }
253         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
254                 "testStartExposed09");
255     }
256     @Test
testEphemeralStartExposed10()257     public void testEphemeralStartExposed10() throws Exception {
258         if (mIsUnsupportedDevice) {
259             return;
260         }
261         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
262                 "testStartExposed10");
263     }
264 
265     @Test
testEphemeralStartEphemeral()266     public void testEphemeralStartEphemeral() throws Exception {
267         if (mIsUnsupportedDevice) {
268             return;
269         }
270         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
271                 "testStartEphemeral");
272     }
273 
274     @Test
testEphemeralGetInstaller01()275     public void testEphemeralGetInstaller01() throws Exception {
276         if (mIsUnsupportedDevice) {
277             return;
278         }
279         installEphemeralApp(EPHEMERAL_1_APK, "com.android.cts.normalapp");
280         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
281                 "testGetInstaller01");
282     }
283     @Test
testEphemeralGetInstaller02()284     public void testEphemeralGetInstaller02() throws Exception {
285         if (mIsUnsupportedDevice) {
286             return;
287         }
288         installApp(NORMAL_APK, "com.android.cts.normalapp");
289         installEphemeralApp(EPHEMERAL_1_APK, "com.android.cts.normalapp");
290         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
291                 "testGetInstaller02");
292     }
293     @Test
testEphemeralGetInstaller03()294     public void testEphemeralGetInstaller03() throws Exception {
295         if (mIsUnsupportedDevice) {
296             return;
297         }
298         installApp(NORMAL_APK, "com.android.cts.normalapp");
299         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
300                 "testGetInstaller03");
301     }
302 
303     @Test
testExposedSystemActivities()304     public void testExposedSystemActivities() throws Exception {
305         if (mIsUnsupportedDevice) {
306             return;
307         }
308         for (Map<String, String> testArgs : EXPECTED_EXPOSED_INTENTS) {
309             final boolean exposed = isIntentExposed(testArgs);
310             if (exposed) {
311                 Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
312                         "testExposedActivity", testArgs);
313             } else {
314                 CLog.w("Skip intent; " + dumpArgs(testArgs));
315             }
316         }
317     }
318 
319     @Test
testBuildSerialUnknown()320     public void testBuildSerialUnknown() throws Exception {
321         if (mIsUnsupportedDevice) {
322             return;
323         }
324         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
325                 "testBuildSerialUnknown");
326     }
327 
328     @Test
testPackageInfo()329     public void testPackageInfo() throws Exception {
330         if (mIsUnsupportedDevice) {
331             return;
332         }
333         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
334                 "testPackageInfo");
335     }
336 
337     @Test
testActivityInfo()338     public void testActivityInfo() throws Exception {
339         if (mIsUnsupportedDevice) {
340             return;
341         }
342         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
343                 "testActivityInfo");
344     }
345 
346     @Test
testWebViewLoads()347     public void testWebViewLoads() throws Exception {
348         if (mIsUnsupportedDevice) {
349             return;
350         }
351         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, WEBVIEW_TEST_CLASS,
352                 "testWebViewLoads");
353     }
354 
355     @Test
testInstallPermissionNotGranted()356     public void testInstallPermissionNotGranted() throws Exception {
357         if (mIsUnsupportedDevice) {
358             return;
359         }
360         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
361                 "testInstallPermissionNotGranted");
362     }
363 
364     @Test
testInstallPermissionGranted()365     public void testInstallPermissionGranted() throws Exception {
366         if (mIsUnsupportedDevice) {
367             return;
368         }
369         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
370                 "testInstallPermissionGranted");
371     }
372 
373     /** Test for android.permission.INSTANT_APP_FOREGROUND_SERVICE */
374     @Test
testStartForegroundService()375     public void testStartForegroundService() throws Exception {
376         if (mIsUnsupportedDevice) {
377             return;
378         }
379         // Make sure the test package does not have INSTANT_APP_FOREGROUND_SERVICE
380         getDevice().executeShellCommand("cmd package revoke " + EPHEMERAL_1_PKG
381                 + " android.permission.INSTANT_APP_FOREGROUND_SERVICE");
382         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
383                 "testStartForegroundService");
384     }
385 
386     /** Test for android.permission.RECORD_AUDIO */
387     @Test
testRecordAudioPermission()388     public void testRecordAudioPermission() throws Exception {
389         if (mIsUnsupportedDevice) {
390             return;
391         }
392         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
393                 "testRecordAudioPermission");
394     }
395 
396     /** Test for android.permission.CAMERA */
397     @Test
testCameraPermission()398     public void testCameraPermission() throws Exception {
399         if (mIsUnsupportedDevice) {
400             return;
401         }
402         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
403                 "testCameraPermission");
404     }
405 
406     /** Test for android.permission.READ_PHONE_NUMBERS */
407     @Test
testReadPhoneNumbersPermission()408     public void testReadPhoneNumbersPermission() throws Exception {
409         if (mIsUnsupportedDevice) {
410             return;
411         }
412         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
413                 "testReadPhoneNumbersPermission");
414     }
415 
416     /** Test for android.permission.ACCESS_COARSE_LOCATION */
417     @Test
testAccessCoarseLocationPermission()418     public void testAccessCoarseLocationPermission() throws Throwable {
419         if (mIsUnsupportedDevice) {
420             return;
421         }
422         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
423                 "testAccessCoarseLocationPermission");
424     }
425 
426     /** Test for android.permission.NETWORK */
427     @Test
testInternetPermission()428     public void testInternetPermission() throws Throwable {
429         if (mIsUnsupportedDevice) {
430             return;
431         }
432         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
433                 "testInternetPermission");
434     }
435 
436     /** Test for android.permission.VIBRATE */
437     @Test
testVibratePermission()438     public void testVibratePermission() throws Throwable {
439         if (mIsUnsupportedDevice) {
440             return;
441         }
442         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
443                 "testVibratePermission");
444     }
445 
446     /** Test for android.permission.WAKE_LOCK */
447     @Test
testWakeLockPermission()448     public void testWakeLockPermission() throws Throwable {
449         if (mIsUnsupportedDevice) {
450             return;
451         }
452         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
453                 "testWakeLockPermission");
454     }
455 
456     /** Test for search manager */
457     @Test
testGetSearchableInfo()458     public void testGetSearchableInfo() throws Throwable {
459         if (mIsUnsupportedDevice) {
460             return;
461         }
462         Utils.runDeviceTestsAsCurrentUser(getDevice(), EPHEMERAL_1_PKG, TEST_CLASS,
463                 "testGetSearchableInfo");
464     }
465 
466     /** Test for upgrade from instant --> full */
467     @Test
testInstantAppUpgrade()468     public void testInstantAppUpgrade() throws Throwable {
469         if (mIsUnsupportedDevice) {
470             return;
471         }
472         installEphemeralApp(UPGRADED_APK);
473         Utils.runDeviceTestsAsCurrentUser(getDevice(), UPGRADED_PKG, TEST_CLASS,
474                 "testInstantApplicationWritePreferences");
475         Utils.runDeviceTestsAsCurrentUser(getDevice(), UPGRADED_PKG, TEST_CLASS,
476                 "testInstantApplicationWriteFile");
477         installFullApp(UPGRADED_APK);
478         Utils.runDeviceTestsAsCurrentUser(getDevice(), UPGRADED_PKG, TEST_CLASS,
479                 "testFullApplicationReadPreferences");
480         Utils.runDeviceTestsAsCurrentUser(getDevice(), UPGRADED_PKG, TEST_CLASS,
481                 "testFullApplicationReadFile");
482     }
483 
makeArgs( String action, String category, String mimeType)484     private static final HashMap<String, String> makeArgs(
485             String action, String category, String mimeType) {
486         if (action == null || action.length() == 0) {
487             fail("action not specified");
488         }
489         final HashMap<String, String> testArgs = new HashMap<>();
490         testArgs.put("action", action);
491         if (category != null && category.length() > 0) {
492             testArgs.put("category", category);
493         }
494         if (mimeType != null && mimeType.length() > 0) {
495             testArgs.put("mime_type", mimeType);
496         }
497         return testArgs;
498     }
499 
500     private static final String[] sUnsupportedFeatures = {
501             "feature:android.hardware.type.watch",
502             "android.hardware.type.embedded",
503     };
isDeviceUnsupported()504     private boolean isDeviceUnsupported() throws Exception {
505         for (String unsupportedFeature : sUnsupportedFeatures) {
506             if (getDevice().hasFeature(unsupportedFeature)) {
507                 return true;
508             }
509         }
510         return false;
511     }
512 
isIntentExposed(Map<String, String> testArgs)513     private boolean isIntentExposed(Map<String, String> testArgs)
514             throws Exception {
515         final StringBuffer command = new StringBuffer();
516         command.append("cmd package query-activities");
517         command.append(" -a ").append(testArgs.get("action"));
518         if (testArgs.get("category") != null) {
519             command.append(" -c ").append(testArgs.get("category"));
520         }
521         if (testArgs.get("mime_type") != null) {
522             command.append(" -t ").append(testArgs.get("mime_type"));
523         }
524         final String output = getDevice().executeShellCommand(command.toString()).trim();
525         return !"No activities found".equals(output);
526     }
527 
dumpArgs(Map<String, String> testArgs)528     private static final String dumpArgs(Map<String, String> testArgs) {
529         final StringBuffer dump = new StringBuffer();
530         dump.append("action: ").append(testArgs.get("action"));
531         if (testArgs.get("category") != null) {
532             dump.append(", category: ").append(testArgs.get("category"));
533         }
534         if (testArgs.get("mime_type") != null) {
535             dump.append(", type: ").append(testArgs.get("mime_type"));
536         }
537         return dump.toString();
538     }
539 
installApp(String apk)540     private void installApp(String apk) throws Exception {
541         new InstallMultiple(false /* instant */)
542                 .addApk(apk)
543                 .run();
544     }
545 
installApp(String apk, String installer)546     private void installApp(String apk, String installer) throws Exception {
547         new InstallMultiple(false /* instant */)
548                 .addApk(apk)
549                 .addArg("-i " + installer)
550                 .run();
551     }
552 
installEphemeralApp(String apk)553     private void installEphemeralApp(String apk) throws Exception {
554         new InstallMultiple(true /* instant */)
555                 .addApk(apk)
556                 .run();
557     }
558 
installEphemeralApp(String apk, String installer)559     private void installEphemeralApp(String apk, String installer) throws Exception {
560         new InstallMultiple(true /* instant */)
561                 .addApk(apk)
562                 .addArg("-i " + installer)
563                 .run();
564     }
565 
installFullApp(String apk)566     private void installFullApp(String apk) throws Exception {
567         new InstallMultiple(false /* instant */)
568                 .addApk(apk)
569                 .addArg("--full")
570                 .run();
571     }
572 
installTestPackages()573     private void installTestPackages() throws Exception {
574         installApp(NORMAL_APK);
575         installApp(UNEXPOSED_APK);
576         installApp(IMPLICIT_APK);
577 
578         installEphemeralApp(EPHEMERAL_1_APK);
579         installEphemeralApp(EPHEMERAL_2_APK);
580     }
581 
uninstallTestPackages()582     private void uninstallTestPackages() throws Exception {
583         uninstallPackage(NORMAL_PKG);
584         uninstallPackage(UNEXPOSED_PKG);
585         uninstallPackage(IMPLICIT_PKG);
586         uninstallPackage(EPHEMERAL_1_PKG);
587         uninstallPackage(EPHEMERAL_2_PKG);
588         uninstallPackage(UPGRADED_PKG);
589     }
590 }
591