diff --git a/android/androidmk.go b/android/androidmk.go index fb3934f8a..704b5605a 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -230,9 +230,15 @@ func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.M if Bool(amod.commonProperties.Proprietary) { fmt.Fprintln(&data.preamble, "LOCAL_PROPRIETARY_MODULE := true") } - if Bool(amod.commonProperties.Vendor) { + if Bool(amod.commonProperties.Vendor) || Bool(amod.commonProperties.Soc_specific) { fmt.Fprintln(&data.preamble, "LOCAL_VENDOR_MODULE := true") } + if Bool(amod.commonProperties.Device_specific) { + fmt.Fprintln(&data.preamble, "LOCAL_ODM_MODULE := true") + } + if Bool(amod.commonProperties.Product_specific) { + fmt.Fprintln(&data.preamble, "LOCAL_OEM_MODULE := true") + } if amod.commonProperties.Owner != nil { fmt.Fprintln(&data.preamble, "LOCAL_MODULE_OWNER :=", *amod.commonProperties.Owner) } diff --git a/android/config.go b/android/config.go index dd0301e95..887291df5 100644 --- a/android/config.go +++ b/android/config.go @@ -661,6 +661,20 @@ func (c *deviceConfig) ExtraVndkVersions() []string { return c.config.ProductVariables.ExtraVndkVersions } +func (c *deviceConfig) OdmPath() string { + if c.config.ProductVariables.OdmPath != nil { + return *c.config.ProductVariables.OdmPath + } + return "odm" +} + +func (c *deviceConfig) OemPath() string { + if c.config.ProductVariables.OemPath != nil { + return *c.config.ProductVariables.OemPath + } + return "oem" +} + func (c *deviceConfig) BtConfigIncludeDir() string { return String(c.config.ProductVariables.BtConfigIncludeDir) } diff --git a/android/module.go b/android/module.go index 3d8f6838d..cb068abba 100644 --- a/android/module.go +++ b/android/module.go @@ -65,7 +65,10 @@ type androidBaseContext interface { Windows() bool Debug() bool PrimaryArch() bool - InstallOnVendorPartition() bool + Platform() bool + DeviceSpecific() bool + SocSpecific() bool + ProductSpecific() bool AConfig() Config DeviceConfig() DeviceConfig } @@ -212,9 +215,26 @@ type commonProperties struct { // vendor who owns this module Owner *string - // whether this module is device specific and should be installed into /vendor + // whether this module is specific to an SoC (System-On-a-Chip). When set to true, + // it is installed into /vendor (or /system/vendor if vendor partition does not exist). + // Use `soc_specific` instead for better meaning. Vendor *bool + // whether this module is specific to an SoC (System-On-a-Chip). When set to true, + // it is installed into /vendor (or /system/vendor if vendor partition does not exist). + Soc_specific *bool + + // whether this module is specific to a device, not only for SoC, but also for off-chip + // peripherals. When set to true, it is installed into /odm (or /vendor/odm if odm partition + // does not exist, or /system/vendor/odm if both odm and vendor partitions do not exist). + // This implies `soc_specific:true`. + Device_specific *bool + + // whether this module is specific to a software configuration of a product (e.g. country, + // network operator, etc). When set to true, it is installed into /oem (or /system/oem if + // oem partition does not exist). + Product_specific *bool + // init.rc files to be installed if this module is installed Init_rc []string @@ -264,6 +284,30 @@ const ( NeitherHostNorDeviceSupported ) +type moduleKind int + +const ( + platformModule moduleKind = iota + deviceSpecificModule + socSpecificModule + productSpecificModule +) + +func (k moduleKind) String() string { + switch k { + case platformModule: + return "platform" + case deviceSpecificModule: + return "device-specific" + case socSpecificModule: + return "soc-specific" + case productSpecificModule: + return "product-specific" + default: + panic(fmt.Errorf("unknown module kind %d", k)) + } +} + func InitAndroidModule(m Module) { base := m.base() base.module = m @@ -546,11 +590,48 @@ func (a *ModuleBase) generateModuleTarget(ctx ModuleContext) { } } +func determineModuleKind(a *ModuleBase, ctx blueprint.BaseModuleContext) moduleKind { + var socSpecific = Bool(a.commonProperties.Vendor) || Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Soc_specific) + var deviceSpecific = Bool(a.commonProperties.Device_specific) + var productSpecific = Bool(a.commonProperties.Product_specific) + + if ((socSpecific || deviceSpecific) && productSpecific) || (socSpecific && deviceSpecific) { + msg := "conflicting value set here" + if productSpecific { + ctx.PropertyErrorf("product_specific", "a module cannot be specific to SoC or device and product at the same time.") + if deviceSpecific { + ctx.PropertyErrorf("device_specific", msg) + } + } else { + ctx.PropertyErrorf("device_specific", "a module cannot be specific to SoC and device at the same time.") + } + if Bool(a.commonProperties.Vendor) { + ctx.PropertyErrorf("vendor", msg) + } + if Bool(a.commonProperties.Proprietary) { + ctx.PropertyErrorf("proprietary", msg) + } + if Bool(a.commonProperties.Soc_specific) { + ctx.PropertyErrorf("soc_specific", msg) + } + } + + if productSpecific { + return productSpecificModule + } else if deviceSpecific { + return deviceSpecificModule + } else if socSpecific { + return socSpecificModule + } else { + return platformModule + } +} + func (a *ModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl { return androidBaseContextImpl{ target: a.commonProperties.CompileTarget, targetPrimary: a.commonProperties.CompilePrimary, - vendor: Bool(a.commonProperties.Proprietary) || Bool(a.commonProperties.Vendor), + kind: determineModuleKind(a, ctx), config: ctx.Config().(Config), } } @@ -606,7 +687,7 @@ type androidBaseContextImpl struct { target Target targetPrimary bool debug bool - vendor bool + kind moduleKind config Config } @@ -867,8 +948,20 @@ func (a *androidBaseContextImpl) DeviceConfig() DeviceConfig { return DeviceConfig{a.config.deviceConfig} } -func (a *androidBaseContextImpl) InstallOnVendorPartition() bool { - return a.vendor +func (a *androidBaseContextImpl) Platform() bool { + return a.kind == platformModule +} + +func (a *androidBaseContextImpl) DeviceSpecific() bool { + return a.kind == deviceSpecificModule +} + +func (a *androidBaseContextImpl) SocSpecific() bool { + return a.kind == socSpecificModule +} + +func (a *androidBaseContextImpl) ProductSpecific() bool { + return a.kind == productSpecificModule } func (a *androidModuleContext) InstallInData() bool { diff --git a/android/paths.go b/android/paths.go index e47b9e4bb..4d9c85860 100644 --- a/android/paths.go +++ b/android/paths.go @@ -845,8 +845,12 @@ func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string var partition string if ctx.InstallInData() { partition = "data" - } else if ctx.InstallOnVendorPartition() { + } else if ctx.SocSpecific() { partition = ctx.DeviceConfig().VendorPath() + } else if ctx.DeviceSpecific() { + partition = ctx.DeviceConfig().OdmPath() + } else if ctx.ProductSpecific() { + partition = ctx.DeviceConfig().OemPath() } else { partition = "system" } diff --git a/android/paths_test.go b/android/paths_test.go index 1e4ba538c..110974f97 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -246,12 +246,34 @@ func TestPathForModuleInstall(t *testing.T) { ctx: &moduleInstallPathContextImpl{ androidBaseContextImpl: androidBaseContextImpl{ target: deviceTarget, - vendor: true, + kind: socSpecificModule, }, }, in: []string{"bin", "my_test"}, out: "target/product/test_device/vendor/bin/my_test", }, + { + name: "odm binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: deviceSpecificModule, + }, + }, + in: []string{"bin", "my_test"}, + out: "target/product/test_device/odm/bin/my_test", + }, + { + name: "oem binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: productSpecificModule, + }, + }, + in: []string{"bin", "my_test"}, + out: "target/product/test_device/oem/bin/my_test", + }, { name: "system native test binary", @@ -269,7 +291,31 @@ func TestPathForModuleInstall(t *testing.T) { ctx: &moduleInstallPathContextImpl{ androidBaseContextImpl: androidBaseContextImpl{ target: deviceTarget, - vendor: true, + kind: socSpecificModule, + }, + inData: true, + }, + in: []string{"nativetest", "my_test"}, + out: "target/product/test_device/data/nativetest/my_test", + }, + { + name: "odm native test binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: deviceSpecificModule, + }, + inData: true, + }, + in: []string{"nativetest", "my_test"}, + out: "target/product/test_device/data/nativetest/my_test", + }, + { + name: "oem native test binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: productSpecificModule, }, inData: true, }, @@ -293,13 +339,37 @@ func TestPathForModuleInstall(t *testing.T) { ctx: &moduleInstallPathContextImpl{ androidBaseContextImpl: androidBaseContextImpl{ target: deviceTarget, - vendor: true, + kind: socSpecificModule, }, inSanitizerDir: true, }, in: []string{"bin", "my_test"}, out: "target/product/test_device/data/asan/vendor/bin/my_test", }, + { + name: "sanitized odm binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: deviceSpecificModule, + }, + inSanitizerDir: true, + }, + in: []string{"bin", "my_test"}, + out: "target/product/test_device/data/asan/odm/bin/my_test", + }, + { + name: "sanitized oem binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: productSpecificModule, + }, + inSanitizerDir: true, + }, + in: []string{"bin", "my_test"}, + out: "target/product/test_device/data/asan/oem/bin/my_test", + }, { name: "sanitized system native test binary", @@ -318,7 +388,33 @@ func TestPathForModuleInstall(t *testing.T) { ctx: &moduleInstallPathContextImpl{ androidBaseContextImpl: androidBaseContextImpl{ target: deviceTarget, - vendor: true, + kind: socSpecificModule, + }, + inData: true, + inSanitizerDir: true, + }, + in: []string{"nativetest", "my_test"}, + out: "target/product/test_device/data/asan/data/nativetest/my_test", + }, + { + name: "sanitized odm native test binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: deviceSpecificModule, + }, + inData: true, + inSanitizerDir: true, + }, + in: []string{"nativetest", "my_test"}, + out: "target/product/test_device/data/asan/data/nativetest/my_test", + }, + { + name: "sanitized oem native test binary", + ctx: &moduleInstallPathContextImpl{ + androidBaseContextImpl: androidBaseContextImpl{ + target: deviceTarget, + kind: productSpecificModule, }, inData: true, inSanitizerDir: true, diff --git a/android/variable.go b/android/variable.go index 155eee56c..6962b0fcb 100644 --- a/android/variable.go +++ b/android/variable.go @@ -174,6 +174,8 @@ type productVariables struct { CFIIncludePaths *[]string `json:",omitempty"` VendorPath *string `json:",omitempty"` + OdmPath *string `json:",omitempty"` + OemPath *string `json:",omitempty"` ClangTidy *bool `json:",omitempty"` TidyChecks *string `json:",omitempty"` diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go index c6e90f00b..82b5eb954 100644 --- a/androidmk/cmd/androidmk/android.go +++ b/androidmk/cmd/androidmk/android.go @@ -152,6 +152,8 @@ func init() { "LOCAL_TIDY": "tidy", "LOCAL_PROPRIETARY_MODULE": "proprietary", "LOCAL_VENDOR_MODULE": "vendor", + "LOCAL_ODM_MODULE": "device_specific", + "LOCAL_OEM_MODULE": "product_specific", "LOCAL_EXPORT_PACKAGE_RESOURCES": "export_package_resources", "LOCAL_PRIVILEGED_MODULE": "privileged", diff --git a/cc/cc.go b/cc/cc.go index 04aa6a6e9..13d0e3b28 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -425,8 +425,9 @@ type moduleContext struct { moduleContextImpl } -func (ctx *moduleContext) InstallOnVendorPartition() bool { - return ctx.ModuleContext.InstallOnVendorPartition() || (ctx.mod.useVndk() && !ctx.mod.isVndk()) +func (ctx *moduleContext) SocSpecific() bool { + return ctx.ModuleContext.SocSpecific() || + (ctx.mod.hasVendorVariant() && ctx.mod.useVndk() && !ctx.mod.isVndk()) } type moduleContextImpl struct { @@ -1402,7 +1403,7 @@ func vendorMutator(mctx android.BottomUpMutatorContext) { mctx.CreateVariations(coreMode) } else if Bool(props.Vendor_available) { mctx.CreateVariations(coreMode, vendorMode) - } else if mctx.InstallOnVendorPartition() { + } else if mctx.SocSpecific() || mctx.DeviceSpecific() { mctx.CreateVariations(vendorMode) } else { mctx.CreateVariations(coreMode) @@ -1416,9 +1417,9 @@ func vendorMutator(mctx android.BottomUpMutatorContext) { } // Sanity check - if m.VendorProperties.Vendor_available != nil && mctx.InstallOnVendorPartition() { + if m.VendorProperties.Vendor_available != nil && (mctx.SocSpecific() || mctx.DeviceSpecific()) { mctx.PropertyErrorf("vendor_available", - "doesn't make sense at the same time as `vendor: true` or `proprietary: true`") + "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`") return } if vndk := m.vndkdep; vndk != nil { @@ -1460,8 +1461,8 @@ func vendorMutator(mctx android.BottomUpMutatorContext) { vendor := mod[1].(*Module) vendor.Properties.UseVndk = true squashVendorSrcs(vendor) - } else if mctx.InstallOnVendorPartition() && String(m.Properties.Sdk_version) == "" { - // This will be available in /vendor only + } else if (mctx.SocSpecific() || mctx.DeviceSpecific()) && String(m.Properties.Sdk_version) == "" { + // This will be available in /vendor (or /odm) only mod := mctx.CreateVariations(vendorMode) vendor := mod[0].(*Module) vendor.Properties.UseVndk = true