• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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//    LOCAL_SRC_FILES := $(LOCAL_MODULE)
557// which occurs often.
558func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expression {
559	if varLocalName, ok := val.(*parser.Variable); ok {
560		if varLocalName.Name == "LOCAL_MODULE" {
561			if v, ok := getLiteralStringProperty(mod, "name"); ok {
562				return v
563			}
564		}
565	}
566	return val
567}
568
569// etcPrebuiltModuleUpdate contains information on updating certain parts of a defined module such as:
570//    * changing the module type from prebuilt_etc to a different one
571//    * stripping the prefix of the install path based on the module type
572//    * appending additional boolean properties to the prebuilt module
573type etcPrebuiltModuleUpdate struct {
574	// The prefix of the install path defined in local_module_path. The prefix is removed from local_module_path
575	// before setting the 'filename' attribute.
576	prefix string
577
578	// There is only one prebuilt module type in makefiles. In Soong, there are multiple versions  of
579	// prebuilts based on local_module_path. By default, it is "prebuilt_etc" if modType is blank. An
580	// example is if the local_module_path contains $(TARGET_OUT)/usr/share, the module type is
581	// considered as prebuilt_usr_share.
582	modType string
583
584	// Additional boolean attributes to be added in the prebuilt module. Each added boolean attribute
585	// has a value of true.
586	flags []string
587}
588
589func (f etcPrebuiltModuleUpdate) update(m *parser.Module, path string) bool {
590	updated := false
591	if path == f.prefix {
592		updated = true
593	} else if trimmedPath := strings.TrimPrefix(path, f.prefix+"/"); trimmedPath != path {
594		m.Properties = append(m.Properties, &parser.Property{
595			Name:  "relative_install_path",
596			Value: &parser.String{Value: trimmedPath},
597		})
598		updated = true
599	}
600	if updated {
601		for _, flag := range f.flags {
602			m.Properties = append(m.Properties, &parser.Property{Name: flag, Value: &parser.Bool{Value: true, Token: "true"}})
603		}
604		if f.modType != "" {
605			m.Type = f.modType
606		}
607	}
608	return updated
609}
610
611var localModuleUpdate = map[string][]etcPrebuiltModuleUpdate{
612	"HOST_OUT": {
613		{prefix: "/etc", modType: "prebuilt_etc_host"},
614		{prefix: "/usr/share", modType: "prebuilt_usr_share_host"},
615		{prefix: "", modType: "prebuilt_root_host"},
616	},
617	"PRODUCT_OUT": {{prefix: "/system/etc"}, {prefix: "/vendor/etc", flags: []string{"proprietary"}}},
618	"TARGET_OUT": {{prefix: "/usr/share", modType: "prebuilt_usr_share"}, {prefix: "/fonts", modType: "prebuilt_font"},
619		{prefix: "/etc/firmware", modType: "prebuilt_firmware"}, {prefix: "/vendor/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}},
620		{prefix: "/etc"}},
621	"TARGET_OUT_ETC":            {{prefix: "/firmware", modType: "prebuilt_firmware"}, {prefix: ""}},
622	"TARGET_OUT_PRODUCT":        {{prefix: "/etc", flags: []string{"product_specific"}}, {prefix: "/fonts", modType: "prebuilt_font", flags: []string{"product_specific"}}},
623	"TARGET_OUT_PRODUCT_ETC":    {{prefix: "", flags: []string{"product_specific"}}},
624	"TARGET_OUT_ODM":            {{prefix: "/etc", flags: []string{"device_specific"}}},
625	"TARGET_OUT_SYSTEM_EXT":     {{prefix: "/etc", flags: []string{"system_ext_specific"}}},
626	"TARGET_OUT_SYSTEM_EXT_ETC": {{prefix: "", flags: []string{"system_ext_specific"}}},
627	"TARGET_OUT_VENDOR":         {{prefix: "/etc", flags: []string{"proprietary"}}, {prefix: "/firmware", modType: "prebuilt_firmware", flags: []string{"proprietary"}}},
628	"TARGET_OUT_VENDOR_ETC":     {{prefix: "", flags: []string{"proprietary"}}},
629	"TARGET_RECOVERY_ROOT_OUT":  {{prefix: "/system/etc", flags: []string{"recovery"}}},
630}
631
632// rewriteAndroidPrebuiltEtc fixes prebuilt_etc rule
633func rewriteAndroidmkPrebuiltEtc(f *Fixer) error {
634	for _, def := range f.tree.Defs {
635		mod, ok := def.(*parser.Module)
636		if !ok {
637			continue
638		}
639
640		if mod.Type != "prebuilt_etc" && mod.Type != "prebuilt_etc_host" {
641			continue
642		}
643
644		// 'srcs' --> 'src' conversion
645		convertToSingleSource(mod, "src")
646
647		renameProperty(mod, "sub_dir", "relative_install_path")
648
649		// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
650		// 'local_module_path'. Analyze its contents and create the correct sub_dir:,
651		// filename: and boolean attributes combination
652		const local_module_path = "local_module_path"
653		if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok {
654			removeProperty(mod, local_module_path)
655			prefixVariableName := getStringProperty(prop_local_module_path, "var")
656			if moduleUpdates, ok := localModuleUpdate[prefixVariableName]; ok {
657				path := getStringProperty(prop_local_module_path, "fixed")
658				updated := false
659				for i := 0; i < len(moduleUpdates) && !updated; i++ {
660					updated = moduleUpdates[i].update(mod, path)
661				}
662				if !updated {
663					expectedPrefices := ""
664					sep := ""
665					for _, moduleUpdate := range moduleUpdates {
666						expectedPrefices += sep
667						sep = ", "
668						expectedPrefices += moduleUpdate.prefix
669					}
670					return indicateAttributeError(mod, "filename",
671						"LOCAL_MODULE_PATH value under $(%s) should start with %s", prefixVariableName, expectedPrefices)
672				}
673			} else {
674				return indicateAttributeError(mod, "filename", "Cannot handle $(%s) for the prebuilt_etc", prefixVariableName)
675			}
676		}
677	}
678	return nil
679}
680
681func rewriteAndroidTest(f *Fixer) error {
682	for _, def := range f.tree.Defs {
683		mod, ok := def.(*parser.Module)
684		if !ok {
685			// The definition is not a module.
686			continue
687		}
688		if mod.Type != "android_test" && mod.Type != "android_test_helper_app" {
689			// The module is not an android_test or android_test_helper_app.
690			continue
691		}
692		// The rewriter converts LOCAL_MODULE_PATH attribute into a struct attribute
693		// 'local_module_path'. For the android_test module, it should be  $(TARGET_OUT_DATA_APPS),
694		// that is, `local_module_path: { var: "TARGET_OUT_DATA_APPS"}`
695		// 1. if the `key: val` pair matches, (key is `local_module_path`,
696		//    and val is `{ var: "TARGET_OUT_DATA_APPS"}`), this property is removed;
697		// 2. o/w, an error msg is thrown.
698		const local_module_path = "local_module_path"
699		if prop_local_module_path, ok := mod.GetProperty(local_module_path); ok {
700			removeProperty(mod, local_module_path)
701			prefixVariableName := getStringProperty(prop_local_module_path, "var")
702			path := getStringProperty(prop_local_module_path, "fixed")
703			if prefixVariableName == "TARGET_OUT_DATA_APPS" && path == "" {
704				continue
705			}
706			return indicateAttributeError(mod, "filename",
707				"Only LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) is allowed for the %s", mod.Type)
708		}
709	}
710	return nil
711}
712
713func rewriteAndroidAppImport(f *Fixer) error {
714	for _, def := range f.tree.Defs {
715		mod, ok := def.(*parser.Module)
716		if !(ok && mod.Type == "android_app_import") {
717			continue
718		}
719		// 'srcs' --> 'apk' conversion
720		convertToSingleSource(mod, "apk")
721		// Handle special certificate value, "PRESIGNED".
722		if cert, ok := mod.GetProperty("certificate"); ok {
723			if certStr, ok := cert.Value.(*parser.String); ok {
724				if certStr.Value == "PRESIGNED" {
725					removeProperty(mod, "certificate")
726					prop := &parser.Property{
727						Name: "presigned",
728						Value: &parser.Bool{
729							Value: true,
730						},
731					}
732					mod.Properties = append(mod.Properties, prop)
733				}
734			}
735		}
736	}
737	return nil
738}
739
740func RewriteRuntimeResourceOverlay(f *Fixer) error {
741	for _, def := range f.tree.Defs {
742		mod, ok := def.(*parser.Module)
743		if !(ok && mod.Type == "runtime_resource_overlay") {
744			continue
745		}
746		// runtime_resource_overlays are always product specific in Make.
747		if _, ok := mod.GetProperty("product_specific"); !ok {
748			prop := &parser.Property{
749				Name: "product_specific",
750				Value: &parser.Bool{
751					Value: true,
752				},
753			}
754			mod.Properties = append(mod.Properties, prop)
755		}
756	}
757	return nil
758}
759
760// Removes library dependencies which are empty (and restricted from usage in Soong)
761func removeEmptyLibDependencies(f *Fixer) error {
762	emptyLibraries := []string{
763		"libhidltransport",
764		"libhwbinder",
765	}
766	relevantFields := []string{
767		"export_shared_lib_headers",
768		"export_static_lib_headers",
769		"static_libs",
770		"whole_static_libs",
771		"shared_libs",
772	}
773	for _, def := range f.tree.Defs {
774		mod, ok := def.(*parser.Module)
775		if !ok {
776			continue
777		}
778		for _, field := range relevantFields {
779			listValue, ok := getLiteralListProperty(mod, field)
780			if !ok {
781				continue
782			}
783			newValues := []parser.Expression{}
784			for _, v := range listValue.Values {
785				stringValue, ok := v.(*parser.String)
786				if !ok {
787					return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field)
788				}
789				if inList(stringValue.Value, emptyLibraries) {
790					continue
791				}
792				newValues = append(newValues, stringValue)
793			}
794			if len(newValues) == 0 && len(listValue.Values) != 0 {
795				removeProperty(mod, field)
796			} else {
797				listValue.Values = newValues
798			}
799		}
800	}
801	return nil
802}
803
804// Removes hidl_interface 'types' which are no longer needed
805func removeHidlInterfaceTypes(f *Fixer) error {
806	for _, def := range f.tree.Defs {
807		mod, ok := def.(*parser.Module)
808		if !(ok && mod.Type == "hidl_interface") {
809			continue
810		}
811		removeProperty(mod, "types")
812	}
813	return nil
814}
815
816func removeSoongConfigBoolVariable(f *Fixer) error {
817	found := map[string]bool{}
818	newDefs := make([]parser.Definition, 0, len(f.tree.Defs))
819	for _, def := range f.tree.Defs {
820		if mod, ok := def.(*parser.Module); ok && mod.Type == "soong_config_bool_variable" {
821			if name, ok := getLiteralStringPropertyValue(mod, "name"); ok {
822				found[name] = true
823			} else {
824				return fmt.Errorf("Found soong_config_bool_variable without a name")
825			}
826		} else {
827			newDefs = append(newDefs, def)
828		}
829	}
830	f.tree.Defs = newDefs
831
832	if len(found) == 0 {
833		return nil
834	}
835
836	return runPatchListMod(func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
837		if mod.Type != "soong_config_module_type" {
838			return nil
839		}
840
841		variables, ok := getLiteralListProperty(mod, "variables")
842		if !ok {
843			return nil
844		}
845
846		boolValues := strings.Builder{}
847		empty := true
848		for _, item := range variables.Values {
849			nameValue, ok := item.(*parser.String)
850			if !ok {
851				empty = false
852				continue
853			}
854			if found[nameValue.Value] {
855				patchList.Add(item.Pos().Offset, item.End().Offset+2, "")
856
857				boolValues.WriteString(`"`)
858				boolValues.WriteString(nameValue.Value)
859				boolValues.WriteString(`",`)
860			} else {
861				empty = false
862			}
863		}
864		if empty {
865			*patchList = parser.PatchList{}
866
867			prop, _ := mod.GetProperty("variables")
868			patchList.Add(prop.Pos().Offset, prop.End().Offset+2, "")
869		}
870		if boolValues.Len() == 0 {
871			return nil
872		}
873
874		boolVariables, ok := getLiteralListProperty(mod, "bool_variables")
875		if ok {
876			patchList.Add(boolVariables.RBracePos.Offset, boolVariables.RBracePos.Offset, ","+boolValues.String())
877		} else {
878			patchList.Add(variables.RBracePos.Offset+2, variables.RBracePos.Offset+2,
879				fmt.Sprintf(`bool_variables: [%s],`, boolValues.String()))
880		}
881
882		return nil
883	})(f)
884
885	return nil
886}
887
888func removeResourceAndAssetsIfDefault(f *Fixer) error {
889	for _, def := range f.tree.Defs {
890		mod, ok := def.(*parser.Module)
891		if !ok {
892			continue
893		}
894		resourceDirList, resourceDirFound := getLiteralListPropertyValue(mod, "resource_dirs")
895		if resourceDirFound && len(resourceDirList) == 1 && resourceDirList[0] == "res" {
896			removeProperty(mod, "resource_dirs")
897		}
898		assetDirList, assetDirFound := getLiteralListPropertyValue(mod, "asset_dirs")
899		if assetDirFound && len(assetDirList) == 1 && assetDirList[0] == "assets" {
900			removeProperty(mod, "asset_dirs")
901		}
902	}
903	return nil
904}
905
906// Converts the default source list property, 'srcs', to a single source property with a given name.
907// "LOCAL_MODULE" reference is also resolved during the conversion process.
908func convertToSingleSource(mod *parser.Module, srcPropertyName string) {
909	if srcs, ok := mod.GetProperty("srcs"); ok {
910		if srcList, ok := srcs.Value.(*parser.List); ok {
911			removeProperty(mod, "srcs")
912			if len(srcList.Values) == 1 {
913				mod.Properties = append(mod.Properties,
914					&parser.Property{
915						Name:     srcPropertyName,
916						NamePos:  srcs.NamePos,
917						ColonPos: srcs.ColonPos,
918						Value:    resolveLocalModule(mod, srcList.Values[0])})
919			} else if len(srcList.Values) > 1 {
920				indicateAttributeError(mod, srcPropertyName, "LOCAL_SRC_FILES should contain at most one item")
921			}
922		} else if _, ok = srcs.Value.(*parser.Variable); ok {
923			removeProperty(mod, "srcs")
924			mod.Properties = append(mod.Properties,
925				&parser.Property{Name: srcPropertyName,
926					NamePos:  srcs.NamePos,
927					ColonPos: srcs.ColonPos,
928					Value:    resolveLocalModule(mod, srcs.Value)})
929		} else {
930			renameProperty(mod, "srcs", "apk")
931		}
932	}
933}
934
935type patchListModFunction func(*parser.Module, []byte, *parser.PatchList) error
936
937func runPatchListMod(modFunc patchListModFunction) func(*Fixer) error {
938	return func(f *Fixer) error {
939		// Make sure all the offsets are accurate
940		buf, err := f.reparse()
941		if err != nil {
942			return err
943		}
944
945		var patchlist parser.PatchList
946		for _, def := range f.tree.Defs {
947			mod, ok := def.(*parser.Module)
948			if !ok {
949				continue
950			}
951
952			err := modFunc(mod, buf, &patchlist)
953			if err != nil {
954				return err
955			}
956		}
957
958		newBuf := new(bytes.Buffer)
959		err = patchlist.Apply(bytes.NewReader(buf), newBuf)
960		if err != nil {
961			return err
962		}
963
964		// Save a copy of the buffer to print for errors below
965		bufCopy := append([]byte(nil), newBuf.Bytes()...)
966
967		newTree, err := parse(f.tree.Name, newBuf)
968		if err != nil {
969			return fmt.Errorf("Failed to parse: %v\nBuffer:\n%s", err, string(bufCopy))
970		}
971
972		f.tree = newTree
973
974		return nil
975	}
976}
977
978var commonPropertyPriorities = []string{
979	"name",
980	"defaults",
981	"device_supported",
982	"host_supported",
983	"installable",
984}
985
986func reorderCommonProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
987	if len(mod.Properties) == 0 {
988		return nil
989	}
990
991	pos := mod.LBracePos.Offset + 1
992	stage := ""
993
994	for _, name := range commonPropertyPriorities {
995		idx := propertyIndex(mod.Properties, name)
996		if idx == -1 {
997			continue
998		}
999		if idx == 0 {
1000			err := patchlist.Add(pos, pos, stage)
1001			if err != nil {
1002				return err
1003			}
1004			stage = ""
1005
1006			pos = mod.Properties[0].End().Offset + 1
1007			mod.Properties = mod.Properties[1:]
1008			continue
1009		}
1010
1011		prop := mod.Properties[idx]
1012		mod.Properties = append(mod.Properties[:idx], mod.Properties[idx+1:]...)
1013
1014		stage += string(buf[prop.Pos().Offset : prop.End().Offset+1])
1015
1016		err := patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, "")
1017		if err != nil {
1018			return err
1019		}
1020	}
1021
1022	if stage != "" {
1023		err := patchlist.Add(pos, pos, stage)
1024		if err != nil {
1025			return err
1026		}
1027	}
1028
1029	return nil
1030}
1031
1032func removeTags(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
1033	prop, ok := mod.GetProperty("tags")
1034	if !ok {
1035		return nil
1036	}
1037	list, ok := prop.Value.(*parser.List)
1038	if !ok {
1039		return nil
1040	}
1041
1042	replaceStr := ""
1043
1044	for _, item := range list.Values {
1045		str, ok := item.(*parser.String)
1046		if !ok {
1047			replaceStr += fmt.Sprintf("// ERROR: Unable to parse tag %q\n", item)
1048			continue
1049		}
1050
1051		switch str.Value {
1052		case "optional":
1053			continue
1054		case "debug":
1055			replaceStr += `// WARNING: Module tags are not supported in Soong.
1056				// Add this module to PRODUCT_PACKAGES_DEBUG in your product file if you want to
1057				// force installation for -userdebug and -eng builds.
1058				`
1059		case "eng":
1060			replaceStr += `// WARNING: Module tags are not supported in Soong.
1061				// Add this module to PRODUCT_PACKAGES_ENG in your product file if you want to
1062				// force installation for -eng builds.
1063				`
1064		case "tests":
1065			switch {
1066			case strings.Contains(mod.Type, "cc_test"),
1067				strings.Contains(mod.Type, "cc_library_static"),
1068				strings.Contains(mod.Type, "java_test"),
1069				mod.Type == "android_test",
1070				mod.Type == "android_test_import":
1071				continue
1072			case strings.Contains(mod.Type, "cc_lib"):
1073				replaceStr += `// WARNING: Module tags are not supported in Soong.
1074					// To make a shared library only for tests, use the "cc_test_library" module
1075					// type. If you don't use gtest, set "gtest: false".
1076					`
1077			case strings.Contains(mod.Type, "cc_bin"):
1078				replaceStr += `// WARNING: Module tags are not supported in Soong.
1079					// For native test binaries, use the "cc_test" module type. Some differences:
1080					//  - If you don't use gtest, set "gtest: false"
1081					//  - Binaries will be installed into /data/nativetest[64]/<name>/<name>
1082					//  - Both 32 & 64 bit versions will be built (as appropriate)
1083					`
1084			case strings.Contains(mod.Type, "java_lib"):
1085				replaceStr += `// WARNING: Module tags are not supported in Soong.
1086					// For JUnit or similar tests, use the "java_test" module type. A dependency on
1087					// Junit will be added by default, if it is using some other runner, set "junit: false".
1088					`
1089			case mod.Type == "android_app":
1090				replaceStr += `// WARNING: Module tags are not supported in Soong.
1091					// For JUnit or instrumentataion app tests, use the "android_test" module type.
1092					`
1093			default:
1094				replaceStr += `// WARNING: Module tags are not supported in Soong.
1095					// In most cases, tests are now identified by their module type:
1096					// cc_test, java_test, python_test
1097					`
1098			}
1099		default:
1100			replaceStr += fmt.Sprintf("// WARNING: Unknown module tag %q\n", str.Value)
1101		}
1102	}
1103
1104	return patchlist.Add(prop.Pos().Offset, prop.End().Offset+2, replaceStr)
1105}
1106
1107type propertyProvider interface {
1108	GetProperty(string) (*parser.Property, bool)
1109	RemoveProperty(string) bool
1110}
1111
1112func removeNestedProperty(mod *parser.Module, patchList *parser.PatchList, propName string) error {
1113	propNames := strings.Split(propName, ".")
1114
1115	var propProvider, toRemoveFrom propertyProvider
1116	propProvider = mod
1117
1118	var propToRemove *parser.Property
1119	for i, name := range propNames {
1120		p, ok := propProvider.GetProperty(name)
1121		if !ok {
1122			return nil
1123		}
1124		// if this is the inner most element, it's time to delete
1125		if i == len(propNames)-1 {
1126			if propToRemove == nil {
1127				// if we cannot remove the properties that the current property is nested in,
1128				// remove only the current property
1129				propToRemove = p
1130				toRemoveFrom = propProvider
1131			}
1132
1133			// remove the property from the list, in case we remove other properties in this list
1134			toRemoveFrom.RemoveProperty(propToRemove.Name)
1135			// only removing the property would leave blank line(s), remove with a patch
1136			if err := patchList.Add(propToRemove.Pos().Offset, propToRemove.End().Offset+2, ""); err != nil {
1137				return err
1138			}
1139		} else {
1140			propMap, ok := p.Value.(*parser.Map)
1141			if !ok {
1142				return nil
1143			}
1144			if len(propMap.Properties) > 1 {
1145				// if there are other properties in this struct, we need to keep this struct
1146				toRemoveFrom = nil
1147				propToRemove = nil
1148			} else if propToRemove == nil {
1149				// otherwise, we can remove the empty struct entirely
1150				toRemoveFrom = propProvider
1151				propToRemove = p
1152			}
1153			propProvider = propMap
1154		}
1155	}
1156
1157	return nil
1158}
1159
1160func removeObsoleteProperty(propName string) patchListModFunction {
1161	return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
1162		return removeNestedProperty(mod, patchList, propName)
1163	}
1164}
1165
1166func mergeMatchingModuleProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
1167	return mergeMatchingProperties(&mod.Properties, buf, patchlist)
1168}
1169
1170func mergeMatchingProperties(properties *[]*parser.Property, buf []byte, patchlist *parser.PatchList) error {
1171	seen := make(map[string]*parser.Property)
1172	for i := 0; i < len(*properties); i++ {
1173		property := (*properties)[i]
1174		if prev, exists := seen[property.Name]; exists {
1175			err := mergeProperties(prev, property, buf, patchlist)
1176			if err != nil {
1177				return err
1178			}
1179			*properties = append((*properties)[:i], (*properties)[i+1:]...)
1180		} else {
1181			seen[property.Name] = property
1182			if mapProperty, ok := property.Value.(*parser.Map); ok {
1183				err := mergeMatchingProperties(&mapProperty.Properties, buf, patchlist)
1184				if err != nil {
1185					return err
1186				}
1187			}
1188		}
1189	}
1190	return nil
1191}
1192
1193func mergeProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error {
1194	// The value of one of the properties may be a variable reference with no type assigned
1195	// Bail out in this case. Soong will notice duplicate entries and will tell to merge them.
1196	if _, isVar := a.Value.(*parser.Variable); isVar {
1197		return nil
1198	}
1199	if _, isVar := b.Value.(*parser.Variable); isVar {
1200		return nil
1201	}
1202	if a.Value.Type() != b.Value.Type() {
1203		return fmt.Errorf("type mismatch when merging properties %q: %s and %s", a.Name, a.Value.Type(), b.Value.Type())
1204	}
1205
1206	switch a.Value.Type() {
1207	case parser.StringType:
1208		return fmt.Errorf("conflicting definitions of string property %q", a.Name)
1209	case parser.ListType:
1210		return mergeListProperties(a, b, buf, patchlist)
1211	}
1212
1213	return nil
1214}
1215
1216func mergeListProperties(a, b *parser.Property, buf []byte, patchlist *parser.PatchList) error {
1217	aval, oka := a.Value.(*parser.List)
1218	bval, okb := b.Value.(*parser.List)
1219	if !oka || !okb {
1220		// Merging expressions not supported yet
1221		return nil
1222	}
1223
1224	s := string(buf[bval.LBracePos.Offset+1 : bval.RBracePos.Offset])
1225	if bval.LBracePos.Line != bval.RBracePos.Line {
1226		if s[0] != '\n' {
1227			panic("expected \n")
1228		}
1229		// If B is a multi line list, skip the first "\n" in case A already has a trailing "\n"
1230		s = s[1:]
1231	}
1232	if aval.LBracePos.Line == aval.RBracePos.Line {
1233		// A is a single line list with no trailing comma
1234		if len(aval.Values) > 0 {
1235			s = "," + s
1236		}
1237	}
1238
1239	err := patchlist.Add(aval.RBracePos.Offset, aval.RBracePos.Offset, s)
1240	if err != nil {
1241		return err
1242	}
1243	err = patchlist.Add(b.NamePos.Offset, b.End().Offset+2, "")
1244	if err != nil {
1245		return err
1246	}
1247
1248	return nil
1249}
1250
1251// removes from <items> every item present in <removals>
1252func filterExpressionList(patchList *parser.PatchList, items *parser.List, removals *parser.List) {
1253	writeIndex := 0
1254	for _, item := range items.Values {
1255		included := true
1256		for _, removal := range removals.Values {
1257			equal, err := parser.ExpressionsAreSame(item, removal)
1258			if err != nil {
1259				continue
1260			}
1261			if equal {
1262				included = false
1263				break
1264			}
1265		}
1266		if included {
1267			items.Values[writeIndex] = item
1268			writeIndex++
1269		} else {
1270			patchList.Add(item.Pos().Offset, item.End().Offset+2, "")
1271		}
1272	}
1273	items.Values = items.Values[:writeIndex]
1274}
1275
1276// Remove each modules[i].Properties[<legacyName>][j] that matches a modules[i].Properties[<canonicalName>][k]
1277func removeMatchingModuleListProperties(mod *parser.Module, patchList *parser.PatchList, canonicalName string, legacyName string) error {
1278	legacyProp, ok := mod.GetProperty(legacyName)
1279	if !ok {
1280		return nil
1281	}
1282	legacyList, ok := legacyProp.Value.(*parser.List)
1283	if !ok || len(legacyList.Values) == 0 {
1284		return nil
1285	}
1286	canonicalList, ok := getLiteralListProperty(mod, canonicalName)
1287	if !ok {
1288		return nil
1289	}
1290
1291	localPatches := parser.PatchList{}
1292	filterExpressionList(&localPatches, legacyList, canonicalList)
1293
1294	if len(legacyList.Values) == 0 {
1295		patchList.Add(legacyProp.Pos().Offset, legacyProp.End().Offset+2, "")
1296	} else {
1297		for _, p := range localPatches {
1298			patchList.Add(p.Start, p.End, p.Replacement)
1299		}
1300	}
1301
1302	return nil
1303}
1304
1305func hasNonEmptyLiteralListProperty(mod *parser.Module, name string) bool {
1306	list, found := getLiteralListProperty(mod, name)
1307	return found && len(list.Values) > 0
1308}
1309
1310func hasNonEmptyLiteralStringProperty(mod *parser.Module, name string) bool {
1311	s, found := getLiteralStringPropertyValue(mod, name)
1312	return found && len(s) > 0
1313}
1314
1315func getLiteralListProperty(mod *parser.Module, name string) (list *parser.List, found bool) {
1316	prop, ok := mod.GetProperty(name)
1317	if !ok {
1318		return nil, false
1319	}
1320	list, ok = prop.Value.(*parser.List)
1321	return list, ok
1322}
1323
1324func getLiteralListPropertyValue(mod *parser.Module, name string) (list []string, found bool) {
1325	listValue, ok := getLiteralListProperty(mod, name)
1326	if !ok {
1327		return nil, false
1328	}
1329	for _, v := range listValue.Values {
1330		stringValue, ok := v.(*parser.String)
1331		if !ok {
1332			return nil, false
1333		}
1334		list = append(list, stringValue.Value)
1335	}
1336
1337	return list, true
1338}
1339
1340func getLiteralStringProperty(mod *parser.Module, name string) (s *parser.String, found bool) {
1341	prop, ok := mod.GetProperty(name)
1342	if !ok {
1343		return nil, false
1344	}
1345	s, ok = prop.Value.(*parser.String)
1346	return s, ok
1347}
1348
1349func getLiteralStringPropertyValue(mod *parser.Module, name string) (s string, found bool) {
1350	stringValue, ok := getLiteralStringProperty(mod, name)
1351	if !ok {
1352		return "", false
1353	}
1354
1355	return stringValue.Value, true
1356}
1357
1358func getLiteralBoolProperty(mod *parser.Module, name string) (b *parser.Bool, found bool) {
1359	prop, ok := mod.GetProperty(name)
1360	if !ok {
1361		return nil, false
1362	}
1363	b, ok = prop.Value.(*parser.Bool)
1364	return b, ok
1365}
1366
1367func getLiteralBoolPropertyValue(mod *parser.Module, name string) (s bool, found bool) {
1368	boolValue, ok := getLiteralBoolProperty(mod, name)
1369	if !ok {
1370		return false, false
1371	}
1372
1373	return boolValue.Value, true
1374}
1375
1376func propertyIndex(props []*parser.Property, propertyName string) int {
1377	for i, prop := range props {
1378		if prop.Name == propertyName {
1379			return i
1380		}
1381	}
1382	return -1
1383}
1384
1385func renameProperty(mod *parser.Module, from, to string) {
1386	for _, prop := range mod.Properties {
1387		if prop.Name == from {
1388			prop.Name = to
1389		}
1390	}
1391}
1392
1393func removeProperty(mod *parser.Module, propertyName string) {
1394	newList := make([]*parser.Property, 0, len(mod.Properties))
1395	for _, prop := range mod.Properties {
1396		if prop.Name != propertyName {
1397			newList = append(newList, prop)
1398		}
1399	}
1400	mod.Properties = newList
1401}
1402
1403func inList(s string, list []string) bool {
1404	for _, v := range list {
1405		if s == v {
1406			return true
1407		}
1408	}
1409	return false
1410}
1411
1412func formatFlagProperty(mod *parser.Module, field string, buf []byte, patchlist *parser.PatchList) error {
1413	// the comment or empty lines in the value of the field are skipped
1414	listValue, ok := getLiteralListProperty(mod, field)
1415	if !ok {
1416		// if do not find
1417		return nil
1418	}
1419	for i := 0; i < len(listValue.Values); i++ {
1420		curValue, ok := listValue.Values[i].(*parser.String)
1421		if !ok {
1422			return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field)
1423		}
1424		if !strings.HasPrefix(curValue.Value, "-") {
1425			return fmt.Errorf("Expecting the string `%s` starting with '-'", curValue.Value)
1426		}
1427		if i+1 < len(listValue.Values) {
1428			nextValue, ok := listValue.Values[i+1].(*parser.String)
1429			if !ok {
1430				return fmt.Errorf("Expecting string for %s.%s fields", mod.Type, field)
1431			}
1432			if !strings.HasPrefix(nextValue.Value, "-") {
1433				// delete the line
1434				err := patchlist.Add(curValue.Pos().Offset, curValue.End().Offset+2, "")
1435				if err != nil {
1436					return err
1437				}
1438				// replace the line
1439				value := "\"" + curValue.Value + " " + nextValue.Value + "\","
1440				err = patchlist.Add(nextValue.Pos().Offset, nextValue.End().Offset+1, value)
1441				if err != nil {
1442					return err
1443				}
1444				// combined two lines to one
1445				i++
1446			}
1447		}
1448	}
1449	return nil
1450}
1451
1452func formatFlagProperties(mod *parser.Module, buf []byte, patchlist *parser.PatchList) error {
1453	relevantFields := []string{
1454		// cc flags
1455		"asflags",
1456		"cflags",
1457		"clang_asflags",
1458		"clang_cflags",
1459		"conlyflags",
1460		"cppflags",
1461		"ldflags",
1462		"tidy_flags",
1463		// java flags
1464		"aaptflags",
1465		"dxflags",
1466		"javacflags",
1467		"kotlincflags",
1468	}
1469	for _, field := range relevantFields {
1470		err := formatFlagProperty(mod, field, buf, patchlist)
1471		if err != nil {
1472			return err
1473		}
1474	}
1475	return nil
1476}
1477
1478func rewriteLicenseProperty(fs pathtools.FileSystem, relativePath string) patchListModFunction {
1479	return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
1480		return rewriteLicenseProperties(mod, patchList, fs, relativePath)
1481	}
1482}
1483
1484// rewrite the "android_license_kinds" and "android_license_files" properties to a package module
1485// (and a license module when needed).
1486func rewriteLicenseProperties(mod *parser.Module, patchList *parser.PatchList, fs pathtools.FileSystem,
1487	relativePath string) error {
1488	// if a package module has been added, no more action is needed.
1489	for _, patch := range *patchList {
1490		if strings.Contains(patch.Replacement, "package {") {
1491			return nil
1492		}
1493	}
1494
1495	// initial the fs
1496	if fs == nil {
1497		fs = pathtools.NewOsFs(os.Getenv("ANDROID_BUILD_TOP"))
1498	}
1499
1500	// initial the relativePath
1501	if len(relativePath) == 0 {
1502		relativePath = getModuleRelativePath()
1503	}
1504	// validate the relativePath
1505	ok := hasFile(relativePath+"/Android.mk", fs)
1506	// some modules in the existing test cases in the androidmk_test.go do not have a valid path
1507	if !ok && len(relativePath) > 0 {
1508		return fmt.Errorf("Cannot find an Android.mk file at path %q", relativePath)
1509	}
1510
1511	licenseKindsPropertyName := "android_license_kinds"
1512	licenseFilesPropertyName := "android_license_files"
1513
1514	androidBpFileErr := "// Error: No Android.bp file is found at path\n" +
1515		"// %s\n" +
1516		"// Please add one there with the needed license module first.\n" +
1517		"// Then reset the default_applicable_licenses property below with the license module name.\n"
1518	licenseModuleErr := "// Error: Cannot get the name of the license module in the\n" +
1519		"// %s file.\n" +
1520		"// If no such license module exists, please add one there first.\n" +
1521		"// Then reset the default_applicable_licenses property below with the license module name.\n"
1522
1523	defaultApplicableLicense := "Android-Apache-2.0"
1524	var licenseModuleName, licensePatch string
1525	var hasFileInParentDir bool
1526
1527	// when LOCAL_NOTICE_FILE is not empty
1528	if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) {
1529		hasFileInParentDir = hasValueStartWithTwoDotsLiteralList(mod, licenseFilesPropertyName)
1530		// if have LOCAL_NOTICE_FILE outside the current directory, need to find and refer to the license
1531		// module in the LOCAL_NOTICE_FILE location directly and no new license module needs to be created
1532		if hasFileInParentDir {
1533			bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName, fs, relativePath)
1534			if !ok {
1535				bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName, fs, relativePath)
1536				if err != nil {
1537					return err
1538				}
1539				licensePatch += fmt.Sprintf(androidBpFileErr, bpDir)
1540				defaultApplicableLicense = ""
1541			} else {
1542				licenseModuleName, _ = getModuleName(bpPath, "license", fs)
1543				if len(licenseModuleName) == 0 {
1544					licensePatch += fmt.Sprintf(licenseModuleErr, bpPath)
1545				}
1546				defaultApplicableLicense = licenseModuleName
1547			}
1548		} else {
1549			// if have LOCAL_NOTICE_FILE in the current directory, need to create a new license module
1550			if len(relativePath) == 0 {
1551				return fmt.Errorf("Cannot obtain the relative path of the Android.mk file")
1552			}
1553			licenseModuleName = strings.Replace(relativePath, "/", "_", -1) + "_license"
1554			defaultApplicableLicense = licenseModuleName
1555		}
1556	}
1557
1558	//add the package module
1559	if hasNonEmptyLiteralListProperty(mod, licenseKindsPropertyName) {
1560		licensePatch += "package {\n" +
1561			"    // See: http://go/android-license-faq\n" +
1562			"    default_applicable_licenses: [\n" +
1563			"         \"" + defaultApplicableLicense + "\",\n" +
1564			"    ],\n" +
1565			"}\n" +
1566			"\n"
1567	}
1568
1569	// append the license module when necessary
1570	// when LOCAL_NOTICE_FILE is not empty and in the current directory, create a new license module
1571	// otherwise, use the above default license directly
1572	if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) && !hasFileInParentDir {
1573		licenseKinds, err := mergeLiteralListPropertyValue(mod, licenseKindsPropertyName)
1574		if err != nil {
1575			return err
1576		}
1577		licenseFiles, err := mergeLiteralListPropertyValue(mod, licenseFilesPropertyName)
1578		if err != nil {
1579			return err
1580		}
1581		licensePatch += "license {\n" +
1582			"    name: \"" + licenseModuleName + "\",\n" +
1583			"    visibility: [\":__subpackages__\"],\n" +
1584			"    license_kinds: [\n" +
1585			licenseKinds +
1586			"    ],\n" +
1587			"    license_text: [\n" +
1588			licenseFiles +
1589			"    ],\n" +
1590			"}\n" +
1591			"\n"
1592	}
1593
1594	// add to the patchList
1595	pos := mod.Pos().Offset
1596	err := patchList.Add(pos, pos, licensePatch)
1597	if err != nil {
1598		return err
1599	}
1600	return nil
1601}
1602
1603// merge the string vaules in a list property of a module into one string with expected format
1604func mergeLiteralListPropertyValue(mod *parser.Module, property string) (s string, err error) {
1605	listValue, ok := getLiteralListPropertyValue(mod, property)
1606	if !ok {
1607		// if do not find
1608		return "", fmt.Errorf("Cannot retrieve the %s.%s field", mod.Type, property)
1609	}
1610	for i := 0; i < len(listValue); i++ {
1611		s += "         \"" + listValue[i] + "\",\n"
1612	}
1613	return s, nil
1614}
1615
1616// check whether a string list property has any value starting with `../`
1617func hasValueStartWithTwoDotsLiteralList(mod *parser.Module, property string) bool {
1618	listValue, ok := getLiteralListPropertyValue(mod, property)
1619	if ok {
1620		for i := 0; i < len(listValue); i++ {
1621			if strings.HasPrefix(listValue[i], "../") {
1622				return true
1623			}
1624		}
1625	}
1626	return false
1627}
1628
1629// get the relative path from ANDROID_BUILD_TOP to the Android.mk file to be converted
1630func getModuleRelativePath() string {
1631	// get the absolute path of the top of the tree
1632	rootPath := os.Getenv("ANDROID_BUILD_TOP")
1633	// get the absolute path of the `Android.mk` file to be converted
1634	absPath := getModuleAbsolutePath()
1635	// get the relative path of the `Android.mk` file to top of the tree
1636	relModulePath, err := filepath.Rel(rootPath, absPath)
1637	if err != nil {
1638		return ""
1639	}
1640	return relModulePath
1641}
1642
1643// get the absolute path of the Android.mk file to be converted
1644func getModuleAbsolutePath() string {
1645	// get the absolute path at where the `androidmk` commend is executed
1646	curAbsPath, err := filepath.Abs(".")
1647	if err != nil {
1648		return ""
1649	}
1650	// the argument for the `androidmk` command could be
1651	// 1. "./a/b/c/Android.mk"; 2. "a/b/c/Android.mk"; 3. "Android.mk"
1652	argPath := flag.Arg(0)
1653	if strings.HasPrefix(argPath, "./") {
1654		argPath = strings.TrimPrefix(argPath, ".")
1655	}
1656	argPath = strings.TrimSuffix(argPath, "Android.mk")
1657	if strings.HasSuffix(argPath, "/") {
1658		argPath = strings.TrimSuffix(argPath, "/")
1659	}
1660	if len(argPath) > 0 && !strings.HasPrefix(argPath, "/") {
1661		argPath = "/" + argPath
1662	}
1663	// get the absolute path of the `Android.mk` file to be converted
1664	absPath := curAbsPath + argPath
1665	return absPath
1666}
1667
1668// check whether a file exists in a filesystem
1669func hasFile(path string, fs pathtools.FileSystem) bool {
1670	ok, _, _ := fs.Exists(path)
1671	return ok
1672}
1673
1674// get the directory where an `Android.bp` file and the property files are expected to locate
1675func getDirFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, error) {
1676	listValue, ok := getLiteralListPropertyValue(mod, property)
1677	if !ok {
1678		// if do not find
1679		return "", fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property)
1680	}
1681	if len(listValue) == 0 {
1682		// if empty
1683		return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property)
1684	}
1685	if relativePath == "" {
1686		relativePath = "."
1687	}
1688	_, isDir, _ := fs.Exists(relativePath)
1689	if !isDir {
1690		return "", fmt.Errorf("Cannot find the path %q", relativePath)
1691	}
1692	path := relativePath
1693	for {
1694		if !strings.HasPrefix(listValue[0], "../") {
1695			break
1696		}
1697		path = filepath.Dir(path)
1698		listValue[0] = strings.TrimPrefix(listValue[0], "../")
1699	}
1700	_, isDir, _ = fs.Exists(path)
1701	if !isDir {
1702		return "", fmt.Errorf("Cannot find the path %q", path)
1703	}
1704	return path, nil
1705}
1706
1707// get the path of the `Android.bp` file at the expected location where the property files locate
1708func getPathFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, bool) {
1709	dir, err := getDirFromProperty(mod, property, fs, relativePath)
1710	if err != nil {
1711		return "", false
1712	}
1713	ok := hasFile(dir+"/Android.bp", fs)
1714	if !ok {
1715		return "", false
1716	}
1717	return dir + "/Android.bp", true
1718}
1719
1720// parse an Android.bp file to get the name of the first module with type of moduleType
1721func getModuleName(path string, moduleType string, fs pathtools.FileSystem) (string, error) {
1722	tree, err := parserPath(path, fs)
1723	if err != nil {
1724		return "", err
1725	}
1726	for _, def := range tree.Defs {
1727		mod, ok := def.(*parser.Module)
1728		if !ok || mod.Type != moduleType {
1729			continue
1730		}
1731		prop, ok := mod.GetProperty("name")
1732		if !ok {
1733			return "", fmt.Errorf("Cannot get the %s."+"name property", mod.Type)
1734		}
1735		propVal, ok := prop.Value.(*parser.String)
1736		if ok {
1737			return propVal.Value, nil
1738		}
1739	}
1740	return "", fmt.Errorf("Cannot find the value of the %s."+"name property", moduleType)
1741}
1742
1743// parse an Android.bp file with the specific path
1744func parserPath(path string, fs pathtools.FileSystem) (tree *parser.File, err error) {
1745	f, err := fs.Open(path)
1746	if err != nil {
1747		return tree, err
1748	}
1749	defer f.Close()
1750	fileContent, _ := ioutil.ReadAll(f)
1751	tree, err = parse(path, bytes.NewBufferString(string(fileContent)))
1752	if err != nil {
1753		return tree, err
1754	}
1755	return tree, nil
1756}
1757
1758// remove the incorrect property that Soong does not support
1759func removeIncorrectProperties(propName string) patchListModFunction {
1760	return removeObsoleteProperty(propName)
1761}
1762
1763// the modules on the same Android.mk file are expected to have the same license
1764func haveSameLicense(f *Fixer) error {
1765	androidLicenseProperties := []string{
1766		"android_license_kinds",
1767		"android_license_conditions",
1768		"android_license_files",
1769	}
1770
1771	var prevModuleName string
1772	var prevLicenseKindsVals, prevLicenseConditionsVals, prevLicenseFilesVals []string
1773	prevLicenseVals := [][]string{
1774		prevLicenseKindsVals,
1775		prevLicenseConditionsVals,
1776		prevLicenseFilesVals,
1777	}
1778
1779	for _, def := range f.tree.Defs {
1780		mod, ok := def.(*parser.Module)
1781		if !ok {
1782			continue
1783		}
1784		for idx, property := range androidLicenseProperties {
1785			curModuleName, ok := getLiteralStringPropertyValue(mod, "name")
1786			// some modules in the existing test cases in the androidmk_test.go do not have name property
1787			hasNameProperty := hasProperty(mod, "name")
1788			if hasNameProperty && (!ok || len(curModuleName) == 0) {
1789				return fmt.Errorf("Cannot retrieve the name property of a module of %s type.", mod.Type)
1790			}
1791			curVals, ok := getLiteralListPropertyValue(mod, property)
1792			// some modules in the existing test cases in the androidmk_test.go do not have license-related property
1793			hasLicenseProperty := hasProperty(mod, property)
1794			if hasLicenseProperty && (!ok || len(curVals) == 0) {
1795				// if do not find the property, or no value is found for the property
1796				return fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property)
1797			}
1798			if len(prevLicenseVals[idx]) > 0 {
1799				if !reflect.DeepEqual(prevLicenseVals[idx], curVals) {
1800					return fmt.Errorf("Modules %s and %s are expected to have the same %s property.",
1801						prevModuleName, curModuleName, property)
1802				}
1803			}
1804			sort.Strings(curVals)
1805			prevLicenseVals[idx] = curVals
1806			prevModuleName = curModuleName
1807		}
1808	}
1809	return nil
1810}
1811
1812func hasProperty(mod *parser.Module, propName string) bool {
1813	_, ok := mod.GetProperty(propName)
1814	return ok
1815}
1816