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