Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f34f6d85 authored by Paul Duffin's avatar Paul Duffin
Browse files

Encapsulate properties to be optimized in a container

This allows additional metadata to be associated with a set of
properties that will be used in a follow up change to filter
properties that are ignored in some variants (e.g. host variants).

Bug: 155628860
Test: m nothing
Change-Id: Ie83c1ffbb71fd5d7a08d350571dad3e3209b1431
parent e051d0d3
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -242,9 +242,13 @@ type testPropertiesStruct struct {
	EmbeddedPropertiesStruct
}

func (p *testPropertiesStruct) optimizableProperties() interface{} {
	return p
}

func TestCommonValueOptimization(t *testing.T) {
	common := &testPropertiesStruct{}
	structs := []*testPropertiesStruct{
	structs := []propertiesContainer{
		&testPropertiesStruct{
			private:     "common",
			Public_Kept: "common",
+41 −20
Original line number Diff line number Diff line
@@ -301,18 +301,18 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro

	addHostDeviceSupportedProperties(s.ModuleBase.DeviceSupported(), s.ModuleBase.HostSupported(), snapshotModule)

	var dynamicMemberPropertiesList []interface{}
	var dynamicMemberPropertiesContainers []propertiesContainer
	osTypeToMemberProperties := make(map[android.OsType]*sdk)
	for _, sdkVariant := range sdkVariants {
		properties := sdkVariant.dynamicMemberTypeListProperties
		osTypeToMemberProperties[sdkVariant.Target().Os] = sdkVariant
		dynamicMemberPropertiesList = append(dynamicMemberPropertiesList, properties)
		dynamicMemberPropertiesContainers = append(dynamicMemberPropertiesContainers, &dynamicMemberPropertiesContainer{properties})
	}

	// Extract the common lists of members into a separate struct.
	commonDynamicMemberProperties := s.dynamicSdkMemberTypes.createMemberListProperties()
	extractor := newCommonValueExtractor(commonDynamicMemberProperties)
	extractor.extractCommonProperties(commonDynamicMemberProperties, dynamicMemberPropertiesList)
	extractor.extractCommonProperties(commonDynamicMemberProperties, dynamicMemberPropertiesContainers)

	// Add properties common to all os types.
	s.addMemberPropertiesToPropertySet(builder, snapshotModule, commonDynamicMemberProperties)
@@ -814,6 +814,10 @@ type baseInfo struct {
	Properties android.SdkMemberProperties
}

func (b *baseInfo) optimizableProperties() interface{} {
	return b.Properties
}

type osTypeSpecificInfo struct {
	baseInfo

@@ -889,17 +893,14 @@ func (osInfo *osTypeSpecificInfo) optimizeProperties(commonValueExtractor *commo
	}

	multilib := multilibNone
	var archPropertiesList []android.SdkMemberProperties
	for _, archInfo := range osInfo.archInfos {
		multilib = multilib.addArchType(archInfo.archType)

		// Optimize the arch properties first.
		archInfo.optimizeProperties(commonValueExtractor)

		archPropertiesList = append(archPropertiesList, archInfo.Properties)
	}

	commonValueExtractor.extractCommonProperties(osInfo.Properties, archPropertiesList)
	commonValueExtractor.extractCommonProperties(osInfo.Properties, osInfo.archInfos)

	// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
	osInfo.Properties.Base().Compile_multilib = multilib.String()
@@ -1011,6 +1012,10 @@ func newArchSpecificInfo(ctx android.SdkMemberContext, archType android.ArchType
	return archInfo
}

func (archInfo *archTypeSpecificInfo) optimizableProperties() interface{} {
	return archInfo.Properties
}

// Get the link type of the variant
//
// If the variant is not differentiated by link type then it returns "",
@@ -1038,12 +1043,7 @@ func (archInfo *archTypeSpecificInfo) optimizeProperties(commonValueExtractor *c
		return
	}

	var propertiesList []android.SdkMemberProperties
	for _, linkInfo := range archInfo.linkInfos {
		propertiesList = append(propertiesList, linkInfo.Properties)
	}

	commonValueExtractor.extractCommonProperties(archInfo.Properties, propertiesList)
	commonValueExtractor.extractCommonProperties(archInfo.Properties, archInfo.linkInfos)
}

// Add the properties for an arch type to a property set.
@@ -1133,21 +1133,21 @@ func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModu

	// The list of property structures which are os type specific but common across
	// architectures within that os type.
	var osSpecificPropertiesList []android.SdkMemberProperties
	var osSpecificPropertiesContainers []*osTypeSpecificInfo

	for osType, osTypeVariants := range variantsByOsType {
		osInfo := newOsTypeSpecificInfo(ctx, osType, variantPropertiesFactory, osTypeVariants)
		osTypeToInfo[osType] = osInfo
		// Add the os specific properties to a list of os type specific yet architecture
		// independent properties structs.
		osSpecificPropertiesList = append(osSpecificPropertiesList, osInfo.Properties)
		osSpecificPropertiesContainers = append(osSpecificPropertiesContainers, osInfo)

		// Optimize the properties across all the variants for a specific os type.
		osInfo.optimizeProperties(commonValueExtractor)
	}

	// Extract properties which are common across all architectures and os types.
	commonValueExtractor.extractCommonProperties(commonProperties, osSpecificPropertiesList)
	commonValueExtractor.extractCommonProperties(commonProperties, osSpecificPropertiesContainers)

	// Add the common properties to the module.
	commonProperties.AddToPropertySet(ctx, bpModule)
@@ -1270,11 +1270,29 @@ foundStruct:
	return value
}

// A container of properties to be optimized.
//
// Allows additional information to be associated with the properties, e.g. for
// filtering.
type propertiesContainer interface {
	// Get the properties that need optimizing.
	optimizableProperties() interface{}
}

// A wrapper for dynamic member properties to allow them to be optimized.
type dynamicMemberPropertiesContainer struct {
	dynamicMemberProperties interface{}
}

func (c dynamicMemberPropertiesContainer) optimizableProperties() interface{} {
	return c.dynamicMemberProperties
}

// Extract common properties from a slice of property structures of the same type.
//
// All the property structures must be of the same type.
// commonProperties - must be a pointer to the structure into which common properties will be added.
// inputPropertiesSlice - must be a slice of input properties structures.
// inputPropertiesSlice - must be a slice of propertiesContainer interfaces.
//
// Iterates over each exported field (capitalized name) and checks to see whether they
// have the same value (using DeepEquals) across all the input properties. If it does not then no
@@ -1284,15 +1302,17 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac
	commonPropertiesValue := reflect.ValueOf(commonProperties)
	commonStructValue := commonPropertiesValue.Elem()

	sliceValue := reflect.ValueOf(inputPropertiesSlice)

	for _, fieldGetter := range e.fieldGetters {
		// 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,
		// otherwise it points to the common value.
		var commonValue *reflect.Value
		sliceValue := reflect.ValueOf(inputPropertiesSlice)

		for i := 0; i < sliceValue.Len(); i++ {
			itemValue := sliceValue.Index(i)
			container := sliceValue.Index(i).Interface().(propertiesContainer)
			itemValue := reflect.ValueOf(container.optimizableProperties())
			fieldValue := fieldGetter(itemValue)

			if commonValue == nil {
@@ -1314,7 +1334,8 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac
			emptyValue := reflect.Zero(commonValue.Type())
			fieldGetter(commonStructValue).Set(*commonValue)
			for i := 0; i < sliceValue.Len(); i++ {
				itemValue := sliceValue.Index(i)
				container := sliceValue.Index(i).Interface().(propertiesContainer)
				itemValue := reflect.ValueOf(container.optimizableProperties())
				fieldValue := fieldGetter(itemValue)
				fieldValue.Set(emptyValue)
			}