1// Copyright 2021 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package java 16 17import ( 18 "android/soong/android" 19 "android/soong/dexpreopt" 20 21 "github.com/google/blueprint" 22 "github.com/google/blueprint/proptools" 23) 24 25func init() { 26 registerSystemserverClasspathBuildComponents(android.InitRegistrationContext) 27 28 android.RegisterSdkMemberType(SystemServerClasspathFragmentSdkMemberType) 29} 30 31func registerSystemserverClasspathBuildComponents(ctx android.RegistrationContext) { 32 ctx.RegisterModuleType("platform_systemserverclasspath", platformSystemServerClasspathFactory) 33 ctx.RegisterModuleType("systemserverclasspath_fragment", systemServerClasspathFactory) 34 ctx.RegisterModuleType("prebuilt_systemserverclasspath_fragment", prebuiltSystemServerClasspathModuleFactory) 35} 36 37var SystemServerClasspathFragmentSdkMemberType = &systemServerClasspathFragmentMemberType{ 38 SdkMemberTypeBase: android.SdkMemberTypeBase{ 39 PropertyName: "systemserverclasspath_fragments", 40 SupportsSdk: true, 41 42 // Support for adding systemserverclasspath_fragments to the sdk snapshot was only added in 43 // Tiramisu. 44 SupportedBuildReleaseSpecification: "Tiramisu+", 45 }, 46} 47 48type platformSystemServerClasspathModule struct { 49 android.ModuleBase 50 51 ClasspathFragmentBase 52} 53 54func platformSystemServerClasspathFactory() android.Module { 55 m := &platformSystemServerClasspathModule{} 56 initClasspathFragment(m, SYSTEMSERVERCLASSPATH) 57 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 58 return m 59} 60 61func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []android.AndroidMkEntries) { 62 return p.classpathFragmentBase().androidMkEntries() 63} 64 65func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 66 configuredJars := p.configuredJars(ctx) 67 classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, p.classpathType) 68 standaloneConfiguredJars := p.standaloneConfiguredJars(ctx) 69 standaloneClasspathJars := configuredJarListToClasspathJars(ctx, standaloneConfiguredJars, STANDALONE_SYSTEMSERVER_JARS) 70 configuredJars = configuredJars.AppendList(&standaloneConfiguredJars) 71 classpathJars = append(classpathJars, standaloneClasspathJars...) 72 p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) 73 p.classpathFragmentBase().installClasspathProto(ctx) 74} 75 76func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { 77 // TODO(satayev): include any apex jars that don't populate their classpath proto config. 78 return dexpreopt.GetGlobalConfig(ctx).SystemServerJars 79} 80 81func (p *platformSystemServerClasspathModule) standaloneConfiguredJars(ctx android.ModuleContext) android.ConfiguredJarList { 82 return dexpreopt.GetGlobalConfig(ctx).StandaloneSystemServerJars 83} 84 85type SystemServerClasspathModule struct { 86 android.ModuleBase 87 android.ApexModuleBase 88 89 ClasspathFragmentBase 90 91 properties systemServerClasspathFragmentProperties 92} 93 94func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error { 95 return nil 96} 97 98type systemServerClasspathFragmentProperties struct { 99 // List of system_server classpath jars, could be either java_library, or java_sdk_library. 100 // 101 // The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH. 102 Contents proptools.Configurable[[]string] `android:"arch_variant"` 103 104 // List of jars that system_server loads dynamically using separate classloaders. 105 // 106 // The order does not matter. 107 Standalone_contents proptools.Configurable[[]string] `android:"arch_variant"` 108} 109 110func systemServerClasspathFactory() android.Module { 111 m := &SystemServerClasspathModule{} 112 m.AddProperties(&m.properties) 113 android.InitApexModule(m) 114 initClasspathFragment(m, SYSTEMSERVERCLASSPATH) 115 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 116 return m 117} 118 119func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 120 if len(s.properties.Contents.GetOrDefault(ctx, nil)) == 0 && len(s.properties.Standalone_contents.GetOrDefault(ctx, nil)) == 0 { 121 ctx.PropertyErrorf("contents", "Either contents or standalone_contents needs to be non-empty") 122 } 123 124 configuredJars := s.configuredJars(ctx) 125 classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, s.classpathType) 126 standaloneConfiguredJars := s.standaloneConfiguredJars(ctx) 127 standaloneClasspathJars := configuredJarListToClasspathJars(ctx, standaloneConfiguredJars, STANDALONE_SYSTEMSERVER_JARS) 128 configuredJars = configuredJars.AppendList(&standaloneConfiguredJars) 129 classpathJars = append(classpathJars, standaloneClasspathJars...) 130 s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) 131 s.setPartitionInfoOfLibraries(ctx) 132} 133 134// Map of java library name to their install partition. 135type LibraryNameToPartitionInfo struct { 136 LibraryNameToPartition map[string]string 137} 138 139// LibraryNameToPartitionInfoProvider will be used by the top-level apex to enforce that dexpreopt files 140// of apex system server jars are installed in the same partition as the top-level apex. 141var LibraryNameToPartitionInfoProvider = blueprint.NewProvider[LibraryNameToPartitionInfo]() 142 143func (s *SystemServerClasspathModule) setPartitionInfoOfLibraries(ctx android.ModuleContext) { 144 libraryNameToPartition := map[string]string{} 145 ctx.VisitDirectDepsWithTag(systemServerClasspathFragmentContentDepTag, func(m android.Module) { 146 libraryNameToPartition[m.Name()] = m.PartitionTag(ctx.DeviceConfig()) 147 }) 148 android.SetProvider(ctx, LibraryNameToPartitionInfoProvider, LibraryNameToPartitionInfo{ 149 LibraryNameToPartition: libraryNameToPartition, 150 }) 151} 152 153func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { 154 global := dexpreopt.GetGlobalConfig(ctx) 155 156 possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Contents.GetOrDefault(ctx, nil), systemServerClasspathFragmentContentDepTag) 157 jars, unknown := global.ApexSystemServerJars.Filter(possibleUpdatableModules) 158 // TODO(satayev): remove geotz ssc_fragment, since geotz is not part of SSCP anymore. 159 _, unknown = android.RemoveFromList("geotz", unknown) 160 // This module only exists in car products. 161 // So ignore it even if it is not in PRODUCT_APEX_SYSTEM_SERVER_JARS. 162 // TODO(b/203233647): Add better mechanism to make it optional. 163 _, unknown = android.RemoveFromList("car-frameworks-service-module", unknown) 164 165 // This module is optional, so it is not present in all products. 166 // (See PRODUCT_ISOLATED_COMPILATION_ENABLED.) 167 // So ignore it even if it is not in PRODUCT_APEX_SYSTEM_SERVER_JARS. 168 // TODO(b/203233647): Add better mechanism to make it optional. 169 _, unknown = android.RemoveFromList("service-compos", unknown) 170 171 // TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths 172 // config. However, any test specific jars would not be present in ApexSystemServerJars. Instead, 173 // we should check if we are creating a config for apex_test via ApexInfo and amend the values. 174 // This is an exception to support end-to-end test for ApexdUnitTests, until such support exists. 175 if android.InList("test_service-apexd", possibleUpdatableModules) { 176 jars = jars.Append("com.android.apex.test_package", "test_service-apexd") 177 } else if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 { 178 // For non test apexes, make sure that all contents are actually declared in make. 179 ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_SYSTEM_SERVER_JARS", unknown) 180 } 181 182 return jars 183} 184 185func (s *SystemServerClasspathModule) standaloneConfiguredJars(ctx android.ModuleContext) android.ConfiguredJarList { 186 global := dexpreopt.GetGlobalConfig(ctx) 187 188 possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Standalone_contents.GetOrDefault(ctx, nil), systemServerClasspathFragmentContentDepTag) 189 jars, _ := global.ApexStandaloneSystemServerJars.Filter(possibleUpdatableModules) 190 191 // TODO(jiakaiz): add a check to ensure that the contents are declared in make. 192 193 return jars 194} 195 196type systemServerClasspathFragmentContentDependencyTag struct { 197 blueprint.BaseDependencyTag 198} 199 200// The systemserverclasspath_fragment contents must never depend on prebuilts. 201func (systemServerClasspathFragmentContentDependencyTag) ReplaceSourceWithPrebuilt() bool { 202 return false 203} 204 205// SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if 206// they were specified using java_systemserver_libs or java_sdk_libs. 207func (b systemServerClasspathFragmentContentDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType { 208 // If the module is a java_sdk_library then treat it as if it was specified in the java_sdk_libs 209 // property, otherwise treat if it was specified in the java_systemserver_libs property. 210 if javaSdkLibrarySdkMemberType.IsInstance(child) { 211 return javaSdkLibrarySdkMemberType 212 } 213 214 return JavaSystemserverLibsSdkMemberType 215} 216 217func (b systemServerClasspathFragmentContentDependencyTag) ExportMember() bool { 218 return true 219} 220 221// Contents of system server fragments require files from prebuilt apex files. 222func (systemServerClasspathFragmentContentDependencyTag) RequiresFilesFromPrebuiltApex() {} 223 224var _ android.ReplaceSourceWithPrebuilt = systemServerClasspathFragmentContentDepTag 225var _ android.SdkMemberDependencyTag = systemServerClasspathFragmentContentDepTag 226var _ android.RequiresFilesFromPrebuiltApexTag = systemServerClasspathFragmentContentDepTag 227 228// The tag used for the dependency between the systemserverclasspath_fragment module and its contents. 229var systemServerClasspathFragmentContentDepTag = systemServerClasspathFragmentContentDependencyTag{} 230 231func IsSystemServerClasspathFragmentContentDepTag(tag blueprint.DependencyTag) bool { 232 return tag == systemServerClasspathFragmentContentDepTag 233} 234 235// The dexpreopt artifacts of apex system server jars are installed onto system image. 236func (s systemServerClasspathFragmentContentDependencyTag) InstallDepNeeded() bool { 237 return true 238} 239 240func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { 241 module := ctx.Module() 242 _, isSourceModule := module.(*SystemServerClasspathModule) 243 var deps []string 244 deps = append(deps, s.properties.Contents.GetOrDefault(ctx, nil)...) 245 deps = append(deps, s.properties.Standalone_contents.GetOrDefault(ctx, nil)...) 246 247 for _, name := range deps { 248 // A systemserverclasspath_fragment must depend only on other source modules, while the 249 // prebuilt_systemserverclasspath_fragment_fragment must only depend on other prebuilt modules. 250 if !isSourceModule { 251 name = android.PrebuiltNameFromSource(name) 252 } 253 ctx.AddDependency(module, systemServerClasspathFragmentContentDepTag, name) 254 } 255} 256 257// Collect information for opening IDE project files in java/jdeps.go. 258func (s *SystemServerClasspathModule) IDEInfo(ctx android.BaseModuleContext, dpInfo *android.IdeInfo) { 259 dpInfo.Deps = append(dpInfo.Deps, s.properties.Contents.GetOrDefault(ctx, nil)...) 260 dpInfo.Deps = append(dpInfo.Deps, s.properties.Standalone_contents.GetOrDefault(ctx, nil)...) 261} 262 263type systemServerClasspathFragmentMemberType struct { 264 android.SdkMemberTypeBase 265} 266 267func (s *systemServerClasspathFragmentMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) { 268 ctx.AddVariationDependencies(nil, dependencyTag, names...) 269} 270 271func (s *systemServerClasspathFragmentMemberType) IsInstance(module android.Module) bool { 272 _, ok := module.(*SystemServerClasspathModule) 273 return ok 274} 275 276func (s *systemServerClasspathFragmentMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { 277 return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_systemserverclasspath_fragment") 278} 279 280func (s *systemServerClasspathFragmentMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { 281 return &systemServerClasspathFragmentSdkMemberProperties{} 282} 283 284type systemServerClasspathFragmentSdkMemberProperties struct { 285 android.SdkMemberPropertiesBase 286 287 // List of system_server classpath jars, could be either java_library, or java_sdk_library. 288 // 289 // The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH. 290 Contents []string 291 292 // List of jars that system_server loads dynamically using separate classloaders. 293 // 294 // The order does not matter. 295 Standalone_contents []string 296} 297 298func (s *systemServerClasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { 299 module := variant.(*SystemServerClasspathModule) 300 301 s.Contents = module.properties.Contents.GetOrDefault(ctx.SdkModuleContext(), nil) 302 s.Standalone_contents = module.properties.Standalone_contents.GetOrDefault(ctx.SdkModuleContext(), nil) 303} 304 305func (s *systemServerClasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { 306 builder := ctx.SnapshotBuilder() 307 requiredMemberDependency := builder.SdkMemberReferencePropertyTag(true) 308 309 if len(s.Contents) > 0 { 310 propertySet.AddPropertyWithTag("contents", s.Contents, requiredMemberDependency) 311 } 312 313 if len(s.Standalone_contents) > 0 { 314 propertySet.AddPropertyWithTag("standalone_contents", s.Standalone_contents, requiredMemberDependency) 315 } 316} 317 318var _ android.SdkMemberType = (*systemServerClasspathFragmentMemberType)(nil) 319 320// A prebuilt version of the systemserverclasspath_fragment module. 321type prebuiltSystemServerClasspathModule struct { 322 SystemServerClasspathModule 323 prebuilt android.Prebuilt 324} 325 326func (module *prebuiltSystemServerClasspathModule) Prebuilt() *android.Prebuilt { 327 return &module.prebuilt 328} 329 330func (module *prebuiltSystemServerClasspathModule) Name() string { 331 return module.prebuilt.Name(module.ModuleBase.Name()) 332} 333 334func (module *prebuiltSystemServerClasspathModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string { 335 return nil 336} 337 338func (module *prebuiltSystemServerClasspathModule) UseProfileGuidedDexpreopt() bool { 339 return false 340} 341 342var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltSystemServerClasspathModule)(nil) 343 344func prebuiltSystemServerClasspathModuleFactory() android.Module { 345 m := &prebuiltSystemServerClasspathModule{} 346 m.AddProperties(&m.properties) 347 // This doesn't actually have any prebuilt files of its own so pass a placeholder for the srcs 348 // array. 349 android.InitPrebuiltModule(m, &[]string{"placeholder"}) 350 android.InitApexModule(m) 351 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 352 return m 353} 354