blob: 401f4d2e55f1aa0b624e36a307fbfe703dea5935 [file] [log] [blame]
// Copyright 2024 Google Inc. All rights reserved.
//
// 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 android
import (
"fmt"
"strings"
"github.com/google/blueprint/proptools"
)
const (
deviceCmType = "device_cm"
systemManifestType = "system_manifest"
productManifestType = "product_manifest"
systemExtManifestType = "system_ext_manifest"
vendorManifestType = "vendor_manifest"
odmManifestType = "odm_manifest"
defaultDcm = "system/libhidl/vintfdata/device_compatibility_matrix.default.xml"
defaultSystemManifest = "system/libhidl/vintfdata/manifest.xml"
defaultSystemExtManifest = "system/libhidl/vintfdata/system_ext_manifest.default.xml"
)
type vintfDataProperties struct {
// Optional name for the installed file. If unspecified it will be manifest.xml by default.
Filename *string
// Type of the vintf data type, the allowed type are device_compatibility_matrix, system_manifest,
// product_manifest, and system_ext_manifest.
Type *string
}
type vintfDataRule struct {
ModuleBase
properties vintfDataProperties
installDirPath InstallPath
outputFilePath Path
noAction bool
}
func init() {
registerVintfDataComponents(InitRegistrationContext)
}
func registerVintfDataComponents(ctx RegistrationContext) {
ctx.RegisterModuleType("vintf_data", vintfDataFactory)
}
// vintf_fragment module processes vintf fragment file and installs under etc/vintf/manifest.
func vintfDataFactory() Module {
m := &vintfDataRule{}
m.AddProperties(
&m.properties,
)
InitAndroidArchModule(m, DeviceSupported, MultilibFirst)
return m
}
func (m *vintfDataRule) GenerateAndroidBuildActions(ctx ModuleContext) {
builder := NewRuleBuilder(pctx, ctx)
gensrc := PathForModuleOut(ctx, "manifest.xml")
assembleVintfEnvs := []string{}
inputPaths := make(Paths, 0)
switch proptools.String(m.properties.Type) {
case deviceCmType:
assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SYSTEMSDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().SystemSdkVersions(), " ")))
deviceMatrixs := PathsForSource(ctx, ctx.Config().DeviceMatrixFile())
if len(deviceMatrixs) > 0 {
inputPaths = append(inputPaths, deviceMatrixs...)
} else {
inputPaths = append(inputPaths, PathForSource(ctx, defaultDcm))
}
case systemManifestType:
assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PLATFORM_SYSTEMSDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().PlatformSystemSdkVersions(), " ")))
inputPaths = append(inputPaths, PathForSource(ctx, defaultSystemManifest))
systemManifestFiles := PathsForSource(ctx, ctx.Config().SystemManifestFile())
if len(systemManifestFiles) > 0 {
inputPaths = append(inputPaths, systemManifestFiles...)
}
case productManifestType:
productManifestFiles := PathsForSource(ctx, ctx.Config().ProductManifestFiles())
// Only need to generate the manifest if PRODUCT_MANIFEST_FILES not defined.
if len(productManifestFiles) == 0 {
m.noAction = true
return
}
inputPaths = append(inputPaths, productManifestFiles...)
case systemExtManifestType:
assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PROVIDED_VNDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().ExtraVndkVersions(), " ")))
inputPaths = append(inputPaths, PathForSource(ctx, defaultSystemExtManifest))
systemExtManifestFiles := PathsForSource(ctx, ctx.Config().SystemExtManifestFiles())
if len(systemExtManifestFiles) > 0 {
inputPaths = append(inputPaths, systemExtManifestFiles...)
}
case vendorManifestType:
assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SEPOLICY_VERS=\"%s\"", ctx.DeviceConfig().BoardSepolicyVers()))
assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PRODUCT_ENFORCE_VINTF_MANIFEST=%t", *ctx.Config().productVariables.Enforce_vintf_manifest))
deviceManifestFiles := PathsForSource(ctx, ctx.Config().DeviceManifestFiles())
// Only need to generate the manifest if DEVICE_MANIFEST_FILE is defined.
if len(deviceManifestFiles) == 0 {
m.noAction = true
return
}
inputPaths = append(inputPaths, deviceManifestFiles...)
case odmManifestType:
assembleVintfEnvs = append(assembleVintfEnvs, "VINTF_IGNORE_TARGET_FCM_VERSION=true")
odmManifestFiles := PathsForSource(ctx, ctx.Config().OdmManifestFiles())
// Only need to generate the manifest if ODM_MANIFEST_FILES is defined.
if len(odmManifestFiles) == 0 {
m.noAction = true
return
}
inputPaths = append(inputPaths, odmManifestFiles...)
default:
panic(fmt.Errorf("For %s: The attribute 'type' value only allowed device_cm, system_manifest, product_manifest, system_ext_manifest!", ctx.Module().Name()))
}
// Process vintf fragment source file with assemble_vintf tool
builder.Command().
Flags(assembleVintfEnvs).
BuiltTool("assemble_vintf").
FlagWithArg("-i ", strings.Join(inputPaths.Strings(), ":")).
FlagWithOutput("-o ", gensrc)
builder.Build("assemble_vintf", "Process vintf data "+gensrc.String())
m.installDirPath = PathForModuleInstall(ctx, "etc", "vintf")
m.outputFilePath = gensrc
installFileName := "manifest.xml"
if filename := proptools.String(m.properties.Filename); filename != "" {
installFileName = filename
}
ctx.InstallFile(m.installDirPath, installFileName, gensrc)
}
// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files
func (m *vintfDataRule) AndroidMkEntries() []AndroidMkEntries {
if m.noAction {
return []AndroidMkEntries{}
}
return []AndroidMkEntries{{
Class: "ETC",
OutputFile: OptionalPathForPath(m.outputFilePath),
}}
}