1// Copyright 2020 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	"reflect"
20	"strings"
21	"testing"
22
23	"github.com/google/blueprint/proptools"
24
25	"android/soong/android"
26)
27
28func TestAndroidAppImport(t *testing.T) {
29	ctx, _ := testJava(t, `
30		android_app_import {
31			name: "foo",
32			apk: "prebuilts/apk/app.apk",
33			certificate: "platform",
34			dex_preopt: {
35				enabled: true,
36			},
37		}
38		`)
39
40	variant := ctx.ModuleForTests("foo", "android_common")
41
42	// Check dexpreopt outputs.
43	if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
44		variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
45		t.Errorf("can't find dexpreopt outputs")
46	}
47
48	// Check cert signing flag.
49	signedApk := variant.Output("signed/foo.apk")
50	signingFlag := signedApk.Args["certificates"]
51	expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
52	if expected != signingFlag {
53		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
54	}
55	rule := variant.Rule("genProvenanceMetaData")
56	android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
57	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
58	android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
59	android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
60}
61
62func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
63	ctx, _ := testJava(t, `
64		android_app_import {
65			name: "foo",
66			apk: "prebuilts/apk/app.apk",
67			certificate: "platform",
68			dex_preopt: {
69				enabled: false,
70			},
71		}
72		`)
73
74	variant := ctx.ModuleForTests("foo", "android_common")
75
76	// Check dexpreopt outputs. They shouldn't exist.
77	if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil ||
78		variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule != nil {
79		t.Errorf("dexpreopt shouldn't have run.")
80	}
81
82	rule := variant.Rule("genProvenanceMetaData")
83	android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
84	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
85	android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
86	android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
87}
88
89func TestAndroidAppImport_Presigned(t *testing.T) {
90	ctx, _ := testJava(t, `
91		android_app_import {
92			name: "foo",
93			apk: "prebuilts/apk/app.apk",
94			presigned: true,
95			dex_preopt: {
96				enabled: true,
97			},
98		}
99		`)
100
101	variant := ctx.ModuleForTests("foo", "android_common")
102
103	// Check dexpreopt outputs.
104	if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
105		variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
106		t.Errorf("can't find dexpreopt outputs")
107	}
108	// Make sure signing was skipped and aligning was done.
109	if variant.MaybeOutput("signed/foo.apk").Rule != nil {
110		t.Errorf("signing rule shouldn't be included.")
111	}
112	if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
113		t.Errorf("can't find aligning rule")
114	}
115
116	rule := variant.Rule("genProvenanceMetaData")
117	android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
118	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
119	android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
120	android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
121}
122
123func TestAndroidAppImport_SigningLineage(t *testing.T) {
124	ctx, _ := testJava(t, `
125	  android_app_import {
126			name: "foo",
127			apk: "prebuilts/apk/app.apk",
128			certificate: "platform",
129			additional_certificates: [":additional_certificate"],
130			lineage: "lineage.bin",
131			rotationMinSdkVersion: "32",
132		}
133
134		android_app_certificate {
135			name: "additional_certificate",
136			certificate: "cert/additional_cert",
137		}
138	`)
139
140	variant := ctx.ModuleForTests("foo", "android_common")
141
142	signedApk := variant.Output("signed/foo.apk")
143	// Check certificates
144	certificatesFlag := signedApk.Args["certificates"]
145	expected := "build/make/target/product/security/platform.x509.pem " +
146		"build/make/target/product/security/platform.pk8 " +
147		"cert/additional_cert.x509.pem cert/additional_cert.pk8"
148	if expected != certificatesFlag {
149		t.Errorf("Incorrect certificates flags, expected: %q, got: %q", expected, certificatesFlag)
150	}
151
152	// Check cert signing flags.
153	actualCertSigningFlags := signedApk.Args["flags"]
154	expectedCertSigningFlags := "--lineage lineage.bin --rotation-min-sdk-version 32"
155	if expectedCertSigningFlags != actualCertSigningFlags {
156		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expectedCertSigningFlags, actualCertSigningFlags)
157	}
158
159	rule := variant.Rule("genProvenanceMetaData")
160	android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
161	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
162	android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
163	android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
164}
165
166func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
167	ctx, _ := testJava(t, `
168	  android_app_import {
169			name: "foo",
170			apk: "prebuilts/apk/app.apk",
171			certificate: "platform",
172			lineage: ":lineage_bin",
173		}
174
175		filegroup {
176			name: "lineage_bin",
177			srcs: ["lineage.bin"],
178		}
179	`)
180
181	variant := ctx.ModuleForTests("foo", "android_common")
182
183	signedApk := variant.Output("signed/foo.apk")
184	// Check cert signing lineage flag.
185	signingFlag := signedApk.Args["flags"]
186	expected := "--lineage lineage.bin"
187	if expected != signingFlag {
188		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
189	}
190
191	rule := variant.Rule("genProvenanceMetaData")
192	android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
193	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
194	android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
195	android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
196}
197
198func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
199	ctx, _ := testJava(t, `
200		android_app_import {
201			name: "foo",
202			apk: "prebuilts/apk/app.apk",
203			default_dev_cert: true,
204			dex_preopt: {
205				enabled: true,
206			},
207		}
208		`)
209
210	variant := ctx.ModuleForTests("foo", "android_common")
211
212	// Check dexpreopt outputs.
213	if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
214		variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
215		t.Errorf("can't find dexpreopt outputs")
216	}
217
218	// Check cert signing flag.
219	signedApk := variant.Output("signed/foo.apk")
220	signingFlag := signedApk.Args["certificates"]
221	expected := "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8"
222	if expected != signingFlag {
223		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
224	}
225
226	rule := variant.Rule("genProvenanceMetaData")
227	android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
228	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
229	android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
230	android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
231}
232
233func TestAndroidAppImport_DpiVariants(t *testing.T) {
234	bp := `
235		android_app_import {
236			name: "foo",
237			apk: "prebuilts/apk/app.apk",
238			dpi_variants: {
239				xhdpi: {
240					apk: "prebuilts/apk/app_xhdpi.apk",
241				},
242				xxhdpi: {
243					apk: "prebuilts/apk/app_xxhdpi.apk",
244				},
245			},
246			presigned: true,
247			dex_preopt: {
248				enabled: true,
249			},
250		}
251		`
252	testCases := []struct {
253		name                                   string
254		aaptPreferredConfig                    *string
255		aaptPrebuiltDPI                        []string
256		expected                               string
257		expectedProvenanceMetaDataArtifactPath string
258	}{
259		{
260			name:                                   "no preferred",
261			aaptPreferredConfig:                    nil,
262			aaptPrebuiltDPI:                        []string{},
263			expected:                               "verify_uses_libraries/apk/app.apk",
264			expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
265		},
266		{
267			name:                                   "AAPTPreferredConfig matches",
268			aaptPreferredConfig:                    proptools.StringPtr("xhdpi"),
269			aaptPrebuiltDPI:                        []string{"xxhdpi", "ldpi"},
270			expected:                               "verify_uses_libraries/apk/app_xhdpi.apk",
271			expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
272		},
273		{
274			name:                                   "AAPTPrebuiltDPI matches",
275			aaptPreferredConfig:                    proptools.StringPtr("mdpi"),
276			aaptPrebuiltDPI:                        []string{"xxhdpi", "xhdpi"},
277			expected:                               "verify_uses_libraries/apk/app_xxhdpi.apk",
278			expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xxhdpi.apk",
279		},
280		{
281			name:                                   "non-first AAPTPrebuiltDPI matches",
282			aaptPreferredConfig:                    proptools.StringPtr("mdpi"),
283			aaptPrebuiltDPI:                        []string{"ldpi", "xhdpi"},
284			expected:                               "verify_uses_libraries/apk/app_xhdpi.apk",
285			expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
286		},
287		{
288			name:                                   "no matches",
289			aaptPreferredConfig:                    proptools.StringPtr("mdpi"),
290			aaptPrebuiltDPI:                        []string{"ldpi", "xxxhdpi"},
291			expected:                               "verify_uses_libraries/apk/app.apk",
292			expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
293		},
294	}
295
296	for _, test := range testCases {
297		result := android.GroupFixturePreparers(
298			PrepareForTestWithJavaDefaultModules,
299			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
300				variables.AAPTPreferredConfig = test.aaptPreferredConfig
301				variables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI
302			}),
303		).RunTestWithBp(t, bp)
304
305		variant := result.ModuleForTests("foo", "android_common")
306		input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
307		if strings.HasSuffix(input, test.expected) {
308			t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
309		}
310
311		provenanceMetaDataRule := variant.Rule("genProvenanceMetaData")
312		android.AssertStringEquals(t, "Invalid input", test.expectedProvenanceMetaDataArtifactPath, provenanceMetaDataRule.Inputs[0].String())
313		android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", provenanceMetaDataRule.Output.String())
314		android.AssertStringEquals(t, "Invalid args", "foo", provenanceMetaDataRule.Args["module_name"])
315		android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", provenanceMetaDataRule.Args["install_path"])
316	}
317}
318
319func TestAndroidAppImport_Filename(t *testing.T) {
320	ctx, _ := testJava(t, `
321		android_app_import {
322			name: "foo",
323			apk: "prebuilts/apk/app.apk",
324			presigned: true,
325		}
326
327		android_app_import {
328			name: "bar",
329			apk: "prebuilts/apk/app.apk",
330			presigned: true,
331			filename: "bar_sample.apk"
332		}
333		`)
334
335	testCases := []struct {
336		name                 string
337		expected             string
338		onDevice             string
339		expectedArtifactPath string
340		expectedMetaDataPath string
341	}{
342		{
343			name:                 "foo",
344			expected:             "foo.apk",
345			onDevice:             "/system/app/foo/foo.apk",
346			expectedArtifactPath: "prebuilts/apk/app.apk",
347			expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
348		},
349		{
350			name:                 "bar",
351			expected:             "bar_sample.apk",
352			onDevice:             "/system/app/bar/bar_sample.apk",
353			expectedArtifactPath: "prebuilts/apk/app.apk",
354			expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
355		},
356	}
357
358	for _, test := range testCases {
359		variant := ctx.ModuleForTests(test.name, "android_common")
360		if variant.MaybeOutput(test.expected).Rule == nil {
361			t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
362		}
363
364		a := variant.Module().(*AndroidAppImport)
365		expectedValues := []string{test.expected}
366		entries := android.AndroidMkEntriesForTest(t, ctx, a)[0]
367		actualValues := entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
368		if !reflect.DeepEqual(actualValues, expectedValues) {
369			t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
370				actualValues, expectedValues)
371		}
372		android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "android_app_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
373
374		rule := variant.Rule("genProvenanceMetaData")
375		android.AssertStringEquals(t, "Invalid input", test.expectedArtifactPath, rule.Inputs[0].String())
376		android.AssertStringEquals(t, "Invalid output", test.expectedMetaDataPath, rule.Output.String())
377		android.AssertStringEquals(t, "Invalid args", test.name, rule.Args["module_name"])
378		android.AssertStringEquals(t, "Invalid args", test.onDevice, rule.Args["install_path"])
379	}
380}
381
382func TestAndroidAppImport_ArchVariants(t *testing.T) {
383	// The test config's target arch is ARM64.
384	testCases := []struct {
385		name         string
386		bp           string
387		expected     string
388		artifactPath string
389		metaDataPath string
390		installPath  string
391	}{
392		{
393			name: "matching arch",
394			bp: `
395				android_app_import {
396					name: "foo",
397					apk: "prebuilts/apk/app.apk",
398					arch: {
399						arm64: {
400							apk: "prebuilts/apk/app_arm64.apk",
401						},
402					},
403					presigned: true,
404					dex_preopt: {
405						enabled: true,
406					},
407				}
408			`,
409			expected:     "verify_uses_libraries/apk/app_arm64.apk",
410			artifactPath: "prebuilts/apk/app_arm64.apk",
411			installPath:  "/system/app/foo/foo.apk",
412		},
413		{
414			name: "matching arch without default",
415			bp: `
416				android_app_import {
417					name: "foo",
418					apk: "prebuilts/apk/app.apk",
419					arch: {
420						arm64: {
421							apk: "prebuilts/apk/app_arm64.apk",
422						},
423					},
424					presigned: true,
425					dex_preopt: {
426						enabled: true,
427					},
428				}
429			`,
430			expected:     "verify_uses_libraries/apk/app_arm64.apk",
431			artifactPath: "prebuilts/apk/app_arm64.apk",
432			installPath:  "/system/app/foo/foo.apk",
433		},
434		{
435			name: "no matching arch",
436			bp: `
437				android_app_import {
438					name: "foo",
439					apk: "prebuilts/apk/app.apk",
440					arch: {
441						arm: {
442							apk: "prebuilts/apk/app_arm.apk",
443						},
444					},
445					presigned: true,
446					dex_preopt: {
447						enabled: true,
448					},
449				}
450			`,
451			expected:     "verify_uses_libraries/apk/app.apk",
452			artifactPath: "prebuilts/apk/app.apk",
453			installPath:  "/system/app/foo/foo.apk",
454		},
455		{
456			name: "no matching arch without default",
457			bp: `
458				android_app_import {
459					name: "foo",
460					arch: {
461						arm: {
462							apk: "prebuilts/apk/app_arm.apk",
463						},
464					},
465					presigned: true,
466					dex_preopt: {
467						enabled: true,
468					},
469				}
470			`,
471			expected:     "",
472			artifactPath: "prebuilts/apk/app_arm.apk",
473			installPath:  "/system/app/foo/foo.apk",
474		},
475		{
476			name: "matching arch and dpi_variants",
477			bp: `
478				android_app_import {
479					name: "foo",
480					apk: "prebuilts/apk/app.apk",
481					arch: {
482						arm64: {
483							apk: "prebuilts/apk/app_arm64.apk",
484							dpi_variants: {
485								mdpi: {
486									apk: "prebuilts/apk/app_arm64_mdpi.apk",
487								},
488								xhdpi: {
489									apk: "prebuilts/apk/app_arm64_xhdpi.apk",
490								},
491							},
492						},
493					},
494					presigned: true,
495					dex_preopt: {
496						enabled: true,
497					},
498				}
499			`,
500			expected:     "verify_uses_libraries/apk/app_arm64_xhdpi.apk",
501			artifactPath: "prebuilts/apk/app_arm64_xhdpi.apk",
502			installPath:  "/system/app/foo/foo.apk",
503		},
504	}
505
506	for _, test := range testCases {
507		t.Run(test.name, func(t *testing.T) {
508			ctx, _ := testJava(t, test.bp)
509
510			variant := ctx.ModuleForTests("foo", "android_common")
511			if test.expected == "" {
512				if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
513					t.Error("module should have been disabled, but wasn't")
514				}
515				rule := variant.MaybeRule("genProvenanceMetaData")
516				android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
517				return
518			}
519			input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
520			if strings.HasSuffix(input, test.expected) {
521				t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
522			}
523			rule := variant.Rule("genProvenanceMetaData")
524			android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
525			android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
526			android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
527			android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
528		})
529	}
530}
531
532func TestAndroidAppImport_SoongConfigVariables(t *testing.T) {
533	testCases := []struct {
534		name         string
535		bp           string
536		expected     string
537		artifactPath string
538		metaDataPath string
539		installPath  string
540	}{
541		{
542			name: "matching arch",
543			bp: `
544				soong_config_module_type {
545					name: "my_android_app_import",
546					module_type: "android_app_import",
547					config_namespace: "my_namespace",
548					value_variables: ["my_apk_var"],
549					properties: ["apk"],
550				}
551				soong_config_value_variable {
552					name: "my_apk_var",
553				}
554				my_android_app_import {
555					name: "foo",
556					soong_config_variables: {
557						my_apk_var: {
558							apk: "prebuilts/apk/%s.apk",
559						},
560					},
561					presigned: true,
562					dex_preopt: {
563						enabled: true,
564					},
565				}
566			`,
567			expected:     "verify_uses_libraries/apk/name_from_soong_config.apk",
568			artifactPath: "prebuilts/apk/name_from_soong_config.apk",
569			installPath:  "/system/app/foo/foo.apk",
570		},
571	}
572
573	for _, test := range testCases {
574		t.Run(test.name, func(t *testing.T) {
575			ctx := android.GroupFixturePreparers(
576				prepareForJavaTest,
577				android.PrepareForTestWithSoongConfigModuleBuildComponents,
578				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
579					variables.VendorVars = map[string]map[string]string{
580						"my_namespace": {
581							"my_apk_var": "name_from_soong_config",
582						},
583					}
584				}),
585			).RunTestWithBp(t, test.bp).TestContext
586
587			variant := ctx.ModuleForTests("foo", "android_common")
588			if test.expected == "" {
589				if variant.Module().Enabled(android.PanickingConfigAndErrorContext(ctx)) {
590					t.Error("module should have been disabled, but wasn't")
591				}
592				rule := variant.MaybeRule("genProvenanceMetaData")
593				android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
594				return
595			}
596			input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
597			if strings.HasSuffix(input, test.expected) {
598				t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
599			}
600			rule := variant.Rule("genProvenanceMetaData")
601			android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
602			android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
603			android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
604			android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
605		})
606	}
607}
608
609func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
610	ctx, _ := testJava(t, `
611		android_app {
612			name: "foo",
613			srcs: ["a.java"],
614			enabled: false,
615		}
616
617 		android_app_import {
618			name: "foo",
619			apk: "prebuilts/apk/app.apk",
620			certificate: "platform",
621			prefer: true,
622		}
623		`)
624
625	variant := ctx.ModuleForTests("prebuilt_foo", "android_common")
626	a := variant.Module().(*AndroidAppImport)
627	// The prebuilt module should still be enabled and active even if the source-based counterpart
628	// is disabled.
629	if !a.prebuilt.UsePrebuilt() {
630		t.Errorf("prebuilt foo module is not active")
631	}
632	if !a.Enabled(android.PanickingConfigAndErrorContext(ctx)) {
633		t.Errorf("prebuilt foo module is disabled")
634	}
635}
636
637func TestAndroidAppImport_relativeInstallPath(t *testing.T) {
638	bp := `
639		android_app_import {
640			name: "no_relative_install_path",
641			apk: "prebuilts/apk/app.apk",
642			presigned: true,
643		}
644
645		android_app_import {
646			name: "relative_install_path",
647			apk: "prebuilts/apk/app.apk",
648			presigned: true,
649			relative_install_path: "my/path",
650		}
651
652		android_app_import {
653			name: "privileged_relative_install_path",
654			apk: "prebuilts/apk/app.apk",
655			presigned: true,
656			privileged: true,
657			relative_install_path: "my/path"
658		}
659		`
660	testCases := []struct {
661		name                string
662		expectedInstallPath string
663		errorMessage        string
664	}{
665		{
666			name:                "no_relative_install_path",
667			expectedInstallPath: "out/soong/target/product/test_device/system/app/no_relative_install_path/no_relative_install_path.apk",
668			errorMessage:        "Install path is not correct when relative_install_path is missing",
669		},
670		{
671			name:                "relative_install_path",
672			expectedInstallPath: "out/soong/target/product/test_device/system/app/my/path/relative_install_path/relative_install_path.apk",
673			errorMessage:        "Install path is not correct for app when relative_install_path is present",
674		},
675		{
676			name:                "privileged_relative_install_path",
677			expectedInstallPath: "out/soong/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk",
678			errorMessage:        "Install path is not correct for privileged app when relative_install_path is present",
679		},
680	}
681	for _, testCase := range testCases {
682		ctx, _ := testJava(t, bp)
683		mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*AndroidAppImport)
684		android.AssertPathRelativeToTopEquals(t, testCase.errorMessage, testCase.expectedInstallPath, mod.installPath)
685	}
686}
687
688func TestAndroidTestImport(t *testing.T) {
689	ctx, _ := testJava(t, `
690		android_test_import {
691			name: "foo",
692			apk: "prebuilts/apk/app.apk",
693			presigned: true,
694			data: [
695				"testdata/data",
696			],
697		}
698		`)
699
700	test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
701
702	// Check android mks.
703	entries := android.AndroidMkEntriesForTest(t, ctx, test)[0]
704	expected := []string{"tests"}
705	actual := entries.EntryMap["LOCAL_MODULE_TAGS"]
706	if !reflect.DeepEqual(expected, actual) {
707		t.Errorf("Unexpected module tags - expected: %q, actual: %q", expected, actual)
708	}
709	expected = []string{"testdata/data:testdata/data"}
710	actual = entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
711	if !reflect.DeepEqual(expected, actual) {
712		t.Errorf("Unexpected test data - expected: %q, actual: %q", expected, actual)
713	}
714}
715
716func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) {
717	ctx, _ := testJava(t, `
718		android_test_import {
719			name: "foo",
720			apk: "prebuilts/apk/app.apk",
721			certificate: "cert/new_cert",
722			data: [
723				"testdata/data",
724			],
725		}
726
727		android_test_import {
728			name: "foo_presigned",
729			apk: "prebuilts/apk/app.apk",
730			presigned: true,
731			data: [
732				"testdata/data",
733			],
734		}
735		`)
736
737	variant := ctx.ModuleForTests("foo", "android_common")
738	jniRule := variant.Output("jnis-uncompressed/foo.apk").BuildParams.Rule.String()
739	if jniRule == android.Cp.String() {
740		t.Errorf("Unexpected JNI uncompress rule command: " + jniRule)
741	}
742
743	variant = ctx.ModuleForTests("foo_presigned", "android_common")
744	jniRule = variant.Output("jnis-uncompressed/foo_presigned.apk").BuildParams.Rule.String()
745	if jniRule != android.Cp.String() {
746		t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
747	}
748	if variant.MaybeOutput("zip-aligned/foo_presigned.apk").Rule == nil {
749		t.Errorf("Presigned test apk should be aligned")
750	}
751}
752
753func TestAndroidTestImport_Preprocessed(t *testing.T) {
754	ctx, _ := testJava(t, `
755		android_test_import {
756			name: "foo",
757			apk: "prebuilts/apk/app.apk",
758			presigned: true,
759			preprocessed: true,
760		}
761		`)
762
763	apkName := "foo.apk"
764	variant := ctx.ModuleForTests("foo", "android_common")
765	jniRule := variant.Output("jnis-uncompressed/" + apkName).BuildParams.Rule.String()
766	if jniRule != android.Cp.String() {
767		t.Errorf("Unexpected JNI uncompress rule: " + jniRule)
768	}
769
770	// Make sure signing and aligning were skipped.
771	if variant.MaybeOutput("signed/"+apkName).Rule != nil {
772		t.Errorf("signing rule shouldn't be included for preprocessed.")
773	}
774	if variant.MaybeOutput("zip-aligned/"+apkName).Rule != nil {
775		t.Errorf("aligning rule shouldn't be for preprocessed")
776	}
777}
778
779func TestAndroidAppImport_Preprocessed(t *testing.T) {
780	ctx, _ := testJava(t, `
781		android_app_import {
782			name: "foo",
783			apk: "prebuilts/apk/app.apk",
784			presigned: true,
785			preprocessed: true,
786		}
787		`)
788
789	apkName := "foo.apk"
790	variant := ctx.ModuleForTests("foo", "android_common")
791	outputBuildParams := variant.Output(apkName).BuildParams
792	if outputBuildParams.Rule.String() != android.Cp.String() {
793		t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
794	}
795
796	// Make sure compression and aligning were validated.
797	if outputBuildParams.Validation == nil {
798		t.Errorf("Expected validation rule, but was not found")
799	}
800
801	validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
802	if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
803		t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
804	}
805}
806
807func TestAndroidTestImport_UncompressDex(t *testing.T) {
808	testCases := []struct {
809		name string
810		bp   string
811	}{
812		{
813			name: "normal",
814			bp: `
815				android_app_import {
816					name: "foo",
817					presigned: true,
818					apk: "prebuilts/apk/app.apk",
819				}
820			`,
821		},
822		{
823			name: "privileged",
824			bp: `
825				android_app_import {
826					name: "foo",
827					presigned: true,
828					privileged: true,
829					apk: "prebuilts/apk/app.apk",
830				}
831			`,
832		},
833	}
834
835	test := func(t *testing.T, bp string, unbundled bool, dontUncompressPrivAppDexs bool) {
836		t.Helper()
837
838		result := android.GroupFixturePreparers(
839			prepareForJavaTest,
840			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
841				if unbundled {
842					variables.Unbundled_build = proptools.BoolPtr(true)
843				}
844				variables.UncompressPrivAppDex = proptools.BoolPtr(!dontUncompressPrivAppDexs)
845			}),
846		).RunTestWithBp(t, bp)
847
848		foo := result.ModuleForTests("foo", "android_common")
849		actual := foo.MaybeRule("uncompress-dex").Rule != nil
850
851		expect := !unbundled
852		if strings.Contains(bp, "privileged: true") {
853			if dontUncompressPrivAppDexs {
854				expect = false
855			} else {
856				// TODO(b/194504107): shouldn't priv-apps be always uncompressed unless
857				// DONT_UNCOMPRESS_PRIV_APPS_DEXS is true (regardless of unbundling)?
858				// expect = true
859			}
860		}
861
862		android.AssertBoolEquals(t, "uncompress dex", expect, actual)
863	}
864
865	for _, unbundled := range []bool{false, true} {
866		for _, dontUncompressPrivAppDexs := range []bool{false, true} {
867			for _, tt := range testCases {
868				name := fmt.Sprintf("%s,unbundled:%t,dontUncompressPrivAppDexs:%t",
869					tt.name, unbundled, dontUncompressPrivAppDexs)
870				t.Run(name, func(t *testing.T) {
871					test(t, tt.bp, unbundled, dontUncompressPrivAppDexs)
872				})
873			}
874		}
875	}
876}
877
878func TestAppImportMissingCertificateAllowMissingDependencies(t *testing.T) {
879	result := android.GroupFixturePreparers(
880		PrepareForTestWithJavaDefaultModules,
881		android.PrepareForTestWithAllowMissingDependencies,
882		android.PrepareForTestWithAndroidMk,
883	).RunTestWithBp(t, `
884		android_app_import {
885			name: "foo",
886			apk: "a.apk",
887			certificate: ":missing_certificate",
888		}`)
889
890	foo := result.ModuleForTests("foo", "android_common")
891	fooApk := foo.Output("signed/foo.apk")
892	if fooApk.Rule != android.ErrorRule {
893		t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
894	}
895	android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
896}
897