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 gki 16 17import ( 18 "fmt" 19 "io" 20 21 "android/soong/android" 22 "android/soong/apex" 23 "github.com/google/blueprint/proptools" 24) 25 26var ( 27 prebuiltApexTag = dependencyTag{name: "prebuilt_apex"} 28) 29 30type prebuiltGkiApexProperties struct { 31 apex.PrebuiltProperties 32 33 // Declared KMI version of the boot image. Example: "5.4-android12-0" 34 Kmi_version *string 35} 36 37type prebuiltGkiApex struct { 38 android.ModuleBase 39 properties prebuiltGkiApexProperties 40 41 extractedBootImage android.WritablePath 42} 43 44func init() { 45 android.RegisterModuleType("prebuilt_gki_apex", prebuiltGkiApexFactory) 46} 47 48// Declare a prebuilt GKI APEX. When installed, the boot image is extracted from 49// the module. 50func prebuiltGkiApexFactory() android.Module { 51 g := &prebuiltGkiApex{} 52 g.AddProperties(&g.properties) 53 android.InitAndroidModule(g) 54 android.AddLoadHook(g, func(ctx android.LoadHookContext) { prebuiltGkiApexMutator(ctx, g) }) 55 return g 56} 57func prebuiltGkiApexMutator(mctx android.LoadHookContext, g *prebuiltGkiApex) { 58 // Whether modules should be enabled according to board variables. 59 enabled := boardDefinesKmiVersion(mctx, proptools.String(g.properties.Kmi_version)) 60 if !enabled { 61 g.Disable() 62 } 63 64 // The prebuilt_apex module. 65 mctx.CreateModule(apex.PrebuiltFactory, &moduleCommonProperties{ 66 Name: proptools.StringPtr(g.BaseModuleName()), 67 Enabled: proptools.BoolPtr(enabled), 68 Product_specific: proptools.BoolPtr(true), 69 }, &g.properties.PrebuiltProperties) 70} 71 72// The appeared name of this prebuiltGkiApex object. Exposed to Soong to avoid conflicting with 73// the generated prebuilt_apex module with name BaseModuleName(). 74func (g *prebuiltGkiApex) Name() string { 75 return g.BaseModuleName() + "_boot_img" 76} 77 78func (g *prebuiltGkiApex) DepsMutator(ctx android.BottomUpMutatorContext) { 79 ctx.AddDependency(ctx.Module(), prebuiltApexTag, g.BaseModuleName()) 80} 81 82func (g *prebuiltGkiApex) GenerateAndroidBuildActions(ctx android.ModuleContext) { 83 var apexFile android.OptionalPath 84 ctx.VisitDirectDepsWithTag(prebuiltApexTag, func(m android.Module) { 85 if prebuiltApex, ok := m.(*apex.Prebuilt); ok { 86 srcFiles, err := prebuiltApex.OutputFiles("") 87 if err != nil { 88 ctx.ModuleErrorf("Cannot get output files from %q: %s", ctx.OtherModuleName(m), err) 89 } else if len(srcFiles) != 1 { 90 ctx.ModuleErrorf("%q generated %d files", ctx.OtherModuleName(m), len(srcFiles)) 91 } else { 92 apexFile = android.OptionalPathForPath(srcFiles[0]) 93 } 94 } else { 95 ctx.ModuleErrorf("%q is not a prebuilt_apex", ctx.OtherModuleName(m)) 96 } 97 }) 98 if !apexFile.Valid() { 99 ctx.ModuleErrorf("Can't determine the prebuilt APEX file") 100 return 101 } 102 103 genDir := android.PathForModuleOut(ctx, "extracted") 104 g.extractedBootImage = genDir.Join(ctx, "boot.img") 105 106 rule := android.NewRuleBuilder(pctx, ctx) 107 rule.Command(). 108 ImplicitOutput(g.extractedBootImage). 109 BuiltTool("extract_img_from_apex"). 110 Flag("--tool").BuiltTool("debugfs"). 111 Flag("--tool").BuiltTool("delta_generator"). 112 Input(apexFile.Path()). 113 Text(genDir.String()) 114 rule.Build("extractImgFromApex", "Extract boot image from prebuilt GKI APEX") 115 116 ctx.Phony(g.BaseModuleName(), g.extractedBootImage) 117} 118 119func (g *prebuiltGkiApex) AndroidMk() android.AndroidMkData { 120 return android.AndroidMkData{ 121 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { 122 fmt.Fprintf(w, "ALL_MODULES.%s.EXTRACTED_BOOT_IMAGE := %s\n", name, g.extractedBootImage) 123 }, 124 } 125} 126