diff --git a/android/sdk.go b/android/sdk.go index 36afc3df2..e823106e8 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -351,6 +351,15 @@ type SdkMemberType interface { // values that differ by arch, fields not tagged as such must have common values across // all variants. // + // * Additional field tags can be specified on a field that will ignore certain values + // for the purpose of common value optimization. A value that is ignored must have the + // default value for the property type. This is to ensure that significant value are not + // ignored by accident. The purpose of this is to allow the snapshot generation to reflect + // the behavior of the runtime. e.g. if a property is ignored on the host then a property + // that is common for android can be treated as if it was common for android and host as + // the setting for host is ignored anyway. + // * `sdk:"ignored-on-host" - this indicates the property is ignored on the host variant. + // // * The sdk module type populates the BpModule structure, creating the arch specific // structure and calls AddToPropertySet(...) on the properties struct to add the member // specific properties in the correct place in the structure. diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 898ecea68..ae1a4923a 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -289,9 +289,12 @@ func TestCommonValueOptimization(t *testing.T) { } extractor := newCommonValueExtractor(common) - extractor.extractCommonProperties(common, structs) h := TestHelper{t} + + err := extractor.extractCommonProperties(common, structs) + h.AssertDeepEquals("unexpected error", nil, err) + h.AssertDeepEquals("common properties not correct", &testPropertiesStruct{ name: "common", diff --git a/sdk/update.go b/sdk/update.go index bcc2c778b..991428eec 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -1215,11 +1215,26 @@ func (s *sdk) getPossibleOsTypes() []android.OsType { // struct (or one of its embedded structs). type fieldAccessorFunc func(structValue reflect.Value) reflect.Value +// Checks the metadata to determine whether the property should be ignored for the +// purposes of common value extraction or not. +type extractorMetadataPredicate func(metadata propertiesContainer) bool + +// Indicates whether optimizable properties are provided by a host variant or +// not. +type isHostVariant interface { + isHostVariant() bool +} + // A property that can be optimized by the commonValueExtractor. type extractorProperty struct { // The name of the field for this property. name string + // Filter that can use metadata associated with the properties being optimized + // to determine whether the field should be ignored during common value + // optimization. + filter extractorMetadataPredicate + // Retrieves the value on which common value optimization will be performed. getter fieldAccessorFunc @@ -1273,6 +1288,20 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS continue } + var filter extractorMetadataPredicate + + // Add a filter + if proptools.HasTag(field, "sdk", "ignored-on-host") { + filter = func(metadata propertiesContainer) bool { + if m, ok := metadata.(isHostVariant); ok { + if m.isHostVariant() { + return false + } + } + return true + } + } + // Save a copy of the field index for use in the function. fieldIndex := f @@ -1304,6 +1333,7 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS } else { property := extractorProperty{ name, + filter, fieldGetter, reflect.Zero(field.Type), proptools.HasTag(field, "android", "arch_variant"), @@ -1372,6 +1402,12 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac for _, property := range e.properties { fieldGetter := property.getter + filter := property.filter + if filter == nil { + filter = func(metadata propertiesContainer) bool { + return true + } + } // Check to see if all the structures have the same value for the field. The commonValue // is nil on entry to the loop and if it is nil on exit then there is no common value or @@ -1389,6 +1425,15 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac itemValue := reflect.ValueOf(container.optimizableProperties()) fieldValue := fieldGetter(itemValue) + if !filter(container) { + expectedValue := property.emptyValue.Interface() + actualValue := fieldValue.Interface() + if !reflect.DeepEqual(expectedValue, actualValue) { + return fmt.Errorf("field %q is supposed to be ignored for %q but is set to %#v instead of %#v", property, container, actualValue, expectedValue) + } + continue + } + if commonValue == nil { // Use the first value as the commonProperties value. commonValue = &fieldValue