mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-23 18:15:30 +00:00
Build script adjustments
This commit is contained in:
parent
307cf87215
commit
8adf27859d
@ -1,10 +1,11 @@
|
|||||||
import org.gradle.api.DefaultTask
|
import org.gradle.api.DefaultTask
|
||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -78,6 +79,9 @@ fun genKeyData(keysDir: File, outSrc: File) {
|
|||||||
|
|
||||||
@CacheableTask
|
@CacheableTask
|
||||||
abstract class ManifestUpdater: DefaultTask() {
|
abstract class ManifestUpdater: DefaultTask() {
|
||||||
|
@get:Input
|
||||||
|
abstract val applicationId: Property<String>
|
||||||
|
|
||||||
@get:InputFile
|
@get:InputFile
|
||||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
abstract val mergedManifest: RegularFileProperty
|
abstract val mergedManifest: RegularFileProperty
|
||||||
@ -99,74 +103,68 @@ abstract class ManifestUpdater: DefaultTask() {
|
|||||||
|
|
||||||
val cmpList = mutableListOf<String>()
|
val cmpList = mutableListOf<String>()
|
||||||
|
|
||||||
cmpList.add(
|
cmpList.add("""
|
||||||
"""
|
|<provider
|
||||||
|<provider
|
| android:name="x.COMPONENT_PLACEHOLDER_0"
|
||||||
| android:name="x.COMPONENT_PLACEHOLDER_0"
|
| android:authorities="${'$'}{applicationId}.provider"
|
||||||
| android:authorities="${'$'}{applicationId}.provider"
|
| android:directBootAware="true"
|
||||||
| android:directBootAware="true"
|
| android:exported="false"
|
||||||
| android:exported="false"
|
| android:grantUriPermissions="true" />""".ind(2)
|
||||||
| android:grantUriPermissions="true" />""".ind(2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmpList.add(
|
cmpList.add("""
|
||||||
"""
|
|<receiver
|
||||||
|<receiver
|
| android:name="x.COMPONENT_PLACEHOLDER_1"
|
||||||
| android:name="x.COMPONENT_PLACEHOLDER_1"
|
| android:exported="false">
|
||||||
| android:exported="false">
|
| <intent-filter>
|
||||||
| <intent-filter>
|
| <action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||||
| <action android:name="android.intent.action.LOCALE_CHANGED" />
|
| <action android:name="android.intent.action.UID_REMOVED" />
|
||||||
| <action android:name="android.intent.action.UID_REMOVED" />
|
| <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
| <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
| </intent-filter>
|
||||||
| </intent-filter>
|
| <intent-filter>
|
||||||
| <intent-filter>
|
| <action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||||
| <action android:name="android.intent.action.PACKAGE_REPLACED" />
|
| <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||||
| <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
|
|
||||||
|
|
| <data android:scheme="package" />
|
||||||
| <data android:scheme="package" />
|
| </intent-filter>
|
||||||
| </intent-filter>
|
|</receiver>""".ind(2)
|
||||||
|</receiver>""".ind(2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmpList.add(
|
cmpList.add("""
|
||||||
"""
|
|<activity
|
||||||
|<activity
|
| android:name="x.COMPONENT_PLACEHOLDER_2"
|
||||||
| android:name="x.COMPONENT_PLACEHOLDER_2"
|
| android:exported="true">
|
||||||
| android:exported="true">
|
| <intent-filter>
|
||||||
| <intent-filter>
|
| <action android:name="android.intent.action.MAIN" />
|
||||||
| <action android:name="android.intent.action.MAIN" />
|
| <category android:name="android.intent.category.LAUNCHER" />
|
||||||
| <category android:name="android.intent.category.LAUNCHER" />
|
| </intent-filter>
|
||||||
| </intent-filter>
|
|</activity>""".ind(2)
|
||||||
|</activity>""".ind(2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmpList.add(
|
cmpList.add("""
|
||||||
"""
|
|<activity
|
||||||
|<activity
|
| android:name="x.COMPONENT_PLACEHOLDER_3"
|
||||||
| android:name="x.COMPONENT_PLACEHOLDER_3"
|
| android:directBootAware="true"
|
||||||
| android:directBootAware="true"
|
| android:exported="false"
|
||||||
| android:exported="false"
|
| android:taskAffinity="">
|
||||||
| android:taskAffinity="">
|
| <intent-filter>
|
||||||
| <intent-filter>
|
| <action android:name="android.intent.action.VIEW"/>
|
||||||
| <action android:name="android.intent.action.VIEW"/>
|
| <category android:name="android.intent.category.DEFAULT"/>
|
||||||
| <category android:name="android.intent.category.DEFAULT"/>
|
| </intent-filter>
|
||||||
| </intent-filter>
|
|</activity>""".ind(2)
|
||||||
|</activity>""".ind(2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmpList.add(
|
cmpList.add("""
|
||||||
"""
|
|<service
|
||||||
|<service
|
| android:name="x.COMPONENT_PLACEHOLDER_4"
|
||||||
| android:name="x.COMPONENT_PLACEHOLDER_4"
|
| android:exported="false" />""".ind(2)
|
||||||
| android:exported="false" />""".ind(2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cmpList.add(
|
cmpList.add("""
|
||||||
"""
|
|<service
|
||||||
|<service
|
| android:name="x.COMPONENT_PLACEHOLDER_5"
|
||||||
| android:name="x.COMPONENT_PLACEHOLDER_5"
|
| android:exported="false"
|
||||||
| android:exported="false"
|
| android:permission="android.permission.BIND_JOB_SERVICE" />""".ind(2)
|
||||||
| android:permission="android.permission.BIND_JOB_SERVICE" />""".ind(2)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Shuffle the order of the components
|
// Shuffle the order of the components
|
||||||
@ -177,15 +175,19 @@ abstract class ManifestUpdater: DefaultTask() {
|
|||||||
val (appPkg, appClass) = appClassDir.asFileTree.first().let {
|
val (appPkg, appClass) = appClassDir.asFileTree.first().let {
|
||||||
it.parentFile.name to it.name.removeSuffix(".java")
|
it.parentFile.name to it.name.removeSuffix(".java")
|
||||||
}
|
}
|
||||||
var manifest = mergedManifest.asFile.get().readText()
|
val components = cmpList.joinToString("\n\n")
|
||||||
manifest = manifest.replace("<application", """<application android:appComponentFactory="$factoryPkg.$factoryClass" android:name="$appPkg.$appClass"""")
|
.replace("\${applicationId}", applicationId.get())
|
||||||
manifest = manifest.replace("</application", "${cmpList.joinToString("\n\n")}\n</application")
|
val manifest = mergedManifest.asFile.get().readText().replace(Regex(".*\\<application"), """
|
||||||
|
|<application
|
||||||
|
| android:appComponentFactory="$factoryPkg.$factoryClass"
|
||||||
|
| android:name="$appPkg.$appClass"""".ind(1)
|
||||||
|
).replace(Regex(".*\\<\\/application"), components + "\n </application")
|
||||||
outputManifest.get().asFile.writeText(manifest)
|
outputManifest.get().asFile.writeText(manifest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun genStubClass(factoryOutDir: File, appOutDir: File) {
|
fun genStubClasses(factoryOutDir: File, appOutDir: File) {
|
||||||
fun String.ind(level: Int) = replaceIndentByMargin(" ".repeat(level))
|
fun String.ind(level: Int) = replaceIndentByMargin(" ".repeat(level))
|
||||||
|
|
||||||
val classNameGenerator = sequence {
|
val classNameGenerator = sequence {
|
||||||
@ -231,7 +233,7 @@ fun genStubClass(factoryOutDir: File, appOutDir: File) {
|
|||||||
genClass("DelegateApplication", appOutDir)
|
genClass("DelegateApplication", appOutDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun genEncryptedResources(res: InputStream, outDir: File) {
|
fun genEncryptedResources(res: ByteArray, outDir: File) {
|
||||||
val mainPkgDir = File(outDir, "com/topjohnwu/magisk")
|
val mainPkgDir = File(outDir, "com/topjohnwu/magisk")
|
||||||
mainPkgDir.mkdirs()
|
mainPkgDir.mkdirs()
|
||||||
|
|
||||||
@ -245,7 +247,7 @@ fun genEncryptedResources(res: InputStream, outDir: File) {
|
|||||||
cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
||||||
val bos = ByteArrayOutputStream()
|
val bos = ByteArrayOutputStream()
|
||||||
|
|
||||||
res.use {
|
ByteArrayInputStream(res).use {
|
||||||
CipherOutputStream(bos, cipher).use { os ->
|
CipherOutputStream(bos, cipher).use { os ->
|
||||||
it.transferTo(os)
|
it.transferTo(os)
|
||||||
}
|
}
|
||||||
|
@ -17,18 +17,33 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.file.DirectoryProperty
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.plugins.ExtensionAware
|
import org.gradle.api.plugins.ExtensionAware
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.Delete
|
||||||
import org.gradle.kotlin.dsl.*
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.Internal
|
||||||
|
import org.gradle.api.tasks.OutputDirectory
|
||||||
|
import org.gradle.api.tasks.StopExecutionException
|
||||||
|
import org.gradle.api.tasks.Sync
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
import org.gradle.kotlin.dsl.filter
|
||||||
|
import org.gradle.kotlin.dsl.get
|
||||||
|
import org.gradle.kotlin.dsl.getValue
|
||||||
|
import org.gradle.kotlin.dsl.named
|
||||||
|
import org.gradle.kotlin.dsl.provideDelegate
|
||||||
|
import org.gradle.kotlin.dsl.register
|
||||||
|
import org.gradle.kotlin.dsl.registering
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
import java.io.ByteArrayInputStream
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.util.*
|
|
||||||
import java.util.jar.JarFile
|
import java.util.jar.JarFile
|
||||||
import java.util.zip.*
|
import java.util.zip.Deflater
|
||||||
|
import java.util.zip.DeflaterOutputStream
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipFile
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
private fun Project.androidBase(configure: Action<BaseExtension>) =
|
private fun Project.androidBase(configure: Action<BaseExtension>) =
|
||||||
extensions.configure("android", configure)
|
extensions.configure("android", configure)
|
||||||
@ -88,30 +103,6 @@ private fun ApkSigningConfig.getPrivateKey(): KeyStore.PrivateKeyEntry {
|
|||||||
return entry as KeyStore.PrivateKeyEntry
|
return entry as KeyStore.PrivateKeyEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addComment(inFile: File, outFile: File, signConfig: ApkSigningConfig, minSdk: Int, eocdComment: String) {
|
|
||||||
val privateKey = signConfig.getPrivateKey()
|
|
||||||
val signingOptions = SigningOptions.builder()
|
|
||||||
.setMinSdkVersion(minSdk)
|
|
||||||
.setV1SigningEnabled(true)
|
|
||||||
.setV2SigningEnabled(true)
|
|
||||||
.setKey(privateKey.privateKey)
|
|
||||||
.setCertificates(privateKey.certificate as X509Certificate)
|
|
||||||
.setValidation(SigningOptions.Validation.ASSUME_INVALID)
|
|
||||||
.build()
|
|
||||||
val options = ZFileOptions().apply {
|
|
||||||
noTimestamps = true
|
|
||||||
autoSortFiles = true
|
|
||||||
}
|
|
||||||
outFile.parentFile.mkdirs()
|
|
||||||
inFile.copyTo(outFile, overwrite = true)
|
|
||||||
ZFiles.apk(outFile, options).use {
|
|
||||||
SigningExtension(signingOptions).register(it)
|
|
||||||
it.eocdComment = eocdComment.toByteArray()
|
|
||||||
it.get(IncrementalPackager.APP_METADATA_ENTRY_PATH)?.delete()
|
|
||||||
it.get(JarFile.MANIFEST_NAME)?.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class AddCommentTask: DefaultTask() {
|
abstract class AddCommentTask: DefaultTask() {
|
||||||
@get:Input
|
@get:Input
|
||||||
abstract val comment: Property<String>
|
abstract val comment: Property<String>
|
||||||
@ -132,7 +123,29 @@ abstract class AddCommentTask: DefaultTask() {
|
|||||||
fun taskAction() = transformationRequest.get().submit(this) { artifact ->
|
fun taskAction() = transformationRequest.get().submit(this) { artifact ->
|
||||||
val inFile = File(artifact.outputFile)
|
val inFile = File(artifact.outputFile)
|
||||||
val outFile = outFolder.file(inFile.name).get().asFile
|
val outFile = outFolder.file(inFile.name).get().asFile
|
||||||
addComment(inFile, outFile, signingConfig.get(), 0, comment.get())
|
|
||||||
|
val privateKey = signingConfig.get().getPrivateKey()
|
||||||
|
val signingOptions = SigningOptions.builder()
|
||||||
|
.setMinSdkVersion(0)
|
||||||
|
.setV1SigningEnabled(true)
|
||||||
|
.setV2SigningEnabled(true)
|
||||||
|
.setKey(privateKey.privateKey)
|
||||||
|
.setCertificates(privateKey.certificate as X509Certificate)
|
||||||
|
.setValidation(SigningOptions.Validation.ASSUME_INVALID)
|
||||||
|
.build()
|
||||||
|
val options = ZFileOptions().apply {
|
||||||
|
noTimestamps = true
|
||||||
|
autoSortFiles = true
|
||||||
|
}
|
||||||
|
outFile.parentFile.mkdirs()
|
||||||
|
inFile.copyTo(outFile, overwrite = true)
|
||||||
|
ZFiles.apk(outFile, options).use {
|
||||||
|
SigningExtension(signingOptions).register(it)
|
||||||
|
it.eocdComment = comment.get().toByteArray()
|
||||||
|
it.get(IncrementalPackager.APP_METADATA_ENTRY_PATH)?.delete()
|
||||||
|
it.get(JarFile.MANIFEST_NAME)?.delete()
|
||||||
|
}
|
||||||
|
|
||||||
outFile
|
outFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -305,16 +318,15 @@ fun Project.setupApp() {
|
|||||||
fun Project.setupStub() {
|
fun Project.setupStub() {
|
||||||
setupAppCommon()
|
setupAppCommon()
|
||||||
|
|
||||||
|
|
||||||
androidComponents.onVariants { variant ->
|
androidComponents.onVariants { variant ->
|
||||||
|
val variantName = variant.name
|
||||||
|
val variantCapped = variantName.replaceFirstChar { it.uppercase() }
|
||||||
val manifestUpdater =
|
val manifestUpdater =
|
||||||
project.tasks.register(
|
project.tasks.register("${variantName}ManifestProducer", ManifestUpdater::class.java) {
|
||||||
"${variant.name}ManifestProducer",
|
dependsOn("generate${variantCapped}ObfuscatedClass")
|
||||||
ManifestUpdater::class.java
|
applicationId.set(variant.applicationId)
|
||||||
) {
|
appClassDir.set(File(buildDir, "generated/source/app/$variantName"))
|
||||||
dependsOn("generate${variant.name.replaceFirstChar { it.uppercase() }}ObfuscatedClass")
|
factoryClassDir.set(File(buildDir, "generated/source/factory/$variantName"))
|
||||||
appClassDir.set(File(buildDir, "generated/source/app/${variant.name}"))
|
|
||||||
factoryClassDir.set(File(buildDir, "generated/source/factory/${variant.name}"))
|
|
||||||
}
|
}
|
||||||
variant.artifacts.use(manifestUpdater)
|
variant.artifacts.use(manifestUpdater)
|
||||||
.wiredWithFiles(
|
.wiredWithFiles(
|
||||||
@ -340,33 +352,34 @@ fun Project.setupStub() {
|
|||||||
doLast {
|
doLast {
|
||||||
outFactoryClassDir.mkdirs()
|
outFactoryClassDir.mkdirs()
|
||||||
outAppClassDir.mkdirs()
|
outAppClassDir.mkdirs()
|
||||||
genStubClass(outFactoryClassDir, outAppClassDir)
|
genStubClasses(outFactoryClassDir, outAppClassDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registerJavaGeneratingTask(genManifestTask, outFactoryClassDir, outAppClassDir)
|
registerJavaGeneratingTask(genManifestTask, outFactoryClassDir, outAppClassDir)
|
||||||
|
|
||||||
val processResourcesTask = tasks.getByPath(":stub:process${variantCapped}Resources")
|
val processResourcesTask = tasks.named("process${variantCapped}Resources") {
|
||||||
processResourcesTask.doLast {
|
doLast {
|
||||||
exec {
|
exec {
|
||||||
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
||||||
}
|
}
|
||||||
|
|
||||||
val bos = ByteArrayOutputStream()
|
val bos = ByteArrayOutputStream()
|
||||||
ZipFile(apkTmp).use { src ->
|
ZipFile(apkTmp).use { src ->
|
||||||
ZipOutputStream(apk.outputStream()).use {
|
ZipOutputStream(apk.outputStream()).use {
|
||||||
it.setLevel(Deflater.BEST_COMPRESSION)
|
it.setLevel(Deflater.BEST_COMPRESSION)
|
||||||
it.putNextEntry(ZipEntry("AndroidManifest.xml"))
|
it.putNextEntry(ZipEntry("AndroidManifest.xml"))
|
||||||
src.getInputStream(src.getEntry("AndroidManifest.xml")).transferTo(it)
|
src.getInputStream(src.getEntry("AndroidManifest.xml")).transferTo(it)
|
||||||
it.closeEntry()
|
it.closeEntry()
|
||||||
}
|
}
|
||||||
DeflaterOutputStream(bos, Deflater(Deflater.BEST_COMPRESSION)).use {
|
DeflaterOutputStream(bos, Deflater(Deflater.BEST_COMPRESSION)).use {
|
||||||
src.getInputStream(src.getEntry("resources.arsc")).transferTo(it)
|
src.getInputStream(src.getEntry("resources.arsc")).transferTo(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
apkTmp.delete()
|
||||||
|
genEncryptedResources(bos.toByteArray(), outResDir)
|
||||||
}
|
}
|
||||||
apkTmp.delete()
|
|
||||||
genEncryptedResources(ByteArrayInputStream(bos.toByteArray()), outResDir)
|
|
||||||
}
|
}
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
registerJavaGeneratingTask(processResourcesTask, outResDir)
|
registerJavaGeneratingTask(processResourcesTask, outResDir)
|
||||||
}
|
}
|
||||||
// Override optimizeReleaseResources task
|
// Override optimizeReleaseResources task
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||||
|
|
||||||
<application
|
<application tools:ignore="MissingApplicationIcon">
|
||||||
tools:ignore="GoogleAppIndexingWarning,MissingApplicationIcon,UnusedAttribute">
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
Loading…
Reference in New Issue
Block a user