From d558c7775580a1d512692882b31a0f83cf47e787 Mon Sep 17 00:00:00 2001 From: cfig Date: Thu, 20 Jul 2023 13:27:36 +0800 Subject: [PATCH] apex: ApexBuildInfo.pb ApexManifest.pb --- .../android/apex/ApexBuildInfoDataClass.kt | 63 ++++++++++ .../com/android/apex/ApexManifestDataClass.kt | 108 ++++++++++++++++++ .../apex/ApexBuildInfoDataClassTest.kt | 25 ++++ .../android/apex/ApexManifestDataClassTest.kt | 25 ++++ .../src/test/resources/apex_build_info.pb | 16 +++ bbootimg/src/test/resources/apex_manifest.pb | 3 + 6 files changed, 240 insertions(+) create mode 100644 bbootimg/src/main/java/com/android/apex/ApexBuildInfoDataClass.kt create mode 100644 bbootimg/src/main/java/com/android/apex/ApexManifestDataClass.kt create mode 100644 bbootimg/src/test/kotlin/com/android/apex/ApexBuildInfoDataClassTest.kt create mode 100644 bbootimg/src/test/kotlin/com/android/apex/ApexManifestDataClassTest.kt create mode 100644 bbootimg/src/test/resources/apex_build_info.pb create mode 100644 bbootimg/src/test/resources/apex_manifest.pb diff --git a/bbootimg/src/main/java/com/android/apex/ApexBuildInfoDataClass.kt b/bbootimg/src/main/java/com/android/apex/ApexBuildInfoDataClass.kt new file mode 100644 index 0000000..2df68c3 --- /dev/null +++ b/bbootimg/src/main/java/com/android/apex/ApexBuildInfoDataClass.kt @@ -0,0 +1,63 @@ +package com.android.apex + +import com.android.apex.ApexBuildInfoOuterClass.ApexBuildInfo +import com.google.protobuf.ByteString +import java.nio.charset.Charset + +/* + string apexer_command_line = 1; + bytes file_contexts = 2; + bytes canned_fs_config = 3; + bytes android_manifest = 4; + string min_sdk_version = 5; + string target_sdk_version = 6; + bool no_hashtree = 7; + string override_apk_package_name = 8; + string logging_parent = 9; + string payload_fs_type = 10; +} + + */ +data class ApexBuildInfoDataClass( + var apexer_command_line: String = "", //string + var file_contexts: String = "", //bytes + var canned_fs_config: String = "",//bytes + var android_manifest: String = "",//bytes + var min_sdk_version: String = "",//string + var target_sdk_version: String = "",//string + var no_hashtree: Boolean = false, + var override_apk_package_name: String = "",//string + var logging_parent: String = "",//string + var payload_fs_type: String = "",//string +) { + fun toPb(): ApexBuildInfo { + return ApexBuildInfo.newBuilder() + .setApexerCommandLine(this.apexer_command_line) + .setFileContexts(ByteString.copyFrom(this.file_contexts, Charset.defaultCharset())) + .setCannedFsConfig(ByteString.copyFrom(this.canned_fs_config, Charset.defaultCharset())) + .setAndroidManifest(ByteString.copyFrom(this.android_manifest, Charset.defaultCharset())) + .setMinSdkVersion(this.min_sdk_version) + .setTargetSdkVersion(this.target_sdk_version) + .setNoHashtree(this.no_hashtree) + .setOverrideApkPackageName(this.override_apk_package_name) + .setLoggingParent(this.logging_parent) + .setPayloadFsType(this.payload_fs_type) + .build() + } + companion object { + fun fromOuterClass(pb: ApexBuildInfoOuterClass.ApexBuildInfo): ApexBuildInfoDataClass? { + return ApexBuildInfoDataClass( + pb.apexerCommandLine, + pb.fileContexts.toStringUtf8(), + pb.cannedFsConfig.toStringUtf8(), + pb.androidManifest.toStringUtf8(), + pb.minSdkVersion, + pb.targetSdkVersion, + pb.noHashtree, + pb.overrideApkPackageName, + pb.loggingParent, + pb.payloadFsType + ) + } + } +} diff --git a/bbootimg/src/main/java/com/android/apex/ApexManifestDataClass.kt b/bbootimg/src/main/java/com/android/apex/ApexManifestDataClass.kt new file mode 100644 index 0000000..5fa035c --- /dev/null +++ b/bbootimg/src/main/java/com/android/apex/ApexManifestDataClass.kt @@ -0,0 +1,108 @@ +package com.android.apex + +import org.slf4j.LoggerFactory + +/* +message ApexManifest { + string name = 1; + int64 version = 2; + string preInstallHook = 3; + string postInstallHook = 4; + string versionName = 5; + bool noCode = 6; + repeated string provideNativeLibs = 7; + repeated string requireNativeLibs = 8; + repeated string jniLibs = 9; + repeated string requireSharedApexLibs = 10; + bool provideSharedApexLibs = 11; + message CompressedApexMetadata { + string originalApexDigest = 1; + } + CompressedApexMetadata capexMetadata = 12; + bool supportsRebootlessUpdate = 13; +} + + */ +data class ApexManifestDataClass( + /* 1 */ var name: String = "", + /* 2 */ var version: Long = 0, + /* 3 */ var preInstallHook: String = "", + /* 4 */ var postInstallHook: String = "", + /* 5 */ var versionName: String = "", + /* 6 */ var noCode: Boolean = false, + /* 7 */ var provideNativeLibs: MutableList = mutableListOf(), + /* 8 */ var requireNativeLibs: MutableList = mutableListOf(), + /* 9 */ var jniLibs: MutableList = mutableListOf(), + /* 10 */ var requireSharedApexLibs: MutableList = mutableListOf(), + /* 11 */ var provideSharedApexLibs: Boolean = false, + /* 12 */ var capexMetadata: CompressedApexMetadata = CompressedApexMetadata(), + /* 13 */ var supportsRebootlessUpdate: Boolean = false, +) { + data class CompressedApexMetadata(var originalApexDigest: String = "") { + fun toPb(): ApexManifestOuterClass.ApexManifest.CompressedApexMetadata { + return ApexManifestOuterClass.ApexManifest.CompressedApexMetadata.newBuilder() + .setOriginalApexDigest(this.originalApexDigest) + .build() + } + companion object { + fun fromOuterClass(pb: ApexManifestOuterClass.ApexManifest.CompressedApexMetadata): CompressedApexMetadata { + return CompressedApexMetadata(pb.originalApexDigest) + } + } + } + + fun toPb(): ApexManifestOuterClass.ApexManifest { + return ApexManifestOuterClass.ApexManifest.newBuilder() + .setName(this.name) + .setVersion(this.version) + .setPreInstallHook(this.preInstallHook) + .setPostInstallHook(this.postInstallHook) + .setVersionName(this.versionName) + .setNoCode(this.noCode) + .setProvideSharedApexLibs(this.provideSharedApexLibs) + .setCapexMetadata(this.capexMetadata.toPb()) + .setSupportsRebootlessUpdate(this.supportsRebootlessUpdate) + .also { + this.provideNativeLibs.forEachIndexed { _, s -> + it.addProvideNativeLibs(s) + } + } + .also { + this.requireNativeLibs.forEachIndexed { _, s -> + it.addRequireNativeLibs(s) + } + } + .also { + this.jniLibs.forEachIndexed { _, s -> + it.addJniLibs(s) + } + } + .also { + this.requireSharedApexLibs.forEachIndexed { _, s -> + it.addRequireSharedApexLibs(s) + } + } + .build() + } + + companion object { + private val log = LoggerFactory.getLogger(ApexManifestDataClass::class.java) + fun fromOuterClass(pb: ApexManifestOuterClass.ApexManifest): ApexManifestDataClass? { + return ApexManifestDataClass( + pb.name, + pb.version, + pb.preInstallHook, + pb.postInstallHook, + pb.versionName, + pb.noCode, + pb.provideNativeLibsList, + pb.requireNativeLibsList, + pb.jniLibsList, + pb.requireSharedApexLibsList, + pb.provideSharedApexLibs, + CompressedApexMetadata.fromOuterClass(pb.capexMetadata), + pb.supportsRebootlessUpdate + ) + } + } +} diff --git a/bbootimg/src/test/kotlin/com/android/apex/ApexBuildInfoDataClassTest.kt b/bbootimg/src/test/kotlin/com/android/apex/ApexBuildInfoDataClassTest.kt new file mode 100644 index 0000000..6be3a30 --- /dev/null +++ b/bbootimg/src/test/kotlin/com/android/apex/ApexBuildInfoDataClassTest.kt @@ -0,0 +1,25 @@ +package com.android.apex + +import cfig.helper.CryptoHelper +import com.fasterxml.jackson.databind.ObjectMapper +import org.junit.Test +import org.slf4j.LoggerFactory +import kotlin.test.assertTrue + +class ApexBuildInfoDataClassTest { + private val log = LoggerFactory.getLogger(ApexBuildInfoOuterClass::class.java) + @Test + fun parseAndPack() { + val raw = ApexBuildInfoDataClassTest::class.java.classLoader.getResourceAsStream("apex_build_info.pb")!!.readBytes() + val originalHash = CryptoHelper.Hasher.sha256(raw) + //parse + val abiPb = ApexBuildInfoOuterClass.ApexBuildInfo.parseFrom(raw) + log.info(abiPb.toString()) + val abiJava = ApexBuildInfoDataClass.fromOuterClass(abiPb) + log.info(ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(abiJava)) + //pack + val convertedHash = CryptoHelper.Hasher.sha256(abiJava!!.toPb().toByteArray()) + //check + assertTrue(originalHash.contentEquals(convertedHash)) + } +} diff --git a/bbootimg/src/test/kotlin/com/android/apex/ApexManifestDataClassTest.kt b/bbootimg/src/test/kotlin/com/android/apex/ApexManifestDataClassTest.kt new file mode 100644 index 0000000..383fd2d --- /dev/null +++ b/bbootimg/src/test/kotlin/com/android/apex/ApexManifestDataClassTest.kt @@ -0,0 +1,25 @@ +package com.android.apex + +import cfig.helper.CryptoHelper +import com.fasterxml.jackson.databind.ObjectMapper +import org.junit.Assert.* +import org.junit.Test +import org.slf4j.LoggerFactory + +class ApexManifestDataClassTest { + private val log = LoggerFactory.getLogger(ApexManifestDataClassTest::class.java) + @Test + fun parseAndPack() { + val raw = ApexManifestDataClassTest::class.java.classLoader.getResourceAsStream("apex_manifest.pb")!!.readBytes() + val originalHash = CryptoHelper.Hasher.sha256(raw) + //parse + val pb = ApexManifestOuterClass.ApexManifest.parseFrom(raw) + log.info(pb.toString()) + val manifest = ApexManifestDataClass.fromOuterClass(pb) + log.info(ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(manifest)) + //pack + val convertedHash = CryptoHelper.Hasher.sha256(manifest!!.toPb().toByteArray()) + //check + assertTrue(originalHash.contentEquals(convertedHash)) + } +} diff --git a/bbootimg/src/test/resources/apex_build_info.pb b/bbootimg/src/test/resources/apex_build_info.pb new file mode 100644 index 0000000..3c4f429 --- /dev/null +++ b/bbootimg/src/test/resources/apex_build_info.pb @@ -0,0 +1,16 @@ +s(/.*)? u:object_r:adbd_exec:s0 + +/apex_manifest\.pb u:object_r:system_file:s0 +/ u:object_r:system_file:s0 +/ 1000 1000 0755 +/apex_manifest.json 1000 1000 0644 +/apex_manifest.pb 1000 1000 0644 +/bin 0 2000 0755 +/bin/lazybox 0 2000 0755 +" + + + + +*31231Rext4 \ No newline at end of file diff --git a/bbootimg/src/test/resources/apex_manifest.pb b/bbootimg/src/test/resources/apex_manifest.pb new file mode 100644 index 0000000..b98c0aa --- /dev/null +++ b/bbootimg/src/test/resources/apex_manifest.pb @@ -0,0 +1,3 @@ + +cc.cfig.lazyboxB:vndkBlibc.soBlibdl.soB liblog.soBlibm.sobB +@2667842c6a7971ff1c8ee4c746d25ee93fa4cb588307a422739886d88dc0a980 \ No newline at end of file