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 "strconv" 24 "strings" 25 26 "android/soong/android" 27 "android/soong/cc" 28 29 "github.com/google/blueprint" 30 "github.com/google/blueprint/proptools" 31) 32 33func init() { 34 registerBuildComponents(android.InitRegistrationContext) 35} 36 37func registerBuildComponents(ctx android.RegistrationContext) { 38 ctx.RegisterModuleType("android_filesystem", filesystemFactory) 39 ctx.RegisterModuleType("android_filesystem_defaults", filesystemDefaultsFactory) 40 ctx.RegisterModuleType("android_system_image", systemImageFactory) 41 ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory) 42 ctx.RegisterModuleType("avb_add_hash_footer_defaults", avbAddHashFooterDefaultsFactory) 43 ctx.RegisterModuleType("avb_gen_vbmeta_image", avbGenVbmetaImageFactory) 44 ctx.RegisterModuleType("avb_gen_vbmeta_image_defaults", avbGenVbmetaImageDefaultsFactory) 45} 46 47type filesystem struct { 48 android.ModuleBase 49 android.PackagingBase 50 android.DefaultableModuleBase 51 52 properties filesystemProperties 53 54 // Function that builds extra files under the root directory and returns the files 55 buildExtraFiles func(ctx android.ModuleContext, root android.OutputPath) android.OutputPaths 56 57 // Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs() 58 filterPackagingSpec func(spec android.PackagingSpec) bool 59 60 output android.OutputPath 61 installDir android.InstallPath 62 63 // For testing. Keeps the result of CopySpecsToDir() 64 entries []string 65} 66 67type symlinkDefinition struct { 68 Target *string 69 Name *string 70} 71 72type filesystemProperties struct { 73 // When set to true, sign the image with avbtool. Default is false. 74 Use_avb *bool 75 76 // Path to the private key that avbtool will use to sign this filesystem image. 77 // TODO(jiyong): allow apex_key to be specified here 78 Avb_private_key *string `android:"path"` 79 80 // Signing algorithm for avbtool. Default is SHA256_RSA4096. 81 Avb_algorithm *string 82 83 // Hash algorithm used for avbtool (for descriptors). This is passed as hash_algorithm to 84 // avbtool. Default used by avbtool is sha1. 85 Avb_hash_algorithm *string 86 87 // The index used to prevent rollback of the image. Only used if use_avb is true. 88 Rollback_index *int64 89 90 // Name of the partition stored in vbmeta desc. Defaults to the name of this module. 91 Partition_name *string 92 93 // Type of the filesystem. Currently, ext4, cpio, and compressed_cpio are supported. Default 94 // is ext4. 95 Type *string 96 97 // Identifies which partition this is for //visibility:any_system_image (and others) visibility 98 // checks, and will be used in the future for API surface checks. 99 Partition_type *string 100 101 // file_contexts file to make image. Currently, only ext4 is supported. 102 File_contexts *string `android:"path"` 103 104 // Base directory relative to root, to which deps are installed, e.g. "system". Default is "." 105 // (root). 106 Base_dir *string 107 108 // Directories to be created under root. e.g. /dev, /proc, etc. 109 Dirs proptools.Configurable[[]string] 110 111 // Symbolic links to be created under root with "ln -sf <target> <name>". 112 Symlinks []symlinkDefinition 113 114 // Seconds since unix epoch to override timestamps of file entries 115 Fake_timestamp *string 116 117 // When set, passed to mkuserimg_mke2fs --mke2fs_uuid & --mke2fs_hash_seed. 118 // Otherwise, they'll be set as random which might cause indeterministic build output. 119 Uuid *string 120 121 // Mount point for this image. Default is "/" 122 Mount_point *string 123 124 // If set to the name of a partition ("system", "vendor", etc), this filesystem module 125 // will also include the contents of the make-built staging directories. If any soong 126 // modules would be installed to the same location as a make module, they will overwrite 127 // the make version. 128 Include_make_built_files string 129 130 // When set, builds etc/event-log-tags file by merging logtags from all dependencies. 131 // Default is false 132 Build_logtags *bool 133 134 // Install aconfig_flags.pb file for the modules installed in this partition. 135 Gen_aconfig_flags_pb *bool 136 137 Fsverity fsverityProperties 138} 139 140// android_filesystem packages a set of modules and their transitive dependencies into a filesystem 141// image. The filesystem images are expected to be mounted in the target device, which means the 142// modules in the filesystem image are built for the target device (i.e. Android, not Linux host). 143// The modules are placed in the filesystem image just like they are installed to the ordinary 144// partitions like system.img. For example, cc_library modules are placed under ./lib[64] directory. 145func filesystemFactory() android.Module { 146 module := &filesystem{} 147 module.filterPackagingSpec = module.filterInstallablePackagingSpec 148 initFilesystemModule(module) 149 return module 150} 151 152func initFilesystemModule(module *filesystem) { 153 module.AddProperties(&module.properties) 154 android.InitPackageModule(module) 155 module.PackagingBase.DepsCollectFirstTargetOnly = true 156 android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) 157 android.InitDefaultableModule(module) 158} 159 160var dependencyTag = struct { 161 blueprint.BaseDependencyTag 162 android.PackagingItemAlwaysDepTag 163}{} 164 165func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) { 166 f.AddDeps(ctx, dependencyTag) 167} 168 169type fsType int 170 171const ( 172 ext4Type fsType = iota 173 compressedCpioType 174 cpioType // uncompressed 175 unknown 176) 177 178func (f *filesystem) fsType(ctx android.ModuleContext) fsType { 179 typeStr := proptools.StringDefault(f.properties.Type, "ext4") 180 switch typeStr { 181 case "ext4": 182 return ext4Type 183 case "compressed_cpio": 184 return compressedCpioType 185 case "cpio": 186 return cpioType 187 default: 188 ctx.PropertyErrorf("type", "%q not supported", typeStr) 189 return unknown 190 } 191} 192 193func (f *filesystem) installFileName() string { 194 return f.BaseModuleName() + ".img" 195} 196 197func (f *filesystem) partitionName() string { 198 return proptools.StringDefault(f.properties.Partition_name, f.Name()) 199} 200 201func (f *filesystem) filterInstallablePackagingSpec(ps android.PackagingSpec) bool { 202 // Filesystem module respects the installation semantic. A PackagingSpec from a module with 203 // IsSkipInstall() is skipped. 204 return !ps.SkipInstall() 205} 206 207var pctx = android.NewPackageContext("android/soong/filesystem") 208 209func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { 210 validatePartitionType(ctx, f) 211 switch f.fsType(ctx) { 212 case ext4Type: 213 f.output = f.buildImageUsingBuildImage(ctx) 214 case compressedCpioType: 215 f.output = f.buildCpioImage(ctx, true) 216 case cpioType: 217 f.output = f.buildCpioImage(ctx, false) 218 default: 219 return 220 } 221 222 f.installDir = android.PathForModuleInstall(ctx, "etc") 223 ctx.InstallFile(f.installDir, f.installFileName(), f.output) 224 225 ctx.SetOutputFiles([]android.Path{f.output}, "") 226} 227 228func validatePartitionType(ctx android.ModuleContext, p partition) { 229 if !android.InList(p.PartitionType(), validPartitions) { 230 ctx.PropertyErrorf("partition_type", "partition_type must be one of %s, found: %s", validPartitions, p.PartitionType()) 231 } 232 233 ctx.VisitDirectDepsWithTag(android.DefaultsDepTag, func(m android.Module) { 234 if fdm, ok := m.(*filesystemDefaults); ok { 235 if p.PartitionType() != fdm.PartitionType() { 236 ctx.PropertyErrorf("partition_type", 237 "%s doesn't match with the partition type %s of the filesystem default module %s", 238 p.PartitionType(), fdm.PartitionType(), m.Name()) 239 } 240 } 241 }) 242} 243 244// Copy extra files/dirs that are not from the `deps` property to `rootDir`, checking for conflicts with files 245// already in `rootDir`. 246func (f *filesystem) buildNonDepsFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.OutputPath) { 247 // create dirs and symlinks 248 for _, dir := range f.properties.Dirs.GetOrDefault(ctx, nil) { 249 // OutputPath.Join verifies dir 250 builder.Command().Text("mkdir -p").Text(rootDir.Join(ctx, dir).String()) 251 } 252 253 for _, symlink := range f.properties.Symlinks { 254 name := strings.TrimSpace(proptools.String(symlink.Name)) 255 target := strings.TrimSpace(proptools.String(symlink.Target)) 256 257 if name == "" { 258 ctx.PropertyErrorf("symlinks", "Name can't be empty") 259 continue 260 } 261 262 if target == "" { 263 ctx.PropertyErrorf("symlinks", "Target can't be empty") 264 continue 265 } 266 267 // OutputPath.Join verifies name. don't need to verify target. 268 dst := rootDir.Join(ctx, name) 269 builder.Command().Textf("(! [ -e %s -o -L %s ] || (echo \"%s already exists from an earlier stage of the build\" && exit 1))", dst, dst, dst) 270 builder.Command().Text("mkdir -p").Text(filepath.Dir(dst.String())) 271 builder.Command().Text("ln -sf").Text(proptools.ShellEscape(target)).Text(dst.String()) 272 } 273 274 // create extra files if there's any 275 if f.buildExtraFiles != nil { 276 rootForExtraFiles := android.PathForModuleGen(ctx, "root-extra").OutputPath 277 extraFiles := f.buildExtraFiles(ctx, rootForExtraFiles) 278 for _, f := range extraFiles { 279 rel, err := filepath.Rel(rootForExtraFiles.String(), f.String()) 280 if err != nil || strings.HasPrefix(rel, "..") { 281 ctx.ModuleErrorf("can't make %q relative to %q", f, rootForExtraFiles) 282 } 283 } 284 if len(extraFiles) > 0 { 285 builder.Command().BuiltTool("merge_directories"). 286 Implicits(extraFiles.Paths()). 287 Text(rootDir.String()). 288 Text(rootForExtraFiles.String()) 289 } 290 } 291} 292 293func (f *filesystem) buildImageUsingBuildImage(ctx android.ModuleContext) android.OutputPath { 294 rootDir := android.PathForModuleOut(ctx, "root").OutputPath 295 rebasedDir := rootDir 296 if f.properties.Base_dir != nil { 297 rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir) 298 } 299 builder := android.NewRuleBuilder(pctx, ctx) 300 // Wipe the root dir to get rid of leftover files from prior builds 301 builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir) 302 specs := f.gatherFilteredPackagingSpecs(ctx) 303 f.entries = f.CopySpecsToDir(ctx, builder, specs, rebasedDir) 304 305 f.buildNonDepsFiles(ctx, builder, rootDir) 306 f.addMakeBuiltFiles(ctx, builder, rootDir) 307 f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir) 308 f.buildEventLogtagsFile(ctx, builder, rebasedDir) 309 f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir) 310 311 // run host_init_verifier 312 // Ideally we should have a concept of pluggable linters that verify the generated image. 313 // While such concept is not implement this will do. 314 // TODO(b/263574231): substitute with pluggable linter. 315 builder.Command(). 316 BuiltTool("host_init_verifier"). 317 FlagWithArg("--out_system=", rootDir.String()+"/system") 318 319 propFile, toolDeps := f.buildPropFile(ctx) 320 output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath 321 builder.Command().BuiltTool("build_image"). 322 Text(rootDir.String()). // input directory 323 Input(propFile). 324 Implicits(toolDeps). 325 Output(output). 326 Text(rootDir.String()) // directory where to find fs_config_files|dirs 327 328 // rootDir is not deleted. Might be useful for quick inspection. 329 builder.Build("build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) 330 331 return output 332} 333 334func (f *filesystem) buildFileContexts(ctx android.ModuleContext) android.OutputPath { 335 builder := android.NewRuleBuilder(pctx, ctx) 336 fcBin := android.PathForModuleOut(ctx, "file_contexts.bin") 337 builder.Command().BuiltTool("sefcontext_compile"). 338 FlagWithOutput("-o ", fcBin). 339 Input(android.PathForModuleSrc(ctx, proptools.String(f.properties.File_contexts))) 340 builder.Build("build_filesystem_file_contexts", fmt.Sprintf("Creating filesystem file contexts for %s", f.BaseModuleName())) 341 return fcBin.OutputPath 342} 343 344// Calculates avb_salt from entry list (sorted) for deterministic output. 345func (f *filesystem) salt() string { 346 return sha1sum(f.entries) 347} 348 349func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android.OutputPath, toolDeps android.Paths) { 350 var deps android.Paths 351 var propFileString strings.Builder 352 addStr := func(name string, value string) { 353 propFileString.WriteString(name) 354 propFileString.WriteRune('=') 355 propFileString.WriteString(value) 356 propFileString.WriteRune('\n') 357 } 358 addPath := func(name string, path android.Path) { 359 addStr(name, path.String()) 360 deps = append(deps, path) 361 } 362 363 // Type string that build_image.py accepts. 364 fsTypeStr := func(t fsType) string { 365 switch t { 366 // TODO(jiyong): add more types like f2fs, erofs, etc. 367 case ext4Type: 368 return "ext4" 369 } 370 panic(fmt.Errorf("unsupported fs type %v", t)) 371 } 372 373 addStr("fs_type", fsTypeStr(f.fsType(ctx))) 374 addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/")) 375 addStr("use_dynamic_partition_size", "true") 376 addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs")) 377 // b/177813163 deps of the host tools have to be added. Remove this. 378 for _, t := range []string{"mke2fs", "e2fsdroid", "tune2fs"} { 379 deps = append(deps, ctx.Config().HostToolPath(ctx, t)) 380 } 381 382 if proptools.Bool(f.properties.Use_avb) { 383 addStr("avb_hashtree_enable", "true") 384 addPath("avb_avbtool", ctx.Config().HostToolPath(ctx, "avbtool")) 385 algorithm := proptools.StringDefault(f.properties.Avb_algorithm, "SHA256_RSA4096") 386 addStr("avb_algorithm", algorithm) 387 key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key)) 388 addPath("avb_key_path", key) 389 addStr("partition_name", f.partitionName()) 390 avb_add_hashtree_footer_args := "--do_not_generate_fec" 391 if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" { 392 avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm 393 } 394 if f.properties.Rollback_index != nil { 395 rollbackIndex := proptools.Int(f.properties.Rollback_index) 396 if rollbackIndex < 0 { 397 ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative") 398 } 399 avb_add_hashtree_footer_args += " --rollback_index " + strconv.Itoa(rollbackIndex) 400 } 401 securityPatchKey := "com.android.build." + f.partitionName() + ".security_patch" 402 securityPatchValue := ctx.Config().PlatformSecurityPatch() 403 avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue 404 addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args) 405 addStr("avb_salt", f.salt()) 406 } 407 408 if proptools.String(f.properties.File_contexts) != "" { 409 addPath("selinux_fc", f.buildFileContexts(ctx)) 410 } 411 if timestamp := proptools.String(f.properties.Fake_timestamp); timestamp != "" { 412 addStr("timestamp", timestamp) 413 } 414 if uuid := proptools.String(f.properties.Uuid); uuid != "" { 415 addStr("uuid", uuid) 416 addStr("hash_seed", uuid) 417 } 418 propFile = android.PathForModuleOut(ctx, "prop").OutputPath 419 android.WriteFileRuleVerbatim(ctx, propFile, propFileString.String()) 420 return propFile, deps 421} 422 423func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) android.OutputPath { 424 if proptools.Bool(f.properties.Use_avb) { 425 ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+ 426 "Consider adding this to bootimg module and signing the entire boot image.") 427 } 428 429 if proptools.String(f.properties.File_contexts) != "" { 430 ctx.PropertyErrorf("file_contexts", "file_contexts is not supported for compressed cpio image.") 431 } 432 433 if f.properties.Include_make_built_files != "" { 434 ctx.PropertyErrorf("include_make_built_files", "include_make_built_files is not supported for compressed cpio image.") 435 } 436 437 rootDir := android.PathForModuleOut(ctx, "root").OutputPath 438 rebasedDir := rootDir 439 if f.properties.Base_dir != nil { 440 rebasedDir = rootDir.Join(ctx, *f.properties.Base_dir) 441 } 442 builder := android.NewRuleBuilder(pctx, ctx) 443 // Wipe the root dir to get rid of leftover files from prior builds 444 builder.Command().Textf("rm -rf %s && mkdir -p %s", rootDir, rootDir) 445 specs := f.gatherFilteredPackagingSpecs(ctx) 446 f.entries = f.CopySpecsToDir(ctx, builder, specs, rebasedDir) 447 448 f.buildNonDepsFiles(ctx, builder, rootDir) 449 f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir) 450 f.buildEventLogtagsFile(ctx, builder, rebasedDir) 451 f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir) 452 453 output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath 454 cmd := builder.Command(). 455 BuiltTool("mkbootfs"). 456 Text(rootDir.String()) // input directory 457 if compressed { 458 cmd.Text("|"). 459 BuiltTool("lz4"). 460 Flag("--favor-decSpeed"). // for faster boot 461 Flag("-12"). // maximum compression level 462 Flag("-l"). // legacy format for kernel 463 Text(">").Output(output) 464 } else { 465 cmd.Text(">").Output(output) 466 } 467 468 // rootDir is not deleted. Might be useful for quick inspection. 469 builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) 470 471 return output 472} 473 474var validPartitions = []string{ 475 "system", 476 "userdata", 477 "cache", 478 "system_other", 479 "vendor", 480 "product", 481 "system_ext", 482 "odm", 483 "vendor_dlkm", 484 "odm_dlkm", 485 "system_dlkm", 486} 487 488func (f *filesystem) addMakeBuiltFiles(ctx android.ModuleContext, builder *android.RuleBuilder, rootDir android.Path) { 489 partition := f.properties.Include_make_built_files 490 if partition == "" { 491 return 492 } 493 if !slices.Contains(validPartitions, partition) { 494 ctx.PropertyErrorf("include_make_built_files", "Expected one of %#v, found %q", validPartitions, partition) 495 return 496 } 497 stampFile := fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/staging_dir.stamp", ctx.Config().DeviceName(), partition) 498 fileListFile := fmt.Sprintf("target/product/%s/obj/PACKAGING/%s_intermediates/file_list.txt", ctx.Config().DeviceName(), partition) 499 stagingDir := fmt.Sprintf("target/product/%s/%s", ctx.Config().DeviceName(), partition) 500 501 builder.Command().BuiltTool("merge_directories"). 502 Implicit(android.PathForArbitraryOutput(ctx, stampFile)). 503 Text("--ignore-duplicates"). 504 FlagWithInput("--file-list", android.PathForArbitraryOutput(ctx, fileListFile)). 505 Text(rootDir.String()). 506 Text(android.PathForArbitraryOutput(ctx, stagingDir).String()) 507} 508 509func (f *filesystem) buildEventLogtagsFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) { 510 if !proptools.Bool(f.properties.Build_logtags) { 511 return 512 } 513 514 logtagsFilePaths := make(map[string]bool) 515 ctx.WalkDeps(func(child, parent android.Module) bool { 516 if logtagsInfo, ok := android.OtherModuleProvider(ctx, child, android.LogtagsProviderKey); ok { 517 for _, path := range logtagsInfo.Logtags { 518 logtagsFilePaths[path.String()] = true 519 } 520 } 521 return true 522 }) 523 524 if len(logtagsFilePaths) == 0 { 525 return 526 } 527 528 etcPath := rebasedDir.Join(ctx, "etc") 529 eventLogtagsPath := etcPath.Join(ctx, "event-log-tags") 530 builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String()) 531 cmd := builder.Command().BuiltTool("merge-event-log-tags"). 532 FlagWithArg("-o ", eventLogtagsPath.String()). 533 FlagWithInput("-m ", android.MergedLogtagsPath(ctx)) 534 535 for _, path := range android.SortedKeys(logtagsFilePaths) { 536 cmd.Text(path) 537 } 538} 539 540type partition interface { 541 PartitionType() string 542} 543 544func (f *filesystem) PartitionType() string { 545 return proptools.StringDefault(f.properties.Partition_type, "system") 546} 547 548var _ partition = (*filesystem)(nil) 549 550var _ android.AndroidMkEntriesProvider = (*filesystem)(nil) 551 552// Implements android.AndroidMkEntriesProvider 553func (f *filesystem) AndroidMkEntries() []android.AndroidMkEntries { 554 return []android.AndroidMkEntries{android.AndroidMkEntries{ 555 Class: "ETC", 556 OutputFile: android.OptionalPathForPath(f.output), 557 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 558 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 559 entries.SetString("LOCAL_MODULE_PATH", f.installDir.String()) 560 entries.SetString("LOCAL_INSTALLED_MODULE_STEM", f.installFileName()) 561 }, 562 }, 563 }} 564} 565 566// Filesystem is the public interface for the filesystem struct. Currently, it's only for the apex 567// package to have access to the output file. 568type Filesystem interface { 569 android.Module 570 OutputPath() android.Path 571 572 // Returns the output file that is signed by avbtool. If this module is not signed, returns 573 // nil. 574 SignedOutputPath() android.Path 575} 576 577var _ Filesystem = (*filesystem)(nil) 578 579func (f *filesystem) OutputPath() android.Path { 580 return f.output 581} 582 583func (f *filesystem) SignedOutputPath() android.Path { 584 if proptools.Bool(f.properties.Use_avb) { 585 return f.OutputPath() 586 } 587 return nil 588} 589 590// Filter the result of GatherPackagingSpecs to discard items targeting outside "system" partition. 591// Note that "apex" module installs its contents to "apex"(fake partition) as well 592// for symbol lookup by imitating "activated" paths. 593func (f *filesystem) gatherFilteredPackagingSpecs(ctx android.ModuleContext) map[string]android.PackagingSpec { 594 specs := f.PackagingBase.GatherPackagingSpecsWithFilter(ctx, f.filterPackagingSpec) 595 return specs 596} 597 598func sha1sum(values []string) string { 599 h := sha256.New() 600 for _, value := range values { 601 io.WriteString(h, value) 602 } 603 return fmt.Sprintf("%x", h.Sum(nil)) 604} 605 606// Base cc.UseCoverage 607 608var _ cc.UseCoverage = (*filesystem)(nil) 609 610func (*filesystem) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool { 611 return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() 612} 613 614// android_filesystem_defaults 615 616type filesystemDefaults struct { 617 android.ModuleBase 618 android.DefaultsModuleBase 619 620 properties filesystemDefaultsProperties 621} 622 623type filesystemDefaultsProperties struct { 624 // Identifies which partition this is for //visibility:any_system_image (and others) visibility 625 // checks, and will be used in the future for API surface checks. 626 Partition_type *string 627} 628 629// android_filesystem_defaults is a default module for android_filesystem and android_system_image 630func filesystemDefaultsFactory() android.Module { 631 module := &filesystemDefaults{} 632 module.AddProperties(&module.properties) 633 module.AddProperties(&android.PackagingProperties{}) 634 android.InitDefaultsModule(module) 635 return module 636} 637 638func (f *filesystemDefaults) PartitionType() string { 639 return proptools.StringDefault(f.properties.Partition_type, "system") 640} 641 642var _ partition = (*filesystemDefaults)(nil) 643 644func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { 645 validatePartitionType(ctx, f) 646} 647