1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm.dex; 18 19 import android.os.Build; 20 import android.support.test.filters.SmallTest; 21 import android.support.test.runner.AndroidJUnit4; 22 import dalvik.system.VMRuntime; 23 24 import java.util.Collections; 25 import org.junit.Before; 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 29 import java.io.IOException; 30 import java.io.StringReader; 31 import java.io.StringWriter; 32 import java.util.Arrays; 33 import java.util.HashMap; 34 import java.util.HashSet; 35 import java.util.Map; 36 import java.util.Set; 37 38 import static org.junit.Assert.assertEquals; 39 import static org.junit.Assert.assertFalse; 40 import static org.junit.Assert.assertNotNull; 41 import static org.junit.Assert.assertNull; 42 import static org.junit.Assert.assertTrue; 43 import static org.junit.Assert.fail; 44 45 import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo; 46 import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo; 47 48 @RunWith(AndroidJUnit4.class) 49 @SmallTest 50 public class PackageDexUsageTests { 51 private PackageDexUsage mPackageDexUsage; 52 53 private TestData mFooBaseUser0; 54 private TestData mFooSplit1User0; 55 private TestData mFooSplit2UsedByOtherApps0; 56 private TestData mFooSecondary1User0; 57 private TestData mFooSecondary1User1; 58 private TestData mFooSecondary2UsedByOtherApps0; 59 private TestData mInvalidIsa; 60 61 private TestData mBarBaseUser0; 62 private TestData mBarSecondary1User0; 63 private TestData mBarSecondary2User1; 64 65 @Before 66 public void setup() { 67 mPackageDexUsage = new PackageDexUsage(); 68 69 String fooPackageName = "com.google.foo"; 70 String fooCodeDir = "/data/app/com.google.foo/"; 71 String fooDataDir = "/data/user/0/com.google.foo/"; 72 73 String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]); 74 75 mFooBaseUser0 = new TestData(fooPackageName, 76 fooCodeDir + "base.apk", 0, isa, false, true, fooPackageName); 77 78 mFooSplit1User0 = new TestData(fooPackageName, 79 fooCodeDir + "split-1.apk", 0, isa, false, true, fooPackageName); 80 81 mFooSplit2UsedByOtherApps0 = new TestData(fooPackageName, 82 fooCodeDir + "split-2.apk", 0, isa, true, true, "used.by.other.com"); 83 84 mFooSecondary1User0 = new TestData(fooPackageName, 85 fooDataDir + "sec-1.dex", 0, isa, false, false, fooPackageName); 86 87 mFooSecondary1User1 = new TestData(fooPackageName, 88 fooDataDir + "sec-1.dex", 1, isa, false, false, fooPackageName); 89 90 mFooSecondary2UsedByOtherApps0 = new TestData(fooPackageName, 91 fooDataDir + "sec-2.dex", 0, isa, true, false, "used.by.other.com"); 92 93 mInvalidIsa = new TestData(fooPackageName, 94 fooCodeDir + "base.apk", 0, "INVALID_ISA", false, true, "INALID_USER"); 95 96 String barPackageName = "com.google.bar"; 97 String barCodeDir = "/data/app/com.google.bar/"; 98 String barDataDir = "/data/user/0/com.google.bar/"; 99 String barDataDir1 = "/data/user/1/com.google.bar/"; 100 101 mBarBaseUser0 = new TestData(barPackageName, 102 barCodeDir + "base.apk", 0, isa, false, true, barPackageName); 103 mBarSecondary1User0 = new TestData(barPackageName, 104 barDataDir + "sec-1.dex", 0, isa, false, false, barPackageName); 105 mBarSecondary2User1 = new TestData(barPackageName, 106 barDataDir1 + "sec-2.dex", 1, isa, false, false, barPackageName); 107 } 108 109 @Test 110 public void testRecordPrimary() { 111 // Assert new information. 112 assertTrue(record(mFooBaseUser0)); 113 114 assertPackageDexUsage(mFooBaseUser0); 115 writeAndReadBack(); 116 assertPackageDexUsage(mFooBaseUser0); 117 } 118 119 @Test 120 public void testRecordSplit() { 121 // Assert new information. 122 assertTrue(record(mFooSplit1User0)); 123 124 assertPackageDexUsage(mFooSplit1User0); 125 writeAndReadBack(); 126 assertPackageDexUsage(mFooSplit1User0); 127 } 128 129 @Test 130 public void testRecordSplitPrimarySequence() { 131 // Assert new information. 132 assertTrue(record(mFooBaseUser0)); 133 // Assert no new information. 134 assertFalse(record(mFooSplit1User0)); 135 136 assertPackageDexUsage(mFooBaseUser0); 137 writeAndReadBack(); 138 assertPackageDexUsage(mFooBaseUser0); 139 140 // Write Split2 which is used by other apps. 141 // Assert new information. 142 assertTrue(record(mFooSplit2UsedByOtherApps0)); 143 assertPackageDexUsage(mFooSplit2UsedByOtherApps0); 144 writeAndReadBack(); 145 assertPackageDexUsage(mFooSplit2UsedByOtherApps0); 146 } 147 148 @Test 149 public void testRecordSecondary() { 150 assertTrue(record(mFooSecondary1User0)); 151 152 assertPackageDexUsage(null, mFooSecondary1User0); 153 writeAndReadBack(); 154 assertPackageDexUsage(null, mFooSecondary1User0); 155 156 // Recording again does not add more data. 157 assertFalse(record(mFooSecondary1User0)); 158 assertPackageDexUsage(null, mFooSecondary1User0); 159 } 160 161 @Test 162 public void testRecordBaseAndSecondarySequence() { 163 // Write split. 164 assertTrue(record(mFooSplit2UsedByOtherApps0)); 165 // Write secondary. 166 assertTrue(record(mFooSecondary1User0)); 167 168 // Check. 169 assertPackageDexUsage(mFooSplit2UsedByOtherApps0, mFooSecondary1User0); 170 writeAndReadBack(); 171 assertPackageDexUsage(mFooSplit2UsedByOtherApps0, mFooSecondary1User0); 172 173 // Write another secondary. 174 assertTrue(record(mFooSecondary2UsedByOtherApps0)); 175 176 // Check. 177 assertPackageDexUsage( 178 mFooSplit2UsedByOtherApps0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0); 179 writeAndReadBack(); 180 assertPackageDexUsage( 181 mFooSplit2UsedByOtherApps0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0); 182 } 183 184 @Test 185 public void testMultiplePackages() { 186 assertTrue(record(mFooBaseUser0)); 187 assertTrue(record(mFooSecondary1User0)); 188 assertTrue(record(mFooSecondary2UsedByOtherApps0)); 189 assertTrue(record(mBarBaseUser0)); 190 assertTrue(record(mBarSecondary1User0)); 191 assertTrue(record(mBarSecondary2User1)); 192 193 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0); 194 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1); 195 writeAndReadBack(); 196 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0); 197 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1); 198 } 199 200 @Test 201 public void testPackageNotFound() { 202 assertNull(mPackageDexUsage.getPackageUseInfo("missing.package")); 203 } 204 205 @Test 206 public void testAttemptToChangeOwner() { 207 assertTrue(record(mFooSecondary1User0)); 208 try { 209 record(mFooSecondary1User1); 210 fail("Expected exception"); 211 } catch (IllegalArgumentException e) { 212 // expected 213 } 214 } 215 216 @Test 217 public void testInvalidIsa() { 218 try { 219 record(mInvalidIsa); 220 fail("Expected exception"); 221 } catch (IllegalArgumentException e) { 222 // expected 223 } 224 } 225 226 @Test 227 public void testReadWriteEmtpy() { 228 // Expect no exceptions when writing/reading without data. 229 writeAndReadBack(); 230 } 231 232 @Test 233 public void testSyncData() { 234 // Write some records. 235 assertTrue(record(mFooBaseUser0)); 236 assertTrue(record(mFooSecondary1User0)); 237 assertTrue(record(mFooSecondary2UsedByOtherApps0)); 238 assertTrue(record(mBarBaseUser0)); 239 assertTrue(record(mBarSecondary1User0)); 240 assertTrue(record(mBarSecondary2User1)); 241 242 // Verify all is good. 243 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0); 244 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1); 245 writeAndReadBack(); 246 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0); 247 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1); 248 249 // Simulate that only user 1 is available. 250 Map<String, Set<Integer>> packageToUsersMap = new HashMap<>(); 251 packageToUsersMap.put(mBarSecondary2User1.mPackageName, 252 new HashSet<>(Arrays.asList(mBarSecondary2User1.mOwnerUserId))); 253 Map<String, Set<String>> packageToCodePaths = new HashMap<>(); 254 packageToCodePaths.put(mBarBaseUser0.mPackageName, 255 new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile))); 256 mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths); 257 258 // Assert that only user 1 files are there. 259 assertPackageDexUsage(mBarBaseUser0, mBarSecondary2User1); 260 assertNull(mPackageDexUsage.getPackageUseInfo(mFooBaseUser0.mPackageName)); 261 } 262 263 @Test 264 public void testRemovePackage() { 265 // Record Bar secondaries for two different users. 266 assertTrue(record(mBarSecondary1User0)); 267 assertTrue(record(mBarSecondary2User1)); 268 269 // Remove the package. 270 assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName)); 271 // Assert that we can't find the package anymore. 272 assertNull(mPackageDexUsage.getPackageUseInfo(mBarSecondary1User0.mPackageName)); 273 } 274 275 @Test 276 public void testRemoveNonexistentPackage() { 277 // Record Bar secondaries for two different users. 278 assertTrue(record(mBarSecondary1User0)); 279 280 // Remove the package. 281 assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName)); 282 // Remove the package again. It should return false because the package no longer 283 // has a record in the use info. 284 assertFalse(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName)); 285 } 286 287 @Test 288 public void testRemoveUserPackage() { 289 // Record Bar secondaries for two different users. 290 assertTrue(record(mBarSecondary1User0)); 291 assertTrue(record(mBarSecondary2User1)); 292 293 // Remove user 0 files. 294 assertTrue(mPackageDexUsage.removeUserPackage(mBarSecondary1User0.mPackageName, 295 mBarSecondary1User0.mOwnerUserId)); 296 // Assert that only user 1 files are there. 297 assertPackageDexUsage(null, mBarSecondary2User1); 298 } 299 300 @Test 301 public void testRemoveDexFile() { 302 // Record Bar secondaries for two different users. 303 assertTrue(record(mBarSecondary1User0)); 304 assertTrue(record(mBarSecondary2User1)); 305 306 // Remove mBarSecondary1User0 file. 307 assertTrue(mPackageDexUsage.removeDexFile(mBarSecondary1User0.mPackageName, 308 mBarSecondary1User0.mDexFile, mBarSecondary1User0.mOwnerUserId)); 309 // Assert that only user 1 files are there. 310 assertPackageDexUsage(null, mBarSecondary2User1); 311 } 312 313 @Test 314 public void testClearUsedByOtherApps() { 315 // Write a package which is used by other apps. 316 assertTrue(record(mFooSplit2UsedByOtherApps0)); 317 assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName)); 318 319 // Check that the package is no longer used by other apps. 320 TestData noLongerUsedByOtherApps = new TestData( 321 mFooSplit2UsedByOtherApps0.mPackageName, 322 mFooSplit2UsedByOtherApps0.mDexFile, 323 mFooSplit2UsedByOtherApps0.mOwnerUserId, 324 mFooSplit2UsedByOtherApps0.mLoaderIsa, 325 /*mIsUsedByOtherApps*/false, 326 mFooSplit2UsedByOtherApps0.mPrimaryOrSplit, 327 mFooSplit2UsedByOtherApps0.mUsedBy); 328 assertPackageDexUsage(noLongerUsedByOtherApps); 329 } 330 331 @Test 332 public void testClearUsedByOtherAppsNonexistent() { 333 // Write a package which is used by other apps. 334 assertTrue(record(mFooSplit2UsedByOtherApps0)); 335 assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName)); 336 // Clearing again should return false as there should be no update on the use info. 337 assertFalse(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName)); 338 } 339 340 @Test 341 public void testRecordDexFileUsers() { 342 PackageDexUsage packageDexUsageRecordUsers = new PackageDexUsage(); 343 Set<String> users = new HashSet<>(Arrays.asList( 344 new String[] {"another.package.1"})); 345 Set<String> usersExtra = new HashSet<>(Arrays.asList( 346 new String[] {"another.package.2", "another.package.3"})); 347 348 assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, users)); 349 assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, usersExtra)); 350 351 assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, users)); 352 assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, usersExtra)); 353 354 packageDexUsageRecordUsers = writeAndReadBack(packageDexUsageRecordUsers); 355 // Verify that the users were recorded. 356 Set<String> userAll = new HashSet<>(users); 357 userAll.addAll(usersExtra); 358 assertPackageDexUsage(packageDexUsageRecordUsers, userAll, mFooSplit2UsedByOtherApps0, 359 mFooSecondary1User0); 360 } 361 362 @Test 363 public void testRecordDexFileUsersNotTheOwningPackage() { 364 PackageDexUsage packageDexUsageRecordUsers = new PackageDexUsage(); 365 Set<String> users = new HashSet<>(Arrays.asList( 366 new String[] {mFooSplit2UsedByOtherApps0.mPackageName})); 367 Set<String> usersExtra = new HashSet<>(Arrays.asList( 368 new String[] {"another.package.2", "another.package.3"})); 369 370 assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, users)); 371 assertTrue(record(packageDexUsageRecordUsers, mFooSplit2UsedByOtherApps0, usersExtra)); 372 373 assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, users)); 374 assertTrue(record(packageDexUsageRecordUsers, mFooSecondary1User0, usersExtra)); 375 376 packageDexUsageRecordUsers = writeAndReadBack(packageDexUsageRecordUsers); 377 // Verify that only the non owning packages were recorded. 378 assertPackageDexUsage(packageDexUsageRecordUsers, usersExtra, mFooSplit2UsedByOtherApps0, 379 mFooSecondary1User0); 380 } 381 382 @Test 383 public void testRecordClassLoaderContextVariableContext() { 384 // Record a secondary dex file. 385 assertTrue(record(mFooSecondary1User0)); 386 // Now update its context. 387 TestData fooSecondary1User0NewContext = mFooSecondary1User0.updateClassLoaderContext( 388 "PCL[new_context.dex]"); 389 assertTrue(record(fooSecondary1User0NewContext)); 390 391 // Not check that the context was switch to variable. 392 TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext( 393 PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT); 394 395 assertPackageDexUsage(null, expectedContext); 396 writeAndReadBack(); 397 assertPackageDexUsage(null, expectedContext); 398 } 399 400 @Test 401 public void testRecordClassLoaderContextUnsupportedContext() { 402 // Record a secondary dex file. 403 assertTrue(record(mFooSecondary1User0)); 404 // Now update its context. 405 TestData unsupportedContext = mFooSecondary1User0.updateClassLoaderContext( 406 PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT); 407 assertTrue(record(unsupportedContext)); 408 409 assertPackageDexUsage(null, unsupportedContext); 410 writeAndReadBack(); 411 assertPackageDexUsage(null, unsupportedContext); 412 } 413 414 @Test 415 public void testRecordClassLoaderContextTransitionFromUnknown() { 416 // Record a secondary dex file. 417 TestData unknownContext = mFooSecondary1User0.updateClassLoaderContext( 418 PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT); 419 assertTrue(record(unknownContext)); 420 421 assertPackageDexUsage(null, unknownContext); 422 writeAndReadBack(); 423 assertPackageDexUsage(null, unknownContext); 424 425 // Now update the secondary dex record with a class loader context. This simulates the 426 // version 2 to version 3 upgrade. 427 428 assertTrue(record(mFooSecondary1User0)); 429 430 assertPackageDexUsage(null, mFooSecondary1User0); 431 writeAndReadBack(); 432 assertPackageDexUsage(null, mFooSecondary1User0); 433 } 434 435 @Test 436 public void testDexUsageClassLoaderContext() { 437 final boolean isUsedByOtherApps = false; 438 final int userId = 0; 439 PackageDexUsage.DexUseInfo validContext = new DexUseInfo(isUsedByOtherApps, userId, 440 "valid_context", "arm"); 441 assertFalse(validContext.isUnknownClassLoaderContext()); 442 assertFalse(validContext.isUnsupportedClassLoaderContext()); 443 assertFalse(validContext.isVariableClassLoaderContext()); 444 445 PackageDexUsage.DexUseInfo unsupportedContext = new DexUseInfo(isUsedByOtherApps, userId, 446 PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT, "arm"); 447 assertFalse(unsupportedContext.isUnknownClassLoaderContext()); 448 assertTrue(unsupportedContext.isUnsupportedClassLoaderContext()); 449 assertFalse(unsupportedContext.isVariableClassLoaderContext()); 450 451 PackageDexUsage.DexUseInfo variableContext = new DexUseInfo(isUsedByOtherApps, userId, 452 PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT, "arm"); 453 assertFalse(variableContext.isUnknownClassLoaderContext()); 454 assertFalse(variableContext.isUnsupportedClassLoaderContext()); 455 assertTrue(variableContext.isVariableClassLoaderContext()); 456 457 PackageDexUsage.DexUseInfo unknownContext = new DexUseInfo(isUsedByOtherApps, userId, 458 PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT, "arm"); 459 assertTrue(unknownContext.isUnknownClassLoaderContext()); 460 assertFalse(unknownContext.isUnsupportedClassLoaderContext()); 461 assertFalse(unknownContext.isVariableClassLoaderContext()); 462 } 463 464 @Test 465 public void testReadVersion1() { 466 String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]); 467 // Equivalent to 468 // record(mFooSplit2UsedByOtherApps0); 469 // record(mFooSecondary1User0); 470 // record(mFooSecondary2UsedByOtherApps0); 471 // record(mBarBaseUser0); 472 // record(mBarSecondary1User0); 473 String content = "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__1\n" 474 + "com.google.foo,1\n" 475 + "#/data/user/0/com.google.foo/sec-1.dex\n" 476 + "0,0," + isa + "\n" 477 + "#/data/user/0/com.google.foo/sec-2.dex\n" 478 + "0,1," + isa + "\n" 479 + "com.google.bar,0\n" 480 + "#/data/user/0/com.google.bar/sec-1.dex\n" 481 + "0,0," + isa + "\n"; 482 483 PackageDexUsage packageDexUsage = new PackageDexUsage(); 484 try { 485 packageDexUsage.read(new StringReader(content)); 486 } catch (IOException e) { 487 fail(); 488 } 489 490 // After the read we must sync the data to fill the missing information on the code paths. 491 Map<String, Set<Integer>> packageToUsersMap = new HashMap<>(); 492 Map<String, Set<String>> packageToCodePaths = new HashMap<>(); 493 494 // Handle foo package. 495 packageToUsersMap.put(mFooSplit2UsedByOtherApps0.mPackageName, 496 new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mOwnerUserId))); 497 packageToCodePaths.put(mFooSplit2UsedByOtherApps0.mPackageName, 498 new HashSet<>(Arrays.asList(mFooSplit2UsedByOtherApps0.mDexFile, 499 mFooSplit1User0.mDexFile, mFooBaseUser0.mDexFile))); 500 // Handle bar package. 501 packageToUsersMap.put(mBarBaseUser0.mPackageName, 502 new HashSet<>(Arrays.asList(mBarBaseUser0.mOwnerUserId))); 503 packageToCodePaths.put(mBarBaseUser0.mPackageName, 504 new HashSet<>(Arrays.asList(mBarBaseUser0.mDexFile))); 505 506 // Sync the data. 507 packageDexUsage.syncData(packageToUsersMap, packageToCodePaths); 508 509 // Update the class loaders to unknown before asserting if needed. Before version 2 we 510 // didn't have any. 511 String unknown = PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT; 512 TestData fooBaseUser0 = mFooBaseUser0.updateClassLoaderContext(unknown); 513 TestData fooSplit1User0 = mFooSplit1User0.updateClassLoaderContext(unknown); 514 TestData fooSplit2UsedByOtherApps0 = 515 mFooSplit2UsedByOtherApps0.updateClassLoaderContext(unknown); 516 TestData fooSecondary1User0 = mFooSecondary1User0.updateClassLoaderContext(unknown); 517 TestData fooSecondary2UsedByOtherApps0 = 518 mFooSecondary2UsedByOtherApps0.updateClassLoaderContext(unknown); 519 TestData barBaseUser0 = mBarBaseUser0.updateClassLoaderContext(unknown); 520 TestData barSecondary1User0 = mBarSecondary1User0.updateClassLoaderContext(unknown); 521 522 // Assert foo code paths. Note that we ignore the users during upgrade. 523 final Set<String> ignoredUsers = null; 524 assertPackageDexUsage(packageDexUsage, ignoredUsers, 525 fooSplit2UsedByOtherApps0, fooSecondary1User0, fooSecondary2UsedByOtherApps0); 526 // Because fooSplit2UsedByOtherApps0 is used by others, all the other code paths must 527 // share the same data. 528 assertPackageDexUsage(packageDexUsage, ignoredUsers, 529 fooSplit1User0.updateUseByOthers(true), 530 fooSecondary1User0, fooSecondary2UsedByOtherApps0); 531 assertPackageDexUsage(packageDexUsage, ignoredUsers, fooBaseUser0.updateUseByOthers(true), 532 fooSecondary1User0, fooSecondary2UsedByOtherApps0); 533 534 // Assert bar code paths. Note that we ignore the users during upgrade. 535 assertPackageDexUsage(packageDexUsage, ignoredUsers, barBaseUser0, barSecondary1User0); 536 } 537 538 private void assertPackageDexUsage(TestData primary, TestData... secondaries) { 539 assertPackageDexUsage(mPackageDexUsage, null, primary, secondaries); 540 } 541 542 private void assertPackageDexUsage(PackageDexUsage packageDexUsage, Set<String> users, 543 TestData primary, TestData... secondaries) { 544 String packageName = primary == null ? secondaries[0].mPackageName : primary.mPackageName; 545 boolean primaryUsedByOtherApps = primary != null && primary.mUsedByOtherApps; 546 PackageUseInfo pInfo = packageDexUsage.getPackageUseInfo(packageName); 547 548 // Check package use info 549 assertNotNull(pInfo); 550 if (primary != null) { 551 assertEquals(primaryUsedByOtherApps, pInfo.isUsedByOtherApps(primary.mDexFile)); 552 if (users != null) { 553 assertEquals(pInfo.getLoadingPackages(primary.mDexFile), users); 554 } 555 } 556 557 Map<String, DexUseInfo> dexUseInfoMap = pInfo.getDexUseInfoMap(); 558 assertEquals(secondaries.length, dexUseInfoMap.size()); 559 560 // Check dex use info 561 for (TestData testData : secondaries) { 562 DexUseInfo dInfo = dexUseInfoMap.get(testData.mDexFile); 563 assertNotNull(dInfo); 564 assertEquals(testData.mUsedByOtherApps, dInfo.isUsedByOtherApps()); 565 assertEquals(testData.mOwnerUserId, dInfo.getOwnerUserId()); 566 assertEquals(1, dInfo.getLoaderIsas().size()); 567 assertTrue(dInfo.getLoaderIsas().contains(testData.mLoaderIsa)); 568 if (users != null) { 569 assertEquals(dInfo.getLoadingPackages(), users); 570 } 571 572 assertEquals(testData.mClassLoaderContext, dInfo.getClassLoaderContext()); 573 } 574 } 575 576 private boolean record(TestData testData) { 577 return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile, 578 testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps, 579 testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext); 580 } 581 582 private boolean record(PackageDexUsage packageDexUsage, TestData testData, Set<String> users) { 583 boolean result = true; 584 for (String user : users) { 585 result = result && packageDexUsage.record(testData.mPackageName, testData.mDexFile, 586 testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps, 587 testData.mPrimaryOrSplit, user, testData.mClassLoaderContext); 588 } 589 return result; 590 } 591 592 private void writeAndReadBack() { 593 mPackageDexUsage = writeAndReadBack(mPackageDexUsage); 594 } 595 596 private PackageDexUsage writeAndReadBack(PackageDexUsage packageDexUsage) { 597 try { 598 StringWriter writer = new StringWriter(); 599 packageDexUsage.write(writer); 600 601 PackageDexUsage newPackageDexUsage = new PackageDexUsage(); 602 newPackageDexUsage.read(new StringReader(writer.toString())); 603 return newPackageDexUsage; 604 } catch (IOException e) { 605 fail("Unexpected IOException: " + e.getMessage()); 606 return null; 607 } 608 } 609 610 private static class TestData { 611 private final String mPackageName; 612 private final String mDexFile; 613 private final int mOwnerUserId; 614 private final String mLoaderIsa; 615 private final boolean mUsedByOtherApps; 616 private final boolean mPrimaryOrSplit; 617 private final String mUsedBy; 618 private final String mClassLoaderContext; 619 620 private TestData(String packageName, String dexFile, int ownerUserId, 621 String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit, String usedBy) { 622 this(packageName, dexFile, ownerUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit, 623 usedBy, "DefaultClassLoaderContextFor_" + dexFile); 624 } 625 private TestData(String packageName, String dexFile, int ownerUserId, 626 String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit, String usedBy, 627 String classLoaderContext) { 628 mPackageName = packageName; 629 mDexFile = dexFile; 630 mOwnerUserId = ownerUserId; 631 mLoaderIsa = loaderIsa; 632 mUsedByOtherApps = isUsedByOtherApps; 633 mPrimaryOrSplit = primaryOrSplit; 634 mUsedBy = usedBy; 635 mClassLoaderContext = classLoaderContext; 636 } 637 638 private TestData updateClassLoaderContext(String newContext) { 639 return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa, mUsedByOtherApps, 640 mPrimaryOrSplit, mUsedBy, newContext); 641 } 642 643 private TestData updateUseByOthers(boolean newUsedByOthers) { 644 return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa, newUsedByOthers, 645 mPrimaryOrSplit, mUsedBy, mClassLoaderContext); 646 } 647 } 648 } 649