1// Copyright 2017 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "fmt" 19 "path/filepath" 20 "reflect" 21 "regexp" 22 "sort" 23 "strings" 24 "testing" 25 26 "github.com/google/blueprint/proptools" 27 28 "android/soong/android" 29 "android/soong/cc" 30) 31 32var ( 33 resourceFiles = []string{ 34 "res/layout/layout.xml", 35 "res/values/strings.xml", 36 "res/values-en-rUS/strings.xml", 37 } 38 39 compiledResourceFiles = []string{ 40 "aapt2/res/layout_layout.xml.flat", 41 "aapt2/res/values_strings.arsc.flat", 42 "aapt2/res/values-en-rUS_strings.arsc.flat", 43 } 44) 45 46func testAppConfig(env map[string]string, bp string, fs map[string][]byte) android.Config { 47 appFS := map[string][]byte{} 48 for k, v := range fs { 49 appFS[k] = v 50 } 51 52 for _, file := range resourceFiles { 53 appFS[file] = nil 54 } 55 56 return testConfig(env, bp, appFS) 57} 58 59func testApp(t *testing.T, bp string) *android.TestContext { 60 config := testAppConfig(nil, bp, nil) 61 62 ctx := testContext() 63 64 run(t, ctx, config) 65 66 return ctx 67} 68 69func TestApp(t *testing.T) { 70 for _, moduleType := range []string{"android_app", "android_library"} { 71 t.Run(moduleType, func(t *testing.T) { 72 ctx := testApp(t, moduleType+` { 73 name: "foo", 74 srcs: ["a.java"], 75 sdk_version: "current" 76 } 77 `) 78 79 foo := ctx.ModuleForTests("foo", "android_common") 80 81 var expectedLinkImplicits []string 82 83 manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml") 84 expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String()) 85 86 frameworkRes := ctx.ModuleForTests("framework-res", "android_common") 87 expectedLinkImplicits = append(expectedLinkImplicits, 88 frameworkRes.Output("package-res.apk").Output.String()) 89 90 // Test the mapping from input files to compiled output file names 91 compile := foo.Output(compiledResourceFiles[0]) 92 if !reflect.DeepEqual(resourceFiles, compile.Inputs.Strings()) { 93 t.Errorf("expected aapt2 compile inputs expected:\n %#v\n got:\n %#v", 94 resourceFiles, compile.Inputs.Strings()) 95 } 96 97 compiledResourceOutputs := compile.Outputs.Strings() 98 sort.Strings(compiledResourceOutputs) 99 100 expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...) 101 102 list := foo.Output("aapt2/res.list") 103 expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String()) 104 105 // Check that the link rule uses 106 res := ctx.ModuleForTests("foo", "android_common").Output("package-res.apk") 107 if !reflect.DeepEqual(expectedLinkImplicits, res.Implicits.Strings()) { 108 t.Errorf("expected aapt2 link implicits expected:\n %#v\n got:\n %#v", 109 expectedLinkImplicits, res.Implicits.Strings()) 110 } 111 }) 112 } 113} 114 115func TestAppSplits(t *testing.T) { 116 ctx := testApp(t, ` 117 android_app { 118 name: "foo", 119 srcs: ["a.java"], 120 package_splits: ["v4", "v7,hdpi"], 121 sdk_version: "current" 122 }`) 123 124 foo := ctx.ModuleForTests("foo", "android_common") 125 126 expectedOutputs := []string{ 127 filepath.Join(buildDir, ".intermediates/foo/android_common/foo.apk"), 128 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v4.apk"), 129 filepath.Join(buildDir, ".intermediates/foo/android_common/foo_v7_hdpi.apk"), 130 } 131 for _, expectedOutput := range expectedOutputs { 132 foo.Output(expectedOutput) 133 } 134 135 outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("") 136 if err != nil { 137 t.Fatal(err) 138 } 139 if g, w := outputFiles.Strings(), expectedOutputs; !reflect.DeepEqual(g, w) { 140 t.Errorf(`want OutputFiles("") = %q, got %q`, w, g) 141 } 142} 143 144func TestAndroidAppSet(t *testing.T) { 145 ctx, config := testJava(t, ` 146 android_app_set { 147 name: "foo", 148 set: "prebuilts/apks/app.apks", 149 prerelease: true, 150 }`) 151 module := ctx.ModuleForTests("foo", "android_common") 152 const packedSplitApks = "foo.zip" 153 params := module.Output(packedSplitApks) 154 if params.Rule == nil { 155 t.Errorf("expected output %s is missing", packedSplitApks) 156 } 157 if s := params.Args["allow-prereleased"]; s != "true" { 158 t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s) 159 } 160 if s := params.Args["partition"]; s != "system" { 161 t.Errorf("wrong partition value: '%s', expected 'system'", s) 162 } 163 mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0] 164 actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"] 165 expectedMaster := []string{"foo.apk"} 166 if !reflect.DeepEqual(actualMaster, expectedMaster) { 167 t.Errorf("Unexpected LOCAL_APK_SET_MASTER_FILE value: '%s', expected: '%s',", 168 actualMaster, expectedMaster) 169 } 170} 171 172func TestAndroidAppSet_Variants(t *testing.T) { 173 bp := ` 174 android_app_set { 175 name: "foo", 176 set: "prebuilts/apks/app.apks", 177 }` 178 testCases := []struct { 179 name string 180 targets []android.Target 181 aaptPrebuiltDPI []string 182 sdkVersion int 183 expected map[string]string 184 }{ 185 { 186 name: "One", 187 targets: []android.Target{ 188 {Os: android.Android, Arch: android.Arch{ArchType: android.X86}}, 189 }, 190 aaptPrebuiltDPI: []string{"ldpi", "xxhdpi"}, 191 sdkVersion: 29, 192 expected: map[string]string{ 193 "abis": "X86", 194 "allow-prereleased": "false", 195 "screen-densities": "LDPI,XXHDPI", 196 "sdk-version": "29", 197 "stem": "foo", 198 }, 199 }, 200 { 201 name: "Two", 202 targets: []android.Target{ 203 {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64}}, 204 {Os: android.Android, Arch: android.Arch{ArchType: android.X86}}, 205 }, 206 aaptPrebuiltDPI: nil, 207 sdkVersion: 30, 208 expected: map[string]string{ 209 "abis": "X86_64,X86", 210 "allow-prereleased": "false", 211 "screen-densities": "all", 212 "sdk-version": "30", 213 "stem": "foo", 214 }, 215 }, 216 } 217 218 for _, test := range testCases { 219 config := testAppConfig(nil, bp, nil) 220 config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI 221 config.TestProductVariables.Platform_sdk_version = &test.sdkVersion 222 config.Targets[android.Android] = test.targets 223 ctx := testContext() 224 run(t, ctx, config) 225 module := ctx.ModuleForTests("foo", "android_common") 226 const packedSplitApks = "foo.zip" 227 params := module.Output(packedSplitApks) 228 for k, v := range test.expected { 229 if actual := params.Args[k]; actual != v { 230 t.Errorf("%s: bad build arg value for '%s': '%s', expected '%s'", 231 test.name, k, actual, v) 232 } 233 } 234 } 235} 236 237func TestPlatformAPIs(t *testing.T) { 238 testJava(t, ` 239 android_app { 240 name: "foo", 241 srcs: ["a.java"], 242 platform_apis: true, 243 } 244 `) 245 246 testJava(t, ` 247 android_app { 248 name: "foo", 249 srcs: ["a.java"], 250 sdk_version: "current", 251 } 252 `) 253 254 testJavaError(t, "platform_apis must be true when sdk_version is empty.", ` 255 android_app { 256 name: "bar", 257 srcs: ["b.java"], 258 } 259 `) 260 261 testJavaError(t, "platform_apis must be false when sdk_version is not empty.", ` 262 android_app { 263 name: "bar", 264 srcs: ["b.java"], 265 sdk_version: "system_current", 266 platform_apis: true, 267 } 268 `) 269} 270 271func TestAndroidAppLinkType(t *testing.T) { 272 testJava(t, ` 273 android_app { 274 name: "foo", 275 srcs: ["a.java"], 276 libs: ["bar"], 277 static_libs: ["baz"], 278 platform_apis: true, 279 } 280 281 java_library { 282 name: "bar", 283 sdk_version: "current", 284 srcs: ["b.java"], 285 } 286 287 android_library { 288 name: "baz", 289 sdk_version: "system_current", 290 srcs: ["c.java"], 291 } 292 `) 293 294 testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", ` 295 android_app { 296 name: "foo", 297 srcs: ["a.java"], 298 libs: ["bar"], 299 sdk_version: "current", 300 static_libs: ["baz"], 301 } 302 303 java_library { 304 name: "bar", 305 sdk_version: "current", 306 srcs: ["b.java"], 307 } 308 309 android_library { 310 name: "baz", 311 sdk_version: "system_current", 312 srcs: ["c.java"], 313 } 314 `) 315 316 testJava(t, ` 317 android_app { 318 name: "foo", 319 srcs: ["a.java"], 320 libs: ["bar"], 321 sdk_version: "system_current", 322 static_libs: ["baz"], 323 } 324 325 java_library { 326 name: "bar", 327 sdk_version: "current", 328 srcs: ["b.java"], 329 } 330 331 android_library { 332 name: "baz", 333 sdk_version: "system_current", 334 srcs: ["c.java"], 335 } 336 `) 337 338 testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", ` 339 android_app { 340 name: "foo", 341 srcs: ["a.java"], 342 libs: ["bar"], 343 sdk_version: "system_current", 344 static_libs: ["baz"], 345 } 346 347 java_library { 348 name: "bar", 349 sdk_version: "current", 350 srcs: ["b.java"], 351 } 352 353 android_library { 354 name: "baz", 355 srcs: ["c.java"], 356 } 357 `) 358} 359 360func TestUpdatableApps(t *testing.T) { 361 testCases := []struct { 362 name string 363 bp string 364 expectedError string 365 }{ 366 { 367 name: "Stable public SDK", 368 bp: `android_app { 369 name: "foo", 370 srcs: ["a.java"], 371 sdk_version: "29", 372 min_sdk_version: "29", 373 updatable: true, 374 }`, 375 }, 376 { 377 name: "Stable system SDK", 378 bp: `android_app { 379 name: "foo", 380 srcs: ["a.java"], 381 sdk_version: "system_29", 382 min_sdk_version: "29", 383 updatable: true, 384 }`, 385 }, 386 { 387 name: "Current public SDK", 388 bp: `android_app { 389 name: "foo", 390 srcs: ["a.java"], 391 sdk_version: "current", 392 min_sdk_version: "29", 393 updatable: true, 394 }`, 395 }, 396 { 397 name: "Current system SDK", 398 bp: `android_app { 399 name: "foo", 400 srcs: ["a.java"], 401 sdk_version: "system_current", 402 min_sdk_version: "29", 403 updatable: true, 404 }`, 405 }, 406 { 407 name: "Current module SDK", 408 bp: `android_app { 409 name: "foo", 410 srcs: ["a.java"], 411 sdk_version: "module_current", 412 min_sdk_version: "29", 413 updatable: true, 414 }`, 415 }, 416 { 417 name: "Current core SDK", 418 bp: `android_app { 419 name: "foo", 420 srcs: ["a.java"], 421 sdk_version: "core_current", 422 min_sdk_version: "29", 423 updatable: true, 424 }`, 425 }, 426 { 427 name: "No Platform APIs", 428 bp: `android_app { 429 name: "foo", 430 srcs: ["a.java"], 431 platform_apis: true, 432 min_sdk_version: "29", 433 updatable: true, 434 }`, 435 expectedError: "Updatable apps must use stable SDKs", 436 }, 437 { 438 name: "No Core Platform APIs", 439 bp: `android_app { 440 name: "foo", 441 srcs: ["a.java"], 442 sdk_version: "core_platform", 443 min_sdk_version: "29", 444 updatable: true, 445 }`, 446 expectedError: "Updatable apps must use stable SDKs", 447 }, 448 { 449 name: "No unspecified APIs", 450 bp: `android_app { 451 name: "foo", 452 srcs: ["a.java"], 453 updatable: true, 454 min_sdk_version: "29", 455 }`, 456 expectedError: "Updatable apps must use stable SDK", 457 }, 458 { 459 name: "Must specify min_sdk_version", 460 bp: `android_app { 461 name: "app_without_min_sdk_version", 462 srcs: ["a.java"], 463 sdk_version: "29", 464 updatable: true, 465 }`, 466 expectedError: "updatable apps must set min_sdk_version.", 467 }, 468 } 469 470 for _, test := range testCases { 471 t.Run(test.name, func(t *testing.T) { 472 if test.expectedError == "" { 473 testJava(t, test.bp) 474 } else { 475 testJavaError(t, test.expectedError, test.bp) 476 } 477 }) 478 } 479} 480 481func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { 482 testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` 483 android_app { 484 name: "foo", 485 srcs: ["a.java"], 486 updatable: true, 487 sdk_version: "current", 488 min_sdk_version: "current", 489 jni_libs: ["libjni"], 490 } 491 492 cc_library { 493 name: "libjni", 494 stl: "none", 495 system_shared_libs: [], 496 sdk_version: "current", 497 } 498 `) 499} 500 501func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { 502 bp := cc.GatherRequiredDepsForTest(android.Android) + ` 503 android_app { 504 name: "foo", 505 srcs: ["a.java"], 506 updatable: true, 507 sdk_version: "current", 508 min_sdk_version: "29", 509 jni_libs: ["libjni"], 510 } 511 512 cc_library { 513 name: "libjni", 514 stl: "none", 515 system_shared_libs: [], 516 sdk_version: "29", 517 } 518 519 ndk_prebuilt_object { 520 name: "ndk_crtbegin_so.29", 521 sdk_version: "29", 522 } 523 524 ndk_prebuilt_object { 525 name: "ndk_crtend_so.29", 526 sdk_version: "29", 527 } 528 ` 529 fs := map[string][]byte{ 530 "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil, 531 "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil, 532 "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil, 533 "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil, 534 } 535 536 ctx, _ := testJavaWithConfig(t, testConfig(nil, bp, fs)) 537 538 inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits 539 var crtbeginFound, crtendFound bool 540 for _, input := range inputs { 541 switch input.String() { 542 case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": 543 crtbeginFound = true 544 case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": 545 crtendFound = true 546 } 547 } 548 if !crtbeginFound || !crtendFound { 549 t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29") 550 } 551} 552 553func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { 554 bp := cc.GatherRequiredDepsForTest(android.Android) + ` 555 android_app { 556 name: "foo", 557 srcs: ["a.java"], 558 updatable: true, 559 sdk_version: "current", 560 min_sdk_version: "29", // this APK should support 29 561 jni_libs: ["libjni"], 562 } 563 564 cc_library { 565 name: "libjni", 566 stl: "none", 567 sdk_version: "current", 568 } 569 ` 570 testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp) 571} 572 573func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) { 574 bp := cc.GatherRequiredDepsForTest(android.Android) + ` 575 android_app { 576 name: "foo", 577 srcs: ["a.java"], 578 updatable: true, 579 sdk_version: "current", 580 min_sdk_version: "29", // this APK should support 29 581 jni_libs: ["libjni"], 582 } 583 584 cc_library { 585 name: "libjni", 586 stl: "none", 587 shared_libs: ["libbar"], 588 system_shared_libs: [], 589 sdk_version: "27", 590 } 591 592 cc_library { 593 name: "libbar", 594 stl: "none", 595 system_shared_libs: [], 596 sdk_version: "current", 597 } 598 ` 599 testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp) 600} 601 602func TestResourceDirs(t *testing.T) { 603 testCases := []struct { 604 name string 605 prop string 606 resources []string 607 }{ 608 { 609 name: "no resource_dirs", 610 prop: "", 611 resources: []string{"res/res/values/strings.xml"}, 612 }, 613 { 614 name: "resource_dirs", 615 prop: `resource_dirs: ["res"]`, 616 resources: []string{"res/res/values/strings.xml"}, 617 }, 618 { 619 name: "empty resource_dirs", 620 prop: `resource_dirs: []`, 621 resources: nil, 622 }, 623 } 624 625 fs := map[string][]byte{ 626 "res/res/values/strings.xml": nil, 627 } 628 629 bp := ` 630 android_app { 631 name: "foo", 632 sdk_version: "current", 633 %s 634 } 635 ` 636 637 for _, testCase := range testCases { 638 t.Run(testCase.name, func(t *testing.T) { 639 config := testConfig(nil, fmt.Sprintf(bp, testCase.prop), fs) 640 ctx := testContext() 641 run(t, ctx, config) 642 643 module := ctx.ModuleForTests("foo", "android_common") 644 resourceList := module.MaybeOutput("aapt2/res.list") 645 646 var resources []string 647 if resourceList.Rule != nil { 648 for _, compiledResource := range resourceList.Inputs.Strings() { 649 resources = append(resources, module.Output(compiledResource).Inputs.Strings()...) 650 } 651 } 652 653 if !reflect.DeepEqual(resources, testCase.resources) { 654 t.Errorf("expected resource files %q, got %q", 655 testCase.resources, resources) 656 } 657 }) 658 } 659} 660 661func TestLibraryAssets(t *testing.T) { 662 bp := ` 663 android_app { 664 name: "foo", 665 sdk_version: "current", 666 static_libs: ["lib1", "lib2", "lib3"], 667 } 668 669 android_library { 670 name: "lib1", 671 sdk_version: "current", 672 asset_dirs: ["assets_a"], 673 } 674 675 android_library { 676 name: "lib2", 677 sdk_version: "current", 678 } 679 680 android_library { 681 name: "lib3", 682 sdk_version: "current", 683 static_libs: ["lib4"], 684 } 685 686 android_library { 687 name: "lib4", 688 sdk_version: "current", 689 asset_dirs: ["assets_b"], 690 } 691 ` 692 693 testCases := []struct { 694 name string 695 assetFlag string 696 assetPackages []string 697 }{ 698 { 699 name: "foo", 700 // lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively. 701 assetPackages: []string{ 702 buildDir + "/.intermediates/foo/android_common/aapt2/package-res.apk", 703 buildDir + "/.intermediates/lib1/android_common/assets.zip", 704 buildDir + "/.intermediates/lib3/android_common/assets.zip", 705 }, 706 }, 707 { 708 name: "lib1", 709 assetFlag: "-A assets_a", 710 }, 711 { 712 name: "lib2", 713 }, 714 { 715 name: "lib3", 716 assetPackages: []string{ 717 buildDir + "/.intermediates/lib3/android_common/aapt2/package-res.apk", 718 buildDir + "/.intermediates/lib4/android_common/assets.zip", 719 }, 720 }, 721 { 722 name: "lib4", 723 assetFlag: "-A assets_b", 724 }, 725 } 726 ctx := testApp(t, bp) 727 728 for _, test := range testCases { 729 t.Run(test.name, func(t *testing.T) { 730 m := ctx.ModuleForTests(test.name, "android_common") 731 732 // Check asset flag in aapt2 link flags 733 var aapt2link android.TestingBuildParams 734 if len(test.assetPackages) > 0 { 735 aapt2link = m.Output("aapt2/package-res.apk") 736 } else { 737 aapt2link = m.Output("package-res.apk") 738 } 739 aapt2Flags := aapt2link.Args["flags"] 740 if test.assetFlag != "" { 741 if !strings.Contains(aapt2Flags, test.assetFlag) { 742 t.Errorf("Can't find asset flag %q in aapt2 link flags %q", test.assetFlag, aapt2Flags) 743 } 744 } else { 745 if strings.Contains(aapt2Flags, " -A ") { 746 t.Errorf("aapt2 link flags %q contain unexpected asset flag", aapt2Flags) 747 } 748 } 749 750 // Check asset merge rule. 751 if len(test.assetPackages) > 0 { 752 mergeAssets := m.Output("package-res.apk") 753 if !reflect.DeepEqual(test.assetPackages, mergeAssets.Inputs.Strings()) { 754 t.Errorf("Unexpected mergeAssets inputs: %v, expected: %v", 755 mergeAssets.Inputs.Strings(), test.assetPackages) 756 } 757 } 758 }) 759 } 760} 761 762func TestAndroidResources(t *testing.T) { 763 testCases := []struct { 764 name string 765 enforceRROTargets []string 766 enforceRROExcludedOverlays []string 767 resourceFiles map[string][]string 768 overlayFiles map[string][]string 769 rroDirs map[string][]string 770 }{ 771 { 772 name: "no RRO", 773 enforceRROTargets: nil, 774 enforceRROExcludedOverlays: nil, 775 resourceFiles: map[string][]string{ 776 "foo": nil, 777 "bar": {"bar/res/res/values/strings.xml"}, 778 "lib": nil, 779 "lib2": {"lib2/res/res/values/strings.xml"}, 780 }, 781 overlayFiles: map[string][]string{ 782 "foo": { 783 buildDir + "/.intermediates/lib2/android_common/package-res.apk", 784 buildDir + "/.intermediates/lib/android_common/package-res.apk", 785 buildDir + "/.intermediates/lib3/android_common/package-res.apk", 786 "foo/res/res/values/strings.xml", 787 "device/vendor/blah/static_overlay/foo/res/values/strings.xml", 788 "device/vendor/blah/overlay/foo/res/values/strings.xml", 789 "product/vendor/blah/overlay/foo/res/values/strings.xml", 790 }, 791 "bar": { 792 "device/vendor/blah/static_overlay/bar/res/values/strings.xml", 793 "device/vendor/blah/overlay/bar/res/values/strings.xml", 794 }, 795 "lib": { 796 buildDir + "/.intermediates/lib2/android_common/package-res.apk", 797 "lib/res/res/values/strings.xml", 798 "device/vendor/blah/overlay/lib/res/values/strings.xml", 799 }, 800 }, 801 rroDirs: map[string][]string{ 802 "foo": nil, 803 "bar": nil, 804 }, 805 }, 806 { 807 name: "enforce RRO on foo", 808 enforceRROTargets: []string{"foo"}, 809 enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"}, 810 resourceFiles: map[string][]string{ 811 "foo": nil, 812 "bar": {"bar/res/res/values/strings.xml"}, 813 "lib": nil, 814 "lib2": {"lib2/res/res/values/strings.xml"}, 815 }, 816 overlayFiles: map[string][]string{ 817 "foo": { 818 buildDir + "/.intermediates/lib2/android_common/package-res.apk", 819 buildDir + "/.intermediates/lib/android_common/package-res.apk", 820 buildDir + "/.intermediates/lib3/android_common/package-res.apk", 821 "foo/res/res/values/strings.xml", 822 "device/vendor/blah/static_overlay/foo/res/values/strings.xml", 823 }, 824 "bar": { 825 "device/vendor/blah/static_overlay/bar/res/values/strings.xml", 826 "device/vendor/blah/overlay/bar/res/values/strings.xml", 827 }, 828 "lib": { 829 buildDir + "/.intermediates/lib2/android_common/package-res.apk", 830 "lib/res/res/values/strings.xml", 831 "device/vendor/blah/overlay/lib/res/values/strings.xml", 832 }, 833 }, 834 835 rroDirs: map[string][]string{ 836 "foo": { 837 "device:device/vendor/blah/overlay/foo/res", 838 // Enforce RRO on "foo" could imply RRO on static dependencies, but for now it doesn't. 839 // "device/vendor/blah/overlay/lib/res", 840 "product:product/vendor/blah/overlay/foo/res", 841 }, 842 "bar": nil, 843 "lib": nil, 844 }, 845 }, 846 { 847 name: "enforce RRO on all", 848 enforceRROTargets: []string{"*"}, 849 enforceRROExcludedOverlays: []string{ 850 // Excluding specific apps/res directories also allowed. 851 "device/vendor/blah/static_overlay/foo", 852 "device/vendor/blah/static_overlay/bar/res", 853 }, 854 resourceFiles: map[string][]string{ 855 "foo": nil, 856 "bar": {"bar/res/res/values/strings.xml"}, 857 "lib": nil, 858 "lib2": {"lib2/res/res/values/strings.xml"}, 859 }, 860 overlayFiles: map[string][]string{ 861 "foo": { 862 buildDir + "/.intermediates/lib2/android_common/package-res.apk", 863 buildDir + "/.intermediates/lib/android_common/package-res.apk", 864 buildDir + "/.intermediates/lib3/android_common/package-res.apk", 865 "foo/res/res/values/strings.xml", 866 "device/vendor/blah/static_overlay/foo/res/values/strings.xml", 867 }, 868 "bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"}, 869 "lib": { 870 buildDir + "/.intermediates/lib2/android_common/package-res.apk", 871 "lib/res/res/values/strings.xml", 872 }, 873 }, 874 rroDirs: map[string][]string{ 875 "foo": { 876 "device:device/vendor/blah/overlay/foo/res", 877 "product:product/vendor/blah/overlay/foo/res", 878 // Lib dep comes after the direct deps 879 "device:device/vendor/blah/overlay/lib/res", 880 }, 881 "bar": {"device:device/vendor/blah/overlay/bar/res"}, 882 "lib": {"device:device/vendor/blah/overlay/lib/res"}, 883 }, 884 }, 885 } 886 887 deviceResourceOverlays := []string{ 888 "device/vendor/blah/overlay", 889 "device/vendor/blah/overlay2", 890 "device/vendor/blah/static_overlay", 891 } 892 893 productResourceOverlays := []string{ 894 "product/vendor/blah/overlay", 895 } 896 897 fs := map[string][]byte{ 898 "foo/res/res/values/strings.xml": nil, 899 "bar/res/res/values/strings.xml": nil, 900 "lib/res/res/values/strings.xml": nil, 901 "lib2/res/res/values/strings.xml": nil, 902 "device/vendor/blah/overlay/foo/res/values/strings.xml": nil, 903 "device/vendor/blah/overlay/bar/res/values/strings.xml": nil, 904 "device/vendor/blah/overlay/lib/res/values/strings.xml": nil, 905 "device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil, 906 "device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil, 907 "device/vendor/blah/overlay2/res/values/strings.xml": nil, 908 "product/vendor/blah/overlay/foo/res/values/strings.xml": nil, 909 } 910 911 bp := ` 912 android_app { 913 name: "foo", 914 sdk_version: "current", 915 resource_dirs: ["foo/res"], 916 static_libs: ["lib", "lib3"], 917 } 918 919 android_app { 920 name: "bar", 921 sdk_version: "current", 922 resource_dirs: ["bar/res"], 923 } 924 925 android_library { 926 name: "lib", 927 sdk_version: "current", 928 resource_dirs: ["lib/res"], 929 static_libs: ["lib2"], 930 } 931 932 android_library { 933 name: "lib2", 934 sdk_version: "current", 935 resource_dirs: ["lib2/res"], 936 } 937 938 // This library has the same resources as lib (should not lead to dupe RROs) 939 android_library { 940 name: "lib3", 941 sdk_version: "current", 942 resource_dirs: ["lib/res"] 943 } 944 ` 945 946 for _, testCase := range testCases { 947 t.Run(testCase.name, func(t *testing.T) { 948 config := testAppConfig(nil, bp, fs) 949 config.TestProductVariables.DeviceResourceOverlays = deviceResourceOverlays 950 config.TestProductVariables.ProductResourceOverlays = productResourceOverlays 951 if testCase.enforceRROTargets != nil { 952 config.TestProductVariables.EnforceRROTargets = testCase.enforceRROTargets 953 } 954 if testCase.enforceRROExcludedOverlays != nil { 955 config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays 956 } 957 958 ctx := testContext() 959 run(t, ctx, config) 960 961 resourceListToFiles := func(module android.TestingModule, list []string) (files []string) { 962 for _, o := range list { 963 res := module.MaybeOutput(o) 964 if res.Rule != nil { 965 // If the overlay is compiled as part of this module (i.e. a .arsc.flat file), 966 // verify the inputs to the .arsc.flat rule. 967 files = append(files, res.Inputs.Strings()...) 968 } else { 969 // Otherwise, verify the full path to the output of the other module 970 files = append(files, o) 971 } 972 } 973 return files 974 } 975 976 getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) { 977 module := ctx.ModuleForTests(moduleName, "android_common") 978 resourceList := module.MaybeOutput("aapt2/res.list") 979 if resourceList.Rule != nil { 980 resourceFiles = resourceListToFiles(module, resourceList.Inputs.Strings()) 981 } 982 overlayList := module.MaybeOutput("aapt2/overlay.list") 983 if overlayList.Rule != nil { 984 overlayFiles = resourceListToFiles(module, overlayList.Inputs.Strings()) 985 } 986 987 for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() { 988 var prefix string 989 if d.overlayType == device { 990 prefix = "device:" 991 } else if d.overlayType == product { 992 prefix = "product:" 993 } else { 994 t.Fatalf("Unexpected overlayType %d", d.overlayType) 995 } 996 rroDirs = append(rroDirs, prefix+d.path.String()) 997 } 998 999 return resourceFiles, overlayFiles, rroDirs 1000 } 1001 1002 modules := []string{"foo", "bar", "lib", "lib2"} 1003 for _, module := range modules { 1004 resourceFiles, overlayFiles, rroDirs := getResources(module) 1005 1006 if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) { 1007 t.Errorf("expected %s resource files:\n %#v\n got:\n %#v", 1008 module, testCase.resourceFiles[module], resourceFiles) 1009 } 1010 if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) { 1011 t.Errorf("expected %s overlay files:\n %#v\n got:\n %#v", 1012 module, testCase.overlayFiles[module], overlayFiles) 1013 } 1014 if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) { 1015 t.Errorf("expected %s rroDirs: %#v\n got:\n %#v", 1016 module, testCase.rroDirs[module], rroDirs) 1017 } 1018 } 1019 }) 1020 } 1021} 1022 1023func TestAppSdkVersion(t *testing.T) { 1024 testCases := []struct { 1025 name string 1026 sdkVersion string 1027 platformSdkInt int 1028 platformSdkCodename string 1029 platformSdkFinal bool 1030 expectedMinSdkVersion string 1031 platformApis bool 1032 }{ 1033 { 1034 name: "current final SDK", 1035 sdkVersion: "current", 1036 platformSdkInt: 27, 1037 platformSdkCodename: "REL", 1038 platformSdkFinal: true, 1039 expectedMinSdkVersion: "27", 1040 }, 1041 { 1042 name: "current non-final SDK", 1043 sdkVersion: "current", 1044 platformSdkInt: 27, 1045 platformSdkCodename: "OMR1", 1046 platformSdkFinal: false, 1047 expectedMinSdkVersion: "OMR1", 1048 }, 1049 { 1050 name: "default final SDK", 1051 sdkVersion: "", 1052 platformApis: true, 1053 platformSdkInt: 27, 1054 platformSdkCodename: "REL", 1055 platformSdkFinal: true, 1056 expectedMinSdkVersion: "27", 1057 }, 1058 { 1059 name: "default non-final SDK", 1060 sdkVersion: "", 1061 platformApis: true, 1062 platformSdkInt: 27, 1063 platformSdkCodename: "OMR1", 1064 platformSdkFinal: false, 1065 expectedMinSdkVersion: "OMR1", 1066 }, 1067 { 1068 name: "14", 1069 sdkVersion: "14", 1070 expectedMinSdkVersion: "14", 1071 }, 1072 } 1073 1074 for _, moduleType := range []string{"android_app", "android_library"} { 1075 for _, test := range testCases { 1076 t.Run(moduleType+" "+test.name, func(t *testing.T) { 1077 platformApiProp := "" 1078 if test.platformApis { 1079 platformApiProp = "platform_apis: true," 1080 } 1081 bp := fmt.Sprintf(`%s { 1082 name: "foo", 1083 srcs: ["a.java"], 1084 sdk_version: "%s", 1085 %s 1086 }`, moduleType, test.sdkVersion, platformApiProp) 1087 1088 config := testAppConfig(nil, bp, nil) 1089 config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt 1090 config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename 1091 config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal 1092 1093 ctx := testContext() 1094 1095 run(t, ctx, config) 1096 1097 foo := ctx.ModuleForTests("foo", "android_common") 1098 link := foo.Output("package-res.apk") 1099 linkFlags := strings.Split(link.Args["flags"], " ") 1100 min := android.IndexList("--min-sdk-version", linkFlags) 1101 target := android.IndexList("--target-sdk-version", linkFlags) 1102 1103 if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 { 1104 t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags) 1105 } 1106 1107 gotMinSdkVersion := linkFlags[min+1] 1108 gotTargetSdkVersion := linkFlags[target+1] 1109 1110 if gotMinSdkVersion != test.expectedMinSdkVersion { 1111 t.Errorf("incorrect --min-sdk-version, expected %q got %q", 1112 test.expectedMinSdkVersion, gotMinSdkVersion) 1113 } 1114 1115 if gotTargetSdkVersion != test.expectedMinSdkVersion { 1116 t.Errorf("incorrect --target-sdk-version, expected %q got %q", 1117 test.expectedMinSdkVersion, gotTargetSdkVersion) 1118 } 1119 }) 1120 } 1121 } 1122} 1123 1124func TestJNIABI(t *testing.T) { 1125 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` 1126 cc_library { 1127 name: "libjni", 1128 system_shared_libs: [], 1129 sdk_version: "current", 1130 stl: "none", 1131 } 1132 1133 android_test { 1134 name: "test", 1135 sdk_version: "core_platform", 1136 jni_libs: ["libjni"], 1137 } 1138 1139 android_test { 1140 name: "test_first", 1141 sdk_version: "core_platform", 1142 compile_multilib: "first", 1143 jni_libs: ["libjni"], 1144 } 1145 1146 android_test { 1147 name: "test_both", 1148 sdk_version: "core_platform", 1149 compile_multilib: "both", 1150 jni_libs: ["libjni"], 1151 } 1152 1153 android_test { 1154 name: "test_32", 1155 sdk_version: "core_platform", 1156 compile_multilib: "32", 1157 jni_libs: ["libjni"], 1158 } 1159 1160 android_test { 1161 name: "test_64", 1162 sdk_version: "core_platform", 1163 compile_multilib: "64", 1164 jni_libs: ["libjni"], 1165 } 1166 `) 1167 1168 testCases := []struct { 1169 name string 1170 abis []string 1171 }{ 1172 {"test", []string{"arm64-v8a"}}, 1173 {"test_first", []string{"arm64-v8a"}}, 1174 {"test_both", []string{"arm64-v8a", "armeabi-v7a"}}, 1175 {"test_32", []string{"armeabi-v7a"}}, 1176 {"test_64", []string{"arm64-v8a"}}, 1177 } 1178 1179 for _, test := range testCases { 1180 t.Run(test.name, func(t *testing.T) { 1181 app := ctx.ModuleForTests(test.name, "android_common") 1182 jniLibZip := app.Output("jnilibs.zip") 1183 var abis []string 1184 args := strings.Fields(jniLibZip.Args["jarArgs"]) 1185 for i := 0; i < len(args); i++ { 1186 if args[i] == "-P" { 1187 abis = append(abis, filepath.Base(args[i+1])) 1188 i++ 1189 } 1190 } 1191 if !reflect.DeepEqual(abis, test.abis) { 1192 t.Errorf("want abis %v, got %v", test.abis, abis) 1193 } 1194 }) 1195 } 1196} 1197 1198func TestAppSdkVersionByPartition(t *testing.T) { 1199 testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", ` 1200 android_app { 1201 name: "foo", 1202 srcs: ["a.java"], 1203 vendor: true, 1204 platform_apis: true, 1205 } 1206 `) 1207 1208 testJava(t, ` 1209 android_app { 1210 name: "bar", 1211 srcs: ["b.java"], 1212 platform_apis: true, 1213 } 1214 `) 1215 1216 for _, enforce := range []bool{true, false} { 1217 bp := ` 1218 android_app { 1219 name: "foo", 1220 srcs: ["a.java"], 1221 product_specific: true, 1222 platform_apis: true, 1223 } 1224 ` 1225 1226 config := testAppConfig(nil, bp, nil) 1227 config.TestProductVariables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce) 1228 if enforce { 1229 testJavaErrorWithConfig(t, "sdk_version must have a value when the module is located at vendor or product", config) 1230 } else { 1231 testJavaWithConfig(t, config) 1232 } 1233 } 1234} 1235 1236func TestJNIPackaging(t *testing.T) { 1237 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` 1238 cc_library { 1239 name: "libjni", 1240 system_shared_libs: [], 1241 stl: "none", 1242 sdk_version: "current", 1243 } 1244 1245 android_app { 1246 name: "app", 1247 jni_libs: ["libjni"], 1248 sdk_version: "current", 1249 } 1250 1251 android_app { 1252 name: "app_noembed", 1253 jni_libs: ["libjni"], 1254 use_embedded_native_libs: false, 1255 sdk_version: "current", 1256 } 1257 1258 android_app { 1259 name: "app_embed", 1260 jni_libs: ["libjni"], 1261 use_embedded_native_libs: true, 1262 sdk_version: "current", 1263 } 1264 1265 android_test { 1266 name: "test", 1267 sdk_version: "current", 1268 jni_libs: ["libjni"], 1269 } 1270 1271 android_test { 1272 name: "test_noembed", 1273 sdk_version: "current", 1274 jni_libs: ["libjni"], 1275 use_embedded_native_libs: false, 1276 } 1277 1278 android_test_helper_app { 1279 name: "test_helper", 1280 sdk_version: "current", 1281 jni_libs: ["libjni"], 1282 } 1283 1284 android_test_helper_app { 1285 name: "test_helper_noembed", 1286 sdk_version: "current", 1287 jni_libs: ["libjni"], 1288 use_embedded_native_libs: false, 1289 } 1290 `) 1291 1292 testCases := []struct { 1293 name string 1294 packaged bool 1295 compressed bool 1296 }{ 1297 {"app", false, false}, 1298 {"app_noembed", false, false}, 1299 {"app_embed", true, false}, 1300 {"test", true, false}, 1301 {"test_noembed", true, true}, 1302 {"test_helper", true, false}, 1303 {"test_helper_noembed", true, true}, 1304 } 1305 1306 for _, test := range testCases { 1307 t.Run(test.name, func(t *testing.T) { 1308 app := ctx.ModuleForTests(test.name, "android_common") 1309 jniLibZip := app.MaybeOutput("jnilibs.zip") 1310 if g, w := (jniLibZip.Rule != nil), test.packaged; g != w { 1311 t.Errorf("expected jni packaged %v, got %v", w, g) 1312 } 1313 1314 if jniLibZip.Rule != nil { 1315 if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w { 1316 t.Errorf("expected jni compressed %v, got %v", w, g) 1317 } 1318 1319 if !strings.Contains(jniLibZip.Implicits[0].String(), "_sdk_") { 1320 t.Errorf("expected input %q to use sdk variant", jniLibZip.Implicits[0].String()) 1321 } 1322 } 1323 }) 1324 } 1325} 1326 1327func TestJNISDK(t *testing.T) { 1328 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` 1329 cc_library { 1330 name: "libjni", 1331 system_shared_libs: [], 1332 stl: "none", 1333 sdk_version: "current", 1334 } 1335 1336 android_test { 1337 name: "app_platform", 1338 jni_libs: ["libjni"], 1339 platform_apis: true, 1340 } 1341 1342 android_test { 1343 name: "app_sdk", 1344 jni_libs: ["libjni"], 1345 sdk_version: "current", 1346 } 1347 1348 android_test { 1349 name: "app_force_platform", 1350 jni_libs: ["libjni"], 1351 sdk_version: "current", 1352 jni_uses_platform_apis: true, 1353 } 1354 1355 android_test { 1356 name: "app_force_sdk", 1357 jni_libs: ["libjni"], 1358 platform_apis: true, 1359 jni_uses_sdk_apis: true, 1360 } 1361 1362 cc_library { 1363 name: "libvendorjni", 1364 system_shared_libs: [], 1365 stl: "none", 1366 vendor: true, 1367 } 1368 1369 android_test { 1370 name: "app_vendor", 1371 jni_libs: ["libvendorjni"], 1372 sdk_version: "current", 1373 vendor: true, 1374 } 1375 `) 1376 1377 testCases := []struct { 1378 name string 1379 sdkJNI bool 1380 vendorJNI bool 1381 }{ 1382 {name: "app_platform"}, 1383 {name: "app_sdk", sdkJNI: true}, 1384 {name: "app_force_platform"}, 1385 {name: "app_force_sdk", sdkJNI: true}, 1386 {name: "app_vendor", vendorJNI: true}, 1387 } 1388 1389 platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). 1390 Output("libjni.so").Output.String() 1391 sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). 1392 Output("libjni.so").Output.String() 1393 vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared"). 1394 Output("libvendorjni.so").Output.String() 1395 1396 for _, test := range testCases { 1397 t.Run(test.name, func(t *testing.T) { 1398 app := ctx.ModuleForTests(test.name, "android_common") 1399 1400 jniLibZip := app.MaybeOutput("jnilibs.zip") 1401 if len(jniLibZip.Implicits) != 1 { 1402 t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings()) 1403 } 1404 gotJNI := jniLibZip.Implicits[0].String() 1405 1406 if test.sdkJNI { 1407 if gotJNI != sdkJNI { 1408 t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI) 1409 } 1410 } else if test.vendorJNI { 1411 if gotJNI != vendorJNI { 1412 t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI) 1413 } 1414 } else { 1415 if gotJNI != platformJNI { 1416 t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI) 1417 } 1418 } 1419 }) 1420 } 1421 1422 t.Run("jni_uses_platform_apis_error", func(t *testing.T) { 1423 testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, ` 1424 android_test { 1425 name: "app_platform", 1426 platform_apis: true, 1427 jni_uses_platform_apis: true, 1428 } 1429 `) 1430 }) 1431 1432 t.Run("jni_uses_sdk_apis_error", func(t *testing.T) { 1433 testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, ` 1434 android_test { 1435 name: "app_sdk", 1436 sdk_version: "current", 1437 jni_uses_sdk_apis: true, 1438 } 1439 `) 1440 }) 1441 1442} 1443 1444func TestCertificates(t *testing.T) { 1445 testCases := []struct { 1446 name string 1447 bp string 1448 certificateOverride string 1449 expectedLineage string 1450 expectedCertificate string 1451 }{ 1452 { 1453 name: "default", 1454 bp: ` 1455 android_app { 1456 name: "foo", 1457 srcs: ["a.java"], 1458 sdk_version: "current", 1459 } 1460 `, 1461 certificateOverride: "", 1462 expectedLineage: "", 1463 expectedCertificate: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8", 1464 }, 1465 { 1466 name: "module certificate property", 1467 bp: ` 1468 android_app { 1469 name: "foo", 1470 srcs: ["a.java"], 1471 certificate: ":new_certificate", 1472 sdk_version: "current", 1473 } 1474 1475 android_app_certificate { 1476 name: "new_certificate", 1477 certificate: "cert/new_cert", 1478 } 1479 `, 1480 certificateOverride: "", 1481 expectedLineage: "", 1482 expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", 1483 }, 1484 { 1485 name: "path certificate property", 1486 bp: ` 1487 android_app { 1488 name: "foo", 1489 srcs: ["a.java"], 1490 certificate: "expiredkey", 1491 sdk_version: "current", 1492 } 1493 `, 1494 certificateOverride: "", 1495 expectedLineage: "", 1496 expectedCertificate: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", 1497 }, 1498 { 1499 name: "certificate overrides", 1500 bp: ` 1501 android_app { 1502 name: "foo", 1503 srcs: ["a.java"], 1504 certificate: "expiredkey", 1505 sdk_version: "current", 1506 } 1507 1508 android_app_certificate { 1509 name: "new_certificate", 1510 certificate: "cert/new_cert", 1511 } 1512 `, 1513 certificateOverride: "foo:new_certificate", 1514 expectedLineage: "", 1515 expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", 1516 }, 1517 { 1518 name: "certificate lineage", 1519 bp: ` 1520 android_app { 1521 name: "foo", 1522 srcs: ["a.java"], 1523 certificate: ":new_certificate", 1524 lineage: "lineage.bin", 1525 sdk_version: "current", 1526 } 1527 1528 android_app_certificate { 1529 name: "new_certificate", 1530 certificate: "cert/new_cert", 1531 } 1532 `, 1533 certificateOverride: "", 1534 expectedLineage: "--lineage lineage.bin", 1535 expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8", 1536 }, 1537 } 1538 1539 for _, test := range testCases { 1540 t.Run(test.name, func(t *testing.T) { 1541 config := testAppConfig(nil, test.bp, nil) 1542 if test.certificateOverride != "" { 1543 config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride} 1544 } 1545 ctx := testContext() 1546 1547 run(t, ctx, config) 1548 foo := ctx.ModuleForTests("foo", "android_common") 1549 1550 signapk := foo.Output("foo.apk") 1551 signCertificateFlags := signapk.Args["certificates"] 1552 if test.expectedCertificate != signCertificateFlags { 1553 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedCertificate, signCertificateFlags) 1554 } 1555 1556 signFlags := signapk.Args["flags"] 1557 if test.expectedLineage != signFlags { 1558 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expectedLineage, signFlags) 1559 } 1560 }) 1561 } 1562} 1563 1564func TestRequestV4SigningFlag(t *testing.T) { 1565 testCases := []struct { 1566 name string 1567 bp string 1568 expected string 1569 }{ 1570 { 1571 name: "default", 1572 bp: ` 1573 android_app { 1574 name: "foo", 1575 srcs: ["a.java"], 1576 sdk_version: "current", 1577 } 1578 `, 1579 expected: "", 1580 }, 1581 { 1582 name: "default", 1583 bp: ` 1584 android_app { 1585 name: "foo", 1586 srcs: ["a.java"], 1587 sdk_version: "current", 1588 v4_signature: false, 1589 } 1590 `, 1591 expected: "", 1592 }, 1593 { 1594 name: "module certificate property", 1595 bp: ` 1596 android_app { 1597 name: "foo", 1598 srcs: ["a.java"], 1599 sdk_version: "current", 1600 v4_signature: true, 1601 } 1602 `, 1603 expected: "--enable-v4", 1604 }, 1605 } 1606 1607 for _, test := range testCases { 1608 t.Run(test.name, func(t *testing.T) { 1609 config := testAppConfig(nil, test.bp, nil) 1610 ctx := testContext() 1611 1612 run(t, ctx, config) 1613 foo := ctx.ModuleForTests("foo", "android_common") 1614 1615 signapk := foo.Output("foo.apk") 1616 signFlags := signapk.Args["flags"] 1617 if test.expected != signFlags { 1618 t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags) 1619 } 1620 }) 1621 } 1622} 1623 1624func TestPackageNameOverride(t *testing.T) { 1625 testCases := []struct { 1626 name string 1627 bp string 1628 packageNameOverride string 1629 expected []string 1630 }{ 1631 { 1632 name: "default", 1633 bp: ` 1634 android_app { 1635 name: "foo", 1636 srcs: ["a.java"], 1637 sdk_version: "current", 1638 } 1639 `, 1640 packageNameOverride: "", 1641 expected: []string{ 1642 buildDir + "/.intermediates/foo/android_common/foo.apk", 1643 buildDir + "/target/product/test_device/system/app/foo/foo.apk", 1644 }, 1645 }, 1646 { 1647 name: "overridden", 1648 bp: ` 1649 android_app { 1650 name: "foo", 1651 srcs: ["a.java"], 1652 sdk_version: "current", 1653 } 1654 `, 1655 packageNameOverride: "foo:bar", 1656 expected: []string{ 1657 // The package apk should be still be the original name for test dependencies. 1658 buildDir + "/.intermediates/foo/android_common/bar.apk", 1659 buildDir + "/target/product/test_device/system/app/bar/bar.apk", 1660 }, 1661 }, 1662 } 1663 1664 for _, test := range testCases { 1665 t.Run(test.name, func(t *testing.T) { 1666 config := testAppConfig(nil, test.bp, nil) 1667 if test.packageNameOverride != "" { 1668 config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride} 1669 } 1670 ctx := testContext() 1671 1672 run(t, ctx, config) 1673 foo := ctx.ModuleForTests("foo", "android_common") 1674 1675 outputs := foo.AllOutputs() 1676 outputMap := make(map[string]bool) 1677 for _, o := range outputs { 1678 outputMap[o] = true 1679 } 1680 for _, e := range test.expected { 1681 if _, exist := outputMap[e]; !exist { 1682 t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs) 1683 } 1684 } 1685 }) 1686 } 1687} 1688 1689func TestInstrumentationTargetOverridden(t *testing.T) { 1690 bp := ` 1691 android_app { 1692 name: "foo", 1693 srcs: ["a.java"], 1694 sdk_version: "current", 1695 } 1696 1697 android_test { 1698 name: "bar", 1699 instrumentation_for: "foo", 1700 sdk_version: "current", 1701 } 1702 ` 1703 config := testAppConfig(nil, bp, nil) 1704 config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"} 1705 ctx := testContext() 1706 1707 run(t, ctx, config) 1708 1709 bar := ctx.ModuleForTests("bar", "android_common") 1710 res := bar.Output("package-res.apk") 1711 aapt2Flags := res.Args["flags"] 1712 e := "--rename-instrumentation-target-package org.dandroid.bp" 1713 if !strings.Contains(aapt2Flags, e) { 1714 t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags) 1715 } 1716} 1717 1718func TestOverrideAndroidApp(t *testing.T) { 1719 ctx, _ := testJava(t, ` 1720 android_app { 1721 name: "foo", 1722 srcs: ["a.java"], 1723 certificate: "expiredkey", 1724 overrides: ["qux"], 1725 sdk_version: "current", 1726 } 1727 1728 override_android_app { 1729 name: "bar", 1730 base: "foo", 1731 certificate: ":new_certificate", 1732 lineage: "lineage.bin", 1733 logging_parent: "bah", 1734 } 1735 1736 android_app_certificate { 1737 name: "new_certificate", 1738 certificate: "cert/new_cert", 1739 } 1740 1741 override_android_app { 1742 name: "baz", 1743 base: "foo", 1744 package_name: "org.dandroid.bp", 1745 } 1746 `) 1747 1748 expectedVariants := []struct { 1749 moduleName string 1750 variantName string 1751 apkName string 1752 apkPath string 1753 certFlag string 1754 lineageFlag string 1755 overrides []string 1756 aaptFlag string 1757 logging_parent string 1758 }{ 1759 { 1760 moduleName: "foo", 1761 variantName: "android_common", 1762 apkPath: "/target/product/test_device/system/app/foo/foo.apk", 1763 certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", 1764 lineageFlag: "", 1765 overrides: []string{"qux"}, 1766 aaptFlag: "", 1767 logging_parent: "", 1768 }, 1769 { 1770 moduleName: "bar", 1771 variantName: "android_common_bar", 1772 apkPath: "/target/product/test_device/system/app/bar/bar.apk", 1773 certFlag: "cert/new_cert.x509.pem cert/new_cert.pk8", 1774 lineageFlag: "--lineage lineage.bin", 1775 overrides: []string{"qux", "foo"}, 1776 aaptFlag: "", 1777 logging_parent: "bah", 1778 }, 1779 { 1780 moduleName: "baz", 1781 variantName: "android_common_baz", 1782 apkPath: "/target/product/test_device/system/app/baz/baz.apk", 1783 certFlag: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8", 1784 lineageFlag: "", 1785 overrides: []string{"qux", "foo"}, 1786 aaptFlag: "--rename-manifest-package org.dandroid.bp", 1787 logging_parent: "", 1788 }, 1789 } 1790 for _, expected := range expectedVariants { 1791 variant := ctx.ModuleForTests("foo", expected.variantName) 1792 1793 // Check the final apk name 1794 outputs := variant.AllOutputs() 1795 expectedApkPath := buildDir + expected.apkPath 1796 found := false 1797 for _, o := range outputs { 1798 if o == expectedApkPath { 1799 found = true 1800 break 1801 } 1802 } 1803 if !found { 1804 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs) 1805 } 1806 1807 // Check the certificate paths 1808 signapk := variant.Output(expected.moduleName + ".apk") 1809 certFlag := signapk.Args["certificates"] 1810 if expected.certFlag != certFlag { 1811 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.certFlag, certFlag) 1812 } 1813 1814 // Check the lineage flags 1815 lineageFlag := signapk.Args["flags"] 1816 if expected.lineageFlag != lineageFlag { 1817 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected.lineageFlag, lineageFlag) 1818 } 1819 1820 // Check if the overrides field values are correctly aggregated. 1821 mod := variant.Module().(*AndroidApp) 1822 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) { 1823 t.Errorf("Incorrect overrides property value, expected: %q, got: %q", 1824 expected.overrides, mod.appProperties.Overrides) 1825 } 1826 1827 // Test Overridable property: Logging_parent 1828 logging_parent := mod.aapt.LoggingParent 1829 if expected.logging_parent != logging_parent { 1830 t.Errorf("Incorrect overrides property value for logging parent, expected: %q, got: %q", 1831 expected.logging_parent, logging_parent) 1832 } 1833 1834 // Check the package renaming flag, if exists. 1835 res := variant.Output("package-res.apk") 1836 aapt2Flags := res.Args["flags"] 1837 if !strings.Contains(aapt2Flags, expected.aaptFlag) { 1838 t.Errorf("package renaming flag, %q is missing in aapt2 link flags, %q", expected.aaptFlag, aapt2Flags) 1839 } 1840 } 1841} 1842 1843func TestOverrideAndroidAppDependency(t *testing.T) { 1844 ctx, _ := testJava(t, ` 1845 android_app { 1846 name: "foo", 1847 srcs: ["a.java"], 1848 sdk_version: "current", 1849 } 1850 1851 override_android_app { 1852 name: "bar", 1853 base: "foo", 1854 package_name: "org.dandroid.bp", 1855 } 1856 1857 android_test { 1858 name: "baz", 1859 srcs: ["b.java"], 1860 instrumentation_for: "foo", 1861 } 1862 1863 android_test { 1864 name: "qux", 1865 srcs: ["b.java"], 1866 instrumentation_for: "bar", 1867 } 1868 `) 1869 1870 // Verify baz, which depends on the overridden module foo, has the correct classpath javac arg. 1871 javac := ctx.ModuleForTests("baz", "android_common").Rule("javac") 1872 fooTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar") 1873 if !strings.Contains(javac.Args["classpath"], fooTurbine) { 1874 t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine) 1875 } 1876 1877 // Verify qux, which depends on the overriding module bar, has the correct classpath javac arg. 1878 javac = ctx.ModuleForTests("qux", "android_common").Rule("javac") 1879 barTurbine := filepath.Join(buildDir, ".intermediates", "foo", "android_common_bar", "turbine-combined", "foo.jar") 1880 if !strings.Contains(javac.Args["classpath"], barTurbine) { 1881 t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine) 1882 } 1883} 1884 1885func TestOverrideAndroidTest(t *testing.T) { 1886 ctx, _ := testJava(t, ` 1887 android_app { 1888 name: "foo", 1889 srcs: ["a.java"], 1890 package_name: "com.android.foo", 1891 sdk_version: "current", 1892 } 1893 1894 override_android_app { 1895 name: "bar", 1896 base: "foo", 1897 package_name: "com.android.bar", 1898 } 1899 1900 android_test { 1901 name: "foo_test", 1902 srcs: ["b.java"], 1903 instrumentation_for: "foo", 1904 } 1905 1906 override_android_test { 1907 name: "bar_test", 1908 base: "foo_test", 1909 package_name: "com.android.bar.test", 1910 instrumentation_for: "bar", 1911 instrumentation_target_package: "com.android.bar", 1912 } 1913 `) 1914 1915 expectedVariants := []struct { 1916 moduleName string 1917 variantName string 1918 apkPath string 1919 overrides []string 1920 targetVariant string 1921 packageFlag string 1922 targetPackageFlag string 1923 }{ 1924 { 1925 variantName: "android_common", 1926 apkPath: "/target/product/test_device/testcases/foo_test/arm64/foo_test.apk", 1927 overrides: nil, 1928 targetVariant: "android_common", 1929 packageFlag: "", 1930 targetPackageFlag: "", 1931 }, 1932 { 1933 variantName: "android_common_bar_test", 1934 apkPath: "/target/product/test_device/testcases/bar_test/arm64/bar_test.apk", 1935 overrides: []string{"foo_test"}, 1936 targetVariant: "android_common_bar", 1937 packageFlag: "com.android.bar.test", 1938 targetPackageFlag: "com.android.bar", 1939 }, 1940 } 1941 for _, expected := range expectedVariants { 1942 variant := ctx.ModuleForTests("foo_test", expected.variantName) 1943 1944 // Check the final apk name 1945 outputs := variant.AllOutputs() 1946 expectedApkPath := buildDir + expected.apkPath 1947 found := false 1948 for _, o := range outputs { 1949 if o == expectedApkPath { 1950 found = true 1951 break 1952 } 1953 } 1954 if !found { 1955 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs) 1956 } 1957 1958 // Check if the overrides field values are correctly aggregated. 1959 mod := variant.Module().(*AndroidTest) 1960 if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) { 1961 t.Errorf("Incorrect overrides property value, expected: %q, got: %q", 1962 expected.overrides, mod.appProperties.Overrides) 1963 } 1964 1965 // Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides. 1966 javac := variant.Rule("javac") 1967 turbine := filepath.Join(buildDir, ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar") 1968 if !strings.Contains(javac.Args["classpath"], turbine) { 1969 t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine) 1970 } 1971 1972 // Check aapt2 flags. 1973 res := variant.Output("package-res.apk") 1974 aapt2Flags := res.Args["flags"] 1975 checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) 1976 checkAapt2LinkFlag(t, aapt2Flags, "rename-instrumentation-target-package", expected.targetPackageFlag) 1977 } 1978} 1979 1980func TestAndroidTest_FixTestConfig(t *testing.T) { 1981 ctx, _ := testJava(t, ` 1982 android_app { 1983 name: "foo", 1984 srcs: ["a.java"], 1985 package_name: "com.android.foo", 1986 sdk_version: "current", 1987 } 1988 1989 android_test { 1990 name: "foo_test", 1991 srcs: ["b.java"], 1992 instrumentation_for: "foo", 1993 } 1994 1995 android_test { 1996 name: "bar_test", 1997 srcs: ["b.java"], 1998 package_name: "com.android.bar.test", 1999 instrumentation_for: "foo", 2000 } 2001 2002 override_android_test { 2003 name: "baz_test", 2004 base: "foo_test", 2005 package_name: "com.android.baz.test", 2006 } 2007 `) 2008 2009 testCases := []struct { 2010 moduleName string 2011 variantName string 2012 expectedFlags []string 2013 }{ 2014 { 2015 moduleName: "foo_test", 2016 variantName: "android_common", 2017 }, 2018 { 2019 moduleName: "bar_test", 2020 variantName: "android_common", 2021 expectedFlags: []string{ 2022 "--manifest " + buildDir + "/.intermediates/bar_test/android_common/manifest_fixer/AndroidManifest.xml", 2023 "--package-name com.android.bar.test", 2024 }, 2025 }, 2026 { 2027 moduleName: "foo_test", 2028 variantName: "android_common_baz_test", 2029 expectedFlags: []string{ 2030 "--manifest " + buildDir + 2031 "/.intermediates/foo_test/android_common_baz_test/manifest_fixer/AndroidManifest.xml", 2032 "--package-name com.android.baz.test", 2033 "--test-file-name baz_test.apk", 2034 }, 2035 }, 2036 } 2037 2038 for _, test := range testCases { 2039 variant := ctx.ModuleForTests(test.moduleName, test.variantName) 2040 params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml") 2041 2042 if len(test.expectedFlags) > 0 { 2043 if params.Rule == nil { 2044 t.Errorf("test_config_fixer was expected to run, but didn't") 2045 } else { 2046 for _, flag := range test.expectedFlags { 2047 if !strings.Contains(params.RuleParams.Command, flag) { 2048 t.Errorf("Flag %q was not found in command: %q", flag, params.RuleParams.Command) 2049 } 2050 } 2051 } 2052 } else { 2053 if params.Rule != nil { 2054 t.Errorf("test_config_fixer was not expected to run, but did: %q", params.RuleParams.Command) 2055 } 2056 } 2057 2058 } 2059} 2060 2061func TestAndroidAppImport(t *testing.T) { 2062 ctx, _ := testJava(t, ` 2063 android_app_import { 2064 name: "foo", 2065 apk: "prebuilts/apk/app.apk", 2066 certificate: "platform", 2067 dex_preopt: { 2068 enabled: true, 2069 }, 2070 } 2071 `) 2072 2073 variant := ctx.ModuleForTests("foo", "android_common") 2074 2075 // Check dexpreopt outputs. 2076 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || 2077 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { 2078 t.Errorf("can't find dexpreopt outputs") 2079 } 2080 2081 // Check cert signing flag. 2082 signedApk := variant.Output("signed/foo.apk") 2083 signingFlag := signedApk.Args["certificates"] 2084 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" 2085 if expected != signingFlag { 2086 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) 2087 } 2088} 2089 2090func TestAndroidAppImport_NoDexPreopt(t *testing.T) { 2091 ctx, _ := testJava(t, ` 2092 android_app_import { 2093 name: "foo", 2094 apk: "prebuilts/apk/app.apk", 2095 certificate: "platform", 2096 dex_preopt: { 2097 enabled: false, 2098 }, 2099 } 2100 `) 2101 2102 variant := ctx.ModuleForTests("foo", "android_common") 2103 2104 // Check dexpreopt outputs. They shouldn't exist. 2105 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil || 2106 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil { 2107 t.Errorf("dexpreopt shouldn't have run.") 2108 } 2109} 2110 2111func TestAndroidAppImport_Presigned(t *testing.T) { 2112 ctx, _ := testJava(t, ` 2113 android_app_import { 2114 name: "foo", 2115 apk: "prebuilts/apk/app.apk", 2116 presigned: true, 2117 dex_preopt: { 2118 enabled: true, 2119 }, 2120 } 2121 `) 2122 2123 variant := ctx.ModuleForTests("foo", "android_common") 2124 2125 // Check dexpreopt outputs. 2126 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || 2127 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { 2128 t.Errorf("can't find dexpreopt outputs") 2129 } 2130 // Make sure signing was skipped and aligning was done. 2131 if variant.MaybeOutput("signed/foo.apk").Rule != nil { 2132 t.Errorf("signing rule shouldn't be included.") 2133 } 2134 if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil { 2135 t.Errorf("can't find aligning rule") 2136 } 2137} 2138 2139func TestAndroidAppImport_SigningLineage(t *testing.T) { 2140 ctx, _ := testJava(t, ` 2141 android_app_import { 2142 name: "foo", 2143 apk: "prebuilts/apk/app.apk", 2144 certificate: "platform", 2145 lineage: "lineage.bin", 2146 } 2147 `) 2148 2149 variant := ctx.ModuleForTests("foo", "android_common") 2150 2151 // Check cert signing lineage flag. 2152 signedApk := variant.Output("signed/foo.apk") 2153 signingFlag := signedApk.Args["flags"] 2154 expected := "--lineage lineage.bin" 2155 if expected != signingFlag { 2156 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) 2157 } 2158} 2159 2160func TestAndroidAppImport_DefaultDevCert(t *testing.T) { 2161 ctx, _ := testJava(t, ` 2162 android_app_import { 2163 name: "foo", 2164 apk: "prebuilts/apk/app.apk", 2165 default_dev_cert: true, 2166 dex_preopt: { 2167 enabled: true, 2168 }, 2169 } 2170 `) 2171 2172 variant := ctx.ModuleForTests("foo", "android_common") 2173 2174 // Check dexpreopt outputs. 2175 if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || 2176 variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { 2177 t.Errorf("can't find dexpreopt outputs") 2178 } 2179 2180 // Check cert signing flag. 2181 signedApk := variant.Output("signed/foo.apk") 2182 signingFlag := signedApk.Args["certificates"] 2183 expected := "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8" 2184 if expected != signingFlag { 2185 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) 2186 } 2187} 2188 2189func TestAndroidAppImport_DpiVariants(t *testing.T) { 2190 bp := ` 2191 android_app_import { 2192 name: "foo", 2193 apk: "prebuilts/apk/app.apk", 2194 dpi_variants: { 2195 xhdpi: { 2196 apk: "prebuilts/apk/app_xhdpi.apk", 2197 }, 2198 xxhdpi: { 2199 apk: "prebuilts/apk/app_xxhdpi.apk", 2200 }, 2201 }, 2202 presigned: true, 2203 dex_preopt: { 2204 enabled: true, 2205 }, 2206 } 2207 ` 2208 testCases := []struct { 2209 name string 2210 aaptPreferredConfig *string 2211 aaptPrebuiltDPI []string 2212 expected string 2213 }{ 2214 { 2215 name: "no preferred", 2216 aaptPreferredConfig: nil, 2217 aaptPrebuiltDPI: []string{}, 2218 expected: "prebuilts/apk/app.apk", 2219 }, 2220 { 2221 name: "AAPTPreferredConfig matches", 2222 aaptPreferredConfig: proptools.StringPtr("xhdpi"), 2223 aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"}, 2224 expected: "prebuilts/apk/app_xhdpi.apk", 2225 }, 2226 { 2227 name: "AAPTPrebuiltDPI matches", 2228 aaptPreferredConfig: proptools.StringPtr("mdpi"), 2229 aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"}, 2230 expected: "prebuilts/apk/app_xxhdpi.apk", 2231 }, 2232 { 2233 name: "non-first AAPTPrebuiltDPI matches", 2234 aaptPreferredConfig: proptools.StringPtr("mdpi"), 2235 aaptPrebuiltDPI: []string{"ldpi", "xhdpi"}, 2236 expected: "prebuilts/apk/app_xhdpi.apk", 2237 }, 2238 { 2239 name: "no matches", 2240 aaptPreferredConfig: proptools.StringPtr("mdpi"), 2241 aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"}, 2242 expected: "prebuilts/apk/app.apk", 2243 }, 2244 } 2245 2246 jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)") 2247 for _, test := range testCases { 2248 config := testAppConfig(nil, bp, nil) 2249 config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig 2250 config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI 2251 ctx := testContext() 2252 2253 run(t, ctx, config) 2254 2255 variant := ctx.ModuleForTests("foo", "android_common") 2256 jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command 2257 matches := jniRuleRe.FindStringSubmatch(jniRuleCommand) 2258 if len(matches) != 2 { 2259 t.Errorf("failed to extract the src apk path from %q", jniRuleCommand) 2260 } 2261 if test.expected != matches[1] { 2262 t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1]) 2263 } 2264 } 2265} 2266 2267func TestAndroidAppImport_Filename(t *testing.T) { 2268 ctx, config := testJava(t, ` 2269 android_app_import { 2270 name: "foo", 2271 apk: "prebuilts/apk/app.apk", 2272 presigned: true, 2273 } 2274 2275 android_app_import { 2276 name: "bar", 2277 apk: "prebuilts/apk/app.apk", 2278 presigned: true, 2279 filename: "bar_sample.apk" 2280 } 2281 `) 2282 2283 testCases := []struct { 2284 name string 2285 expected string 2286 }{ 2287 { 2288 name: "foo", 2289 expected: "foo.apk", 2290 }, 2291 { 2292 name: "bar", 2293 expected: "bar_sample.apk", 2294 }, 2295 } 2296 2297 for _, test := range testCases { 2298 variant := ctx.ModuleForTests(test.name, "android_common") 2299 if variant.MaybeOutput(test.expected).Rule == nil { 2300 t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs()) 2301 } 2302 2303 a := variant.Module().(*AndroidAppImport) 2304 expectedValues := []string{test.expected} 2305 actualValues := android.AndroidMkEntriesForTest( 2306 t, config, "", a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"] 2307 if !reflect.DeepEqual(actualValues, expectedValues) { 2308 t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'", 2309 actualValues, expectedValues) 2310 } 2311 } 2312} 2313 2314func TestAndroidAppImport_ArchVariants(t *testing.T) { 2315 // The test config's target arch is ARM64. 2316 testCases := []struct { 2317 name string 2318 bp string 2319 expected string 2320 }{ 2321 { 2322 name: "matching arch", 2323 bp: ` 2324 android_app_import { 2325 name: "foo", 2326 apk: "prebuilts/apk/app.apk", 2327 arch: { 2328 arm64: { 2329 apk: "prebuilts/apk/app_arm64.apk", 2330 }, 2331 }, 2332 presigned: true, 2333 dex_preopt: { 2334 enabled: true, 2335 }, 2336 } 2337 `, 2338 expected: "prebuilts/apk/app_arm64.apk", 2339 }, 2340 { 2341 name: "no matching arch", 2342 bp: ` 2343 android_app_import { 2344 name: "foo", 2345 apk: "prebuilts/apk/app.apk", 2346 arch: { 2347 arm: { 2348 apk: "prebuilts/apk/app_arm.apk", 2349 }, 2350 }, 2351 presigned: true, 2352 dex_preopt: { 2353 enabled: true, 2354 }, 2355 } 2356 `, 2357 expected: "prebuilts/apk/app.apk", 2358 }, 2359 } 2360 2361 jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)") 2362 for _, test := range testCases { 2363 ctx, _ := testJava(t, test.bp) 2364 2365 variant := ctx.ModuleForTests("foo", "android_common") 2366 jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command 2367 matches := jniRuleRe.FindStringSubmatch(jniRuleCommand) 2368 if len(matches) != 2 { 2369 t.Errorf("failed to extract the src apk path from %q", jniRuleCommand) 2370 } 2371 if test.expected != matches[1] { 2372 t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1]) 2373 } 2374 } 2375} 2376 2377func TestAndroidTestImport(t *testing.T) { 2378 ctx, config := testJava(t, ` 2379 android_test_import { 2380 name: "foo", 2381 apk: "prebuilts/apk/app.apk", 2382 presigned: true, 2383 data: [ 2384 "testdata/data", 2385 ], 2386 } 2387 `) 2388 2389 test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport) 2390 2391 // Check android mks. 2392 entries := android.AndroidMkEntriesForTest(t, config, "", test)[0] 2393 expected := []string{"tests"} 2394 actual := entries.EntryMap["LOCAL_MODULE_TAGS"] 2395 if !reflect.DeepEqual(expected, actual) { 2396 t.Errorf("Unexpected module tags - expected: %q, actual: %q", expected, actual) 2397 } 2398 expected = []string{"testdata/data:testdata/data"} 2399 actual = entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] 2400 if !reflect.DeepEqual(expected, actual) { 2401 t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual) 2402 } 2403} 2404 2405func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) { 2406 ctx, _ := testJava(t, ` 2407 android_test_import { 2408 name: "foo", 2409 apk: "prebuilts/apk/app.apk", 2410 certificate: "cert/new_cert", 2411 data: [ 2412 "testdata/data", 2413 ], 2414 } 2415 2416 android_test_import { 2417 name: "foo_presigned", 2418 apk: "prebuilts/apk/app.apk", 2419 presigned: true, 2420 data: [ 2421 "testdata/data", 2422 ], 2423 } 2424 `) 2425 2426 variant := ctx.ModuleForTests("foo", "android_common") 2427 jniRule := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command 2428 if !strings.HasPrefix(jniRule, "if (zipinfo") { 2429 t.Errorf("Unexpected JNI uncompress rule command: " + jniRule) 2430 } 2431 2432 variant = ctx.ModuleForTests("foo_presigned", "android_common") 2433 jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String() 2434 if jniRule != android.Cp.String() { 2435 t.Errorf("Unexpected JNI uncompress rule: " + jniRule) 2436 } 2437 if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil { 2438 t.Errorf("Presigned test apk should be aligned") 2439 } 2440} 2441 2442func TestAndroidTestImport_Preprocessed(t *testing.T) { 2443 ctx, _ := testJava(t, ` 2444 android_test_import { 2445 name: "foo", 2446 apk: "prebuilts/apk/app.apk", 2447 presigned: true, 2448 preprocessed: true, 2449 } 2450 2451 android_test_import { 2452 name: "foo_cert", 2453 apk: "prebuilts/apk/app.apk", 2454 certificate: "cert/new_cert", 2455 preprocessed: true, 2456 } 2457 `) 2458 2459 testModules := []string{"foo", "foo_cert"} 2460 for _, m := range testModules { 2461 apkName := m + ".apk" 2462 variant := ctx.ModuleForTests(m, "android_common") 2463 jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String() 2464 if jniRule != android.Cp.String() { 2465 t.Errorf("Unexpected JNI uncompress rule: " + jniRule) 2466 } 2467 2468 // Make sure signing and aligning were skipped. 2469 if variant.MaybeOutput("signed/"+apkName).Rule != nil { 2470 t.Errorf("signing rule shouldn't be included for preprocessed.") 2471 } 2472 if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil { 2473 t.Errorf("aligning rule shouldn't be for preprocessed") 2474 } 2475 } 2476} 2477 2478func TestStl(t *testing.T) { 2479 ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` 2480 cc_library { 2481 name: "libjni", 2482 sdk_version: "current", 2483 stl: "c++_shared", 2484 } 2485 2486 android_test { 2487 name: "stl", 2488 jni_libs: ["libjni"], 2489 compile_multilib: "both", 2490 sdk_version: "current", 2491 stl: "c++_shared", 2492 } 2493 2494 android_test { 2495 name: "system", 2496 jni_libs: ["libjni"], 2497 compile_multilib: "both", 2498 sdk_version: "current", 2499 } 2500 `) 2501 2502 testCases := []struct { 2503 name string 2504 jnis []string 2505 }{ 2506 {"stl", 2507 []string{ 2508 "libjni.so", 2509 "libc++_shared.so", 2510 }, 2511 }, 2512 {"system", 2513 []string{ 2514 "libjni.so", 2515 }, 2516 }, 2517 } 2518 2519 for _, test := range testCases { 2520 t.Run(test.name, func(t *testing.T) { 2521 app := ctx.ModuleForTests(test.name, "android_common") 2522 jniLibZip := app.Output("jnilibs.zip") 2523 var jnis []string 2524 args := strings.Fields(jniLibZip.Args["jarArgs"]) 2525 for i := 0; i < len(args); i++ { 2526 if args[i] == "-f" { 2527 jnis = append(jnis, args[i+1]) 2528 i += 1 2529 } 2530 } 2531 jnisJoined := strings.Join(jnis, " ") 2532 for _, jni := range test.jnis { 2533 if !strings.Contains(jnisJoined, jni) { 2534 t.Errorf("missing jni %q in %q", jni, jnis) 2535 } 2536 } 2537 }) 2538 } 2539} 2540 2541func TestUsesLibraries(t *testing.T) { 2542 bp := ` 2543 java_sdk_library { 2544 name: "foo", 2545 srcs: ["a.java"], 2546 api_packages: ["foo"], 2547 sdk_version: "current", 2548 } 2549 2550 java_sdk_library { 2551 name: "qux", 2552 srcs: ["a.java"], 2553 api_packages: ["qux"], 2554 sdk_version: "current", 2555 } 2556 2557 java_sdk_library { 2558 name: "quuz", 2559 srcs: ["a.java"], 2560 api_packages: ["quuz"], 2561 sdk_version: "current", 2562 } 2563 2564 java_sdk_library { 2565 name: "bar", 2566 srcs: ["a.java"], 2567 api_packages: ["bar"], 2568 sdk_version: "current", 2569 } 2570 2571 android_app { 2572 name: "app", 2573 srcs: ["a.java"], 2574 libs: ["qux", "quuz.stubs"], 2575 uses_libs: ["foo"], 2576 sdk_version: "current", 2577 optional_uses_libs: [ 2578 "bar", 2579 "baz", 2580 ], 2581 } 2582 2583 android_app_import { 2584 name: "prebuilt", 2585 apk: "prebuilts/apk/app.apk", 2586 certificate: "platform", 2587 uses_libs: ["foo"], 2588 optional_uses_libs: [ 2589 "bar", 2590 "baz", 2591 ], 2592 } 2593 ` 2594 2595 config := testAppConfig(nil, bp, nil) 2596 config.TestProductVariables.MissingUsesLibraries = []string{"baz"} 2597 2598 ctx := testContext() 2599 2600 run(t, ctx, config) 2601 2602 app := ctx.ModuleForTests("app", "android_common") 2603 prebuilt := ctx.ModuleForTests("prebuilt", "android_common") 2604 2605 // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. 2606 manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] 2607 if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) { 2608 t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) 2609 } 2610 if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) { 2611 t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) 2612 } 2613 2614 // Test that all libraries are verified 2615 cmd := app.Rule("verify_uses_libraries").RuleParams.Command 2616 if w := "--uses-library foo"; !strings.Contains(cmd, w) { 2617 t.Errorf("wanted %q in %q", w, cmd) 2618 } 2619 2620 if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) { 2621 t.Errorf("wanted %q in %q", w, cmd) 2622 } 2623 2624 cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command 2625 2626 if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) { 2627 t.Errorf("wanted %q in %q", w, cmd) 2628 } 2629 2630 if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) { 2631 t.Errorf("wanted %q in %q", w, cmd) 2632 } 2633 2634 // Test that only present libraries are preopted 2635 cmd = app.Rule("dexpreopt").RuleParams.Command 2636 2637 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) { 2638 t.Errorf("wanted %q in %q", w, cmd) 2639 } 2640 2641 cmd = prebuilt.Rule("dexpreopt").RuleParams.Command 2642 2643 if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) { 2644 t.Errorf("wanted %q in %q", w, cmd) 2645 } 2646} 2647 2648func TestCodelessApp(t *testing.T) { 2649 testCases := []struct { 2650 name string 2651 bp string 2652 noCode bool 2653 }{ 2654 { 2655 name: "normal", 2656 bp: ` 2657 android_app { 2658 name: "foo", 2659 srcs: ["a.java"], 2660 sdk_version: "current", 2661 } 2662 `, 2663 noCode: false, 2664 }, 2665 { 2666 name: "app without sources", 2667 bp: ` 2668 android_app { 2669 name: "foo", 2670 sdk_version: "current", 2671 } 2672 `, 2673 noCode: true, 2674 }, 2675 { 2676 name: "app with libraries", 2677 bp: ` 2678 android_app { 2679 name: "foo", 2680 static_libs: ["lib"], 2681 sdk_version: "current", 2682 } 2683 2684 java_library { 2685 name: "lib", 2686 srcs: ["a.java"], 2687 sdk_version: "current", 2688 } 2689 `, 2690 noCode: false, 2691 }, 2692 { 2693 name: "app with sourceless libraries", 2694 bp: ` 2695 android_app { 2696 name: "foo", 2697 static_libs: ["lib"], 2698 sdk_version: "current", 2699 } 2700 2701 java_library { 2702 name: "lib", 2703 sdk_version: "current", 2704 } 2705 `, 2706 // TODO(jungjw): this should probably be true 2707 noCode: false, 2708 }, 2709 } 2710 2711 for _, test := range testCases { 2712 t.Run(test.name, func(t *testing.T) { 2713 ctx := testApp(t, test.bp) 2714 2715 foo := ctx.ModuleForTests("foo", "android_common") 2716 manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] 2717 if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode { 2718 t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs) 2719 } 2720 }) 2721 } 2722} 2723 2724func TestEmbedNotice(t *testing.T) { 2725 ctx, _ := testJavaWithFS(t, cc.GatherRequiredDepsForTest(android.Android)+` 2726 android_app { 2727 name: "foo", 2728 srcs: ["a.java"], 2729 static_libs: ["javalib"], 2730 jni_libs: ["libjni"], 2731 notice: "APP_NOTICE", 2732 embed_notices: true, 2733 sdk_version: "current", 2734 } 2735 2736 // No embed_notice flag 2737 android_app { 2738 name: "bar", 2739 srcs: ["a.java"], 2740 jni_libs: ["libjni"], 2741 notice: "APP_NOTICE", 2742 sdk_version: "current", 2743 } 2744 2745 // No NOTICE files 2746 android_app { 2747 name: "baz", 2748 srcs: ["a.java"], 2749 embed_notices: true, 2750 sdk_version: "current", 2751 } 2752 2753 cc_library { 2754 name: "libjni", 2755 system_shared_libs: [], 2756 stl: "none", 2757 notice: "LIB_NOTICE", 2758 sdk_version: "current", 2759 } 2760 2761 java_library { 2762 name: "javalib", 2763 srcs: [ 2764 ":gen", 2765 ], 2766 sdk_version: "current", 2767 } 2768 2769 genrule { 2770 name: "gen", 2771 tools: ["gentool"], 2772 out: ["gen.java"], 2773 notice: "GENRULE_NOTICE", 2774 } 2775 2776 java_binary_host { 2777 name: "gentool", 2778 srcs: ["b.java"], 2779 notice: "TOOL_NOTICE", 2780 } 2781 `, map[string][]byte{ 2782 "APP_NOTICE": nil, 2783 "GENRULE_NOTICE": nil, 2784 "LIB_NOTICE": nil, 2785 "TOOL_NOTICE": nil, 2786 }) 2787 2788 // foo has NOTICE files to process, and embed_notices is true. 2789 foo := ctx.ModuleForTests("foo", "android_common") 2790 // verify merge notices rule. 2791 mergeNotices := foo.Rule("mergeNoticesRule") 2792 noticeInputs := mergeNotices.Inputs.Strings() 2793 // TOOL_NOTICE should be excluded as it's a host module. 2794 if len(mergeNotices.Inputs) != 3 { 2795 t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs) 2796 } 2797 if !inList("APP_NOTICE", noticeInputs) { 2798 t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs) 2799 } 2800 if !inList("LIB_NOTICE", noticeInputs) { 2801 t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs) 2802 } 2803 if !inList("GENRULE_NOTICE", noticeInputs) { 2804 t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs) 2805 } 2806 // aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets. 2807 res := foo.Output("package-res.apk") 2808 aapt2Flags := res.Args["flags"] 2809 e := "-A " + buildDir + "/.intermediates/foo/android_common/NOTICE" 2810 if !strings.Contains(aapt2Flags, e) { 2811 t.Errorf("asset dir flag for NOTICE, %q is missing in aapt2 link flags, %q", e, aapt2Flags) 2812 } 2813 2814 // bar has NOTICE files to process, but embed_notices is not set. 2815 bar := ctx.ModuleForTests("bar", "android_common") 2816 res = bar.Output("package-res.apk") 2817 aapt2Flags = res.Args["flags"] 2818 e = "-A " + buildDir + "/.intermediates/bar/android_common/NOTICE" 2819 if strings.Contains(aapt2Flags, e) { 2820 t.Errorf("bar shouldn't have the asset dir flag for NOTICE: %q", e) 2821 } 2822 2823 // baz's embed_notice is true, but it doesn't have any NOTICE files. 2824 baz := ctx.ModuleForTests("baz", "android_common") 2825 res = baz.Output("package-res.apk") 2826 aapt2Flags = res.Args["flags"] 2827 e = "-A " + buildDir + "/.intermediates/baz/android_common/NOTICE" 2828 if strings.Contains(aapt2Flags, e) { 2829 t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e) 2830 } 2831} 2832 2833func TestUncompressDex(t *testing.T) { 2834 testCases := []struct { 2835 name string 2836 bp string 2837 2838 uncompressedPlatform bool 2839 uncompressedUnbundled bool 2840 }{ 2841 { 2842 name: "normal", 2843 bp: ` 2844 android_app { 2845 name: "foo", 2846 srcs: ["a.java"], 2847 sdk_version: "current", 2848 } 2849 `, 2850 uncompressedPlatform: true, 2851 uncompressedUnbundled: false, 2852 }, 2853 { 2854 name: "use_embedded_dex", 2855 bp: ` 2856 android_app { 2857 name: "foo", 2858 use_embedded_dex: true, 2859 srcs: ["a.java"], 2860 sdk_version: "current", 2861 } 2862 `, 2863 uncompressedPlatform: true, 2864 uncompressedUnbundled: true, 2865 }, 2866 { 2867 name: "privileged", 2868 bp: ` 2869 android_app { 2870 name: "foo", 2871 privileged: true, 2872 srcs: ["a.java"], 2873 sdk_version: "current", 2874 } 2875 `, 2876 uncompressedPlatform: true, 2877 uncompressedUnbundled: true, 2878 }, 2879 { 2880 name: "normal_uncompress_dex_true", 2881 bp: ` 2882 android_app { 2883 name: "foo", 2884 srcs: ["a.java"], 2885 sdk_version: "current", 2886 uncompress_dex: true, 2887 } 2888 `, 2889 uncompressedPlatform: true, 2890 uncompressedUnbundled: true, 2891 }, 2892 { 2893 name: "normal_uncompress_dex_false", 2894 bp: ` 2895 android_app { 2896 name: "foo", 2897 srcs: ["a.java"], 2898 sdk_version: "current", 2899 uncompress_dex: false, 2900 } 2901 `, 2902 uncompressedPlatform: false, 2903 uncompressedUnbundled: false, 2904 }, 2905 } 2906 2907 test := func(t *testing.T, bp string, want bool, unbundled bool) { 2908 t.Helper() 2909 2910 config := testAppConfig(nil, bp, nil) 2911 if unbundled { 2912 config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true) 2913 } 2914 2915 ctx := testContext() 2916 2917 run(t, ctx, config) 2918 2919 foo := ctx.ModuleForTests("foo", "android_common") 2920 dex := foo.Rule("r8") 2921 uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0") 2922 aligned := foo.MaybeRule("zipalign").Rule != nil 2923 2924 if uncompressedInDexJar != want { 2925 t.Errorf("want uncompressed in dex %v, got %v", want, uncompressedInDexJar) 2926 } 2927 2928 if aligned != want { 2929 t.Errorf("want aligned %v, got %v", want, aligned) 2930 } 2931 } 2932 2933 for _, tt := range testCases { 2934 t.Run(tt.name, func(t *testing.T) { 2935 t.Run("platform", func(t *testing.T) { 2936 test(t, tt.bp, tt.uncompressedPlatform, false) 2937 }) 2938 t.Run("unbundled", func(t *testing.T) { 2939 test(t, tt.bp, tt.uncompressedUnbundled, true) 2940 }) 2941 }) 2942 } 2943} 2944 2945func checkAapt2LinkFlag(t *testing.T, aapt2Flags, flagName, expectedValue string) { 2946 if expectedValue != "" { 2947 expectedFlag := "--" + flagName + " " + expectedValue 2948 if !strings.Contains(aapt2Flags, expectedFlag) { 2949 t.Errorf("%q is missing in aapt2 link flags, %q", expectedFlag, aapt2Flags) 2950 } 2951 } else { 2952 unexpectedFlag := "--" + flagName 2953 if strings.Contains(aapt2Flags, unexpectedFlag) { 2954 t.Errorf("unexpected flag, %q is found in aapt2 link flags, %q", unexpectedFlag, aapt2Flags) 2955 } 2956 } 2957} 2958 2959func TestRuntimeResourceOverlay(t *testing.T) { 2960 fs := map[string][]byte{ 2961 "baz/res/res/values/strings.xml": nil, 2962 "bar/res/res/values/strings.xml": nil, 2963 } 2964 bp := ` 2965 runtime_resource_overlay { 2966 name: "foo", 2967 certificate: "platform", 2968 lineage: "lineage.bin", 2969 product_specific: true, 2970 static_libs: ["bar"], 2971 resource_libs: ["baz"], 2972 aaptflags: ["--keep-raw-values"], 2973 } 2974 2975 runtime_resource_overlay { 2976 name: "foo_themed", 2977 certificate: "platform", 2978 product_specific: true, 2979 theme: "faza", 2980 overrides: ["foo"], 2981 } 2982 2983 android_library { 2984 name: "bar", 2985 resource_dirs: ["bar/res"], 2986 } 2987 2988 android_app { 2989 name: "baz", 2990 sdk_version: "current", 2991 resource_dirs: ["baz/res"], 2992 } 2993 ` 2994 config := testAppConfig(nil, bp, fs) 2995 ctx := testContext() 2996 run(t, ctx, config) 2997 2998 m := ctx.ModuleForTests("foo", "android_common") 2999 3000 // Check AAPT2 link flags. 3001 aapt2Flags := m.Output("package-res.apk").Args["flags"] 3002 expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"} 3003 absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " ")) 3004 if len(absentFlags) > 0 { 3005 t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags) 3006 } 3007 3008 // Check overlay.list output for static_libs dependency. 3009 overlayList := m.Output("aapt2/overlay.list").Inputs.Strings() 3010 staticLibPackage := buildDir + "/.intermediates/bar/android_common/package-res.apk" 3011 if !inList(staticLibPackage, overlayList) { 3012 t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList) 3013 } 3014 3015 // Check AAPT2 link flags for resource_libs dependency. 3016 resourceLibFlag := "-I " + buildDir + "/.intermediates/baz/android_common/package-res.apk" 3017 if !strings.Contains(aapt2Flags, resourceLibFlag) { 3018 t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags) 3019 } 3020 3021 // Check cert signing flag. 3022 signedApk := m.Output("signed/foo.apk") 3023 lineageFlag := signedApk.Args["flags"] 3024 expectedLineageFlag := "--lineage lineage.bin" 3025 if expectedLineageFlag != lineageFlag { 3026 t.Errorf("Incorrect signing lineage flags, expected: %q, got: %q", expectedLineageFlag, lineageFlag) 3027 } 3028 signingFlag := signedApk.Args["certificates"] 3029 expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8" 3030 if expected != signingFlag { 3031 t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag) 3032 } 3033 androidMkEntries := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0] 3034 path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"] 3035 expectedPath := []string{"build/make/target/product/security/platform.x509.pem"} 3036 if !reflect.DeepEqual(path, expectedPath) { 3037 t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath) 3038 } 3039 3040 // Check device location. 3041 path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"] 3042 expectedPath = []string{"/tmp/target/product/test_device/product/overlay"} 3043 if !reflect.DeepEqual(path, expectedPath) { 3044 t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath) 3045 } 3046 3047 // A themed module has a different device location 3048 m = ctx.ModuleForTests("foo_themed", "android_common") 3049 androidMkEntries = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0] 3050 path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"] 3051 expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"} 3052 if !reflect.DeepEqual(path, expectedPath) { 3053 t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath) 3054 } 3055 3056 overrides := androidMkEntries.EntryMap["LOCAL_OVERRIDES_PACKAGES"] 3057 expectedOverrides := []string{"foo"} 3058 if !reflect.DeepEqual(overrides, expectedOverrides) { 3059 t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides) 3060 } 3061} 3062 3063func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) { 3064 ctx, config := testJava(t, ` 3065 java_defaults { 3066 name: "rro_defaults", 3067 theme: "default_theme", 3068 product_specific: true, 3069 aaptflags: ["--keep-raw-values"], 3070 } 3071 3072 runtime_resource_overlay { 3073 name: "foo_with_defaults", 3074 defaults: ["rro_defaults"], 3075 } 3076 3077 runtime_resource_overlay { 3078 name: "foo_barebones", 3079 } 3080 `) 3081 3082 // 3083 // RRO module with defaults 3084 // 3085 m := ctx.ModuleForTests("foo_with_defaults", "android_common") 3086 3087 // Check AAPT2 link flags. 3088 aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ") 3089 expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"} 3090 absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags) 3091 if len(absentFlags) > 0 { 3092 t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags) 3093 } 3094 3095 // Check device location. 3096 path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"] 3097 expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"} 3098 if !reflect.DeepEqual(path, expectedPath) { 3099 t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath) 3100 } 3101 3102 // 3103 // RRO module without defaults 3104 // 3105 m = ctx.ModuleForTests("foo_barebones", "android_common") 3106 3107 // Check AAPT2 link flags. 3108 aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ") 3109 unexpectedFlags := "--keep-raw-values" 3110 if inList(unexpectedFlags, aapt2Flags) { 3111 t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags) 3112 } 3113 3114 // Check device location. 3115 path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"] 3116 expectedPath = []string{"/tmp/target/product/test_device/system/overlay"} 3117 if !reflect.DeepEqual(path, expectedPath) { 3118 t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath) 3119 } 3120} 3121 3122func TestOverrideRuntimeResourceOverlay(t *testing.T) { 3123 ctx, _ := testJava(t, ` 3124 runtime_resource_overlay { 3125 name: "foo_overlay", 3126 certificate: "platform", 3127 product_specific: true, 3128 sdk_version: "current", 3129 } 3130 3131 override_runtime_resource_overlay { 3132 name: "bar_overlay", 3133 base: "foo_overlay", 3134 package_name: "com.android.bar.overlay", 3135 target_package_name: "com.android.bar", 3136 } 3137 `) 3138 3139 expectedVariants := []struct { 3140 moduleName string 3141 variantName string 3142 apkPath string 3143 overrides []string 3144 targetVariant string 3145 packageFlag string 3146 targetPackageFlag string 3147 }{ 3148 { 3149 variantName: "android_common", 3150 apkPath: "/target/product/test_device/product/overlay/foo_overlay.apk", 3151 overrides: nil, 3152 targetVariant: "android_common", 3153 packageFlag: "", 3154 targetPackageFlag: "", 3155 }, 3156 { 3157 variantName: "android_common_bar_overlay", 3158 apkPath: "/target/product/test_device/product/overlay/bar_overlay.apk", 3159 overrides: []string{"foo_overlay"}, 3160 targetVariant: "android_common_bar", 3161 packageFlag: "com.android.bar.overlay", 3162 targetPackageFlag: "com.android.bar", 3163 }, 3164 } 3165 for _, expected := range expectedVariants { 3166 variant := ctx.ModuleForTests("foo_overlay", expected.variantName) 3167 3168 // Check the final apk name 3169 outputs := variant.AllOutputs() 3170 expectedApkPath := buildDir + expected.apkPath 3171 found := false 3172 for _, o := range outputs { 3173 if o == expectedApkPath { 3174 found = true 3175 break 3176 } 3177 } 3178 if !found { 3179 t.Errorf("Can't find %q in output files.\nAll outputs:%v", expectedApkPath, outputs) 3180 } 3181 3182 // Check if the overrides field values are correctly aggregated. 3183 mod := variant.Module().(*RuntimeResourceOverlay) 3184 if !reflect.DeepEqual(expected.overrides, mod.properties.Overrides) { 3185 t.Errorf("Incorrect overrides property value, expected: %q, got: %q", 3186 expected.overrides, mod.properties.Overrides) 3187 } 3188 3189 // Check aapt2 flags. 3190 res := variant.Output("package-res.apk") 3191 aapt2Flags := res.Args["flags"] 3192 checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag) 3193 checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag) 3194 } 3195} 3196