1// Copyright 2020 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)
20
21type partitionGroup int
22
23// Representation of partition group for checking inter-partition library dependencies.
24// Between system and system_ext, there are no restrictions of dependencies,
25// so we can treat these partitions as the same in terms of inter-partition dependency.
26// Same policy is applied between vendor and odm partiton.
27const (
28	partitionGroupNone partitionGroup = iota
29	// group for system, and system_ext partition
30	partitionGroupSystem
31	// group for vendor and odm partition
32	partitionGroupVendor
33	// product partition
34	partitionGroupProduct
35)
36
37func (g partitionGroup) String() string {
38	switch g {
39	case partitionGroupSystem:
40		return "system"
41	case partitionGroupVendor:
42		return "vendor"
43	case partitionGroupProduct:
44		return "product"
45	}
46
47	return ""
48}
49
50// Get partition group of java module that can be used at inter-partition dependency check.
51// We currently have three groups
52//   (system, system_ext) => system partition group
53//   (vendor, odm) => vendor partition group
54//   (product) => product partition group
55func (j *Module) partitionGroup(ctx android.EarlyModuleContext) partitionGroup {
56	// system and system_ext partition can be treated as the same in terms of inter-partition dependency.
57	if j.Platform() || j.SystemExtSpecific() {
58		return partitionGroupSystem
59	}
60
61	// vendor and odm partition can be treated as the same in terms of inter-partition dependency.
62	if j.SocSpecific() || j.DeviceSpecific() {
63		return partitionGroupVendor
64	}
65
66	// product partition is independent.
67	if j.ProductSpecific() {
68		return partitionGroupProduct
69	}
70
71	panic("Cannot determine partition type")
72}
73
74func (j *Module) allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool {
75	return inList(j.Name(), ctx.Config().InterPartitionJavaLibraryAllowList())
76}
77
78func (j *Module) syspropWithPublicStubs() bool {
79	return j.deviceProperties.SyspropPublicStub != ""
80}
81
82type javaSdkLibraryEnforceContext interface {
83	Name() string
84	allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool
85	partitionGroup(ctx android.EarlyModuleContext) partitionGroup
86	syspropWithPublicStubs() bool
87}
88
89var _ javaSdkLibraryEnforceContext = (*Module)(nil)
90
91func (j *Module) checkPartitionsForJavaDependency(ctx android.EarlyModuleContext, propName string, dep javaSdkLibraryEnforceContext) {
92	if dep.allowListedInterPartitionJavaLibrary(ctx) {
93		return
94	}
95
96	if dep.syspropWithPublicStubs() {
97		return
98	}
99
100	// If product interface is not enforced, skip check between system and product partition.
101	// But still need to check between product and vendor partition because product interface flag
102	// just represents enforcement between product and system, and vendor interface enforcement
103	// that is enforced here by precondition is representing enforcement between vendor and other partitions.
104	if !ctx.Config().EnforceProductPartitionInterface() {
105		productToSystem := j.partitionGroup(ctx) == partitionGroupProduct && dep.partitionGroup(ctx) == partitionGroupSystem
106		systemToProduct := j.partitionGroup(ctx) == partitionGroupSystem && dep.partitionGroup(ctx) == partitionGroupProduct
107
108		if productToSystem || systemToProduct {
109			return
110		}
111	}
112
113	// If module and dependency library is inter-partition
114	if j.partitionGroup(ctx) != dep.partitionGroup(ctx) {
115		errorFormat := "dependency on java_library (%q) is not allowed across the partitions (%s -> %s), use java_sdk_library instead"
116		ctx.PropertyErrorf(propName, errorFormat, dep.Name(), j.partitionGroup(ctx), dep.partitionGroup(ctx))
117	}
118}
119