1// Copyright 2022 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package android 16 17import ( 18 "fmt" 19 "strings" 20 21 "github.com/google/blueprint/proptools" 22) 23 24func init() { 25 ctx := InitRegistrationContext 26 ctx.RegisterModuleType("buildinfo_prop", buildinfoPropFactory) 27} 28 29type buildinfoPropProperties struct { 30 // Whether this module is directly installable to one of the partitions. Default: true. 31 Installable *bool 32} 33 34type buildinfoPropModule struct { 35 ModuleBase 36 37 properties buildinfoPropProperties 38 39 outputFilePath OutputPath 40 installPath InstallPath 41} 42 43var _ OutputFileProducer = (*buildinfoPropModule)(nil) 44 45func (p *buildinfoPropModule) installable() bool { 46 return proptools.BoolDefault(p.properties.Installable, true) 47} 48 49// OutputFileProducer 50func (p *buildinfoPropModule) OutputFiles(tag string) (Paths, error) { 51 if tag != "" { 52 return nil, fmt.Errorf("unsupported tag %q", tag) 53 } 54 return Paths{p.outputFilePath}, nil 55} 56 57func getBuildVariant(config Config) string { 58 if config.Eng() { 59 return "eng" 60 } else if config.Debuggable() { 61 return "userdebug" 62 } else { 63 return "user" 64 } 65} 66 67func getBuildFlavor(config Config) string { 68 buildFlavor := config.DeviceProduct() + "-" + getBuildVariant(config) 69 if InList("address", config.SanitizeDevice()) && !strings.Contains(buildFlavor, "_asan") { 70 buildFlavor += "_asan" 71 } 72 return buildFlavor 73} 74 75func shouldAddBuildThumbprint(config Config) bool { 76 knownOemProperties := []string{ 77 "ro.product.brand", 78 "ro.product.name", 79 "ro.product.device", 80 } 81 82 for _, knownProp := range knownOemProperties { 83 if InList(knownProp, config.OemProperties()) { 84 return true 85 } 86 } 87 return false 88} 89 90func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { 91 if ctx.ModuleName() != "buildinfo.prop" || ctx.ModuleDir() != "build/soong" { 92 ctx.ModuleErrorf("There can only be one buildinfo_prop module in build/soong") 93 return 94 } 95 p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath 96 if !ctx.Config().KatiEnabled() { 97 WriteFileRule(ctx, p.outputFilePath, "# no buildinfo.prop if kati is disabled") 98 return 99 } 100 101 rule := NewRuleBuilder(pctx, ctx) 102 103 config := ctx.Config() 104 buildVariant := getBuildVariant(config) 105 buildFlavor := getBuildFlavor(config) 106 107 cmd := rule.Command().BuiltTool("buildinfo") 108 109 if config.BoardUseVbmetaDigestInFingerprint() { 110 cmd.Flag("--use-vbmeta-digest-in-fingerprint") 111 } 112 113 cmd.FlagWithArg("--build-flavor=", buildFlavor) 114 cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx)) 115 cmd.FlagWithArg("--build-id=", config.BuildId()) 116 cmd.FlagWithArg("--build-keys=", config.BuildKeys()) 117 118 // Note: depending on BuildNumberFile will cause the build.prop file to be rebuilt 119 // every build, but that's intentional. 120 cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx)) 121 if shouldAddBuildThumbprint(config) { 122 // In the previous make implementation, a dependency was not added on the thumbprint file 123 cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String()) 124 } 125 126 cmd.FlagWithArg("--build-type=", config.BuildType()) 127 cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME")) 128 cmd.FlagWithArg("--build-variant=", buildVariant) 129 cmd.FlagForEachArg("--cpu-abis=", config.DeviceAbi()) 130 131 // Technically we should also have a dependency on BUILD_DATETIME_FILE, 132 // but it can be either an absolute or relative path, which is hard to turn into 133 // a Path object. So just rely on the BuildNumberFile always changing to cause 134 // us to rebuild. 135 cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE")) 136 137 if len(config.ProductLocales()) > 0 { 138 cmd.FlagWithArg("--default-locale=", config.ProductLocales()[0]) 139 } 140 141 cmd.FlagForEachArg("--default-wifi-channels=", config.ProductDefaultWifiChannels()) 142 cmd.FlagWithArg("--device=", config.DeviceName()) 143 if config.DisplayBuildNumber() { 144 cmd.Flag("--display-build-number") 145 } 146 147 cmd.FlagWithArg("--platform-base-os=", config.PlatformBaseOS()) 148 cmd.FlagWithArg("--platform-display-version=", config.PlatformDisplayVersionName()) 149 cmd.FlagWithArg("--platform-min-supported-target-sdk-version=", config.PlatformMinSupportedTargetSdkVersion()) 150 cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx)) 151 cmd.FlagWithArg("--platform-preview-sdk-version=", config.PlatformPreviewSdkVersion()) 152 cmd.FlagWithArg("--platform-sdk-version=", config.PlatformSdkVersion().String()) 153 cmd.FlagWithArg("--platform-security-patch=", config.PlatformSecurityPatch()) 154 cmd.FlagWithArg("--platform-version=", config.PlatformVersionName()) 155 cmd.FlagWithArg("--platform-version-codename=", config.PlatformSdkCodename()) 156 cmd.FlagForEachArg("--platform-version-all-codenames=", config.PlatformVersionActiveCodenames()) 157 cmd.FlagWithArg("--platform-version-known-codenames=", config.PlatformVersionKnownCodenames()) 158 cmd.FlagWithArg("--platform-version-last-stable=", config.PlatformVersionLastStable()) 159 cmd.FlagWithArg("--product=", config.DeviceProduct()) 160 161 cmd.FlagWithOutput("--out=", p.outputFilePath) 162 163 rule.Build(ctx.ModuleName(), "generating buildinfo props") 164 165 if !p.installable() { 166 p.SkipInstall() 167 } 168 169 p.installPath = PathForModuleInstall(ctx) 170 ctx.InstallFile(p.installPath, p.Name(), p.outputFilePath) 171} 172 173func (p *buildinfoPropModule) AndroidMkEntries() []AndroidMkEntries { 174 return []AndroidMkEntries{{ 175 Class: "ETC", 176 OutputFile: OptionalPathForPath(p.outputFilePath), 177 ExtraEntries: []AndroidMkExtraEntriesFunc{ 178 func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) { 179 entries.SetString("LOCAL_MODULE_PATH", p.installPath.String()) 180 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base()) 181 entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable()) 182 }, 183 }, 184 }} 185} 186 187// buildinfo_prop module generates a build.prop file, which contains a set of common 188// system/build.prop properties, such as ro.build.version.*. Not all properties are implemented; 189// currently this module is only for microdroid. 190func buildinfoPropFactory() Module { 191 module := &buildinfoPropModule{} 192 module.AddProperties(&module.properties) 193 InitAndroidModule(module) 194 return module 195} 196