1// Copyright (C) 2019 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 selinux 16 17import ( 18 "fmt" 19 "io" 20 21 "github.com/google/blueprint" 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/sysprop" 26) 27 28type selinuxContextsProperties struct { 29 // Filenames under sepolicy directories, which will be used to generate contexts file. 30 Srcs []string `android:"path"` 31 32 // Output file name. Defaults to module name 33 Stem *string 34 35 Product_variables struct { 36 Address_sanitize struct { 37 Srcs []string `android:"path"` 38 } 39 } 40 41 // Whether the comments in generated contexts file will be removed or not. 42 Remove_comment *bool 43 44 // Whether the result context file is sorted with fc_sort or not. 45 Fc_sort *bool 46 47 // Make this module available when building for recovery 48 Recovery_available *bool 49} 50 51type seappProperties struct { 52 // Files containing neverallow rules. 53 Neverallow_files []string `android:"path"` 54 55 // Precompiled sepolicy binary file which will be fed to checkseapp. 56 Sepolicy *string `android:"path"` 57} 58 59type selinuxContextsModule struct { 60 android.ModuleBase 61 android.DefaultableModuleBase 62 flaggableModuleBase 63 64 properties selinuxContextsProperties 65 seappProperties seappProperties 66 build func(ctx android.ModuleContext, inputs android.Paths) android.Path 67 deps func(ctx android.BottomUpMutatorContext) 68 outputPath android.Path 69 installPath android.InstallPath 70} 71 72var _ flaggableModule = (*selinuxContextsModule)(nil) 73 74var ( 75 reuseContextsDepTag = dependencyTag{name: "reuseContexts"} 76 syspropLibraryDepTag = dependencyTag{name: "sysprop_library"} 77) 78 79func init() { 80 pctx.HostBinToolVariable("fc_sort", "fc_sort") 81 82 android.RegisterModuleType("contexts_defaults", contextsDefaultsFactory) 83 android.RegisterModuleType("file_contexts", fileFactory) 84 android.RegisterModuleType("hwservice_contexts", hwServiceFactory) 85 android.RegisterModuleType("property_contexts", propertyFactory) 86 android.RegisterModuleType("service_contexts", serviceFactory) 87 android.RegisterModuleType("keystore2_key_contexts", keystoreKeyFactory) 88 android.RegisterModuleType("seapp_contexts", seappFactory) 89 android.RegisterModuleType("vndservice_contexts", vndServiceFactory) 90 91 android.RegisterModuleType("file_contexts_test", fileContextsTestFactory) 92 android.RegisterModuleType("property_contexts_test", propertyContextsTestFactory) 93 android.RegisterModuleType("hwservice_contexts_test", hwserviceContextsTestFactory) 94 android.RegisterModuleType("service_contexts_test", serviceContextsTestFactory) 95 android.RegisterModuleType("vndservice_contexts_test", vndServiceContextsTestFactory) 96} 97 98func (m *selinuxContextsModule) InstallInRoot() bool { 99 return m.InRecovery() 100} 101 102func (m *selinuxContextsModule) InstallInRecovery() bool { 103 // ModuleBase.InRecovery() checks the image variant 104 return m.InRecovery() 105} 106 107func (m *selinuxContextsModule) onlyInRecovery() bool { 108 // ModuleBase.InstallInRecovery() checks commonProperties.Recovery property 109 return m.ModuleBase.InstallInRecovery() 110} 111 112func (m *selinuxContextsModule) DepsMutator(ctx android.BottomUpMutatorContext) { 113 m.flagDeps(ctx) 114 115 if m.deps != nil { 116 m.deps(ctx) 117 } 118 119 if m.InRecovery() && !m.onlyInRecovery() { 120 ctx.AddFarVariationDependencies([]blueprint.Variation{ 121 {Mutator: "image", Variation: android.CoreVariation}, 122 }, reuseContextsDepTag, ctx.ModuleName()) 123 } 124} 125 126func (m *selinuxContextsModule) propertyContextsDeps(ctx android.BottomUpMutatorContext) { 127 for _, lib := range sysprop.SyspropLibraries(ctx.Config()) { 128 ctx.AddFarVariationDependencies([]blueprint.Variation{}, syspropLibraryDepTag, lib) 129 } 130} 131 132func (m *selinuxContextsModule) stem() string { 133 return proptools.StringDefault(m.properties.Stem, m.Name()) 134} 135 136func (m *selinuxContextsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 137 if m.InRecovery() { 138 // Installing context files at the root of the recovery partition 139 m.installPath = android.PathForModuleInstall(ctx) 140 } else { 141 m.installPath = android.PathForModuleInstall(ctx, "etc", "selinux") 142 } 143 144 if m.InRecovery() && !m.onlyInRecovery() { 145 dep := ctx.GetDirectDepWithTag(m.Name(), reuseContextsDepTag) 146 147 if reuseDeps, ok := dep.(*selinuxContextsModule); ok { 148 m.outputPath = reuseDeps.outputPath 149 ctx.InstallFile(m.installPath, m.stem(), m.outputPath) 150 return 151 } 152 } 153 154 m.outputPath = m.build(ctx, android.PathsForModuleSrc(ctx, m.properties.Srcs)) 155 ctx.InstallFile(m.installPath, m.stem(), m.outputPath) 156 157 ctx.SetOutputFiles([]android.Path{m.outputPath}, "") 158} 159 160func newModule() *selinuxContextsModule { 161 m := &selinuxContextsModule{} 162 m.AddProperties( 163 &m.properties, 164 &m.seappProperties, 165 ) 166 initFlaggableModule(m) 167 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 168 android.InitDefaultableModule(m) 169 android.AddLoadHook(m, func(ctx android.LoadHookContext) { 170 m.selinuxContextsHook(ctx) 171 }) 172 return m 173} 174 175type contextsDefaults struct { 176 android.ModuleBase 177 android.DefaultsModuleBase 178} 179 180// contexts_defaults provides a set of properties that can be inherited by other contexts modules. 181// (file_contexts, property_contexts, seapp_contexts, etc.) A module can use the properties from a 182// contexts_defaults using `defaults: ["<:default_module_name>"]`. Properties of both modules are 183// erged (when possible) by prepending the default module's values to the depending module's values. 184func contextsDefaultsFactory() android.Module { 185 m := &contextsDefaults{} 186 m.AddProperties( 187 &selinuxContextsProperties{}, 188 &seappProperties{}, 189 &flaggableModuleProperties{}, 190 ) 191 android.InitDefaultsModule(m) 192 return m 193} 194 195func (m *selinuxContextsModule) selinuxContextsHook(ctx android.LoadHookContext) { 196 // TODO: clean this up to use build/soong/android/variable.go after b/79249983 197 var srcs []string 198 199 for _, sanitize := range ctx.Config().SanitizeDevice() { 200 if sanitize == "address" { 201 srcs = append(srcs, m.properties.Product_variables.Address_sanitize.Srcs...) 202 break 203 } 204 } 205 206 m.properties.Srcs = append(m.properties.Srcs, srcs...) 207} 208 209func (m *selinuxContextsModule) AndroidMk() android.AndroidMkData { 210 nameSuffix := "" 211 if m.InRecovery() && !m.onlyInRecovery() { 212 nameSuffix = ".recovery" 213 } 214 return android.AndroidMkData{ 215 Class: "ETC", 216 OutputFile: android.OptionalPathForPath(m.outputPath), 217 SubName: nameSuffix, 218 Extra: []android.AndroidMkExtraFunc{ 219 func(w io.Writer, outputFile android.Path) { 220 fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", m.installPath.String()) 221 fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", m.stem()) 222 }, 223 }, 224 } 225} 226 227func (m *selinuxContextsModule) ImageMutatorBegin(ctx android.BaseModuleContext) { 228 if proptools.Bool(m.properties.Recovery_available) && m.ModuleBase.InstallInRecovery() { 229 ctx.PropertyErrorf("recovery_available", 230 "doesn't make sense at the same time as `recovery: true`") 231 } 232} 233 234func (m *selinuxContextsModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool { 235 return !m.ModuleBase.InstallInRecovery() 236} 237 238func (m *selinuxContextsModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 239 return false 240} 241 242func (m *selinuxContextsModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 243 return false 244} 245 246func (m *selinuxContextsModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 247 return false 248} 249 250func (m *selinuxContextsModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { 251 return m.ModuleBase.InstallInRecovery() || proptools.Bool(m.properties.Recovery_available) 252} 253 254func (m *selinuxContextsModule) ExtraImageVariations(ctx android.BaseModuleContext) []string { 255 return nil 256} 257 258func (m *selinuxContextsModule) SetImageVariation(ctx android.BaseModuleContext, variation string) { 259} 260 261var _ android.ImageInterface = (*selinuxContextsModule)(nil) 262 263func (m *selinuxContextsModule) buildGeneralContexts(ctx android.ModuleContext, inputs android.Paths) android.Path { 264 builtContext := pathForModuleOut(ctx, ctx.ModuleName()+"_m4out") 265 266 rule := android.NewRuleBuilder(pctx, ctx) 267 268 newlineFile := pathForModuleOut(ctx, "newline") 269 270 rule.Command().Text("echo").FlagWithOutput("> ", newlineFile) 271 rule.Temporary(newlineFile) 272 273 var inputsWithNewline android.Paths 274 for _, input := range inputs { 275 inputsWithNewline = append(inputsWithNewline, input, newlineFile) 276 } 277 278 flags := m.getBuildFlags(ctx) 279 rule.Command(). 280 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")). 281 Text("--fatal-warnings -s"). 282 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()). 283 Flags(flagsToM4Macros(flags)). 284 Inputs(inputsWithNewline). 285 FlagWithOutput("> ", builtContext) 286 287 if proptools.Bool(m.properties.Remove_comment) { 288 rule.Temporary(builtContext) 289 290 remove_comment_output := pathForModuleOut(ctx, ctx.ModuleName()+"_remove_comment") 291 292 rule.Command(). 293 Text("sed -e 's/#.*$//' -e '/^$/d'"). 294 Input(builtContext). 295 FlagWithOutput("> ", remove_comment_output) 296 297 builtContext = remove_comment_output 298 } 299 300 if proptools.Bool(m.properties.Fc_sort) { 301 rule.Temporary(builtContext) 302 303 sorted_output := pathForModuleOut(ctx, ctx.ModuleName()+"_sorted") 304 305 rule.Command(). 306 Tool(ctx.Config().HostToolPath(ctx, "fc_sort")). 307 FlagWithInput("-i ", builtContext). 308 FlagWithOutput("-o ", sorted_output) 309 310 builtContext = sorted_output 311 } 312 313 ret := pathForModuleOut(ctx, m.stem()) 314 rule.Temporary(builtContext) 315 rule.Command().Text("cp").Input(builtContext).Output(ret) 316 317 rule.DeleteTemporaryFiles() 318 rule.Build("selinux_contexts", "building contexts: "+m.Name()) 319 320 return ret 321} 322 323func (m *selinuxContextsModule) buildFileContexts(ctx android.ModuleContext, inputs android.Paths) android.Path { 324 if m.properties.Remove_comment == nil { 325 m.properties.Remove_comment = proptools.BoolPtr(true) 326 } 327 return m.buildGeneralContexts(ctx, inputs) 328} 329 330func fileFactory() android.Module { 331 m := newModule() 332 m.build = m.buildFileContexts 333 return m 334} 335 336func (m *selinuxContextsModule) buildServiceContexts(ctx android.ModuleContext, inputs android.Paths) android.Path { 337 if m.properties.Remove_comment == nil { 338 m.properties.Remove_comment = proptools.BoolPtr(true) 339 } 340 341 return m.buildGeneralContexts(ctx, inputs) 342} 343 344func (m *selinuxContextsModule) checkVendorPropertyNamespace(ctx android.ModuleContext, input android.Path) android.Path { 345 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel() 346 ApiLevelR := android.ApiLevelOrPanic(ctx, "R") 347 348 rule := android.NewRuleBuilder(pctx, ctx) 349 350 // This list is from vts_treble_sys_prop_test. 351 allowedPropertyPrefixes := []string{ 352 "ctl.odm.", 353 "ctl.vendor.", 354 "ctl.start$odm.", 355 "ctl.start$vendor.", 356 "ctl.stop$odm.", 357 "ctl.stop$vendor.", 358 "init.svc.odm.", 359 "init.svc.vendor.", 360 "ro.boot.", 361 "ro.hardware.", 362 "ro.odm.", 363 "ro.vendor.", 364 "odm.", 365 "persist.odm.", 366 "persist.vendor.", 367 "vendor.", 368 } 369 370 // persist.camera is also allowed for devices launching with R or eariler 371 if shippingApiLevel.LessThanOrEqualTo(ApiLevelR) { 372 allowedPropertyPrefixes = append(allowedPropertyPrefixes, "persist.camera.") 373 } 374 375 var allowedContextPrefixes []string 376 377 if shippingApiLevel.GreaterThanOrEqualTo(ApiLevelR) { 378 // This list is from vts_treble_sys_prop_test. 379 allowedContextPrefixes = []string{ 380 "vendor_", 381 "odm_", 382 } 383 } 384 385 cmd := rule.Command(). 386 BuiltTool("check_prop_prefix"). 387 FlagWithInput("--property-contexts ", input). 388 FlagForEachArg("--allowed-property-prefix ", proptools.ShellEscapeList(allowedPropertyPrefixes)). // contains shell special character '$' 389 FlagForEachArg("--allowed-context-prefix ", allowedContextPrefixes) 390 391 if !ctx.DeviceConfig().BuildBrokenVendorPropertyNamespace() { 392 cmd.Flag("--strict") 393 } 394 395 out := pathForModuleOut(ctx, ctx.ModuleName()+"_namespace_checked") 396 rule.Command().Text("cp -f").Input(input).Output(out) 397 rule.Build("check_namespace", "checking namespace of "+ctx.ModuleName()) 398 return out 399} 400 401func (m *selinuxContextsModule) buildPropertyContexts(ctx android.ModuleContext, inputs android.Paths) android.Path { 402 // vendor/odm properties are enforced for devices launching with Android Q or later. So, if 403 // vendor/odm, make sure that only vendor/odm properties exist. 404 builtCtxFile := m.buildGeneralContexts(ctx, inputs) 405 406 shippingApiLevel := ctx.DeviceConfig().ShippingApiLevel() 407 ApiLevelQ := android.ApiLevelOrPanic(ctx, "Q") 408 if (ctx.SocSpecific() || ctx.DeviceSpecific()) && shippingApiLevel.GreaterThanOrEqualTo(ApiLevelQ) { 409 builtCtxFile = m.checkVendorPropertyNamespace(ctx, builtCtxFile) 410 } 411 412 var apiFiles android.Paths 413 ctx.VisitDirectDepsWithTag(syspropLibraryDepTag, func(c android.Module) { 414 i, ok := c.(interface{ CurrentSyspropApiFile() android.OptionalPath }) 415 if !ok { 416 panic(fmt.Errorf("unknown dependency %q for %q", ctx.OtherModuleName(c), ctx.ModuleName())) 417 } 418 if api := i.CurrentSyspropApiFile(); api.Valid() { 419 apiFiles = append(apiFiles, api.Path()) 420 } 421 }) 422 423 // check compatibility with sysprop_library 424 if len(apiFiles) > 0 { 425 out := pathForModuleOut(ctx, ctx.ModuleName()+"_api_checked") 426 rule := android.NewRuleBuilder(pctx, ctx) 427 428 msg := `\n******************************\n` + 429 `API of sysprop_library doesn't match with property_contexts\n` + 430 `Please fix the breakage and rebuild.\n` + 431 `******************************\n` 432 433 rule.Command(). 434 Text("( "). 435 BuiltTool("sysprop_type_checker"). 436 FlagForEachInput("--api ", apiFiles). 437 FlagWithInput("--context ", builtCtxFile). 438 Text(" || ( echo").Flag("-e"). 439 Flag(`"` + msg + `"`). 440 Text("; exit 38) )") 441 442 rule.Command().Text("cp -f").Input(builtCtxFile).Output(out) 443 rule.Build("property_contexts_check_api", "checking API: "+m.Name()) 444 builtCtxFile = out 445 } 446 447 return builtCtxFile 448} 449 450func (m *selinuxContextsModule) shouldCheckCoredomain(ctx android.ModuleContext) bool { 451 if !ctx.SocSpecific() && !ctx.DeviceSpecific() { 452 return false 453 } 454 455 return ctx.DeviceConfig().CheckVendorSeappViolations() 456} 457 458func (m *selinuxContextsModule) buildSeappContexts(ctx android.ModuleContext, inputs android.Paths) android.Path { 459 neverallowFile := pathForModuleOut(ctx, "neverallow") 460 ret := pathForModuleOut(ctx, "checkseapp", m.stem()) 461 462 // Step 1. Generate a M4 processed neverallow file 463 flags := m.getBuildFlags(ctx) 464 m4NeverallowFile := pathForModuleOut(ctx, "neverallow.m4out") 465 rule := android.NewRuleBuilder(pctx, ctx) 466 rule.Command(). 467 Tool(ctx.Config().PrebuiltBuildTool(ctx, "m4")). 468 Flag("--fatal-warnings"). 469 FlagForEachArg("-D", ctx.DeviceConfig().SepolicyM4Defs()). 470 Flags(flagsToM4Macros(flags)). 471 Inputs(android.PathsForModuleSrc(ctx, m.seappProperties.Neverallow_files)). 472 FlagWithOutput("> ", m4NeverallowFile) 473 474 rule.Temporary(m4NeverallowFile) 475 rule.Command(). 476 Text("( grep"). 477 Flag("-ihe"). 478 Text("'^neverallow'"). 479 Input(m4NeverallowFile). 480 Text(">"). 481 Output(neverallowFile). 482 Text("|| true )") // to make ninja happy even when result is empty 483 484 // Step 2. Generate a M4 processed contexts file 485 builtCtx := m.buildGeneralContexts(ctx, inputs) 486 487 // Step 3. checkseapp 488 rule.Temporary(neverallowFile) 489 checkCmd := rule.Command().BuiltTool("checkseapp"). 490 FlagWithInput("-p ", android.PathForModuleSrc(ctx, proptools.String(m.seappProperties.Sepolicy))). 491 FlagWithOutput("-o ", ret). 492 Input(builtCtx). 493 Input(neverallowFile) 494 495 if m.shouldCheckCoredomain(ctx) { 496 checkCmd.Flag("-c") // check coredomain for vendor contexts 497 } 498 499 rule.Build("seapp_contexts", "Building seapp_contexts: "+m.Name()) 500 return ret 501} 502 503func hwServiceFactory() android.Module { 504 m := newModule() 505 m.build = m.buildServiceContexts 506 return m 507} 508 509func propertyFactory() android.Module { 510 m := newModule() 511 m.build = m.buildPropertyContexts 512 m.deps = m.propertyContextsDeps 513 return m 514} 515 516func serviceFactory() android.Module { 517 m := newModule() 518 m.build = m.buildServiceContexts 519 return m 520} 521 522func keystoreKeyFactory() android.Module { 523 m := newModule() 524 m.build = m.buildGeneralContexts 525 return m 526} 527 528func seappFactory() android.Module { 529 m := newModule() 530 m.build = m.buildSeappContexts 531 return m 532} 533 534func vndServiceFactory() android.Module { 535 m := newModule() 536 m.build = m.buildGeneralContexts 537 android.AddLoadHook(m, func(ctx android.LoadHookContext) { 538 if !ctx.SocSpecific() { 539 ctx.ModuleErrorf(m.Name(), "must set vendor: true") 540 return 541 } 542 }) 543 return m 544} 545 546type contextsTestProperties struct { 547 // Contexts files to be tested. 548 Srcs []string `android:"path"` 549 550 // Precompiled sepolicy binary to be tesed together. 551 Sepolicy *string `android:"path"` 552} 553 554type fileContextsTestProperties struct { 555 // Test data. File passed to `checkfc -t` to validate how contexts are resolved. 556 Test_data *string `android:"path"` 557} 558 559type contextsTestModule struct { 560 android.ModuleBase 561 562 // The type of context. 563 context contextType 564 565 properties contextsTestProperties 566 fileProperties fileContextsTestProperties 567 testTimestamp android.OutputPath 568} 569 570type contextType int 571 572const ( 573 FileContext contextType = iota 574 PropertyContext 575 ServiceContext 576 HwServiceContext 577 VndServiceContext 578) 579 580// checkfc parses a context file and checks for syntax errors. 581// If -s is specified, the service backend is used to verify binder services. 582// If -l is specified, the service backend is used to verify hwbinder services. 583// Otherwise, context_file is assumed to be a file_contexts file 584// If -e is specified, then the context_file is allowed to be empty. 585 586// file_contexts_test tests given file_contexts files with checkfc. 587func fileContextsTestFactory() android.Module { 588 m := &contextsTestModule{context: FileContext} 589 m.AddProperties(&m.properties) 590 m.AddProperties(&m.fileProperties) 591 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 592 return m 593} 594 595// property_contexts_test tests given property_contexts files with property_info_checker. 596func propertyContextsTestFactory() android.Module { 597 m := &contextsTestModule{context: PropertyContext} 598 m.AddProperties(&m.properties) 599 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 600 return m 601} 602 603// hwservice_contexts_test tests given hwservice_contexts files with checkfc. 604func hwserviceContextsTestFactory() android.Module { 605 m := &contextsTestModule{context: HwServiceContext} 606 m.AddProperties(&m.properties) 607 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 608 return m 609} 610 611// service_contexts_test tests given service_contexts files with checkfc. 612func serviceContextsTestFactory() android.Module { 613 // checkfc -s: service_contexts test 614 m := &contextsTestModule{context: ServiceContext} 615 m.AddProperties(&m.properties) 616 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 617 return m 618} 619 620// vndservice_contexts_test tests given vndservice_contexts files with checkfc. 621func vndServiceContextsTestFactory() android.Module { 622 m := &contextsTestModule{context: VndServiceContext} 623 m.AddProperties(&m.properties) 624 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 625 return m 626} 627 628func (m *contextsTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 629 tool := "checkfc" 630 if m.context == PropertyContext { 631 tool = "property_info_checker" 632 } 633 634 if len(m.properties.Srcs) == 0 { 635 ctx.PropertyErrorf("srcs", "can't be empty") 636 return 637 } 638 639 validateWithPolicy := true 640 if proptools.String(m.properties.Sepolicy) == "" { 641 if m.context == FileContext { 642 if proptools.String(m.fileProperties.Test_data) == "" { 643 ctx.PropertyErrorf("test_data", "Either test_data or sepolicy should be provided") 644 return 645 } 646 validateWithPolicy = false 647 } else { 648 ctx.PropertyErrorf("sepolicy", "can't be empty") 649 return 650 } 651 } 652 653 flags := []string(nil) 654 switch m.context { 655 case FileContext: 656 if !validateWithPolicy { 657 flags = []string{"-t"} 658 } 659 case ServiceContext: 660 flags = []string{"-s" /* binder services */} 661 case HwServiceContext: 662 flags = []string{"-e" /* allow empty */, "-l" /* hwbinder services */} 663 case VndServiceContext: 664 flags = []string{"-e" /* allow empty */, "-v" /* vnd service */} 665 } 666 667 srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs) 668 rule := android.NewRuleBuilder(pctx, ctx) 669 670 if validateWithPolicy { 671 sepolicy := android.PathForModuleSrc(ctx, proptools.String(m.properties.Sepolicy)) 672 rule.Command().BuiltTool(tool). 673 Flags(flags). 674 Input(sepolicy). 675 Inputs(srcs) 676 } else { 677 test_data := android.PathForModuleSrc(ctx, proptools.String(m.fileProperties.Test_data)) 678 rule.Command().BuiltTool(tool). 679 Flags(flags). 680 Inputs(srcs). 681 Input(test_data) 682 } 683 684 m.testTimestamp = pathForModuleOut(ctx, "timestamp") 685 rule.Command().Text("touch").Output(m.testTimestamp) 686 rule.Build("contexts_test", "running contexts test: "+ctx.ModuleName()) 687} 688 689func (m *contextsTestModule) AndroidMkEntries() []android.AndroidMkEntries { 690 return []android.AndroidMkEntries{android.AndroidMkEntries{ 691 Class: "FAKE", 692 // OutputFile is needed, even though BUILD_PHONY_PACKAGE doesn't use it. 693 // Without OutputFile this module won't be exported to Makefile. 694 OutputFile: android.OptionalPathForPath(m.testTimestamp), 695 Include: "$(BUILD_PHONY_PACKAGE)", 696 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 697 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 698 entries.SetString("LOCAL_ADDITIONAL_DEPENDENCIES", m.testTimestamp.String()) 699 }, 700 }, 701 }} 702} 703 704// contextsTestModule implements ImageInterface to be able to include recovery_available contexts 705// modules as its sources. 706func (m *contextsTestModule) ImageMutatorBegin(ctx android.BaseModuleContext) { 707} 708 709func (m *contextsTestModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool { 710 return true 711} 712 713func (m *contextsTestModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 714 return false 715} 716 717func (m *contextsTestModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 718 return false 719} 720 721func (m *contextsTestModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { 722 return false 723} 724 725func (m *contextsTestModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { 726 return false 727} 728 729func (m *contextsTestModule) ExtraImageVariations(ctx android.BaseModuleContext) []string { 730 return nil 731} 732 733func (m *contextsTestModule) SetImageVariation(ctx android.BaseModuleContext, variation string) { 734} 735 736var _ android.ImageInterface = (*contextsTestModule)(nil) 737