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
15// This file implements the logic of bpfix and also provides a programmatic interface
16
17package bpfix
18
19import (
20	"bytes"
21	"errors"
22	"flag"
23	"fmt"
24	"io"
25	"io/ioutil"
26	"os"
27	"path/filepath"
28	"reflect"
29	"sort"
30	"strings"
31
32	"github.com/google/blueprint/parser"
33	"github.com/google/blueprint/pathtools"
34)
35
36// Reformat takes a blueprint file as a string and returns a formatted version
37func Reformat(input string) (string, error) {
38	tree, err := parse("<string>", bytes.NewBufferString(input))
39	if err != nil {
40		return "", err
41	}
42
43	res, err := parser.Print(tree)
44	if err != nil {
45		return "", err
46	}
47
48	return string(res), nil
49}
50
51// A FixRequest specifies the details of which fixes to apply to an individual file
52// A FixRequest doesn't specify whether to do a dry run or where to write the results; that's in cmd/bpfix.go
53type FixRequest struct {
54	steps []FixStep
55}
56type FixStepsExtension struct {
57	Name  string
58	Steps []FixStep
59}
60
61type FixStep struct {
62	Name string
63	Fix  func(f *Fixer) error
64}
65
66var fixStepsExtensions = []*FixStepsExtension(nil)
67
68func RegisterFixStepExtension(extension *FixStepsExtension) {
69	fixStepsExtensions = append(fixStepsExtensions, extension)
70}
71
72var fixSteps = []FixStep{
73	{
74		Name: "simplifyKnownRedundantVariables",
75		Fix:  runPatchListMod(simplifyKnownPropertiesDuplicatingEachOther),
76	},
77	{
78		Name: "rewriteIncorrectAndroidmkPrebuilts",
79		Fix:  rewriteIncorrectAndroidmkPrebuilts,
80	},
81	{
82		Name: "rewriteCtsModuleTypes",
83		Fix:  rewriteCtsModuleTypes,
84	},
85	{
86		Name: "rewriteIncorrectAndroidmkAndroidLibraries",
87		Fix:  rewriteIncorrectAndroidmkAndroidLibraries,
88	},
89	{
90		Name: "rewriteTestModuleTypes",
91		Fix:  rewriteTestModuleTypes,
92	},
93	{
94		Name: "rewriteAndroidmkJavaLibs",
95		Fix:  rewriteAndroidmkJavaLibs,
96	},
97	{
98		Name: "rewriteJavaStaticLibs",
99		Fix:  rewriteJavaStaticLibs,
100	},
101	{
102		Name: "rewritePrebuiltEtc",
103		Fix:  rewriteAndroidmkPrebuiltEtc,
104	},
105	{
106		Name: "mergeMatchingModuleProperties",
107		Fix:  runPatchListMod(mergeMatchingModuleProperties),
108	},
109	{
110		Name: "reorderCommonProperties",
111		Fix:  runPatchListMod(reorderCommonProperties),
112	},
113	{
114		Name: "removeTags",
115		Fix:  runPatchListMod(removeTags),
116	},
117	{
118		Name: "rewriteAndroidTest",
119		Fix:  rewriteAndroidTest,
120	},
121	{
122		Name: "rewriteAndroidAppImport",
123		Fix:  rewriteAndroidAppImport,
124	},
125	{
126		Name: "removeEmptyLibDependencies",
127		Fix:  removeEmptyLibDependencies,
128	},
129	{
130		Name: "removeHidlInterfaceTypes",
131		Fix:  removeHidlInterfaceTypes,
132	},
133	{
134		Name: "removeSoongConfigBoolVariable",
135		Fix:  removeSoongConfigBoolVariable,
136	},
137	{
138		Name: "removePdkProperty",
139		Fix:  runPatchListMod(removeObsoleteProperty("product_variables.pdk")),
140	},
141	{
142		Name: "removeScudoProperty",
143		Fix:  runPatchListMod(removeObsoleteProperty("sanitize.scudo")),
144	},
145	{
146		Name: "removeAndroidLicenseKinds",
147		Fix:  runPatchListMod(removeIncorrectProperties("android_license_kinds")),
148	},
149	{
150		Name: "removeAndroidLicenseConditions",
151		Fix:  runPatchListMod(removeIncorrectProperties("android_license_conditions")),
152	},
153	{
154		Name: "removeAndroidLicenseFiles",
155		Fix:  runPatchListMod(removeIncorrectProperties("android_license_files")),
156	},
157	{
158		Name: "formatFlagProperties",
159		Fix:  runPatchListMod(formatFlagProperties),
160	},
161	{
162		Name: "removeResourcesAndAssetsIfDefault",
163		Fix:  removeResourceAndAssetsIfDefault,
164	},
165}
166
167// for fix that only need to run once
168var fixStepsOnce = []FixStep{
169	{
170		Name: "haveSameLicense",
171		Fix:  haveSameLicense,
172	},
173	{
174		Name: "rewriteLicenseProperties",
175		Fix:  runPatchListMod(rewriteLicenseProperty(nil, "")),
176	},
177}
178
179func NewFixRequest() FixRequest {
180	return FixRequest{}
181}
182
183func (r FixRequest) AddAll() (result FixRequest) {
184	result.steps = append([]FixStep(nil), r.steps...)
185	result.steps = append(result.steps, fixSteps...)
186	for _, extension := range fixStepsExtensions {
187		result.steps = append(result.steps, extension.Steps...)
188	}
189	return result
190}
191
192func (r FixRequest) AddBase() (result FixRequest) {
193	result.steps = append([]FixStep(nil), r.steps...)
194	result.steps = append(result.steps, fixSteps...)
195	return result
196}
197
198func (r FixRequest) AddMatchingExtensions(pattern string) (result FixRequest) {
199	result.steps = append([]FixStep(nil), r.steps...)
200	for _, extension := range fixStepsExtensions {
201		if match, _ := filepath.Match(pattern, extension.Name); match {
202			result.steps = append(result.steps, extension.Steps...)
203		}
204	}
205	return result
206}
207
208type Fixer struct {
209	tree *parser.File
210}
211
212func (f Fixer) Tree() *parser.File {
213	return f.tree
214}
215
216func NewFixer(tree *parser.File) *Fixer {
217	fixer := &Fixer{tree}
218
219	// make a copy of the tree
220	fixer.reparse()
221
222	return fixer
223}
224
225// Fix repeatedly applies the fixes listed in the given FixRequest to the given File
226// until there is no fix that affects the tree
227func (f *Fixer) Fix(config FixRequest) (*parser.File, error) {
228	prevIdentifier, err := f.fingerprint()
229	if err != nil {
230		return nil, err
231	}
232
233	// run fix that is expected to run once first
234	configOnce := NewFixRequest()
235	configOnce.steps = append(configOnce.steps, fixStepsOnce...)
236	if len(configOnce.steps) > 0 {
237		err = f.fixTreeOnce(configOnce)
238		if err != nil {
239			return nil, err
240		}
241	}
242
243	maxNumIterations := 20
244	i := 0
245	for {
246		err = f.fixTreeOnce(config)
247		newIdentifier, err := f.fingerprint()
248		if err != nil {
249			return nil, err
250		}
251		if bytes.Equal(newIdentifier, prevIdentifier) {
252			break
253		}
254		prevIdentifier = newIdentifier
255		// any errors from a previous iteration generally get thrown away and overwritten by errors on the next iteration
256
257		// detect infinite loop
258		i++
259		if i >= maxNumIterations {
260			return nil, fmt.Errorf("Applied fixes %d times and yet the tree continued to change. Is there an infinite loop?", i)
261		}
262	}
263	return f.tree, err
264}
265
266// returns a unique identifier for the given tree that can be used to determine whether the tree changed
267func (f *Fixer) fingerprint() (fingerprint []byte, err error) {
268	bytes, err := parser.Print(f.tree)
269	if err != nil {
270		return nil, err
271	}
272	return bytes, nil
273}
274
275func (f *Fixer) reparse() ([]byte, error) {
276	buf, err := parser.Print(f.tree)
277	if err != nil {
278		return nil, err
279	}
280	newTree, err := parse(f.tree.Name, bytes.NewReader(buf))
281	if err != nil {
282		return nil, err
283	}
284	f.tree = newTree
285	return buf, nil
286}
287
288func parse(name string, r io.Reader) (*parser.File, error) {
289	tree, errs := parser.Parse(name, r, parser.NewScope(nil))
290	if errs != nil {
291		s := "parse error: "
292		for _, err := range errs {
293			s += "\n" + err.Error()
294		}
295		return nil, errors.New(s)
296	}
297	return tree, nil
298}
299
300func (f *Fixer) fixTreeOnce(config FixRequest) error {
301	for _, fix := range config.steps {
302		err := fix.Fix(f)
303		if err != nil {
304			return err
305		}
306	}
307	return nil
308}
309
310func simplifyKnownPropertiesDuplicatingEachOther(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
311	// remove from local_include_dirs anything in export_include_dirs
312	return removeMatchingModuleListProperties(mod, patchList,
313		"export_include_dirs", "local_include_dirs")
314}
315
316func rewriteIncorrectAndroidmkPrebuilts(f *Fixer) error {
317	for _, def := range f.tree.Defs {
318		mod, ok := def.(*parser.Module)
319		if !ok {
320			continue
321		}
322		if mod.Type != "java_import" {
323			continue
324		}
325		host, _ := getLiteralBoolPropertyValue(mod, "host")
326		if host {
327			mod.Type = "java_import_host"
328			removeProperty(mod, "host")
329		}
330		srcs, ok := getLiteralListProperty(mod, "srcs")
331		if !ok {
332			continue
333		}
334		if len(srcs.Values) == 0 {
335			continue
336		}
337		src, ok := srcs.Values[0].(*parser.String)
338		if !ok {
339			continue
340		}
341		switch filepath.Ext(src.Value) {
342		case ".jar":
343			renameProperty(mod, "srcs", "jars")
344
345		case ".aar":
346			renameProperty(mod, "srcs", "aars")
347			mod.Type = "android_library_import"
348
349			// An android_library_import doesn't get installed, so setting "installable = false" isn't supported
350			removeProperty(mod, "installable")
351		}
352	}
353
354	return nil
355}
356
357func rewriteCtsModuleTypes(f *Fixer) error {
358	for _, def := range f.tree.Defs {
359		mod, ok := def.(*parser.Module)
360		if !ok {
361			continue
362		}
363
364		if mod.Type != "cts_support_package" && mod.Type != "cts_package" &&
365			mod.Type != "cts_target_java_library" &&
366			mod.Type != "cts_host_java_library" {
367
368			continue
369		}
370
371		var defStr string
372		switch mod.Type {
373		case "cts_support_package":
374			mod.Type = "android_test_helper_app"
375			defStr = "cts_support_defaults"
376		case "cts_package":
377			mod.Type = "android_test"
378			defStr = "cts_defaults"
379		case "cts_target_java_library":
380			mod.Type = "java_library"
381			defStr = "cts_defaults"
382		case "cts_host_java_library":
383			mod.Type = "java_library_host"
384			defStr = "cts_defaults"
385		}
386
387		defaults := &parser.Property{
388			Name: "defaults",
389			Value: &parser.List{
390				Values: []parser.Expression{
391					&parser.String{
392						Value: defStr,
393					},
394				},
395			},
396		}
397		mod.Properties = append(mod.Properties, defaults)
398	}
399
400	return nil
401}
402
403func rewriteIncorrectAndroidmkAndroidLibraries(f *Fixer) error {
404	for _, def := range f.tree.Defs {
405		mod, ok := def.(*parser.Module)
406		if !ok {
407			continue
408		}
409
410		if !strings.HasPrefix(mod.Type, "java_") && !strings.HasPrefix(mod.Type, "android_") {
411			continue
412		}
413
414		hasAndroidLibraries := hasNonEmptyLiteralListProperty(mod, "android_libs")
415		hasStaticAndroidLibraries := hasNonEmptyLiteralListProperty(mod, "android_static_libs")
416		hasResourceDirs := hasNonEmptyLiteralListProperty(mod, "resource_dirs")
417
418		if hasAndroidLibraries || hasStaticAndroidLibraries || hasResourceDirs {
419			if mod.Type == "java_library_static" || mod.Type == "java_library" {
420				mod.Type = "android_library"
421			}
422		}
423
424		if mod.Type == "java_import" && !hasStaticAndroidLibraries {
425			removeProperty(mod, "android_static_libs")
426		}
427
428		// These may conflict with existing libs and static_libs properties, but the
429		// mergeMatchingModuleProperties pass will fix it.
430		renameProperty(mod, "shared_libs", "libs")
431		renameProperty(mod, "android_libs", "libs")
432		renameProperty(mod, "android_static_libs", "static_libs")
433	}
434
435	return nil
436}
437
438// rewriteTestModuleTypes looks for modules that are identifiable as tests but for which Make doesn't have a separate
439// module class, and moves them to the appropriate Soong module type.
440func rewriteTestModuleTypes(f *Fixer) error {
441	for _, def := range f.tree.Defs {
442		mod, ok := def.(*parser.Module)
443		if !ok {
444			continue
445		}
446
447		if !strings.HasPrefix(mod.Type, "java_") && !strings.HasPrefix(mod.Type, "android_") && mod.Type != "cc_binary" {
448			continue
449		}
450
451		hasInstrumentationFor := hasNonEmptyLiteralStringProperty(mod, "instrumentation_for")
452		hasTestSuites := hasNonEmptyLiteralListProperty(mod, "test_suites")
453		tags, _ := getLiteralListPropertyValue(mod, "tags")
454
455		var hasTestsTag bool
456		for _, tag := range tags {
457			if tag == "tests" {
458				hasTestsTag = true
459			}
460		}
461
462		isTest := hasInstrumentationFor || hasTestsTag || hasTestSuites
463
464		if isTest {
465			switch mod.Type {
466			case "android_app":
467				mod.Type = "android_test"
468			case "android_app_import":
469				mod.Type = "android_test_import"
470			case "java_library", "java_library_installable":
471				mod.Type = "java_test"
472			case "java_library_host":
473				mod.Type = "java_test_host"
474			case "cc_binary":
475				mod.Type = "cc_test"
476			}
477		}
478	}
479
480	return nil
481}
482
483// rewriteJavaStaticLibs rewrites java_library_static into java_library
484func rewriteJavaStaticLibs(f *Fixer) error {
485	for _, def := range f.tree.Defs {
486		mod, ok := def.(*parser.Module)
487		if !ok {
488			continue
489		}
490
491		if mod.Type == "java_library_static" {
492			mod.Type = "java_library"
493		}
494	}
495
496	return nil
497}
498
499// rewriteAndroidmkJavaLibs rewrites java_library_installable into java_library plus installable: true
500func rewriteAndroidmkJavaLibs(f *Fixer) error {
501	for _, def := range f.tree.Defs {
502		mod, ok := def.(*parser.Module)
503		if !ok {
504			continue
505		}
506
507		if mod.Type != "java_library_installable" {
508			continue
509		}
510
511		mod.Type = "java_library"
512
513		_, hasInstallable := mod.GetProperty("installable")
514		if !hasInstallable {
515			prop := &parser.Property{
516				Name: "installable",
517				Value: &parser.Bool{
518					Value: true,
519				},
520			}
521			mod.Properties = append(mod.Properties, prop)
522		}
523	}
524
525	return nil
526}
527
528// Helper function to get the value of a string-valued property in a given compound property.
529func getStringProperty(prop *parser.Property, fieldName string) string {
530	if propsAsMap, ok := prop.Value.(*parser.Map); ok {
531		for _, propField := range propsAsMap.Properties {
532			if fieldName == propField.Name {
533				if propFieldAsString, ok := propField.Value.(*parser.String); ok {
534					return propFieldAsString.Value
535				} else {
536					return ""
537				}
538			}
539		}
540	}
541	return ""
542}
543
544// Set the value of the given attribute to the error message
545func indicateAttributeError(mod *parser.Module, attributeName string, format string, a ...interface{}) error {
546	msg := fmt.Sprintf(format, a...)
547	mod.Properties = append(mod.Properties, &parser.Property{
548		Name:  attributeName,
549		Value: &parser.String{Value: "ERROR: " + msg},
550	})
551	return errors.New(msg)
552}
553
554// If a variable is LOCAL_MODULE, get its value from the 'name' attribute.
555// This handles the statement
556//
557//	LOCAL_SRC_FILES := $(LOCAL_MODULE)
558//
559// which occurs often.
560func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expression {
561	if varLocalName, ok := val.(*parser.Variable); ok {
562		if varLocalName.Name == "LOCAL_MODULE" {
563			if v, ok := getLiteralStringProperty(mod, "name"); ok {
564				return v
565			}
566		}
567	}
568	return val
569}
570
571// etcPrebuiltModuleUpdate contains information on updating certain parts of a defined module such as:
572//   - changing the module type from prebuilt_etc to a different one
573//   - stripping the prefix of the install path based on the module type
574//   - appending additional boolean properties to the prebuilt module
575type etcPrebuiltModuleUpdate struct {
576	// The prefix of the install path defined in local_module_path. The prefix is removed from local_module_path
577	// before setting the 'filename' attribute.
578	prefix string
579
580	// There is only one prebuilt module type in makefiles. In Soong, there are multiple versions  of
581	// prebuilts based on local_module_path. By default, it is "prebuilt_etc" if modType is blank. An
582	// example is if the local_module_path contains $(TARGET_OUT)/usr/share, the module type is
583	// considered as prebuilt_usr_share.
584	modType string
585
586	// Additional boolean attributes to be added in the prebuilt module. Each added boolean attribute
587	// has a value of true.
588	flags []string
589}
590
591func (f etcPrebuiltModuleUpdate) update(m *parser.Module, path string) bool {
592	updated := false
593	if path == f.prefix {
594		updated = true
595	} else if trimmedPath := strings.TrimPrefix(path, f.prefix+"/"); trimmedPath != path {
596		m.Properties = append(m.Properties, &parser.Property{
597			Name:  "relative_install_path",
598			Value: &parser.String{Value: trimmedPath},
599		})
600		updated = true
601	}
602	if updated {
603		for _, flag := range f.flags {
604			m.Properties = append(m.Properties, &parser.Property{Name: flag, Value: &parser.Bool{Value: true, Token: "true"}})
605		}
606		if f.modType != "" {
607			m.Type = f.modType
608		}
609	}
610	return updated
611}
612
613var localModuleUpdate = map[string][]etcPrebuiltModuleUpdate{
614	"HOST_OUT": {
615		{prefix: "/etc", modType: "prebuilt_etc_host"},
616		{prefix: "/usr/share", modType: "prebuilt_usr_share_host"},
617		{prefix: "", modType: "prebuilt_root_host"},
618	},
619	"PRODUCT_OUT": {{prefix: "/system/etc"}, {prefix: "/vendor/etc", flags: []string{"proprietary"}}},
620	"TARGET_OUT": {{prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"},
621		{prefix: "/etc/firmware", modType: "prebuilt_firmware"}, {prefix: "/vendor/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}},
622		{prefix: "/etc"}},
623	"TARGET_OUT_ETC":            {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}},
624	"TARGET_OUT_PRODUCT":        {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
625	"TARGET_OUT_PRODUCT_ETC":    {{prefix: "", flags: []string{"product_specific"}}},
626	"TARGET_OUT_ODM":            {{prefix: "/etc", flags: []string{"device_specific"}}},
627	"TARGET_OUT_SYSTEM_EXT":     {{prefix: "/etc", flags: []string{"system_ext_specific"}}},
628	"TARGET_OUT_SYSTEM_EXT_ETC": {{prefix: "", flags: []string{"system_ext_specific"}}},
629	"TARGET_OUT_VENDOR":         {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}},
630	"TARGET_OUT_VENDOR_ETC":     {{prefix: "", flags: []string{"proprietary"}}},
631	"TARGET_RECOVERY_ROOT_OUT":  {{prefix: "/system/etc", flags: []string{"recovery"}}},
632}
633
634// rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule
635func rewriteAndroidmkPrebuiltEtc(f *Fixer) error {
636	for _, def := range f.tree.Defs {
637		mod, ok := def.(*parser.Module)
638		if !ok {
639			continue
640		}
641
642		if mod.Type != "prebuilt_etc" && mod.Type != "prebuilt_etc_host" {
643			continue
644		}
645
646		// 'srcs' --> 'src' conversion
647		convertToSingleSource(mod, "src")
648
649		renameProperty(mod, "sub_dir", "relative_install_path")
650
651		// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
652		// 'local_module_path'. Analyze its contents and create the correct sub_dir:,
653		// filename: and boolean attributes combination
654		const local_module_path = "local_module_path"
655		if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok {
656			removeProperty(mod, local_module_path)
657			prefixVariableName := getStringProperty(prop_local_module_path, "var")
658			if moduleUpdates, ok := localModuleUpdate[prefixVariableName]; ok {
659				path := getStringProperty(prop_local_module_path, "fixed")
660				updated := false
661				for i := 0; i < len(moduleUpdates) && !updated; i++ {
662					updated = moduleUpdates[i].update(mod, path)
663				}
664				if !updated {
665					expectedPrefices := ""
666					sep := ""
667					for _, moduleUpdate := range moduleUpdates {
668						expectedPrefices += sep
669						sep = ", "
670						expectedPrefices += moduleUpdate.prefix
671					}
672					return indicateAttributeError(mod, "filename",
673						"LOCAL_MODULE_PATH value under $(%s) should start with %s", prefixVariableName, expectedPrefices)
674				}
675			} else {
676				return indicateAttributeError(mod, "filename", "Cannot handle $(%s) for the prebuilt_etc", prefixVariableName)
677			}
678		}
679	}
680	return nil
681}
682
683func rewriteAndroidTest(f *Fixer) error {
684	for _, def := range f.tree.Defs {
685		mod, ok := def.(*parser.Module)
686		if !ok {
687			// The definition is not a module.
688			continue
689		}
690		if mod.Type != "android_test" && mod.Type != "android_test_helper_app" {
691			// The module is not an android_test or android_test_helper_app.
692			continue
693		}
694		// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
695		// 'local_module_path'. For the android_test module, it should be  $(TARGET_OUT_DATA_APPS),
696		// that is, `local_module_path: { var: "TARGET_OUT_DATA_APPS"}`
697		// 1. if the `key: val` pair matches, (key is `local_module_path`,
698		//    and val is `{ var: "TARGET_OUT_DATA_APPS"}`), this property is removed;
699		// 2. o/w, an error msg is thrown.
700		const local_module_path = "local_module_path"
701		if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok {
702			removeProperty(mod, local_module_path)
703			prefixVariableName := getStringProperty(prop_local_module_path, "var")
704			path := getStringProperty(prop_local_module_path, "fixed")
705			if prefixVariableName == "TARGET_OUT_DATA_APPS" && path == "" {
706				continue
707			}
708			return indicateAttributeError(mod, "filename",
709				"Only LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) is allowed for the %s", mod.Type)
710		}
711	}
712	return nil
713}
714
715func rewriteAndroidAppImport(f *Fixer) error {
716	for _, def := range f.tree.Defs {
717		mod, ok := def.(*parser.Module)
718		if !(ok && mod.Type == "android_app_import") {
719			continue
720		}
721		// 'srcs' --> 'apk' conversion
722		convertToSingleSource(mod, "apk")
723		// Handle special certificate value, "PRESIGNED".
724		if cert, ok := mod.GetProperty("certificate"); ok {
725			if certStr, ok := cert.Value.(*parser.String); ok {
726				if certStr.Value == "PRESIGNED" {
727					removeProperty(mod, "certificate")
728					prop := &parser.Property{
729						Name: "presigned",
730						Value: &parser.Bool{
731							Value: true,
732						},
733					}
734					mod.Properties = append(mod.Properties, prop)
735				}
736			}
737		}
738	}
739	return nil
740}
741
742func RewriteRuntimeResourceOverlay(f *Fixer) error {
743	for _, def := range f.tree.Defs {
744		mod, ok := def.(*parser.Module)
745		if !(ok && mod.Type == "runtime_resource_overlay") {
746			continue
747		}
748		// runtime_resource_overlays are always product specific in Make.
749		if _, ok := mod.GetProperty("product_specific"); !ok {
750			prop := &parser.Property{
751				Name: "product_specific",
752				Value: &parser.Bool{
753					Value: true,
754				},
755			}
756			mod.Properties = append(mod.Properties, prop)
757		}
758	}
759	return nil
760}
761
762// Removes library dependencies which are empty (and restricted from usage in Soong)
763func removeEmptyLibDependencies(f *Fixer) error {
764	emptyLibraries := []string{
765		"libhidltransport",
766		"libhwbinder",
767	}
768	relevantFields := []string{
769		"export_shared_lib_headers",
770		"export_static_lib_headers",
771		"static_libs",
772		"whole_static_libs",
773		"shared_libs",
774	}
775	for _, def := range f.tree.Defs {
776		mod, ok := def.(*parser.Module)
777		if !ok {
778			continue
779		}
780		for _, field := range relevantFields {
781			listValue, ok := getLiteralListProperty(mod, field)
782			if !ok {
783				continue
784			}
785			newValues := []parser.Expression{}
786			for _, v := range listValue.Values {
787				stringValue, ok := v.(*parser.String)
788				if !ok {
789					return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field)
790				}
791				if inList(stringValue.Value, emptyLibraries) {
792					continue
793				}
794				newValues = append(newValues, stringValue)
795			}
796			if len(newValues) == 0 && len(listValue.Values) != 0 {
797				removeProperty(mod, field)
798			} else {
799				listValue.Values = newValues
800			}
801		}
802	}
803	return nil
804}
805
806// Removes hidl_interface 'types' which are no longer needed
807func removeHidlInterfaceTypes(f *Fixer) error {
808	for _, def := range f.tree.Defs {
809		mod, ok := def.(*parser.Module)
810		if !(ok && mod.Type == "hidl_interface") {
811			continue
812		}
813		removeProperty(mod, "types")
814	}
815	return nil
816}
817
818func removeSoongConfigBoolVariable(f *Fixer) error {
819	found := map[string]bool{}
820	newDefs := make([]parser.Definition, 0, len(f.tree.Defs))
821	for _, def := range f.tree.Defs {
822		if mod, ok := def.(*parser.Module); ok && mod.Type == "soong_config_bool_variable" {
823			if name, ok := getLiteralStringPropertyValue(mod, "name"); ok {
824				found[name] = true
825			} else {
826				return fmt.Errorf("Found soong_config_bool_variable without a name")
827			}
828		} else {
829			newDefs = append(newDefs, def)
830		}
831	}
832	f.tree.Defs = newDefs
833
834	if len(found) == 0 {
835		return nil
836	}
837
838	return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
839		if mod.Type != "soong_config_module_type" {
840			return nil
841		}
842
843		variables, ok := getLiteralListProperty(mod, "variables")
844		if !ok {
845			return nil
846		}
847
848		boolValues := strings.Builder{}
849		empty := true
850		for _, item := range variables.Values {
851			nameValue, ok := item.(*parser.String)
852			if !ok {
853				empty = false
854				continue
855			}
856			if found[nameValue.Value] {
857				patchList.Add(item.Pos().Offset, item.End().Offset+2, "")
858
859				boolValues.WriteString(`"`)
860				boolValues.WriteString(nameValue.Value)
861				boolValues.WriteString(`",`)
862			} else {
863				empty = false
864			}
865		}
866		if empty {
867			*patchList = parser.PatchList{}
868
869			prop, _ := mod.GetProperty("variables")
870			patchList.Add(prop.Pos().Offset, prop.End().Offset+2, "")
871		}
872		if boolValues.Len() == 0 {
873			return nil
874		}
875
876		boolVariables, ok := getLiteralListProperty(mod, "bool_variables")
877		if ok {
878			patchList.Add(boolVariables.RBracePos.Offset, boolVariables.RBracePos.Offset, ","+boolValues.String())
879		} else {
880			patchList.Add(variables.RBracePos.Offset+2, variables.RBracePos.Offset+2,
881				fmt.Sprintf(`bool_variables: [%s],`, boolValues.String()))
882		}
883
884		return nil
885	})(f)
886
887	return nil
888}
889
890func removeResourceAndAssetsIfDefault(f *Fixer) error {
891	for _, def := range f.tree.Defs {
892		mod, ok := def.(*parser.Module)
893		if !ok {
894			continue
895		}
896		resourceDirList, resourceDirFound := getLiteralListPropertyValue(mod, "resource_dirs")
897		if resourceDirFound && len(resourceDirList) == 1 && resourceDirList[0] == "res" {
898			removeProperty(mod, "resource_dirs")
899		}
900		assetDirList, assetDirFound := getLiteralListPropertyValue(mod, "asset_dirs")
901		if assetDirFound && len(assetDirList) == 1 && assetDirList[0] == "assets" {
902			removeProperty(mod, "asset_dirs")
903		}
904	}
905	return nil
906}
907
908// Converts the default source list property, 'srcs', to a single source property with a given name.
909// "LOCAL_MODULE" reference is also resolved during the conversion process.
910func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
911	if srcs, ok := mod.GetProperty("srcs"); ok {
912		if srcList, ok := srcs.Value.(*parser.List); ok {
913			removeProperty(mod, "srcs")
914			if len(srcList.Values) == 1 {
915				mod.Properties = append(mod.Properties,
916					&parser.Property{
917						Name:     srcPropertyName,
918						NamePos:  srcs.NamePos,
919						ColonPos: srcs.ColonPos,
920						Value:    resolveLocalModule(mod, srcList.Values[0])})
921			} else if len(srcList.Values) > 1 {
922				indicateAttributeError(mod, srcPropertyName, "LOCAL_SRC_FILES should contain at most one item")
923			}
924		} else if _, ok = srcs.Value.(*parser.Variable); ok {
925			removeProperty(mod, "srcs")
926			mod.Properties = append(mod.Properties,
927				&parser.Property{Name: srcPropertyName,
928					NamePos:  srcs.NamePos,
929					ColonPos: srcs.ColonPos,
930					Value:    resolveLocalModule(mod, srcs.Value)})
931		} else {
932			renameProperty(mod, "srcs", "apk")
933		}
934	}
935}
936
937type patchListModFunction func(*parser.Module, []byte, *parser.PatchList) error
938
939func runPatchListMod(modFunc patchListModFunction) func(*Fixer) error {
940	return func(f *Fixer) error {
941		// Make sure all the offsets are accurate
942		buf, err := f.reparse()
943		if err != nil {
944			return err
945		}
946
947		var patchlist parser.PatchList
948		for _, def := range f.tree.Defs {
949			mod, ok := def.(*parser.Module)
950			if !ok {
951				continue
952			}
953
954			err := modFunc(mod, buf, &patchlist)
955			if err != nil {
956				return err
957			}
958		}
959
960		newBuf := new(bytes.Buffer)
961		err = patchlist.Apply(bytes.NewReader(buf), newBuf)
962		if err != nil {
963			return err
964		}
965
966		// Save a copy of the buffer to print for errors below
967		bufCopy := append([]byte(nil), newBuf.Bytes()...)
968
969		newTree, err := parse(f.tree.Name, newBuf)
970		if err != nil {
971			return fmt.Errorf("Failed to parse: %v\nBuffer:\n%s", err, string(bufCopy))
972		}
973
974		f.tree = newTree
975
976		return nil
977	}
978}
979
980var commonPropertyPriorities = []string{
981	"name",
982	"defaults",
983	"device_supported",
984	"host_supported",
985	"installable",
986}
987
988func reorderCommonProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
989	if len(mod.Properties) == 0 {
990		return nil
991	}
992
993	pos := mod.LBracePos.Offset + 1
994	stage := ""
995
996	for _, name := range commonPropertyPriorities {
997		idx := propertyIndex(mod.Properties, name)
998		if idx == -1 {
999			continue
1000		}
1001		if idx == 0 {
1002			err := patchlist.Add(pos, pos, stage)
1003			if err != nil {
1004				return err
1005			}
1006			stage = ""
1007
1008			pos = mod.Properties[0].End().Offset + 1
1009			mod.Properties = mod.Properties[1:]
1010			continue
1011		}
1012
1013		prop := mod.Properties[idx]
1014		mod.Properties = append(mod.Properties[:idx], mod.Properties[idx+1:]...)
1015
1016		stage += string(buf[prop.Pos().Offset : prop.End().Offset+1])
1017
1018		err := patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, "")
1019		if err != nil {
1020			return err
1021		}
1022	}
1023
1024	if stage != "" {
1025		err := patchlist.Add(pos, pos, stage)
1026		if err != nil {
1027			return err
1028		}
1029	}
1030
1031	return nil
1032}
1033
1034func removeTags(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
1035	prop, ok := mod.GetProperty("tags")
1036	if !ok {
1037		return nil
1038	}
1039	list, ok := prop.Value.(*parser.List)
1040	if !ok {
1041		return nil
1042	}
1043
1044	replaceStr := ""
1045
1046	for _, item := range list.Values {
1047		str, ok := item.(*parser.String)
1048		if !ok {
1049			replaceStr += fmt.Sprintf("// ERROR: Unable to parse tag %q\n", item)
1050			continue
1051		}
1052
1053		switch str.Value {
1054		case "optional":
1055			continue
1056		case "debug":
1057			replaceStr += `// WARNING: Module tags are not supported in Soong.
1058				// Add this module to PRODUCT_PACKAGES_DEBUG in your product file if you want to
1059				// force installation for -userdebug and -eng builds.
1060				`
1061		case "eng":
1062			replaceStr += `// WARNING: Module tags are not supported in Soong.
1063				// Add this module to PRODUCT_PACKAGES_ENG in your product file if you want to
1064				// force installation for -eng builds.
1065				`
1066		case "tests":
1067			switch {
1068			case strings.Contains(mod.Type, "cc_test"),
1069				strings.Contains(mod.Type, "cc_library_static"),
1070				strings.Contains(mod.Type, "java_test"),
1071				mod.Type == "android_test",
1072				mod.Type == "android_test_import":
1073				continue
1074			case strings.Contains(mod.Type, "cc_lib"):
1075				replaceStr += `// WARNING: Module tags are not supported in Soong.
1076					// To make a shared library only for tests, use the "cc_test_library" module
1077					// type. If you don't use gtest, set "gtest: false".
1078					`
1079			case strings.Contains(mod.Type, "cc_bin"):
1080				replaceStr += `// WARNING: Module tags are not supported in Soong.
1081					// For native test binaries, use the "cc_test" module type. Some differences:
1082					//  - If you don't use gtest, set "gtest: false"
1083					//  - Binaries will be installed into /data/nativetest[64]/<name>/<name>
1084					//  - Both 32 & 64 bit versions will be built (as appropriate)
1085					`
1086			case strings.Contains(mod.Type, "java_lib"):
1087				replaceStr += `// WARNING: Module tags are not supported in Soong.
1088					// For JUnit or similar tests, use the "java_test" module type. A dependency on
1089					// Junit will be added by default, if it is using some other runner, set "junit: false".
1090					`
1091			case mod.Type == "android_app":
1092				replaceStr += `// WARNING: Module tags are not supported in Soong.
1093					// For JUnit or instrumentataion app tests, use the "android_test" module type.
1094					`
1095			default:
1096				replaceStr += `// WARNING: Module tags are not supported in Soong.
1097					// In most cases, tests are now identified by their module type:
1098					// cc_test, java_test, python_test
1099					`
1100			}
1101		default:
1102			replaceStr += fmt.Sprintf("// WARNING: Unknown module tag %q\n", str.Value)
1103		}
1104	}
1105
1106	return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, replaceStr)
1107}
1108
1109type propertyProvider interface {
1110	GetProperty(string) (*parser.Property, bool)
1111	RemoveProperty(string) bool
1112}
1113
1114func removeNestedProperty(mod *parser.Module, patchList *parser.PatchList, propName string) error {
1115	propNames := strings.Split(propName, ".")
1116
1117	var propProvider, toRemoveFrom propertyProvider
1118	propProvider = mod
1119
1120	var propToRemove *parser.Property
1121	for i, name := range propNames {
1122		p, ok := propProvider.GetProperty(name)
1123		if !ok {
1124			return nil
1125		}
1126		// if this is the inner most element, it's time to delete
1127		if i == len(propNames)-1 {
1128			if propToRemove == nil {
1129				// if we cannot remove the properties that the current property is nested in,
1130				// remove only the current property
1131				propToRemove = p
1132				toRemoveFrom = propProvider
1133			}
1134
1135			// remove the property from the list, in case we remove other properties in this list
1136			toRemoveFrom.RemoveProperty(propToRemove.Name)
1137			// only removing the property would leave blank line(s), remove with a patch
1138			if err := patchList.Add(propToRemove.Pos().Offset, propToRemove.End().Offset+2, ""); err != nil {
1139				return err
1140			}
1141		} else {
1142			propMap, ok := p.Value.(*parser.Map)
1143			if !ok {
1144				return nil
1145			}
1146			if len(propMap.Properties) > 1 {
1147				// if there are other properties in this struct, we need to keep this struct
1148				toRemoveFrom = nil
1149				propToRemove = nil
1150			} else if propToRemove == nil {
1151				// otherwise, we can remove the empty struct entirely
1152				toRemoveFrom = propProvider
1153				propToRemove = p
1154			}
1155			propProvider = propMap
1156		}
1157	}
1158
1159	return nil
1160}
1161
1162func removeObsoleteProperty(propName string) patchListModFunction {
1163	return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
1164		return removeNestedProperty(mod, patchList, propName)
1165	}
1166}
1167
1168func mergeMatchingModuleProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
1169	return mergeMatchingProperties(&mod.Properties, buf, patchlist)
1170}
1171
1172func mergeMatchingProperties(properties *[]*parser.Property, buf []byte, patchlist *parser.PatchList) error {
1173	seen := make(map[string]*parser.Property)
1174	for i := 0; i < len(*properties); i++ {
1175		property := (*properties)[i]
1176		if prev, exists := seen[property.Name]; exists {
1177			err := mergeProperties(prev, property, buf, patchlist)
1178			if err != nil {
1179				return err
1180			}
1181			*properties = append((*properties)[:i], (*properties)[i+1:]...)
1182		} else {
1183			seen[property.Name] = property
1184			if mapProperty, ok := property.Value.(*parser.Map); ok {
1185				err := mergeMatchingProperties(&mapProperty.Properties, buf, patchlist)
1186				if err != nil {
1187					return err
1188				}
1189			}
1190		}
1191	}
1192	return nil
1193}
1194
1195func mergeProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error {
1196	// The value of one of the properties may be a variable reference with no type assigned
1197	// Bail out in this case. Soong will notice duplicate entries and will tell to merge them.
1198	if _, isVar := a.Value.(*parser.Variable); isVar {
1199		return nil
1200	}
1201	if _, isVar := b.Value.(*parser.Variable); isVar {
1202		return nil
1203	}
1204	if a.Value.Type() != b.Value.Type() {
1205		return fmt.Errorf("type mismatch when merging properties %q: %s and %s", a.Name, a.Value.Type(), b.Value.Type())
1206	}
1207
1208	switch a.Value.Type() {
1209	case parser.StringType:
1210		return fmt.Errorf("conflicting definitions of string property %q", a.Name)
1211	case parser.ListType:
1212		return mergeListProperties(a, b, buf, patchlist)
1213	}
1214
1215	return nil
1216}
1217
1218func mergeListProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error {
1219	aval, oka := a.Value.(*parser.List)
1220	bval, okb := b.Value.(*parser.List)
1221	if !oka || !okb {
1222		// Merging expressions not supported yet
1223		return nil
1224	}
1225
1226	s := string(buf[bval.LBracePos.Offset+1 : bval.RBracePos.Offset])
1227	if bval.LBracePos.Line != bval.RBracePos.Line {
1228		if s[0] != '\n' {
1229			panic("expected \n")
1230		}
1231		// If B is a multi line list, skip the first "\n" in case A already has a trailing "\n"
1232		s = s[1:]
1233	}
1234	if aval.LBracePos.Line == aval.RBracePos.Line {
1235		// A is a single line list with no trailing comma
1236		if len(aval.Values) > 0 {
1237			s = "," + s
1238		}
1239	}
1240
1241	err := patchlist.Add(aval.RBracePos.Offset, aval.RBracePos.Offset, s)
1242	if err != nil {
1243		return err
1244	}
1245	err = patchlist.Add(b.NamePos.Offset, b.End().Offset+2, "")
1246	if err != nil {
1247		return err
1248	}
1249
1250	return nil
1251}
1252
1253// removes from <items> every item present in <removals>
1254func filterExpressionList(patchList *parser.PatchList, items *parser.List, removals *parser.List) {
1255	writeIndex := 0
1256	for _, item := range items.Values {
1257		included := true
1258		for _, removal := range removals.Values {
1259			equal, err := parser.ExpressionsAreSame(item, removal)
1260			if err != nil {
1261				continue
1262			}
1263			if equal {
1264				included = false
1265				break
1266			}
1267		}
1268		if included {
1269			items.Values[writeIndex] = item
1270			writeIndex++
1271		} else {
1272			patchList.Add(item.Pos().Offset, item.End().Offset+2, "")
1273		}
1274	}
1275	items.Values = items.Values[:writeIndex]
1276}
1277
1278// Remove each modules[i].Properties[<legacyName>][j] that matches a modules[i].Properties[<canonicalName>][k]
1279func removeMatchingModuleListProperties(mod *parser.Module, patchList *parser.PatchList, canonicalName string, legacyName string) error {
1280	legacyProp, ok := mod.GetProperty(legacyName)
1281	if !ok {
1282		return nil
1283	}
1284	legacyList, ok := legacyProp.Value.(*parser.List)
1285	if !ok || len(legacyList.Values) == 0 {
1286		return nil
1287	}
1288	canonicalList, ok := getLiteralListProperty(mod, canonicalName)
1289	if !ok {
1290		return nil
1291	}
1292
1293	localPatches := parser.PatchList{}
1294	filterExpressionList(&localPatches, legacyList, canonicalList)
1295
1296	if len(legacyList.Values) == 0 {
1297		patchList.Add(legacyProp.Pos().Offset, legacyProp.End().Offset+2, "")
1298	} else {
1299		for _, p := range localPatches {
1300			patchList.Add(p.Start, p.End, p.Replacement)
1301		}
1302	}
1303
1304	return nil
1305}
1306
1307func hasNonEmptyLiteralListProperty(mod *parser.Module, name string) bool {
1308	list, found := getLiteralListProperty(mod, name)
1309	return found && len(list.Values) > 0
1310}
1311
1312func hasNonEmptyLiteralStringProperty(mod *parser.Module, name string) bool {
1313	s, found := getLiteralStringPropertyValue(mod, name)
1314	return found && len(s) > 0
1315}
1316
1317func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) {
1318	prop, ok := mod.GetProperty(name)
1319	if !ok {
1320		return nil, false
1321	}
1322	list, ok = prop.Value.(*parser.List)
1323	return list, ok
1324}
1325
1326func getLiteralListPropertyValue(mod *parser.Module, name string) (list []string, found bool) {
1327	listValue, ok := getLiteralListProperty(mod, name)
1328	if !ok {
1329		return nil, false
1330	}
1331	for _, v := range listValue.Values {
1332		stringValue, ok := v.(*parser.String)
1333		if !ok {
1334			return nil, false
1335		}
1336		list = append(list, stringValue.Value)
1337	}
1338
1339	return list, true
1340}
1341
1342func getLiteralStringProperty(mod *parser.Module, name string) (s *parser.String, found bool) {
1343	prop, ok := mod.GetProperty(name)
1344	if !ok {
1345		return nil, false
1346	}
1347	s, ok = prop.Value.(*parser.String)
1348	return s, ok
1349}
1350
1351func getLiteralStringPropertyValue(mod *parser.Module, name string) (s string, found bool) {
1352	stringValue, ok := getLiteralStringProperty(mod, name)
1353	if !ok {
1354		return "", false
1355	}
1356
1357	return stringValue.Value, true
1358}
1359
1360func getLiteralBoolProperty(mod *parser.Module, name string) (b *parser.Bool, found bool) {
1361	prop, ok := mod.GetProperty(name)
1362	if !ok {
1363		return nil, false
1364	}
1365	b, ok = prop.Value.(*parser.Bool)
1366	return b, ok
1367}
1368
1369func getLiteralBoolPropertyValue(mod *parser.Module, name string) (s bool, found bool) {
1370	boolValue, ok := getLiteralBoolProperty(mod, name)
1371	if !ok {
1372		return false, false
1373	}
1374
1375	return boolValue.Value, true
1376}
1377
1378func propertyIndex(props []*parser.Property, propertyName string) int {
1379	for i, prop := range props {
1380		if prop.Name == propertyName {
1381			return i
1382		}
1383	}
1384	return -1
1385}
1386
1387func renameProperty(mod *parser.Module, from, to string) {
1388	for _, prop := range mod.Properties {
1389		if prop.Name == from {
1390			prop.Name = to
1391		}
1392	}
1393}
1394
1395func removeProperty(mod *parser.Module, propertyName string) {
1396	newList := make([]*parser.Property, 0, len(mod.Properties))
1397	for _, prop := range mod.Properties {
1398		if prop.Name != propertyName {
1399			newList = append(newList, prop)
1400		}
1401	}
1402	mod.Properties = newList
1403}
1404
1405func inList(s string, list []string) bool {
1406	for _, v := range list {
1407		if s == v {
1408			return true
1409		}
1410	}
1411	return false
1412}
1413
1414func formatFlagProperty(mod *parser.Module, field string, buf []byte, patchlist *parser.PatchList) error {
1415	// the comment or empty lines in the value of the field are skipped
1416	listValue, ok := getLiteralListProperty(mod, field)
1417	if !ok {
1418		// if do not find
1419		return nil
1420	}
1421	for i := 0; i < len(listValue.Values); i++ {
1422		curValue, ok := listValue.Values[i].(*parser.String)
1423		if !ok {
1424			return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field)
1425		}
1426		if !strings.HasPrefix(curValue.Value, "-") {
1427			return fmt.Errorf("Expecting the string `%s` starting with '-'", curValue.Value)
1428		}
1429		if i+1 < len(listValue.Values) {
1430			nextValue, ok := listValue.Values[i+1].(*parser.String)
1431			if !ok {
1432				return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field)
1433			}
1434			if !strings.HasPrefix(nextValue.Value, "-") {
1435				// delete the line
1436				err := patchlist.Add(curValue.Pos().Offset, curValue.End().Offset+2, "")
1437				if err != nil {
1438					return err
1439				}
1440				// replace the line
1441				value := "\"" + curValue.Value + " " + nextValue.Value + "\","
1442				err = patchlist.Add(nextValue.Pos().Offset, nextValue.End().Offset+1, value)
1443				if err != nil {
1444					return err
1445				}
1446				// combined two lines to one
1447				i++
1448			}
1449		}
1450	}
1451	return nil
1452}
1453
1454func formatFlagProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
1455	relevantFields := []string{
1456		// cc flags
1457		"asflags",
1458		"cflags",
1459		"clang_asflags",
1460		"clang_cflags",
1461		"conlyflags",
1462		"cppflags",
1463		"ldflags",
1464		"tidy_flags",
1465		// java flags
1466		"aaptflags",
1467		"dxflags",
1468		"javacflags",
1469		"kotlincflags",
1470	}
1471	for _, field := range relevantFields {
1472		err := formatFlagProperty(mod, field, buf, patchlist)
1473		if err != nil {
1474			return err
1475		}
1476	}
1477	return nil
1478}
1479
1480func rewriteLicenseProperty(fs pathtools.FileSystem, relativePath string) patchListModFunction {
1481	return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
1482		return rewriteLicenseProperties(mod, patchList, fs, relativePath)
1483	}
1484}
1485
1486// rewrite the "android_license_kinds" and "android_license_files" properties to a package module
1487// (and a license module when needed).
1488func rewriteLicenseProperties(mod *parser.Module, patchList *parser.PatchList, fs pathtools.FileSystem,
1489	relativePath string) error {
1490	// if a package module has been added, no more action is needed.
1491	for _, patch := range *patchList {
1492		if strings.Contains(patch.Replacement, "package {") {
1493			return nil
1494		}
1495	}
1496
1497	// initial the fs
1498	if fs == nil {
1499		fs = pathtools.NewOsFs(os.Getenv("ANDROID_BUILD_TOP"))
1500	}
1501
1502	// initial the relativePath
1503	if len(relativePath) == 0 {
1504		relativePath = getModuleRelativePath()
1505	}
1506	// validate the relativePath
1507	ok := hasFile(relativePath+"/Android.mk", fs)
1508	// some modules in the existing test cases in the androidmk_test.go do not have a valid path
1509	if !ok && len(relativePath) > 0 {
1510		return fmt.Errorf("Cannot find an Android.mk file at path %q", relativePath)
1511	}
1512
1513	licenseKindsPropertyName := "android_license_kinds"
1514	licenseFilesPropertyName := "android_license_files"
1515
1516	androidBpFileErr := "// Error: No Android.bp file is found at path\n" +
1517		"// %s\n" +
1518		"// Please add one there with the needed license module first.\n" +
1519		"// Then reset the default_applicable_licenses property below with the license module name.\n"
1520	licenseModuleErr := "// Error: Cannot get the name of the license module in the\n" +
1521		"// %s file.\n" +
1522		"// If no such license module exists, please add one there first.\n" +
1523		"// Then reset the default_applicable_licenses property below with the license module name.\n"
1524
1525	defaultApplicableLicense := "Android-Apache-2.0"
1526	var licenseModuleName, licensePatch string
1527	var hasFileInParentDir bool
1528
1529	// when LOCAL_NOTICE_FILE is not empty
1530	if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) {
1531		hasFileInParentDir = hasValueStartWithTwoDotsLiteralList(mod, licenseFilesPropertyName)
1532		// if have LOCAL_NOTICE_FILE outside the current directory, need to find and refer to the license
1533		// module in the LOCAL_NOTICE_FILE location directly and no new license module needs to be created
1534		if hasFileInParentDir {
1535			bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName, fs, relativePath)
1536			if !ok {
1537				bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName, fs, relativePath)
1538				if err != nil {
1539					return err
1540				}
1541				licensePatch += fmt.Sprintf(androidBpFileErr, bpDir)
1542				defaultApplicableLicense = ""
1543			} else {
1544				licenseModuleName, _ = getModuleName(bpPath, "license", fs)
1545				if len(licenseModuleName) == 0 {
1546					licensePatch += fmt.Sprintf(licenseModuleErr, bpPath)
1547				}
1548				defaultApplicableLicense = licenseModuleName
1549			}
1550		} else {
1551			// if have LOCAL_NOTICE_FILE in the current directory, need to create a new license module
1552			if len(relativePath) == 0 {
1553				return fmt.Errorf("Cannot obtain the relative path of the Android.mk file")
1554			}
1555			licenseModuleName = strings.Replace(relativePath, "/", "_", -1) + "_license"
1556			defaultApplicableLicense = licenseModuleName
1557		}
1558	}
1559
1560	//add the package module
1561	if hasNonEmptyLiteralListProperty(mod, licenseKindsPropertyName) {
1562		licensePatch += "package {\n" +
1563			"    // See: http://go/android-license-faq\n" +
1564			"    default_applicable_licenses: [\n" +
1565			"         \"" + defaultApplicableLicense + "\",\n" +
1566			"    ],\n" +
1567			"}\n" +
1568			"\n"
1569	}
1570
1571	// append the license module when necessary
1572	// when LOCAL_NOTICE_FILE is not empty and in the current directory, create a new license module
1573	// otherwise, use the above default license directly
1574	if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) && !hasFileInParentDir {
1575		licenseKinds, err := mergeLiteralListPropertyValue(mod, licenseKindsPropertyName)
1576		if err != nil {
1577			return err
1578		}
1579		licenseFiles, err := mergeLiteralListPropertyValue(mod, licenseFilesPropertyName)
1580		if err != nil {
1581			return err
1582		}
1583		licensePatch += "license {\n" +
1584			"    name: \"" + licenseModuleName + "\",\n" +
1585			"    visibility: [\":__subpackages__\"],\n" +
1586			"    license_kinds: [\n" +
1587			licenseKinds +
1588			"    ],\n" +
1589			"    license_text: [\n" +
1590			licenseFiles +
1591			"    ],\n" +
1592			"}\n" +
1593			"\n"
1594	}
1595
1596	// add to the patchList
1597	pos := mod.Pos().Offset
1598	err := patchList.Add(pos, pos, licensePatch)
1599	if err != nil {
1600		return err
1601	}
1602	return nil
1603}
1604
1605// merge the string vaules in a list property of a module into one string with expected format
1606func mergeLiteralListPropertyValue(mod *parser.Module, property string) (s string, err error) {
1607	listValue, ok := getLiteralListPropertyValue(mod, property)
1608	if !ok {
1609		// if do not find
1610		return "", fmt.Errorf("Cannot retrieve the %s.%s field", mod.Type, property)
1611	}
1612	for i := 0; i < len(listValue); i++ {
1613		s += "         \"" + listValue[i] + "\",\n"
1614	}
1615	return s, nil
1616}
1617
1618// check whether a string list property has any value starting with `../`
1619func hasValueStartWithTwoDotsLiteralList(mod *parser.Module, property string) bool {
1620	listValue, ok := getLiteralListPropertyValue(mod, property)
1621	if ok {
1622		for i := 0; i < len(listValue); i++ {
1623			if strings.HasPrefix(listValue[i], "../") {
1624				return true
1625			}
1626		}
1627	}
1628	return false
1629}
1630
1631// get the relative path from ANDROID_BUILD_TOP to the Android.mk file to be converted
1632func getModuleRelativePath() string {
1633	// get the absolute path of the top of the tree
1634	rootPath := os.Getenv("ANDROID_BUILD_TOP")
1635	// get the absolute path of the `Android.mk` file to be converted
1636	absPath := getModuleAbsolutePath()
1637	// get the relative path of the `Android.mk` file to top of the tree
1638	relModulePath, err := filepath.Rel(rootPath, absPath)
1639	if err != nil {
1640		return ""
1641	}
1642	return relModulePath
1643}
1644
1645// get the absolute path of the Android.mk file to be converted
1646func getModuleAbsolutePath() string {
1647	// get the absolute path at where the `androidmk` commend is executed
1648	curAbsPath, err := filepath.Abs(".")
1649	if err != nil {
1650		return ""
1651	}
1652	// the argument for the `androidmk` command could be
1653	// 1. "./a/b/c/Android.mk"; 2. "a/b/c/Android.mk"; 3. "Android.mk"
1654	argPath := flag.Arg(0)
1655	if strings.HasPrefix(argPath, "./") {
1656		argPath = strings.TrimPrefix(argPath, ".")
1657	}
1658	argPath = strings.TrimSuffix(argPath, "Android.mk")
1659	if strings.HasSuffix(argPath, "/") {
1660		argPath = strings.TrimSuffix(argPath, "/")
1661	}
1662	if len(argPath) > 0 && !strings.HasPrefix(argPath, "/") {
1663		argPath = "/" + argPath
1664	}
1665	// get the absolute path of the `Android.mk` file to be converted
1666	absPath := curAbsPath + argPath
1667	return absPath
1668}
1669
1670// check whether a file exists in a filesystem
1671func hasFile(path string, fs pathtools.FileSystem) bool {
1672	ok, _, _ := fs.Exists(path)
1673	return ok
1674}
1675
1676// get the directory where an `Android.bp` file and the property files are expected to locate
1677func getDirFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, error) {
1678	listValue, ok := getLiteralListPropertyValue(mod, property)
1679	if !ok {
1680		// if do not find
1681		return "", fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property)
1682	}
1683	if len(listValue) == 0 {
1684		// if empty
1685		return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property)
1686	}
1687	if relativePath == "" {
1688		relativePath = "."
1689	}
1690	_, isDir, _ := fs.Exists(relativePath)
1691	if !isDir {
1692		return "", fmt.Errorf("Cannot find the path %q", relativePath)
1693	}
1694	path := relativePath
1695	for {
1696		if !strings.HasPrefix(listValue[0], "../") {
1697			break
1698		}
1699		path = filepath.Dir(path)
1700		listValue[0] = strings.TrimPrefix(listValue[0], "../")
1701	}
1702	_, isDir, _ = fs.Exists(path)
1703	if !isDir {
1704		return "", fmt.Errorf("Cannot find the path %q", path)
1705	}
1706	return path, nil
1707}
1708
1709// get the path of the `Android.bp` file at the expected location where the property files locate
1710func getPathFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, bool) {
1711	dir, err := getDirFromProperty(mod, property, fs, relativePath)
1712	if err != nil {
1713		return "", false
1714	}
1715	ok := hasFile(dir+"/Android.bp", fs)
1716	if !ok {
1717		return "", false
1718	}
1719	return dir + "/Android.bp", true
1720}
1721
1722// parse an Android.bp file to get the name of the first module with type of moduleType
1723func getModuleName(path string, moduleType string, fs pathtools.FileSystem) (string, error) {
1724	tree, err := parserPath(path, fs)
1725	if err != nil {
1726		return "", err
1727	}
1728	for _, def := range tree.Defs {
1729		mod, ok := def.(*parser.Module)
1730		if !ok || mod.Type != moduleType {
1731			continue
1732		}
1733		prop, ok := mod.GetProperty("name")
1734		if !ok {
1735			return "", fmt.Errorf("Cannot get the %s."+"name property", mod.Type)
1736		}
1737		propVal, ok := prop.Value.(*parser.String)
1738		if ok {
1739			return propVal.Value, nil
1740		}
1741	}
1742	return "", fmt.Errorf("Cannot find the value of the %s."+"name property", moduleType)
1743}
1744
1745// parse an Android.bp file with the specific path
1746func parserPath(path string, fs pathtools.FileSystem) (tree *parser.File, err error) {
1747	f, err := fs.Open(path)
1748	if err != nil {
1749		return tree, err
1750	}
1751	defer f.Close()
1752	fileContent, _ := ioutil.ReadAll(f)
1753	tree, err = parse(path, bytes.NewBufferString(string(fileContent)))
1754	if err != nil {
1755		return tree, err
1756	}
1757	return tree, nil
1758}
1759
1760// remove the incorrect property that Soong does not support
1761func removeIncorrectProperties(propName string) patchListModFunction {
1762	return removeObsoleteProperty(propName)
1763}
1764
1765// the modules on the same Android.mk file are expected to have the same license
1766func haveSameLicense(f *Fixer) error {
1767	androidLicenseProperties := []string{
1768		"android_license_kinds",
1769		"android_license_conditions",
1770		"android_license_files",
1771	}
1772
1773	var prevModuleName string
1774	var prevLicenseKindsVals, prevLicenseConditionsVals, prevLicenseFilesVals []string
1775	prevLicenseVals := [][]string{
1776		prevLicenseKindsVals,
1777		prevLicenseConditionsVals,
1778		prevLicenseFilesVals,
1779	}
1780
1781	for _, def := range f.tree.Defs {
1782		mod, ok := def.(*parser.Module)
1783		if !ok {
1784			continue
1785		}
1786		for idx, property := range androidLicenseProperties {
1787			curModuleName, ok := getLiteralStringPropertyValue(mod, "name")
1788			// some modules in the existing test cases in the androidmk_test.go do not have name property
1789			hasNameProperty := hasProperty(mod, "name")
1790			if hasNameProperty && (!ok || len(curModuleName) == 0) {
1791				return fmt.Errorf("Cannot retrieve the name property of a module of %s type.", mod.Type)
1792			}
1793			curVals, ok := getLiteralListPropertyValue(mod, property)
1794			// some modules in the existing test cases in the androidmk_test.go do not have license-related property
1795			hasLicenseProperty := hasProperty(mod, property)
1796			if hasLicenseProperty && (!ok || len(curVals) == 0) {
1797				// if do not find the property, or no value is found for the property
1798				return fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property)
1799			}
1800			if len(prevLicenseVals[idx]) > 0 {
1801				if !reflect.DeepEqual(prevLicenseVals[idx], curVals) {
1802					return fmt.Errorf("Modules %s and %s are expected to have the same %s property.",
1803						prevModuleName, curModuleName, property)
1804				}
1805			}
1806			sort.Strings(curVals)
1807			prevLicenseVals[idx] = curVals
1808			prevModuleName = curModuleName
1809		}
1810	}
1811	return nil
1812}
1813
1814func hasProperty(mod *parser.Module, propName string) bool {
1815	_, ok := mod.GetProperty(propName)
1816	return ok
1817}
1818