aboutsummaryrefslogtreecommitdiff
path: root/java/apkcerts.go
blob: 8aba27b9d0e8704058d421b108c52ad2b1dccc1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright 2015 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"
	"fmt"
	"slices"
	"strings"

	"github.com/google/blueprint"
)

func init() {
	android.InitRegistrationContext.RegisterParallelSingletonType("apkcerts_singleton", apkCertsSingletonFactory)
}

// Info that should be included into the apkcerts.txt file.
// The info can be provided as either a text file containing a subset of the final apkcerts.txt,
// or as a certificate and name. The text file will be preferred if it exists
type ApkCertInfo struct {
	ApkCertsFile android.Path

	Certificate Certificate
	Name        string

	// True if LOCAL_MODULE_TAGS would contain "tests" in a make build.
	// In make this caused the partition in the apkcerts.txt file to be "data" instead of "system"
	Test bool
}

var ApkCertInfoProvider = blueprint.NewProvider[ApkCertInfo]()

type ApkCertsInfo []ApkCertInfo

var ApkCertsInfoProvider = blueprint.NewProvider[ApkCertsInfo]()

func apkCertsSingletonFactory() android.Singleton {
	return &apkCertsSingleton{}
}

type apkCertsSingleton struct{}

func (a *apkCertsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
	apkCerts := []string{}
	var apkCertsFiles android.Paths
	ctx.VisitAllModuleProxies(func(m android.ModuleProxy) {
		commonInfo, ok := android.OtherModuleProvider(ctx, m, android.CommonModuleInfoProvider)
		if !ok || commonInfo.SkipAndroidMkProcessing {
			return
		}
		if info, ok := android.OtherModuleProvider(ctx, m, android.HideApexVariantFromMakeProvider); ok && info.HideApexVariantFromMake {
			return
		}

		partition := commonInfo.PartitionTag

		specifiesPartition := commonInfo.SocSpecific || commonInfo.Vendor ||
			commonInfo.Proprietary || commonInfo.SystemExtSpecific || commonInfo.ProductSpecific ||
			commonInfo.DeviceSpecific

		if info, ok := android.OtherModuleProvider(ctx, m, ApkCertsInfoProvider); ok {
			for _, certInfo := range info {
				if certInfo.ApkCertsFile != nil {
					apkCertsFiles = append(apkCertsFiles, certInfo.ApkCertsFile)
				} else {
					// Partition information of apk-in-apex is not exported to the legacy Make packaging system.
					// Hardcode the partition to "system"
					apkCerts = append(apkCerts, FormatApkCertsLine(certInfo.Certificate, certInfo.Name, "system"))
				}
			}
		} else if info, ok := android.OtherModuleProvider(ctx, m, ApkCertInfoProvider); ok {
			if info.ApkCertsFile != nil {
				apkCertsFiles = append(apkCertsFiles, info.ApkCertsFile)
			} else {
				// From base_rules.mk
				if info.Test && partition == "system" && !specifiesPartition {
					partition = "data"
				}

				apkCerts = append(apkCerts, FormatApkCertsLine(info.Certificate, info.Name, partition))
			}
		}
	})
	slices.Sort(apkCerts) // sort by name
	apkCertsInfoWithoutAppSets := android.PathForOutput(ctx, "apkcerts_singleton", "apkcerts_without_app_sets.txt")
	android.WriteFileRule(ctx, apkCertsInfoWithoutAppSets, strings.Join(apkCerts, "\n"))
	apkCertsInfo := ApkCertsFile(ctx)
	ctx.Build(pctx, android.BuildParams{
		Rule:        android.CatAndSortAndUnique,
		Description: "combine apkcerts.txt",
		Output:      apkCertsInfo,
		Inputs:      append(apkCertsFiles, apkCertsInfoWithoutAppSets),
	})
}

func (s *apkCertsSingleton) MakeVars(ctx android.MakeVarsContext) {
	ctx.Strict("SOONG_APKCERTS_FILE", ApkCertsFile(ctx).String())
}

func ApkCertsFile(ctx android.PathContext) android.WritablePath {
	return android.PathForOutput(ctx, "apkcerts_singleton", "apkcerts.txt")
}

func FormatApkCertsLine(cert Certificate, name, partition string) string {
	pem := cert.AndroidMkString()
	var key string
	if cert.Key == nil {
		key = ""
	} else {
		key = cert.Key.String()
	}
	return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
}