|  | // Copyright 2024 Google Inc. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | package java | 
|  |  | 
|  | import ( | 
|  | "android/soong/android" | 
|  | "android/soong/etc" | 
|  | "fmt" | 
|  | "path" | 
|  | "strings" | 
|  |  | 
|  | "github.com/google/blueprint/proptools" | 
|  | ) | 
|  |  | 
|  | // --------------------------------------------------------------------------------------------- | 
|  | // Naming scheme of the submodules generated by java_sdk_library and java_sdk_library_import | 
|  | // --------------------------------------------------------------------------------------------- | 
|  |  | 
|  | const ( | 
|  | sdkXmlFileSuffix = ".xml" | 
|  | implLibSuffix    = ".impl" | 
|  | ) | 
|  |  | 
|  | func implLibraryModuleName(sdkLibName string) string { | 
|  | return sdkLibName + implLibSuffix | 
|  | } | 
|  |  | 
|  | // Module name of the runtime implementation library | 
|  | func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string { | 
|  | return implLibraryModuleName(c.module.RootLibraryName()) | 
|  | } | 
|  |  | 
|  | // Module name of the XML file for the lib | 
|  | func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string { | 
|  | return c.module.RootLibraryName() + sdkXmlFileSuffix | 
|  | } | 
|  |  | 
|  | // Name of the java_library module that compiles the stubs source. | 
|  | func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string { | 
|  | baseName := c.module.RootLibraryName() | 
|  | return apiScope.stubsLibraryModuleName(baseName) | 
|  | } | 
|  |  | 
|  | // Name of the java_library module that compiles the exportable stubs source. | 
|  | func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string { | 
|  | baseName := c.module.RootLibraryName() | 
|  | return apiScope.exportableStubsLibraryModuleName(baseName) | 
|  | } | 
|  |  | 
|  | // Name of the droidstubs module that generates the stubs source and may also | 
|  | // generate/check the API. | 
|  | func (c *commonToSdkLibraryAndImport) droidstubsModuleName(apiScope *apiScope) string { | 
|  | baseName := c.module.RootLibraryName() | 
|  | return apiScope.stubsSourceModuleName(baseName) | 
|  | } | 
|  |  | 
|  | // Name of the java_api_library module that generates the from-text stubs source | 
|  | // and compiles to a jar file. | 
|  | func (c *commonToSdkLibraryAndImport) fromTextStubsLibraryModuleName(apiScope *apiScope) string { | 
|  | baseName := c.module.RootLibraryName() | 
|  | return apiScope.apiLibraryModuleName(baseName) | 
|  | } | 
|  |  | 
|  | // Name of the java_library module that compiles the stubs | 
|  | // generated from source Java files. | 
|  | func (c *commonToSdkLibraryAndImport) fromSourceStubsLibraryModuleName(apiScope *apiScope) string { | 
|  | baseName := c.module.RootLibraryName() | 
|  | return apiScope.sourceStubsLibraryModuleName(baseName) | 
|  | } | 
|  |  | 
|  | // Name of the java_library module that compiles the exportable stubs | 
|  | // generated from source Java files. | 
|  | func (c *commonToSdkLibraryAndImport) exportableFromSourceStubsLibraryModuleName(apiScope *apiScope) string { | 
|  | baseName := c.module.RootLibraryName() | 
|  | return apiScope.exportableSourceStubsLibraryModuleName(baseName) | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------------------------- | 
|  | // Build rules of the submodules generated by java_sdk_library. | 
|  | // java_sdk_library "framework-foo" generates the following submodules: | 
|  | // | 
|  | // - "framework-foo.impl" (type: [Library]): the implementation library, which generates the | 
|  | //		compilation outputs that include the implementation details and the private apis | 
|  | //		(i.e. class/methods that are annotated @hide). | 
|  | // | 
|  | // - "framework-foo.stubs.source.<[apiScope.name]>" (type: [Droidstubs]): droidstubs module that | 
|  | //		generates the stubs and the api files for the given api scope. | 
|  | // | 
|  | // - "framework-foo.stubs.<[apiScope.name]>" (type: [Library]): stub library module that | 
|  | //		provides the compilation output of the stubs to the reverse dependencies. The module | 
|  | //		itself does not perform any compilation actions; the module statically depends on one of | 
|  | //		the from-source stub module or the from-text stub configuration based on the build | 
|  | // 		configuration. | 
|  | // | 
|  | // - "framework-foo.stubs.<[apiScope.name]>.from-source" (type: [Library]): stub library module | 
|  | //		that compiles the stubs generated by the droidstubs submodule. This module is a static | 
|  | //		dependency of the stub library module when | 
|  | //		[android/soong/android/config.BuildFromTextStub()] is false. | 
|  | // | 
|  | // - "framework-foo.stubs.<[apiScope.name]>.from-text" (type: [ApiLibrary]): api library module | 
|  | //		that generates and compiles the stubs from the api files checked in the tree instead of | 
|  | //		the source Java files (e.g. *-current.txt files). This module is a static dependency of | 
|  | //		the stub library module when [android/soong/android/config.BuildFromTextStub()] is true. | 
|  | // | 
|  | // - "framework-foo.stubs.exportable.<[apiScope.name]>" (type: [Library]): stub library module | 
|  | //		that provides the "exportable" stubs. "exportable" stubs are the stubs that do not | 
|  | //		include in-development flagged apis. This module is only used for SDK builds to generate | 
|  | //		the SDK artifacts, and not purposed for consumption for other modules. | 
|  | // | 
|  | // - "framework-foo.stubs.exportable.<[apiScope.name]>.from-source" (type: [Library]): stub | 
|  | //		library module that compiles the "exportable" stubs generated by the droidstubs | 
|  | //		submodule. This module is always a static dependency of the "exportable" stub library | 
|  | //		module given that from-text stubs cannot be used for SDK builds as it does not contain | 
|  | //		documentations. | 
|  | // | 
|  | // - "framework-foo.xml" (type: [sdkLibraryXml]): xml library that generates the permission xml | 
|  | //		file, which allows [SdkLibrary] to be used with <uses-permission> tag in the | 
|  | //		AndroidManifest.xml files. | 
|  | // --------------------------------------------------------------------------------------------- | 
|  |  | 
|  | // Creates the implementation [Library] with ".impl" suffix. | 
|  | func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) { | 
|  | visibility := childModuleVisibility(module.sdkLibraryProperties.Impl_library_visibility) | 
|  |  | 
|  | staticLibs := module.properties.Static_libs.Clone() | 
|  | staticLibs.AppendSimpleValue(module.sdkLibraryProperties.Impl_only_static_libs) | 
|  | props := struct { | 
|  | Name           *string | 
|  | Enabled        proptools.Configurable[bool] | 
|  | Visibility     []string | 
|  | Libs           []string | 
|  | Static_libs    proptools.Configurable[[]string] | 
|  | Apex_available []string | 
|  | Stem           *string | 
|  | }{ | 
|  | Name:       proptools.StringPtr(module.implLibraryModuleName()), | 
|  | Enabled:    module.EnabledProperty(), | 
|  | Visibility: visibility, | 
|  |  | 
|  | Libs: append(module.properties.Libs, module.sdkLibraryProperties.Impl_only_libs...), | 
|  |  | 
|  | Static_libs: staticLibs, | 
|  | // Pass the apex_available settings down so that the impl library can be statically | 
|  | // embedded within a library that is added to an APEX. Needed for updatable-media. | 
|  | Apex_available: module.ApexAvailable(), | 
|  |  | 
|  | Stem: proptools.StringPtr(module.Name()), | 
|  | } | 
|  |  | 
|  | properties := []interface{}{ | 
|  | &module.properties, | 
|  | &module.protoProperties, | 
|  | &module.deviceProperties, | 
|  | &module.dexProperties, | 
|  | &module.dexpreoptProperties, | 
|  | &module.linter.properties, | 
|  | &module.overridableProperties, | 
|  | &props, | 
|  | module.sdkComponentPropertiesForChildLibrary(), | 
|  | } | 
|  | mctx.CreateModule(LibraryFactory, properties...) | 
|  | } | 
|  |  | 
|  | // Creates the [Droidstubs] module with ".stubs.source.<[apiScope.name]>" that creates stubs | 
|  | // source files from the given full source files and also updates and checks the API | 
|  | // specification files (i.e. "*-current.txt", "*-removed.txt" files). | 
|  | func (module *SdkLibrary) createDroidstubs(mctx android.DefaultableHookContext, apiScope *apiScope, name string, scopeSpecificDroidstubsArgs []string) { | 
|  | props := struct { | 
|  | Name                             *string | 
|  | Enabled                          proptools.Configurable[bool] | 
|  | Visibility                       []string | 
|  | Srcs                             []string | 
|  | Installable                      *bool | 
|  | Sdk_version                      *string | 
|  | Api_surface                      *string | 
|  | System_modules                   *string | 
|  | Libs                             proptools.Configurable[[]string] | 
|  | Output_javadoc_comments          *bool | 
|  | Arg_files                        []string | 
|  | Args                             *string | 
|  | Java_version                     *string | 
|  | Annotations_enabled              *bool | 
|  | Merge_annotations_dirs           []string | 
|  | Merge_inclusion_annotations_dirs []string | 
|  | Generate_stubs                   *bool | 
|  | Previous_api                     *string | 
|  | Aconfig_declarations             []string | 
|  | Check_api                        struct { | 
|  | Current       ApiToCheck | 
|  | Last_released ApiToCheck | 
|  |  | 
|  | Api_lint struct { | 
|  | Enabled       *bool | 
|  | New_since     *string | 
|  | Baseline_file *string | 
|  | } | 
|  | } | 
|  | Aidl struct { | 
|  | Include_dirs       []string | 
|  | Local_include_dirs []string | 
|  | } | 
|  | Dists []android.Dist | 
|  | }{} | 
|  |  | 
|  | // The stubs source processing uses the same compile time classpath when extracting the | 
|  | // API from the implementation library as it does when compiling it. i.e. the same | 
|  | // * sdk version | 
|  | // * system_modules | 
|  | // * libs (static_libs/libs) | 
|  |  | 
|  | props.Name = proptools.StringPtr(name) | 
|  | props.Enabled = module.EnabledProperty() | 
|  | props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility) | 
|  | props.Srcs = append(props.Srcs, module.properties.Srcs...) | 
|  | props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...) | 
|  | props.Sdk_version = module.deviceProperties.Sdk_version | 
|  | props.Api_surface = &apiScope.name | 
|  | props.System_modules = module.deviceProperties.System_modules | 
|  | props.Installable = proptools.BoolPtr(false) | 
|  | // A droiddoc module has only one Libs property and doesn't distinguish between | 
|  | // shared libs and static libs. So we need to add both of these libs to Libs property. | 
|  | props.Libs = proptools.NewConfigurable[[]string](nil, nil) | 
|  | props.Libs.AppendSimpleValue(module.properties.Libs) | 
|  | props.Libs.Append(module.properties.Static_libs) | 
|  | props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs) | 
|  | props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs) | 
|  | props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs | 
|  | props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs | 
|  | props.Java_version = module.properties.Java_version | 
|  |  | 
|  | props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled | 
|  | props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs | 
|  | props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs | 
|  | props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations | 
|  |  | 
|  | droidstubsArgs := []string{} | 
|  | if len(module.sdkLibraryProperties.Api_packages) != 0 { | 
|  | droidstubsArgs = append(droidstubsArgs, "--stub-packages "+strings.Join(module.sdkLibraryProperties.Api_packages, ":")) | 
|  | } | 
|  | droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...) | 
|  | disabledWarnings := []string{"HiddenSuperclass"} | 
|  | if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) { | 
|  | disabledWarnings = append(disabledWarnings, | 
|  | "BroadcastBehavior", | 
|  | "DeprecationMismatch", | 
|  | "MissingPermission", | 
|  | "SdkConstant", | 
|  | "Todo", | 
|  | ) | 
|  | } | 
|  | droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide ")) | 
|  |  | 
|  | // Output Javadoc comments for public scope. | 
|  | if apiScope == apiScopePublic { | 
|  | props.Output_javadoc_comments = proptools.BoolPtr(true) | 
|  | } | 
|  |  | 
|  | // Add in scope specific arguments. | 
|  | droidstubsArgs = append(droidstubsArgs, scopeSpecificDroidstubsArgs...) | 
|  | props.Arg_files = module.sdkLibraryProperties.Droiddoc_option_files | 
|  | props.Args = proptools.StringPtr(strings.Join(droidstubsArgs, " ")) | 
|  |  | 
|  | // List of APIs identified from the provided source files are created. They are later | 
|  | // compared against to the not-yet-released (a.k.a current) list of APIs and to the | 
|  | // last-released (a.k.a numbered) list of API. | 
|  | currentApiFileName := apiScope.apiFilePrefix + "current.txt" | 
|  | removedApiFileName := apiScope.apiFilePrefix + "removed.txt" | 
|  | apiDir := module.getApiDir() | 
|  | currentApiFileName = path.Join(apiDir, currentApiFileName) | 
|  | removedApiFileName = path.Join(apiDir, removedApiFileName) | 
|  |  | 
|  | // check against the not-yet-release API | 
|  | props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName) | 
|  | props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName) | 
|  |  | 
|  | if module.compareAgainstLatestApi(apiScope) { | 
|  | // check against the latest released API | 
|  | latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) | 
|  | props.Previous_api = latestApiFilegroupName | 
|  | props.Check_api.Last_released.Api_file = latestApiFilegroupName | 
|  | props.Check_api.Last_released.Removed_api_file = proptools.StringPtr( | 
|  | module.latestRemovedApiFilegroupName(apiScope)) | 
|  | props.Check_api.Last_released.Baseline_file = proptools.StringPtr( | 
|  | module.latestIncompatibilitiesFilegroupName(apiScope)) | 
|  |  | 
|  | if proptools.Bool(module.sdkLibraryProperties.Api_lint.Enabled) { | 
|  | // Enable api lint. | 
|  | props.Check_api.Api_lint.Enabled = proptools.BoolPtr(true) | 
|  | props.Check_api.Api_lint.New_since = latestApiFilegroupName | 
|  |  | 
|  | // If it exists then pass a lint-baseline.txt through to droidstubs. | 
|  | baselinePath := path.Join(apiDir, apiScope.apiFilePrefix+"lint-baseline.txt") | 
|  | baselinePathRelativeToRoot := path.Join(mctx.ModuleDir(), baselinePath) | 
|  | paths, err := mctx.GlobWithDeps(baselinePathRelativeToRoot, nil) | 
|  | if err != nil { | 
|  | mctx.ModuleErrorf("error checking for presence of %s: %s", baselinePathRelativeToRoot, err) | 
|  | } | 
|  | if len(paths) == 1 { | 
|  | props.Check_api.Api_lint.Baseline_file = proptools.StringPtr(baselinePath) | 
|  | } else if len(paths) != 0 { | 
|  | mctx.ModuleErrorf("error checking for presence of %s: expected one path, found: %v", baselinePathRelativeToRoot, paths) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if !Bool(module.sdkLibraryProperties.No_dist) { | 
|  | // Dist the api txt and removed api txt artifacts for sdk builds. | 
|  | distDir := proptools.StringPtr(path.Join(module.apiDistPath(apiScope), "api")) | 
|  | stubsTypeTagPrefix := "" | 
|  | if mctx.Config().ReleaseHiddenApiExportableStubs() { | 
|  | stubsTypeTagPrefix = ".exportable" | 
|  | } | 
|  | for _, p := range []struct { | 
|  | tag     string | 
|  | pattern string | 
|  | }{ | 
|  | // "exportable" api files are copied to the dist directory instead of the | 
|  | // "everything" api files when "RELEASE_HIDDEN_API_EXPORTABLE_STUBS" build flag | 
|  | // is set. Otherwise, the "everything" api files are copied to the dist directory. | 
|  | {tag: "%s.api.txt", pattern: "%s.txt"}, | 
|  | {tag: "%s.removed-api.txt", pattern: "%s-removed.txt"}, | 
|  | } { | 
|  | props.Dists = append(props.Dists, android.Dist{ | 
|  | Targets: []string{"sdk", "win_sdk"}, | 
|  | Dir:     distDir, | 
|  | Dest:    proptools.StringPtr(fmt.Sprintf(p.pattern, module.distStem())), | 
|  | Tag:     proptools.StringPtr(fmt.Sprintf(p.tag, stubsTypeTagPrefix)), | 
|  | }) | 
|  | } | 
|  | } | 
|  |  | 
|  | mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx) | 
|  | } | 
|  |  | 
|  | type libraryProperties struct { | 
|  | Name           *string | 
|  | Enabled        proptools.Configurable[bool] | 
|  | Visibility     []string | 
|  | Srcs           []string | 
|  | Installable    *bool | 
|  | Sdk_version    *string | 
|  | System_modules *string | 
|  | Patch_module   *string | 
|  | Libs           []string | 
|  | Static_libs    []string | 
|  | Compile_dex    *bool | 
|  | Java_version   *string | 
|  | Openjdk9       struct { | 
|  | Srcs       []string | 
|  | Javacflags []string | 
|  | } | 
|  | Dist struct { | 
|  | Targets []string | 
|  | Dest    *string | 
|  | Dir     *string | 
|  | Tag     *string | 
|  | } | 
|  | Is_stubs_module       *bool | 
|  | Stub_contributing_api *string | 
|  | } | 
|  |  | 
|  | func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties { | 
|  | props := libraryProperties{} | 
|  | props.Enabled = module.EnabledProperty() | 
|  | props.Visibility = []string{"//visibility:override", "//visibility:private"} | 
|  | // sources are generated from the droiddoc | 
|  | sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) | 
|  | props.Sdk_version = proptools.StringPtr(sdkVersion) | 
|  | props.System_modules = module.deviceProperties.System_modules | 
|  | props.Patch_module = module.properties.Patch_module | 
|  | props.Installable = proptools.BoolPtr(false) | 
|  | props.Libs = module.sdkLibraryProperties.Stub_only_libs | 
|  | props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...) | 
|  | props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs | 
|  | // The stub-annotations library contains special versions of the annotations | 
|  | // with CLASS retention policy, so that they're kept. | 
|  | if proptools.Bool(module.sdkLibraryProperties.Annotations_enabled) { | 
|  | props.Libs = append(props.Libs, "stub-annotations") | 
|  | } | 
|  | props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs | 
|  | props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags | 
|  | // We compile the stubs for 1.8 in line with the main android.jar stubs, and potential | 
|  | // interop with older developer tools that don't support 1.9. | 
|  | props.Java_version = proptools.StringPtr("1.8") | 
|  | props.Is_stubs_module = proptools.BoolPtr(true) | 
|  | props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String()) | 
|  |  | 
|  | return props | 
|  | } | 
|  |  | 
|  | // Creates the from-source stub [Library] with ".stubs.<[apiScope.name]>.from-source" suffix. | 
|  | func (module *SdkLibrary) createFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { | 
|  |  | 
|  | props := module.stubsLibraryProps(mctx, apiScope) | 
|  | props.Name = proptools.StringPtr(module.fromSourceStubsLibraryModuleName(apiScope)) | 
|  | props.Srcs = []string{":" + module.droidstubsModuleName(apiScope)} | 
|  |  | 
|  | mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | // Creates the "exportable" from-source stub [Library] with | 
|  | // ".stubs.exportable.<[apiScope.name]>" suffix. | 
|  | func (module *SdkLibrary) createExportableFromSourceStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { | 
|  | props := module.stubsLibraryProps(mctx, apiScope) | 
|  | props.Name = proptools.StringPtr(module.exportableFromSourceStubsLibraryModuleName(apiScope)) | 
|  | props.Srcs = []string{":" + module.droidstubsModuleName(apiScope) + "{.exportable}"} | 
|  |  | 
|  | mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | // Creates the from-text stub [ApiLibrary] with ".stubs.<[apiScope.name]>.from-text" suffix. | 
|  | func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { | 
|  | props := struct { | 
|  | Name              *string | 
|  | Enabled           proptools.Configurable[bool] | 
|  | Visibility        []string | 
|  | Api_contributions []string | 
|  | Libs              proptools.Configurable[[]string] | 
|  | Static_libs       []string | 
|  | System_modules    *string | 
|  | Enable_validation *bool | 
|  | Stubs_type        *string | 
|  | Sdk_version       *string | 
|  | Previous_api      *string | 
|  | }{} | 
|  |  | 
|  | props.Name = proptools.StringPtr(module.fromTextStubsLibraryModuleName(apiScope)) | 
|  | props.Enabled = module.EnabledProperty() | 
|  | props.Visibility = []string{"//visibility:override", "//visibility:private"} | 
|  |  | 
|  | apiContributions := []string{} | 
|  |  | 
|  | // Api surfaces are not independent of each other, but have subset relationships, | 
|  | // and so does the api files. To generate from-text stubs for api surfaces other than public, | 
|  | // all subset api domains' api_contriubtions must be added as well. | 
|  | scope := apiScope | 
|  | for scope != nil { | 
|  | apiContributions = append(apiContributions, module.droidstubsModuleName(scope)+".api.contribution") | 
|  | scope = scope.extends | 
|  | } | 
|  | if apiScope == apiScopePublic { | 
|  | additionalApiContribution := module.apiLibraryAdditionalApiContribution() | 
|  | if additionalApiContribution != "" { | 
|  | apiContributions = append(apiContributions, additionalApiContribution) | 
|  | } | 
|  | } | 
|  |  | 
|  | props.Api_contributions = apiContributions | 
|  |  | 
|  | // Ensure that stub-annotations is added to the classpath before any other libs | 
|  | props.Libs = proptools.NewConfigurable[[]string](nil, nil) | 
|  | props.Libs.AppendSimpleValue([]string{"stub-annotations"}) | 
|  | props.Libs.AppendSimpleValue(module.properties.Libs) | 
|  | props.Libs.Append(module.properties.Static_libs) | 
|  | props.Libs.AppendSimpleValue(module.sdkLibraryProperties.Stub_only_libs) | 
|  | props.Libs.AppendSimpleValue(module.scopeToProperties[apiScope].Libs) | 
|  | props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs | 
|  |  | 
|  | props.System_modules = module.deviceProperties.System_modules | 
|  | props.Enable_validation = proptools.BoolPtr(true) | 
|  | props.Stubs_type = proptools.StringPtr("everything") | 
|  |  | 
|  | if module.deviceProperties.Sdk_version != nil { | 
|  | props.Sdk_version = module.deviceProperties.Sdk_version | 
|  | } | 
|  |  | 
|  | if module.compareAgainstLatestApi(apiScope) { | 
|  | // check against the latest released API | 
|  | latestApiFilegroupName := proptools.StringPtr(module.latestApiFilegroupName(apiScope)) | 
|  | props.Previous_api = latestApiFilegroupName | 
|  | } | 
|  |  | 
|  | mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope, doDist bool) libraryProperties { | 
|  | props := libraryProperties{} | 
|  |  | 
|  | props.Enabled = module.EnabledProperty() | 
|  | props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility) | 
|  | sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) | 
|  | props.Sdk_version = proptools.StringPtr(sdkVersion) | 
|  |  | 
|  | props.System_modules = module.deviceProperties.System_modules | 
|  |  | 
|  | // The imports need to be compiled to dex if the java_sdk_library requests it. | 
|  | compileDex := module.dexProperties.Compile_dex | 
|  | if module.stubLibrariesCompiledForDex() { | 
|  | compileDex = proptools.BoolPtr(true) | 
|  | } | 
|  | props.Compile_dex = compileDex | 
|  |  | 
|  | props.Stub_contributing_api = proptools.StringPtr(apiScope.kind.String()) | 
|  |  | 
|  | if !Bool(module.sdkLibraryProperties.No_dist) && doDist { | 
|  | props.Dist.Targets = []string{"sdk", "win_sdk"} | 
|  | props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem())) | 
|  | props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope)) | 
|  | props.Dist.Tag = proptools.StringPtr(".jar") | 
|  | } | 
|  | props.Is_stubs_module = proptools.BoolPtr(true) | 
|  |  | 
|  | return props | 
|  | } | 
|  |  | 
|  | // Creates the stub [Library] with ".stubs.<[apiScope.name]>" suffix. | 
|  | func (module *SdkLibrary) createTopLevelStubsLibrary( | 
|  | mctx android.DefaultableHookContext, apiScope *apiScope) { | 
|  |  | 
|  | // Dist the "everything" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is false | 
|  | doDist := !mctx.Config().ReleaseHiddenApiExportableStubs() | 
|  | props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist) | 
|  | props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) | 
|  |  | 
|  | // Add the stub compiling java_library/java_api_library as static lib based on build config | 
|  | staticLib := module.fromSourceStubsLibraryModuleName(apiScope) | 
|  | if mctx.Config().BuildFromTextStub() && module.ModuleBuildFromTextStubs() { | 
|  | staticLib = module.fromTextStubsLibraryModuleName(apiScope) | 
|  | } | 
|  | props.Static_libs = append(props.Static_libs, staticLib) | 
|  |  | 
|  | mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | // Creates the "exportable" stub [Library] with ".stubs.exportable.<[apiScope.name]>" suffix. | 
|  | func (module *SdkLibrary) createTopLevelExportableStubsLibrary( | 
|  | mctx android.DefaultableHookContext, apiScope *apiScope) { | 
|  |  | 
|  | // Dist the "exportable" stubs when the RELEASE_HIDDEN_API_EXPORTABLE_STUBS build flag is true | 
|  | doDist := mctx.Config().ReleaseHiddenApiExportableStubs() | 
|  | props := module.topLevelStubsLibraryProps(mctx, apiScope, doDist) | 
|  | props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope)) | 
|  |  | 
|  | staticLib := module.exportableFromSourceStubsLibraryModuleName(apiScope) | 
|  | props.Static_libs = append(props.Static_libs, staticLib) | 
|  |  | 
|  | mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | // Creates the [sdkLibraryXml] with ".xml" suffix. | 
|  | func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) { | 
|  | moduleMinApiLevel := module.Library.MinSdkVersion(mctx) | 
|  | var moduleMinApiLevelStr = moduleMinApiLevel.String() | 
|  | if moduleMinApiLevel == android.NoneApiLevel { | 
|  | moduleMinApiLevelStr = "current" | 
|  | } | 
|  | props := struct { | 
|  | Name                      *string | 
|  | Enabled                   proptools.Configurable[bool] | 
|  | Lib_name                  *string | 
|  | Apex_available            []string | 
|  | On_bootclasspath_since    *string | 
|  | On_bootclasspath_before   *string | 
|  | Min_device_sdk            *string | 
|  | Max_device_sdk            *string | 
|  | Sdk_library_min_api_level *string | 
|  | Uses_libs_dependencies    proptools.Configurable[[]string] | 
|  | }{ | 
|  | Name:                      proptools.StringPtr(module.xmlPermissionsModuleName()), | 
|  | Enabled:                   module.EnabledProperty(), | 
|  | Lib_name:                  proptools.StringPtr(module.BaseModuleName()), | 
|  | Apex_available:            module.ApexProperties.Apex_available, | 
|  | On_bootclasspath_since:    module.commonSdkLibraryProperties.On_bootclasspath_since, | 
|  | On_bootclasspath_before:   module.commonSdkLibraryProperties.On_bootclasspath_before, | 
|  | Min_device_sdk:            module.commonSdkLibraryProperties.Min_device_sdk, | 
|  | Max_device_sdk:            module.commonSdkLibraryProperties.Max_device_sdk, | 
|  | Sdk_library_min_api_level: &moduleMinApiLevelStr, | 
|  | Uses_libs_dependencies:    module.usesLibraryProperties.Uses_libs.Clone(), | 
|  | } | 
|  |  | 
|  | mctx.CreateModule(sdkLibraryXmlFactory, &props) | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------------------------- | 
|  | // Build rules of the submodules generated by java_sdk_library_import. | 
|  | // Note that the java_sdk_library_import module does not generate the implementation library. | 
|  | // Instead, it will create a dependency to the source implemenetation library if one exists. | 
|  | // java_sdk_library_import "framework-foo" generates the following submodules: | 
|  | // | 
|  | // - "framework-foo.stubs.<[apiScope.name]>" (type: [Import]): prebuilt stub library module that | 
|  | //		provides the stub jar file checked in the tree. | 
|  | // | 
|  | // - "framework-foo.stubs.source.<[apiScope.name]>" (type: [PrebuiltStubsSources]): prebuilt | 
|  | //		droidstubs module that provides the stub source jar file checked in the tree. | 
|  | // | 
|  | // - "framework-foo.stubs.source.<[apiScope.name]>.api.contribution" | 
|  | //		(type [JavaApiContributionImport]): prebuilt java_api_contribution module that provides | 
|  | //		the prebuilt api file for previously released from-text stub generation. | 
|  | // --------------------------------------------------------------------------------------------- | 
|  |  | 
|  | // Creates the prebuilt stub [Import] with ".stubs.<[apiScope.name]>" suffix. | 
|  | func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { | 
|  | // Creates a java import for the jar with ".stubs" suffix | 
|  | props := struct { | 
|  | Name                             *string | 
|  | Source_module_name               *string | 
|  | Created_by_java_sdk_library_name *string | 
|  | Sdk_version                      *string | 
|  | Libs                             []string | 
|  | Jars                             []string | 
|  | Compile_dex                      *bool | 
|  | Is_stubs_module                  *bool | 
|  |  | 
|  | android.UserSuppliedPrebuiltProperties | 
|  | }{} | 
|  | props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) | 
|  | props.Source_module_name = proptools.StringPtr(apiScope.stubsLibraryModuleName(module.BaseModuleName())) | 
|  | props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName()) | 
|  | props.Sdk_version = scopeProperties.Sdk_version | 
|  | // Prepend any of the libs from the legacy public properties to the libs for each of the | 
|  | // scopes to avoid having to duplicate them in each scope. | 
|  | props.Libs = append(module.properties.Libs, scopeProperties.Libs...) | 
|  | props.Jars = scopeProperties.Jars | 
|  |  | 
|  | // The imports are preferred if the java_sdk_library_import is preferred. | 
|  | props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) | 
|  |  | 
|  | // The imports need to be compiled to dex if the java_sdk_library_import requests it. | 
|  | compileDex := module.properties.Compile_dex | 
|  | if module.stubLibrariesCompiledForDex() { | 
|  | compileDex = proptools.BoolPtr(true) | 
|  | } | 
|  | props.Compile_dex = compileDex | 
|  | props.Is_stubs_module = proptools.BoolPtr(true) | 
|  |  | 
|  | mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { | 
|  | props := struct { | 
|  | Name                             *string | 
|  | Source_module_name               *string | 
|  | Created_by_java_sdk_library_name *string | 
|  | Srcs                             []string | 
|  |  | 
|  | android.UserSuppliedPrebuiltProperties | 
|  | }{} | 
|  | props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope)) | 
|  | props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName())) | 
|  | props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName()) | 
|  | props.Srcs = scopeProperties.Stub_srcs | 
|  |  | 
|  | // The stubs source is preferred if the java_sdk_library_import is preferred. | 
|  | props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) | 
|  |  | 
|  | mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | // Creates the prebuilt api contribution [JavaApiContributionImport] with | 
|  | // ".stubs.source.<[apiScope.name]>.api.contribution" suffix. | 
|  | func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { | 
|  | api_file := scopeProperties.Current_api | 
|  | api_surface := &apiScope.name | 
|  |  | 
|  | props := struct { | 
|  | Name                             *string | 
|  | Source_module_name               *string | 
|  | Created_by_java_sdk_library_name *string | 
|  | Api_surface                      *string | 
|  | Api_file                         *string | 
|  | Visibility                       []string | 
|  | }{} | 
|  |  | 
|  | props.Name = proptools.StringPtr(module.droidstubsModuleName(apiScope) + ".api.contribution") | 
|  | props.Source_module_name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()) + ".api.contribution") | 
|  | props.Created_by_java_sdk_library_name = proptools.StringPtr(module.RootLibraryName()) | 
|  | props.Api_surface = api_surface | 
|  | props.Api_file = api_file | 
|  | props.Visibility = []string{"//visibility:override", "//visibility:public"} | 
|  |  | 
|  | mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) | 
|  | } | 
|  |  | 
|  | // --------------------------------------------------------------------------------------------- | 
|  | // End of the build rules of the submodules generated by java_sdk_library_import. | 
|  | // --------------------------------------------------------------------------------------------- | 
|  |  | 
|  | // Definition of the [sdkLibraryXml] module. The module generates the permissions xml file, | 
|  | // so that the apps can specify the java_sdk_library using <uses-permission> tag in the | 
|  | // AndroidManifest.xml file. | 
|  | type sdkLibraryXml struct { | 
|  | android.ModuleBase | 
|  | android.DefaultableModuleBase | 
|  | android.ApexModuleBase | 
|  |  | 
|  | properties sdkLibraryXmlProperties | 
|  |  | 
|  | outputFilePath android.OutputPath | 
|  | installDirPath android.InstallPath | 
|  |  | 
|  | hideApexVariantFromMake bool | 
|  | } | 
|  |  | 
|  | type sdkLibraryXmlProperties struct { | 
|  | // canonical name of the lib | 
|  | Lib_name *string | 
|  |  | 
|  | // Signals that this shared library is part of the bootclasspath starting | 
|  | // on the version indicated in this attribute. | 
|  | // | 
|  | // This will make platforms at this level and above to ignore | 
|  | // <uses-library> tags with this library name because the library is already | 
|  | // available | 
|  | On_bootclasspath_since *string | 
|  |  | 
|  | // Signals that this shared library was part of the bootclasspath before | 
|  | // (but not including) the version indicated in this attribute. | 
|  | // | 
|  | // The system will automatically add a <uses-library> tag with this library to | 
|  | // apps that target any SDK less than the version indicated in this attribute. | 
|  | On_bootclasspath_before *string | 
|  |  | 
|  | // Indicates that PackageManager should ignore this shared library if the | 
|  | // platform is below the version indicated in this attribute. | 
|  | // | 
|  | // This means that the device won't recognise this library as installed. | 
|  | Min_device_sdk *string | 
|  |  | 
|  | // Indicates that PackageManager should ignore this shared library if the | 
|  | // platform is above the version indicated in this attribute. | 
|  | // | 
|  | // This means that the device won't recognise this library as installed. | 
|  | Max_device_sdk *string | 
|  |  | 
|  | // The SdkLibrary's min api level as a string | 
|  | // | 
|  | // This value comes from the ApiLevel of the MinSdkVersion property. | 
|  | Sdk_library_min_api_level *string | 
|  |  | 
|  | // Uses-libs dependencies that the shared library requires to work correctly. | 
|  | // | 
|  | // This will add dependency="foo:bar" to the <library> section. | 
|  | Uses_libs_dependencies proptools.Configurable[[]string] | 
|  | } | 
|  |  | 
|  | // java_sdk_library_xml builds the permission xml file for a java_sdk_library. | 
|  | // Not to be used directly by users. java_sdk_library internally uses this. | 
|  | func sdkLibraryXmlFactory() android.Module { | 
|  | module := &sdkLibraryXml{} | 
|  |  | 
|  | module.AddProperties(&module.properties) | 
|  |  | 
|  | android.InitApexModule(module) | 
|  | android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) | 
|  |  | 
|  | return module | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) UniqueApexVariations() bool { | 
|  | // sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the | 
|  | // mounted APEX, which contains the name of the APEX. | 
|  | return true | 
|  | } | 
|  |  | 
|  | // from android.PrebuiltEtcModule | 
|  | func (module *sdkLibraryXml) BaseDir() string { | 
|  | return "etc" | 
|  | } | 
|  |  | 
|  | // from android.PrebuiltEtcModule | 
|  | func (module *sdkLibraryXml) SubDir() string { | 
|  | return "permissions" | 
|  | } | 
|  |  | 
|  | var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil) | 
|  |  | 
|  | // from android.ApexModule | 
|  | func (module *sdkLibraryXml) AvailableFor(what string) bool { | 
|  | return true | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) DepsMutator(ctx android.BottomUpMutatorContext) { | 
|  | // do nothing | 
|  | } | 
|  |  | 
|  | var _ android.ApexModule = (*sdkLibraryXml)(nil) | 
|  |  | 
|  | // Implements android.ApexModule | 
|  | func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, | 
|  | sdkVersion android.ApiLevel) error { | 
|  | // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked | 
|  | return nil | 
|  | } | 
|  |  | 
|  | // File path to the runtime implementation library | 
|  | func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string { | 
|  | implName := proptools.String(module.properties.Lib_name) | 
|  | if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() { | 
|  | // TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name. | 
|  | // In most cases, this works fine. But when apex_name is set or override_apex is used | 
|  | // this can be wrong. | 
|  | return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexInfo.BaseApexName, implName) | 
|  | } | 
|  | partition := "system" | 
|  | if module.SocSpecific() { | 
|  | partition = "vendor" | 
|  | } else if module.DeviceSpecific() { | 
|  | partition = "odm" | 
|  | } else if module.ProductSpecific() { | 
|  | partition = "product" | 
|  | } else if module.SystemExtSpecific() { | 
|  | partition = "system_ext" | 
|  | } | 
|  | return "/" + partition + "/framework/" + implName + ".jar" | 
|  | } | 
|  |  | 
|  | func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string { | 
|  | if value == nil { | 
|  | return "" | 
|  | } | 
|  | apiLevel, err := android.ApiLevelFromUser(ctx, *value) | 
|  | if err != nil { | 
|  | // attributes in bp files have underscores but in the xml have dashes. | 
|  | ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error()) | 
|  | return "" | 
|  | } | 
|  | if apiLevel.IsCurrent() { | 
|  | // passing "current" would always mean a future release, never the current (or the current in | 
|  | // progress) which means some conditions would never be triggered. | 
|  | ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), | 
|  | `"current" is not an allowed value for this attribute`) | 
|  | return "" | 
|  | } | 
|  | // "safeValue" is safe because it translates finalized codenames to a string | 
|  | // with their SDK int. | 
|  | safeValue := apiLevel.String() | 
|  | return formattedOptionalAttribute(attrName, &safeValue) | 
|  | } | 
|  |  | 
|  | // formats an attribute for the xml permissions file if the value is not null | 
|  | // returns empty string otherwise | 
|  | func formattedOptionalAttribute(attrName string, value *string) string { | 
|  | if value == nil { | 
|  | return "" | 
|  | } | 
|  | return fmt.Sprintf("        %s=\"%s\"\n", attrName, *value) | 
|  | } | 
|  |  | 
|  | func formattedDependenciesAttribute(dependencies []string) string { | 
|  | if dependencies == nil { | 
|  | return "" | 
|  | } | 
|  | return fmt.Sprintf("        dependency=\"%s\"\n", strings.Join(dependencies, ":")) | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string { | 
|  | libName := proptools.String(module.properties.Lib_name) | 
|  | libNameAttr := formattedOptionalAttribute("name", &libName) | 
|  | filePath := module.implPath(ctx) | 
|  | filePathAttr := formattedOptionalAttribute("file", &filePath) | 
|  | implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since) | 
|  | implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before) | 
|  | minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk) | 
|  | maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk) | 
|  | dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies.GetOrDefault(ctx, nil)) | 
|  | // <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that). | 
|  | // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T | 
|  | var libraryTag string | 
|  | if module.properties.Min_device_sdk != nil { | 
|  | libraryTag = "    <apex-library\n" | 
|  | } else { | 
|  | libraryTag = "    <library\n" | 
|  | } | 
|  |  | 
|  | return strings.Join([]string{ | 
|  | "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", | 
|  | "<!-- Copyright (C) 2018 The Android Open Source Project\n", | 
|  | "\n", | 
|  | "    Licensed under the Apache License, Version 2.0 (the \"License\");\n", | 
|  | "    you may not use this file except in compliance with the License.\n", | 
|  | "    You may obtain a copy of the License at\n", | 
|  | "\n", | 
|  | "        http://www.apache.org/licenses/LICENSE-2.0\n", | 
|  | "\n", | 
|  | "    Unless required by applicable law or agreed to in writing, software\n", | 
|  | "    distributed under the License is distributed on an \"AS IS\" BASIS,\n", | 
|  | "    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", | 
|  | "    See the License for the specific language governing permissions and\n", | 
|  | "    limitations under the License.\n", | 
|  | "-->\n", | 
|  | "<permissions>\n", | 
|  | libraryTag, | 
|  | libNameAttr, | 
|  | filePathAttr, | 
|  | implicitFromAttr, | 
|  | implicitUntilAttr, | 
|  | minSdkAttr, | 
|  | maxSdkAttr, | 
|  | dependenciesAttr, | 
|  | "    />\n", | 
|  | "</permissions>\n", | 
|  | }, "") | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) { | 
|  | apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) | 
|  | module.hideApexVariantFromMake = !apexInfo.IsForPlatform() | 
|  |  | 
|  | libName := proptools.String(module.properties.Lib_name) | 
|  | module.selfValidate(ctx) | 
|  | xmlContent := module.permissionsContents(ctx) | 
|  |  | 
|  | module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath | 
|  | android.WriteFileRuleVerbatim(ctx, module.outputFilePath, xmlContent) | 
|  |  | 
|  | module.installDirPath = android.PathForModuleInstall(ctx, "etc", module.SubDir()) | 
|  | ctx.PackageFile(module.installDirPath, libName+".xml", module.outputFilePath) | 
|  |  | 
|  | ctx.SetOutputFiles(android.OutputPaths{module.outputFilePath}.Paths(), "") | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries { | 
|  | if module.hideApexVariantFromMake { | 
|  | return []android.AndroidMkEntries{{ | 
|  | Disabled: true, | 
|  | }} | 
|  | } | 
|  |  | 
|  | return []android.AndroidMkEntries{{ | 
|  | Class:      "ETC", | 
|  | OutputFile: android.OptionalPathForPath(module.outputFilePath), | 
|  | ExtraEntries: []android.AndroidMkExtraEntriesFunc{ | 
|  | func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { | 
|  | entries.SetString("LOCAL_MODULE_TAGS", "optional") | 
|  | entries.SetString("LOCAL_MODULE_PATH", module.installDirPath.String()) | 
|  | entries.SetString("LOCAL_INSTALLED_MODULE_STEM", module.outputFilePath.Base()) | 
|  | }, | 
|  | }, | 
|  | }} | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) { | 
|  | module.validateAtLeastTAttributes(ctx) | 
|  | module.validateMinAndMaxDeviceSdk(ctx) | 
|  | module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx) | 
|  | module.validateOnBootclasspathBeforeRequirements(ctx) | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) { | 
|  | t := android.ApiLevelOrPanic(ctx, "Tiramisu") | 
|  | module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk") | 
|  | module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk") | 
|  | module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before") | 
|  | module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since") | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) { | 
|  | if attr != nil { | 
|  | if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil { | 
|  | // we will inform the user of invalid inputs when we try to write the | 
|  | // permissions xml file so we don't need to do it here | 
|  | if t.GreaterThan(level) { | 
|  | ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T") | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) { | 
|  | if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil { | 
|  | min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk) | 
|  | max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk) | 
|  | if minErr == nil && maxErr == nil { | 
|  | // we will inform the user of invalid inputs when we try to write the | 
|  | // permissions xml file so we don't need to do it here | 
|  | if min.GreaterThan(max) { | 
|  | ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk") | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) { | 
|  | moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level) | 
|  | if module.properties.Min_device_sdk != nil { | 
|  | api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk) | 
|  | if err == nil { | 
|  | if moduleMinApi.GreaterThan(api) { | 
|  | ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi) | 
|  | } | 
|  | } | 
|  | } | 
|  | if module.properties.Max_device_sdk != nil { | 
|  | api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk) | 
|  | if err == nil { | 
|  | if moduleMinApi.GreaterThan(api) { | 
|  | ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi) | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) { | 
|  | moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level) | 
|  | if module.properties.On_bootclasspath_before != nil { | 
|  | t := android.ApiLevelOrPanic(ctx, "Tiramisu") | 
|  | // if we use the attribute, then we need to do this validation | 
|  | if moduleMinApi.LessThan(t) { | 
|  | // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+) | 
|  | if module.properties.Min_device_sdk == nil { | 
|  | ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T") | 
|  | } | 
|  | } | 
|  | } | 
|  | } |