1// Copyright (C) 2020 The Android Open Source Project 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 filesystem 16 17import ( 18 "crypto/sha256" 19 "fmt" 20 "io" 21 "path/filepath" 22 "slices" 23 "sort" 24 "strconv" 25 "strings" 26 27 "android/soong/android" 28 "android/soong/cc" 29 "android/soong/java" 30 "android/soong/linkerconfig" 31 32 "github.com/google/blueprint" 33 "github.com/google/blueprint/depset" 34 "github.com/google/blueprint/proptools" 35) 36 37var pctx = android.NewPackageContext("android/soong/filesystem") 38 39func init() { 40 registerBuildComponents(android.InitRegistrationContext) 41 registerMutators(android.InitRegistrationContext) 42 pctx.HostBinToolVariable("fileslist", "fileslist") 43 pctx.HostBinToolVariable("fs_config", "fs_config") 44 pctx.HostBinToolVariable("symbols_map", "symbols_map") 45} 46 47func registerBuildComponents(ctx android.RegistrationContext) { 48 ctx.RegisterModuleType("android_filesystem", FilesystemFactory) 49 ctx.RegisterModuleType("android_filesystem_defaults", filesystemDefaultsFactory) 50 ctx.RegisterModuleType("android_system_image", SystemImageFactory) 51 ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory) 52 ctx.RegisterModuleType("avb_add_hash_footer_defaults", avbAddHashFooterDefaultsFactory) 53 ctx.RegisterModuleType("avb_gen_vbmeta_image", avbGenVbmetaImageFactory) 54 ctx.RegisterModuleType("avb_gen_vbmeta_image_defaults", avbGenVbmetaImageDefaultsFactory) 55} 56 57func registerMutators(ctx android.RegistrationContext) { 58 ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 59 ctx.BottomUp("add_autogenerated_rro_deps", addAutogeneratedRroDeps) 60 }) 61} 62 63var ( 64 // Remember to add referenced files to implicits! 65 textFileProcessorRule = pctx.AndroidStaticRule("text_file_processing", blueprint.RuleParams{ 66 Command: "build/soong/scripts/text_file_processor.py $in $out", 67 CommandDeps: []string{"build/soong/scripts/text_file_processor.py"}, 68 }) 69 70 // Remember to add the output image file as an implicit dependency! 71 installedFilesJsonRule = pctx.AndroidStaticRule("installed_files_json", blueprint.RuleParams{ 72 Command: `${fileslist} ${rootDir} > ${out}`, 73 CommandDeps: []string{"${fileslist}"}, 74 }, "rootDir") 75 76 installedFilesTxtRule = pctx.AndroidStaticRule("installed_files_txt", blueprint.RuleParams{ 77 Command: `build/make/tools/fileslist_util.py -c ${in} > ${out}`, 78 CommandDeps: []string{"build/make/tools/fileslist_util.py"}, 79 }) 80 fsConfigRule = pctx.AndroidStaticRule("fs_config_rule", blueprint.RuleParams{ 81 Command: `(cd ${rootDir}; find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,${prefix},' | ${fs_config} -C -D ${rootDir} -R "${prefix}" > ${out}`, 82 CommandDeps: []string{"${fs_config}"}, 83 }, "rootDir", "prefix") 84) 85 86type filesystem struct { 87 android.ModuleBase 88 android.PackagingBase 89 android.DefaultableModuleBase 90 91 properties FilesystemProperties 92 93 output android.Path 94 installDir android.InstallPath 95 96 fileListFile android.Path 97 98 // Keeps the entries installed from this filesystem 99 entries []string 100 101 filesystemBuilder filesystemBuilder 102 103 selinuxFc android.Path 104} 105 106type filesystemBuilder interface { 107 BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo) 108 // Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs() 109 FilterPackagingSpec(spec android.PackagingSpec) bool 110 // Function that modifies PackagingSpec in PackagingBase.GatherPackagingSpecs() to customize. 111 // For example, GSI system.img contains system_ext and product artifacts and their 112 // relPathInPackage need to be rebased to system/system_ext and system/system_product. 113 ModifyPackagingSpec(spec *android.PackagingSpec) 114 115 // Function to check if the filesystem should not use `vintf_fragments` property, 116 // but use `vintf_fragment` module type instead 117 ShouldUseVintfFragmentModuleOnly() bool 118} 119 120var _ filesystemBuilder = (*filesystem)(nil) 121 122type SymlinkDefinition struct { 123 Target *string 124 Name *string 125} 126 127// CopyWithNamePrefix returns a new [SymlinkDefinition] with prefix added to Name. 128func (s *SymlinkDefinition) CopyWithNamePrefix(prefix string) SymlinkDefinition { 129 return SymlinkDefinition{ 130 Target: s.Target, 131 Name: proptools.StringPtr(filepath.Join(prefix, proptools.String(s.Name))), 132 } 133} 134 135type FilesystemProperties struct { 136 // When set to true, sign the image with avbtool. Default is false. 137 Use_avb *bool 138 139 // Path to the private key that avbtool will use to sign this filesystem image. 140 // TODO(jiyong): allow apex_key to be specified here 141 Avb_private_key *string `android:"path"` 142 143 // Signing algorithm for avbtool. Default is SHA256_RSA4096. 144 Avb_algorithm *string 145 146 // Hash algorithm used for avbtool (for descriptors). This is passed as hash_algorithm to 147 // avbtool. Default is sha256. 148 Avb_hash_algorithm *string 149 150 // The security patch passed to as the com.android.build.<type>.security_patch avb property. 151 Security_patch *string 152 153 // Whether or not to use forward-error-correction codes when signing with AVB. Defaults to true. 154 Use_fec *bool 155 156 // The index used to prevent rollback of the image. Only used if use_avb is true. 157 Rollback_index *int64 158 159 // Rollback index location of this image. Must be 1, 2, 3, etc. 160 Rollback_index_location *int64 161 162 // Name of the partition stored in vbmeta desc. Defaults to the name of this module. 163 Partition_name *string 164 165 // Type of the filesystem. Currently, ext4, erofs, cpio, and compressed_cpio are supported. Default 166 // is ext4. 167 Type *string 168 169 // Identifies which partition this is for //visibility:any_system_image (and others) visibility 170 // checks, and will be used in the future for API surface checks. 171 Partition_type *string 172 173 // file_contexts file to make image. Currently, only ext4 is supported. These file contexts 174 // will be compiled with sefcontext_compile 175 File_contexts *string `android:"path"` 176 177 // The selinux file contexts, after having already run them through sefcontext_compile 178 Precompiled_file_contexts *string `android:"path"` 179 180 // Base directory relative to root, to which deps are installed, e.g. "system". Default is "." 181 // (root). 182 Base_dir *string 183 184 // Directories to be created under root. e.g. /dev, /proc, etc. 185 Dirs proptools.Configurable[[]string] 186 187 // List of filesystem modules to include in creating the partition. The root directory of 188 // the provided filesystem modules are included in creating the partition. 189 // This is only supported for cpio and compressed cpio filesystem types. 190 Include_files_of []string 191 192 // Symbolic links to be created under root with "ln -sf <target> <name>". 193 Symlinks []SymlinkDefinition 194 195 // Seconds since unix epoch to override timestamps of file entries 196 Fake_timestamp *string 197 198 // When set, passed to mkuserimg_mke2fs --mke2fs_uuid & --mke2fs_hash_seed. 199 // Otherwise, they'll be set as random which might cause indeterministic build output. 200 Uuid *string 201 202 // Mount point for this image. Default is "/" 203 Mount_point *string 204 205 // When set, builds etc/event-log-tags file by merging logtags from all dependencies. 206 // Default is false 207 Build_logtags *bool 208 209 // Install aconfig_flags.pb file for the modules installed in this partition. 210 Gen_aconfig_flags_pb *bool 211 212 Fsverity fsverityProperties 213 214 // If this property is set to true, the filesystem will call ctx.UncheckedModule(), causing 215 // it to not be built on checkbuilds. Used for the automatic migration from make to soong 216 // build modules, where we want to emit some not-yet-working filesystems and we don't want them 217 // to be built. 218 Unchecked_module *bool `blueprint:"mutated"` 219 220 Erofs ErofsProperties 221 222 F2fs F2fsProperties 223 224 Linker_config LinkerConfigProperties 225 226 // Determines if the module is auto-generated from Soong or not. If the module is 227 // auto-generated, its deps are exempted from visibility enforcement. 228 Is_auto_generated *bool 229 230 // Path to the dev nodes description file. This is only needed for building the ramdisk 231 // partition and should not be explicitly specified. 232 Dev_nodes_description_file *string `android:"path" blueprint:"mutated"` 233 234 // Additional dependencies used for building android products 235 Android_filesystem_deps AndroidFilesystemDeps 236 237 // Name of the output. Default is $(module_name).img 238 Stem *string 239 240 // The size of the partition on the device. It will be a build error if this built partition 241 // image exceeds this size. 242 Partition_size *int64 243 244 // Whether to format f2fs and ext4 in a way that supports casefolding 245 Support_casefolding *bool 246 247 // Whether to format f2fs and ext4 in a way that supports project quotas 248 Support_project_quota *bool 249 250 // Whether to enable per-file compression in f2fs 251 Enable_compression *bool 252 253 // Whether this partition is not supported by flashall. 254 // If true, this partition will not be included in the `updatedpackage` dist artifact. 255 No_flashall *bool 256} 257 258type AndroidFilesystemDeps struct { 259 System *string 260 System_ext *string 261} 262 263// Additional properties required to generate erofs FS partitions. 264type ErofsProperties struct { 265 // Compressor and Compression level passed to mkfs.erofs. e.g. (lz4hc,9) 266 // Please see external/erofs-utils/README for complete documentation. 267 Compressor *string 268 269 // Used as --compress-hints for mkfs.erofs 270 Compress_hints *string `android:"path"` 271 272 Sparse *bool 273} 274 275// Additional properties required to generate f2fs FS partitions. 276type F2fsProperties struct { 277 Sparse *bool 278} 279 280type LinkerConfigProperties struct { 281 282 // Build a linker.config.pb file 283 Gen_linker_config *bool 284 285 // List of files (in .json format) that will be converted to a linker config file (in .pb format). 286 // The linker config file be installed in the filesystem at /etc/linker.config.pb 287 Linker_config_srcs []string `android:"path"` 288} 289 290// android_filesystem packages a set of modules and their transitive dependencies into a filesystem 291// image. The filesystem images are expected to be mounted in the target device, which means the 292// modules in the filesystem image are built for the target device (i.e. Android, not Linux host). 293// The modules are placed in the filesystem image just like they are installed to the ordinary 294// partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory. 295func FilesystemFactory() android.Module { 296 module := &filesystem{} 297 module.filesystemBuilder = module 298 initFilesystemModule(module, module) 299 return module 300} 301 302func initFilesystemModule(module android.DefaultableModule, filesystemModule *filesystem) { 303 module.AddProperties(&filesystemModule.properties) 304 android.InitPackageModule(filesystemModule) 305 filesystemModule.PackagingBase.DepsCollectFirstTargetOnly = true 306 filesystemModule.PackagingBase.AllowHighPriorityDeps = true 307 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 308 android.InitDefaultableModule(module) 309 310 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 311 filesystemModule.setDevNodesDescriptionProp() 312 }) 313} 314 315type depTag struct { 316 blueprint.BaseDependencyTag 317 android.PackagingItemAlwaysDepTag 318} 319 320var dependencyTag = depTag{} 321 322type depTagWithVisibilityEnforcementBypass struct { 323 depTag 324} 325 326type interPartitionDepTag struct { 327 blueprint.BaseDependencyTag 328} 329 330var interPartitionDependencyTag = interPartitionDepTag{} 331 332var interPartitionInstallDependencyTag = interPartitionDepTag{} 333 334var _ android.ExcludeFromVisibilityEnforcementTag = (*depTagWithVisibilityEnforcementBypass)(nil) 335 336func (t depTagWithVisibilityEnforcementBypass) ExcludeFromVisibilityEnforcement() {} 337 338var dependencyTagWithVisibilityEnforcementBypass = depTagWithVisibilityEnforcementBypass{} 339 340// ramdiskDevNodesDescription is the name of the filegroup module that provides the file that 341// contains the description of dev nodes added to the CPIO archive for the ramdisk partition. 342const ramdiskDevNodesDescription = "ramdisk_node_list" 343 344func (f *filesystem) setDevNodesDescriptionProp() { 345 if proptools.String(f.properties.Partition_name) == "ramdisk" { 346 f.properties.Dev_nodes_description_file = proptools.StringPtr(":" + ramdiskDevNodesDescription) 347 } 348} 349 350func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) { 351 if proptools.Bool(f.properties.Is_auto_generated) { 352 f.AddDeps(ctx, dependencyTagWithVisibilityEnforcementBypass) 353 } else { 354 f.AddDeps(ctx, dependencyTag) 355 } 356 if f.properties.Android_filesystem_deps.System != nil { 357 ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System)) 358 } 359 if f.properties.Android_filesystem_deps.System_ext != nil { 360 ctx.AddDependency(ctx.Module(), interPartitionDependencyTag, proptools.String(f.properties.Android_filesystem_deps.System_ext)) 361 } 362 for _, partition := range f.properties.Include_files_of { 363 ctx.AddDependency(ctx.Module(), interPartitionInstallDependencyTag, partition) 364 } 365} 366 367type fsType int 368 369const ( 370 ext4Type fsType = iota 371 erofsType 372 f2fsType 373 compressedCpioType 374 cpioType // uncompressed 375 unknown 376) 377 378func (fs fsType) IsUnknown() bool { 379 return fs == unknown 380} 381 382// Type string that build_image.py accepts. 383func (t fsType) String() string { 384 switch t { 385 // TODO(372522486): add more types like f2fs, erofs, etc. 386 case ext4Type: 387 return "ext4" 388 case erofsType: 389 return "erofs" 390 case f2fsType: 391 return "f2fs" 392 } 393 panic(fmt.Errorf("unsupported fs type %d", t)) 394} 395 396type InstalledFilesStruct struct { 397 Txt android.Path 398 Json android.Path 399} 400 401type InstalledModuleInfo struct { 402 Name string 403 Variation string 404} 405 406type FilesystemInfo struct { 407 // The built filesystem image 408 Output android.Path 409 // Returns the output file that is signed by avbtool. If this module is not signed, returns 410 // nil. 411 SignedOutputPath android.Path 412 // An additional hermetic filesystem image. 413 // e.g. this will contain inodes with pinned timestamps. 414 // This will be copied to target_files.zip 415 OutputHermetic android.Path 416 // A text file containing the list of paths installed on the partition. 417 FileListFile android.Path 418 // The root staging directory used to build the output filesystem. If consuming this, make sure 419 // to add a dependency on the Output file, as you cannot add dependencies on directories 420 // in ninja. 421 RootDir android.Path 422 // Extra root directories that are also built into the partition. Currently only used for 423 // including the recovery partition files into the vendor_boot image. 424 ExtraRootDirs android.Paths 425 // The rebased staging directory used to build the output filesystem. If consuming this, make 426 // sure to add a dependency on the Output file, as you cannot add dependencies on directories 427 // in ninja. In many cases this is the same as RootDir, only in the system partition is it 428 // different. There, it points to the "system" sub-directory of RootDir. 429 RebasedDir android.Path 430 // A text file with block data of the .img file 431 // This is an implicit output of `build_image` 432 MapFile android.Path 433 // Name of the module that produced this FilesystemInfo origionally. (though it may be 434 // re-exported by super images or boot images) 435 ModuleName string 436 // The property file generated by this module and passed to build_image. 437 // It's exported here so that system_other can reuse system's property file. 438 BuildImagePropFile android.Path 439 // Paths to all the tools referenced inside of the build image property file. 440 BuildImagePropFileDeps android.Paths 441 // Packaging specs to be installed on the system_other image, for the initial boot's dexpreopt. 442 SpecsForSystemOther map[string]android.PackagingSpec 443 444 FullInstallPaths []FullInstallPathInfo 445 446 // Installed files dep set of this module and its dependency filesystem modules 447 InstalledFilesDepSet depset.DepSet[InstalledFilesStruct] 448 449 // Path to compress hints file for erofs filesystems 450 // This will be nil for other fileystems like ext4 451 ErofsCompressHints android.Path 452 453 SelinuxFc android.Path 454 455 FilesystemConfig android.Path 456 457 Owners []InstalledModuleInfo 458 459 HasFsverity bool 460 461 PropFileForMiscInfo android.Path 462 463 // Additional avb and partition size information. 464 // `system_other` will use this information of `system` dep for misc_info.txt processing. 465 PartitionSize *int64 466 UseAvb bool 467 AvbAlgorithm string 468 AvbHashAlgorithm string 469 AvbKey android.Path 470 PartitionName string 471 NoFlashall bool 472 // HasOrIsRecovery returns true for recovery and for ramdisks with a recovery partition. 473 HasOrIsRecovery bool 474} 475 476// FullInstallPathInfo contains information about the "full install" paths of all the files 477// inside this partition. The full install paths are the files installed in 478// out/target/product/<device>/<partition>. This is essentially legacy behavior, maintained for 479// tools like adb sync and adevice, but we should update them to query the build system for the 480// installed files no matter where they are. 481type FullInstallPathInfo struct { 482 // RequiresFullInstall tells us if the origional module did the install to FullInstallPath 483 // already. If it's false, the android_device module needs to emit the install rule. 484 RequiresFullInstall bool 485 // The "full install" paths for the files in this filesystem. This is the paths in the 486 // out/target/product/<device>/<partition> folder. They're not used by this filesystem, 487 // but can be depended on by the top-level android_device module to cause the staging 488 // directories to be built. 489 FullInstallPath android.InstallPath 490 491 // The file that's copied to FullInstallPath. May be nil if SymlinkTarget is set or IsDir is 492 // true. 493 SourcePath android.Path 494 495 // The target of the symlink, if this file is a symlink. 496 SymlinkTarget string 497 498 // If this file is a directory. Only used for empty directories, which are mostly mount points. 499 IsDir bool 500} 501 502var FilesystemProvider = blueprint.NewProvider[FilesystemInfo]() 503 504type FilesystemDefaultsInfo struct{} 505 506var FilesystemDefaultsInfoProvider = blueprint.NewProvider[FilesystemDefaultsInfo]() 507 508func GetFsTypeFromString(ctx android.EarlyModuleContext, typeStr string) fsType { 509 switch typeStr { 510 case "ext4": 511 return ext4Type 512 case "erofs": 513 return erofsType 514 case "f2fs": 515 return f2fsType 516 case "compressed_cpio": 517 return compressedCpioType 518 case "cpio": 519 return cpioType 520 default: 521 return unknown 522 } 523} 524 525func (f *filesystem) fsType(ctx android.ModuleContext) fsType { 526 typeStr := proptools.StringDefault(f.properties.Type, "ext4") 527 fsType := GetFsTypeFromString(ctx, typeStr) 528 if fsType == unknown { 529 ctx.PropertyErrorf("type", "%q not supported", typeStr) 530 } 531 return fsType 532} 533 534func (f *filesystem) installFileName() string { 535 return proptools.StringDefault(f.properties.Stem, f.BaseModuleName()+".img") 536} 537 538func (f *filesystem) partitionName() string { 539 return proptools.StringDefault(f.properties.Partition_name, f.Name()) 540} 541 542func (f *filesystem) FilterPackagingSpec(ps android.PackagingSpec) bool { 543 // Filesystem module respects the installation semantic. A PackagingSpec from a module with 544 // IsSkipInstall() is skipped. 545 if ps.SkipInstall() { 546 return false 547 } 548 // "apex" is a fake partition used to install files in out/target/product/<device>/apex/. 549 // Don't include these files in the partition. We should also look into removing the following 550 // TODO to check the PackagingSpec's partition against this filesystem's partition for all 551 // modules, not just autogenerated ones, which will fix this as well. 552 if ps.Partition() == "apex" { 553 return false 554 } 555 if proptools.Bool(f.properties.Is_auto_generated) { // TODO (spandandas): Remove this. 556 pt := f.PartitionType() 557 return ps.Partition() == pt || strings.HasPrefix(ps.Partition(), pt+"/") 558 } 559 return true 560} 561 562func (f *filesystem) ModifyPackagingSpec(ps *android.PackagingSpec) { 563 // Sometimes, android.modulePartition() returns a path with >1 path components. 564 // This makes the partition field of packagingSpecs have multiple components, like 565 // "system/product". Right now, the filesystem module doesn't look at the partition field 566 // when deciding what path to install the file under, only the RelPathInPackage field, so 567 // we move the later path components from partition to relPathInPackage. This should probably 568 // be revisited in the future. 569 prefix := f.PartitionType() + "/" 570 if strings.HasPrefix(ps.Partition(), prefix) { 571 subPartition := strings.TrimPrefix(ps.Partition(), prefix) 572 ps.SetPartition(f.PartitionType()) 573 ps.SetRelPathInPackage(filepath.Join(subPartition, ps.RelPathInPackage())) 574 } 575} 576 577func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir android.Path, image android.Path) InstalledFilesStruct { 578 fileName := "installed-files" 579 if len(partition) > 0 { 580 fileName += fmt.Sprintf("-%s", partition) 581 } 582 txt := android.PathForModuleOut(ctx, fmt.Sprintf("%s.txt", fileName)) 583 json := android.PathForModuleOut(ctx, fmt.Sprintf("%s.json", fileName)) 584 585 ctx.Build(pctx, android.BuildParams{ 586 Rule: installedFilesJsonRule, 587 Implicit: image, 588 Output: json, 589 Description: "Installed file list json", 590 Args: map[string]string{ 591 "rootDir": rootDir.String(), 592 }, 593 }) 594 595 ctx.Build(pctx, android.BuildParams{ 596 Rule: installedFilesTxtRule, 597 Input: json, 598 Output: txt, 599 Description: "Installed file list txt", 600 }) 601 602 return InstalledFilesStruct{ 603 Txt: txt, 604 Json: json, 605 } 606} 607 608func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { 609 validatePartitionType(ctx, f) 610 if f.filesystemBuilder.ShouldUseVintfFragmentModuleOnly() { 611 f.validateVintfFragments(ctx) 612 } 613 614 if len(f.properties.Include_files_of) > 0 && !android.InList(f.fsType(ctx), []fsType{compressedCpioType, cpioType}) { 615 ctx.PropertyErrorf("include_files_of", "include_files_of is only supported for cpio and compressed cpio filesystem types.") 616 } 617 618 rootDir := android.PathForModuleOut(ctx, f.rootDirString()).OutputPath 619 rebasedDir := rootDir 620 if f.properties.Base_dir != nil { 621 rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir) 622 } 623 builder := android.NewRuleBuilder(pctx, ctx) 624 625 // Wipe the root dir to get rid of leftover files from prior builds 626 builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir) 627 specs := f.gatherFilteredPackagingSpecs(ctx) 628 629 var fullInstallPaths []FullInstallPathInfo 630 for _, specRel := range android.SortedKeys(specs) { 631 spec := specs[specRel] 632 fullInstallPaths = append(fullInstallPaths, FullInstallPathInfo{ 633 FullInstallPath: spec.FullInstallPath(), 634 RequiresFullInstall: spec.RequiresFullInstall(), 635 SourcePath: spec.SrcPath(), 636 SymlinkTarget: spec.ToGob().SymlinkTarget, 637 }) 638 } 639 640 f.entries = f.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir) 641 f.buildNonDepsFiles(ctx, builder, rootDir, rebasedDir, &fullInstallPaths) 642 f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir, &fullInstallPaths) 643 f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths) 644 f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths) 645 f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths) 646 // Assemeble the staging dir and output a timestamp 647 builder.Command().Text("touch").Output(f.fileystemStagingDirTimestamp(ctx)) 648 builder.Build("assemble_filesystem_staging_dir", fmt.Sprintf("Assemble filesystem staging dir %s", f.BaseModuleName())) 649 650 // Create a new rule builder for build_image 651 builder = android.NewRuleBuilder(pctx, ctx) 652 var mapFile android.Path 653 var outputHermetic android.WritablePath 654 var buildImagePropFile android.Path 655 var buildImagePropFileDeps android.Paths 656 var extraRootDirs android.Paths 657 var propFileForMiscInfo android.Path 658 switch f.fsType(ctx) { 659 case ext4Type, erofsType, f2fsType: 660 buildImagePropFile, buildImagePropFileDeps = f.buildPropFile(ctx) 661 propFileForMiscInfo = f.buildPropFileForMiscInfo(ctx) 662 output := android.PathForModuleOut(ctx, f.installFileName()) 663 f.buildImageUsingBuildImage(ctx, builder, buildImageParams{rootDir, buildImagePropFile, buildImagePropFileDeps, output}) 664 f.output = output 665 // Create the hermetic img file using a separate rule builder so that it can be built independently 666 hermeticBuilder := android.NewRuleBuilder(pctx, ctx) 667 outputHermetic = android.PathForModuleOut(ctx, "for_target_files", f.installFileName()) 668 propFileHermetic := f.propFileForHermeticImg(ctx, hermeticBuilder, buildImagePropFile) 669 f.buildImageUsingBuildImage(ctx, hermeticBuilder, buildImageParams{rootDir, propFileHermetic, buildImagePropFileDeps, outputHermetic}) 670 mapFile = f.getMapFile(ctx) 671 case compressedCpioType: 672 f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, true) 673 case cpioType: 674 f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, false) 675 default: 676 return 677 } 678 679 f.installDir = android.PathForModuleInstall(ctx, "etc") 680 ctx.InstallFile(f.installDir, f.installFileName(), f.output) 681 ctx.SetOutputFiles([]android.Path{f.output}, "") 682 683 if f.partitionName() == "recovery" { 684 rootDir = rootDir.Join(ctx, "root") 685 } 686 687 fileListFile := android.PathForModuleOut(ctx, "fileList") 688 android.WriteFileRule(ctx, fileListFile, f.installedFilesList()) 689 690 var partitionNameForInstalledFiles string 691 switch f.partitionName() { 692 case "system": 693 partitionNameForInstalledFiles = "" 694 case "vendor_ramdisk": 695 partitionNameForInstalledFiles = "vendor-ramdisk" 696 default: 697 partitionNameForInstalledFiles = f.partitionName() 698 } 699 700 var erofsCompressHints android.Path 701 if f.properties.Erofs.Compress_hints != nil { 702 erofsCompressHints = android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints) 703 } 704 705 fsInfo := FilesystemInfo{ 706 Output: f.OutputPath(), 707 SignedOutputPath: f.SignedOutputPath(), 708 OutputHermetic: outputHermetic, 709 FileListFile: fileListFile, 710 RootDir: rootDir, 711 ExtraRootDirs: extraRootDirs, 712 RebasedDir: rebasedDir, 713 MapFile: mapFile, 714 ModuleName: ctx.ModuleName(), 715 BuildImagePropFile: buildImagePropFile, 716 BuildImagePropFileDeps: buildImagePropFileDeps, 717 SpecsForSystemOther: f.systemOtherFiles(ctx), 718 FullInstallPaths: fullInstallPaths, 719 InstalledFilesDepSet: depset.New( 720 depset.POSTORDER, 721 []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rootDir, f.output)}, 722 includeFilesInstalledFiles(ctx), 723 ), 724 ErofsCompressHints: erofsCompressHints, 725 SelinuxFc: f.selinuxFc, 726 FilesystemConfig: f.generateFilesystemConfig(ctx, rootDir, rebasedDir), 727 Owners: f.gatherOwners(specs), 728 HasFsverity: f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil, 729 PropFileForMiscInfo: propFileForMiscInfo, 730 PartitionSize: f.properties.Partition_size, 731 PartitionName: f.partitionName(), 732 HasOrIsRecovery: f.hasOrIsRecovery(ctx), 733 NoFlashall: proptools.Bool(f.properties.No_flashall), 734 } 735 if proptools.Bool(f.properties.Use_avb) { 736 fsInfo.UseAvb = true 737 fsInfo.AvbAlgorithm = proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096") 738 fsInfo.AvbHashAlgorithm = proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") 739 if f.properties.Avb_private_key != nil { 740 fsInfo.AvbKey = android.PathForModuleSrc(ctx, *f.properties.Avb_private_key) 741 } 742 } 743 744 android.SetProvider(ctx, FilesystemProvider, fsInfo) 745 746 android.SetProvider(ctx, android.PartitionTypeInfoProvider, android.PartitionTypeInfo{ 747 PartitionType: f.PartitionType(), 748 }) 749 750 f.fileListFile = fileListFile 751 752 if proptools.Bool(f.properties.Unchecked_module) { 753 ctx.UncheckedModule() 754 } 755 756 f.setVbmetaPartitionProvider(ctx) 757 758 // Dump metadata that can not be done in android/compliance-metadata.go 759 complianceMetadataInfo := ctx.ComplianceMetadataInfo() 760 filesContained := make([]string, 0, len(fullInstallPaths)) 761 for _, file := range fullInstallPaths { 762 filesContained = append(filesContained, file.FullInstallPath.String()) 763 } 764 complianceMetadataInfo.SetFilesContained(filesContained) 765} 766 767func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath { 768 return android.PathForModuleOut(ctx, "staging_dir.timestamp") 769} 770 771func (f *filesystem) generateFilesystemConfig(ctx android.ModuleContext, rootDir android.Path, rebasedDir android.Path) android.Path { 772 rootDirString := rootDir.String() 773 prefix := f.partitionName() + "/" 774 if f.partitionName() == "system" { 775 rootDirString = rebasedDir.String() 776 } 777 if f.partitionName() == "ramdisk" || f.partitionName() == "recovery" { 778 // Hardcoded to match make behavior. 779 // https://cs.android.com/android/_/android/platform/build/+/2a0ef42a432d4da00201e8eb7697dcaa68fd2389:core/Makefile;l=6957-6962;drc=9ea8ad9232cef4d0a24d70133b1b9d2ce2defe5f;bpv=1;bpt=0 780 prefix = "" 781 } 782 out := android.PathForModuleOut(ctx, "filesystem_config.txt") 783 ctx.Build(pctx, android.BuildParams{ 784 Rule: fsConfigRule, 785 Input: f.fileystemStagingDirTimestamp(ctx), // assemble the staging directory 786 Output: out, 787 Args: map[string]string{ 788 "rootDir": rootDirString, 789 "prefix": prefix, 790 }, 791 }) 792 return out 793} 794 795func (f *filesystem) setVbmetaPartitionProvider(ctx android.ModuleContext) { 796 var extractedPublicKey android.ModuleOutPath 797 if f.properties.Avb_private_key != nil { 798 key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key)) 799 extractedPublicKey = android.PathForModuleOut(ctx, f.partitionName()+".avbpubkey") 800 ctx.Build(pctx, android.BuildParams{ 801 Rule: extractPublicKeyRule, 802 Input: key, 803 Output: extractedPublicKey, 804 }) 805 } 806 807 var ril int 808 if f.properties.Rollback_index_location != nil { 809 ril = proptools.Int(f.properties.Rollback_index_location) 810 } 811 812 android.SetProvider(ctx, vbmetaPartitionProvider, vbmetaPartitionInfo{ 813 Name: f.partitionName(), 814 RollbackIndexLocation: ril, 815 PublicKey: extractedPublicKey, 816 Output: f.output, 817 }) 818} 819 820func (f *filesystem) getMapFile(ctx android.ModuleContext) android.WritablePath { 821 // create the filepath by replacing the extension of the corresponding img file 822 return android.PathForModuleOut(ctx, f.installFileName()).ReplaceExtension(ctx, "map") 823} 824 825func (f *filesystem) validateVintfFragments(ctx android.ModuleContext) { 826 visitedModule := map[string]bool{} 827 packagingSpecs := f.gatherFilteredPackagingSpecs(ctx) 828 829 moduleInFileSystem := func(mod android.Module) bool { 830 for _, ps := range android.OtherModuleProviderOrDefault( 831 ctx, mod, android.InstallFilesProvider).PackagingSpecs { 832 if _, ok := packagingSpecs[ps.RelPathInPackage()]; ok { 833 return true 834 } 835 } 836 return false 837 } 838 839 ctx.WalkDeps(func(child, parent android.Module) bool { 840 if visitedModule[child.Name()] { 841 return false 842 } 843 if !moduleInFileSystem(child) { 844 visitedModule[child.Name()] = true 845 return true 846 } 847 if vintfFragments := child.VintfFragments(ctx); vintfFragments != nil { 848 ctx.PropertyErrorf( 849 "vintf_fragments", 850 "Module %s is referenced by soong-defined filesystem %s with property vintf_fragments(%s) in use."+ 851 " Use vintf_fragment_modules property instead.", 852 child.Name(), 853 f.BaseModuleName(), 854 strings.Join(vintfFragments, ", "), 855 ) 856 } 857 visitedModule[child.Name()] = true 858 return true 859 }) 860} 861 862func (f *filesystem) appendToEntry(ctx android.ModuleContext, installedFile android.Path) { 863 partitionBaseDir := android.PathForModuleOut(ctx, f.rootDirString(), proptools.String(f.properties.Base_dir)).String() + "/" 864 865 relPath, inTargetPartition := strings.CutPrefix(installedFile.String(), partitionBaseDir) 866 if inTargetPartition { 867 f.entries = append(f.entries, relPath) 868 } 869} 870 871func (f *filesystem) installedFilesList() string { 872 installedFilePaths := android.FirstUniqueStrings(f.entries) 873 slices.Sort(installedFilePaths) 874 875 return strings.Join(installedFilePaths, "\n") 876} 877 878func validatePartitionType(ctx android.ModuleContext, p partition) { 879 if !android.InList(p.PartitionType(), validPartitions) { 880 ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, p.PartitionType()) 881 } 882 883 ctx.VisitDirectDepsProxyWithTag(android.DefaultsDepTag, func(m android.ModuleProxy) { 884 if _, ok := android.OtherModuleProvider(ctx, m, FilesystemDefaultsInfoProvider); ok { 885 partitionInfo := android.OtherModuleProviderOrDefault(ctx, m, android.PartitionTypeInfoProvider) 886 if p.PartitionType() != partitionInfo.PartitionType { 887 ctx.PropertyErrorf("partition_type", 888 "%s doesn't match with the partition type %s of the filesystem default module %s", 889 p.PartitionType(), partitionInfo.PartitionType, m.Name()) 890 } 891 } 892 }) 893} 894 895// Copy extra files/dirs that are not from the `deps` property to `rootDir`, checking for conflicts with files 896// already in `rootDir`. 897func (f *filesystem) buildNonDepsFiles( 898 ctx android.ModuleContext, 899 builder *android.RuleBuilder, 900 rootDir android.OutputPath, 901 rebasedDir android.OutputPath, 902 fullInstallPaths *[]FullInstallPathInfo, 903) { 904 rebasedPrefix, err := filepath.Rel(rootDir.String(), rebasedDir.String()) 905 if err != nil || strings.HasPrefix(rebasedPrefix, "../") { 906 panic("rebasedDir could not be made relative to rootDir") 907 } 908 if !strings.HasSuffix(rebasedPrefix, "/") { 909 rebasedPrefix += "/" 910 } 911 if rebasedPrefix == "./" { 912 rebasedPrefix = "" 913 } 914 915 // create dirs and symlinks 916 for _, dir := range f.properties.Dirs.GetOrDefault(ctx, nil) { 917 // OutputPath.Join verifies dir 918 builder.Command().Text("mkdir -p").Text(rootDir.Join(ctx, dir).String()) 919 // Only add the fullInstallPath logic for files in the rebased dir. The root dir 920 // is harder to install to. 921 if strings.HasPrefix(dir, rebasedPrefix) { 922 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 923 FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(dir, rebasedPrefix)), 924 IsDir: true, 925 }) 926 } 927 } 928 929 for _, symlink := range f.properties.Symlinks { 930 name := strings.TrimSpace(proptools.String(symlink.Name)) 931 target := strings.TrimSpace(proptools.String(symlink.Target)) 932 933 if name == "" { 934 ctx.PropertyErrorf("symlinks", "Name can't be empty") 935 continue 936 } 937 938 if target == "" { 939 ctx.PropertyErrorf("symlinks", "Target can't be empty") 940 continue 941 } 942 943 // OutputPath.Join verifies name. don't need to verify target. 944 dst := rootDir.Join(ctx, name) 945 builder.Command().Textf("(! [ -e %s -o -L %s ] || (echo \"%s already exists from an earlier stage of the build\" && exit 1))", dst, dst, dst) 946 builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String())) 947 builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String()) 948 f.appendToEntry(ctx, dst) 949 // Add the fullInstallPath logic for files in the rebased dir, and for non-rebased files in "system" partition 950 // the fullInstallPath is changed to "root" which aligns to the behavior in Make. 951 if f.PartitionType() == "system" { 952 installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)) 953 if !strings.HasPrefix(name, rebasedPrefix) { 954 installPath = android.PathForModuleInPartitionInstall(ctx, "root", name) 955 } 956 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 957 FullInstallPath: installPath, 958 SymlinkTarget: target, 959 }) 960 } else { 961 if strings.HasPrefix(name, rebasedPrefix) { 962 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 963 FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)), 964 SymlinkTarget: target, 965 }) 966 } 967 } 968 } 969 970 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=2835;drc=b186569ef00ff2f2a1fab28aedc75ebc32bcd67b 971 if f.partitionName() == "recovery" { 972 builder.Command().Text("mkdir -p").Text(rootDir.Join(ctx, "root/linkerconfig").String()) 973 builder.Command().Text("touch").Text(rootDir.Join(ctx, "root/linkerconfig/ld.config.txt").String()) 974 } 975} 976 977func (f *filesystem) copyPackagingSpecs(ctx android.ModuleContext, builder *android.RuleBuilder, specs map[string]android.PackagingSpec, rootDir, rebasedDir android.WritablePath) []string { 978 rootDirSpecs := make(map[string]android.PackagingSpec) 979 rebasedDirSpecs := make(map[string]android.PackagingSpec) 980 981 for rel, spec := range specs { 982 if spec.Partition() == "root" { 983 rootDirSpecs[rel] = spec 984 } else { 985 rebasedDirSpecs[rel] = spec 986 } 987 } 988 989 dirsToSpecs := make(map[android.WritablePath]map[string]android.PackagingSpec) 990 dirsToSpecs[rootDir] = rootDirSpecs 991 dirsToSpecs[rebasedDir] = rebasedDirSpecs 992 993 // Preserve timestamps for adb sync, so that this staging dir file matches the timestamp in the 994 // out/target/product staging directory. 995 return f.CopySpecsToDirs(ctx, builder, dirsToSpecs, true) 996} 997 998func (f *filesystem) rootDirString() string { 999 return f.partitionName() 1000} 1001 1002type buildImageParams struct { 1003 // inputs 1004 rootDir android.OutputPath 1005 propFile android.Path 1006 toolDeps android.Paths 1007 // outputs 1008 output android.WritablePath 1009} 1010 1011func (f *filesystem) buildImageUsingBuildImage( 1012 ctx android.ModuleContext, 1013 builder *android.RuleBuilder, 1014 params buildImageParams) { 1015 // run host_init_verifier 1016 // Ideally we should have a concept of pluggable linters that verify the generated image. 1017 // While such concept is not implement this will do. 1018 // TODO(b/263574231): substitute with pluggable linter. 1019 builder.Command(). 1020 BuiltTool("host_init_verifier"). 1021 FlagWithArg("--out_system=", params.rootDir.String()+"/system") 1022 1023 // Most of the time, if build_image were to call a host tool, it accepts the path to the 1024 // host tool in a field in the prop file. However, it doesn't have that option for fec, which 1025 // it expects to just be on the PATH. Add fec to the PATH. 1026 fec := ctx.Config().HostToolPath(ctx, "fec") 1027 pathToolDirs := []string{filepath.Dir(fec.String())} 1028 1029 builder.Command(). 1030 Textf("PATH=%s:$PATH", strings.Join(pathToolDirs, ":")). 1031 BuiltTool("build_image"). 1032 Text(params.rootDir.String()). // input directory 1033 Input(params.propFile). 1034 Implicits(params.toolDeps). 1035 Implicit(fec). 1036 Implicit(f.fileystemStagingDirTimestamp(ctx)). // assemble the staging directory 1037 Output(params.output). 1038 Text(params.rootDir.String()) // directory where to find fs_config_files|dirs 1039 1040 if f.properties.Partition_size != nil { 1041 assertMaxImageSize(builder, params.output, *f.properties.Partition_size, false) 1042 } 1043 1044 // rootDir is not deleted. Might be useful for quick inspection. 1045 builder.Build("build_"+params.output.String(), fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) 1046} 1047 1048func (f *filesystem) propFileForHermeticImg(ctx android.ModuleContext, builder *android.RuleBuilder, inputPropFile android.Path) android.Path { 1049 propFilePinnedTimestamp := android.PathForModuleOut(ctx, "for_target_files", "prop") 1050 builder.Command().Textf("cat").Input(inputPropFile).Flag(">").Output(propFilePinnedTimestamp). 1051 Textf(" && echo use_fixed_timestamp=true >> %s", propFilePinnedTimestamp). 1052 Textf(" && echo block_list=%s >> %s", f.getMapFile(ctx).String(), propFilePinnedTimestamp) // mapfile will be an implicit output 1053 builder.Command().Text("touch").Output(f.getMapFile(ctx)) 1054 return propFilePinnedTimestamp 1055} 1056 1057func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.Path { 1058 builder := android.NewRuleBuilder(pctx, ctx) 1059 fcBin := android.PathForModuleOut(ctx, "file_contexts.bin") 1060 builder.Command().BuiltTool("sefcontext_compile"). 1061 FlagWithOutput("-o ", fcBin). 1062 Input(android.PathForModuleSrc(ctx, proptools.String(f.properties.File_contexts))) 1063 builder.Build("build_filesystem_file_contexts", fmt.Sprintf("Creating filesystem file contexts for %s", f.BaseModuleName())) 1064 return fcBin 1065} 1066 1067func (f *filesystem) buildPropFile(ctx android.ModuleContext) (android.Path, android.Paths) { 1068 var deps android.Paths 1069 var lines []string 1070 addStr := func(name string, value string) { 1071 lines = append(lines, fmt.Sprintf("%s=%s", name, value)) 1072 } 1073 addPath := func(name string, path android.Path) { 1074 addStr(name, path.String()) 1075 deps = append(deps, path) 1076 } 1077 1078 addStr("fs_type", f.fsType(ctx).String()) 1079 addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/")) 1080 addStr("use_dynamic_partition_size", "true") 1081 addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs")) 1082 // b/177813163 deps of the host tools have to be added. Remove this. 1083 for _, t := range []string{"mke2fs", "e2fsdroid", "tune2fs"} { 1084 deps = append(deps, ctx.Config().HostToolPath(ctx, t)) 1085 } 1086 1087 if proptools.Bool(f.properties.Use_avb) { 1088 addStr("avb_hashtree_enable", "true") 1089 addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool")) 1090 algorithm := proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096") 1091 addStr("avb_algorithm", algorithm) 1092 if f.properties.Avb_private_key != nil { 1093 key := android.PathForModuleSrc(ctx, *f.properties.Avb_private_key) 1094 addPath("avb_key_path", key) 1095 } 1096 addStr("partition_name", f.partitionName()) 1097 addStr("avb_add_hashtree_footer_args", f.getAvbAddHashtreeFooterArgs(ctx)) 1098 } 1099 1100 if f.properties.File_contexts != nil && f.properties.Precompiled_file_contexts != nil { 1101 ctx.ModuleErrorf("file_contexts and precompiled_file_contexts cannot both be set") 1102 } else if f.properties.File_contexts != nil { 1103 f.selinuxFc = f.buildFileContexts(ctx) 1104 } else if f.properties.Precompiled_file_contexts != nil { 1105 f.selinuxFc = android.PathForModuleSrc(ctx, *f.properties.Precompiled_file_contexts) 1106 } 1107 if f.selinuxFc != nil { 1108 addPath("selinux_fc", f.selinuxFc) 1109 } 1110 if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" { 1111 addStr("timestamp", timestamp) 1112 } else if ctx.Config().Getenv("USE_FIXED_TIMESTAMP_IMG_FILES") == "true" { 1113 addStr("use_fixed_timestamp", "true") 1114 } 1115 1116 if uuid := proptools.String(f.properties.Uuid); uuid != "" { 1117 addStr("uuid", uuid) 1118 addStr("hash_seed", uuid) 1119 } 1120 1121 // Disable sparse only when partition size is not defined. disable_sparse has the same 1122 // effect as <partition name>_disable_sparse. 1123 if f.properties.Partition_size == nil { 1124 addStr("disable_sparse", "true") 1125 } 1126 1127 fst := f.fsType(ctx) 1128 switch fst { 1129 case erofsType: 1130 // Add erofs properties 1131 addStr("erofs_default_compressor", proptools.StringDefault(f.properties.Erofs.Compressor, "lz4hc,9")) 1132 if f.properties.Erofs.Compress_hints != nil { 1133 src := android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints) 1134 addPath("erofs_default_compress_hints", src) 1135 } 1136 if proptools.BoolDefault(f.properties.Erofs.Sparse, true) { 1137 // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b 1138 addStr("erofs_sparse_flag", "-s") 1139 } 1140 case f2fsType: 1141 if proptools.BoolDefault(f.properties.F2fs.Sparse, true) { 1142 // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2294;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0 1143 addStr("f2fs_sparse_flag", "-S") 1144 } 1145 } 1146 f.checkFsTypePropertyError(ctx, fst, fst.String()) 1147 1148 if f.properties.Partition_size != nil { 1149 addStr("partition_size", strconv.FormatInt(*f.properties.Partition_size, 10)) 1150 } 1151 1152 if proptools.BoolDefault(f.properties.Support_casefolding, false) { 1153 addStr("needs_casefold", "1") 1154 } 1155 1156 if proptools.BoolDefault(f.properties.Support_project_quota, false) { 1157 addStr("needs_projid", "1") 1158 } 1159 1160 if proptools.BoolDefault(f.properties.Enable_compression, false) { 1161 addStr("needs_compress", "1") 1162 } 1163 1164 sort.Strings(lines) 1165 1166 propFilePreProcessing := android.PathForModuleOut(ctx, "prop_pre_processing") 1167 android.WriteFileRule(ctx, propFilePreProcessing, strings.Join(lines, "\n")) 1168 propFile := android.PathForModuleOut(ctx, "prop") 1169 ctx.Build(pctx, android.BuildParams{ 1170 Rule: textFileProcessorRule, 1171 Input: propFilePreProcessing, 1172 Output: propFile, 1173 }) 1174 return propFile, deps 1175} 1176 1177func (f *filesystem) buildPropFileForMiscInfo(ctx android.ModuleContext) android.Path { 1178 var lines []string 1179 addStr := func(name string, value string) { 1180 lines = append(lines, fmt.Sprintf("%s=%s", name, value)) 1181 } 1182 1183 addStr("use_dynamic_partition_size", "true") 1184 addStr("ext_mkuserimg", "mkuserimg_mke2fs") 1185 1186 addStr("building_"+f.partitionName()+"_image", "true") 1187 addStr(f.partitionName()+"_fs_type", f.fsType(ctx).String()) 1188 1189 if proptools.Bool(f.properties.Use_avb) { 1190 addStr("avb_"+f.partitionName()+"_hashtree_enable", "true") 1191 addStr("avb_"+f.partitionName()+"_add_hashtree_footer_args", strings.TrimSpace(f.getAvbAddHashtreeFooterArgs(ctx))) 1192 } 1193 1194 if f.selinuxFc != nil { 1195 addStr(f.partitionName()+"_selinux_fc", f.selinuxFc.String()) 1196 } 1197 1198 // Disable sparse only when partition size is not defined. disable_sparse has the same 1199 // effect as <partition name>_disable_sparse. 1200 if f.properties.Partition_size == nil { 1201 addStr(f.partitionName()+"_disable_sparse", "true") 1202 } else if f.partitionName() == "userdata" { 1203 // Add userdata's partition size to misc_info.txt. 1204 // userdata has been special-cased to make the make packaging misc_info.txt implementation 1205 addStr("userdata_size", strconv.FormatInt(*f.properties.Partition_size, 10)) 1206 } 1207 1208 fst := f.fsType(ctx) 1209 switch fst { 1210 case erofsType: 1211 // Add erofs properties 1212 addStr("erofs_default_compressor", proptools.StringDefault(f.properties.Erofs.Compressor, "lz4hc,9")) 1213 if proptools.BoolDefault(f.properties.Erofs.Sparse, true) { 1214 // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2292;bpv=1;bpt=0;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b 1215 addStr("erofs_sparse_flag", "-s") 1216 } 1217 case f2fsType: 1218 if proptools.BoolDefault(f.properties.F2fs.Sparse, true) { 1219 // https://source.corp.google.com/h/googleplex-android/platform/build/+/88b1c67239ca545b11580237242774b411f2fed9:core/Makefile;l=2294;drc=ea8f34bc1d6e63656b4ec32f2391e9d54b3ebb6b;bpv=1;bpt=0 1220 addStr("f2fs_sparse_flag", "-S") 1221 } 1222 } 1223 1224 if proptools.BoolDefault(f.properties.Support_casefolding, false) { 1225 addStr("needs_casefold", "1") 1226 } 1227 1228 if proptools.BoolDefault(f.properties.Support_project_quota, false) { 1229 addStr("needs_projid", "1") 1230 } 1231 1232 if proptools.BoolDefault(f.properties.Enable_compression, false) { 1233 addStr("needs_compress", "1") 1234 } 1235 1236 sort.Strings(lines) 1237 1238 propFilePreProcessing := android.PathForModuleOut(ctx, "prop_misc_info_pre_processing") 1239 android.WriteFileRule(ctx, propFilePreProcessing, strings.Join(lines, "\n")) 1240 propFile := android.PathForModuleOut(ctx, "prop_file_for_misc_info") 1241 ctx.Build(pctx, android.BuildParams{ 1242 Rule: textFileProcessorRule, 1243 Input: propFilePreProcessing, 1244 Output: propFile, 1245 }) 1246 1247 return propFile 1248} 1249 1250func (f *filesystem) getAvbAddHashtreeFooterArgs(ctx android.ModuleContext) string { 1251 avb_add_hashtree_footer_args := "" 1252 if !proptools.BoolDefault(f.properties.Use_fec, true) { 1253 avb_add_hashtree_footer_args += " --do_not_generate_fec" 1254 } 1255 hashAlgorithm := proptools.StringDefault(f.properties.Avb_hash_algorithm, "sha256") 1256 avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm 1257 if f.properties.Rollback_index != nil { 1258 rollbackIndex := proptools.Int(f.properties.Rollback_index) 1259 if rollbackIndex < 0 { 1260 ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") 1261 } 1262 avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) 1263 } 1264 avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.os_version:%s", f.partitionName(), ctx.Config().PlatformVersionLastStable()) 1265 // We're not going to add BuildFingerPrintFile as a dep. If it changed, it's likely because 1266 // the build number changed, and we don't want to trigger rebuilds solely based on the build 1267 // number. 1268 avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.fingerprint:{CONTENTS_OF:%s}", f.partitionName(), ctx.Config().BuildFingerprintFile(ctx)) 1269 if f.properties.Security_patch != nil && proptools.String(f.properties.Security_patch) != "" { 1270 avb_add_hashtree_footer_args += fmt.Sprintf(" --prop com.android.build.%s.security_patch:%s", f.partitionName(), proptools.String(f.properties.Security_patch)) 1271 } 1272 return avb_add_hashtree_footer_args 1273} 1274 1275// This method checks if there is any property set for the fstype(s) other than 1276// the current fstype. 1277func (f *filesystem) checkFsTypePropertyError(ctx android.ModuleContext, t fsType, fs string) { 1278 raiseError := func(otherFsType, currentFsType string) { 1279 errMsg := fmt.Sprintf("%s is non-empty, but FS type is %s\n. Please delete %s properties if this partition should use %s\n", otherFsType, currentFsType, otherFsType, currentFsType) 1280 ctx.PropertyErrorf(otherFsType, errMsg) 1281 } 1282 1283 if t != erofsType { 1284 if f.properties.Erofs.Compressor != nil || f.properties.Erofs.Compress_hints != nil || f.properties.Erofs.Sparse != nil { 1285 raiseError("erofs", fs) 1286 } 1287 } 1288 if t != f2fsType { 1289 if f.properties.F2fs.Sparse != nil { 1290 raiseError("f2fs", fs) 1291 } 1292 } 1293} 1294 1295func includeFilesRootDir(ctx android.ModuleContext) (rootDirs android.Paths, partitions android.Paths) { 1296 ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { 1297 if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok { 1298 rootDirs = append(rootDirs, fsProvider.RootDir) 1299 partitions = append(partitions, fsProvider.Output) 1300 } else { 1301 ctx.PropertyErrorf("include_files_of", "only filesystem modules can be listed in "+ 1302 "include_files_of but %s is not a filesystem module", m.Name()) 1303 } 1304 }) 1305 return rootDirs, partitions 1306} 1307 1308func includeFilesInstalledFiles(ctx android.ModuleContext) (ret []depset.DepSet[InstalledFilesStruct]) { 1309 ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { 1310 if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok { 1311 ret = append(ret, fsProvider.InstalledFilesDepSet) 1312 } 1313 }) 1314 return 1315} 1316 1317func (f *filesystem) hasOrIsRecovery(ctx android.ModuleContext) bool { 1318 if f.partitionName() == "recovery" { 1319 return true 1320 } 1321 ret := false 1322 ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) { 1323 if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok && fsProvider.PartitionName == "recovery" { 1324 ret = true 1325 } 1326 }) 1327 return ret 1328} 1329 1330func (f *filesystem) buildCpioImage( 1331 ctx android.ModuleContext, 1332 builder *android.RuleBuilder, 1333 rootDir android.OutputPath, 1334 compressed bool, 1335) (android.Path, android.Paths) { 1336 if proptools.Bool(f.properties.Use_avb) { 1337 ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+ 1338 "Consider adding this to bootimg module and signing the entire boot image.") 1339 } 1340 1341 if proptools.String(f.properties.File_contexts) != "" { 1342 ctx.PropertyErrorf("file_contexts", "file_contexts is not supported for compressed cpio image.") 1343 } 1344 1345 rootDirs, partitions := includeFilesRootDir(ctx) 1346 1347 output := android.PathForModuleOut(ctx, f.installFileName()) 1348 cmd := builder.Command(). 1349 BuiltTool("mkbootfs"). 1350 Implicit(f.fileystemStagingDirTimestamp(ctx)). 1351 Text(rootDir.String()) // input directory 1352 1353 for i := range len(rootDirs) { 1354 cmd.Text(rootDirs[i].String()) 1355 } 1356 cmd.Implicits(partitions) 1357 1358 if nodeList := f.properties.Dev_nodes_description_file; nodeList != nil { 1359 cmd.FlagWithInput("-n ", android.PathForModuleSrc(ctx, proptools.String(nodeList))) 1360 } 1361 if compressed { 1362 cmd.Text("|"). 1363 BuiltTool("lz4"). 1364 Flag("--favor-decSpeed"). // for faster boot 1365 Flag("-12"). // maximum compression level 1366 Flag("-l"). // legacy format for kernel 1367 Text(">").Output(output) 1368 } else { 1369 cmd.Text(">").Output(output) 1370 } 1371 1372 // rootDir is not deleted. Might be useful for quick inspection. 1373 builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) 1374 1375 return output, rootDirs 1376} 1377 1378var validPartitions = []string{ 1379 "system", 1380 "userdata", 1381 "cache", 1382 "system_other", 1383 "vendor", 1384 "product", 1385 "system_ext", 1386 "odm", 1387 "vendor_dlkm", 1388 "odm_dlkm", 1389 "system_dlkm", 1390 "ramdisk", 1391 "vendor_ramdisk", 1392 "recovery", 1393} 1394 1395func (f *filesystem) buildEventLogtagsFile( 1396 ctx android.ModuleContext, 1397 builder *android.RuleBuilder, 1398 rebasedDir android.OutputPath, 1399 fullInstallPaths *[]FullInstallPathInfo, 1400) { 1401 if !proptools.Bool(f.properties.Build_logtags) { 1402 return 1403 } 1404 1405 etcPath := rebasedDir.Join(ctx, "etc") 1406 eventLogtagsPath := etcPath.Join(ctx, "event-log-tags") 1407 builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String()) 1408 builder.Command().Text("cp").Input(android.MergedLogtagsPath(ctx)).Text(eventLogtagsPath.String()) 1409 1410 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 1411 FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "event-log-tags"), 1412 SourcePath: android.MergedLogtagsPath(ctx), 1413 }) 1414 1415 f.appendToEntry(ctx, eventLogtagsPath) 1416} 1417 1418func (f *filesystem) BuildLinkerConfigFile( 1419 ctx android.ModuleContext, 1420 builder *android.RuleBuilder, 1421 rebasedDir android.OutputPath, 1422 fullInstallPaths *[]FullInstallPathInfo, 1423) { 1424 if !proptools.Bool(f.properties.Linker_config.Gen_linker_config) { 1425 return 1426 } 1427 1428 provideModules, _ := f.getLibsForLinkerConfig(ctx) 1429 intermediateOutput := android.PathForModuleOut(ctx, "linker.config.pb") 1430 linkerconfig.BuildLinkerConfig(ctx, android.PathsForModuleSrc(ctx, f.properties.Linker_config.Linker_config_srcs), provideModules, nil, intermediateOutput) 1431 output := rebasedDir.Join(ctx, "etc", "linker.config.pb") 1432 builder.Command().Text("cp").Input(intermediateOutput).Output(output) 1433 1434 *fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{ 1435 FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "linker.config.pb"), 1436 SourcePath: intermediateOutput, 1437 }) 1438 1439 f.appendToEntry(ctx, output) 1440} 1441 1442func (f *filesystem) ShouldUseVintfFragmentModuleOnly() bool { 1443 return false 1444} 1445 1446type partition interface { 1447 PartitionType() string 1448} 1449 1450func (f *filesystem) PartitionType() string { 1451 return proptools.StringDefault(f.properties.Partition_type, "system") 1452} 1453 1454var _ partition = (*filesystem)(nil) 1455 1456var _ android.AndroidMkEntriesProvider = (*filesystem)(nil) 1457 1458// Implements android.AndroidMkEntriesProvider 1459func (f *filesystem) AndroidMkEntries() []android.AndroidMkEntries { 1460 return []android.AndroidMkEntries{android.AndroidMkEntries{ 1461 Class: "ETC", 1462 OutputFile: android.OptionalPathForPath(f.output), 1463 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 1464 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 1465 entries.SetString("LOCAL_MODULE_PATH", f.installDir.String()) 1466 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", f.installFileName()) 1467 entries.SetString("LOCAL_FILESYSTEM_FILELIST", f.fileListFile.String()) 1468 }, 1469 }, 1470 }} 1471} 1472 1473// Filesystem is the public interface for the filesystem struct. Currently, it's only for the apex 1474// package to have access to the output file. 1475type Filesystem interface { 1476 android.Module 1477 OutputPath() android.Path 1478 1479 // Returns the output file that is signed by avbtool. If this module is not signed, returns 1480 // nil. 1481 SignedOutputPath() android.Path 1482} 1483 1484var _ Filesystem = (*filesystem)(nil) 1485 1486func (f *filesystem) OutputPath() android.Path { 1487 return f.output 1488} 1489 1490func (f *filesystem) SignedOutputPath() android.Path { 1491 if proptools.Bool(f.properties.Use_avb) { 1492 return f.OutputPath() 1493 } 1494 return nil 1495} 1496 1497// Filter the result of GatherPackagingSpecs to discard items targeting outside "system" partition. 1498// Note that "apex" module installs its contents to "apex"(fake partition) as well 1499// for symbol lookup by imitating "activated" paths. 1500func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map[string]android.PackagingSpec { 1501 return f.PackagingBase.GatherPackagingSpecsWithFilterAndModifier(ctx, f.filesystemBuilder.FilterPackagingSpec, f.filesystemBuilder.ModifyPackagingSpec) 1502} 1503 1504func (f *filesystem) gatherOwners(specs map[string]android.PackagingSpec) []InstalledModuleInfo { 1505 var owners []InstalledModuleInfo 1506 for _, p := range android.SortedKeys(specs) { 1507 spec := specs[p] 1508 owners = append(owners, InstalledModuleInfo{ 1509 Name: spec.Owner(), 1510 Variation: spec.Variation(), 1511 }) 1512 } 1513 return owners 1514} 1515 1516// Dexpreopt files are installed to system_other. Collect the packaingSpecs for the dexpreopt files 1517// from this partition to export to the system_other partition later. 1518func (f *filesystem) systemOtherFiles(ctx android.ModuleContext) map[string]android.PackagingSpec { 1519 filter := func(spec android.PackagingSpec) bool { 1520 // For some reason system_other packaging specs don't set the partition field. 1521 return strings.HasPrefix(spec.RelPathInPackage(), "system_other/") 1522 } 1523 modifier := func(spec *android.PackagingSpec) { 1524 spec.SetRelPathInPackage(strings.TrimPrefix(spec.RelPathInPackage(), "system_other/")) 1525 spec.SetPartition("system_other") 1526 } 1527 return f.PackagingBase.GatherPackagingSpecsWithFilterAndModifier(ctx, filter, modifier) 1528} 1529 1530func sha1sum(values []string) string { 1531 h := sha256.New() 1532 for _, value := range values { 1533 io.WriteString(h, value) 1534 } 1535 return fmt.Sprintf("%x", h.Sum(nil)) 1536} 1537 1538// Base cc.UseCoverage 1539 1540var _ cc.UseCoverage = (*filesystem)(nil) 1541 1542func (*filesystem) IsNativeCoverageNeeded(ctx cc.IsNativeCoverageNeededContext) bool { 1543 return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() 1544} 1545 1546// android_filesystem_defaults 1547 1548type filesystemDefaults struct { 1549 android.ModuleBase 1550 android.DefaultsModuleBase 1551 1552 properties FilesystemProperties 1553} 1554 1555// android_filesystem_defaults is a default module for android_filesystem and android_system_image 1556func filesystemDefaultsFactory() android.Module { 1557 module := &filesystemDefaults{} 1558 module.AddProperties(&module.properties) 1559 module.AddProperties(&android.PackagingProperties{}) 1560 android.InitDefaultsModule(module) 1561 return module 1562} 1563 1564func (f *filesystemDefaults) PartitionType() string { 1565 return proptools.StringDefault(f.properties.Partition_type, "system") 1566} 1567 1568var _ partition = (*filesystemDefaults)(nil) 1569 1570func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { 1571 validatePartitionType(ctx, f) 1572 android.SetProvider(ctx, FilesystemDefaultsInfoProvider, FilesystemDefaultsInfo{}) 1573 android.SetProvider(ctx, android.PartitionTypeInfoProvider, android.PartitionTypeInfo{ 1574 PartitionType: f.PartitionType(), 1575 }) 1576} 1577 1578// getLibsForLinkerConfig returns 1579// 1. A list of libraries installed in this filesystem 1580// 2. A list of dep libraries _not_ installed in this filesystem 1581// 1582// `linkerconfig.BuildLinkerConfig` will convert these two to a linker.config.pb for the filesystem 1583// (1) will be added to --provideLibs if they are C libraries with a stable interface (has stubs) 1584// (2) will be added to --requireLibs if they are C libraries with a stable interface (has stubs) 1585func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]android.ModuleProxy, []android.ModuleProxy) { 1586 // we need "Module"s for packaging items 1587 modulesInPackageByModule := make(map[android.ModuleProxy]bool) 1588 modulesInPackageByName := make(map[string]bool) 1589 1590 deps := f.gatherFilteredPackagingSpecs(ctx) 1591 ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { 1592 if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled { 1593 return false 1594 } 1595 for _, ps := range android.OtherModuleProviderOrDefault( 1596 ctx, child, android.InstallFilesProvider).PackagingSpecs { 1597 if _, ok := deps[ps.RelPathInPackage()]; ok && ps.Partition() == f.PartitionType() { 1598 modulesInPackageByModule[child] = true 1599 modulesInPackageByName[child.Name()] = true 1600 return true 1601 } 1602 } 1603 return true 1604 }) 1605 1606 provideModules := make([]android.ModuleProxy, 0, len(modulesInPackageByModule)) 1607 for mod := range modulesInPackageByModule { 1608 provideModules = append(provideModules, mod) 1609 } 1610 1611 var requireModules []android.ModuleProxy 1612 ctx.WalkDepsProxy(func(child, parent android.ModuleProxy) bool { 1613 if !android.OtherModulePointerProviderOrDefault(ctx, child, android.CommonModuleInfoProvider).Enabled { 1614 return false 1615 } 1616 _, parentInPackage := modulesInPackageByModule[parent] 1617 _, childInPackageName := modulesInPackageByName[child.Name()] 1618 1619 // When parent is in the package, and child (or its variant) is not, this can be from an interface. 1620 if parentInPackage && !childInPackageName { 1621 requireModules = append(requireModules, child) 1622 } 1623 return true 1624 }) 1625 1626 return provideModules, requireModules 1627} 1628 1629// Checks that the given file doesn't exceed the given size, and will also print a warning 1630// if it's nearing the maximum size. Equivalent to assert-max-image-size in make: 1631// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/definitions.mk;l=3455;drc=993c4de29a02a6accd60ceaaee153307e1a18d10 1632func assertMaxImageSize(builder *android.RuleBuilder, image android.Path, maxSize int64, addAvbLater bool) { 1633 if addAvbLater { 1634 // The value 69632 is derived from MAX_VBMETA_SIZE + MAX_FOOTER_SIZE in avbtool. 1635 // Logic copied from make: 1636 // https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=228;drc=a6a0007ef24e16c0b79f439beac4a118416717e6 1637 maxSize -= 69632 1638 } 1639 cmd := builder.Command() 1640 cmd.Textf(`file="%s"; maxsize="%d";`+ 1641 `total=$(stat -c "%%s" "$file" | tr -d '\n');`+ 1642 `if [ "$total" -gt "$maxsize" ]; then `+ 1643 ` echo "error: $file too large ($total > $maxsize)";`+ 1644 ` false;`+ 1645 `elif [ "$total" -gt $((maxsize - 32768)) ]; then `+ 1646 ` echo "WARNING: $file approaching size limit ($total now; limit $maxsize)";`+ 1647 `fi`, 1648 image, maxSize) 1649 cmd.Implicit(image) 1650} 1651 1652// addAutogeneratedRroDeps walks the transitive closure of vendor and product partitions. 1653// It visits apps installed in system and system_ext partitions, and adds the autogenerated 1654// RRO modules to its own deps. 1655func addAutogeneratedRroDeps(ctx android.BottomUpMutatorContext) { 1656 f, ok := ctx.Module().(*filesystem) 1657 if !ok { 1658 return 1659 } 1660 thisPartition := f.PartitionType() 1661 if thisPartition != "vendor" && thisPartition != "product" { 1662 if f.properties.Android_filesystem_deps.System != nil { 1663 ctx.PropertyErrorf("android_filesystem_deps.system", "only vendor or product partitions can use android_filesystem_deps") 1664 } 1665 if f.properties.Android_filesystem_deps.System_ext != nil { 1666 ctx.PropertyErrorf("android_filesystem_deps.system_ext", "only vendor or product partitions can use android_filesystem_deps") 1667 } 1668 return 1669 } 1670 ctx.WalkDeps(func(child, parent android.Module) bool { 1671 depTag := ctx.OtherModuleDependencyTag(child) 1672 if parent.Name() == f.Name() && depTag != interPartitionDependencyTag { 1673 return false // This is a module listed in deps of vendor/product filesystem 1674 } 1675 if vendorOverlay := java.AutogeneratedRroModuleName(ctx, child.Name(), "vendor"); ctx.OtherModuleExists(vendorOverlay) && thisPartition == "vendor" { 1676 ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, vendorOverlay) 1677 } 1678 if productOverlay := java.AutogeneratedRroModuleName(ctx, child.Name(), "product"); ctx.OtherModuleExists(productOverlay) && thisPartition == "product" { 1679 ctx.AddFarVariationDependencies(nil, dependencyTagWithVisibilityEnforcementBypass, productOverlay) 1680 } 1681 return true 1682 }) 1683} 1684 1685func (f *filesystem) MakeVars(ctx android.MakeVarsModuleContext) []android.ModuleMakeVarsValue { 1686 if f.Name() == ctx.Config().SoongDefinedSystemImage() { 1687 return []android.ModuleMakeVarsValue{{"SOONG_DEFINED_SYSTEM_IMAGE_PATH", f.output.String()}} 1688 } 1689 return nil 1690} 1691 1692func setCommonFilesystemInfo(ctx android.ModuleContext, m Filesystem) { 1693 android.SetProvider(ctx, FilesystemProvider, FilesystemInfo{ 1694 Output: m.OutputPath(), 1695 SignedOutputPath: m.SignedOutputPath(), 1696 }) 1697} 1698