1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content.pm.cts; 18 19 import static android.content.Context.RECEIVER_EXPORTED; 20 import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256; 21 import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256; 22 import static android.content.pm.PackageInstaller.DATA_LOADER_TYPE_INCREMENTAL; 23 import static android.content.pm.PackageInstaller.DATA_LOADER_TYPE_NONE; 24 import static android.content.pm.PackageInstaller.DATA_LOADER_TYPE_STREAMING; 25 import static android.content.pm.PackageInstaller.EXTRA_DATA_LOADER_TYPE; 26 import static android.content.pm.PackageInstaller.EXTRA_SESSION_ID; 27 import static android.content.pm.PackageInstaller.LOCATION_DATA_APP; 28 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID; 29 import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ROOT_HASH; 30 import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES; 31 import static android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES; 32 import static android.content.pm.PackageManager.MATCH_STATIC_SHARED_AND_SDK_LIBRARIES; 33 import static android.content.pm.PackageManager.VERIFICATION_ALLOW; 34 import static android.content.pm.PackageManager.VERIFICATION_REJECT; 35 36 import static org.junit.Assert.assertEquals; 37 import static org.junit.Assert.assertFalse; 38 import static org.junit.Assert.assertNotEquals; 39 import static org.junit.Assert.assertNotNull; 40 import static org.junit.Assert.assertNull; 41 import static org.junit.Assert.assertThrows; 42 import static org.junit.Assert.assertTrue; 43 import static org.junit.Assume.assumeTrue; 44 45 import android.app.UiAutomation; 46 import android.content.BroadcastReceiver; 47 import android.content.ComponentName; 48 import android.content.Context; 49 import android.content.IIntentReceiver; 50 import android.content.IIntentSender; 51 import android.content.Intent; 52 import android.content.IntentFilter; 53 import android.content.IntentSender; 54 import android.content.pm.ApkChecksum; 55 import android.content.pm.ApplicationInfo; 56 import android.content.pm.DataLoaderParams; 57 import android.content.pm.InstallSourceInfo; 58 import android.content.pm.PackageInfo; 59 import android.content.pm.PackageInstaller; 60 import android.content.pm.PackageInstaller.SessionParams; 61 import android.content.pm.PackageManager; 62 import android.content.pm.SharedLibraryInfo; 63 import android.content.pm.Signature; 64 import android.content.pm.SigningInfo; 65 import android.content.pm.cts.util.AbandonAllPackageSessionsRule; 66 import android.os.Bundle; 67 import android.os.IBinder; 68 import android.os.ParcelFileDescriptor; 69 import android.os.Process; 70 import android.os.RemoteException; 71 import android.os.UserHandle; 72 import android.os.UserManager; 73 import android.platform.test.annotations.AppModeFull; 74 import android.util.PackageUtils; 75 76 import androidx.test.InstrumentationRegistry; 77 import androidx.test.filters.LargeTest; 78 79 import com.android.internal.util.ConcurrentUtils; 80 import com.android.internal.util.HexDump; 81 82 import libcore.util.HexEncoding; 83 84 import org.junit.After; 85 import org.junit.Before; 86 import org.junit.Rule; 87 import org.junit.Test; 88 import org.junit.runner.RunWith; 89 import org.junit.runners.Parameterized; 90 import org.junit.runners.Parameterized.Parameter; 91 import org.junit.runners.Parameterized.Parameters; 92 93 import java.io.ByteArrayOutputStream; 94 import java.io.File; 95 import java.io.FileInputStream; 96 import java.io.FileOutputStream; 97 import java.io.IOException; 98 import java.io.InputStream; 99 import java.io.OutputStream; 100 import java.security.cert.CertificateEncodingException; 101 import java.util.ArrayList; 102 import java.util.Arrays; 103 import java.util.List; 104 import java.util.Optional; 105 import java.util.Random; 106 import java.util.concurrent.CompletableFuture; 107 import java.util.concurrent.TimeUnit; 108 import java.util.concurrent.TimeoutException; 109 import java.util.concurrent.atomic.AtomicInteger; 110 import java.util.concurrent.atomic.AtomicReference; 111 import java.util.function.BiConsumer; 112 import java.util.regex.Matcher; 113 import java.util.regex.Pattern; 114 import java.util.stream.Collectors; 115 116 @RunWith(Parameterized.class) 117 @AppModeFull 118 public class PackageManagerShellCommandTest { 119 static final String TEST_APP_PACKAGE = "com.example.helloworld"; 120 static final String TEST_VERIFIER_PACKAGE = "com.example.helloverifier"; 121 static final String TEST_SUFFICIENT_VERIFIER_PACKAGE = "com.example.hellosufficient"; 122 123 private static final String CTS_PACKAGE_NAME = "android.content.cts"; 124 125 private static final String TEST_APK_PATH = "/data/local/tmp/cts/content/"; 126 static final String TEST_HW5 = "HelloWorld5.apk"; 127 private static final String TEST_HW5_SPLIT0 = "HelloWorld5_hdpi-v4.apk"; 128 private static final String TEST_HW5_SPLIT1 = "HelloWorld5_mdpi-v4.apk"; 129 private static final String TEST_HW5_SPLIT2 = "HelloWorld5_xhdpi-v4.apk"; 130 private static final String TEST_HW5_SPLIT3 = "HelloWorld5_xxhdpi-v4.apk"; 131 private static final String TEST_HW5_SPLIT4 = "HelloWorld5_xxxhdpi-v4.apk"; 132 private static final String TEST_HW7 = "HelloWorld7.apk"; 133 private static final String TEST_HW7_SPLIT0 = "HelloWorld7_hdpi-v4.apk"; 134 private static final String TEST_HW7_SPLIT1 = "HelloWorld7_mdpi-v4.apk"; 135 private static final String TEST_HW7_SPLIT2 = "HelloWorld7_xhdpi-v4.apk"; 136 private static final String TEST_HW7_SPLIT3 = "HelloWorld7_xxhdpi-v4.apk"; 137 private static final String TEST_HW7_SPLIT4 = "HelloWorld7_xxxhdpi-v4.apk"; 138 139 private static final String TEST_SDK1_PACKAGE = "com.test.sdk1_1"; 140 private static final String TEST_SDK1_MAJOR_VERSION2_PACKAGE = "com.test.sdk1_2"; 141 private static final String TEST_SDK2_PACKAGE = "com.test.sdk2_2"; 142 private static final String TEST_SDK3_PACKAGE = "com.test.sdk3_3"; 143 private static final String TEST_SDK_USER_PACKAGE = "com.test.sdk.user"; 144 145 private static final String TEST_SDK1_NAME = "com.test.sdk1"; 146 private static final String TEST_SDK2_NAME = "com.test.sdk2"; 147 private static final String TEST_SDK3_NAME = "com.test.sdk3"; 148 149 private static final String TEST_SDK1 = "HelloWorldSdk1.apk"; 150 private static final String TEST_SDK1_UPDATED = "HelloWorldSdk1Updated.apk"; 151 private static final String TEST_SDK1_MAJOR_VERSION2 = "HelloWorldSdk1MajorVersion2.apk"; 152 private static final String TEST_SDK1_DIFFERENT_SIGNER = "HelloWorldSdk1DifferentSigner.apk"; 153 private static final String TEST_SDK2 = "HelloWorldSdk2.apk"; 154 private static final String TEST_SDK2_UPDATED = "HelloWorldSdk2Updated.apk"; 155 private static final String TEST_USING_SDK1 = "HelloWorldUsingSdk1.apk"; 156 private static final String TEST_USING_SDK1_AND_SDK2 = "HelloWorldUsingSdk1And2.apk"; 157 158 private static final String TEST_SDK3_USING_SDK1 = "HelloWorldSdk3UsingSdk1.apk"; 159 private static final String TEST_SDK3_USING_SDK1_AND_SDK2 = "HelloWorldSdk3UsingSdk1And2.apk"; 160 private static final String TEST_USING_SDK3 = "HelloWorldUsingSdk3.apk"; 161 162 private static final String TEST_HW_NO_APP_STORAGE = "HelloWorldNoAppStorage.apk"; 163 164 private static final String TEST_SUFFICIENT = "HelloWorldWithSufficient.apk"; 165 166 private static final String TEST_SUFFICIENT_VERIFIER_REJECT = 167 "HelloSufficientVerifierReject.apk"; 168 169 private static final String TEST_VERIFIER_ALLOW = "HelloVerifierAllow.apk"; 170 private static final String TEST_VERIFIER_REJECT = "HelloVerifierReject.apk"; 171 private static final String TEST_VERIFIER_DELAYED_REJECT = "HelloVerifierDelayedReject.apk"; 172 private static final String TEST_VERIFIER_DISABLED = "HelloVerifierDisabled.apk"; 173 174 private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; 175 176 private static final String SHELL_PACKAGE_NAME = "com.android.shell"; 177 178 static final long DEFAULT_STREAMING_VERIFICATION_TIMEOUT_MS = 3 * 1000; 179 static final long VERIFICATION_BROADCAST_RECEIVED_TIMEOUT_MS = 10 * 1000; 180 181 @Rule 182 public AbandonAllPackageSessionsRule mAbandonSessionsRule = new AbandonAllPackageSessionsRule(); 183 184 @Parameter 185 public int mDataLoaderType; 186 187 @Parameters initParameters()188 public static Iterable<Object> initParameters() { 189 return Arrays.asList(DATA_LOADER_TYPE_NONE, DATA_LOADER_TYPE_STREAMING, 190 DATA_LOADER_TYPE_INCREMENTAL); 191 } 192 193 private boolean mStreaming = false; 194 private boolean mIncremental = false; 195 private String mInstall = ""; 196 private String mPackageVerifier = null; 197 private String mUnusedStaticSharedLibsMinCachePeriod = null; 198 private long mStreamingVerificationTimeoutMs = DEFAULT_STREAMING_VERIFICATION_TIMEOUT_MS; 199 getPackageInstaller()200 private static PackageInstaller getPackageInstaller() { 201 return getPackageManager().getPackageInstaller(); 202 } 203 getPackageManager()204 private static PackageManager getPackageManager() { 205 return InstrumentationRegistry.getContext().getPackageManager(); 206 } 207 getContext()208 private static Context getContext() { 209 return InstrumentationRegistry.getContext(); 210 } 211 getUiAutomation()212 private static UiAutomation getUiAutomation() { 213 return InstrumentationRegistry.getInstrumentation().getUiAutomation(); 214 } 215 executeShellCommand(String command)216 private static String executeShellCommand(String command) throws IOException { 217 final ParcelFileDescriptor stdout = getUiAutomation().executeShellCommand(command); 218 try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(stdout)) { 219 return readFullStream(inputStream); 220 } 221 } 222 executeShellCommand(String command, File input)223 private static String executeShellCommand(String command, File input) 224 throws IOException { 225 return executeShellCommand(command, new File[]{input}); 226 } 227 executeShellCommand(String command, File[] inputs)228 private static String executeShellCommand(String command, File[] inputs) 229 throws IOException { 230 final ParcelFileDescriptor[] pfds = getUiAutomation().executeShellCommandRw(command); 231 ParcelFileDescriptor stdout = pfds[0]; 232 ParcelFileDescriptor stdin = pfds[1]; 233 try (FileOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream( 234 stdin)) { 235 for (File input : inputs) { 236 try (FileInputStream inputStream = new FileInputStream(input)) { 237 writeFullStream(inputStream, outputStream, input.length()); 238 } 239 } 240 } 241 try (InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(stdout)) { 242 return readFullStream(inputStream); 243 } 244 } 245 readFullStream(InputStream inputStream)246 private static String readFullStream(InputStream inputStream) throws IOException { 247 ByteArrayOutputStream result = new ByteArrayOutputStream(); 248 writeFullStream(inputStream, result, -1); 249 return result.toString("UTF-8"); 250 } 251 writeFullStream(InputStream inputStream, OutputStream outputStream, long expected)252 private static void writeFullStream(InputStream inputStream, OutputStream outputStream, 253 long expected) 254 throws IOException { 255 byte[] buffer = new byte[1024]; 256 long total = 0; 257 int length; 258 while ((length = inputStream.read(buffer)) != -1) { 259 outputStream.write(buffer, 0, length); 260 total += length; 261 } 262 if (expected > 0) { 263 assertEquals(expected, total); 264 } 265 } 266 writeFileToSession(PackageInstaller.Session session, String name, String apk)267 private static void writeFileToSession(PackageInstaller.Session session, String name, 268 String apk) throws IOException { 269 File file = new File(createApkPath(apk)); 270 try (OutputStream os = session.openWrite(name, 0, file.length()); 271 InputStream is = new FileInputStream(file)) { 272 writeFullStream(is, os, file.length()); 273 } 274 } 275 276 @Before onBefore()277 public void onBefore() throws Exception { 278 // Check if Incremental is allowed and revert to non-dataloader installation. 279 if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL && !checkIncrementalDeliveryFeature()) { 280 mDataLoaderType = DATA_LOADER_TYPE_NONE; 281 } 282 283 mStreaming = mDataLoaderType != DATA_LOADER_TYPE_NONE; 284 mIncremental = mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL; 285 mInstall = mDataLoaderType == DATA_LOADER_TYPE_NONE ? " install " : 286 mDataLoaderType == DATA_LOADER_TYPE_STREAMING ? " install-streaming " : 287 " install-incremental "; 288 289 uninstallPackageSilently(TEST_APP_PACKAGE); 290 assertFalse(isAppInstalled(TEST_APP_PACKAGE)); 291 292 uninstallPackageSilently(TEST_VERIFIER_PACKAGE); 293 uninstallPackageSilently(TEST_SUFFICIENT_VERIFIER_PACKAGE); 294 295 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 296 uninstallPackageSilently(TEST_SDK3_PACKAGE); 297 uninstallPackageSilently(TEST_SDK2_PACKAGE); 298 uninstallPackageSilently(TEST_SDK1_PACKAGE); 299 uninstallPackageSilently(TEST_SDK1_MAJOR_VERSION2_PACKAGE); 300 301 mPackageVerifier = executeShellCommand("settings get global verifier_verify_adb_installs"); 302 // Disable the package verifier for non-incremental installations to avoid the dialog 303 // when installing an app. 304 executeShellCommand("settings put global verifier_verify_adb_installs 0"); 305 306 mUnusedStaticSharedLibsMinCachePeriod = executeShellCommand( 307 "settings get global unused_static_shared_lib_min_cache_period"); 308 309 try { 310 mStreamingVerificationTimeoutMs = Long.parseUnsignedLong( 311 executeShellCommand("settings get global streaming_verifier_timeout")); 312 } catch (NumberFormatException ignore) { 313 } 314 } 315 316 @After onAfter()317 public void onAfter() throws Exception { 318 uninstallPackageSilently(TEST_APP_PACKAGE); 319 assertFalse(isAppInstalled(TEST_APP_PACKAGE)); 320 assertEquals(null, getSplits(TEST_APP_PACKAGE)); 321 322 uninstallPackageSilently(TEST_VERIFIER_PACKAGE); 323 uninstallPackageSilently(TEST_SUFFICIENT_VERIFIER_PACKAGE); 324 325 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 326 uninstallPackageSilently(TEST_SDK3_PACKAGE); 327 uninstallPackageSilently(TEST_SDK2_PACKAGE); 328 uninstallPackageSilently(TEST_SDK1_PACKAGE); 329 uninstallPackageSilently(TEST_SDK1_MAJOR_VERSION2_PACKAGE); 330 331 // Reset the global settings to their original values. 332 executeShellCommand("settings put global verifier_verify_adb_installs " + mPackageVerifier); 333 executeShellCommand("settings put global unused_static_shared_lib_min_cache_period " 334 + mUnusedStaticSharedLibsMinCachePeriod); 335 336 // Set the test override to invalid. 337 setSystemProperty("debug.pm.uses_sdk_library_default_cert_digest", "invalid"); 338 setSystemProperty("debug.pm.prune_unused_shared_libraries_delay", "invalid"); 339 setSystemProperty("debug.pm.adb_verifier_override_packages", "invalid"); 340 } 341 checkIncrementalDeliveryFeature()342 private boolean checkIncrementalDeliveryFeature() { 343 final Context context = InstrumentationRegistry.getInstrumentation().getContext(); 344 return context.getPackageManager().hasSystemFeature( 345 PackageManager.FEATURE_INCREMENTAL_DELIVERY); 346 } 347 348 @Test testAppInstall()349 public void testAppInstall() throws Exception { 350 installPackage(TEST_HW5); 351 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 352 } 353 354 @Test testAppInstallErr()355 public void testAppInstallErr() throws Exception { 356 if (!mStreaming) { 357 return; 358 } 359 File file = new File(createApkPath(TEST_HW5)); 360 String command = "pm " + mInstall + " -t -g " + file.getPath() + (new Random()).nextLong(); 361 String commandResult = executeShellCommand(command); 362 assertEquals("Failure [failed to add file(s)]\n", commandResult); 363 assertFalse(isAppInstalled(TEST_APP_PACKAGE)); 364 } 365 366 @Test testAppInstallStdIn()367 public void testAppInstallStdIn() throws Exception { 368 installPackageStdIn(TEST_HW5); 369 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 370 } 371 372 @Test testAppInstallStdInErr()373 public void testAppInstallStdInErr() throws Exception { 374 File file = new File(createApkPath(TEST_HW5)); 375 String commandResult = executeShellCommand("pm " + mInstall + " -t -g -S " + file.length(), 376 new File[]{}); 377 if (mIncremental) { 378 assertTrue(commandResult, commandResult.startsWith("Failure [")); 379 } else { 380 assertTrue(commandResult, 381 commandResult.startsWith("Failure [INSTALL_PARSE_FAILED_NOT_APK")); 382 } 383 assertFalse(isAppInstalled(TEST_APP_PACKAGE)); 384 } 385 386 @Test testAppUpdate()387 public void testAppUpdate() throws Exception { 388 installPackage(TEST_HW5); 389 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 390 updatePackage(TEST_APP_PACKAGE, TEST_HW7); 391 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 392 } 393 394 @Test testAppUpdateSameApk()395 public void testAppUpdateSameApk() throws Exception { 396 installPackage(TEST_HW5); 397 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 398 updatePackage(TEST_APP_PACKAGE, TEST_HW5); 399 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 400 } 401 402 @Test testAppUpdateStdIn()403 public void testAppUpdateStdIn() throws Exception { 404 installPackageStdIn(TEST_HW5); 405 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 406 updatePackageStdIn(TEST_APP_PACKAGE, TEST_HW7); 407 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 408 } 409 410 @Test testAppUpdateStdInSameApk()411 public void testAppUpdateStdInSameApk() throws Exception { 412 installPackageStdIn(TEST_HW5); 413 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 414 updatePackageStdIn(TEST_APP_PACKAGE, TEST_HW5); 415 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 416 } 417 418 @Test testAppUpdateSkipEnable()419 public void testAppUpdateSkipEnable() throws Exception { 420 installPackage(TEST_HW5); 421 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 422 assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 423 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE)); 424 disablePackage(TEST_APP_PACKAGE); 425 assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 426 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE)); 427 updatePackage(TEST_APP_PACKAGE, TEST_HW5); 428 assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 429 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE)); 430 disablePackage(TEST_APP_PACKAGE); 431 assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 432 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE)); 433 updatePackageSkipEnable(TEST_APP_PACKAGE, TEST_HW5); 434 assertEquals(PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 435 getPackageManager().getApplicationEnabledSetting(TEST_APP_PACKAGE)); 436 } 437 438 @Test testSplitsInstall()439 public void testSplitsInstall() throws Exception { 440 installSplits(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 441 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 442 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 443 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 444 getSplits(TEST_APP_PACKAGE)); 445 } 446 447 @Test testSplitsInstallStdIn()448 public void testSplitsInstallStdIn() throws Exception { 449 installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 450 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, ""); 451 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 452 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 453 getSplits(TEST_APP_PACKAGE)); 454 } 455 456 @Test testSplitsInstallDash()457 public void testSplitsInstallDash() throws Exception { 458 installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 459 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, "-"); 460 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 461 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 462 getSplits(TEST_APP_PACKAGE)); 463 } 464 465 @Test testSplitsBatchInstall()466 public void testSplitsBatchInstall() throws Exception { 467 installSplitsBatch(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 468 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 469 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 470 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 471 getSplits(TEST_APP_PACKAGE)); 472 } 473 474 @Test testSplitsUpdate()475 public void testSplitsUpdate() throws Exception { 476 installSplits(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 477 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 478 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 479 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 480 getSplits(TEST_APP_PACKAGE)); 481 updateSplits(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2, 482 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}); 483 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 484 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 485 getSplits(TEST_APP_PACKAGE)); 486 } 487 488 489 @Test testSplitsAdd()490 public void testSplitsAdd() throws Exception { 491 installSplits(new String[]{TEST_HW5}); 492 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 493 assertEquals("base", getSplits(TEST_APP_PACKAGE)); 494 495 updateSplits(new String[]{TEST_HW5_SPLIT0}); 496 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 497 assertEquals("base, config.hdpi", getSplits(TEST_APP_PACKAGE)); 498 499 updateSplits(new String[]{TEST_HW5_SPLIT1}); 500 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 501 assertEquals("base, config.hdpi, config.mdpi", getSplits(TEST_APP_PACKAGE)); 502 503 updateSplits(new String[]{TEST_HW5_SPLIT2}); 504 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 505 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi", 506 getSplits(TEST_APP_PACKAGE)); 507 508 updateSplits(new String[]{TEST_HW5_SPLIT3}); 509 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 510 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi", 511 getSplits(TEST_APP_PACKAGE)); 512 513 updateSplits(new String[]{TEST_HW5_SPLIT4}); 514 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 515 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 516 getSplits(TEST_APP_PACKAGE)); 517 } 518 519 @Test testSplitsUpdateStdIn()520 public void testSplitsUpdateStdIn() throws Exception { 521 installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 522 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, ""); 523 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 524 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 525 getSplits(TEST_APP_PACKAGE)); 526 installSplitsStdIn(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2, 527 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}, ""); 528 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 529 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 530 getSplits(TEST_APP_PACKAGE)); 531 } 532 533 @Test testSplitsUpdateDash()534 public void testSplitsUpdateDash() throws Exception { 535 installSplitsStdIn(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 536 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}, "-"); 537 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 538 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 539 getSplits(TEST_APP_PACKAGE)); 540 installSplitsStdIn(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2, 541 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}, "-"); 542 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 543 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 544 getSplits(TEST_APP_PACKAGE)); 545 } 546 547 @Test testSplitsBatchUpdate()548 public void testSplitsBatchUpdate() throws Exception { 549 installSplitsBatch(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 550 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 551 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 552 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 553 getSplits(TEST_APP_PACKAGE)); 554 updateSplitsBatch( 555 new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2, 556 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}); 557 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 558 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 559 getSplits(TEST_APP_PACKAGE)); 560 } 561 562 @Test testSplitsBatchAdd()563 public void testSplitsBatchAdd() throws Exception { 564 installSplitsBatch(new String[]{TEST_HW5}); 565 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 566 assertEquals("base", getSplits(TEST_APP_PACKAGE)); 567 568 updateSplitsBatch(new String[]{TEST_HW5_SPLIT0, TEST_HW5_SPLIT1}); 569 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 570 assertEquals("base, config.hdpi, config.mdpi", getSplits(TEST_APP_PACKAGE)); 571 572 updateSplitsBatch(new String[]{TEST_HW5_SPLIT2, TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 573 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 574 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 575 getSplits(TEST_APP_PACKAGE)); 576 } 577 578 @Test testSplitsUninstall()579 public void testSplitsUninstall() throws Exception { 580 installSplits(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 581 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 582 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 583 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 584 getSplits(TEST_APP_PACKAGE)); 585 uninstallSplits(TEST_APP_PACKAGE, new String[]{"config.hdpi"}); 586 assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 587 getSplits(TEST_APP_PACKAGE)); 588 uninstallSplits(TEST_APP_PACKAGE, new String[]{"config.xxxhdpi", "config.xhdpi"}); 589 assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE)); 590 } 591 592 @Test testSplitsBatchUninstall()593 public void testSplitsBatchUninstall() throws Exception { 594 installSplitsBatch(new String[]{TEST_HW5, TEST_HW5_SPLIT0, TEST_HW5_SPLIT1, TEST_HW5_SPLIT2, 595 TEST_HW5_SPLIT3, TEST_HW5_SPLIT4}); 596 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 597 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 598 getSplits(TEST_APP_PACKAGE)); 599 uninstallSplitsBatch(TEST_APP_PACKAGE, new String[]{"config.hdpi"}); 600 assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 601 getSplits(TEST_APP_PACKAGE)); 602 uninstallSplitsBatch(TEST_APP_PACKAGE, new String[]{"config.xxxhdpi", "config.xhdpi"}); 603 assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE)); 604 } 605 606 @Test testSplitsRemove()607 public void testSplitsRemove() throws Exception { 608 installSplits(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2, 609 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}); 610 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 611 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 612 getSplits(TEST_APP_PACKAGE)); 613 614 String sessionId = createUpdateSession(TEST_APP_PACKAGE); 615 removeSplits(sessionId, new String[]{"config.hdpi"}); 616 commitSession(sessionId); 617 assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 618 getSplits(TEST_APP_PACKAGE)); 619 620 sessionId = createUpdateSession(TEST_APP_PACKAGE); 621 removeSplits(sessionId, new String[]{"config.xxxhdpi", "config.xhdpi"}); 622 commitSession(sessionId); 623 assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE)); 624 } 625 626 @Test testSplitsBatchRemove()627 public void testSplitsBatchRemove() throws Exception { 628 installSplitsBatch(new String[]{TEST_HW7, TEST_HW7_SPLIT0, TEST_HW7_SPLIT1, TEST_HW7_SPLIT2, 629 TEST_HW7_SPLIT3, TEST_HW7_SPLIT4}); 630 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 631 assertEquals("base, config.hdpi, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 632 getSplits(TEST_APP_PACKAGE)); 633 634 String sessionId = createUpdateSession(TEST_APP_PACKAGE); 635 removeSplitsBatch(sessionId, new String[]{"config.hdpi"}); 636 commitSession(sessionId); 637 assertEquals("base, config.mdpi, config.xhdpi, config.xxhdpi, config.xxxhdpi", 638 getSplits(TEST_APP_PACKAGE)); 639 640 sessionId = createUpdateSession(TEST_APP_PACKAGE); 641 removeSplitsBatch(sessionId, new String[]{"config.xxxhdpi", "config.xhdpi"}); 642 commitSession(sessionId); 643 assertEquals("base, config.mdpi, config.xxhdpi", getSplits(TEST_APP_PACKAGE)); 644 } 645 646 @Test testAppInstallErrDuplicate()647 public void testAppInstallErrDuplicate() throws Exception { 648 if (!mStreaming) { 649 return; 650 } 651 String split = createApkPath(TEST_HW5); 652 String commandResult = executeShellCommand( 653 "pm " + mInstall + " -t -g " + split + " " + split); 654 assertEquals("Failure [failed to add file(s)]\n", commandResult); 655 assertFalse(isAppInstalled(TEST_APP_PACKAGE)); 656 } 657 658 @Test testDontKillWithSplit()659 public void testDontKillWithSplit() throws Exception { 660 installPackage(TEST_HW5); 661 662 getUiAutomation().adoptShellPermissionIdentity(); 663 try { 664 final PackageInstaller installer = getPackageInstaller(); 665 final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); 666 params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 667 params.setAppPackageName(TEST_APP_PACKAGE); 668 params.setDontKillApp(true); 669 670 final int sessionId = installer.createSession(params); 671 PackageInstaller.Session session = installer.openSession(sessionId); 672 assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0); 673 674 writeFileToSession(session, "hw5_split0", TEST_HW5_SPLIT0); 675 676 final CompletableFuture<Boolean> result = new CompletableFuture<>(); 677 final CompletableFuture<Integer> status = new CompletableFuture<>(); 678 final CompletableFuture<String> statusMessage = new CompletableFuture<>(); 679 session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() { 680 @Override 681 public void send(int code, Intent intent, String resolvedType, 682 IBinder whitelistToken, IIntentReceiver finishedReceiver, 683 String requiredPermission, Bundle options) throws RemoteException { 684 boolean dontKillApp = 685 (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0; 686 status.complete( 687 intent.getIntExtra(PackageInstaller.EXTRA_STATUS, Integer.MIN_VALUE)); 688 statusMessage.complete( 689 intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)); 690 result.complete(dontKillApp); 691 } 692 })); 693 694 // We are adding split. OK to have the flag. 695 assertTrue(result.get()); 696 // Verify that the return status is set 697 assertEquals(statusMessage.get(), PackageInstaller.STATUS_SUCCESS, (int) status.get()); 698 } finally { 699 getUiAutomation().dropShellPermissionIdentity(); 700 } 701 } 702 703 @Test testDontKillRemovedWithBaseApkFullInstall()704 public void testDontKillRemovedWithBaseApkFullInstall() throws Exception { 705 installPackage(TEST_HW5); 706 707 getUiAutomation().adoptShellPermissionIdentity(); 708 try { 709 final PackageInstaller installer = getPackageInstaller(); 710 final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL); 711 params.setAppPackageName(TEST_APP_PACKAGE); 712 params.setDontKillApp(true); 713 714 final int sessionId = installer.createSession(params); 715 PackageInstaller.Session session = installer.openSession(sessionId); 716 assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0); 717 718 writeFileToSession(session, "hw7", TEST_HW7); 719 720 final CompletableFuture<Boolean> result = new CompletableFuture<>(); 721 session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() { 722 @Override 723 public void send(int code, Intent intent, String resolvedType, 724 IBinder whitelistToken, IIntentReceiver finishedReceiver, 725 String requiredPermission, Bundle options) throws RemoteException { 726 boolean dontKillApp = 727 (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0; 728 result.complete(dontKillApp); 729 } 730 })); 731 732 // We are updating base.apk. Flag to be removed. 733 assertFalse(result.get()); 734 } finally { 735 getUiAutomation().dropShellPermissionIdentity(); 736 } 737 } 738 739 @Test testDontKillRemovedWithBaseApk()740 public void testDontKillRemovedWithBaseApk() throws Exception { 741 installPackage(TEST_HW5); 742 743 getUiAutomation().adoptShellPermissionIdentity(); 744 try { 745 final PackageInstaller installer = getPackageInstaller(); 746 final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); 747 params.setAppPackageName(TEST_APP_PACKAGE); 748 params.setDontKillApp(true); 749 750 final int sessionId = installer.createSession(params); 751 PackageInstaller.Session session = installer.openSession(sessionId); 752 assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0); 753 754 writeFileToSession(session, "hw7", TEST_HW7); 755 756 final CompletableFuture<Boolean> result = new CompletableFuture<>(); 757 session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() { 758 @Override 759 public void send(int code, Intent intent, String resolvedType, 760 IBinder whitelistToken, IIntentReceiver finishedReceiver, 761 String requiredPermission, Bundle options) throws RemoteException { 762 boolean dontKillApp = 763 (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0; 764 result.complete(dontKillApp); 765 } 766 })); 767 768 // We are updating base.apk. Flag to be removed. 769 assertFalse(result.get()); 770 } finally { 771 getUiAutomation().dropShellPermissionIdentity(); 772 } 773 } 774 775 @Test testDataLoaderParamsApiV1()776 public void testDataLoaderParamsApiV1() throws Exception { 777 if (!mStreaming) { 778 return; 779 } 780 781 getUiAutomation().adoptShellPermissionIdentity(); 782 try { 783 final PackageInstaller installer = getPackageInstaller(); 784 785 final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL); 786 787 final int sessionId = installer.createSession(params); 788 PackageInstaller.Session session = installer.openSession(sessionId); 789 790 assertEquals(null, session.getDataLoaderParams()); 791 792 installer.abandonSession(sessionId); 793 } finally { 794 getUiAutomation().dropShellPermissionIdentity(); 795 } 796 } 797 798 @Test testDataLoaderParamsApiV2()799 public void testDataLoaderParamsApiV2() throws Exception { 800 if (!mStreaming) { 801 return; 802 } 803 804 getUiAutomation().adoptShellPermissionIdentity(); 805 try { 806 final PackageInstaller installer = getPackageInstaller(); 807 808 final SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL); 809 final ComponentName componentName = new ComponentName("foo", "bar"); 810 final String args = "args"; 811 params.setDataLoaderParams( 812 mIncremental ? DataLoaderParams.forIncremental(componentName, args) 813 : DataLoaderParams.forStreaming(componentName, args)); 814 815 final int sessionId = installer.createSession(params); 816 PackageInstaller.Session session = installer.openSession(sessionId); 817 818 DataLoaderParams dataLoaderParams = session.getDataLoaderParams(); 819 assertEquals(mIncremental ? DATA_LOADER_TYPE_INCREMENTAL : DATA_LOADER_TYPE_STREAMING, 820 dataLoaderParams.getType()); 821 assertEquals("foo", dataLoaderParams.getComponentName().getPackageName()); 822 assertEquals("bar", dataLoaderParams.getComponentName().getClassName()); 823 assertEquals("args", dataLoaderParams.getArguments()); 824 825 installer.abandonSession(sessionId); 826 } finally { 827 getUiAutomation().dropShellPermissionIdentity(); 828 } 829 } 830 831 @Test testRemoveFileApiV2()832 public void testRemoveFileApiV2() throws Exception { 833 if (!mStreaming) { 834 return; 835 } 836 837 getUiAutomation().adoptShellPermissionIdentity(); 838 try { 839 final PackageInstaller installer = getPackageInstaller(); 840 841 final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING); 842 params.setAppPackageName("com.package.name"); 843 final ComponentName componentName = new ComponentName("foo", "bar"); 844 final String args = "args"; 845 params.setDataLoaderParams( 846 mIncremental ? DataLoaderParams.forIncremental(componentName, args) 847 : DataLoaderParams.forStreaming(componentName, args)); 848 849 final int sessionId = installer.createSession(params); 850 PackageInstaller.Session session = installer.openSession(sessionId); 851 852 session.addFile(LOCATION_DATA_APP, "base.apk", 123, "123".getBytes(), null); 853 String[] files = session.getNames(); 854 assertEquals(1, files.length); 855 assertEquals("base.apk", files[0]); 856 857 session.removeFile(LOCATION_DATA_APP, "base.apk"); 858 files = session.getNames(); 859 assertEquals(2, files.length); 860 assertEquals("base.apk", files[0]); 861 assertEquals("base.apk.removed", files[1]); 862 863 installer.abandonSession(sessionId); 864 } finally { 865 getUiAutomation().dropShellPermissionIdentity(); 866 } 867 } 868 869 @Test testSdkInstallAndUpdate()870 public void testSdkInstallAndUpdate() throws Exception { 871 installPackage(TEST_SDK1); 872 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 873 874 // Same APK. 875 installPackage(TEST_SDK1); 876 877 // Updated APK. 878 installPackage(TEST_SDK1_UPDATED); 879 880 // Reverted APK. 881 installPackage(TEST_SDK1); 882 883 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 884 } 885 886 @Test testSdkInstallMultipleMajorVersions()887 public void testSdkInstallMultipleMajorVersions() throws Exception { 888 // Major version 1. 889 installPackage(TEST_SDK1); 890 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 891 892 // Major version 2. 893 installPackage(TEST_SDK1_MAJOR_VERSION2); 894 895 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 896 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 2)); 897 } 898 899 @Test testSdkInstallMultipleMinorVersionsWrongSignature()900 public void testSdkInstallMultipleMinorVersionsWrongSignature() throws Exception { 901 // Major version 1. 902 installPackage(TEST_SDK1); 903 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 904 905 // Major version 1, different signer. 906 installPackage(TEST_SDK1_DIFFERENT_SIGNER, 907 "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package com.test.sdk1_1 " 908 + "signatures do not match newer version"); 909 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 910 } 911 912 @Test testSdkInstallMultipleMajorVersionsWrongSignature()913 public void testSdkInstallMultipleMajorVersionsWrongSignature() throws Exception { 914 // Major version 1. 915 installPackage(TEST_SDK1_DIFFERENT_SIGNER); 916 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 917 918 // Major version 2. 919 installPackage(TEST_SDK1_MAJOR_VERSION2, 920 "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package com.test.sdk1_1 " 921 + "signatures do not match newer version"); 922 923 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 924 } 925 926 @Test testSdkInstallAndUpdateTwoMajorVersions()927 public void testSdkInstallAndUpdateTwoMajorVersions() throws Exception { 928 installPackage(TEST_SDK1); 929 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 930 931 installPackage(TEST_SDK2); 932 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 933 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 934 935 // Same APK. 936 installPackage(TEST_SDK1); 937 installPackage(TEST_SDK2); 938 939 // Updated APK. 940 installPackage(TEST_SDK1_UPDATED); 941 installPackage(TEST_SDK2_UPDATED); 942 943 // Reverted APK. 944 installPackage(TEST_SDK1); 945 installPackage(TEST_SDK2); 946 947 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 948 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 949 } 950 951 @Test testAppUsingSdkInstallAndUpdate()952 public void testAppUsingSdkInstallAndUpdate() throws Exception { 953 // Try to install without required SDK1. 954 installPackage(TEST_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 955 assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE)); 956 957 // Now install the required SDK1. 958 installPackage(TEST_SDK1); 959 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 960 961 overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE)); 962 963 // Install and uninstall. 964 installPackage(TEST_USING_SDK1); 965 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 966 967 // Update SDK1. 968 installPackage(TEST_SDK1_UPDATED); 969 970 // Install again. 971 installPackage(TEST_USING_SDK1); 972 973 // Check resolution API. 974 getUiAutomation().adoptShellPermissionIdentity(); 975 try { 976 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE, 977 PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES)); 978 assertEquals(1, appInfo.sharedLibraryInfos.size()); 979 SharedLibraryInfo libInfo = appInfo.sharedLibraryInfos.get(0); 980 assertEquals("com.test.sdk1", libInfo.getName()); 981 assertEquals(1, libInfo.getLongVersion()); 982 } finally { 983 getUiAutomation().dropShellPermissionIdentity(); 984 } 985 986 // Try to install without required SDK2. 987 installPackage(TEST_USING_SDK1_AND_SDK2, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 988 989 // Now install the required SDK2. 990 installPackage(TEST_SDK2); 991 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 992 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 993 994 // Install and uninstall. 995 installPackage(TEST_USING_SDK1_AND_SDK2); 996 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 997 998 // Update both SDKs. 999 installPackage(TEST_SDK1_UPDATED); 1000 installPackage(TEST_SDK2_UPDATED); 1001 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1002 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 1003 1004 // Install again. 1005 installPackage(TEST_USING_SDK1_AND_SDK2); 1006 1007 // Check resolution API. 1008 getUiAutomation().adoptShellPermissionIdentity(); 1009 try { 1010 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE, 1011 PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES)); 1012 assertEquals(2, appInfo.sharedLibraryInfos.size()); 1013 assertEquals("com.test.sdk1", appInfo.sharedLibraryInfos.get(0).getName()); 1014 assertEquals(1, appInfo.sharedLibraryInfos.get(0).getLongVersion()); 1015 assertEquals("com.test.sdk2", appInfo.sharedLibraryInfos.get(1).getName()); 1016 assertEquals(2, appInfo.sharedLibraryInfos.get(1).getLongVersion()); 1017 } finally { 1018 getUiAutomation().dropShellPermissionIdentity(); 1019 } 1020 } 1021 1022 @Test testAppUsingSdkInstallGroupInstall()1023 public void testAppUsingSdkInstallGroupInstall() throws Exception { 1024 // Install/uninstall the sdk to grab its certDigest. 1025 installPackage(TEST_SDK1); 1026 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1027 String sdkCertDigest = getPackageCertDigest(TEST_SDK1_PACKAGE); 1028 uninstallPackageSilently(TEST_SDK1_PACKAGE); 1029 1030 // Try to install without required SDK1. 1031 installPackage(TEST_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1032 assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE)); 1033 1034 // Parent session 1035 String parentSessionId = createSession("--multi-package"); 1036 1037 // Required SDK1. 1038 String sdkSessionId = createSession(""); 1039 addSplits(sdkSessionId, new String[] { createApkPath(TEST_SDK1) }); 1040 1041 // The app. 1042 String appSessionId = createSession(""); 1043 addSplits(appSessionId, new String[] { createApkPath(TEST_USING_SDK1) }); 1044 1045 overrideUsesSdkLibraryCertificateDigest(sdkCertDigest); 1046 1047 // Add both child sessions to the primary session and commit. 1048 assertEquals("Success\n", executeShellCommand( 1049 "pm install-add-session " + parentSessionId + " " + sdkSessionId + " " 1050 + appSessionId)); 1051 commitSession(parentSessionId); 1052 1053 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1054 assertTrue(isAppInstalled(TEST_SDK_USER_PACKAGE)); 1055 1056 // Check resolution API. 1057 getUiAutomation().adoptShellPermissionIdentity(); 1058 try { 1059 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE, 1060 PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES)); 1061 assertEquals(1, appInfo.sharedLibraryInfos.size()); 1062 SharedLibraryInfo libInfo = appInfo.sharedLibraryInfos.get(0); 1063 assertEquals("com.test.sdk1", libInfo.getName()); 1064 assertEquals(1, libInfo.getLongVersion()); 1065 } finally { 1066 getUiAutomation().dropShellPermissionIdentity(); 1067 } 1068 } 1069 1070 @Test testInstallFailsMismatchingCertificate()1071 public void testInstallFailsMismatchingCertificate() throws Exception { 1072 // Install the required SDK1. 1073 installPackage(TEST_SDK1); 1074 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1075 1076 // Try to install the package with empty digest. 1077 installPackage(TEST_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1078 } 1079 1080 @Test testUninstallSdkWhileAppUsing()1081 public void testUninstallSdkWhileAppUsing() throws Exception { 1082 // Install the required SDK1. 1083 installPackage(TEST_SDK1); 1084 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1085 1086 overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE)); 1087 1088 // Install the package. 1089 installPackage(TEST_USING_SDK1); 1090 1091 uninstallPackage(TEST_SDK1_PACKAGE, "Failure [DELETE_FAILED_USED_SHARED_LIBRARY]"); 1092 } 1093 1094 @Test testGetSharedLibraries()1095 public void testGetSharedLibraries() throws Exception { 1096 // Install the SDK1. 1097 installPackage(TEST_SDK1); 1098 { 1099 List<SharedLibraryInfo> libs = getSharedLibraries(); 1100 SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1); 1101 assertNotNull(sdk1); 1102 SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2); 1103 assertNull(sdk2); 1104 } 1105 1106 // Install the SDK2. 1107 installPackage(TEST_SDK2); 1108 { 1109 List<SharedLibraryInfo> libs = getSharedLibraries(); 1110 SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1); 1111 assertNotNull(sdk1); 1112 SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2); 1113 assertNotNull(sdk2); 1114 } 1115 1116 // Install and uninstall the user package. 1117 { 1118 overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE)); 1119 1120 installPackage(TEST_USING_SDK1_AND_SDK2); 1121 1122 List<SharedLibraryInfo> libs = getSharedLibraries(); 1123 SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1); 1124 assertNotNull(sdk1); 1125 SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2); 1126 assertNotNull(sdk2); 1127 1128 assertEquals(TEST_SDK_USER_PACKAGE, 1129 sdk1.getDependentPackages().get(0).getPackageName()); 1130 assertEquals(TEST_SDK_USER_PACKAGE, 1131 sdk2.getDependentPackages().get(0).getPackageName()); 1132 1133 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 1134 } 1135 1136 // Uninstall the SDK1. 1137 uninstallPackageSilently(TEST_SDK1_PACKAGE); 1138 { 1139 List<SharedLibraryInfo> libs = getSharedLibraries(); 1140 SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1); 1141 assertNull(sdk1); 1142 SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2); 1143 assertNotNull(sdk2); 1144 } 1145 1146 // Uninstall the SDK2. 1147 uninstallPackageSilently(TEST_SDK2_PACKAGE); 1148 { 1149 List<SharedLibraryInfo> libs = getSharedLibraries(); 1150 SharedLibraryInfo sdk1 = findLibrary(libs, "com.test.sdk1", 1); 1151 assertNull(sdk1); 1152 SharedLibraryInfo sdk2 = findLibrary(libs, "com.test.sdk2", 2); 1153 assertNull(sdk2); 1154 } 1155 } 1156 1157 @Test testUninstallUnusedSdks()1158 public void testUninstallUnusedSdks() throws Exception { 1159 installPackage(TEST_SDK1); 1160 installPackage(TEST_SDK2); 1161 1162 overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE)); 1163 installPackage(TEST_USING_SDK1_AND_SDK2); 1164 1165 setSystemProperty("debug.pm.prune_unused_shared_libraries_delay", "0"); 1166 executeShellCommand("settings put global unused_static_shared_lib_min_cache_period 0"); 1167 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 1168 1169 // Wait for 3secs max. 1170 for (int i = 0; i < 30; ++i) { 1171 if (!isSdkInstalled(TEST_SDK1_NAME, 1) && !isSdkInstalled(TEST_SDK2_NAME, 2)) { 1172 break; 1173 } 1174 final int beforeRetryDelayMs = 100; 1175 Thread.currentThread().sleep(beforeRetryDelayMs); 1176 } 1177 assertFalse(isSdkInstalled(TEST_SDK1_NAME, 1)); 1178 assertFalse(isSdkInstalled(TEST_SDK2_NAME, 2)); 1179 } 1180 1181 @Test testAppUsingSdkUsingSdkInstallAndUpdate()1182 public void testAppUsingSdkUsingSdkInstallAndUpdate() throws Exception { 1183 // Try to install without required SDK1. 1184 installPackage(TEST_USING_SDK3, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1185 assertFalse(isAppInstalled(TEST_SDK_USER_PACKAGE)); 1186 1187 // Try to install SDK3 without required SDK1. 1188 installPackage(TEST_SDK3_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1189 assertFalse(isSdkInstalled(TEST_SDK3_NAME, 3)); 1190 1191 // Now install the required SDK1. 1192 installPackage(TEST_SDK1); 1193 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1194 1195 overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE)); 1196 1197 // Now install the required SDK3. 1198 installPackage(TEST_SDK3_USING_SDK1); 1199 assertTrue(isSdkInstalled(TEST_SDK3_NAME, 3)); 1200 1201 // Install and uninstall. 1202 installPackage(TEST_USING_SDK3); 1203 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 1204 1205 // Update SDK1. 1206 installPackage(TEST_SDK1_UPDATED); 1207 1208 // Install again. 1209 installPackage(TEST_USING_SDK3); 1210 1211 // Check resolution API. 1212 getUiAutomation().adoptShellPermissionIdentity(); 1213 try { 1214 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE, 1215 PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES)); 1216 assertEquals(1, appInfo.sharedLibraryInfos.size()); 1217 SharedLibraryInfo libInfo = appInfo.sharedLibraryInfos.get(0); 1218 assertEquals("com.test.sdk3", libInfo.getName()); 1219 assertEquals(3, libInfo.getLongVersion()); 1220 } finally { 1221 getUiAutomation().dropShellPermissionIdentity(); 1222 } 1223 1224 // Try to install updated SDK3 without required SDK2. 1225 installPackage(TEST_SDK3_USING_SDK1_AND_SDK2, 1226 "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1227 1228 // Now install the required SDK2. 1229 installPackage(TEST_SDK2); 1230 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1231 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 1232 1233 installPackage(TEST_SDK3_USING_SDK1_AND_SDK2); 1234 assertTrue(isSdkInstalled(TEST_SDK3_NAME, 3)); 1235 1236 // Install and uninstall. 1237 installPackage(TEST_USING_SDK3); 1238 uninstallPackageSilently(TEST_SDK_USER_PACKAGE); 1239 1240 // Update both SDKs. 1241 installPackage(TEST_SDK1_UPDATED); 1242 installPackage(TEST_SDK2_UPDATED); 1243 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1244 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 1245 1246 // Install again. 1247 installPackage(TEST_USING_SDK3); 1248 1249 // Check resolution API. 1250 getUiAutomation().adoptShellPermissionIdentity(); 1251 try { 1252 ApplicationInfo appInfo = getPackageManager().getApplicationInfo(TEST_SDK_USER_PACKAGE, 1253 PackageManager.ApplicationInfoFlags.of(GET_SHARED_LIBRARY_FILES)); 1254 assertEquals(1, appInfo.sharedLibraryInfos.size()); 1255 assertEquals("com.test.sdk3", appInfo.sharedLibraryInfos.get(0).getName()); 1256 assertEquals(3, appInfo.sharedLibraryInfos.get(0).getLongVersion()); 1257 } finally { 1258 getUiAutomation().dropShellPermissionIdentity(); 1259 } 1260 } 1261 1262 @Test testSdkUsingSdkInstallAndUpdate()1263 public void testSdkUsingSdkInstallAndUpdate() throws Exception { 1264 // Try to install without required SDK1. 1265 installPackage(TEST_SDK3_USING_SDK1, "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1266 assertFalse(isSdkInstalled(TEST_SDK3_NAME, 3)); 1267 1268 // Now install the required SDK1. 1269 installPackage(TEST_SDK1); 1270 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1271 1272 overrideUsesSdkLibraryCertificateDigest(getPackageCertDigest(TEST_SDK1_PACKAGE)); 1273 1274 // Install and uninstall. 1275 installPackage(TEST_SDK3_USING_SDK1); 1276 uninstallPackageSilently(TEST_SDK3_PACKAGE); 1277 1278 // Update SDK1. 1279 installPackage(TEST_SDK1_UPDATED); 1280 1281 // Install again. 1282 installPackage(TEST_SDK3_USING_SDK1); 1283 1284 // Check resolution API. 1285 { 1286 List<SharedLibraryInfo> libs = getSharedLibraries(); 1287 SharedLibraryInfo sdk3 = findLibrary(libs, "com.test.sdk3", 3); 1288 assertNotNull(sdk3); 1289 List<SharedLibraryInfo> deps = sdk3.getDependencies(); 1290 assertEquals(1, deps.size()); 1291 SharedLibraryInfo libInfo = deps.get(0); 1292 assertEquals("com.test.sdk1", libInfo.getName()); 1293 assertEquals(1, libInfo.getLongVersion()); 1294 } 1295 1296 // Try to install without required SDK2. 1297 installPackage(TEST_SDK3_USING_SDK1_AND_SDK2, 1298 "Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY"); 1299 1300 // Now install the required SDK2. 1301 installPackage(TEST_SDK2); 1302 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1303 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 1304 1305 // Install and uninstall. 1306 installPackage(TEST_SDK3_USING_SDK1_AND_SDK2); 1307 uninstallPackageSilently(TEST_SDK3_PACKAGE); 1308 1309 // Update both SDKs. 1310 installPackage(TEST_SDK1_UPDATED); 1311 installPackage(TEST_SDK2_UPDATED); 1312 assertTrue(isSdkInstalled(TEST_SDK1_NAME, 1)); 1313 assertTrue(isSdkInstalled(TEST_SDK2_NAME, 2)); 1314 1315 // Install again. 1316 installPackage(TEST_SDK3_USING_SDK1_AND_SDK2); 1317 1318 // Check resolution API. 1319 { 1320 List<SharedLibraryInfo> libs = getSharedLibraries(); 1321 SharedLibraryInfo sdk3 = findLibrary(libs, "com.test.sdk3", 3); 1322 assertNotNull(sdk3); 1323 List<SharedLibraryInfo> deps = sdk3.getDependencies(); 1324 assertEquals(2, deps.size()); 1325 assertEquals("com.test.sdk1", deps.get(0).getName()); 1326 assertEquals(1, deps.get(0).getLongVersion()); 1327 assertEquals("com.test.sdk2", deps.get(1).getName()); 1328 assertEquals(2, deps.get(1).getLongVersion()); 1329 } 1330 } 1331 runPackageVerifierTest(BiConsumer<Context, Intent> onBroadcast)1332 private void runPackageVerifierTest(BiConsumer<Context, Intent> onBroadcast) 1333 throws Exception { 1334 runPackageVerifierTest(TEST_HW5, TEST_HW7, "Success", onBroadcast); 1335 } 1336 runPackageVerifierTest(String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)1337 private void runPackageVerifierTest(String expectedResultStartsWith, 1338 BiConsumer<Context, Intent> onBroadcast) throws Exception { 1339 runPackageVerifierTest(TEST_HW5, TEST_HW7, expectedResultStartsWith, onBroadcast); 1340 } 1341 runPackageVerifierTest(String baseName, String updatedName, String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)1342 private void runPackageVerifierTest(String baseName, String updatedName, 1343 String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast) 1344 throws Exception { 1345 AtomicReference<Thread> onBroadcastThread = new AtomicReference<>(); 1346 1347 runPackageVerifierTestSync(baseName, updatedName, expectedResultStartsWith, 1348 (context, intent) -> { 1349 Thread thread = new Thread(() -> onBroadcast.accept(context, intent)); 1350 thread.start(); 1351 onBroadcastThread.set(thread); 1352 }); 1353 1354 final Thread thread = onBroadcastThread.get(); 1355 if (thread != null) { 1356 thread.join(); 1357 } 1358 } 1359 runPackageVerifierTestSync(String baseName, String updatedName, String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast)1360 private void runPackageVerifierTestSync(String baseName, String updatedName, 1361 String expectedResultStartsWith, BiConsumer<Context, Intent> onBroadcast) 1362 throws Exception { 1363 // Install a package. 1364 installPackage(baseName); 1365 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1366 1367 getUiAutomation().adoptShellPermissionIdentity( 1368 android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, 1369 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL); 1370 1371 final CompletableFuture<Boolean> broadcastReceived = new CompletableFuture<>(); 1372 1373 // Create a single-use broadcast receiver 1374 BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 1375 @Override 1376 public void onReceive(Context context, Intent intent) { 1377 context.unregisterReceiver(this); 1378 onBroadcast.accept(context, intent); 1379 broadcastReceived.complete(true); 1380 } 1381 }; 1382 // Create an intent-filter and register the receiver 1383 IntentFilter intentFilter = new IntentFilter(); 1384 intentFilter.addAction(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); 1385 intentFilter.addDataType(PACKAGE_MIME_TYPE); 1386 // The broadcast is sent for user 0, so we need to request it for all users. 1387 // TODO(b/232317379) Fix this in proper way 1388 getContext().registerReceiverForAllUsers(broadcastReceiver, intentFilter, null, null, 1389 RECEIVER_EXPORTED); 1390 1391 // Enable verification. 1392 executeShellCommand("settings put global verifier_verify_adb_installs 1"); 1393 // Override verifier for updates of debuggable apps. 1394 setSystemProperty("debug.pm.adb_verifier_override_packages", 1395 CTS_PACKAGE_NAME + ";" + TEST_VERIFIER_PACKAGE); 1396 1397 // Update the package, should trigger verifier override. 1398 installPackage(updatedName, expectedResultStartsWith); 1399 1400 // Wait for broadcast. 1401 broadcastReceived.get(VERIFICATION_BROADCAST_RECEIVED_TIMEOUT_MS, TimeUnit.MILLISECONDS); 1402 } 1403 1404 @Test 1405 @LargeTest testPackageVerifierAllow()1406 public void testPackageVerifierAllow() throws Exception { 1407 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1408 1409 runPackageVerifierTest((context, intent) -> { 1410 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1411 assertNotEquals(-1, verificationId); 1412 1413 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1414 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1415 assertNotEquals(-1, sessionId); 1416 1417 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1418 }); 1419 1420 assertEquals(mDataLoaderType, dataLoaderType.get()); 1421 } 1422 1423 @Test 1424 @LargeTest testPackageVerifierAllowTwoVerifiers()1425 public void testPackageVerifierAllowTwoVerifiers() throws Exception { 1426 installPackage(TEST_VERIFIER_ALLOW); 1427 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1428 1429 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1430 1431 runPackageVerifierTest((context, intent) -> { 1432 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1433 assertNotEquals(-1, verificationId); 1434 1435 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1436 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1437 assertNotEquals(-1, sessionId); 1438 1439 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1440 }); 1441 1442 assertEquals(mDataLoaderType, dataLoaderType.get()); 1443 } 1444 1445 @Test 1446 @LargeTest testPackageVerifierReject()1447 public void testPackageVerifierReject() throws Exception { 1448 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1449 1450 runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1451 (context, intent) -> { 1452 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1453 assertNotEquals(-1, verificationId); 1454 1455 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1456 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1457 assertNotEquals(-1, sessionId); 1458 1459 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_REJECT); 1460 }); 1461 1462 assertEquals(mDataLoaderType, dataLoaderType.get()); 1463 } 1464 1465 @Test 1466 @LargeTest testPackageSufficientVerifierReject()1467 public void testPackageSufficientVerifierReject() throws Exception { 1468 // TEST_SUFFICIENT configured to have hellosufficient as sufficient verifier. 1469 installPackage(TEST_SUFFICIENT_VERIFIER_REJECT); 1470 assertTrue(isAppInstalled(TEST_SUFFICIENT_VERIFIER_PACKAGE)); 1471 1472 // PackageManager.verifyPendingInstall() call only works with user 0 as verifier is expected 1473 // to be user 0. So skip the test if it is not user 0. 1474 // TODO(b/232317379) Fix this in proper way 1475 assumeTrue(getContext().getUserId() == UserHandle.USER_SYSTEM); 1476 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1477 1478 runPackageVerifierTest(TEST_HW5, TEST_SUFFICIENT, 1479 "Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1480 (context, intent) -> { 1481 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1482 assertNotEquals(-1, verificationId); 1483 1484 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1485 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1486 assertNotEquals(-1, sessionId); 1487 1488 // This is a required verifier. The installation should fail, even though the 1489 // required verifier allows installation. 1490 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1491 }); 1492 1493 assertEquals(mDataLoaderType, dataLoaderType.get()); 1494 } 1495 1496 @Test 1497 @LargeTest testPackageVerifierRejectTwoVerifiersBothReject()1498 public void testPackageVerifierRejectTwoVerifiersBothReject() throws Exception { 1499 installPackage(TEST_VERIFIER_REJECT); 1500 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1501 1502 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1503 1504 runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1505 (context, intent) -> { 1506 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1507 assertNotEquals(-1, verificationId); 1508 1509 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1510 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1511 assertNotEquals(-1, sessionId); 1512 1513 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_REJECT); 1514 }); 1515 1516 assertEquals(mDataLoaderType, dataLoaderType.get()); 1517 } 1518 1519 @Test 1520 @LargeTest testPackageVerifierRejectTwoVerifiersOnlyOneRejects()1521 public void testPackageVerifierRejectTwoVerifiersOnlyOneRejects() throws Exception { 1522 installPackage(TEST_VERIFIER_REJECT); 1523 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1524 1525 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1526 1527 runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1528 (context, intent) -> { 1529 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1530 assertNotEquals(-1, verificationId); 1531 1532 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1533 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1534 assertNotEquals(-1, sessionId); 1535 1536 // This one allows, the other one rejects. 1537 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1538 }); 1539 1540 assertEquals(mDataLoaderType, dataLoaderType.get()); 1541 } 1542 1543 @Test 1544 @LargeTest testPackageVerifierRejectTwoVerifiersOnlyOneDelayedRejects()1545 public void testPackageVerifierRejectTwoVerifiersOnlyOneDelayedRejects() throws Exception { 1546 if (mIncremental) { 1547 // Incremental does not allow timeout extension. 1548 return; 1549 } 1550 installPackage(TEST_VERIFIER_DELAYED_REJECT); 1551 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1552 1553 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1554 1555 runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1556 (context, intent) -> { 1557 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1558 assertNotEquals(-1, verificationId); 1559 1560 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1561 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1562 assertNotEquals(-1, sessionId); 1563 1564 // This one allows, the other one rejects. 1565 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1566 }); 1567 1568 assertEquals(mDataLoaderType, dataLoaderType.get()); 1569 } 1570 1571 @Test 1572 @LargeTest testPackageVerifierRejectAfterTimeout()1573 public void testPackageVerifierRejectAfterTimeout() throws Exception { 1574 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1575 1576 runPackageVerifierTestSync(TEST_HW5, TEST_HW7, "Success", (context, intent) -> { 1577 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1578 assertNotEquals(-1, verificationId); 1579 1580 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1581 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1582 assertNotEquals(-1, sessionId); 1583 1584 try { 1585 if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL) { 1586 // For streaming installations, the timeout is fixed at 3secs and always 1587 // allow the install. Try to extend the timeout and then reject after 1588 // much shorter time. 1589 getPackageManager().extendVerificationTimeout(verificationId, 1590 VERIFICATION_REJECT, mStreamingVerificationTimeoutMs * 3); 1591 Thread.sleep(mStreamingVerificationTimeoutMs * 2); 1592 getPackageManager().verifyPendingInstall(verificationId, 1593 VERIFICATION_REJECT); 1594 } else { 1595 getPackageManager().verifyPendingInstall(verificationId, 1596 VERIFICATION_ALLOW); 1597 } 1598 } catch (InterruptedException e) { 1599 throw new RuntimeException(e); 1600 } 1601 }); 1602 1603 assertEquals(mDataLoaderType, dataLoaderType.get()); 1604 } 1605 1606 @Test 1607 @LargeTest testPackageVerifierWithExtensionAndTimeout()1608 public void testPackageVerifierWithExtensionAndTimeout() throws Exception { 1609 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1610 1611 runPackageVerifierTest((context, intent) -> { 1612 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1613 assertNotEquals(-1, verificationId); 1614 1615 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1616 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1617 assertNotEquals(-1, sessionId); 1618 1619 try { 1620 if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL) { 1621 // For streaming installations, the timeout is fixed at 3secs and always 1622 // allow the install. Try to extend the timeout and then reject after 1623 // much shorter time. 1624 getPackageManager().extendVerificationTimeout(verificationId, 1625 VERIFICATION_REJECT, mStreamingVerificationTimeoutMs * 3); 1626 Thread.sleep(mStreamingVerificationTimeoutMs * 2); 1627 getPackageManager().verifyPendingInstall(verificationId, 1628 VERIFICATION_REJECT); 1629 } else { 1630 getPackageManager().verifyPendingInstall(verificationId, 1631 VERIFICATION_ALLOW); 1632 } 1633 } catch (InterruptedException e) { 1634 throw new RuntimeException(e); 1635 } 1636 }); 1637 1638 assertEquals(mDataLoaderType, dataLoaderType.get()); 1639 } 1640 1641 @Test testPackageVerifierWithChecksums()1642 public void testPackageVerifierWithChecksums() throws Exception { 1643 AtomicInteger dataLoaderType = new AtomicInteger(-1); 1644 List<ApkChecksum> checksums = new ArrayList<>(); 1645 StringBuilder rootHash = new StringBuilder(); 1646 1647 runPackageVerifierTest((context, intent) -> { 1648 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1649 assertNotEquals(-1, verificationId); 1650 1651 dataLoaderType.set(intent.getIntExtra(EXTRA_DATA_LOADER_TYPE, -1)); 1652 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1653 assertNotEquals(-1, sessionId); 1654 1655 try { 1656 PackageInstaller.Session session = getPackageInstaller().openSession(sessionId); 1657 assertNotNull(session); 1658 1659 rootHash.append(intent.getStringExtra(EXTRA_VERIFICATION_ROOT_HASH)); 1660 1661 String[] names = session.getNames(); 1662 assertEquals(1, names.length); 1663 session.requestChecksums(names[0], 0, PackageManager.TRUST_ALL, 1664 ConcurrentUtils.DIRECT_EXECUTOR, 1665 result -> checksums.addAll(result)); 1666 } catch (IOException | CertificateEncodingException e) { 1667 throw new RuntimeException(e); 1668 } 1669 }); 1670 1671 assertEquals(mDataLoaderType, dataLoaderType.get()); 1672 1673 assertEquals(1, checksums.size()); 1674 1675 if (mDataLoaderType == DATA_LOADER_TYPE_INCREMENTAL) { 1676 assertEquals(TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, checksums.get(0).getType()); 1677 assertEquals(rootHash.toString(), 1678 "base.apk:" + HexDump.toHexString(checksums.get(0).getValue())); 1679 } else { 1680 assertEquals(TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256, checksums.get(0).getType()); 1681 } 1682 } 1683 1684 @Test testPackageVerifierWithOneVerifierDisabledAtRunTime()1685 public void testPackageVerifierWithOneVerifierDisabledAtRunTime() throws Exception { 1686 installPackage(TEST_VERIFIER_REJECT); 1687 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1688 runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1689 (context, intent) -> { 1690 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1691 assertNotEquals(-1, verificationId); 1692 1693 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1694 assertNotEquals(-1, sessionId); 1695 1696 // This one allows, the other one rejects. 1697 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1698 }); 1699 1700 // We can't disable the test package, but we can disable the second verifier package 1701 disablePackage(TEST_VERIFIER_PACKAGE); 1702 // Expect the installation to success, even though the second verifier would reject it 1703 // if the verifier is enabled 1704 runPackageVerifierTest( 1705 (context, intent) -> { 1706 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1707 assertNotEquals(-1, verificationId); 1708 1709 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1710 assertNotEquals(-1, sessionId); 1711 1712 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1713 }); 1714 1715 } 1716 1717 @Test testPackageVerifierWithOneVerifierDisabledAtManifest()1718 public void testPackageVerifierWithOneVerifierDisabledAtManifest() throws Exception { 1719 // The second verifier package is disabled in its manifest 1720 installPackage(TEST_VERIFIER_REJECT); 1721 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1722 runPackageVerifierTest("Failure [INSTALL_FAILED_VERIFICATION_FAILURE: Install not allowed", 1723 (context, intent) -> { 1724 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1725 assertNotEquals(-1, verificationId); 1726 1727 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1728 assertNotEquals(-1, sessionId); 1729 1730 // This one allows, the other one rejects. 1731 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1732 }); 1733 // Uninstall the second verifier first to allow for the new verifier installation 1734 uninstallPackageSilently(TEST_VERIFIER_PACKAGE); 1735 installPackage(TEST_VERIFIER_DISABLED); 1736 assertTrue(isAppInstalled(TEST_VERIFIER_PACKAGE)); 1737 // Expect the installation to success, even though the second verifier would reject it 1738 // if the verifier is enabled 1739 runPackageVerifierTest( 1740 (context, intent) -> { 1741 int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1); 1742 assertNotEquals(-1, verificationId); 1743 1744 int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1); 1745 assertNotEquals(-1, sessionId); 1746 1747 getPackageManager().verifyPendingInstall(verificationId, VERIFICATION_ALLOW); 1748 }); 1749 1750 } 1751 1752 @Test testAppWithNoAppStorageUpdateSuccess()1753 public void testAppWithNoAppStorageUpdateSuccess() throws Exception { 1754 installPackage(TEST_HW_NO_APP_STORAGE); 1755 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1756 // Updates that don't change value of NO_APP_DATA_STORAGE property are allowed. 1757 installPackage(TEST_HW_NO_APP_STORAGE); 1758 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1759 } 1760 1761 @Test testAppUpdateAddsNoAppDataStorageProperty()1762 public void testAppUpdateAddsNoAppDataStorageProperty() throws Exception { 1763 installPackage(TEST_HW5); 1764 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1765 installPackage( 1766 TEST_HW_NO_APP_STORAGE, 1767 "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Update " 1768 + "attempted to change value of " 1769 + "android.internal.PROPERTY_NO_APP_DATA_STORAGE"); 1770 } 1771 1772 @Test testAppUpdateRemovesNoAppDataStorageProperty()1773 public void testAppUpdateRemovesNoAppDataStorageProperty() throws Exception { 1774 installPackage(TEST_HW_NO_APP_STORAGE); 1775 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1776 installPackage( 1777 TEST_HW5, 1778 "Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Update " 1779 + "attempted to change value of " 1780 + "android.internal.PROPERTY_NO_APP_DATA_STORAGE"); 1781 } 1782 1783 @Test testNoAppDataStoragePropertyCanChangeAfterUninstall()1784 public void testNoAppDataStoragePropertyCanChangeAfterUninstall() throws Exception { 1785 installPackage(TEST_HW_NO_APP_STORAGE); 1786 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1787 uninstallPackageSilently(TEST_APP_PACKAGE); 1788 // After app is uninstalled new install can change the value of the property. 1789 installPackage(TEST_HW5); 1790 assertTrue(isAppInstalled(TEST_APP_PACKAGE)); 1791 } 1792 1793 @Test testQuerySdkSandboxPackageName()1794 public void testQuerySdkSandboxPackageName() throws Exception { 1795 final PackageManager pm = getPackageManager(); 1796 final String name = pm.getSdkSandboxPackageName(); 1797 assertNotNull(name); 1798 final ApplicationInfo info = pm.getApplicationInfo( 1799 name, PackageManager.ApplicationInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY)); 1800 assertEquals(ApplicationInfo.FLAG_SYSTEM, info.flags & ApplicationInfo.FLAG_SYSTEM); 1801 assertTrue(info.sourceDir.startsWith("/apex/com.android.adservices")); 1802 } 1803 1804 @Test testGetPackagesForUid_sdkSandboxUid()1805 public void testGetPackagesForUid_sdkSandboxUid() throws Exception { 1806 final PackageManager pm = getPackageManager(); 1807 final String[] pkgs = pm.getPackagesForUid(Process.toSdkSandboxUid(10239)); 1808 assertEquals(1, pkgs.length); 1809 assertEquals(pm.getSdkSandboxPackageName(), pkgs[0]); 1810 } 1811 1812 @Test testGetNameForUid_sdkSandboxUid()1813 public void testGetNameForUid_sdkSandboxUid() throws Exception { 1814 final PackageManager pm = getPackageManager(); 1815 final String pkgName = pm.getNameForUid(Process.toSdkSandboxUid(11543)); 1816 assertEquals(pm.getSdkSandboxPackageName(), pkgName); 1817 } 1818 1819 @Test testGetNamesForUids_sdkSandboxUids()1820 public void testGetNamesForUids_sdkSandboxUids() throws Exception { 1821 final PackageManager pm = getPackageManager(); 1822 final int[] uids = new int[]{Process.toSdkSandboxUid(10101)}; 1823 final String[] names = pm.getNamesForUids(uids); 1824 assertEquals(1, names.length); 1825 assertEquals(pm.getSdkSandboxPackageName(), names[0]); 1826 } 1827 1828 @LargeTest 1829 @Test testCreateUserCurAsType()1830 public void testCreateUserCurAsType() throws Exception { 1831 assumeTrue(UserManager.supportsMultipleUsers()); 1832 final String oldPropertyValue = getSystemProperty(UserManager.DEV_CREATE_OVERRIDE_PROPERTY); 1833 setSystemProperty(UserManager.DEV_CREATE_OVERRIDE_PROPERTY, "1"); 1834 try { 1835 Pattern pattern = Pattern.compile("Success: created user id (\\d+)\\R*"); 1836 String commandResult = executeShellCommand("pm create-user --profileOf cur " 1837 + "--user-type android.os.usertype.profile.CLONE test"); 1838 Matcher matcher = pattern.matcher(commandResult); 1839 assertTrue(matcher.find()); 1840 commandResult = executeShellCommand("pm remove-user " + matcher.group(1)); 1841 assertEquals("Success: removed user\n", commandResult); 1842 commandResult = executeShellCommand("pm create-user --profileOf current " 1843 + "--user-type android.os.usertype.profile.CLONE test"); 1844 matcher = pattern.matcher(commandResult); 1845 assertTrue(matcher.find()); 1846 commandResult = executeShellCommand("pm remove-user " + matcher.group(1)); 1847 assertEquals("Success: removed user\n", commandResult); 1848 } finally { 1849 if (!oldPropertyValue.isEmpty()) { 1850 setSystemProperty(UserManager.DEV_CREATE_OVERRIDE_PROPERTY, oldPropertyValue); 1851 } 1852 } 1853 } 1854 1855 @Test testShellInitiatingPkgName()1856 public void testShellInitiatingPkgName() throws Exception { 1857 installPackage(TEST_HW5); 1858 InstallSourceInfo installSourceInfo = getPackageManager() 1859 .getInstallSourceInfo(TEST_APP_PACKAGE); 1860 assertEquals(SHELL_PACKAGE_NAME, installSourceInfo.getInitiatingPackageName()); 1861 assertNull(installSourceInfo.getInstallingPackageName()); 1862 } 1863 1864 @Test testShellInitiatingPkgNameSetInstallerPkgName()1865 public void testShellInitiatingPkgNameSetInstallerPkgName() throws Exception { 1866 installPackageWithInstallerPkgName(TEST_HW5, CTS_PACKAGE_NAME); 1867 InstallSourceInfo installSourceInfo = getPackageManager() 1868 .getInstallSourceInfo(TEST_APP_PACKAGE); 1869 assertEquals(SHELL_PACKAGE_NAME, installSourceInfo.getInitiatingPackageName()); 1870 assertEquals(CTS_PACKAGE_NAME, installSourceInfo.getInstallingPackageName()); 1871 } 1872 1873 static class FullyRemovedBroadcastReceiver extends BroadcastReceiver { 1874 private final String mTargetPackage; 1875 private final int mTargetUserId; 1876 private final CompletableFuture<Boolean> mUserReceivedBroadcast = new CompletableFuture<>(); FullyRemovedBroadcastReceiver(String packageName, int targetUserId)1877 FullyRemovedBroadcastReceiver(String packageName, int targetUserId) { 1878 mTargetPackage = packageName; 1879 mTargetUserId = targetUserId; 1880 } 1881 @Override onReceive(Context context, Intent intent)1882 public void onReceive(Context context, Intent intent) { 1883 final String packageName = intent.getData().getEncodedSchemeSpecificPart(); 1884 final int userId = context.getUserId(); 1885 if (intent.getAction().equals(Intent.ACTION_PACKAGE_FULLY_REMOVED) 1886 && packageName.equals(mTargetPackage) && userId == mTargetUserId) { 1887 mUserReceivedBroadcast.complete(true); 1888 context.unregisterReceiver(this); 1889 } 1890 } assertBroadcastReceived()1891 public void assertBroadcastReceived() throws Exception { 1892 // Make sure broadcast has been sent from PackageManager 1893 executeShellCommand("pm wait-for-handler --timeout 2000"); 1894 // Make sure broadcast has been dispatched from the queue 1895 executeShellCommand(String.format( 1896 "am wait-for-broadcast-dispatch -a %s -d package:%s", 1897 Intent.ACTION_PACKAGE_FULLY_REMOVED, mTargetPackage)); 1898 // Checks that broadcast is delivered here 1899 assertTrue(mUserReceivedBroadcast.get(500, TimeUnit.MILLISECONDS)); 1900 } assertBroadcastNotReceived()1901 public void assertBroadcastNotReceived() throws Exception { 1902 // Make sure broadcast has been sent from PackageManager 1903 executeShellCommand("pm wait-for-handler --timeout 2000"); 1904 executeShellCommand(String.format( 1905 "am wait-for-broadcast-dispatch -a %s -d package:%s", 1906 Intent.ACTION_PACKAGE_FULLY_REMOVED, mTargetPackage)); 1907 assertThrows(TimeoutException.class, 1908 () -> mUserReceivedBroadcast.get(500, TimeUnit.MILLISECONDS)); 1909 } 1910 } 1911 getSharedLibraries()1912 private List<SharedLibraryInfo> getSharedLibraries() { 1913 getUiAutomation().adoptShellPermissionIdentity(); 1914 try { 1915 return getPackageManager().getSharedLibraries(PackageManager.PackageInfoFlags.of(0)); 1916 } finally { 1917 getUiAutomation().dropShellPermissionIdentity(); 1918 } 1919 } 1920 findLibrary(List<SharedLibraryInfo> libs, String name, long version)1921 private SharedLibraryInfo findLibrary(List<SharedLibraryInfo> libs, String name, long version) { 1922 for (int i = 0, size = libs.size(); i < size; ++i) { 1923 SharedLibraryInfo lib = libs.get(i); 1924 if (name.equals(lib.getName()) && version == lib.getLongVersion()) { 1925 return lib; 1926 } 1927 } 1928 return null; 1929 } 1930 createUpdateSession(String packageName)1931 private String createUpdateSession(String packageName) throws IOException { 1932 return createSession("-p " + packageName); 1933 } 1934 createSession(String arg)1935 private String createSession(String arg) throws IOException { 1936 final String prefix = "Success: created install session ["; 1937 final String suffix = "]\n"; 1938 final String commandResult = executeShellCommand("pm install-create " + arg); 1939 assertTrue(commandResult, commandResult.startsWith(prefix)); 1940 assertTrue(commandResult, commandResult.endsWith(suffix)); 1941 return commandResult.substring(prefix.length(), commandResult.length() - suffix.length()); 1942 } 1943 addSplits(String sessionId, String[] splitNames)1944 private void addSplits(String sessionId, String[] splitNames) throws IOException { 1945 for (String splitName : splitNames) { 1946 File file = new File(splitName); 1947 assertEquals( 1948 "Success: streamed " + file.length() + " bytes\n", 1949 executeShellCommand("pm install-write " + sessionId + " " + file.getName() + " " 1950 + splitName)); 1951 } 1952 } 1953 addSplitsStdIn(String sessionId, String[] splitNames, String args)1954 private void addSplitsStdIn(String sessionId, String[] splitNames, String args) 1955 throws IOException { 1956 for (String splitName : splitNames) { 1957 File file = new File(splitName); 1958 assertEquals("Success: streamed " + file.length() + " bytes\n", executeShellCommand( 1959 "pm install-write -S " + file.length() + " " + sessionId + " " + file.getName() 1960 + " " + args, file)); 1961 } 1962 } 1963 removeSplits(String sessionId, String[] splitNames)1964 private void removeSplits(String sessionId, String[] splitNames) throws IOException { 1965 for (String splitName : splitNames) { 1966 assertEquals("Success\n", 1967 executeShellCommand("pm install-remove " + sessionId + " " + splitName)); 1968 } 1969 } 1970 removeSplitsBatch(String sessionId, String[] splitNames)1971 private void removeSplitsBatch(String sessionId, String[] splitNames) throws IOException { 1972 assertEquals("Success\n", executeShellCommand( 1973 "pm install-remove " + sessionId + " " + String.join(" ", splitNames))); 1974 } 1975 commitSession(String sessionId)1976 private void commitSession(String sessionId) throws IOException { 1977 assertEquals("Success\n", executeShellCommand("pm install-commit " + sessionId)); 1978 } 1979 isAppInstalled(String packageName)1980 static boolean isAppInstalled(String packageName) throws IOException { 1981 final String commandResult = executeShellCommand("pm list packages"); 1982 final int prefixLength = "package:".length(); 1983 return Arrays.stream(commandResult.split("\\r?\\n")).anyMatch( 1984 line -> line.length() > prefixLength && line.substring(prefixLength).equals( 1985 packageName)); 1986 } 1987 isSdkInstalled(String name, int versionMajor)1988 private boolean isSdkInstalled(String name, int versionMajor) throws IOException { 1989 final String sdkString = name + ":" + versionMajor; 1990 final String commandResult = executeShellCommand("pm list sdks"); 1991 final int prefixLength = "sdk:".length(); 1992 return Arrays.stream(commandResult.split("\\r?\\n")) 1993 .anyMatch(line -> line.length() > prefixLength && line.substring( 1994 prefixLength).equals(sdkString)); 1995 } 1996 getPackageCertDigest(String packageName)1997 private String getPackageCertDigest(String packageName) throws Exception { 1998 getUiAutomation().adoptShellPermissionIdentity(); 1999 try { 2000 PackageInfo sdkPackageInfo = getPackageManager().getPackageInfo(packageName, 2001 PackageManager.PackageInfoFlags.of( 2002 GET_SIGNING_CERTIFICATES | MATCH_STATIC_SHARED_AND_SDK_LIBRARIES)); 2003 SigningInfo signingInfo = sdkPackageInfo.signingInfo; 2004 Signature[] signatures = 2005 signingInfo != null ? signingInfo.getSigningCertificateHistory() : null; 2006 byte[] digest = PackageUtils.computeSha256DigestBytes(signatures[0].toByteArray()); 2007 return new String(HexEncoding.encode(digest)); 2008 } finally { 2009 getUiAutomation().dropShellPermissionIdentity(); 2010 } 2011 } 2012 2013 /** 2014 * SDK package is signed by build system. In theory we could try to extract the signature, 2015 * and patch the app manifest. This property allows us to override in runtime, which is much 2016 * easier. 2017 */ overrideUsesSdkLibraryCertificateDigest(String sdkCertDigest)2018 private void overrideUsesSdkLibraryCertificateDigest(String sdkCertDigest) throws Exception { 2019 setSystemProperty("debug.pm.uses_sdk_library_default_cert_digest", sdkCertDigest); 2020 } 2021 getSplits(String packageName)2022 static String getSplits(String packageName) throws IOException { 2023 final String commandResult = executeShellCommand("pm dump " + packageName); 2024 final String prefix = " splits=["; 2025 final int prefixLength = prefix.length(); 2026 Optional<String> maybeSplits = Arrays.stream(commandResult.split("\\r?\\n")) 2027 .filter(line -> line.startsWith(prefix)).findFirst(); 2028 if (!maybeSplits.isPresent()) { 2029 return null; 2030 } 2031 String splits = maybeSplits.get(); 2032 return splits.substring(prefixLength, splits.length() - 1); 2033 } 2034 createApkPath(String baseName)2035 static String createApkPath(String baseName) { 2036 return TEST_APK_PATH + baseName; 2037 } 2038 2039 /* Install for all the users */ installPackage(String baseName)2040 private void installPackage(String baseName) throws IOException { 2041 File file = new File(createApkPath(baseName)); 2042 assertEquals("Success\n", executeShellCommand( 2043 "pm " + mInstall + " -t -g " + file.getPath())); 2044 } 2045 installPackage(String baseName, String expectedResultStartsWith)2046 private void installPackage(String baseName, String expectedResultStartsWith) 2047 throws IOException { 2048 File file = new File(createApkPath(baseName)); 2049 String result = executeShellCommand("pm " + mInstall + " -t -g " + file.getPath()); 2050 assertTrue(result, result.startsWith(expectedResultStartsWith)); 2051 } 2052 installPackageWithInstallerPkgName(String baseName, String installerName)2053 private void installPackageWithInstallerPkgName(String baseName, String installerName) 2054 throws IOException { 2055 File file = new File(createApkPath(baseName)); 2056 assertEquals("Success\n", executeShellCommand( 2057 "pm " + mInstall + "-i " + installerName + " -t -g " + file.getPath())); 2058 } 2059 updatePackage(String packageName, String baseName)2060 private void updatePackage(String packageName, String baseName) throws IOException { 2061 File file = new File(createApkPath(baseName)); 2062 assertEquals("Success\n", executeShellCommand( 2063 "pm " + mInstall + " -t -p " + packageName + " -g " + file.getPath())); 2064 } 2065 updatePackageSkipEnable(String packageName, String baseName)2066 private void updatePackageSkipEnable(String packageName, String baseName) throws IOException { 2067 File file = new File(createApkPath(baseName)); 2068 assertEquals("Success\n", executeShellCommand( 2069 "pm " + mInstall + " --skip-enable -t -p " + packageName + " -g " + file.getPath() 2070 )); 2071 } 2072 installPackageStdIn(String baseName)2073 private void installPackageStdIn(String baseName) throws IOException { 2074 File file = new File(createApkPath(baseName)); 2075 assertEquals("Success\n", 2076 executeShellCommand("pm " + mInstall + " -t -g -S " + file.length(), file)); 2077 } 2078 updatePackageStdIn(String packageName, String baseName)2079 private void updatePackageStdIn(String packageName, String baseName) throws IOException { 2080 File file = new File(createApkPath(baseName)); 2081 assertEquals("Success\n", executeShellCommand( 2082 "pm " + mInstall + " -t -p " + packageName + " -g -S " + file.length(), file)); 2083 } 2084 installSplits(String[] baseNames)2085 private void installSplits(String[] baseNames) throws IOException { 2086 if (mStreaming) { 2087 installSplitsBatch(baseNames); 2088 return; 2089 } 2090 String[] splits = Arrays.stream(baseNames).map( 2091 baseName -> createApkPath(baseName)).toArray(String[]::new); 2092 String sessionId = createSession(TEST_APP_PACKAGE); 2093 addSplits(sessionId, splits); 2094 commitSession(sessionId); 2095 } 2096 updateSplits(String[] baseNames)2097 private void updateSplits(String[] baseNames) throws IOException { 2098 if (mStreaming) { 2099 updateSplitsBatch(baseNames); 2100 return; 2101 } 2102 String[] splits = Arrays.stream(baseNames).map( 2103 baseName -> createApkPath(baseName)).toArray(String[]::new); 2104 String sessionId = createSession("-p " + TEST_APP_PACKAGE); 2105 addSplits(sessionId, splits); 2106 commitSession(sessionId); 2107 } 2108 installSplitsStdInStreaming(String[] splits)2109 private void installSplitsStdInStreaming(String[] splits) throws IOException { 2110 File[] files = Arrays.stream(splits).map(split -> new File(split)).toArray(File[]::new); 2111 String param = Arrays.stream(files).map( 2112 file -> file.getName() + ":" + file.length()).collect(Collectors.joining(" ")); 2113 assertEquals("Success\n", executeShellCommand("pm" + mInstall + param, files)); 2114 } 2115 installSplitsStdIn(String[] baseNames, String args)2116 private void installSplitsStdIn(String[] baseNames, String args) throws IOException { 2117 String[] splits = Arrays.stream(baseNames).map( 2118 baseName -> createApkPath(baseName)).toArray(String[]::new); 2119 if (mStreaming) { 2120 installSplitsStdInStreaming(splits); 2121 return; 2122 } 2123 String sessionId = createSession(TEST_APP_PACKAGE); 2124 addSplitsStdIn(sessionId, splits, args); 2125 commitSession(sessionId); 2126 } 2127 installSplitsBatch(String[] baseNames)2128 private void installSplitsBatch(String[] baseNames) throws IOException { 2129 final String[] splits = Arrays.stream(baseNames).map( 2130 baseName -> createApkPath(baseName)).toArray(String[]::new); 2131 assertEquals("Success\n", 2132 executeShellCommand("pm " + mInstall + " -t -g " + String.join(" ", splits))); 2133 } 2134 updateSplitsBatch(String[] baseNames)2135 private void updateSplitsBatch(String[] baseNames) throws IOException { 2136 final String[] splits = Arrays.stream(baseNames).map( 2137 baseName -> createApkPath(baseName)).toArray(String[]::new); 2138 assertEquals("Success\n", executeShellCommand( 2139 "pm " + mInstall + " -p " + TEST_APP_PACKAGE + " -t -g " + String.join(" ", 2140 splits))); 2141 } 2142 uninstallPackage(String packageName, String expectedResultStartsWith)2143 private void uninstallPackage(String packageName, String expectedResultStartsWith) 2144 throws IOException { 2145 String result = uninstallPackageSilently(packageName); 2146 assertTrue(result, result.startsWith(expectedResultStartsWith)); 2147 } 2148 uninstallPackageSilently(String packageName)2149 private String uninstallPackageSilently(String packageName) throws IOException { 2150 return executeShellCommand("pm uninstall " + packageName); 2151 } 2152 uninstallSplits(String packageName, String[] splitNames)2153 private void uninstallSplits(String packageName, String[] splitNames) throws IOException { 2154 for (String splitName : splitNames) { 2155 assertEquals("Success\n", 2156 executeShellCommand("pm uninstall " + packageName + " " + splitName)); 2157 } 2158 } 2159 uninstallSplitsBatch(String packageName, String[] splitNames)2160 private void uninstallSplitsBatch(String packageName, String[] splitNames) throws IOException { 2161 assertEquals("Success\n", executeShellCommand( 2162 "pm uninstall " + packageName + " " + String.join(" ", splitNames))); 2163 } 2164 setSystemProperty(String name, String value)2165 public static void setSystemProperty(String name, String value) throws Exception { 2166 assertEquals("", executeShellCommand("setprop " + name + " " + value)); 2167 } 2168 getSystemProperty(String prop)2169 private static String getSystemProperty(String prop) throws Exception { 2170 return executeShellCommand("getprop " + prop).replace("\n", ""); 2171 } 2172 disablePackage(String packageName)2173 private void disablePackage(String packageName) { 2174 getUiAutomation().adoptShellPermissionIdentity(); 2175 try { 2176 getPackageManager().setApplicationEnabledSetting(packageName, 2177 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); 2178 } finally { 2179 getUiAutomation().dropShellPermissionIdentity(); 2180 } 2181 } 2182 } 2183 2184