blob: da8a1234b5e46c979eec837a80709b3604043068 [file] [log] [blame]
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gki
import (
"fmt"
"io"
"android/soong/android"
"android/soong/apex"
"github.com/google/blueprint/proptools"
)
var (
prebuiltApexTag = dependencyTag{name: "prebuilt_apex"}
)
type prebuiltGkiApexProperties struct {
apex.PrebuiltProperties
// Declared KMI version of the boot image. Example: "5.4-android12-0"
Kmi_version *string
}
type prebuiltGkiApex struct {
android.ModuleBase
properties prebuiltGkiApexProperties
extractedBootImage android.WritablePath
}
func init() {
android.RegisterModuleType("prebuilt_gki_apex", prebuiltGkiApexFactory)
}
// Declare a prebuilt GKI APEX. When installed, the boot image is extracted from
// the module.
func prebuiltGkiApexFactory() android.Module {
g := &prebuiltGkiApex{}
g.AddProperties(&g.properties)
android.InitAndroidModule(g)
android.AddLoadHook(g, func(ctx android.LoadHookContext) { prebuiltGkiApexMutator(ctx, g) })
return g
}
func prebuiltGkiApexMutator(mctx android.LoadHookContext, g *prebuiltGkiApex) {
// Whether modules should be enabled according to board variables.
enabled := boardDefinesKmiVersion(mctx, proptools.String(g.properties.Kmi_version))
if !enabled {
g.Disable()
}
// The prebuilt_apex module.
mctx.CreateModule(apex.PrebuiltFactory, &moduleCommonProperties{
Name: proptools.StringPtr(g.BaseModuleName()),
Enabled: proptools.BoolPtr(enabled),
Product_specific: proptools.BoolPtr(true),
}, &g.properties.PrebuiltProperties)
}
// The appeared name of this prebuiltGkiApex object. Exposed to Soong to avoid conflicting with
// the generated prebuilt_apex module with name BaseModuleName().
func (g *prebuiltGkiApex) Name() string {
return g.BaseModuleName() + "_boot_img"
}
func (g *prebuiltGkiApex) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), prebuiltApexTag, g.BaseModuleName())
}
func (g *prebuiltGkiApex) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var apexFile android.OptionalPath
ctx.VisitDirectDepsWithTag(prebuiltApexTag, func(m android.Module) {
if prebuiltApex, ok := m.(*apex.Prebuilt); ok {
srcFiles, err := prebuiltApex.OutputFiles("")
if err != nil {
ctx.ModuleErrorf("Cannot get output files from %q: %s", ctx.OtherModuleName(m), err)
} else if len(srcFiles) != 1 {
ctx.ModuleErrorf("%q generated %d files", ctx.OtherModuleName(m), len(srcFiles))
} else {
apexFile = android.OptionalPathForPath(srcFiles[0])
}
} else {
ctx.ModuleErrorf("%q is not a prebuilt_apex", ctx.OtherModuleName(m))
}
})
if !apexFile.Valid() {
ctx.ModuleErrorf("Can't determine the prebuilt APEX file")
return
}
genDir := android.PathForModuleOut(ctx, "extracted")
g.extractedBootImage = genDir.Join(ctx, "boot.img")
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
ImplicitOutput(g.extractedBootImage).
BuiltTool("extract_img_from_apex").
Flag("--tool").BuiltTool("debugfs").
Flag("--tool").BuiltTool("delta_generator").
Input(apexFile.Path()).
Text(genDir.String())
rule.Build("extractImgFromApex", "Extract boot image from prebuilt GKI APEX")
ctx.Phony(g.BaseModuleName(), g.extractedBootImage)
}
func (g *prebuiltGkiApex) AndroidMk() android.AndroidMkData {
return android.AndroidMkData{
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
fmt.Fprintf(w, "ALL_MODULES.%s.EXTRACTED_BOOT_IMAGE := %s\n", name, g.extractedBootImage)
},
}
}