1// Copyright 2024 Google Inc. All rights reserved. 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 android 16 17import ( 18 "fmt" 19 "strings" 20 21 "github.com/google/blueprint/proptools" 22) 23 24const ( 25 deviceCmType = "device_cm" 26 systemManifestType = "system_manifest" 27 productManifestType = "product_manifest" 28 systemExtManifestType = "system_ext_manifest" 29 vendorManifestType = "vendor_manifest" 30 odmManifestType = "odm_manifest" 31 32 defaultDcm = "system/libhidl/vintfdata/device_compatibility_matrix.default.xml" 33 defaultSystemManifest = "system/libhidl/vintfdata/manifest.xml" 34 defaultSystemExtManifest = "system/libhidl/vintfdata/system_ext_manifest.default.xml" 35) 36 37type vintfDataProperties struct { 38 // Optional name for the installed file. If unspecified it will be manifest.xml by default. 39 Filename *string 40 41 // Type of the vintf data type, the allowed type are device_compatibility_matrix, system_manifest, 42 // product_manifest, and system_ext_manifest. 43 Type *string 44} 45 46type vintfDataRule struct { 47 ModuleBase 48 49 properties vintfDataProperties 50 51 installDirPath InstallPath 52 outputFilePath Path 53 noAction bool 54} 55 56func init() { 57 registerVintfDataComponents(InitRegistrationContext) 58} 59 60func registerVintfDataComponents(ctx RegistrationContext) { 61 ctx.RegisterModuleType("vintf_data", vintfDataFactory) 62} 63 64// vintf_fragment module processes vintf fragment file and installs under etc/vintf/manifest. 65func vintfDataFactory() Module { 66 m := &vintfDataRule{} 67 m.AddProperties( 68 &m.properties, 69 ) 70 InitAndroidArchModule(m, DeviceSupported, MultilibFirst) 71 72 return m 73} 74 75func (m *vintfDataRule) GenerateAndroidBuildActions(ctx ModuleContext) { 76 builder := NewRuleBuilder(pctx, ctx) 77 gensrc := PathForModuleOut(ctx, "manifest.xml") 78 assembleVintfEnvs := []string{} 79 inputPaths := make(Paths, 0) 80 81 switch proptools.String(m.properties.Type) { 82 case deviceCmType: 83 assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SYSTEMSDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().SystemSdkVersions(), " "))) 84 85 deviceMatrixs := PathsForSource(ctx, ctx.Config().DeviceMatrixFile()) 86 if len(deviceMatrixs) > 0 { 87 inputPaths = append(inputPaths, deviceMatrixs...) 88 } else { 89 inputPaths = append(inputPaths, PathForSource(ctx, defaultDcm)) 90 } 91 case systemManifestType: 92 assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PLATFORM_SYSTEMSDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().PlatformSystemSdkVersions(), " "))) 93 94 inputPaths = append(inputPaths, PathForSource(ctx, defaultSystemManifest)) 95 systemManifestFiles := PathsForSource(ctx, ctx.Config().SystemManifestFile()) 96 if len(systemManifestFiles) > 0 { 97 inputPaths = append(inputPaths, systemManifestFiles...) 98 } 99 case productManifestType: 100 productManifestFiles := PathsForSource(ctx, ctx.Config().ProductManifestFiles()) 101 // Only need to generate the manifest if PRODUCT_MANIFEST_FILES not defined. 102 if len(productManifestFiles) == 0 { 103 m.noAction = true 104 return 105 } 106 107 inputPaths = append(inputPaths, productManifestFiles...) 108 case systemExtManifestType: 109 assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PROVIDED_VNDK_VERSIONS=\"%s\"", strings.Join(ctx.DeviceConfig().ExtraVndkVersions(), " "))) 110 111 inputPaths = append(inputPaths, PathForSource(ctx, defaultSystemExtManifest)) 112 systemExtManifestFiles := PathsForSource(ctx, ctx.Config().SystemExtManifestFiles()) 113 if len(systemExtManifestFiles) > 0 { 114 inputPaths = append(inputPaths, systemExtManifestFiles...) 115 } 116 case vendorManifestType: 117 assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SEPOLICY_VERS=\"%s\"", ctx.DeviceConfig().BoardSepolicyVers())) 118 assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PRODUCT_ENFORCE_VINTF_MANIFEST=%t", *ctx.Config().productVariables.Enforce_vintf_manifest)) 119 deviceManifestFiles := PathsForSource(ctx, ctx.Config().DeviceManifestFiles()) 120 // Only need to generate the manifest if DEVICE_MANIFEST_FILE is defined. 121 if len(deviceManifestFiles) == 0 { 122 m.noAction = true 123 return 124 } 125 126 inputPaths = append(inputPaths, deviceManifestFiles...) 127 case odmManifestType: 128 assembleVintfEnvs = append(assembleVintfEnvs, "VINTF_IGNORE_TARGET_FCM_VERSION=true") 129 odmManifestFiles := PathsForSource(ctx, ctx.Config().OdmManifestFiles()) 130 // Only need to generate the manifest if ODM_MANIFEST_FILES is defined. 131 if len(odmManifestFiles) == 0 { 132 m.noAction = true 133 return 134 } 135 136 inputPaths = append(inputPaths, odmManifestFiles...) 137 default: 138 panic(fmt.Errorf("For %s: The attribute 'type' value only allowed device_cm, system_manifest, product_manifest, system_ext_manifest!", ctx.Module().Name())) 139 } 140 141 // Process vintf fragment source file with assemble_vintf tool 142 builder.Command(). 143 Flags(assembleVintfEnvs). 144 BuiltTool("assemble_vintf"). 145 FlagWithArg("-i ", strings.Join(inputPaths.Strings(), ":")). 146 FlagWithOutput("-o ", gensrc) 147 148 builder.Build("assemble_vintf", "Process vintf data "+gensrc.String()) 149 150 m.installDirPath = PathForModuleInstall(ctx, "etc", "vintf") 151 m.outputFilePath = gensrc 152 153 installFileName := "manifest.xml" 154 if filename := proptools.String(m.properties.Filename); filename != "" { 155 installFileName = filename 156 } 157 158 ctx.InstallFile(m.installDirPath, installFileName, gensrc) 159} 160 161// Make this module visible to AndroidMK so it can be referenced from modules defined from Android.mk files 162func (m *vintfDataRule) AndroidMkEntries() []AndroidMkEntries { 163 if m.noAction { 164 return []AndroidMkEntries{} 165 } 166 167 return []AndroidMkEntries{{ 168 Class: "ETC", 169 OutputFile: OptionalPathForPath(m.outputFilePath), 170 }} 171} 172