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 android.content.pm.cts;
18 
19 import static android.content.Context.RECEIVER_EXPORTED;
20 import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
21 import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256;
22 import static android.content.pm.Flags.FLAG_SDK_LIB_INDEPENDENCE;
23 import static android.content.pm.PackageInstaller.DATA_LOADER_TYPE_INCREMENTAL;
24 import static android.content.pm.PackageInstaller.DATA_LOADER_TYPE_NONE;
25 import static android.content.pm.PackageInstaller.DATA_LOADER_TYPE_STREAMING;
26 import static android.content.pm.PackageInstaller.EXTRA_DATA_LOADER_TYPE;
27 import static android.content.pm.PackageInstaller.EXTRA_SESSION_ID;
28 import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
29 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
30 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ROOT_HASH;
31 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
32 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES;
33 import static android.content.pm.PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES;
34 import static android.content.pm.PackageManager.VERIFICATION_ALLOW;
35 import static android.content.pm.PackageManager.VERIFICATION_REJECT;
36 
37 import static com.google.common.truth.Truth.assertThat;
38 
39 import static org.junit.Assert.assertEquals;
40 import static org.junit.Assert.assertFalse;
41 import static org.junit.Assert.assertNotEquals;
42 import static org.junit.Assert.assertNotNull;
43 import static org.junit.Assert.assertNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.junit.Assume.assumeFalse;
46 import static org.junit.Assume.assumeTrue;
47 import static org.testng.Assert.assertThrows;
48 import static org.testng.Assert.expectThrows;
49 
50 import android.Manifest;
51 import android.app.UiAutomation;
52 import android.app.usage.StorageStats;
53 import android.app.usage.StorageStatsManager;
54 import android.content.BroadcastReceiver;
55 import android.content.ComponentName;
56 import android.content.Context;
57 import android.content.IIntentReceiver;
58 import android.content.IIntentSender;
59 import android.content.Intent;
60 import android.content.IntentFilter;
61 import android.content.IntentSender;
62 import android.content.pm.ApkChecksum;
63 import android.content.pm.ApplicationInfo;
64 import android.content.pm.DataLoaderParams;
65 import android.content.pm.Flags;
66 import android.content.pm.PackageInfo;
67 import android.content.pm.PackageInstaller;
68 import android.content.pm.PackageInstaller.SessionParams;
69 import android.content.pm.PackageManager;
70 import android.content.pm.ResolveInfo;
71 import android.content.pm.SharedLibraryInfo;
72 import android.content.pm.Signature;
73 import android.content.pm.SigningInfo;
74 import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
75 import android.os.Bundle;
76 import android.os.IBinder;
77 import android.os.ParcelFileDescriptor;
78 import android.os.Process;
79 import android.os.RemoteException;
80 import android.os.UserHandle;
81 import android.os.storage.StorageManager;
82 import android.platform.test.annotations.AppModeFull;
83 import android.platform.test.annotations.AppModeNonSdkSandbox;
84 import android.platform.test.annotations.RequiresFlagsDisabled;
85 import android.platform.test.annotations.RequiresFlagsEnabled;
86 import android.platform.test.flag.junit.CheckFlagsRule;
87 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
88 import android.util.PackageUtils;
89 
90 import androidx.test.InstrumentationRegistry;
91 import androidx.test.filters.LargeTest;
92 
93 import com.android.compatibility.common.util.SystemUtil;
94 import com.android.internal.util.ConcurrentUtils;
95 import com.android.internal.util.HexDump;
96 
97 import libcore.util.HexEncoding;
98 
99 import org.junit.AfterClass;
100 import org.junit.Before;
101 import org.junit.BeforeClass;
102 import org.junit.Rule;
103 import org.junit.Test;
104 import org.junit.runner.RunWith;
105 import org.junit.runners.Parameterized;
106 import org.junit.runners.Parameterized.Parameter;
107 import org.junit.runners.Parameterized.Parameters;
108 
109 import java.io.ByteArrayOutputStream;
110 import java.io.File;
111 import java.io.FileInputStream;
112 import java.io.FileOutputStream;
113 import java.io.IOException;
114 import java.io.InputStream;
115 import java.io.OutputStream;
116 import java.security.cert.CertificateEncodingException;
117 import java.text.DecimalFormat;
118 import java.util.ArrayList;
119 import java.util.Arrays;
120 import java.util.List;
121 import java.util.Optional;
122 import java.util.Random;
123 import java.util.concurrent.CompletableFuture;
124 import java.util.concurrent.TimeUnit;
125 import java.util.concurrent.TimeoutException;
126 import java.util.concurrent.atomic.AtomicInteger;
127 import java.util.concurrent.atomic.AtomicReference;
128 import java.util.function.BiConsumer;
129 import java.util.stream.Collectors;
130 
131 @RunWith(Parameterized.class)
132 @AppModeFull
133 @AppModeNonSdkSandbox
134 public class PackageManagerShellCommandInstallTest {
135     static final String TEST_APP_PACKAGE = "com.example.helloworld";
136     static final String TEST_VERIFIER_PACKAGE = "com.example.helloverifier";
137     static final String TEST_SUFFICIENT_VERIFIER_PACKAGE = "com.example.hellosufficient";
138 
139     private static final String CTS_PACKAGE_NAME = "android.content.cts";
140 
141     private static final String TEST_APK_PATH = "/data/local/tmp/cts/content/";
142     static final String TEST_HW5 = "HelloWorld5.apk";
143     static final String TEST_HW_SYSTEM_USER_ONLY = "HelloWorldSystemUserOnly.apk";
144     private static final String TEST_HW5_SPLIT0 = "HelloWorld5_hdpi-v4.apk";
145     private static final String TEST_HW5_SPLIT1 = "HelloWorld5_mdpi-v4.apk";
146     private static final String TEST_HW5_SPLIT2 = "HelloWorld5_xhdpi-v4.apk";
147     private static final String TEST_HW5_SPLIT3 = "HelloWorld5_xxhdpi-v4.apk";
148     private static final String TEST_HW5_SPLIT4 = "HelloWorld5_xxxhdpi-v4.apk";
149     private static final String TEST_HW7 = "HelloWorld7.apk";
150     private static final String TEST_HW7_SPLIT0 = "HelloWorld7_hdpi-v4.apk";
151     private static final String TEST_HW7_SPLIT1 = "HelloWorld7_mdpi-v4.apk";
152     private static final String TEST_HW7_SPLIT2 = "HelloWorld7_xhdpi-v4.apk";
153     private static final String TEST_HW7_SPLIT3 = "HelloWorld7_xxhdpi-v4.apk";
154     private static final String TEST_HW7_SPLIT4 = "HelloWorld7_xxxhdpi-v4.apk";
155 
156     private static final String TEST_SDK1_PACKAGE = "com.test.sdk1_1";
157     private static final String TEST_SDK1_MAJOR_VERSION2_PACKAGE = "com.test.sdk1_2";
158     private static final String TEST_SDK2_PACKAGE = "com.test.sdk2_2";
159     private static final String TEST_SDK3_PACKAGE = "com.test.sdk3_3";
160     private static final String TEST_SDK_USER_PACKAGE = "com.test.sdk.user";
161 
162     private static final String TEST_SDK1_NAME = "com.test.sdk1";
163     private static final String TEST_SDK2_NAME = "com.test.sdk2";
164     private static final String TEST_SDK3_NAME = "com.test.sdk3";
165 
166     private static final String TEST_SDK1 = "HelloWorldSdk1.apk";
167     private static final String TEST_SDK1_UPDATED = "HelloWorldSdk1Updated.apk";
168     private static final String TEST_SDK1_MAJOR_VERSION2 = "HelloWorldSdk1MajorVersion2.apk";
169     private static final String TEST_SDK1_DIFFERENT_SIGNER = "HelloWorldSdk1DifferentSigner.apk";
170     private static final String TEST_SDK2 = "HelloWorldSdk2.apk";
171     private static final String TEST_SDK2_UPDATED = "HelloWorldSdk2Updated.apk";
172 
173     private static final String TEST_USING_SDK1_OPTIONAL = "HelloWorldUsingSdk1Optional.apk";
174 
175     private static final String TEST_USING_SDK1_OPTIONAL_SDK2 =
176             "HelloWorldUsingSdk1OptionalSdk2.apk";
177     private static final String TEST_USING_SDK1 = "HelloWorldUsingSdk1.apk";
178     private static final String TEST_USING_SDK1_AND_SDK2 = "HelloWorldUsingSdk1And2.apk";
179 
180     private static final String TEST_SDK3_USING_SDK1 = "HelloWorldSdk3UsingSdk1.apk";
181     private static final String TEST_SDK3_USING_SDK1_AND_SDK2 = "HelloWorldSdk3UsingSdk1And2.apk";
182     private static final String TEST_USING_SDK3 = "HelloWorldUsingSdk3.apk";
183 
184 
185     private static final String TEST_SUFFICIENT = "HelloWorldWithSufficient.apk";
186 
187     private static final String TEST_SUFFICIENT_VERIFIER_REJECT =
188             "HelloSufficientVerifierReject.apk";
189 
190     private static final String TEST_VERIFIER_ALLOW = "HelloVerifierAllow.apk";
191     private static final String TEST_VERIFIER_REJECT = "HelloVerifierReject.apk";
192     private static final String TEST_VERIFIER_DELAYED_REJECT = "HelloVerifierDelayedReject.apk";
193     private static final String TEST_VERIFIER_DISABLED = "HelloVerifierDisabled.apk";
194 
195     private static final String TEST_INSTALLER_APP = "HelloInstallerApp.apk";
196     private static final String TEST_INSTALLER_APP_UPDATED =
197             "HelloInstallerAppUpdated.apk";
198 
199     private static final String TEST_INSTALLER_APP_ABSENT = "HelloInstallerAppAbsent.apk";
200     private static final String TEST_INSTALLER_APP_ABSENT_UPDATED =
201             "HelloInstallerAppAbsentUpdated.apk";
202 
203     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
204 
205     static final long DEFAULT_STREAMING_VERIFICATION_TIMEOUT_MS = 3 * 1000;
206     static final long VERIFICATION_BROADCAST_RECEIVED_TIMEOUT_MS = 10 * 1000;
207 
208     @Rule
209     public AbandonAllPackageSessionsRule mAbandonSessionsRule = new AbandonAllPackageSessionsRule();
210 
211     @Rule
212     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
213 
214     @Parameter
215     public int mDataLoaderType;
216 
217     @Parameters
initParameters()218     public static Iterable<Object> initParameters() {
219         return Arrays.asList(DATA_LOADER_TYPE_NONE, DATA_LOADER_TYPE_STREAMING,
220                              DATA_LOADER_TYPE_INCREMENTAL);
221     }
222 
223     private boolean mStreaming = false;
224     private boolean mIncremental = false;
225     private boolean mVerifierTimeoutTest = false;
226     private String mInstall = "";
227     private static long sStreamingVerificationTimeoutMs = DEFAULT_STREAMING_VERIFICATION_TIMEOUT_MS;
228 
getPackageInstaller()229     private static PackageInstaller getPackageInstaller() {
230         return getPackageManager().getPackageInstaller();
231     }
232 
getPackageManager()233     private static PackageManager getPackageManager() {
234         return InstrumentationRegistry.getContext().getPackageManager();
235     }
236 
getContext()237     private static Context getContext() {
238         return InstrumentationRegistry.getContext();
239     }
240 
getUiAutomation()241     private static UiAutomation getUiAutomation() {
242         return InstrumentationRegistry.getInstrumentation().getUiAutomation();
243     }
244 
executeShellCommand(String command)245     /* package */ static String executeShellCommand(String command) throws IOException {
246         final ParcelFileDescriptor stdout = getUiAutomation().executeShellCommand(command);
247         try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(stdout)) {
248             return readFullStream(inputStream);
249         }
250     }
251 
executeShellCommand(String command, File input)252     private static String executeShellCommand(String command, File input)
253             throws IOException {
254         return executeShellCommand(command, new File[]{input});
255     }
256 
executeShellCommand(String command, File[] inputs)257     private static String executeShellCommand(String command, File[] inputs)
258             throws IOException {
259         final ParcelFileDescriptor[] pfds = getUiAutomation().executeShellCommandRw(command);
260         ParcelFileDescriptor stdout = pfds[0];
261         ParcelFileDescriptor stdin = pfds[1];
262         try (FileOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(
263                 stdin)) {
264             for (File input : inputs) {
265                 try (FileInputStream inputStream = new FileInputStream(input)) {
266                     writeFullStream(inputStream, outputStream, input.length());
267                 }
268             }
269         }
270         try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(stdout)) {
271             return readFullStream(inputStream);
272         }
273     }
274 
readFullStream(InputStream inputStream)275     private static String readFullStream(InputStream inputStream) throws IOException {
276         ByteArrayOutputStream result = new ByteArrayOutputStream();
277         writeFullStream(inputStream, result, -1);
278         return result.toString("UTF-8");
279     }
280 
writeFullStream(InputStream inputStream, OutputStream outputStream, long expected)281     private static void writeFullStream(InputStream inputStream, OutputStream outputStream,
282             long expected)
283             throws IOException {
284         byte[] buffer = new byte[1024];
285         long total = 0;
286         int length;
287         while ((length = inputStream.read(buffer)) != -1) {
288             outputStream.write(buffer, 0, length);
289             total += length;
290         }
291         if (expected > 0) {
292             assertEquals(expected, total);
293         }
294     }
295 
writeFileToSession(PackageInstaller.Session session, String name, String apk)296     private static void writeFileToSession(PackageInstaller.Session session, String name,
297             String apk) throws IOException {
298         File file = new File(createApkPath(apk));
299         try (OutputStream os = session.openWrite(name, 0, file.length());
300              InputStream is = new FileInputStream(file)) {
301             writeFullStream(is, os, file.length());
302         }
303     }
304 
305     @BeforeClass
onBeforeClass()306     public static void onBeforeClass() throws Exception {
307         try {
308             sStreamingVerificationTimeoutMs = Long.parseUnsignedLong(
309                     executeShellCommand("settings get global streaming_verifier_timeout"));
310         } catch (NumberFormatException ignore) {
311         }
312     }
313 
314     @Before
onBefore()315     public void onBefore() throws Exception {
316         // Check if Incremental is allowed and skip incremental tests otherwise.
317         assumeFalse(mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL
318                 && !checkIncrementalDeliveryFeature());
319 
320         mStreaming = mDataLoaderType != DATA_LOADER_TYPE_NONE;
321         mIncremental = mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL;
322         // Don't repeat verifier timeout tests for non-Incremental installs.
323         mVerifierTimeoutTest = !mStreaming || mIncremental;
324 
325         mInstall = mDataLoaderType == DATA_LOADER_TYPE_NONE ? " install " :
326                 mDataLoaderType == DATA_LOADER_TYPE_STREAMING ? " install-streaming " :
327                         " install-incremental ";
328 
329         uninstallPackageSilently(TEST_APP_PACKAGE);
330 
331         executeShellCommand("settings put global verifier_verify_adb_installs 0");
332     }
333 
onBeforeSdkTests()334     private void onBeforeSdkTests() throws Exception {
335         assumeFalse(mStreaming);
336 
337         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
338         uninstallPackageSilently(TEST_SDK3_PACKAGE);
339         uninstallPackageSilently(TEST_SDK2_PACKAGE);
340         uninstallPackageSilently(TEST_SDK1_PACKAGE);
341         uninstallPackageSilently(TEST_SDK1_MAJOR_VERSION2_PACKAGE);
342 
343         setSystemProperty("debug.pm.uses_sdk_library_default_cert_digest", "invalid");
344         setSystemProperty("debug.pm.prune_unused_shared_libraries_delay", "invalid");
345     }
346 
347     @AfterClass
onAfterClass()348     public static void onAfterClass() throws Exception {
349         uninstallPackageSilently(TEST_APP_PACKAGE);
350 
351         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
352         uninstallPackageSilently(TEST_SUFFICIENT_VERIFIER_PACKAGE);
353 
354         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
355         uninstallPackageSilently(TEST_SDK3_PACKAGE);
356         uninstallPackageSilently(TEST_SDK2_PACKAGE);
357         uninstallPackageSilently(TEST_SDK1_PACKAGE);
358         uninstallPackageSilently(TEST_SDK1_MAJOR_VERSION2_PACKAGE);
359 
360         // Set the test override to invalid.
361         setSystemProperty("debug.pm.uses_sdk_library_default_cert_digest", "invalid");
362         setSystemProperty("debug.pm.prune_unused_shared_libraries_delay", "invalid");
363         setSystemProperty("debug.pm.adb_verifier_override_packages", "invalid");
364     }
365 
checkIncrementalDeliveryFeature()366     private boolean checkIncrementalDeliveryFeature() {
367         final Context context = InstrumentationRegistry.getInstrumentation().getContext();
368         return context.getPackageManager().hasSystemFeature(
369                 PackageManager.FEATURE_INCREMENTAL_DELIVERY);
370     }
371 
372     @Test
testAppInstall()373     public void testAppInstall() throws Exception {
374         installPackage(TEST_HW5);
375         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
376     }
377 
378     @Test
testAppInstallInvalidUser()379     public void testAppInstallInvalidUser() throws Exception {
380         File file = new File(createApkPath(TEST_HW5));
381         // MAX_USER_ID = UserHandle.MAX_SECONDARY_USER_ID
382         // ideally the test environment will not reach 999
383         String result = executeShellCommand(
384                 "pm " + mInstall + " --user 999" + " -t -g " + file.getPath());
385         assertThat(result).isEqualTo("Failure [user 999 doesn't exist]\n");
386     }
387 
388     @Test
testAppUnInstallInvalidUser()389     public void testAppUnInstallInvalidUser() throws Exception {
390         // MAX_USER_ID = UserHandle.MAX_SECONDARY_USER_ID
391         // ideally the test environment will not reach 999
392         String result = executeShellCommand("pm uninstall --user 999 " + TEST_APP_PACKAGE);
393         assertThat(result).isEqualTo("Failure [user 999 doesn't exist]\n");
394     }
395 
396     @Test
testAppInstallErr()397     public void testAppInstallErr() throws Exception {
398         assumeTrue(mStreaming);
399         File file = new File(createApkPath(TEST_HW5));
400         String command = "pm " + mInstall + " -t -g " + file.getPath() + (new Random()).nextLong();
401         String commandResult = executeShellCommand(command);
402         assertEquals("Failure [failed to add file(s)]\n", commandResult);
403         assertFalse(isAppInstalled(TEST_APP_PACKAGE));
404     }
405 
406     @Test
testAppInstallStdIn()407     public void testAppInstallStdIn() throws Exception {
408         installPackageStdIn(TEST_HW5);
409         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
410     }
411 
412     @Test
testAppInstallStdInErr()413     public void testAppInstallStdInErr() throws Exception {
414         File file = new File(createApkPath(TEST_HW5));
415         String commandResult = executeShellCommand("pm " + mInstall + " -t -g -S " + file.length(),
416                 new File[]{});
417         if (mIncremental) {
418             assertTrue(commandResult, commandResult.startsWith("Failure ["));
419         } else {
420             assertTrue(commandResult,
421                     commandResult.startsWith("Failure [INSTALL_PARSE_FAILED_NOT_APK"));
422         }
423         assertFalse(isAppInstalled(TEST_APP_PACKAGE));
424     }
425 
426     @Test
427     @RequiresFlagsEnabled(android.content.pm.Flags.FLAG_GET_PACKAGE_STORAGE_STATS)
testGetPackageStorageStats()428     public void testGetPackageStorageStats() throws Exception {
429         installPackage(TEST_HW5);
430         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
431 
432         StorageStatsManager storageStatsManager =
433             getContext().getSystemService(StorageStatsManager.class);
434         StorageStats stats =
435             storageStatsManager.queryStatsForPackage(StorageManager.UUID_DEFAULT,
436                 TEST_APP_PACKAGE, android.os.Process.myUserHandle());
437 
438         String commandResult =
439             executeShellCommand("pm get-package-storage-stats " + TEST_APP_PACKAGE);
440         String[] lines = commandResult.split("\n");
441         for (String line : lines) {
442             String dataType = line.split(": ")[0];
443             String value = line.split(": ")[1];
444             switch (dataType) {
445                 case "code":
446                     assertEquals(value, getDataSizeDisplay(stats.getAppBytes()));
447                     break;
448                 case "data":
449                     assertEquals(value, getDataSizeDisplay(stats.getDataBytes()));
450                     break;
451                 case "cache":
452                     assertEquals(value, getDataSizeDisplay(stats.getCacheBytes()));
453                     break;
454                 case "apk":
455                     assertEquals(value, getDataSizeDisplay(stats.getAppBytesByDataType(
456                         StorageStats.APP_DATA_TYPE_FILE_TYPE_APK)));
457                     break;
458                 case "lib":
459                     assertEquals(value, getDataSizeDisplay(stats.getAppBytesByDataType(
460                         StorageStats.APP_DATA_TYPE_LIB)));
461                     break;
462                 case "dm":
463                     assertEquals(value, getDataSizeDisplay(stats.getAppBytesByDataType(
464                         StorageStats.APP_DATA_TYPE_FILE_TYPE_DM)));
465                     break;
466                 case "dexopt artifacts":
467                     assertEquals(value, getDataSizeDisplay(stats.getAppBytesByDataType(
468                         StorageStats.APP_DATA_TYPE_FILE_TYPE_DEXOPT_ARTIFACT)));
469                     break;
470                 case "current profile":
471                     assertEquals(value, getDataSizeDisplay(stats.getAppBytesByDataType(
472                         StorageStats.APP_DATA_TYPE_FILE_TYPE_CURRENT_PROFILE)));
473                     break;
474                 case "reference profile":
475                     assertEquals(value, getDataSizeDisplay(stats.getAppBytesByDataType(
476                         StorageStats.APP_DATA_TYPE_FILE_TYPE_REFERENCE_PROFILE)));
477                     break;
478                 case "external cache":
479                     assertEquals(value, getDataSizeDisplay(stats.getExternalCacheBytes()));
480                     break;
481             }
482         }
483     }
484 
485     @Test
testAppUpdate()486     public void testAppUpdate() throws Exception {
487         installPackage(TEST_HW5);
488         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
489         updatePackage(TEST_APP_PACKAGE, TEST_HW7);
490         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
491     }
492 
493     @Test
testAppUpdateSameApk()494     public void testAppUpdateSameApk() throws Exception {
495         installPackage(TEST_HW5);
496         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
497         updatePackage(TEST_APP_PACKAGE, TEST_HW5);
498         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
499     }
500 
501     @Test
testAppUpdateStdIn()502     public void testAppUpdateStdIn() throws Exception {
503         installPackageStdIn(TEST_HW5);
504         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
505         updatePackageStdIn(TEST_APP_PACKAGE, TEST_HW7);
506         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
507     }
508 
509     @Test
testAppUpdateStdInSameApk()510     public void testAppUpdateStdInSameApk() throws Exception {
511         installPackageStdIn(TEST_HW5);
512         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
513         updatePackageStdIn(TEST_APP_PACKAGE, TEST_HW5);
514         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
515     }
516 
517     @Test
testAppUpdateSkipEnable()518     public void testAppUpdateSkipEnable() throws Exception {
519         assumeFalse(mStreaming);
520         installPackage(TEST_HW5);
521         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
522         assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
523                 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE));
524         disablePackage(TEST_APP_PACKAGE);
525         assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
526                 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE));
527         updatePackage(TEST_APP_PACKAGE, TEST_HW5);
528         assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
529                 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE));
530         disablePackage(TEST_APP_PACKAGE);
531         assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
532                 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE));
533         updatePackageSkipEnable(TEST_APP_PACKAGE, TEST_HW5);
534         assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
535                 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE));
536     }
537 
538     @Test
testSplitsInstall()539     public void testSplitsInstall() throws Exception {
540         assumeFalse(mStreaming); // Tested in testSplitsBatchInstall.
541         installSplits(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
542                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
543         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
544         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
545                 getSplits(TEST_APP_PACKAGE));
546     }
547 
548     @Test
testSplitsInstallStdIn()549     public void testSplitsInstallStdIn() throws Exception {
550         installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
551                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, "");
552         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
553         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
554                 getSplits(TEST_APP_PACKAGE));
555     }
556 
557     @Test
testSplitsInstallDash()558     public void testSplitsInstallDash() throws Exception {
559         installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
560                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, "-");
561         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
562         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
563                 getSplits(TEST_APP_PACKAGE));
564     }
565 
566     @Test
testSplitsBatchInstall()567     public void testSplitsBatchInstall() throws Exception {
568         installSplitsBatch(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
569                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
570         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
571         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
572                 getSplits(TEST_APP_PACKAGE));
573     }
574 
575     @Test
testSplitsUpdate()576     public void testSplitsUpdate() throws Exception {
577         assumeFalse(mStreaming); // Tested in testSplitsBatchUpdate.
578         installSplits(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
579                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
580         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
581         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
582                 getSplits(TEST_APP_PACKAGE));
583         updateSplits(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2,
584                 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4});
585         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
586         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
587                 getSplits(TEST_APP_PACKAGE));
588     }
589 
590 
591     @Test
testSplitsAdd()592     public void testSplitsAdd() throws Exception {
593         assumeFalse(mStreaming); // Tested in testSplitsBatchAdd.
594         installSplits(new String[]{TEST_HW5});
595         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
596         assertEquals("base", getSplits(TEST_APP_PACKAGE));
597 
598         updateSplits(new String[]{TEST_HW5_SPLIT0});
599         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
600         assertEquals("base, config.hdpi", getSplits(TEST_APP_PACKAGE));
601 
602         updateSplits(new String[]{TEST_HW5_SPLIT1});
603         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
604         assertEquals("base, config.hdpi, config.mdpi", getSplits(TEST_APP_PACKAGE));
605 
606         updateSplits(new String[]{TEST_HW5_SPLIT2});
607         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
608         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi",
609                 getSplits(TEST_APP_PACKAGE));
610 
611         updateSplits(new String[]{TEST_HW5_SPLIT3});
612         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
613         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi",
614                 getSplits(TEST_APP_PACKAGE));
615 
616         updateSplits(new String[]{TEST_HW5_SPLIT4});
617         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
618         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
619                 getSplits(TEST_APP_PACKAGE));
620     }
621 
622     @Test
testSplitsUpdateStdIn()623     public void testSplitsUpdateStdIn() throws Exception {
624         installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
625                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, "");
626         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
627         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
628                 getSplits(TEST_APP_PACKAGE));
629         installSplitsStdIn(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2,
630                 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}, "");
631         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
632         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
633                 getSplits(TEST_APP_PACKAGE));
634     }
635 
636     @Test
testSplitsUpdateDash()637     public void testSplitsUpdateDash() throws Exception {
638         installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
639                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, "-");
640         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
641         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
642                 getSplits(TEST_APP_PACKAGE));
643         installSplitsStdIn(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2,
644                 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}, "-");
645         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
646         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
647                 getSplits(TEST_APP_PACKAGE));
648     }
649 
650     @Test
testSplitsBatchUpdate()651     public void testSplitsBatchUpdate() throws Exception {
652         installSplitsBatch(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
653                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
654         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
655         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
656                 getSplits(TEST_APP_PACKAGE));
657         updateSplitsBatch(
658                 new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2,
659                         TEST_HW7_SPLIT3, TEST_HW7_SPLIT4});
660         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
661         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
662                 getSplits(TEST_APP_PACKAGE));
663     }
664 
665     @Test
testSplitsBatchAdd()666     public void testSplitsBatchAdd() throws Exception {
667         installSplitsBatch(new String[]{TEST_HW5});
668         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
669         assertEquals("base", getSplits(TEST_APP_PACKAGE));
670 
671         updateSplitsBatch(new String[]{TEST_HW5_SPLIT0, TEST_HW5_SPLIT1});
672         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
673         assertEquals("base, config.hdpi, config.mdpi", getSplits(TEST_APP_PACKAGE));
674 
675         updateSplitsBatch(new String[]{TEST_HW5_SPLIT2, TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
676         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
677         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
678                 getSplits(TEST_APP_PACKAGE));
679     }
680 
681     @Test
testSplitsUninstall()682     public void testSplitsUninstall() throws Exception {
683         assumeFalse(mStreaming); // Tested in testSplitsBatchUninstall.
684         installSplits(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
685                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
686         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
687         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
688                 getSplits(TEST_APP_PACKAGE));
689         uninstallSplits(TEST_APP_PACKAGE, new String[]{"config.hdpi"});
690         assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
691                 getSplits(TEST_APP_PACKAGE));
692         uninstallSplits(TEST_APP_PACKAGE, new String[]{"config.xxxhdpi", "config.xhdpi"});
693         assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE));
694     }
695 
696     @Test
testSplitsBatchUninstall()697     public void testSplitsBatchUninstall() throws Exception {
698         installSplitsBatch(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2,
699                 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4});
700         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
701         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
702                 getSplits(TEST_APP_PACKAGE));
703         uninstallSplitsBatch(TEST_APP_PACKAGE, new String[]{"config.hdpi"});
704         assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
705                 getSplits(TEST_APP_PACKAGE));
706         uninstallSplitsBatch(TEST_APP_PACKAGE, new String[]{"config.xxxhdpi", "config.xhdpi"});
707         assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE));
708     }
709 
710     @Test
testSplitsRemove()711     public void testSplitsRemove() throws Exception {
712         assumeFalse(mStreaming); // Tested in testSplitsBatchRemove.
713         installSplits(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2,
714                 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4});
715         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
716         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
717                 getSplits(TEST_APP_PACKAGE));
718 
719         String sessionId = createUpdateSession(TEST_APP_PACKAGE);
720         removeSplits(sessionId, new String[]{"config.hdpi"});
721         commitSession(sessionId);
722         assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
723                 getSplits(TEST_APP_PACKAGE));
724 
725         sessionId = createUpdateSession(TEST_APP_PACKAGE);
726         removeSplits(sessionId, new String[]{"config.xxxhdpi", "config.xhdpi"});
727         commitSession(sessionId);
728         assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE));
729     }
730 
731     @Test
testSplitsBatchRemove()732     public void testSplitsBatchRemove() throws Exception {
733         installSplitsBatch(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2,
734                 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4});
735         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
736         assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
737                 getSplits(TEST_APP_PACKAGE));
738 
739         String sessionId = createUpdateSession(TEST_APP_PACKAGE);
740         removeSplitsBatch(sessionId, new String[]{"config.hdpi"});
741         commitSession(sessionId);
742         assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi",
743                 getSplits(TEST_APP_PACKAGE));
744 
745         sessionId = createUpdateSession(TEST_APP_PACKAGE);
746         removeSplitsBatch(sessionId, new String[]{"config.xxxhdpi", "config.xhdpi"});
747         commitSession(sessionId);
748         assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE));
749     }
750 
751     @Test
testAppInstallErrDuplicate()752     public void testAppInstallErrDuplicate() throws Exception {
753         assumeTrue(mStreaming);
754         String split = createApkPath(TEST_HW5);
755         String commandResult = executeShellCommand(
756                 "pm " + mInstall + " -t -g " + split + " " + split);
757         assertEquals("Failure [failed to add file(s)]\n", commandResult);
758         assertFalse(isAppInstalled(TEST_APP_PACKAGE));
759     }
760 
761     @Test
testDontKillWithSplit()762     public void testDontKillWithSplit() throws Exception {
763         assumeFalse(mStreaming);
764         installPackage(TEST_HW5);
765         installDontKillSplit();
766     }
767 
installDontKillSplit()768     private void installDontKillSplit() throws Exception {
769         getUiAutomation().adoptShellPermissionIdentity();
770         try {
771             final PackageInstaller installer = getPackageInstaller();
772             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
773             params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
774             params.setAppPackageName(TEST_APP_PACKAGE);
775             params.setDontKillApp(true);
776 
777             final int sessionId = installer.createSession(params);
778             PackageInstaller.Session session = installer.openSession(sessionId);
779             assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
780 
781             writeFileToSession(session, "hw5_split0", TEST_HW5_SPLIT0);
782 
783             final CompletableFuture<Boolean> result = new CompletableFuture<>();
784             final CompletableFuture<Integer> status = new CompletableFuture<>();
785             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
786             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
787                 @Override
788                 public void send(int code, Intent intent, String resolvedType,
789                                  IBinder whitelistToken, IIntentReceiver finishedReceiver,
790                                  String requiredPermission, Bundle options) throws RemoteException {
791                     boolean dontKillApp =
792                             (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
793                     status.complete(
794                             intent.getIntExtra(PackageInstaller.EXTRA_STATUS, Integer.MIN_VALUE));
795                     statusMessage.complete(
796                             intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
797                     result.complete(dontKillApp);
798                 }
799             }));
800 
801             // We are adding split. OK to have the flag.
802             assertTrue(result.get());
803             // Verify that the return status is set
804             assertEquals(statusMessage.get(), PackageInstaller.STATUS_SUCCESS, (int) status.get());
805         } finally {
806             getUiAutomation().dropShellPermissionIdentity();
807         }
808     }
809 
810     @RequiresFlagsEnabled(Flags.FLAG_IMPROVE_INSTALL_DONT_KILL)
811     @Test
testDontKillOldPathsArePreserved()812     public void testDontKillOldPathsArePreserved() throws Exception {
813         assumeFalse(mStreaming);
814         installPackage(TEST_HW5);
815         String oldPath =
816                 getPackageManager().getApplicationInfo(TEST_APP_PACKAGE, 0).publicSourceDir;
817         installDontKillSplit();
818 
819         List<String> oldPaths = getOldCodePaths(TEST_APP_PACKAGE);
820         assertNotNull(oldPaths);
821         assertEquals(1, oldPaths.size());
822         // publicSourceDir contains the full path to the APK
823         // oldPaths only contains paths to directory
824         assertTrue(oldPath.startsWith(oldPaths.get(0)));
825     }
826 
827     @Test
testDontKillRemovedWithBaseApkFullInstall()828     public void testDontKillRemovedWithBaseApkFullInstall() throws Exception {
829         assumeFalse(mStreaming);
830         installPackage(TEST_HW5);
831 
832         getUiAutomation().adoptShellPermissionIdentity();
833         try {
834             final PackageInstaller installer = getPackageInstaller();
835             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
836             params.setAppPackageName(TEST_APP_PACKAGE);
837             params.setDontKillApp(true);
838 
839             final int sessionId = installer.createSession(params);
840             PackageInstaller.Session session = installer.openSession(sessionId);
841             assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
842 
843             writeFileToSession(session, "hw7", TEST_HW7);
844 
845             final CompletableFuture<Boolean> result = new CompletableFuture<>();
846             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
847                 @Override
848                 public void send(int code, Intent intent, String resolvedType,
849                         IBinder whitelistToken, IIntentReceiver finishedReceiver,
850                         String requiredPermission, Bundle options) throws RemoteException {
851                     boolean dontKillApp =
852                             (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
853                     result.complete(dontKillApp);
854                 }
855             }));
856 
857             // We are updating base.apk. Flag to be removed.
858             assertFalse(result.get());
859         } finally {
860             getUiAutomation().dropShellPermissionIdentity();
861         }
862     }
863 
864     @Test
testDontKillRemovedWithBaseApk()865     public void testDontKillRemovedWithBaseApk() throws Exception {
866         assumeFalse(mStreaming);
867         installPackage(TEST_HW5);
868 
869         getUiAutomation().adoptShellPermissionIdentity();
870         try {
871             final PackageInstaller installer = getPackageInstaller();
872             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
873             params.setAppPackageName(TEST_APP_PACKAGE);
874             params.setDontKillApp(true);
875 
876             final int sessionId = installer.createSession(params);
877             PackageInstaller.Session session = installer.openSession(sessionId);
878             assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
879 
880             writeFileToSession(session, "hw7", TEST_HW7);
881 
882             final CompletableFuture<Boolean> result = new CompletableFuture<>();
883             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
884                 @Override
885                 public void send(int code, Intent intent, String resolvedType,
886                         IBinder whitelistToken, IIntentReceiver finishedReceiver,
887                         String requiredPermission, Bundle options) throws RemoteException {
888                     boolean dontKillApp =
889                             (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
890                     result.complete(dontKillApp);
891                 }
892             }));
893 
894             // We are updating base.apk. Flag to be removed.
895             assertFalse(result.get());
896         } finally {
897             getUiAutomation().dropShellPermissionIdentity();
898         }
899     }
900 
901     @Test
testDontKillRemovedWithRemovedSplit()902     public void testDontKillRemovedWithRemovedSplit() throws Exception {
903         assumeFalse(mStreaming);
904         installSplitsBatch(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1});
905         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
906         assertEquals("base, config.hdpi, config.mdpi", getSplits(TEST_APP_PACKAGE));
907 
908         getUiAutomation().adoptShellPermissionIdentity();
909         try {
910             final PackageInstaller installer = getPackageInstaller();
911             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
912             params.setAppPackageName(TEST_APP_PACKAGE);
913             params.setDontKillApp(true);
914 
915             final int sessionId = installer.createSession(params);
916             PackageInstaller.Session session = installer.openSession(sessionId);
917             assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
918             session.removeSplit("config.mdpi");
919 
920             final CompletableFuture<Boolean> result = new CompletableFuture<>();
921             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
922                 @Override
923                 public void send(int code, Intent intent, String resolvedType,
924                                  IBinder whitelistToken, IIntentReceiver finishedReceiver,
925                                  String requiredPermission, Bundle options) throws RemoteException {
926                     boolean dontKillApp =
927                             (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
928                     result.complete(dontKillApp);
929                 }
930             }));
931 
932             // We are removing a split apk. Flag should be removed.
933             assertFalse(result.get());
934         } finally {
935             getUiAutomation().dropShellPermissionIdentity();
936         }
937     }
938 
939     @Test
testDontKillRemovedWithReplacedSplit()940     public void testDontKillRemovedWithReplacedSplit() throws Exception {
941         assumeFalse(mStreaming);
942         installSplitsBatch(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1});
943         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
944         assertEquals("base, config.hdpi, config.mdpi", getSplits(TEST_APP_PACKAGE));
945 
946         getUiAutomation().adoptShellPermissionIdentity();
947         try {
948             final PackageInstaller installer = getPackageInstaller();
949             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
950             params.setAppPackageName(TEST_APP_PACKAGE);
951             params.setDontKillApp(true);
952 
953             final int sessionId = installer.createSession(params);
954             PackageInstaller.Session session = installer.openSession(sessionId);
955             assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
956 
957             writeFileToSession(session, "split_config.mdpi", TEST_HW7_SPLIT1);
958 
959             final CompletableFuture<Boolean> result = new CompletableFuture<>();
960             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
961                 @Override
962                 public void send(int code, Intent intent, String resolvedType,
963                                  IBinder whitelistToken, IIntentReceiver finishedReceiver,
964                                  String requiredPermission, Bundle options) throws RemoteException {
965                     boolean dontKillApp =
966                             (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
967                     result.complete(dontKillApp);
968                 }
969             }));
970 
971             // We are replacing an existing split apk. Flag should be removed.
972             assertFalse(result.get());
973         } finally {
974             getUiAutomation().dropShellPermissionIdentity();
975         }
976     }
977 
978     @Test
testDataLoaderParamsApiV1()979     public void testDataLoaderParamsApiV1() throws Exception {
980         assumeTrue(mStreaming);
981 
982         getUiAutomation().adoptShellPermissionIdentity();
983         try {
984             final PackageInstaller installer = getPackageInstaller();
985 
986             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
987 
988             final int sessionId = installer.createSession(params);
989             PackageInstaller.Session session = installer.openSession(sessionId);
990 
991             assertEquals(null, session.getDataLoaderParams());
992 
993             installer.abandonSession(sessionId);
994         } finally {
995             getUiAutomation().dropShellPermissionIdentity();
996         }
997     }
998 
999     @Test
testDataLoaderParamsApiV2()1000     public void testDataLoaderParamsApiV2() throws Exception {
1001         assumeTrue(mStreaming);
1002 
1003         getUiAutomation().adoptShellPermissionIdentity();
1004         try {
1005             final PackageInstaller installer = getPackageInstaller();
1006 
1007             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
1008             final ComponentName componentName = new ComponentName("foo", "bar");
1009             final String args = "args";
1010             params.setDataLoaderParams(
1011                     mIncremental ? DataLoaderParams.forIncremental(componentName, args)
1012                             : DataLoaderParams.forStreaming(componentName, args));
1013 
1014             final int sessionId = installer.createSession(params);
1015             PackageInstaller.Session session = installer.openSession(sessionId);
1016 
1017             DataLoaderParams dataLoaderParams = session.getDataLoaderParams();
1018             assertEquals(mIncremental ? DATA_LOADER_TYPE_INCREMENTAL : DATA_LOADER_TYPE_STREAMING,
1019                     dataLoaderParams.getType());
1020             assertEquals("foo", dataLoaderParams.getComponentName().getPackageName());
1021             assertEquals("bar", dataLoaderParams.getComponentName().getClassName());
1022             assertEquals("args", dataLoaderParams.getArguments());
1023 
1024             installer.abandonSession(sessionId);
1025         } finally {
1026             getUiAutomation().dropShellPermissionIdentity();
1027         }
1028     }
1029 
1030     @Test
testRemoveFileApiV2()1031     public void testRemoveFileApiV2() throws Exception {
1032         assumeTrue(mStreaming);
1033 
1034         getUiAutomation().adoptShellPermissionIdentity();
1035         try {
1036             final PackageInstaller installer = getPackageInstaller();
1037 
1038             final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
1039             params.setAppPackageName("com.package.name");
1040             final ComponentName componentName = new ComponentName("foo", "bar");
1041             final String args = "args";
1042             params.setDataLoaderParams(
1043                     mIncremental ? DataLoaderParams.forIncremental(componentName, args)
1044                             : DataLoaderParams.forStreaming(componentName, args));
1045 
1046             final int sessionId = installer.createSession(params);
1047             PackageInstaller.Session session = installer.openSession(sessionId);
1048 
1049             session.addFile(LOCATION_DATA_APP, "base.apk", 123, "123".getBytes(), null);
1050             String[] files = session.getNames();
1051             assertEquals(1, files.length);
1052             assertEquals("base.apk", files[0]);
1053 
1054             session.removeFile(LOCATION_DATA_APP, "base.apk");
1055             files = session.getNames();
1056             assertEquals(2, files.length);
1057             assertEquals("base.apk", files[0]);
1058             assertEquals("base.apk.removed", files[1]);
1059 
1060             installer.abandonSession(sessionId);
1061         } finally {
1062             getUiAutomation().dropShellPermissionIdentity();
1063         }
1064     }
1065 
1066     @Test
1067     @RequiresFlagsDisabled(Flags.FLAG_DISALLOW_SDK_LIBS_TO_BE_APPS)
testSdkInstallAndUpdate_sdkLibsBeAppsHasAppId()1068     public void testSdkInstallAndUpdate_sdkLibsBeAppsHasAppId() throws Exception {
1069         onBeforeSdkTests();
1070 
1071         installPackage(TEST_SDK1);
1072         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1073 
1074         SystemUtil.runWithShellPermissionIdentity(() -> {
1075             // No uid is assigned for SDK package
1076             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK1_PACKAGE,
1077                     PackageManager.ApplicationInfoFlags.of(
1078                             MATCH_STATIC_SHARED_AND_SDK_LIBRARIES));
1079             assertThat(appInfo.uid).isGreaterThan(Process.INVALID_UID);
1080         });
1081 
1082         // Same APK.
1083         installPackage(TEST_SDK1);
1084 
1085         // Updated APK.
1086         installPackage(TEST_SDK1_UPDATED);
1087 
1088         // Reverted APK.
1089         installPackage(TEST_SDK1);
1090 
1091         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1092     }
1093 
1094     @Test
1095     @RequiresFlagsEnabled(Flags.FLAG_DISALLOW_SDK_LIBS_TO_BE_APPS)
testSdkInstallAndUpdate_blockSdkLibsBeAppsNoAppId()1096     public void testSdkInstallAndUpdate_blockSdkLibsBeAppsNoAppId() throws Exception {
1097         onBeforeSdkTests();
1098 
1099         installPackage(TEST_SDK1);
1100         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1101 
1102         SystemUtil.runWithShellPermissionIdentity(() -> {
1103             // No uid is assigned for SDK package
1104             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK1_PACKAGE,
1105                     PackageManager.ApplicationInfoFlags.of(
1106                             MATCH_STATIC_SHARED_AND_SDK_LIBRARIES));
1107             assertThat(appInfo.uid).isEqualTo(Process.INVALID_UID);
1108         });
1109 
1110         // Same APK.
1111         installPackage(TEST_SDK1);
1112 
1113         // Updated APK.
1114         installPackage(TEST_SDK1_UPDATED);
1115 
1116         // Reverted APK.
1117         installPackage(TEST_SDK1);
1118 
1119         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1120     }
1121 
1122     @Test
testGetPackageInfoForSdk_notSystemOrShell()1123     public void testGetPackageInfoForSdk_notSystemOrShell() throws Exception {
1124         onBeforeSdkTests();
1125 
1126         installPackage(TEST_SDK1);
1127         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1128 
1129         // Normal access
1130         assertThrows(PackageManager.NameNotFoundException.class,
1131                 () -> getPackageManager().getPackageInfo(TEST_SDK1_PACKAGE,
1132                         PackageManager.PackageInfoFlags.of(MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)));
1133     }
1134 
1135     @Test
testGetApplicationInfoForSdk_notSystemOrShell()1136     public void testGetApplicationInfoForSdk_notSystemOrShell() throws Exception {
1137         onBeforeSdkTests();
1138 
1139         installPackage(TEST_SDK1);
1140         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1141 
1142         // Normal access
1143         assertThrows(PackageManager.NameNotFoundException.class,
1144                 () -> getPackageManager().getApplicationInfo(TEST_SDK1_PACKAGE,
1145                         PackageManager.ApplicationInfoFlags.of(
1146                                 MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)));
1147     }
1148 
1149     @Test
testSharedLibraryAccess_notSystemOrShell()1150     public void testSharedLibraryAccess_notSystemOrShell() throws Exception {
1151         onBeforeSdkTests();
1152 
1153         installPackage(TEST_SDK1);
1154         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1155 
1156         // Normal access
1157         List<SharedLibraryInfo> shareLibs = getPackageManager().getSharedLibraries(/*flags=*/ 0);
1158         SharedLibraryInfo sdk = findLibrary(shareLibs, TEST_SDK1_NAME, 1);
1159         assertThat(sdk).isNull();
1160     }
1161 
1162     @Test
testGetPackageInfoForSdk_systemOrShell()1163     public void testGetPackageInfoForSdk_systemOrShell() throws Exception {
1164         onBeforeSdkTests();
1165 
1166         installPackage(TEST_SDK1);
1167         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1168 
1169         // Access as a shell
1170         SystemUtil.runWithShellPermissionIdentity(() -> {
1171             PackageInfo info = getPackageManager().getPackageInfo(TEST_SDK1_PACKAGE,
1172                     PackageManager.PackageInfoFlags.of(MATCH_STATIC_SHARED_AND_SDK_LIBRARIES));
1173 
1174             assertThat(info).isNotNull();
1175             assertThat(info.packageName).isEqualTo(TEST_SDK1_PACKAGE);
1176         });
1177     }
1178 
1179     @Test
testGetApplicationInfoForSdk_systemOrShell()1180     public void testGetApplicationInfoForSdk_systemOrShell() throws Exception {
1181         onBeforeSdkTests();
1182 
1183         installPackage(TEST_SDK1);
1184         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1185 
1186         // Access as a shell
1187         SystemUtil.runWithShellPermissionIdentity(() -> {
1188             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK1_PACKAGE,
1189                     PackageManager.ApplicationInfoFlags.of(
1190                             MATCH_STATIC_SHARED_AND_SDK_LIBRARIES));
1191 
1192             assertThat(appInfo).isNotNull();
1193             assertThat(appInfo.icon).isGreaterThan(0);
1194 
1195             assertThat(appInfo.targetSdkVersion).isEqualTo(34);
1196             assertThat(appInfo.minSdkVersion).isEqualTo(30);
1197         });
1198     }
1199 
1200     @Test
testSharedLibraryAccess_systemOrShell()1201     public void testSharedLibraryAccess_systemOrShell() throws Exception {
1202         onBeforeSdkTests();
1203 
1204         installPackage(TEST_SDK1);
1205         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1206 
1207         // Access as a shell
1208         SystemUtil.runWithShellPermissionIdentity(() -> {
1209             List<SharedLibraryInfo> shareLibs = getPackageManager().getSharedLibraries(/*flags=*/
1210                     0);
1211             SharedLibraryInfo sdk = findLibrary(shareLibs, TEST_SDK1_NAME, 1);
1212             assertThat(sdk).isNotNull();
1213         });
1214     }
1215 
1216     @Test
testGetProperty()1217     public void testGetProperty() throws Exception {
1218         onBeforeSdkTests();
1219 
1220         installPackage(TEST_SDK1);
1221         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1222 
1223         PackageManager.Property property =
1224                 getPackageManager().getProperty("com.test.sdk1_1.TEST_PROPERTY",
1225                         TEST_SDK1_PACKAGE);
1226         assertThat(property).isNotNull();
1227         assertThat(property.getName()).isEqualTo("com.test.sdk1_1.TEST_PROPERTY");
1228         assertThat(property.getString()).isEqualTo("com.test.sdk1_1.testp1");
1229     }
1230 
1231     @Test
1232     @RequiresFlagsEnabled(Flags.FLAG_DISALLOW_SDK_LIBS_TO_BE_APPS)
testSdkBlockSdkLibsBeAppsNoComponentRegistered()1233     public void testSdkBlockSdkLibsBeAppsNoComponentRegistered() throws Exception {
1234         onBeforeSdkTests();
1235 
1236         installPackage(TEST_SDK1);
1237         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1238 
1239         // Check Activity
1240         Intent intent1 = new Intent();
1241         intent1.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".MainActivity");
1242         List<ResolveInfo> resolveInfoList1 =
1243                 getPackageManager().queryIntentActivities(intent1, 0);
1244 
1245         assertThat(resolveInfoList1).isEmpty();
1246 
1247         // Check Service
1248         Intent intent2 = new Intent();
1249         intent2.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".FakeService");
1250         List<ResolveInfo> resolveInfoList2 =
1251                 getPackageManager().queryIntentServices(intent2, 0);
1252 
1253         assertThat(resolveInfoList2).isEmpty();
1254 
1255         // Check Receiver
1256         Intent intent3 = new Intent();
1257         intent3.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".FakeReceiver");
1258         List<ResolveInfo> resolveInfoList3 =
1259                 getPackageManager().queryBroadcastReceivers(intent3, 0);
1260 
1261         assertThat(resolveInfoList3).isEmpty();
1262 
1263         // Check Provider
1264         Intent intent4 = new Intent();
1265         intent4.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".FakeProvider");
1266         List<ResolveInfo> resolveInfoList4 =
1267                 getPackageManager().queryIntentContentProviders(intent4, 0);
1268 
1269         assertThat(resolveInfoList4).isEmpty();
1270     }
1271 
1272     @Test
1273     @RequiresFlagsDisabled(Flags.FLAG_DISALLOW_SDK_LIBS_TO_BE_APPS)
testSdkLibsBeAppsComponentRegistered()1274     public void testSdkLibsBeAppsComponentRegistered() throws Exception {
1275         onBeforeSdkTests();
1276 
1277         installPackage(TEST_SDK1);
1278         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1279 
1280         // Check Activity
1281         Intent intent1 = new Intent();
1282         intent1.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".MainActivity");
1283         List<ResolveInfo> resolveInfoList1 =
1284                 getPackageManager().queryIntentActivities(intent1, 0);
1285 
1286         assertThat(resolveInfoList1).isNotEmpty();
1287         assertThat(resolveInfoList1.size()).isEqualTo(1);
1288 
1289         // Check Service
1290         Intent intent2 = new Intent();
1291         intent2.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".FakeService");
1292         List<ResolveInfo> resolveInfoList2 =
1293                 getPackageManager().queryIntentServices(intent2, 0);
1294 
1295         assertThat(resolveInfoList2).isNotEmpty();
1296         assertThat(resolveInfoList2.size()).isEqualTo(1);
1297 
1298         // Check Receiver
1299         Intent intent3 = new Intent();
1300         intent3.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".FakeReceiver");
1301         List<ResolveInfo> resolveInfoList3 =
1302                 getPackageManager().queryBroadcastReceivers(intent3, 0);
1303 
1304         assertThat(resolveInfoList3).isNotEmpty();
1305         assertThat(resolveInfoList3.size()).isEqualTo(1);
1306 
1307         // Check Provider
1308         Intent intent4 = new Intent();
1309         intent4.setClassName(TEST_SDK1_PACKAGE, TEST_SDK1_PACKAGE + ".FakeProvider");
1310         List<ResolveInfo> resolveInfoList4 =
1311                 getPackageManager().queryIntentContentProviders(intent4, 0);
1312 
1313         assertThat(resolveInfoList4).isNotEmpty();
1314         assertThat(resolveInfoList4.size()).isEqualTo(1);
1315     }
1316 
1317     @Test
testSdkInstallMultipleMajorVersions()1318     public void testSdkInstallMultipleMajorVersions() throws Exception {
1319         onBeforeSdkTests();
1320 
1321         // Major version 1.
1322         installPackage(TEST_SDK1);
1323         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1324 
1325         // Major version 2.
1326         installPackage(TEST_SDK1_MAJOR_VERSION2);
1327 
1328         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1329         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 2));
1330     }
1331 
1332     @Test
testSdkInstallMultipleMinorVersionsWrongSignature()1333     public void testSdkInstallMultipleMinorVersionsWrongSignature() throws Exception {
1334         onBeforeSdkTests();
1335 
1336         // Major version 1.
1337         installPackage(TEST_SDK1);
1338         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1339 
1340         // Major version 1, different signer.
1341         installPackage(TEST_SDK1_DIFFERENT_SIGNER,
1342                 "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package com.test.sdk1_1 "
1343                         + "signatures do not match newer version");
1344         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1345     }
1346 
1347     @Test
testSdkInstallMultipleMajorVersionsWrongSignature()1348     public void testSdkInstallMultipleMajorVersionsWrongSignature() throws Exception {
1349         onBeforeSdkTests();
1350 
1351         // Major version 1.
1352         installPackage(TEST_SDK1_DIFFERENT_SIGNER);
1353         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1354 
1355         // Major version 2.
1356         installPackage(TEST_SDK1_MAJOR_VERSION2,
1357                 "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package com.test.sdk1_1 "
1358                         + "signatures do not match newer version");
1359 
1360         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1361     }
1362 
1363     @Test
testSdkInstallAndUpdateTwoMajorVersions()1364     public void testSdkInstallAndUpdateTwoMajorVersions() throws Exception {
1365         onBeforeSdkTests();
1366 
1367         installPackage(TEST_SDK1);
1368         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1369 
1370         installPackage(TEST_SDK2);
1371         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1372         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1373 
1374         // Same APK.
1375         installPackage(TEST_SDK1);
1376         installPackage(TEST_SDK2);
1377 
1378         // Updated APK.
1379         installPackage(TEST_SDK1_UPDATED);
1380         installPackage(TEST_SDK2_UPDATED);
1381 
1382         // Reverted APK.
1383         installPackage(TEST_SDK1);
1384         installPackage(TEST_SDK2);
1385 
1386         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1387         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1388     }
1389 
1390     @Test
1391     @RequiresFlagsEnabled(FLAG_SDK_LIB_INDEPENDENCE)
testAppUsingSdkOptionalInstallInstall_allowAppInstallWithoutSDK()1392     public void testAppUsingSdkOptionalInstallInstall_allowAppInstallWithoutSDK()
1393             throws Exception {
1394         onBeforeSdkTests();
1395 
1396         // Try to install without required SDK1.
1397         installPackage(TEST_USING_SDK1_OPTIONAL);
1398         assertTrue(isAppInstalled(TEST_SDK_USER_PACKAGE));
1399     }
1400 
1401     @Test
1402     @RequiresFlagsDisabled(FLAG_SDK_LIB_INDEPENDENCE)
testAppUsingSdkOptionalInstall_blockAppInstallWithoutSDK()1403     public void testAppUsingSdkOptionalInstall_blockAppInstallWithoutSDK() throws Exception {
1404         onBeforeSdkTests();
1405 
1406         // Try to install without required SDK1.
1407         installPackage(TEST_USING_SDK1_OPTIONAL, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1408         assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE));
1409     }
1410 
1411     @Test
testAppUsingSdkRequiredInstallAndUpdate()1412     public void testAppUsingSdkRequiredInstallAndUpdate() throws Exception {
1413         onBeforeSdkTests();
1414         // Try to install without required SDK1.
1415         installPackage(TEST_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1416         assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE));
1417 
1418         // Now install the required SDK1.
1419         installPackage(TEST_SDK1);
1420         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1421 
1422         overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1423 
1424         // Install and uninstall.
1425         installPackage(TEST_USING_SDK1);
1426         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1427 
1428         // Update SDK1.
1429         installPackage(TEST_SDK1_UPDATED);
1430 
1431         // Install again.
1432         installPackage(TEST_USING_SDK1);
1433 
1434         // Check resolution API.
1435         getUiAutomation().adoptShellPermissionIdentity();
1436         try {
1437             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE,
1438                     PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1439             assertEquals(1, appInfo.sharedLibraryInfos.size());
1440             SharedLibraryInfo libInfo = appInfo.sharedLibraryInfos.get(0);
1441             assertEquals("com.test.sdk1", libInfo.getName());
1442             assertEquals(1, libInfo.getLongVersion());
1443         } finally {
1444             getUiAutomation().dropShellPermissionIdentity();
1445         }
1446 
1447         // Try to install without required SDK2.
1448         installPackage(TEST_USING_SDK1_AND_SDK2,
1449                 "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1450 
1451         // Now install the required SDK2.
1452         installPackage(TEST_SDK2);
1453         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1454         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1455 
1456         // Install and uninstall.
1457         installPackage(TEST_USING_SDK1_AND_SDK2);
1458         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1459 
1460         // Update both SDKs.
1461         installPackage(TEST_SDK1_UPDATED);
1462         installPackage(TEST_SDK2_UPDATED);
1463         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1464         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1465 
1466         // Install again.
1467         installPackage(TEST_USING_SDK1_AND_SDK2);
1468 
1469         // Check resolution API.
1470         getUiAutomation().adoptShellPermissionIdentity();
1471         try {
1472             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE,
1473                     PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1474             assertEquals(2, appInfo.sharedLibraryInfos.size());
1475             assertEquals("com.test.sdk1", appInfo.sharedLibraryInfos.get(0).getName());
1476             assertEquals(1, appInfo.sharedLibraryInfos.get(0).getLongVersion());
1477             assertEquals("com.test.sdk2", appInfo.sharedLibraryInfos.get(1).getName());
1478             assertEquals(2, appInfo.sharedLibraryInfos.get(1).getLongVersion());
1479         } finally {
1480             getUiAutomation().dropShellPermissionIdentity();
1481         }
1482     }
1483 
1484     @Test
testAppUsingSdkRequiredInstallGroupInstall()1485     public void testAppUsingSdkRequiredInstallGroupInstall() throws Exception {
1486         onBeforeSdkTests();
1487 
1488         // Install/uninstall the sdk to grab its certDigest.
1489         installPackage(TEST_SDK1);
1490         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1491         String sdkCertDigest = getPackageCertDigest(TEST_SDK1_PACKAGE);
1492         uninstallPackageSilently(TEST_SDK1_PACKAGE);
1493 
1494         // Try to install without required SDK1.
1495         installPackage(TEST_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1496         assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE));
1497 
1498         // Parent session
1499         String parentSessionId = createSession("--multi-package");
1500 
1501         // Required SDK1.
1502         String sdkSessionId = createSession("");
1503         addSplits(sdkSessionId, new String[] { createApkPath(TEST_SDK1) });
1504 
1505         // The app.
1506         String appSessionId = createSession("");
1507         addSplits(appSessionId, new String[] { createApkPath(TEST_USING_SDK1) });
1508 
1509         overrideUsesSdkLibraryCertificateDigest(sdkCertDigest);
1510 
1511         // Add both child sessions to the primary session and commit.
1512         assertEquals("Success\n", executeShellCommand(
1513                 "pm install-add-session " + parentSessionId + " " + sdkSessionId + " "
1514                         + appSessionId));
1515         commitSession(parentSessionId);
1516 
1517         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1518         assertTrue(isAppInstalled(TEST_SDK_USER_PACKAGE));
1519 
1520         // Check resolution API.
1521         getUiAutomation().adoptShellPermissionIdentity();
1522         try {
1523             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE,
1524                     PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1525             assertEquals(1, appInfo.sharedLibraryInfos.size());
1526             SharedLibraryInfo libInfo = appInfo.sharedLibraryInfos.get(0);
1527             assertEquals("com.test.sdk1", libInfo.getName());
1528             assertEquals(1, libInfo.getLongVersion());
1529         } finally {
1530             getUiAutomation().dropShellPermissionIdentity();
1531         }
1532     }
1533 
1534     @Test
testInstallSdkFailsMismatchingCertificate()1535     public void testInstallSdkFailsMismatchingCertificate() throws Exception {
1536         onBeforeSdkTests();
1537 
1538         // Install the required SDK1.
1539         installPackage(TEST_SDK1);
1540         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1541 
1542         // Try to install the package with empty digest.
1543         installPackage(TEST_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1544     }
1545 
1546     @Test
testUninstallSdkRequiredWhileAppUsing_blockUninstall()1547     public void testUninstallSdkRequiredWhileAppUsing_blockUninstall() throws Exception {
1548         onBeforeSdkTests();
1549 
1550         // Install the required SDK1.
1551         installPackage(TEST_SDK1);
1552         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1553 
1554         overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1555 
1556         // Install the package.
1557         installPackage(TEST_USING_SDK1);
1558 
1559         uninstallPackage(TEST_SDK1_PACKAGE, "Failure [DELETE_FAILED_USED_SHARED_LIBRARY]");
1560 
1561         // The SDK is still installed
1562         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1563     }
1564 
1565     @Test
1566     @RequiresFlagsEnabled(FLAG_SDK_LIB_INDEPENDENCE)
testUninstallSdkOptionalWhileAppUsing_allowUninstall()1567     public void testUninstallSdkOptionalWhileAppUsing_allowUninstall() throws Exception {
1568         onBeforeSdkTests();
1569 
1570         // Install the required SDK1.
1571         installPackage(TEST_SDK1);
1572         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1573 
1574         overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1575 
1576         // Install the package optional using sdk1
1577         installPackage(TEST_USING_SDK1_OPTIONAL);
1578 
1579         uninstallPackage(TEST_SDK1_PACKAGE, "Success");
1580         assertThat(isSdkInstalled(TEST_SDK1_NAME, 1)).isFalse();
1581     }
1582 
1583     @Test
1584     @RequiresFlagsEnabled(FLAG_SDK_LIB_INDEPENDENCE)
testSdkOptionalEnabledGetSharedLibraries()1585     public void testSdkOptionalEnabledGetSharedLibraries() throws Exception {
1586         onBeforeSdkTests();
1587 
1588         // Install the SDK1.
1589         installPackage(TEST_SDK1);
1590         // Install the SDK2.
1591         installPackage(TEST_SDK2);
1592 
1593         {
1594             List<SharedLibraryInfo> libs = getSharedLibraries();
1595             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1596             assertNotNull(sdk1);
1597             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1598             assertNotNull(sdk2);
1599         }
1600         {
1601             overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1602 
1603             installPackage(TEST_USING_SDK1_OPTIONAL_SDK2);
1604 
1605             List<SharedLibraryInfo> libs = getSharedLibraries();
1606             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1607             assertNotNull(sdk1);
1608             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1609             assertNotNull(sdk2);
1610 
1611             // SDK1 optional
1612             assertEquals(TEST_SDK_USER_PACKAGE,
1613                     sdk1.getDependentPackages().get(0).getPackageName());
1614             assertEquals(TEST_SDK_USER_PACKAGE,
1615                     sdk1.getOptionalDependentPackages().get(0).getPackageName());
1616 
1617             // SDK2 required
1618             assertEquals(TEST_SDK_USER_PACKAGE,
1619                     sdk2.getDependentPackages().get(0).getPackageName());
1620             assertThat(sdk2.getOptionalDependentPackages()).isEmpty();
1621 
1622             getUiAutomation().adoptShellPermissionIdentity();
1623             try {
1624                 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(
1625                         TEST_SDK_USER_PACKAGE,
1626                         PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1627 
1628                 // feature is enabled. Two, one is optional, one is required
1629                 assertThat(appInfo.sharedLibraryInfos).isNotNull();
1630                 assertThat(appInfo.optionalSharedLibraryInfos).isNotNull();
1631                 assertThat(appInfo.sharedLibraryInfos.size()).isEqualTo(2);
1632                 assertThat(appInfo.optionalSharedLibraryInfos.size()).isEqualTo(1);
1633 
1634                 assertThat(appInfo.optionalSharedLibraryInfos.get(0).getName()).isEqualTo(
1635                         "com.test.sdk1");
1636                 assertThat(appInfo.optionalSharedLibraryInfos.get(0).getLongVersion()).isEqualTo(1);
1637 
1638                 assertThat(appInfo.sharedLibraryInfos.get(0).getName()).isEqualTo(
1639                         "com.test.sdk1");
1640                 assertThat(appInfo.sharedLibraryInfos.get(0).getLongVersion()).isEqualTo(1);
1641                 assertThat(appInfo.sharedLibraryInfos.get(1).getName()).isEqualTo(
1642                         "com.test.sdk2");
1643                 assertThat(appInfo.sharedLibraryInfos.get(1).getLongVersion()).isEqualTo(2);
1644             } finally {
1645                 getUiAutomation().dropShellPermissionIdentity();
1646             }
1647             uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1648         }
1649     }
1650 
1651     @Test
1652     @RequiresFlagsDisabled(FLAG_SDK_LIB_INDEPENDENCE)
testSdkOptionalDisabledGetSharedLibraries()1653     public void testSdkOptionalDisabledGetSharedLibraries() throws Exception {
1654         onBeforeSdkTests();
1655 
1656         // Install the SDK1.
1657         installPackage(TEST_SDK1);
1658         // Install the SDK2.
1659         installPackage(TEST_SDK2);
1660 
1661         {
1662             List<SharedLibraryInfo> libs = getSharedLibraries();
1663             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1664             assertNotNull(sdk1);
1665             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1666             assertNotNull(sdk2);
1667         }
1668 
1669         {
1670             overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1671 
1672             installPackage(TEST_USING_SDK1_OPTIONAL_SDK2);
1673 
1674             List<SharedLibraryInfo> libs = getSharedLibraries();
1675             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1676             assertNotNull(sdk1);
1677             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1678             assertNotNull(sdk2);
1679 
1680             assertEquals(TEST_SDK_USER_PACKAGE,
1681                     sdk1.getDependentPackages().get(0).getPackageName());
1682             assertEquals(TEST_SDK_USER_PACKAGE,
1683                     sdk2.getDependentPackages().get(0).getPackageName());
1684             assertThat(sdk1.getOptionalDependentPackages()).isEmpty();
1685             assertThat(sdk2.getOptionalDependentPackages()).isEmpty();
1686 
1687 
1688             getUiAutomation().adoptShellPermissionIdentity();
1689             try {
1690                 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(
1691                         TEST_SDK_USER_PACKAGE,
1692                         PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1693 
1694                 // Two, one is optional, one is required but feature is disabled
1695                 assertThat(appInfo.sharedLibraryInfos).isNotNull();
1696                 assertThat(appInfo.optionalSharedLibraryInfos).isNull();
1697                 assertThat(appInfo.sharedLibraryInfos.size()).isEqualTo(2);
1698 
1699                 assertThat(appInfo.sharedLibraryInfos.get(0).getName()).isEqualTo(
1700                         "com.test.sdk1");
1701                 assertThat(appInfo.sharedLibraryInfos.get(0).getLongVersion()).isEqualTo(1);
1702 
1703                 assertThat(appInfo.sharedLibraryInfos.get(1).getName()).isEqualTo(
1704                         "com.test.sdk2");
1705                 assertThat(appInfo.sharedLibraryInfos.get(1).getLongVersion()).isEqualTo(2);
1706             } finally {
1707                 getUiAutomation().dropShellPermissionIdentity();
1708             }
1709             uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1710         }
1711     }
1712 
1713     @Test
testGetSharedLibraries()1714     public void testGetSharedLibraries() throws Exception {
1715         onBeforeSdkTests();
1716 
1717         // Install the SDK1.
1718         installPackage(TEST_SDK1);
1719         {
1720             List<SharedLibraryInfo> libs = getSharedLibraries();
1721             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1722             assertNotNull(sdk1);
1723             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1724             assertNull(sdk2);
1725         }
1726 
1727         // Install the SDK2.
1728         installPackage(TEST_SDK2);
1729         {
1730             List<SharedLibraryInfo> libs = getSharedLibraries();
1731             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1732             assertNotNull(sdk1);
1733             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1734             assertNotNull(sdk2);
1735         }
1736 
1737         // Install and uninstall the user package.
1738         {
1739             overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1740 
1741             installPackage(TEST_USING_SDK1_AND_SDK2);
1742 
1743             List<SharedLibraryInfo> libs = getSharedLibraries();
1744             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1745             assertNotNull(sdk1);
1746             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1747             assertNotNull(sdk2);
1748 
1749             assertEquals(TEST_SDK_USER_PACKAGE,
1750                     sdk1.getDependentPackages().get(0).getPackageName());
1751             assertEquals(TEST_SDK_USER_PACKAGE,
1752                     sdk2.getDependentPackages().get(0).getPackageName());
1753             assertThat(sdk1.getOptionalDependentPackages()).isEmpty();
1754             assertThat(sdk2.getOptionalDependentPackages()).isEmpty();
1755 
1756             uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1757         }
1758 
1759         // Uninstall the SDK1.
1760         uninstallPackageSilently(TEST_SDK1_PACKAGE);
1761         {
1762             List<SharedLibraryInfo> libs = getSharedLibraries();
1763             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1764             assertNull(sdk1);
1765             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1766             assertNotNull(sdk2);
1767         }
1768 
1769         // Uninstall the SDK2.
1770         uninstallPackageSilently(TEST_SDK2_PACKAGE);
1771         {
1772             List<SharedLibraryInfo> libs = getSharedLibraries();
1773             SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1);
1774             assertNull(sdk1);
1775             SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2);
1776             assertNull(sdk2);
1777         }
1778     }
1779 
1780     @Test
testUninstallUnusedSdks()1781     public void testUninstallUnusedSdks() throws Exception {
1782         onBeforeSdkTests();
1783 
1784         installPackage(TEST_SDK1);
1785         installPackage(TEST_SDK2);
1786 
1787         overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1788         installPackage(TEST_USING_SDK1_AND_SDK2);
1789 
1790         setSystemProperty("debug.pm.prune_unused_shared_libraries_delay", "0");
1791         executeShellCommand("settings put global unused_static_shared_lib_min_cache_period 0");
1792         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1793 
1794         // Wait for 3secs max.
1795         for (int i = 0; i < 30; ++i) {
1796             if (!isSdkInstalled(TEST_SDK1_NAME, 1) && !isSdkInstalled(TEST_SDK2_NAME, 2)) {
1797                 break;
1798             }
1799             final int beforeRetryDelayMs = 100;
1800             Thread.currentThread().sleep(beforeRetryDelayMs);
1801         }
1802         assertFalse(isSdkInstalled(TEST_SDK1_NAME, 1));
1803         assertFalse(isSdkInstalled(TEST_SDK2_NAME, 2));
1804     }
1805 
1806     @Test
testAppUsingSdkRequiredUsingSdkInstallAndUpdate()1807     public void testAppUsingSdkRequiredUsingSdkInstallAndUpdate() throws Exception {
1808         onBeforeSdkTests();
1809 
1810         // Try to install without required SDK1.
1811         installPackage(TEST_USING_SDK3, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1812         assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE));
1813 
1814         // Try to install SDK3 without required SDK1.
1815         installPackage(TEST_SDK3_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1816         assertFalse(isSdkInstalled(TEST_SDK3_NAME, 3));
1817 
1818         // Now install the required SDK1.
1819         installPackage(TEST_SDK1);
1820         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1821 
1822         overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1823 
1824         // Now install the required SDK3.
1825         installPackage(TEST_SDK3_USING_SDK1);
1826         assertTrue(isSdkInstalled(TEST_SDK3_NAME, 3));
1827 
1828         // Install and uninstall.
1829         installPackage(TEST_USING_SDK3);
1830         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1831 
1832         // Update SDK1.
1833         installPackage(TEST_SDK1_UPDATED);
1834 
1835         // Install again.
1836         installPackage(TEST_USING_SDK3);
1837 
1838         // Check resolution API.
1839         getUiAutomation().adoptShellPermissionIdentity();
1840         try {
1841             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE,
1842                     PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1843             assertEquals(1, appInfo.sharedLibraryInfos.size());
1844             SharedLibraryInfo libInfo = appInfo.sharedLibraryInfos.get(0);
1845             assertEquals("com.test.sdk3", libInfo.getName());
1846             assertEquals(3, libInfo.getLongVersion());
1847         } finally {
1848             getUiAutomation().dropShellPermissionIdentity();
1849         }
1850 
1851         // Try to install updated SDK3 without required SDK2.
1852         installPackage(TEST_SDK3_USING_SDK1_AND_SDK2,
1853                 "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1854 
1855         // Now install the required SDK2.
1856         installPackage(TEST_SDK2);
1857         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1858         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1859 
1860         installPackage(TEST_SDK3_USING_SDK1_AND_SDK2);
1861         assertTrue(isSdkInstalled(TEST_SDK3_NAME, 3));
1862 
1863         // Install and uninstall.
1864         installPackage(TEST_USING_SDK3);
1865         uninstallPackageSilently(TEST_SDK_USER_PACKAGE);
1866 
1867         // Update both SDKs.
1868         installPackage(TEST_SDK1_UPDATED);
1869         installPackage(TEST_SDK2_UPDATED);
1870         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1871         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1872 
1873         // Install again.
1874         installPackage(TEST_USING_SDK3);
1875 
1876         // Check resolution API.
1877         getUiAutomation().adoptShellPermissionIdentity();
1878         try {
1879             ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE,
1880                     PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES));
1881             assertEquals(1, appInfo.sharedLibraryInfos.size());
1882             assertEquals("com.test.sdk3", appInfo.sharedLibraryInfos.get(0).getName());
1883             assertEquals(3, appInfo.sharedLibraryInfos.get(0).getLongVersion());
1884         } finally {
1885             getUiAutomation().dropShellPermissionIdentity();
1886         }
1887     }
1888 
1889     @Test
testSdkUsingSdkRequiredInstallAndUpdate()1890     public void testSdkUsingSdkRequiredInstallAndUpdate() throws Exception {
1891         onBeforeSdkTests();
1892 
1893         // Try to install without required SDK1.
1894         installPackage(TEST_SDK3_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1895         assertFalse(isSdkInstalled(TEST_SDK3_NAME, 3));
1896 
1897         // Now install the required SDK1.
1898         installPackage(TEST_SDK1);
1899         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1900 
1901         overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE));
1902 
1903         // Install and uninstall.
1904         installPackage(TEST_SDK3_USING_SDK1);
1905         uninstallPackageSilently(TEST_SDK3_PACKAGE);
1906 
1907         // Update SDK1.
1908         installPackage(TEST_SDK1_UPDATED);
1909 
1910         // Install again.
1911         installPackage(TEST_SDK3_USING_SDK1);
1912 
1913         // Check resolution API.
1914         {
1915             List<SharedLibraryInfo> libs = getSharedLibraries();
1916             SharedLibraryInfo sdk3 = findLibrary(libs, "com.test.sdk3", 3);
1917             assertNotNull(sdk3);
1918             List<SharedLibraryInfo> deps = sdk3.getDependencies();
1919             assertEquals(1, deps.size());
1920             SharedLibraryInfo libInfo = deps.get(0);
1921             assertEquals("com.test.sdk1", libInfo.getName());
1922             assertEquals(1, libInfo.getLongVersion());
1923         }
1924 
1925         // Try to install without required SDK2.
1926         installPackage(TEST_SDK3_USING_SDK1_AND_SDK2,
1927                 "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY");
1928 
1929         // Now install the required SDK2.
1930         installPackage(TEST_SDK2);
1931         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1932         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1933 
1934         // Install and uninstall.
1935         installPackage(TEST_SDK3_USING_SDK1_AND_SDK2);
1936         uninstallPackageSilently(TEST_SDK3_PACKAGE);
1937 
1938         // Update both SDKs.
1939         installPackage(TEST_SDK1_UPDATED);
1940         installPackage(TEST_SDK2_UPDATED);
1941         assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1));
1942         assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2));
1943 
1944         // Install again.
1945         installPackage(TEST_SDK3_USING_SDK1_AND_SDK2);
1946 
1947         // Check resolution API.
1948         {
1949             List<SharedLibraryInfo> libs = getSharedLibraries();
1950             SharedLibraryInfo sdk3 = findLibrary(libs, "com.test.sdk3", 3);
1951             assertNotNull(sdk3);
1952             List<SharedLibraryInfo> deps = sdk3.getDependencies();
1953             assertEquals(2, deps.size());
1954             assertEquals("com.test.sdk1", deps.get(0).getName());
1955             assertEquals(1, deps.get(0).getLongVersion());
1956             assertEquals("com.test.sdk2", deps.get(1).getName());
1957             assertEquals(2, deps.get(1).getLongVersion());
1958         }
1959     }
1960 
runPackageVerifierTest(BiConsumer<Context, Intent> onBroadcast)1961     private void runPackageVerifierTest(BiConsumer<Context, Intent> onBroadcast)
1962             throws Exception {
1963         runPackageVerifierTest(TEST_HW5, TEST_HW7, "Success", onBroadcast);
1964     }
1965 
runPackageVerifierTest(String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)1966     private void runPackageVerifierTest(String expectedResultStartsWith,
1967             BiConsumer<Context, Intent> onBroadcast) throws Exception {
1968         runPackageVerifierTest(TEST_HW5, TEST_HW7, expectedResultStartsWith, onBroadcast);
1969     }
1970 
runPackageVerifierTest(String baseName, String updatedName, String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)1971     private void runPackageVerifierTest(String baseName, String updatedName,
1972             String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)
1973             throws Exception {
1974         AtomicReference<Thread> onBroadcastThread = new AtomicReference<>();
1975 
1976         runPackageVerifierTestSync(baseName, updatedName, expectedResultStartsWith,
1977                 (context, intent) -> {
1978                     Thread thread = new Thread(() -> onBroadcast.accept(context, intent));
1979                     thread.start();
1980                     onBroadcastThread.set(thread);
1981                 });
1982 
1983         final Thread thread = onBroadcastThread.get();
1984         if (thread != null) {
1985             thread.join();
1986         }
1987     }
1988 
runPackageVerifierTestSync(String baseName, String updatedName, String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)1989     private void runPackageVerifierTestSync(String baseName, String updatedName,
1990             String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)
1991             throws Exception {
1992         // Install a package.
1993         installPackage(baseName);
1994         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
1995 
1996         getUiAutomation().adoptShellPermissionIdentity(
1997                 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
1998                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
1999 
2000         final CompletableFuture<Boolean> broadcastReceived = new CompletableFuture<>();
2001 
2002         // Create a single-use broadcast receiver
2003         BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
2004             @Override
2005             public void onReceive(Context context, Intent intent) {
2006                 context.unregisterReceiver(this);
2007                 onBroadcast.accept(context, intent);
2008                 broadcastReceived.complete(true);
2009             }
2010         };
2011         // Create an intent-filter and register the receiver
2012         IntentFilter intentFilter = new IntentFilter();
2013         intentFilter.addAction(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
2014         intentFilter.addDataType(PACKAGE_MIME_TYPE);
2015         // The broadcast is sent for user 0, so we need to request it for all users.
2016         // TODO(b/232317379) Fix this in proper way
2017         getContext().registerReceiverForAllUsers(broadcastReceiver, intentFilter, null, null,
2018                 RECEIVER_EXPORTED);
2019 
2020         // Enable verification.
2021         executeShellCommand("settings put global verifier_verify_adb_installs 1");
2022         // Override verifier for updates of debuggable apps.
2023         setSystemProperty("debug.pm.adb_verifier_override_packages",
2024                 CTS_PACKAGE_NAME + ";" + TEST_VERIFIER_PACKAGE);
2025 
2026         final int settingValue = Integer.parseInt(
2027                 executeShellCommand("settings get global verifier_verify_adb_installs").trim());
2028         final String sysPropertyValue = getSystemProperty(
2029                 "debug.pm.adb_verifier_override_packages").trim();
2030         // Make sure the setting and property are set
2031         assertEquals("verifier_verify_adb_installs is " + settingValue + " expecting 1",
2032                 1, settingValue);
2033         assertEquals("debug.pm.adb_verifier_override_packages is " + sysPropertyValue,
2034                 CTS_PACKAGE_NAME + ";" + TEST_VERIFIER_PACKAGE, sysPropertyValue);
2035 
2036         // Update the package, should trigger verifier override.
2037         installPackage(updatedName, expectedResultStartsWith);
2038 
2039         // Wait for broadcast.
2040         broadcastReceived.get(VERIFICATION_BROADCAST_RECEIVED_TIMEOUT_MS, TimeUnit.MILLISECONDS);
2041     }
2042 
2043     @Test
2044     @LargeTest
testPackageVerifierAllow()2045     public void testPackageVerifierAllow() throws Exception {
2046         assumeTrue(!mStreaming);
2047         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2048 
2049         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2050 
2051         runPackageVerifierTest((context, intent) -> {
2052             int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2053             assertNotEquals(-1, verificationId);
2054 
2055             dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2056             int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2057             assertNotEquals(-1, sessionId);
2058 
2059             getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2060         });
2061 
2062         assertEquals(mDataLoaderType, dataLoaderType.get());
2063     }
2064 
2065     @Test
2066     @LargeTest
testPackageVerifierAllowTwoVerifiers()2067     public void testPackageVerifierAllowTwoVerifiers() throws Exception {
2068         assumeTrue(!mStreaming);
2069         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2070 
2071         installPackage(TEST_VERIFIER_ALLOW);
2072         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2073 
2074         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2075 
2076         runPackageVerifierTest((context, intent) -> {
2077             int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2078             assertNotEquals(-1, verificationId);
2079 
2080             dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2081             int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2082             assertNotEquals(-1, sessionId);
2083 
2084             getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2085         });
2086 
2087         assertEquals(mDataLoaderType, dataLoaderType.get());
2088     }
2089 
2090     @Test
2091     @LargeTest
testPackageVerifierReject()2092     public void testPackageVerifierReject() throws Exception {
2093         assumeTrue(!mStreaming);
2094         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2095 
2096         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2097 
2098         runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2099                 (context, intent) -> {
2100                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2101                     assertNotEquals(-1, verificationId);
2102 
2103                     dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2104                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2105                     assertNotEquals(-1, sessionId);
2106 
2107                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_REJECT);
2108                 });
2109 
2110         assertEquals(mDataLoaderType, dataLoaderType.get());
2111     }
2112 
2113     @Test
2114     @LargeTest
testPackageSufficientVerifierReject()2115     public void testPackageSufficientVerifierReject() throws Exception {
2116         assumeTrue(!mStreaming);
2117         uninstallPackageSilently(TEST_SUFFICIENT_VERIFIER_PACKAGE);
2118 
2119         // TEST_SUFFICIENT configured to have hellosufficient as sufficient verifier.
2120         installPackage(TEST_SUFFICIENT_VERIFIER_REJECT);
2121         assertTrue(isAppInstalled(TEST_SUFFICIENT_VERIFIER_PACKAGE));
2122 
2123         // PackageManager.verifyPendingInstall() call only works with user 0 as verifier is expected
2124         // to be user 0. So skip the test if it is not user 0.
2125         // TODO(b/232317379) Fix this in proper way
2126         assumeTrue(getContext().getUserId() == UserHandle.USER_SYSTEM);
2127         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2128 
2129         runPackageVerifierTest(TEST_HW5, TEST_SUFFICIENT,
2130                 "Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2131                 (context, intent) -> {
2132                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2133                     assertNotEquals(-1, verificationId);
2134 
2135                     dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2136                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2137                     assertNotEquals(-1, sessionId);
2138 
2139                     // This is a required verifier. The installation should fail, even though the
2140                     // required verifier allows installation.
2141                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2142                 });
2143 
2144         assertEquals(mDataLoaderType, dataLoaderType.get());
2145     }
2146 
2147     @Test
2148     @LargeTest
testPackageVerifierRejectTwoVerifiersBothReject()2149     public void testPackageVerifierRejectTwoVerifiersBothReject() throws Exception {
2150         assumeTrue(!mStreaming);
2151         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2152 
2153         installPackage(TEST_VERIFIER_REJECT);
2154         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2155 
2156         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2157 
2158         runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2159                 (context, intent) -> {
2160                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2161                     assertNotEquals(-1, verificationId);
2162 
2163                     dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2164                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2165                     assertNotEquals(-1, sessionId);
2166 
2167                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_REJECT);
2168                 });
2169 
2170         assertEquals(mDataLoaderType, dataLoaderType.get());
2171     }
2172 
2173     @Test
2174     @LargeTest
testPackageVerifierRejectTwoVerifiersOnlyOneRejects()2175     public void testPackageVerifierRejectTwoVerifiersOnlyOneRejects() throws Exception {
2176         assumeTrue(!mStreaming);
2177         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2178 
2179         installPackage(TEST_VERIFIER_REJECT);
2180         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2181 
2182         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2183 
2184         runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2185                 (context, intent) -> {
2186                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2187                     assertNotEquals(-1, verificationId);
2188 
2189                     dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2190                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2191                     assertNotEquals(-1, sessionId);
2192 
2193                     // This one allows, the other one rejects.
2194                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2195                 });
2196 
2197         assertEquals(mDataLoaderType, dataLoaderType.get());
2198     }
2199 
2200     @Test
2201     @LargeTest
testPackageVerifierRejectTwoVerifiersOnlyOneDelayedRejects()2202     public void testPackageVerifierRejectTwoVerifiersOnlyOneDelayedRejects() throws Exception {
2203         assumeTrue(!mStreaming);
2204         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2205 
2206         installPackage(TEST_VERIFIER_DELAYED_REJECT);
2207         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2208 
2209         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2210 
2211         runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2212                 (context, intent) -> {
2213                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2214                     assertNotEquals(-1, verificationId);
2215 
2216                     dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2217                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2218                     assertNotEquals(-1, sessionId);
2219 
2220                     // This one allows, the other one rejects.
2221                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2222                 });
2223 
2224         assertEquals(mDataLoaderType, dataLoaderType.get());
2225     }
2226 
2227     @Test
2228     @LargeTest
testPackageVerifierRejectAfterTimeout()2229     public void testPackageVerifierRejectAfterTimeout() throws Exception {
2230         assumeTrue(mVerifierTimeoutTest);
2231         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2232 
2233         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2234 
2235         runPackageVerifierTestSync(TEST_HW5, TEST_HW7, "Success", (context, intent) -> {
2236             int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2237             assertNotEquals(-1, verificationId);
2238 
2239             dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2240             int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2241             assertNotEquals(-1, sessionId);
2242 
2243             try {
2244                 if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL) {
2245                     // For streaming installations, the timeout is fixed at 3secs and always
2246                     // allow the install. Try to extend the timeout and then reject after
2247                     // much shorter time.
2248                     getPackageManager().extendVerificationTimeout(verificationId,
2249                             VERIFICATION_REJECT, sStreamingVerificationTimeoutMs * 3);
2250                     Thread.sleep(sStreamingVerificationTimeoutMs * 2);
2251                     getPackageManager().verifyPendingInstall(verificationId,
2252                             VERIFICATION_REJECT);
2253                 } else {
2254                     getPackageManager().verifyPendingInstall(verificationId,
2255                             VERIFICATION_ALLOW);
2256                 }
2257             } catch (InterruptedException e) {
2258                 throw new RuntimeException(e);
2259             }
2260         });
2261 
2262         assertEquals(mDataLoaderType, dataLoaderType.get());
2263     }
2264 
2265     @Test
2266     @LargeTest
testPackageVerifierWithExtensionAndTimeout()2267     public void testPackageVerifierWithExtensionAndTimeout() throws Exception {
2268         assumeTrue(mVerifierTimeoutTest);
2269         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2270 
2271         runPackageVerifierTest((context, intent) -> {
2272             int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2273             assertNotEquals(-1, verificationId);
2274 
2275             dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2276             int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2277             assertNotEquals(-1, sessionId);
2278 
2279             try {
2280                 if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL) {
2281                     // For streaming installations, the timeout is fixed at 3secs and always
2282                     // allow the install. Try to extend the timeout and then reject after
2283                     // much shorter time.
2284                     getPackageManager().extendVerificationTimeout(verificationId,
2285                             VERIFICATION_REJECT, sStreamingVerificationTimeoutMs * 3);
2286                     Thread.sleep(sStreamingVerificationTimeoutMs * 2);
2287                     getPackageManager().verifyPendingInstall(verificationId,
2288                             VERIFICATION_REJECT);
2289                 } else {
2290                     getPackageManager().verifyPendingInstall(verificationId,
2291                             VERIFICATION_ALLOW);
2292                 }
2293             } catch (InterruptedException e) {
2294                 throw new RuntimeException(e);
2295             }
2296         });
2297 
2298         assertEquals(mDataLoaderType, dataLoaderType.get());
2299     }
2300 
2301     @Test
testPackageVerifierWithChecksums()2302     public void testPackageVerifierWithChecksums() throws Exception {
2303         assumeTrue(mVerifierTimeoutTest);
2304         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2305 
2306         AtomicInteger dataLoaderType = new AtomicInteger(-1);
2307         List<ApkChecksum> checksums = new ArrayList<>();
2308         StringBuilder rootHash = new StringBuilder();
2309 
2310         runPackageVerifierTest((context, intent) -> {
2311             int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2312             assertNotEquals(-1, verificationId);
2313 
2314             dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1));
2315             int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2316             assertNotEquals(-1, sessionId);
2317 
2318             try {
2319                 PackageInstaller.Session session = getPackageInstaller().openSession(sessionId);
2320                 assertNotNull(session);
2321 
2322                 rootHash.append(intent.getStringExtra(EXTRA_VERIFICATION_ROOT_HASH));
2323 
2324                 String[] names = session.getNames();
2325                 assertEquals(1, names.length);
2326                 session.requestChecksums(names[0], 0, PackageManager.TRUST_ALL,
2327                         ConcurrentUtils.DIRECT_EXECUTOR,
2328                         result -> checksums.addAll(result));
2329             } catch (IOException | CertificateEncodingException e) {
2330                 throw new RuntimeException(e);
2331             }
2332         });
2333 
2334         assertEquals(mDataLoaderType, dataLoaderType.get());
2335 
2336         assertEquals(1, checksums.size());
2337 
2338         if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL) {
2339             assertEquals(TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, checksums.get(0).getType());
2340             assertEquals(rootHash.toString(),
2341                     "base.apk:" + HexDump.toHexString(checksums.get(0).getValue()));
2342         } else {
2343             assertEquals(TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256, checksums.get(0).getType());
2344         }
2345     }
2346 
2347     @Test
testPackageVerifierWithOneVerifierDisabledAtRunTime()2348     public void testPackageVerifierWithOneVerifierDisabledAtRunTime() throws Exception {
2349         assumeTrue(!mStreaming);
2350         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2351 
2352         installPackage(TEST_VERIFIER_REJECT);
2353         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2354         runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2355                 (context, intent) -> {
2356                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2357                     assertNotEquals(-1, verificationId);
2358 
2359                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2360                     assertNotEquals(-1, sessionId);
2361 
2362                     // This one allows, the other one rejects.
2363                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2364                 });
2365 
2366         // We can't disable the test package, but we can disable the second verifier package
2367         disablePackage(TEST_VERIFIER_PACKAGE);
2368         // Expect the installation to success, even though the second verifier would reject it
2369         // if the verifier is enabled
2370         runPackageVerifierTest(
2371                 (context, intent) -> {
2372                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2373                     assertNotEquals(-1, verificationId);
2374 
2375                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2376                     assertNotEquals(-1, sessionId);
2377 
2378                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2379                 });
2380 
2381     }
2382 
2383     @Test
testPackageVerifierWithOneVerifierDisabledAtManifest()2384     public void testPackageVerifierWithOneVerifierDisabledAtManifest() throws Exception {
2385         assumeTrue(!mStreaming);
2386         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2387 
2388         // The second verifier package is disabled in its manifest
2389         installPackage(TEST_VERIFIER_REJECT);
2390         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2391         runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed",
2392                 (context, intent) -> {
2393                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2394                     assertNotEquals(-1, verificationId);
2395 
2396                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2397                     assertNotEquals(-1, sessionId);
2398 
2399                     // This one allows, the other one rejects.
2400                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2401                 });
2402         // Uninstall the second verifier first to allow for the new verifier installation
2403         uninstallPackageSilently(TEST_VERIFIER_PACKAGE);
2404         installPackage(TEST_VERIFIER_DISABLED);
2405         assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE));
2406         // Expect the installation to success, even though the second verifier would reject it
2407         // if the verifier is enabled
2408         runPackageVerifierTest(
2409                 (context, intent) -> {
2410                     int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
2411                     assertNotEquals(-1, verificationId);
2412 
2413                     int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
2414                     assertNotEquals(-1, sessionId);
2415 
2416                     getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW);
2417                 });
2418 
2419     }
2420 
2421     @Test
testEmergencyInstallerNoAttribute()2422     public void testEmergencyInstallerNoAttribute() throws Exception {
2423         installPackage(TEST_INSTALLER_APP_ABSENT);
2424         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
2425 
2426         getUiAutomation()
2427                 .adoptShellPermissionIdentity(Manifest.permission.EMERGENCY_INSTALL_PACKAGES);
2428         try {
2429             final PackageInstaller installer = getPackageInstaller();
2430             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2431             params.setAppPackageName(TEST_APP_PACKAGE);
2432             final int sessionId = installer.createSession(params);
2433             PackageInstaller.Session session = installer.openSession(sessionId);
2434 
2435             writeFileToSession(session, "installer_app_absent_updated",
2436                     TEST_INSTALLER_APP_ABSENT_UPDATED);
2437 
2438             final CompletableFuture<Integer> status = new CompletableFuture<>();
2439             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
2440             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
2441                 @Override
2442                 public void send(int code, Intent intent, String resolvedType,
2443                         IBinder whitelistToken, IIntentReceiver finishedReceiver,
2444                         String requiredPermission, Bundle options) throws RemoteException {
2445                     status.complete(intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
2446                             Integer.MIN_VALUE));
2447                     statusMessage.complete(
2448                             intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
2449                 }
2450             }));
2451 
2452             assertEquals(statusMessage.get(), PackageInstaller.STATUS_PENDING_USER_ACTION,
2453                     (int) status.get());
2454         } finally {
2455             getUiAutomation().dropShellPermissionIdentity();
2456         }
2457     }
2458 
2459     @Test
testEmergencyInstallerNoPermission()2460     public void testEmergencyInstallerNoPermission() throws Exception {
2461         installPackage(TEST_INSTALLER_APP);
2462         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
2463 
2464         try {
2465             final PackageInstaller installer = getPackageInstaller();
2466             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2467             params.setAppPackageName(TEST_APP_PACKAGE);
2468             final int sessionId = installer.createSession(params);
2469             PackageInstaller.Session session = installer.openSession(sessionId);
2470 
2471             writeFileToSession(session, "installer_app_updated", TEST_INSTALLER_APP_UPDATED);
2472 
2473             final CompletableFuture<Integer> status = new CompletableFuture<>();
2474             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
2475             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
2476                 @Override
2477                 public void send(int code, Intent intent, String resolvedType,
2478                         IBinder whitelistToken, IIntentReceiver finishedReceiver,
2479                         String requiredPermission, Bundle options) throws RemoteException {
2480                     status.complete(intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
2481                             Integer.MIN_VALUE));
2482                     statusMessage.complete(
2483                             intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
2484                 }
2485             }));
2486 
2487             assertEquals(statusMessage.get(), PackageInstaller.STATUS_PENDING_USER_ACTION,
2488                     (int) status.get());
2489         } finally {
2490             getUiAutomation().dropShellPermissionIdentity();
2491         }
2492     }
2493 
2494     // We can't test updating a system app with INSTALL_PACKAGES in CTS tests; this positive test
2495     // will be in GTS tests instead.
2496     @Test
testEmergencyInstallerNonSystemApp()2497     public void testEmergencyInstallerNonSystemApp() throws Exception {
2498         installPackage(TEST_INSTALLER_APP);
2499         assertTrue(isAppInstalled(TEST_APP_PACKAGE));
2500 
2501         getUiAutomation()
2502                 .adoptShellPermissionIdentity(Manifest.permission.EMERGENCY_INSTALL_PACKAGES);
2503         try {
2504             final PackageInstaller installer = getPackageInstaller();
2505             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2506             params.setAppPackageName(TEST_APP_PACKAGE);
2507             final int sessionId = installer.createSession(params);
2508             PackageInstaller.Session session = installer.openSession(sessionId);
2509 
2510             writeFileToSession(session, "installer_app_updated", TEST_INSTALLER_APP_UPDATED);
2511 
2512             final CompletableFuture<Integer> status = new CompletableFuture<>();
2513             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
2514             session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
2515                 @Override
2516                 public void send(int code, Intent intent, String resolvedType,
2517                         IBinder whitelistToken, IIntentReceiver finishedReceiver,
2518                         String requiredPermission, Bundle options) throws RemoteException {
2519                     status.complete(intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
2520                             Integer.MIN_VALUE));
2521                     statusMessage.complete(
2522                             intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
2523                 }
2524             }));
2525 
2526             assertEquals(statusMessage.get(), PackageInstaller.STATUS_PENDING_USER_ACTION,
2527                     (int) status.get());
2528         } finally {
2529             getUiAutomation().dropShellPermissionIdentity();
2530         }
2531     }
2532 
2533     @Test
testEmergencyInstallerUninstallNoAttribiute()2534     public void testEmergencyInstallerUninstallNoAttribiute() throws Exception {
2535         assumeTrue(mDataLoaderType == DATA_LOADER_TYPE_NONE);
2536         getUiAutomation().adoptShellPermissionIdentity(
2537                 Manifest.permission.EMERGENCY_INSTALL_PACKAGES,
2538                 Manifest.permission.REQUEST_DELETE_PACKAGES,
2539                 Manifest.permission.INSTALL_PACKAGES);
2540 
2541         try {
2542             installPackage(TEST_INSTALLER_APP_ABSENT);
2543             assertTrue(isAppInstalled(TEST_APP_PACKAGE));
2544 
2545             final PackageInstaller installer = getPackageInstaller();
2546             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2547             params.setAppPackageName(TEST_APP_PACKAGE);
2548             final int sessionId = installer.createSession(params);
2549             installer.openSession(sessionId);
2550 
2551             final CompletableFuture<Integer> status = new CompletableFuture<>();
2552             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
2553 
2554             installer.uninstall(TEST_APP_PACKAGE,
2555                     new IntentSender((IIntentSender) new IIntentSender.Stub() {
2556                         @Override
2557                         public void send(int code, Intent intent, String resolvedType,
2558                                 IBinder whitelistToken, IIntentReceiver finishedReceiver,
2559                                 String requiredPermission, Bundle options) throws RemoteException {
2560                             status.complete(intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
2561                                     Integer.MIN_VALUE));
2562                             statusMessage.complete(
2563                                     intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
2564                         }
2565                     }));
2566 
2567             assertEquals(statusMessage.get(), PackageInstaller.STATUS_PENDING_USER_ACTION,
2568                     (int) status.get());
2569         } finally {
2570             getUiAutomation().dropShellPermissionIdentity();
2571         }
2572     }
2573 
2574     @Test
testEmergencyInstallerUninstallNoPermission()2575     public void testEmergencyInstallerUninstallNoPermission() throws Exception {
2576         assumeTrue(mDataLoaderType == DATA_LOADER_TYPE_NONE);
2577 
2578         getUiAutomation().adoptShellPermissionIdentity(
2579                 Manifest.permission.REQUEST_DELETE_PACKAGES,
2580                 Manifest.permission.INSTALL_PACKAGES);
2581 
2582         try {
2583             installPackage(TEST_INSTALLER_APP);
2584             assertTrue(isAppInstalled(TEST_APP_PACKAGE));
2585 
2586             final PackageInstaller installer = getPackageInstaller();
2587             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2588             params.setAppPackageName(TEST_APP_PACKAGE);
2589             final int sessionId = installer.createSession(params);
2590             installer.openSession(sessionId);
2591 
2592             final CompletableFuture<Integer> status = new CompletableFuture<>();
2593             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
2594 
2595             installer.uninstall(TEST_APP_PACKAGE,
2596                     new IntentSender((IIntentSender) new IIntentSender.Stub() {
2597                         @Override
2598                         public void send(int code, Intent intent, String resolvedType,
2599                                 IBinder whitelistToken, IIntentReceiver finishedReceiver,
2600                                 String requiredPermission, Bundle options) throws RemoteException {
2601                             status.complete(intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
2602                                     Integer.MIN_VALUE));
2603                             statusMessage.complete(
2604                                     intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
2605                         }
2606                     }));
2607 
2608             assertEquals(statusMessage.get(), PackageInstaller.STATUS_PENDING_USER_ACTION,
2609                     (int) status.get());
2610         } finally {
2611             getUiAutomation().dropShellPermissionIdentity();
2612         }
2613     }
2614 
2615     // We can't test uninstalling a system app in CTS tests; this positive test will be in GTS tests
2616     // instead.
2617     @Test
testEmergencyInstallerUninstallNonSystemApp()2618     public void testEmergencyInstallerUninstallNonSystemApp() throws Exception {
2619         assumeTrue(mDataLoaderType == DATA_LOADER_TYPE_NONE);
2620         getUiAutomation().adoptShellPermissionIdentity(
2621                 Manifest.permission.EMERGENCY_INSTALL_PACKAGES,
2622                 Manifest.permission.REQUEST_DELETE_PACKAGES,
2623                 Manifest.permission.INSTALL_PACKAGES);
2624 
2625         try {
2626             installPackage(TEST_INSTALLER_APP);
2627             assertTrue(isAppInstalled(TEST_APP_PACKAGE));
2628 
2629             final PackageInstaller installer = getPackageInstaller();
2630             final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
2631             params.setAppPackageName(TEST_APP_PACKAGE);
2632             final int sessionId = installer.createSession(params);
2633             installer.openSession(sessionId);
2634 
2635             final CompletableFuture<Integer> status = new CompletableFuture<>();
2636             final CompletableFuture<String> statusMessage = new CompletableFuture<>();
2637 
2638             installer.uninstall(TEST_APP_PACKAGE,
2639                     new IntentSender((IIntentSender) new IIntentSender.Stub() {
2640                         @Override
2641                         public void send(int code, Intent intent, String resolvedType,
2642                                 IBinder whitelistToken, IIntentReceiver finishedReceiver,
2643                                 String requiredPermission, Bundle options) throws RemoteException {
2644                             status.complete(intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
2645                                     Integer.MIN_VALUE));
2646                             statusMessage.complete(
2647                                     intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE));
2648                         }
2649                     }));
2650 
2651             assertEquals(statusMessage.get(), PackageInstaller.STATUS_PENDING_USER_ACTION,
2652                     (int) status.get());
2653         } finally {
2654             getUiAutomation().dropShellPermissionIdentity();
2655         }
2656     }
2657 
getSharedLibraries()2658     private List<SharedLibraryInfo> getSharedLibraries() {
2659         getUiAutomation().adoptShellPermissionIdentity();
2660         try {
2661             return getPackageManager().getSharedLibraries(PackageManager.PackageInfoFlags.of(0));
2662         } finally {
2663             getUiAutomation().dropShellPermissionIdentity();
2664         }
2665     }
2666 
findLibrary(List<SharedLibraryInfo> libs, String name, long version)2667     private SharedLibraryInfo findLibrary(List<SharedLibraryInfo> libs, String name, long version) {
2668         for (int i = 0, size = libs.size(); i < size; ++i) {
2669             SharedLibraryInfo lib = libs.get(i);
2670             if (name.equals(lib.getName()) && version == lib.getLongVersion()) {
2671                 return lib;
2672             }
2673         }
2674         return null;
2675     }
2676 
createUpdateSession(String packageName)2677     private String createUpdateSession(String packageName) throws IOException {
2678         return createSession("-p " + packageName);
2679     }
2680 
createSession(String arg)2681     private String createSession(String arg) throws IOException {
2682         final String prefix = "Success: created install session [";
2683         final String suffix = "]\n";
2684         final String commandResult = executeShellCommand("pm install-create " + arg);
2685         assertTrue(commandResult, commandResult.startsWith(prefix));
2686         assertTrue(commandResult, commandResult.endsWith(suffix));
2687         return commandResult.substring(prefix.length(), commandResult.length() - suffix.length());
2688     }
2689 
addSplits(String sessionId, String[] splitNames)2690     private void addSplits(String sessionId, String[] splitNames) throws IOException {
2691         for (String splitName : splitNames) {
2692             File file = new File(splitName);
2693             assertEquals(
2694                     "Success: streamed " + file.length() + " bytes\n",
2695                     executeShellCommand("pm install-write " + sessionId + " " + file.getName() + " "
2696                             + splitName));
2697         }
2698     }
2699 
addSplitsStdIn(String sessionId, String[] splitNames, String args)2700     private void addSplitsStdIn(String sessionId, String[] splitNames, String args)
2701             throws IOException {
2702         for (String splitName : splitNames) {
2703             File file = new File(splitName);
2704             assertEquals("Success: streamed " + file.length() + " bytes\n", executeShellCommand(
2705                     "pm install-write -S " + file.length() + " " + sessionId + " " + file.getName()
2706                             + " " + args, file));
2707         }
2708     }
2709 
removeSplits(String sessionId, String[] splitNames)2710     private void removeSplits(String sessionId, String[] splitNames) throws IOException {
2711         for (String splitName : splitNames) {
2712             assertEquals("Success\n",
2713                     executeShellCommand("pm install-remove " + sessionId + " " + splitName));
2714         }
2715     }
2716 
removeSplitsBatch(String sessionId, String[] splitNames)2717     private void removeSplitsBatch(String sessionId, String[] splitNames) throws IOException {
2718         assertEquals("Success\n", executeShellCommand(
2719                 "pm install-remove " + sessionId + " " + String.join(" ", splitNames)));
2720     }
2721 
commitSession(String sessionId)2722     private void commitSession(String sessionId) throws IOException {
2723         assertEquals("Success\n", executeShellCommand("pm install-commit " + sessionId));
2724     }
2725 
isAppInstalled(String packageName)2726     static boolean isAppInstalled(String packageName) throws IOException {
2727         final String commandResult = executeShellCommand("pm list packages");
2728         final int prefixLength = "package:".length();
2729         return Arrays.stream(commandResult.split("\\r?\\n")).anyMatch(
2730                 line -> line.length() > prefixLength && line.substring(prefixLength).equals(
2731                         packageName));
2732     }
2733 
isSdkInstalled(String name, int versionMajor)2734     private boolean isSdkInstalled(String name, int versionMajor) throws IOException {
2735         final String sdkString = name + ":" + versionMajor;
2736         final String commandResult = executeShellCommand("pm list sdks");
2737         final int prefixLength = "sdk:".length();
2738         return Arrays.stream(commandResult.split("\\r?\\n"))
2739                 .anyMatch(line -> line.length() > prefixLength && line.substring(
2740                         prefixLength).equals(sdkString));
2741     }
2742 
getPackageCertDigest(String packageName)2743     private String getPackageCertDigest(String packageName) throws Exception {
2744         getUiAutomation().adoptShellPermissionIdentity();
2745         try {
2746             PackageInfo sdkPackageInfo = getPackageManager().getPackageInfo(packageName,
2747                     PackageManager.PackageInfoFlags.of(
2748                             GET_SIGNING_CERTIFICATES | MATCH_STATIC_SHARED_AND_SDK_LIBRARIES));
2749             SigningInfo signingInfo = sdkPackageInfo.signingInfo;
2750             Signature[] signatures =
2751                     signingInfo != null ? signingInfo.getSigningCertificateHistory() : null;
2752             byte[] digest = PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray());
2753             return new String(HexEncoding.encode(digest));
2754         } finally {
2755             getUiAutomation().dropShellPermissionIdentity();
2756         }
2757     }
2758 
2759     /**
2760      * SDK package is signed by build system. In theory we could try to extract the signature,
2761      * and patch the app manifest. This property allows us to override in runtime, which is much
2762      * easier.
2763      */
overrideUsesSdkLibraryCertificateDigest(String sdkCertDigest)2764     private void overrideUsesSdkLibraryCertificateDigest(String sdkCertDigest) throws Exception {
2765         setSystemProperty("debug.pm.uses_sdk_library_default_cert_digest", sdkCertDigest);
2766     }
2767 
getSplits(String packageName)2768     static String getSplits(String packageName) throws IOException {
2769         final String commandResult = executeShellCommand("pm dump " + packageName);
2770         final String prefix = "    splits=[";
2771         final int prefixLength = prefix.length();
2772         Optional<String> maybeSplits = Arrays.stream(commandResult.split("\\r?\\n"))
2773                 .filter(line -> line.startsWith(prefix)).findFirst();
2774         if (!maybeSplits.isPresent()) {
2775             return null;
2776         }
2777         String splits = maybeSplits.get();
2778         return splits.substring(prefixLength, splits.length() - 1);
2779     }
2780 
createApkPath(String baseName)2781     static String createApkPath(String baseName) {
2782         return TEST_APK_PATH + baseName;
2783     }
2784 
2785     /* Install for all the users */
installPackage(String baseName)2786     private void installPackage(String baseName) throws IOException {
2787         File file = new File(createApkPath(baseName));
2788         assertEquals("Success\n", executeShellCommand(
2789                 "pm " + mInstall + " -t -g " + file.getPath()));
2790     }
2791 
installPackage(String baseName, String expectedResultStartsWith)2792     private void installPackage(String baseName, String expectedResultStartsWith)
2793             throws IOException {
2794         File file = new File(createApkPath(baseName));
2795         String result = executeShellCommand("pm " + mInstall + " -t -g " + file.getPath());
2796         assertTrue(result, result.startsWith(expectedResultStartsWith));
2797     }
2798 
updatePackage(String packageName, String baseName)2799     private void updatePackage(String packageName, String baseName) throws IOException {
2800         File file = new File(createApkPath(baseName));
2801         assertEquals("Success\n", executeShellCommand(
2802                 "pm " + mInstall + " -t -p " + packageName + " -g " + file.getPath()));
2803     }
2804 
updatePackageSkipEnable(String packageName, String baseName)2805     private void updatePackageSkipEnable(String packageName, String baseName) throws IOException {
2806         File file = new File(createApkPath(baseName));
2807         assertEquals("Success\n", executeShellCommand(
2808                 "pm " + mInstall + " --skip-enable -t -p " + packageName + " -g " + file.getPath()
2809         ));
2810     }
2811 
installPackageStdIn(String baseName)2812     private void installPackageStdIn(String baseName) throws IOException {
2813         File file = new File(createApkPath(baseName));
2814         assertEquals("Success\n",
2815                 executeShellCommand("pm " + mInstall + " -t -g -S " + file.length(), file));
2816     }
2817 
updatePackageStdIn(String packageName, String baseName)2818     private void updatePackageStdIn(String packageName, String baseName) throws IOException {
2819         File file = new File(createApkPath(baseName));
2820         assertEquals("Success\n", executeShellCommand(
2821                 "pm " + mInstall + " -t -p " + packageName + " -g -S " + file.length(), file));
2822     }
2823 
installSplits(String[] baseNames)2824     private void installSplits(String[] baseNames) throws IOException {
2825         if (mStreaming) {
2826             installSplitsBatch(baseNames);
2827             return;
2828         }
2829         String[] splits = Arrays.stream(baseNames).map(
2830                 baseName -> createApkPath(baseName)).toArray(String[]::new);
2831         String sessionId = createSession(TEST_APP_PACKAGE);
2832         addSplits(sessionId, splits);
2833         commitSession(sessionId);
2834     }
2835 
updateSplits(String[] baseNames)2836     private void updateSplits(String[] baseNames) throws IOException {
2837         if (mStreaming) {
2838             updateSplitsBatch(baseNames);
2839             return;
2840         }
2841         String[] splits = Arrays.stream(baseNames).map(
2842                 baseName -> createApkPath(baseName)).toArray(String[]::new);
2843         String sessionId = createSession("-p " + TEST_APP_PACKAGE);
2844         addSplits(sessionId, splits);
2845         commitSession(sessionId);
2846     }
2847 
installSplitsStdInStreaming(String[] splits)2848     private void installSplitsStdInStreaming(String[] splits) throws IOException {
2849         File[] files = Arrays.stream(splits).map(split -> new File(split)).toArray(File[]::new);
2850         String param = Arrays.stream(files).map(
2851                 file -> file.getName() + ":" + file.length()).collect(Collectors.joining(" "));
2852         assertEquals("Success\n", executeShellCommand("pm" + mInstall + param, files));
2853     }
2854 
installSplitsStdIn(String[] baseNames, String args)2855     private void installSplitsStdIn(String[] baseNames, String args) throws IOException {
2856         String[] splits = Arrays.stream(baseNames).map(
2857                 baseName -> createApkPath(baseName)).toArray(String[]::new);
2858         if (mStreaming) {
2859             installSplitsStdInStreaming(splits);
2860             return;
2861         }
2862         String sessionId = createSession(TEST_APP_PACKAGE);
2863         addSplitsStdIn(sessionId, splits, args);
2864         commitSession(sessionId);
2865     }
2866 
installSplitsBatch(String[] baseNames)2867     private void installSplitsBatch(String[] baseNames) throws IOException {
2868         final String[] splits = Arrays.stream(baseNames).map(
2869                 baseName -> createApkPath(baseName)).toArray(String[]::new);
2870         assertEquals("Success\n",
2871                 executeShellCommand("pm " + mInstall + " -t -g " + String.join(" ", splits)));
2872     }
2873 
updateSplitsBatch(String[] baseNames)2874     private void updateSplitsBatch(String[] baseNames) throws IOException {
2875         final String[] splits = Arrays.stream(baseNames).map(
2876                 baseName -> createApkPath(baseName)).toArray(String[]::new);
2877         assertEquals("Success\n", executeShellCommand(
2878                 "pm " + mInstall + " -p " + TEST_APP_PACKAGE + " -t -g " + String.join(" ",
2879                         splits)));
2880     }
2881 
uninstallPackage(String packageName, String expectedResultStartsWith)2882     private void uninstallPackage(String packageName, String expectedResultStartsWith)
2883             throws IOException {
2884         String result = uninstallPackageSilently(packageName);
2885         assertTrue(result, result.startsWith(expectedResultStartsWith));
2886     }
2887 
uninstallPackageSilently(String packageName)2888     private static String uninstallPackageSilently(String packageName) throws IOException {
2889         return executeShellCommand("pm uninstall " + packageName);
2890     }
2891 
uninstallSplits(String packageName, String[] splitNames)2892     private void uninstallSplits(String packageName, String[] splitNames) throws IOException {
2893         for (String splitName : splitNames) {
2894             assertEquals("Success\n",
2895                     executeShellCommand("pm uninstall " + packageName + " " + splitName));
2896         }
2897     }
2898 
uninstallSplitsBatch(String packageName, String[] splitNames)2899     private void uninstallSplitsBatch(String packageName, String[] splitNames) throws IOException {
2900         assertEquals("Success\n", executeShellCommand(
2901                 "pm uninstall " + packageName + " " + String.join(" ", splitNames)));
2902     }
2903 
setSystemProperty(String name, String value)2904     public static void setSystemProperty(String name, String value) throws Exception {
2905         assertEquals("", executeShellCommand("setprop " + name + " " + value));
2906     }
2907 
getSystemProperty(String prop)2908     public static String getSystemProperty(String prop) throws Exception {
2909         return executeShellCommand("getprop " + prop).replace("\n", "");
2910     }
2911 
disablePackage(String packageName)2912     private void disablePackage(String packageName) {
2913         getUiAutomation().adoptShellPermissionIdentity();
2914         try {
2915             getPackageManager().setApplicationEnabledSetting(packageName,
2916                     PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
2917         } finally {
2918             getUiAutomation().dropShellPermissionIdentity();
2919         }
2920     }
2921 
getOldCodePaths(String packageName)2922     private List<String> getOldCodePaths(String packageName) throws IOException {
2923         final String commandResult = executeShellCommand("dumpsys package " + packageName);
2924         final String prefix = "      oldCodePath=";
2925         return Arrays.stream(commandResult.split("\\r?\\n"))
2926                 .filter(line -> line.startsWith(prefix))
2927                 .map(s -> s.substring(prefix.length()))
2928                 .toList();
2929     }
2930 
getFormattedBytes(long size)2931     private String getFormattedBytes(long size) {
2932         double k = size/1024.0;
2933         double m = size/1048576.0;
2934         double g = size/1073741824.0;
2935 
2936         DecimalFormat dec = new DecimalFormat("0.00");
2937         if (g > 1) {
2938             return dec.format(g).concat(" Gb");
2939         } else if (m > 1) {
2940             return dec.format(m).concat(" Mb");
2941         } else if (k > 1) {
2942             return dec.format(k).concat(" Kb");
2943         }
2944         return "";
2945     }
2946 
2947     /**
2948      * Return the string that displays the data size.
2949      */
getDataSizeDisplay(long size)2950     private String getDataSizeDisplay(long size) {
2951         String formattedOutput = getFormattedBytes(size);
2952         if (!formattedOutput.isEmpty()) {
2953            formattedOutput = " (" + formattedOutput + ")";
2954         }
2955         return Long.toString(size) + " bytes" + formattedOutput;
2956     }
2957 
2958     static class PackageBroadcastReceiver extends BroadcastReceiver {
2959         private final String mTargetPackage;
2960         private final int mTargetUserId;
2961         private CompletableFuture<Intent> mUserReceivedBroadcast = new CompletableFuture();
2962         private final String mAction;
PackageBroadcastReceiver(String packageName, int targetUserId, String action)2963         PackageBroadcastReceiver(String packageName, int targetUserId, String action) {
2964             mTargetPackage = packageName;
2965             mTargetUserId = targetUserId;
2966             mAction = action;
2967             reset();
2968         }
2969         @Override
onReceive(Context context, Intent intent)2970         public void onReceive(Context context, Intent intent) {
2971             final String packageName = intent.getData() == null
2972                     ? null : intent.getData().getEncodedSchemeSpecificPart();
2973             final int userId = context.getUserId();
2974             if (intent.getAction().equals(mAction) && userId == mTargetUserId
2975                     && (packageName == null || packageName.equals(mTargetPackage))) {
2976                 // Only check packageName if it is included in the intent
2977                 mUserReceivedBroadcast.complete(intent);
2978             }
2979         }
assertBroadcastReceived()2980         public void assertBroadcastReceived() throws Exception {
2981             // Make sure broadcast has been sent from PackageManager
2982             executeShellCommand("pm wait-for-handler --timeout 2000");
2983             // Make sure broadcast has been dispatched from the queue
2984             executeShellCommand(String.format(
2985                     "am wait-for-broadcast-dispatch -a %s -d package:%s", mAction, mTargetPackage));
2986             // Checks that broadcast is delivered here
2987             assertNotNull(mUserReceivedBroadcast.get(6000, TimeUnit.MILLISECONDS));
2988         }
assertBroadcastNotReceived()2989         public void assertBroadcastNotReceived() throws Exception {
2990             // Make sure broadcast has been sent from PackageManager
2991             executeShellCommand("pm wait-for-handler --timeout 2000");
2992             executeShellCommand(String.format(
2993                     "am wait-for-broadcast-dispatch -a %s -d package:%s", mAction, mTargetPackage));
2994             expectThrows(TimeoutException.class,
2995                     () -> mUserReceivedBroadcast.get(500, TimeUnit.MILLISECONDS));
2996         }
2997 
getBroadcastResult()2998         public Intent getBroadcastResult() {
2999             return mUserReceivedBroadcast.getNow(null);
3000         }
3001 
reset()3002         public void reset() {
3003             mUserReceivedBroadcast = new CompletableFuture();
3004         }
3005     }
3006 }
3007 
3008