diff --git a/java/sdk_library.go b/java/sdk_library.go index 3d02c95b2..9f0564a9c 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -268,6 +268,10 @@ func (scope *apiScope) stubsSourceModuleName(baseName string) string { return baseName + ".stubs.source" + scope.moduleSuffix } +func (scope *apiScope) apiModuleName(baseName string) string { + return baseName + ".api" + scope.moduleSuffix +} + func (scope *apiScope) String() string { return scope.name } @@ -1078,6 +1082,21 @@ func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *sco return nil } +func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { + + // If a specific numeric version has been requested then use prebuilt versions of the sdk. + if !sdkVersion.ApiLevel.IsPreview() { + return PrebuiltJars(ctx, c.module.RootLibraryName(), sdkVersion) + } + + paths := c.selectScopePaths(ctx, sdkVersion.Kind) + if paths == nil { + return nil + } + + return paths.stubsHeaderPath +} + // selectScopePaths returns the *scopePaths appropriate for the specific kind. // // If the module does not support the specific kind then it will return the *scopePaths for the @@ -1244,6 +1263,12 @@ var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil) type SdkLibraryDependency interface { SdkLibraryComponentDependency + // Get the header jars appropriate for the supplied sdk_version. + // + // These are turbine generated jars so they only change if the externals of the + // class changes but it does not contain and implementation or JavaDoc. + SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths + // SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt // java_sdk_library_import module. It is needed by the hiddenapi processing tool which // processes dex files. @@ -2167,6 +2192,72 @@ func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { mctx.CreateModule(sdkLibraryXmlFactory, &props) } +func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths { + var ver android.ApiLevel + var kind android.SdkKind + if s.UsePrebuilt(ctx) { + ver = s.ApiLevel + kind = s.Kind + } else { + // We don't have prebuilt SDK for the specific sdkVersion. + // Instead of breaking the build, fallback to use "system_current" + ver = android.FutureApiLevel + kind = android.SdkSystem + } + + dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String()) + jar := filepath.Join(dir, baseName+".jar") + jarPath := android.ExistentPathForSource(ctx, jar) + if !jarPath.Valid() { + if ctx.Config().AllowMissingDependencies() { + return android.Paths{android.PathForSource(ctx, jar)} + } else { + ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar) + } + return nil + } + return android.Paths{jarPath.Path()} +} + +// Check to see if the other module is within the same set of named APEXes as this module. +// +// If either this or the other module are on the platform then this will return +// false. +func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool { + apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) + otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider) + return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants) +} + +func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { + // If the client doesn't set sdk_version, but if this library prefers stubs over + // the impl library, let's provide the widest API surface possible. To do so, + // force override sdk_version to module_current so that the closest possible API + // surface could be found in selectHeaderJarsForSdkVersion + if module.defaultsToStubs() && !sdkVersion.Specified() { + sdkVersion = android.SdkSpecFrom(ctx, "module_current") + } + + // Only provide access to the implementation library if it is actually built. + if module.requiresRuntimeImplementationLibrary() { + // Check any special cases for java_sdk_library. + // + // Only allow access to the implementation library in the following condition: + // * No sdk_version specified on the referencing module. + // * The referencing module is in the same apex as this. + if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) { + return module.implLibraryHeaderJars + } + } + + return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion) +} + +// to satisfy SdkLibraryDependency interface +func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { + return module.sdkJars(ctx, sdkVersion) +} + var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries") func javaSdkLibraries(config android.Config) *[]string { @@ -2285,6 +2376,10 @@ func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool { return !proptools.Bool(module.sdkLibraryProperties.Api_only) } +func (module *SdkLibrary) defaultsToStubs() bool { + return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs) +} + func moduleStubLinkType(j *Module) (stub bool, ret sdkLinkType) { kind := android.ToSdkKind(proptools.String(j.properties.Stub_contributing_api)) switch kind { @@ -2771,6 +2866,28 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo } } +func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths { + + // For consistency with SdkLibrary make the implementation jar available to libraries that + // are within the same APEX. + implLibraryModule := module.implLibraryModule + if implLibraryModule != nil && withinSameApexesAs(ctx, module) { + if headerJars { + return implLibraryModule.HeaderJars() + } else { + return implLibraryModule.ImplementationJars() + } + } + + return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion) +} + +// to satisfy SdkLibraryDependency interface +func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths { + // This module is just a wrapper for the prebuilt stubs. + return module.sdkJars(ctx, sdkVersion, true) +} + // to satisfy UsesLibraryDependency interface func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath { // The dex implementation jar extracted from the .apex file should be used in preference to the