summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:20:04 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:20:04 +0000
commit41813124bfc405bedef0e3094e7843e325416c10 (patch)
tree2fd7b299fb019dccf02c386f456f71785a0563f5
parent863d29a94d18216224b70785bbbf9839e1498e1d (diff)
parentfbf62f8632731c3c78cfbfce15e6cd4c2079978a (diff)
downloadGki-android14-mainline-sdkext-release.tar.gz
Snap for 10453563 from fbf62f8632731c3c78cfbfce15e6cd4c2079978a to mainline-sdkext-releaseaml_sdk_341510000aml_sdk_341410000aml_sdk_341110080aml_sdk_341110000aml_sdk_341010000aml_sdk_340912010android14-mainline-sdkext-release
Change-Id: I82c30207972d7297caab0cc6ee7811eda35a8673
-rw-r--r--Android.bp157
-rw-r--r--TEST_MAPPING3
-rw-r--r--build/Android.bp41
-rw-r--r--build/gki.go311
-rw-r--r--build/kmi.go45
-rw-r--r--build/kmi_test.go48
-rw-r--r--build/prebuilt.go125
-rw-r--r--build/properties.go50
-rw-r--r--build/raw_img_ota.go250
-rw-r--r--build_gki_apex_manifest.cpp133
-rw-r--r--com.android.gki.avbpubkeybin1032 -> 0 bytes
-rw-r--r--com.android.gki.pem51
-rwxr-xr-xdownload_boot_prebuilt.py140
-rw-r--r--extract_img_from_apex.py96
-rw-r--r--ota_from_raw_image.py113
-rw-r--r--preinstall.sh39
-rw-r--r--test/Android.bp55
-rw-r--r--test/AndroidTest.xml21
-rw-r--r--test/com.android.gki.kmi_5_4_android12_0_test_prebuilt.apexbin1258765 -> 0 bytes
-rw-r--r--test/src/com/android/gki/tests/GkiInstallTest.java318
20 files changed, 0 insertions, 1996 deletions
diff --git a/Android.bp b/Android.bp
deleted file mode 100644
index eb7729b..0000000
--- a/Android.bp
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-python_defaults {
- name: "gki_python_defaults",
- libs: [
- "releasetools_ota_from_target_files",
- ],
- version: {
- py3: {
- embedded_launcher: true,
- },
- },
- target: {
- darwin: {
- // required module "brillo_update_payload" is disabled on darwin
- enabled: false,
- },
- },
-}
-
-python_binary_host {
- name: "ota_from_raw_image",
- defaults: ["gki_python_defaults"],
- srcs: ["ota_from_raw_image.py"],
- required: [
- "brillo_update_payload",
- ],
-}
-
-python_binary_host {
- name: "extract_img_from_apex",
- defaults: ["gki_python_defaults"],
- srcs: ["extract_img_from_apex.py"],
- required: [
- "debugfs",
- "delta_generator",
- ],
-}
-
-apex_key {
- name: "com.android.gki.key",
- public_key: "com.android.gki.avbpubkey",
- private_key: "com.android.gki.pem",
-}
-
-// Use cc_prebuilt_binary because sh_binary does not support product_specific.
-// TODO(b/169954965): Change to sh_binary when product_specific is supported.
-cc_prebuilt_binary {
- name: "com.android.gki.preinstall",
- product_specific: true,
- srcs: ["preinstall.sh"],
- apex_available: ["com.android.gki.*"],
- strip: {
- none: true,
- },
-}
-
-// Common defaults for all GKI APEXes.
-apex_defaults {
- name: "com.android.gki_defaults",
- product_specific: true,
- binaries: [
- "update_engine_stable_client",
- "com.android.gki.preinstall",
- ],
- file_contexts: ":com.android.gki-file_contexts",
- // Key to sign apex_payload.img
- key: "com.android.gki.key",
- // Key to sign APEX. Left empty to use defaults.
- certificate: "",
- updatable: false,
-}
-
-// Helper binary to build APEX manifest for GKI.
-cc_binary_host {
- name: "build_gki_apex_manifest",
- srcs: [
- "build_gki_apex_manifest.cpp",
- ],
- static_libs: [
- "libbase",
- "libgflags",
- "libjsoncpp",
- "libkver",
- "liblog",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
-}
-
-// Build GKI APEX 5.4-android12-unstable from $(PRODUCT_OUT)/boot.img.
-// Also generate test packages.
-gki_apex {
- name: "com.android.gki.kmi_5_4_android12_unstable",
- installable: true,
- kmi_version: "5.4-android12-unstable",
- product_out_path: "boot.img",
- gen_test: true,
-}
-
-// Build GKI APEX 5.10-android12-unstable from $(PRODUCT_OUT)/boot.img.
-// Also generate test packages.
-gki_apex {
- name: "com.android.gki.kmi_5_10_android12_unstable",
- installable: true,
- kmi_version: "5.10-android12-unstable",
- product_out_path: "boot.img",
- gen_test: true,
-}
-
-// Build GKI APEX 5.4-android12-unstable from $(PRODUCT_OUT)/boot-5.4.img
-gki_apex {
- name: "com.android.gki.kmi_5_4_android12_unstable_boot-5.4",
- installable: false,
- kmi_version: "5.4-android12-unstable",
- product_out_path: "boot-5.4.img",
-}
-
-// Build GKI APEX 5.10-android12-unstable from $(PRODUCT_OUT)/boot-5.10.img
-gki_apex {
- name: "com.android.gki.kmi_5_10_android12_unstable_boot-5.10",
- installable: false,
- kmi_version: "5.10-android12-unstable",
- product_out_path: "boot-5.10.img",
-}
-
-// List of all test APEXes for GkiInstallTest. Append "_test_high" and "_test_low" for each
-// gki_apex with gen_test:true.
-filegroup {
- name: "gki_install_test_files",
- srcs: [
- ":com.android.gki.kmi_5_4_android12_unstable_test_high",
- ":com.android.gki.kmi_5_4_android12_unstable_test_low",
- ":com.android.gki.kmi_5_10_android12_unstable_test_high",
- ":com.android.gki.kmi_5_10_android12_unstable_test_low",
- ],
-}
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 592bd85..ce2bc64 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,9 +2,6 @@
"presubmit": [
{
"name": "libkver_test"
- },
- {
- "name": "GkiInstallTest"
}
]
}
diff --git a/build/Android.bp b/build/Android.bp
deleted file mode 100644
index d9cb6ff..0000000
--- a/build/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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 {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-bootstrap_go_package {
- name: "gki-soong-rules",
- pkgPath: "android/soong/gki",
- pluginFor: ["soong_build"],
- deps: [
- "blueprint",
- "blueprint-proptools",
- "soong",
- "soong-android",
- "soong-apex",
- "soong-phony",
- ],
- srcs: [
- "gki.go",
- "kmi.go",
- "prebuilt.go",
- "properties.go",
- "raw_img_ota.go",
- ],
- testSrcs: [
- "kmi_test.go",
- ],
-}
diff --git a/build/gki.go b/build/gki.go
deleted file mode 100644
index e34130b..0000000
--- a/build/gki.go
+++ /dev/null
@@ -1,311 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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 gki
-
-import (
- "path/filepath"
- "strings"
-
- "android/soong/android"
- "android/soong/apex"
- "android/soong/etc"
- "android/soong/genrule"
-
- "github.com/google/blueprint/proptools"
-)
-
-type gkiApexProperties struct {
- // Path relative to $(PRODUCT_OUT) that points to the boot image. This is
- // passed to the generated makefile_goal.
- // Exactly one of [factory, product_out_path] must be set.
- Product_out_path *string
-
- // Declared KMI version of the boot image. Example: "5.4-android12-0"
- Kmi_version *string
-
- // The certificate to sign the OTA payload.
- // The name of a certificate in the default certificate directory, blank to
- // use the default product certificate,
- // or an android_app_certificate module name in the form ":module".
- Ota_payload_certificate *string
-
- // Whether test APEXes are generated. Test APEXes are named with
- // ${name}_test_high and ${name}_test_low, respectively.
- Gen_test *bool
-
- // Whether this APEX is installable to one of the partitions. Default:
- // see apex.installable.
- Installable *bool
-
- // Whether modules should be enabled according to board variables.
- ModulesEnabled bool `blueprint:"mutated"`
- // APEX package name that will be declared in the APEX manifest.
- // e.g. com.android.gki.kmi_5_4_android12_0
- ApexName *string `blueprint:"mutated"`
-}
-
-type gkiApex struct {
- android.ModuleBase
- properties gkiApexProperties
-}
-
-func init() {
- android.RegisterModuleType("gki_apex", gkiApexFactory)
-}
-
-// Declare a GKI APEX. Generate a set of modules to define an apex with name
-// "com.android.gki" + sanitized(kmi_version).
-func gkiApexFactory() android.Module {
- g := &gkiApex{}
- g.AddProperties(&g.properties)
- android.InitAndroidModule(g)
- android.AddLoadHook(g, func(ctx android.LoadHookContext) { gkiApexMutator(ctx, g) })
- return g
-}
-
-func gkiApexMutator(mctx android.LoadHookContext, g *gkiApex) {
- g.validateAndSetMutableProperties(mctx)
- g.createModulesRealApexes(mctx)
-}
-
-func (g *gkiApex) validateAndSetMutableProperties(mctx android.LoadHookContext) {
- // Parse kmi_version property to find APEX name.
- apexName, err := kmiVersionToApexName(proptools.String(g.properties.Kmi_version))
- if err != nil {
- mctx.PropertyErrorf("kmi_version", err.Error())
- return
- }
-
- // Set mutable properties.
- g.properties.ModulesEnabled = g.bootImgHasRules(mctx) && g.boardDefinesKmiVersion(mctx)
- g.properties.ApexName = proptools.StringPtr(apexName)
-}
-
-func testApexBundleFactory() android.Module {
- return apex.ApexBundleFactory(true /* testApex */)
-}
-
-// Create modules for a real APEX package that contains an OTA payload.
-func (g *gkiApex) createModulesRealApexes(mctx android.LoadHookContext) {
- // Import $(PRODUCT_OUT)/boot.img to Soong
- bootImage := g.moduleName() + "_bootimage"
- mctx.CreateModule(android.MakefileGoalFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(bootImage),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &makefileGoalProperties{
- Product_out_path: g.properties.Product_out_path,
- })
- // boot.img -> kernel_release.txt
- mctx.CreateModule(genrule.GenRuleFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(g.kernelReleaseFileName()),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &genRuleProperties{
- Defaults: []string{"extract_kernel_release_defaults"},
- Srcs: []string{":" + bootImage},
- })
- // boot.img -> payload.bin and payload_properties.txt
- otaPayloadGen := g.moduleName() + "_ota_payload_gen"
- mctx.CreateModule(rawImageOtaFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(otaPayloadGen),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &rawImageOtaProperties{
- Certificate: g.properties.Ota_payload_certificate,
- Image_goals: []string{"boot:" + bootImage},
- })
- // copy payload.bin to <apex>/etc/ota
- mctx.CreateModule(etc.PrebuiltEtcFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(g.otaPayloadName()),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &prebuiltEtcProperties{
- Src: proptools.StringPtr(":" + otaPayloadGen + "{" + payloadTag + "}"),
- Filename_from_src: proptools.BoolPtr(true),
- Relative_install_path: proptools.StringPtr("ota"),
- Installable: proptools.BoolPtr(false),
- })
- // copy payload_properties.txt to <apex>/etc/ota
- mctx.CreateModule(etc.PrebuiltEtcFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(g.otaPropertiesName()),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &prebuiltEtcProperties{
- Src: proptools.StringPtr(":" + otaPayloadGen + "{" + payloadPropertiesTag + "}"),
- Filename_from_src: proptools.BoolPtr(true),
- Relative_install_path: proptools.StringPtr("ota"),
- Installable: proptools.BoolPtr(false),
- })
- // Create the APEX module with name g.moduleName(). Use factory APEX version.
- g.createModulesRealApex(mctx, g.moduleName(), false, "")
-
- // Create test APEX modules if gen_test. Test packages are not installable.
- // Use hard-coded APEX version.
- if proptools.Bool(g.properties.Gen_test) {
- g.createModulesRealApex(mctx, g.moduleName()+"_test_high", true, "1000000000")
- g.createModulesRealApex(mctx, g.moduleName()+"_test_low", true, "1")
- }
-}
-
-func (g *gkiApex) createModulesRealApex(mctx android.LoadHookContext,
- moduleName string,
- isTestApex bool,
- overrideApexVersion string) {
- // Check kmi_version property against kernel_release.txt, then
- // kernel_release.txt -> apex_manifest.json.
- apexManifest := moduleName + "_apex_manifest"
- mctx.CreateModule(genrule.GenRuleFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(apexManifest),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &genRuleProperties{
- Tools: []string{"build_gki_apex_manifest"},
- Out: []string{"apex_manifest.json"},
- Srcs: []string{":" + g.kernelReleaseFileName()},
- Cmd: proptools.StringPtr(g.createApexManifestCmd(overrideApexVersion)),
- })
-
- // The APEX module.
-
- // For test APEXes, if module is not enabled because KMI version is not
- // compatible with the device, create a stub module that produces an empty
- // file. This is so that the module name can be used in tests.
- if isTestApex && !g.properties.ModulesEnabled {
- mctx.CreateModule(genrule.GenRuleFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(moduleName),
- }, &genRuleProperties{
- Out: []string{moduleName + ".apex"},
- Cmd: proptools.StringPtr(`touch $(out)`),
- })
- return
- }
-
- // For test APEXes, if module is enabled, build an apex_test with installable: false.
- // For installed APEXes, build apex, respecting installable and enabled.
- apexFactory := apex.BundleFactory
- overrideInstallable := g.properties.Installable
- if isTestApex {
- apexFactory = testApexBundleFactory
- overrideInstallable = proptools.BoolPtr(false)
- }
-
- mctx.CreateModule(apexFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(moduleName),
- Enabled: proptools.BoolPtr(g.properties.ModulesEnabled),
- }, &apexProperties{
- Apex_name: g.properties.ApexName,
- Manifest: proptools.StringPtr(":" + apexManifest),
- Defaults: []string{"com.android.gki_defaults"},
- // A real GKI APEX cannot be preinstalled to the device.
- // It can only be provided as an update.
- Installable: overrideInstallable,
- Prebuilts: []string{
- g.otaPayloadName(),
- g.otaPropertiesName(),
- },
- })
-}
-
-// Original module name as specified by the "name" property.
-// This is also the APEX module name, i.e. the file name of the APEX file.
-// This is also the prefix of names of all generated modules that the phony module depends on.
-// e.g. com.android.gki.kmi_5_4_android12_0_boot
-func (g *gkiApex) moduleName() string {
- return g.BaseModuleName()
-}
-
-// The appeared name of this gkiApex object. Exposed to Soong to avoid conflicting with
-// the generated APEX module with name moduleName().
-// e.g. com.android.gki.kmi_5_4_android12_0_boot_all
-func (g *gkiApex) Name() string {
- return g.moduleName() + "_all"
-}
-
-// Names for intermediate modules.
-func (g *gkiApex) kernelReleaseFileName() string {
- return g.moduleName() + "_bootimage_kernel_release_file"
-}
-
-func (g *gkiApex) otaPayloadName() string {
- return g.moduleName() + "_ota_payload"
-}
-
-func (g *gkiApex) otaPropertiesName() string {
- return g.moduleName() + "_ota_payload_properties"
-}
-
-// If the boot image pointed at product_out_path has no rule to be generated, do not generate any
-// build rules for this gki_apex module. For example, if this gki_apex module is:
-// { name: "foo", product_out_path: "boot-bar.img" }
-// But there is no rule to generate boot-bar.img, then
-// - `m foo` fails with `unknown target 'foo'`
-// - checkbuild is still successful. The module foo doesn't even exist, so there
-// is no dependency on boot-bar.img
-//
-// There is a rule to generate "boot-foo.img" if "kernel-foo" is in BOARD_KERNEL_BINARIES.
-// As a special case, there is a rule to generate "boot.img" if BOARD_KERNEL_BINARIES is empty,
-// or "kernel" is in BOARD_KERNEL_BINARIES.
-func (g *gkiApex) bootImgHasRules(mctx android.EarlyModuleContext) bool {
- kernelNames := mctx.DeviceConfig().BoardKernelBinaries()
- if len(kernelNames) == 0 {
- return proptools.String(g.properties.Product_out_path) == "boot.img"
- }
- for _, kernelName := range kernelNames {
- validBootImagePath := strings.Replace(kernelName, "kernel", "boot", -1) + ".img"
- if proptools.String(g.properties.Product_out_path) == validBootImagePath {
- return true
- }
- }
- return false
-}
-
-// Only generate if this module's kmi_version property is in BOARD_KERNEL_MODULE_INTERFACE_VERSIONS.
-// Otherwise, this board does not support GKI APEXes, so no modules are generated at all.
-// This function also avoids building invalid modules in checkbuild. For example, if these
-// gki_apex modules are defined:
-// gki_apex { name: "boot-kmi-1", kmi_version: "1", product_out_path: "boot.img" }
-// gki_apex { name: "boot-kmi-2", kmi_version: "2", product_out_path: "boot.img" }
-// But a given device's $PRODUCT_OUT/boot.img can only support at most one KMI version.
-// Disable some modules accordingly to make sure checkbuild still works.
-func boardDefinesKmiVersion(mctx android.EarlyModuleContext, kmiVersion string) bool {
- kmiVersions := mctx.DeviceConfig().BoardKernelModuleInterfaceVersions()
- return android.InList(kmiVersion, kmiVersions)
-}
-
-func (g *gkiApex) boardDefinesKmiVersion(mctx android.EarlyModuleContext) bool {
- return boardDefinesKmiVersion(mctx, proptools.String(g.properties.Kmi_version))
-}
-
-// Transform kernel release file in $(in) to KMI version + sublevel.
-// e.g. 5.4.42-android12-0 => name: "com.android.gki.kmi_5_4_android12_0", version: "300000000"
-// Finally, write APEX manifest JSON to $(out).
-func (g *gkiApex) createApexManifestCmd(apexVersion string) string {
- ret := `$(location build_gki_apex_manifest) ` +
- `--kmi_version "` + proptools.String(g.properties.Kmi_version) + `" ` +
- `--apex_manifest $(out) --kernel_release_file $(in)`
- // Override version field if set.
- if apexVersion != "" {
- ret += ` --apex_version ` + apexVersion
- }
- return ret
-}
-
-func (g *gkiApex) DepsMutator(ctx android.BottomUpMutatorContext) {
-}
-
-func (g *gkiApex) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-}
-
-// OTA payload binary is signed with default_system_dev_certificate, which is equivalent to
-// DefaultAppCertificate().
-func getDefaultCertificate(ctx android.EarlyModuleContext) string {
- pem, _ := ctx.Config().DefaultAppCertificate(ctx)
- return strings.TrimSuffix(pem.String(), filepath.Ext(pem.String()))
-}
diff --git a/build/kmi.go b/build/kmi.go
deleted file mode 100644
index cf03cb2..0000000
--- a/build/kmi.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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.
-
-// Minimum support of KMI version in Go. Keep in sync with libkver.
-
-package gki
-
-import (
- "fmt"
- "regexp"
-)
-
-var digits = "([0-9]+)"
-var reKmi = regexp.MustCompile("^([0-9]+)[.]([0-9]+)-(android[0-9]+)-([0-9]+|unstable)$")
-
-// Input is a valid KMI version, e.g. 5.4-android12-0.
-// Return a sanitized string to be used as a suffix of APEX package name
-// com.android.gki.kmi_5_4_android12_0
-// Keep in sync with libkver.
-func kmiVersionToApexName(s string) (string, error) {
- matches := reKmi.FindAllStringSubmatch(s, 4)
-
- if matches == nil {
- return "", fmt.Errorf("Poorly formed KMI version: %q must match regex %q", s, reKmi)
- }
-
- version := matches[0][1]
- patchLevel := matches[0][2]
- androidRelease := matches[0][3]
- kmiGeneration := matches[0][4]
-
- return fmt.Sprintf("com.android.gki.kmi_%s_%s_%s_%s",
- version, patchLevel, androidRelease, kmiGeneration), nil
-}
diff --git a/build/kmi_test.go b/build/kmi_test.go
deleted file mode 100644
index de7642b..0000000
--- a/build/kmi_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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.
-
-// Minimum support of KMI version in Go. Keep in sync with libkver.
-
-package gki
-
-import (
- "testing"
-)
-
-func expectValid(t *testing.T, kmi string, expectedApexName string) {
- t.Helper()
- got, e := kmiVersionToApexName(kmi)
- if e != nil {
- t.Errorf("Expected no error when parsing %q, got %q", kmi, e)
- }
- if got != expectedApexName {
- t.Errorf("Expected kmiVersionToApexName(%q) == %q, got %q", kmi, expectedApexName, got)
- }
-}
-
-func expectInvalid(t *testing.T, kmi string) {
- t.Helper()
- got, e := kmiVersionToApexName(kmi)
- if e == nil {
- t.Errorf("Expected error when parsing %q, got no error with result %q", kmi, got)
- }
-}
-
-func TestParse(t *testing.T) {
- expectInvalid(t, "")
- expectInvalid(t, "foobar")
- expectInvalid(t, "1")
- expectValid(t, "5.4-android12-0", "com.android.gki.kmi_5_4_android12_0")
- expectValid(t, "5.4-android12-42", "com.android.gki.kmi_5_4_android12_42")
-}
diff --git a/build/prebuilt.go b/build/prebuilt.go
deleted file mode 100644
index da8a123..0000000
--- a/build/prebuilt.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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 gki
-
-import (
- "fmt"
- "io"
-
- "android/soong/android"
- "android/soong/apex"
- "github.com/google/blueprint/proptools"
-)
-
-var (
- prebuiltApexTag = dependencyTag{name: "prebuilt_apex"}
-)
-
-type prebuiltGkiApexProperties struct {
- apex.PrebuiltProperties
-
- // Declared KMI version of the boot image. Example: "5.4-android12-0"
- Kmi_version *string
-}
-
-type prebuiltGkiApex struct {
- android.ModuleBase
- properties prebuiltGkiApexProperties
-
- extractedBootImage android.WritablePath
-}
-
-func init() {
- android.RegisterModuleType("prebuilt_gki_apex", prebuiltGkiApexFactory)
-}
-
-// Declare a prebuilt GKI APEX. When installed, the boot image is extracted from
-// the module.
-func prebuiltGkiApexFactory() android.Module {
- g := &prebuiltGkiApex{}
- g.AddProperties(&g.properties)
- android.InitAndroidModule(g)
- android.AddLoadHook(g, func(ctx android.LoadHookContext) { prebuiltGkiApexMutator(ctx, g) })
- return g
-}
-func prebuiltGkiApexMutator(mctx android.LoadHookContext, g *prebuiltGkiApex) {
- // Whether modules should be enabled according to board variables.
- enabled := boardDefinesKmiVersion(mctx, proptools.String(g.properties.Kmi_version))
- if !enabled {
- g.Disable()
- }
-
- // The prebuilt_apex module.
- mctx.CreateModule(apex.PrebuiltFactory, &moduleCommonProperties{
- Name: proptools.StringPtr(g.BaseModuleName()),
- Enabled: proptools.BoolPtr(enabled),
- Product_specific: proptools.BoolPtr(true),
- }, &g.properties.PrebuiltProperties)
-}
-
-// The appeared name of this prebuiltGkiApex object. Exposed to Soong to avoid conflicting with
-// the generated prebuilt_apex module with name BaseModuleName().
-func (g *prebuiltGkiApex) Name() string {
- return g.BaseModuleName() + "_boot_img"
-}
-
-func (g *prebuiltGkiApex) DepsMutator(ctx android.BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), prebuiltApexTag, g.BaseModuleName())
-}
-
-func (g *prebuiltGkiApex) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- var apexFile android.OptionalPath
- ctx.VisitDirectDepsWithTag(prebuiltApexTag, func(m android.Module) {
- if prebuiltApex, ok := m.(*apex.Prebuilt); ok {
- srcFiles, err := prebuiltApex.OutputFiles("")
- if err != nil {
- ctx.ModuleErrorf("Cannot get output files from %q: %s", ctx.OtherModuleName(m), err)
- } else if len(srcFiles) != 1 {
- ctx.ModuleErrorf("%q generated %d files", ctx.OtherModuleName(m), len(srcFiles))
- } else {
- apexFile = android.OptionalPathForPath(srcFiles[0])
- }
- } else {
- ctx.ModuleErrorf("%q is not a prebuilt_apex", ctx.OtherModuleName(m))
- }
- })
- if !apexFile.Valid() {
- ctx.ModuleErrorf("Can't determine the prebuilt APEX file")
- return
- }
-
- genDir := android.PathForModuleOut(ctx, "extracted")
- g.extractedBootImage = genDir.Join(ctx, "boot.img")
-
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- ImplicitOutput(g.extractedBootImage).
- BuiltTool("extract_img_from_apex").
- Flag("--tool").BuiltTool("debugfs").
- Flag("--tool").BuiltTool("delta_generator").
- Input(apexFile.Path()).
- Text(genDir.String())
- rule.Build("extractImgFromApex", "Extract boot image from prebuilt GKI APEX")
-
- ctx.Phony(g.BaseModuleName(), g.extractedBootImage)
-}
-
-func (g *prebuiltGkiApex) AndroidMk() android.AndroidMkData {
- return android.AndroidMkData{
- Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
- fmt.Fprintf(w, "ALL_MODULES.%s.EXTRACTED_BOOT_IMAGE := %s\n", name, g.extractedBootImage)
- },
- }
-}
diff --git a/build/properties.go b/build/properties.go
deleted file mode 100644
index af68446..0000000
--- a/build/properties.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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 gki
-
-type moduleCommonProperties struct {
- Name *string
- Enabled *bool
- Required []string
- Product_specific *bool
-}
-
-type makefileGoalProperties struct {
- Product_out_path *string
-}
-
-type genRuleProperties struct {
- Cmd *string
- Defaults []string
- Out []string
- Srcs []string
- Tools []string
-}
-
-type prebuiltEtcProperties struct {
- Src *string
- Filename_from_src *bool
- Relative_install_path *string
- Installable *bool
-}
-
-type apexProperties struct {
- Apex_name *string
- Manifest *string
- Defaults []string
- Installable *bool
- Prebuilts []string
- Overrides []string
-}
diff --git a/build/raw_img_ota.go b/build/raw_img_ota.go
deleted file mode 100644
index 2f29e2e..0000000
--- a/build/raw_img_ota.go
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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.
-
-// A special genrule that creates OTA payload and payload_properties from a raw
-// image. This rule is created so that the two outputs, payload and
-// payload_properties, can be distinguished with tags.
-
-package gki
-
-import (
- "fmt"
- "sort"
- "strings"
-
- "android/soong/android"
- "android/soong/java"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
-)
-
-type dependencyTag struct {
- blueprint.BaseDependencyTag
- name string
-}
-
-// {"foo": "fooVal", "bar": "barVal"} -> ["${foo}", "${bar}"]
-func keysToVars(deps map[string]string) []string {
- var ret []string
- for dep := range deps {
- ret = append(ret, fmt.Sprintf("${%s}", dep))
- }
- sort.Strings(ret)
- return ret
-}
-
-var (
- certificateTag = dependencyTag{name: "certificate"}
- rawImageTag = dependencyTag{name: "raw_image"}
-
- pctx = android.NewPackageContext("android/gki")
-
- otaFromRawImageDeps = map[string]string{
- "ota_from_raw_image": "ota_from_raw_image",
-
- // Needed by ota_from_target_files
- "brillo_update_payload": "brillo_update_payload",
-
- // Needed by brillo_update_payload
- "delta_generator": "delta_generator",
- // b/171581299: shflags isn't built to the path where HostBinToolVariable
- // points to without explicitly declaring it, even if it is stated as
- // required by brillo_update_payload.
- "shflags": "lib/shflags/shflags",
-
- // Needed by GetBootImageTimestamp
- "lz4": "lz4",
- "toybox": "toybox",
- "unpack_bootimg": "unpack_bootimg",
- }
-
- otaFromRawImageVarDeps = keysToVars(otaFromRawImageDeps)
-
- otaFromRawImageRule = pctx.AndroidStaticRule("ota_from_raw_image", blueprint.RuleParams{
- Command: `${ota_from_raw_image} --tools ` + strings.Join(otaFromRawImageVarDeps, " ") +
- ` ${kwargs} --out ${outDir} -- ${inputArg}`,
- CommandDeps: otaFromRawImageVarDeps,
- Description: "ota_from_raw_image ${outDir}",
- }, "kwargs", "outDir", "inputArg")
-
- // Tags to OutputFiles
- payloadTag = "payload"
- payloadPropertiesTag = "properties"
-)
-
-func init() {
- for dep := range otaFromRawImageDeps {
- pctx.HostBinToolVariable(dep, otaFromRawImageDeps[dep])
- }
- // Intentionally not register this module so that it can only be constructed by gki_apex.
-}
-
-type rawImageOtaProperties struct {
- // The name of a certificate in the default certificate directory, blank to use the default product certificate,
- // or an android_app_certificate module name in the form ":module".
- Certificate *string
-
- // A set of images and their related modules. Must be in this form
- // IMAGE_NAME:MODULE, where IMAGE_NAME is an image name like "boot", and
- // MODULE is the name of a makefile_goal.
- Image_goals []string
-}
-
-type rawImageOta struct {
- android.ModuleBase
- properties rawImageOtaProperties
-
- pem android.Path
- key android.Path
-
- outPayload android.WritablePath
- outProperties android.WritablePath
-}
-
-// Declare a rule that generates a signed OTA payload from a raw image. This
-// includes payload.bin and payload_properties.txt.
-func rawImageOtaFactory() android.Module {
- r := &rawImageOta{}
- r.AddProperties(&r.properties)
- android.InitAndroidModule(r)
- return r
-}
-
-func (r *rawImageOta) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "":
- return android.Paths{r.outPayload, r.outProperties}, nil
- case payloadTag:
- return android.Paths{r.outPayload}, nil
- case payloadPropertiesTag:
- return android.Paths{r.outProperties}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
-}
-
-var _ android.OutputFileProducer = (*rawImageOta)(nil)
-
-func (r *rawImageOta) getCertString(ctx android.BaseModuleContext) string {
- moduleName := ctx.ModuleName()
- certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(moduleName)
- if overridden {
- return ":" + certificate
- }
- return proptools.String(r.properties.Certificate)
-}
-
-// Returns module->image_name mapping, e.g. "bootimage_soong"->"boot"
-func (r *rawImageOta) goalToImage(ctx android.EarlyModuleContext) map[string]string {
- ret := map[string]string{}
- for _, imageGoal := range r.properties.Image_goals {
- lst := strings.Split(imageGoal, ":")
- if len(lst) != 2 {
- ctx.PropertyErrorf("image_goals", "Must be in the form IMAGE_NAME:MODULE")
- return map[string]string{}
- }
- ret[lst[1]] = lst[0]
- }
- return ret
-}
-
-func (r *rawImageOta) DepsMutator(ctx android.BottomUpMutatorContext) {
- // Add dependency to modules in image_goals
- for module, _ := range r.goalToImage(ctx) {
- ctx.AddVariationDependencies(nil, rawImageTag, module)
- }
- // Add dependency to certificate module, if any.
- cert := android.SrcIsModule(r.getCertString(ctx))
- if cert != "" {
- ctx.AddVariationDependencies(nil, certificateTag, cert)
- }
-}
-
-func (r *rawImageOta) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- inputArg := []string{}
- kwargs := []string{}
- implicits := android.Paths{}
-
- // Handle image_goals
- goalToImage := r.goalToImage(ctx)
- ctx.VisitDirectDepsWithTag(rawImageTag, func(module android.Module) {
- depName := ctx.OtherModuleName(module)
- imgPath := android.OutputFileForModule(ctx, module, "")
- if imgPath != nil {
- implicits = append(implicits, imgPath)
- inputArg = append(inputArg, goalToImage[depName]+":"+imgPath.String())
- } else {
- ctx.ModuleErrorf("image dependency %q does not generate any output", depName)
- }
- })
-
- // Handle certificate
- ctx.VisitDirectDepsWithTag(certificateTag, func(module android.Module) {
- depName := ctx.OtherModuleName(module)
- if cert, ok := module.(*java.AndroidAppCertificate); ok {
- r.pem = cert.Certificate.Pem
- r.key = cert.Certificate.Key
- } else {
- ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
- }
- })
- r.setCertificateAndPrivateKey(ctx)
- keyName, keyError := removeCertExt(r.pem)
- if keyError != nil {
- ctx.ModuleErrorf("Cannot get certificate to sign the OTA payload binary: " + keyError.Error())
- }
- implicits = append(implicits, r.pem, r.key)
- kwargs = append(kwargs, "--key "+proptools.String(keyName))
-
- // Set outputs
- outDir := android.PathForModuleGen(ctx, "payload_files")
- r.outPayload = outDir.Join(ctx, "payload.bin")
- r.outProperties = outDir.Join(ctx, "payload_properties.txt")
-
- ctx.Build(pctx, android.BuildParams{
- Rule: otaFromRawImageRule,
- Description: "Generate OTA from raw image",
- Implicits: implicits,
- Outputs: android.WritablePaths{r.outPayload, r.outProperties},
- Args: map[string]string{
- "kwargs": strings.Join(kwargs, " "),
- "outDir": outDir.String(),
- "inputArg": strings.Join(inputArg, " "),
- },
- })
-}
-
-func (r *rawImageOta) setCertificateAndPrivateKey(ctx android.ModuleContext) {
- if r.pem == nil {
- cert := proptools.String(r.properties.Certificate)
- if cert == "" {
- pem, key := ctx.Config().DefaultAppCertificate(ctx)
- r.pem = pem
- r.key = key
- } else {
- defaultDir := ctx.Config().DefaultAppCertificateDir(ctx)
- r.pem = defaultDir.Join(ctx, cert+".x509.pem")
- r.key = defaultDir.Join(ctx, cert+".pk8")
- }
- }
-}
-
-func removeCertExt(path android.Path) (*string, error) {
- s := path.String()
- if strings.HasSuffix(s, ".x509.pem") {
- return proptools.StringPtr(strings.TrimSuffix(s, ".x509.pem")), nil
- }
- return nil, fmt.Errorf("Path %q does not end with .x509.pem", s)
-}
diff --git a/build_gki_apex_manifest.cpp b/build_gki_apex_manifest.cpp
deleted file mode 100644
index 3e6a878..0000000
--- a/build_gki_apex_manifest.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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.
-//
-
-#include <sysexits.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <gflags/gflags.h>
-#include <json/json.h>
-#include <kver/kernel_release.h>
-#include <kver/kmi_version.h>
-#include <kver/utils.h>
-
-using android::kver::GetFactoryApexVersion;
-using android::kver::KernelRelease;
-using android::kver::KmiVersion;
-
-static constexpr uint64_t UNSTABLE_GENERATION = UINT64_MAX;
-
-namespace {
-
-int CheckKmi(const KernelRelease& kernel_release, const KmiVersion& kmi_version) {
- const auto& actual_kmi_version = kernel_release.kmi_version();
- if (actual_kmi_version == kmi_version) {
- return EX_OK;
- }
- if (kmi_version.generation() == UNSTABLE_GENERATION &&
- kmi_version.version() == actual_kmi_version.version() &&
- kmi_version.patch_level() == actual_kmi_version.patch_level() &&
- kmi_version.android_release() == actual_kmi_version.android_release()) {
- LOG(WARNING) << "Actual KMI version " << actual_kmi_version.string()
- << " matches unstable KMI version";
- return EX_OK;
- }
- LOG(ERROR) << "KMI version does not match. Actual: " << actual_kmi_version.string()
- << ", expected: " << kmi_version.string();
- return EX_SOFTWARE;
-}
-
-int WriteApexManifest(const std::string& apex_name, Json::UInt64 apex_version,
- const std::string& out_file) {
- Json::Value root;
- root["name"] = apex_name;
- root["version"] = apex_version;
- root["preInstallHook"] = "bin/com.android.gki.preinstall";
- Json::StreamWriterBuilder factory;
- std::string json_string = Json::writeString(factory, root);
- if (!android::base::WriteStringToFile(json_string, out_file)) {
- PLOG(ERROR) << "Cannot write to " << out_file;
- return EX_SOFTWARE;
- }
- return EX_OK;
-}
-
-} // namespace
-
-DEFINE_string(kernel_release_file, "",
- "Input file that contains a kernel release string parsed from the boot image. "
- "Exactly one of --kernel_release_file or --factory must be set.");
-DEFINE_bool(factory, false,
- "Set to true for factory APEX package. Exactly one of --kernel_release_file or "
- "--factory must be set.");
-DEFINE_string(kmi_version, "", "Declared KMI version for this APEX.");
-DEFINE_string(apex_manifest, "", "Output APEX manifest JSON file.");
-DEFINE_uint64(apex_version, GetFactoryApexVersion(),
- "Override APEX version in APEX manifest. Use factory APEX version if unspecified.");
-
-int main(int argc, char** argv) {
- gflags::ParseCommandLineFlags(&argc, &argv, true);
-
- if (FLAGS_kmi_version.empty()) {
- LOG(ERROR) << "--kmi_version must be set.";
- return EX_SOFTWARE;
- }
- std::string_view kmi_version_sv(FLAGS_kmi_version);
- std::string kmi_version_string;
- if (android::base::ConsumeSuffix(&kmi_version_sv, "unstable")) {
- kmi_version_string = std::string(kmi_version_sv) + std::to_string(UNSTABLE_GENERATION);
- } else {
- kmi_version_string = kmi_version_sv;
- }
- auto kmi_version = KmiVersion::Parse(kmi_version_string);
- if (!kmi_version.has_value()) {
- LOG(ERROR) << "--kmi_version is not a valid KMI version.";
- return EX_SOFTWARE;
- }
-
- if (FLAGS_factory + (!FLAGS_kernel_release_file.empty()) != 1) {
- LOG(ERROR) << "Exactly one of --kernel_release_file or --factory must be set.";
- return EX_SOFTWARE;
- }
-
- if (!FLAGS_kernel_release_file.empty()) {
- std::string kernel_release_string;
- if (!android::base::ReadFileToString(FLAGS_kernel_release_file, &kernel_release_string)) {
- PLOG(ERROR) << "Cannot read " << FLAGS_kernel_release_file;
- return EX_SOFTWARE;
- }
- auto kernel_release = KernelRelease::Parse(kernel_release_string, true /* allow_suffix */);
- if (!kernel_release.has_value()) {
- LOG(ERROR) << kernel_release_string << " is not a valid GKI kernel release string";
- return EX_SOFTWARE;
- }
- int res = CheckKmi(*kernel_release, *kmi_version);
- if (res != EX_OK) return res;
- }
-
- std::string apex_name = GetApexName(*kmi_version);
- uint64_t apex_version = FLAGS_apex_version;
-
- if (FLAGS_apex_manifest.empty()) {
- LOG(WARNING) << "Skip writing APEX manifest because --apex_manifest is not set.";
- } else {
- int res = WriteApexManifest(apex_name, apex_version, FLAGS_apex_manifest);
- if (res != EX_OK) return res;
- }
-
- return EX_OK;
-}
diff --git a/com.android.gki.avbpubkey b/com.android.gki.avbpubkey
deleted file mode 100644
index 166d37e..0000000
--- a/com.android.gki.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/com.android.gki.pem b/com.android.gki.pem
deleted file mode 100644
index fd85678..0000000
--- a/com.android.gki.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/download_boot_prebuilt.py b/download_boot_prebuilt.py
deleted file mode 100755
index bd665d7..0000000
--- a/download_boot_prebuilt.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2019-2020 The Android Open Source Project
-#
-# 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.
-#
-
-import argparse
-import collections
-import functools
-import glob
-import json
-import logging
-import os
-import pathlib
-import re
-import shlex
-import shutil
-import subprocess
-import sys
-import tempfile
-import urllib.request
-
-from concurrent import futures
-from pathlib import Path
-
-BASE_URL = "https://ci.android.com/builds/submitted/{build_id}/{target}/latest/raw"
-SUPPORTED_ARCHS = ["arm64"]
-VARIANTS = ["userdebug"]
-BOOT_PREBUILT_REL_DIR = "packages/modules/BootPrebuilt"
-ANDROID_BUILD_TOP = os.environ["ANDROID_BUILD_TOP"]
-
-logger = logging.getLogger(__name__)
-logging.basicConfig(level=logging.INFO)
-
-def parse_args():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "build_id",
- type=int,
- help="the build id to download the build for, e.g. 6148204")
- parser.add_argument(
- "--bug",
- type=str,
- default=None,
- help="optional bug number for git commit.")
-
- return parser.parse_args()
-
-
-def download_file(url, dest_filename):
- logger.info("Downloading %s -> %s", url, dest_filename)
- urllib.request.urlretrieve(url, dest_filename)
-
-
-def get_artifact_download_spec(build_id, device, variant, dest_dir):
- target = "{}-{}".format(device, variant)
- url_base = BASE_URL.format(build_id=build_id, target=target)
- filename = "{}-img-{}.zip".format(device, build_id)
- url = os.path.join(url_base, filename)
- dest_filename = os.path.join(dest_dir, filename)
- return url, dest_filename
-
-
-def update_prebuilt(build_id, boot_prebuilt, ver, arch, variant, bug):
- device = "aosp_" + arch
- arch_dir = os.path.join(boot_prebuilt, ver, arch)
- variant_dir = os.path.join(arch_dir, variant)
- boot_img_name = "boot-{}.img".format(ver)
- stored_img_name = "boot-{}.img".format(variant)
- try:
- subprocess.check_call(["repo", "start", "boot-prebuilt-{}".format(build_id)], cwd=arch_dir)
-
- os.makedirs(variant_dir)
- url, dest_filename = get_artifact_download_spec(build_id, device, variant, variant_dir)
- download_file(url, dest_filename)
- args = ["unzip", "-d", variant_dir, dest_filename, boot_img_name]
- logger.info("Calling: %s", " ".join(args))
- subprocess.check_call(args)
- shutil.move(os.path.join(variant_dir, boot_img_name), os.path.join(arch_dir, stored_img_name))
-
- finally:
- shutil.rmtree(variant_dir)
-
- message = """Update prebuilts to {build_id}.
-
-Test: Treehugger
-Bug: {bug}
-""".format(build_id=build_id, bug=bug or "N/A")
-
- logger.info("Creating commit for %s", arch_dir)
- subprocess.check_call(["git", "add", "."], cwd=arch_dir)
- subprocess.check_call(["git", "commit", "-m", message], cwd=arch_dir)
-
-
-def main():
- args = parse_args()
- with futures.ThreadPoolExecutor(max_workers=10) as pool:
- fs = []
- boot_prebuilt = os.path.join(ANDROID_BUILD_TOP, BOOT_PREBUILT_REL_DIR)
- for ver in os.listdir(boot_prebuilt):
- if not re.match(r'\d+[.]\d+', ver):
- continue
- for arch in os.listdir(os.path.join(boot_prebuilt, ver)):
- if arch not in SUPPORTED_ARCHS:
- continue
- for variant in VARIANTS:
- fs.append((ver, arch, pool.submit(update_prebuilt, args.build_id, boot_prebuilt, ver,
- arch, variant, args.bug)))
-
- futures.wait([f for ver, arch, f in fs])
- success_dirs = []
- logger.info("===============")
- logger.info("Summary:")
- for ver, arch, future in fs:
- if future.exception():
- logger.error("%s/%s: %s", ver, arch, future.exception())
- else:
- logger.info("%s/%s: Updated.", ver, arch)
- success_dirs.append(os.path.join(BOOT_PREBUILT_REL_DIR, ver, arch))
-
- if success_dirs:
- args = ["repo", "upload", "--verify", "--hashtag-branch", "--br",
- "boot-prebuilt-{}".format(args.build_id)] + success_dirs
- logger.info(" ".join(args))
- subprocess.check_call(args, cwd=ANDROID_BUILD_TOP)
-
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/extract_img_from_apex.py b/extract_img_from_apex.py
deleted file mode 100644
index 12eb987..0000000
--- a/extract_img_from_apex.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (C) 2020 The Android Open Source Project
-#
-# 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.
-
-"""
-Extract boot.img from a GKI APEX.
-
-Usage: extract_img_from_apex [--tool host_tool [--tool ...]] \
- input_gki.apex out_dir
-"""
-
-import logging
-import os
-import sys
-
-import common
-
-APEX_PAYLOAD_FILE = "apex_payload.img"
-APEX_PAYLOAD_BIN_PATH = "/etc/ota/payload.bin"
-
-logger = logging.getLogger(__name__)
-OPTIONS = common.OPTIONS
-
-
-def ExtractImagesFromApex(apex, out_dir):
- if not os.path.isdir(out_dir):
- os.makedirs(out_dir)
- apex_dir = common.UnzipTemp(apex, [APEX_PAYLOAD_FILE])
- apex_payload = os.path.join(apex_dir, APEX_PAYLOAD_FILE)
-
- payload_bin = common.MakeTempFile("payload_", ".bin")
- debugfs_command = ['debugfs', '-R', "dump {} {}".format(
- APEX_PAYLOAD_BIN_PATH, payload_bin), apex_payload]
-
- common.RunAndCheckOutput(debugfs_command)
- assert os.path.getsize(payload_bin) > 0, payload_bin + " is an empty file!"
-
- boot_img = os.path.join(out_dir, 'boot.img')
- with open(boot_img, 'w') as _:
- pass
-
- delta_generator_command = [
- 'delta_generator',
- '--is_partial_update=true',
- '--in_file=' + payload_bin,
- '--partition_names=boot',
- '--new_partitions=' + boot_img
- ]
- common.RunAndCheckOutput(delta_generator_command)
-
-
-def main(argv):
- def option_handler(o, a):
- if o == "--tool":
- name = os.path.basename(a)
- common.SetHostToolLocation(name, a)
- else:
- return False
- return True
-
- args = common.ParseOptions(
- argv, __doc__,
- extra_long_opts=["tool="],
- extra_option_handler=option_handler)
-
- if len(args) != 2:
- common.Usage(__doc__)
- sys.exit(1)
-
- common.InitLogging()
-
- ExtractImagesFromApex(args[0], args[1])
- logger.info("done.")
-
-
-if __name__ == '__main__':
- try:
- common.CloseInheritedPipes()
- main(sys.argv[1:])
- except common.ExternalError:
- logger.exception("\n ERROR:\n")
- sys.exit(1)
- finally:
- common.Cleanup()
diff --git a/ota_from_raw_image.py b/ota_from_raw_image.py
deleted file mode 100644
index acd0697..0000000
--- a/ota_from_raw_image.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright (C) 2020 The Android Open Source Project
-#
-# 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.
-
-"""
-Generate payload.bin from a single image.
-"""
-
-import argparse
-import logging
-import os
-import re
-import shutil
-import sys
-from zipfile import ZipFile
-
-import common
-from ota_from_target_files import (Payload, PayloadSigner)
-
-logger = logging.getLogger(__name__)
-OPTIONS = common.OPTIONS
-
-
-def _ParseArgs():
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--tools", metavar="PATH", type=str, nargs="*",
- help="A list of real paths of tools that this script depends on.")
- parser.add_argument("--key", type=str,
- help="Key to use to sign the package. If unspecified, script does not sign "
- "the package and payload_properties.txt is not generated.")
- parser.add_argument("--out", type=str, required=True,
- help="Required output directory to payload.bin and payload_properties.txt")
- parser.add_argument("input", metavar="NAME:IMAGE", nargs="+",
- help="Name of the image and path to the image, e.g. boot:path/to/boot.img")
- args = parser.parse_args()
-
- return args
-
-
-def _PrepareEnvironment(args):
- common.InitLogging()
- if not args.tools:
- return
- for path in args.tools:
- name = os.path.basename(path)
- # Use absolute path because GetBootImageTimestamp changes cwd when running some tools.
- common.SetHostToolLocation(name, os.path.abspath(path))
- # brillo_update_payload is a shell script that depends on this environment variable.
- if name == "delta_generator":
- os.environ["GENERATOR"] = path
-
-
-def CreateOtaFromRawImages(args):
- _PrepareEnvironment(args)
-
- tf = common.MakeTempFile("target_files", ".zip")
- payload_additional_args = ["--is_partial_update", "true"]
- with ZipFile(tf, "w") as zip:
- names = []
- for pair_str in args.input:
- pair = pair_str.split(":")
- assert len(pair) == 2, "Incorrect format: " + pair_str
- name, img_path = tuple(pair)
- zip.write(img_path, arcname=os.path.join("IMAGES", name + ".img"))
- names.append(name)
- if name == "boot":
- timestamp = common.GetBootImageTimestamp(img_path)
- assert timestamp is not None, "Cannot extract timestamp from boot image"
- payload_additional_args += ["--partition_timestamps",
- "boot:" + str(timestamp)]
-
- zip.writestr("META/ab_partitions.txt", "\n".join(names) + "\n")
- zip.writestr("META/dynamic_partitions_info.txt", """
-virtual_ab=true
-super_partition_groups=
- """)
-
- payload = Payload()
- payload.Generate(tf, None, payload_additional_args)
-
- if args.key:
- OPTIONS.package_key = args.key
- OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
- payload_signer = PayloadSigner()
- payload.Sign(payload_signer)
-
- shutil.copy(payload.payload_file, os.path.join(args.out, "payload.bin"))
- if payload.payload_properties:
- shutil.copy(payload.payload_properties, os.path.join(args.out, "payload_properties.txt"))
-
-
-if __name__ == "__main__":
- try:
- common.CloseInheritedPipes()
- args = _ParseArgs()
- CreateOtaFromRawImages(args)
- except common.ExternalError:
- logger.exception("\n ERROR:\n")
- sys.exit(1)
- finally:
- common.Cleanup()
diff --git a/preinstall.sh b/preinstall.sh
deleted file mode 100644
index fbd16e1..0000000
--- a/preinstall.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/system/bin/sh
-
-# sleep_exit [<exit_code>]
-function sleep_exit() {
- # Sleep before exit to ensure logs flushes.
- sleep 5s
- exit $@
-}
-
-# log_gki <priority> <message>
-function log_gki() {
- log -t gki -p $@
-}
-
-log_gki i "GKI APEX preinstall hook starting."
-
-mydir=$(dirname $(dirname $(realpath "$0")))
-if [[ $(dirname $mydir) != "/apex" ]] || [[ $(basename $mydir) != com.android.gki.* ]]; then
- log_gki e "This script must be installed under /apex/com.android.gki.*"
- sleep_exit 1
-fi
-
-# The pre-installed APEX does not contain any OTA payload. Just skip installing anything.
-if [[ ! -f ${mydir}/etc/ota/payload.bin ]]; then
- log_gki e "No payload.bin found."
- sleep_exit 1
-fi
-
-log_gki i "Applying payload.";
-
-if ! ${mydir}/bin/update_engine_stable_client \
- --payload ${mydir}/etc/ota/payload.bin \
- --headers "$(cat ${mydir}/etc/ota/payload_properties.txt)"; then
- log_gki e "OTA failed"
- sleep_exit 1
-fi
-
-log_gki i "OTA successful"
-sleep_exit 0
diff --git a/test/Android.bp b/test/Android.bp
deleted file mode 100644
index 483b6d9..0000000
--- a/test/Android.bp
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// 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.
-
-// A list of names of test APEXes for GkiInstallTest to instantiate test cases.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-genrule {
- name: "gki_install_test_file_list",
- srcs: [":gki_install_test_files"],
- out: ["gki_install_test_file_list.txt"],
- cmd: "for file in $(in); do basename $${file} >> $(out); done",
-}
-
-java_test_host {
- name: "GkiInstallTest",
- srcs: [
- "src/**/*.java",
- ":gki_install_test_file_list",
- ],
- test_suites: [
- "device-tests",
- ],
- libs: [
- "compatibility-tradefed",
- "tradefed",
- ],
- static_libs: [
- "cts-host-utils",
- "hamcrest-library",
- ],
- data: [":gki_install_test_files"],
- java_resources: [":gki_install_test_file_list"],
-}
-
-// Prebuilts
-
-prebuilt_gki_apex {
- name: "com.android.gki.kmi_5_4_android12_0_test_prebuilt",
- installable: false,
- kmi_version: "5.4-android12-0",
- src: "com.android.gki.kmi_5_4_android12_0_test_prebuilt.apex",
-}
diff --git a/test/AndroidTest.xml b/test/AndroidTest.xml
deleted file mode 100644
index 5eceeb2..0000000
--- a/test/AndroidTest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- 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.
--->
-
-<configuration description="GKI Install test">
- <test class="com.android.tradefed.testtype.HostTest" >
- <option name="jar" value="GkiInstallTest.jar" />
- </test>
-</configuration>
diff --git a/test/com.android.gki.kmi_5_4_android12_0_test_prebuilt.apex b/test/com.android.gki.kmi_5_4_android12_0_test_prebuilt.apex
deleted file mode 100644
index 1c01dd9..0000000
--- a/test/com.android.gki.kmi_5_4_android12_0_test_prebuilt.apex
+++ /dev/null
Binary files differ
diff --git a/test/src/com/android/gki/tests/GkiInstallTest.java b/test/src/com/android/gki/tests/GkiInstallTest.java
deleted file mode 100644
index 0b00ba6..0000000
--- a/test/src/com/android/gki/tests/GkiInstallTest.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * 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 com.android.gki.tests;
-
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.either;
-import static org.hamcrest.Matchers.everyItem;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.isIn;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.io.FileMatchers.aFileWithSize;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeThat;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
-
-import static java.util.stream.Collectors.toList;
-
-import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
-import android.cts.host.utils.DeviceJUnit4Parameterized;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.ITestDevice.ApexInfo;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-import org.junit.runners.Parameterized.UseParametersRunnerFactory;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.Scanner;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-@RunWith(DeviceJUnit4Parameterized.class)
-@UseParametersRunnerFactory(DeviceJUnit4ClassRunnerWithParameters.RunnerFactory.class)
-public class GkiInstallTest extends BaseHostJUnit4Test {
-
- // Keep in sync with gki.go.
- private static final String HIGH_SUFFIX = "_test_high.apex";
- private static final String LOW_SUFFIX = "_test_low.apex";
- private static final long TEST_HIGH_VERSION = 1000000000L;
-
- // Timeout between device online for adb commands and boot completed flag is set.
- private static final long DEVICE_AVAIL_TIMEOUT_MS = 180000; // 3mins
- // Timeout for `adb install`.
- private static final long INSTALL_TIMEOUT_MS = 600000; // 10mins
-
- @Parameter
- public String mFileName;
-
- private String mPackageName;
- private File mApexFile;
- private boolean mExpectInstallSuccess;
- private final Set<String> mOverlayfs = new HashSet();
-
- @Parameters(name = "{0}")
- public static Iterable<String> getTestFileNames() {
- try (Scanner scanner = new Scanner(
- GkiInstallTest.class.getClassLoader().getResourceAsStream(
- "gki_install_test_file_list.txt"))) {
- List<String> list = new ArrayList<>();
- scanner.forEachRemaining(list::add);
- return list;
- }
- }
-
- @Before
- public void setUp() throws Exception {
- inferPackageName();
- skipTestIfPackageNotInstalled();
- skipTestIfWrongKernelVersion();
- findTestApexFile();
- prepareOverlayfs();
- }
-
- /** Set mPackageName and mExpectInstallSuccess according to mFileName. */
- private void inferPackageName() throws Exception {
- if (mFileName.endsWith(HIGH_SUFFIX)) {
- mPackageName = mFileName.substring(0, mFileName.length() - HIGH_SUFFIX.length());
- mExpectInstallSuccess = true;
- } else if (mFileName.endsWith(LOW_SUFFIX)) {
- mPackageName = mFileName.substring(0, mFileName.length() - LOW_SUFFIX.length());
- mExpectInstallSuccess = false;
- } else {
- fail("Unrecognized test data file: " + mFileName);
- }
- }
-
- /** Skip the test if mPackageName is not installed on the device. */
- private void skipTestIfPackageNotInstalled() throws Exception {
- CLog.i("Wait for device to be available for %d ms...", DEVICE_AVAIL_TIMEOUT_MS);
- getDevice().waitForDeviceAvailable(DEVICE_AVAIL_TIMEOUT_MS);
- CLog.i("Device is available after %d ms", DEVICE_AVAIL_TIMEOUT_MS);
-
- // Skip if the device does not support this APEX package.
- CLog.i("Checking if %s is installed on the device.", mPackageName);
- ApexInfo oldApexInfo = getApexInfo(getDevice(), mPackageName);
- assumeThat(oldApexInfo, is(notNullValue()));
- assumeThat(oldApexInfo.name, is(mPackageName));
- }
-
- /**
- * Skip the test if APEX package name does not match kernel version.
- *
- * Due to b/186566367, on mixed builds, the wrong GKI APEX may be installed. In that case, just
- * skip the test.
- *
- * As an exception, the package may contain "unstable" as the generation. When this is the
- * case, any generation number in kernel release is considered a match.
- *
- * @throws Exception
- */
- private void skipTestIfWrongKernelVersion() throws Exception {
- Pattern packagePattern = Pattern.compile(
- "^com\\.android\\.gki\\.kmi_(?<w>\\d+)_(?<x>\\d+)_(?<z>android\\d+)_" +
- "(?<k>\\d+|unstable)$");
- Matcher packageMatcher = packagePattern.matcher(mPackageName);
- assertTrue(packageMatcher.matches());
-
- Pattern kernelPattern = Pattern.compile(
- "^Linux version (?<fullrel>(?<w>\\d+)\\.(?<x>\\d+)\\.(?<y>\\d+)-(?<z>android\\d+)"
- + "-(?<k>\\d+))");
- String kernel = getDevice().executeShellCommand("cat /proc/version");
- Matcher kernelMatcher = kernelPattern.matcher(kernel);
- assumeTrue("Not GKI: " + kernel, kernelMatcher.find());
-
- String desc = String.format("package %s vs kernel release %s", mPackageName,
- kernelMatcher.group("fullrel"));
-
- CLog.i("Checking: %s", desc);
-
- assumeThat(desc, packageMatcher.group("w"), is(kernelMatcher.group("w")));
- assumeThat(desc, packageMatcher.group("x"), is(kernelMatcher.group("x")));
- assumeThat(desc, packageMatcher.group("z"), is(kernelMatcher.group("z")));
- assumeThat(desc, packageMatcher.group("k"),
- anyOf(is("unstable"), is(kernelMatcher.group("k"))));
- }
-
- /** Find the corresponding APEX test file with mFileName. */
- private void findTestApexFile() throws Exception {
- // Find the APEX file.
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
- mApexFile = buildHelper.getTestFile(mFileName);
-
- // There may be empty .apex files in the directory for disabled APEXes. But if the device
- // is known to install the package, the test must be built with non-empty APEXes for this
- // particular package.
- assertThat("Test is not built properly. It does not contain a non-empty " + mFileName,
- mApexFile, is(aFileWithSize(greaterThan(0L))));
- }
-
- /**
- * Record what partitions have overlayfs set up. Then, tear down overlayfs because it may
- * make OTA fail.
- *
- * Usually, the test does not require root to run, but if the device has overlayfs set up,
- * the test assumes that the device has root functionality, and attempts to tear down
- * overlayfs before the test starts.
- * Note that this function immediately reboots after enabling adb root to ensure the test runs
- * with the same permission before it is called.
- */
- private void prepareOverlayfs() throws Exception {
- mOverlayfs.addAll(getOverlayfsState(getDevice()));
-
- if (!mOverlayfs.isEmpty()) {
- getDevice().enableAdbRoot();
- getDevice().executeAdbCommand("enable-verity");
- rebootUntilAvailable(getDevice(), DEVICE_AVAIL_TIMEOUT_MS);
- }
- }
-
- @Test
- public void testInstallAndReboot() throws Exception {
- CLog.i("Installing %s with %d ms timeout", mApexFile, INSTALL_TIMEOUT_MS);
- String result = getDevice().installPackage(mApexFile, false,
- "--staged-ready-timeout", String.valueOf(INSTALL_TIMEOUT_MS));
- if (!mExpectInstallSuccess) {
- assertNotNull("Should not be able to install downgrade package", result);
- assertThat(result, either(containsString("Downgrade of APEX package " + mPackageName
- + " is not allowed.")).or(containsString("INSTALL_FAILED_VERSION_DOWNGRADE")));
- return;
- }
-
- assertNull("Installation failed with " + result, result);
- rebootUntilAvailable(getDevice(), DEVICE_AVAIL_TIMEOUT_MS);
-
- ApexInfo newApexInfo = getApexInfo(getDevice(), mPackageName);
- assertNotNull(newApexInfo);
- assertThat(newApexInfo.versionCode, is(TEST_HIGH_VERSION));
- }
-
- /**
- * Restore overlayfs on partitions.
- *
- * Usually, tearDown() does not require root to run, but if the device had overlayfs set up
- * before the test has started,
- * the test assumes that the device has root functionality, and attempts to re-set up
- * overlayfs after the test ends.
- * Note that tearDown() immediately reboots after enabling adb root to ensure the test ends up
- * with the same permission before the test has started.
- */
- @After
- public void tearDown() throws Exception {
- // Restore overlayfs for partitions that the test knows of.
- CLog.i("Test ends, now restoring overlayfs partitions %s.", mOverlayfs);
- if (mOverlayfs.contains("system")) {
- getDevice().enableAdbRoot();
- getDevice().remountSystemWritable();
- }
- if (mOverlayfs.contains("vendor")) {
- getDevice().enableAdbRoot();
- getDevice().remountVendorWritable();
- }
- CLog.i("Restoring overlayfs partition ends, now rebooting.");
-
- // Reboot device no matter what to avoid interference.
- rebootUntilAvailable(getDevice(), DEVICE_AVAIL_TIMEOUT_MS);
-
- // remount*Writable should have enabled overlayfs for all necessary partitions. If not,
- // throw an error.
- Set<String> newOverlayfsState = getOverlayfsState(getDevice());
- assertThat("Some partitions did not restore overlayfs properly. Before test: " + mOverlayfs
- + ", after test: " + newOverlayfsState, mOverlayfs,
- everyItem(isIn(newOverlayfsState)));
- CLog.i("All overlayfs states are restored.");
- }
-
- /**
- * @param device the device under test
- * @param packageName the package name to look for
- * @return The {@link ApexInfo} of the APEX named {@code packageName} on the
- * {@code device}, or {@code null} if the device does not have the APEX installed.
- * @throws Exception an error has occurred.
- */
- private static ApexInfo getApexInfo(ITestDevice device, String packageName)
- throws Exception {
- assertNotNull(packageName);
- List<ApexInfo> list = device.getActiveApexes().stream().filter(
- apexInfo -> packageName.equals(apexInfo.name)).collect(toList());
- if (list.isEmpty()) return null;
- assertThat(list.size(), is(1));
- return list.get(0);
- }
-
- /**
- * Similar to device.reboot(), but with a timeout on waitForDeviceAvailable. Note that
- * the timeout does not include the rebootUntilOnline() call.
- *
- * @param device the device under test
- * @param timeoutMs timeout for waitForDeviceAvailable() call
- * @throws Exception an error has occurred.
- */
- private static void rebootUntilAvailable(ITestDevice device, long timeoutMs)
- throws Exception {
- CLog.i("Reboot and waiting for device to be online");
- device.rebootUntilOnline();
- CLog.i("Device online, wait for device to be available for %d ms...", timeoutMs);
- device.waitForDeviceAvailable(timeoutMs);
- CLog.i("Device is available after %d ms", timeoutMs);
- }
-
- /**
- * Get all partitions that have overlayfs setup. Parse /proc/mounts and if it finds lines like:
- * {@code overlayfs /vendor ...}, then put {@code vendor} in the returned set.
- * @param device the device under test
- * @return a list of partitions like {@code system}, {@code vendor} that has overlayfs set up
- * @throws Exception an error has occurred.
- */
- private static Set<String> getOverlayfsState(ITestDevice device) throws Exception {
- Set<String> ret = new HashSet();
- File mounts = device.pullFile("/proc/mounts");
- try (Scanner scanner = new Scanner(mounts)) {
- while (scanner.hasNextLine()) {
- String line = scanner.nextLine();
- String[] tokens = line.split("\\s");
- if (tokens.length < 2) continue;
- if (!"overlay".equals(tokens[0])) continue;
- Path path = Paths.get(tokens[1]);
- if (path.getNameCount() == 0) continue;
- ret.add(path.getName(0).toString());
- }
- }
- CLog.i("Device has overlayfs set up on partitions %s", ret);
- return ret;
- }
-}