• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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