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

Commit 01db2608 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "mark platform un-availability"

parents 47832975 89e850ab
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -198,6 +198,10 @@ func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod bluep
	a.AddStrings("LOCAL_HOST_REQUIRED_MODULES", a.Host_required...)
	a.AddStrings("LOCAL_TARGET_REQUIRED_MODULES", a.Target_required...)

	if am, ok := mod.(ApexModule); ok {
		a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
	}

	archStr := amod.Arch().ArchType.String()
	host := false
	switch amod.Os().Class {
+20 −0
Original line number Diff line number Diff line
@@ -101,6 +101,16 @@ type ApexModule interface {
	// Tests if this module is available for the specified APEX or ":platform"
	AvailableFor(what string) bool

	// Return true if this module is not available to platform (i.e. apex_available
	// property doesn't have "//apex_available:platform"), or shouldn't be available
	// to platform, which is the case when this module depends on other module that
	// isn't available to platform.
	NotAvailableForPlatform() bool

	// Mark that this module is not available to platform. Set by the
	// check-platform-availability mutator in the apex package.
	SetNotAvailableForPlatform()

	// Returns the highest version which is <= maxSdkVersion.
	// For example, with maxSdkVersion is 10 and versionList is [9,11]
	// it returns 9 as string
@@ -126,6 +136,8 @@ type ApexProperties struct {
	Apex_available []string

	Info ApexInfo `blueprint:"mutated"`

	NotAvailableForPlatform bool `blueprint:"mutated"`
}

// Marker interface that identifies dependencies that are excluded from APEX
@@ -215,6 +227,14 @@ func (m *ApexModuleBase) AvailableFor(what string) bool {
	return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
}

func (m *ApexModuleBase) NotAvailableForPlatform() bool {
	return m.ApexProperties.NotAvailableForPlatform
}

func (m *ApexModuleBase) SetNotAvailableForPlatform() {
	m.ApexProperties.NotAvailableForPlatform = true
}

func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
	// By default, if there is a dependency from A to B, we try to include both in the same APEX,
	// unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning true.
+55 −0
Original line number Diff line number Diff line
@@ -746,6 +746,7 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
	ctx.BottomUp("apex", apexMutator).Parallel()
	ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
	ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
	ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
}

// Mark the direct and transitive dependencies of apex bundles so that they
@@ -784,6 +785,60 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) {
	})
}

// mark if a module cannot be available to platform. A module cannot be available
// to platform if 1) it is explicitly marked as not available (i.e. "//apex_available:platform"
// is absent) or 2) it depends on another module that isn't (or can't be) available to platform
func markPlatformAvailability(mctx android.BottomUpMutatorContext) {
	// Host and recovery are not considered as platform
	if mctx.Host() || mctx.Module().InstallInRecovery() {
		return
	}

	if am, ok := mctx.Module().(android.ApexModule); ok {
		availableToPlatform := am.AvailableFor(android.AvailableToPlatform)

		// In a rare case when a lib is marked as available only to an apex
		// but the apex doesn't exist. This can happen in a partial manifest branch
		// like master-art. Currently, libstatssocket in the stats APEX is causing
		// this problem.
		// Include the lib in platform because the module SDK that ought to provide
		// it doesn't exist, so it would otherwise be left out completely.
		// TODO(b/154888298) remove this by adding those libraries in module SDKS and skipping
		// this check for libraries provided by SDKs.
		if !availableToPlatform && !android.InAnyApex(am.Name()) {
			availableToPlatform = true
		}

		// If any of the dep is not available to platform, this module is also considered
		// as being not available to platform even if it has "//apex_available:platform"
		mctx.VisitDirectDeps(func(child android.Module) {
			if !am.DepIsInSameApex(mctx, child) {
				// if the dependency crosses apex boundary, don't consider it
				return
			}
			if dep, ok := child.(android.ApexModule); ok && dep.NotAvailableForPlatform() {
				availableToPlatform = false
				// TODO(b/154889534) trigger an error when 'am' has "//apex_available:platform"
			}
		})

		// Exception 1: stub libraries and native bridge libraries are always available to platform
		if cc, ok := mctx.Module().(*cc.Module); ok &&
			(cc.IsStubs() || cc.Target().NativeBridge == android.NativeBridgeEnabled) {
			availableToPlatform = true
		}

		// Exception 2: bootstrap bionic libraries are also always available to platform
		if cc.InstallToBootstrap(mctx.ModuleName(), mctx.Config()) {
			availableToPlatform = true
		}

		if !availableToPlatform {
			am.SetNotAvailableForPlatform()
		}
	}
}

// If a module in an APEX depends on a module from an SDK then it needs an APEX
// specific variant created for it. Refer to sdk.sdkDepsReplaceMutator.
func inAnySdk(module android.Module) bool {
+50 −27
Original line number Diff line number Diff line
@@ -3750,22 +3750,12 @@ func TestApexAvailable_InvalidApexName(t *testing.T) {
	}`)
}

func TestApexAvailable_CreatedForPlatform(t *testing.T) {
	// check that libfoo and libbar are created only for myapex, but not for the platform
	// TODO(jiyong) the checks for the platform variant are removed because we now create
	// the platform variant regardless of the apex_availability. Instead, we will make sure that
	// the platform variants are not used from other platform modules. When that is done,
	// these checks will be replaced by expecting a specific error message that will be
	// emitted when the platform variant is used.
	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
	//	ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")

func TestApexAvailable_CheckForPlatform(t *testing.T) {
	ctx, _ := testApex(t, `
	apex {
		name: "myapex",
		key: "myapex.key",
		native_shared_libs: ["libbar", "libbaz"],
	}

	apex_key {
@@ -3778,16 +3768,52 @@ func TestApexAvailable_CreatedForPlatform(t *testing.T) {
		name: "libfoo",
		stl: "none",
		system_shared_libs: [],
		shared_libs: ["libbar"],
		apex_available: ["//apex_available:platform"],
	}

	cc_library {
		name: "libfoo2",
		stl: "none",
		system_shared_libs: [],
		shared_libs: ["libbaz"],
		apex_available: ["//apex_available:platform"],
	}

	cc_library {
		name: "libbar",
		stl: "none",
		system_shared_libs: [],
		apex_available: ["myapex"],
	}

	cc_library {
		name: "libbaz",
		stl: "none",
		system_shared_libs: [],
		apex_available: ["myapex"],
		stubs: {
			versions: ["1"],
		},
	}`)

	// check that libfoo is created only for the platform
	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
	// libfoo shouldn't be available to platform even though it has "//apex_available:platform",
	// because it depends on libbar which isn't available to platform
	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
	if libfoo.NotAvailableForPlatform() != true {
		t.Errorf("%q shouldn't be available to platform", libfoo.String())
	}

	// libfoo2 however can be available to platform because it depends on libbaz which provides
	// stubs
	libfoo2 := ctx.ModuleForTests("libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
	if libfoo2.NotAvailableForPlatform() == true {
		t.Errorf("%q should be available to platform", libfoo2.String())
	}
}

func TestApexAvailable_CreatedForApex(t *testing.T) {
	testApex(t, `
	ctx, _ := testApex(t, `
	apex {
		name: "myapex",
		key: "myapex.key",
@@ -3810,17 +3836,14 @@ func TestApexAvailable_CreatedForApex(t *testing.T) {
		},
	}`)

	// shared variant of libfoo is only available to myapex
	// TODO(jiyong) the checks for the platform variant are removed because we now create
	// the platform variant regardless of the apex_availability. Instead, we will make sure that
	// the platform variants are not used from other platform modules. When that is done,
	// these checks will be replaced by expecting a specific error message that will be
	// emitted when the platform variant is used.
	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
	//	// but the static variant is available to both myapex and the platform
	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
	libfooShared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
	if libfooShared.NotAvailableForPlatform() != true {
		t.Errorf("%q shouldn't be available to platform", libfooShared.String())
	}
	libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
	if libfooStatic.NotAvailableForPlatform() != false {
		t.Errorf("%q should be available to platform", libfooStatic.String())
	}
}

func TestOverrideApex(t *testing.T) {