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