Skip to content

Commit

Permalink
add aidl parcelables into aar
Browse files Browse the repository at this point in the history
  • Loading branch information
0xera committed Oct 22, 2024
1 parent c4dae7c commit 2eabbb8
Show file tree
Hide file tree
Showing 18 changed files with 647 additions and 59 deletions.
140 changes: 115 additions & 25 deletions grease/src/main/kotlin/io/deepmedia/tools/grease/GreasePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,15 @@ import com.android.ide.common.symbols.parseManifest
import com.android.manifmerger.ManifestMerger2
import com.android.manifmerger.ManifestProvider
import com.android.utils.appendCapitalized
import com.github.jengelman.gradle.plugins.shadow.ShadowStats
import com.github.jengelman.gradle.plugins.shadow.relocation.RelocatePathContext
import com.github.jengelman.gradle.plugins.shadow.relocation.Relocator
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.attributes.Usage
import org.gradle.api.file.Directory
import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
import org.gradle.kotlin.dsl.support.unzipTo
Expand Down Expand Up @@ -68,20 +72,25 @@ open class GreasePlugin : Plugin<Project> {
createConfigurations(false)
createConfigurations(true)

fun configure(variant: Variant, vararg configurations: Configuration) {
configureVariantManifest(target, variant, configurations, log)
configureVariantJniLibs(target, variant, configurations, log)
configureVariantResources(target, variant, configurations, log)
configureVariantSources(target, variant, configurations, greaseExtension, log)
configureVariantAssets(target, variant, configurations, log)
configureVariantProguardFiles(target, variant, configurations, log)
fun configure(variant: Variant, runtime: List<Configuration>, api: List<Configuration>) {
configureVariantManifest(target, variant, runtime, log)
configureVariantJniLibs(target, variant, runtime, log)
configureVariantAidlParcelables(target, variant, runtime + api, log)
configureVariantResources(target, variant, runtime, log)
configureVariantSources(target, variant, runtime, greaseExtension, log)
configureVariantAssets(target, variant, runtime, log)
configureVariantProguardFiles(target, variant, runtime, log)
}
// Configure all variants.
androidComponents.onVariants { variant ->
val childLog = log.child("configureVariant")
childLog.d { "Configuring variant ${variant.name}..." }
target.afterEvaluate {
configure(variant, target.greaseOf(variant), target.greaseOf(variant, true))
configure(
variant = variant,
runtime = listOf(target.greaseOf(variant), target.greaseOf(variant, true)),
api = listOf(target.greaseApiOf(variant), target.greaseApiOf(variant, true))
)
}
}
}
Expand Down Expand Up @@ -110,7 +119,7 @@ open class GreasePlugin : Plugin<Project> {
private fun configureVariantManifest(
target: Project,
variant: Variant,
configurations: Array<out Configuration>,
configurations: List<Configuration>,
logger: Logger
) {
val log = logger.child("configureVariantManifest")
Expand All @@ -121,7 +130,7 @@ open class GreasePlugin : Plugin<Project> {
target.locateTask(componentConfig.resolveTaskName("process", "Manifest"))?.configure {
val processManifestTask = this as ProcessLibraryManifest

val extraManifests = configurations.artifactsOf(AndroidArtifacts.ArtifactType.MANIFEST)
val extraManifests = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.MANIFEST)
dependsOn(extraManifests)

// After the file is copied we can go on with the actual manifest merging.
Expand Down Expand Up @@ -210,7 +219,7 @@ open class GreasePlugin : Plugin<Project> {
private fun configureVariantJniLibs(
target: Project,
variant: Variant,
configurations: Array<out Configuration>,
configurations: List<Configuration>,
logger: Logger
) {
val log = logger.child("configureVariantJniLibs")
Expand All @@ -220,7 +229,7 @@ open class GreasePlugin : Plugin<Project> {

target.locateTask(creationConfig.resolveTaskName("copy", "JniLibsProjectAndLocalJars"))?.configure {
val copyJniTask = this as LibraryJniLibsTask
val extraJniLibs = configurations.artifactsOf(AndroidArtifacts.ArtifactType.JNI)
val extraJniLibs = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.JNI)
dependsOn(extraJniLibs)

fun injectJniLibs() {
Expand Down Expand Up @@ -248,6 +257,37 @@ open class GreasePlugin : Plugin<Project> {
}
}

private fun configureVariantAidlParcelables(
target: Project,
variant: Variant,
configurations: List<Configuration>,
logger: Logger
) {
val log = logger.child("configureVariantAidlParcelables")
log.d { "Configuring variant ${variant.name}..." }
val creationConfig = variant.componentCreationConfigOrThrow()
creationConfig.taskContainer.aidlCompileTask?.configure {
val extraAidlFiles = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.AIDL)
dependsOn(extraAidlFiles)
fun injectAidlFiles() {
log.d { "Executing for variant ${variant.name} and ${extraAidlFiles.files.size} roots..." }
extraAidlFiles.files.forEach { inputRoot ->
log.d { "Found aidl parcelables files root: $inputRoot" }
val inputFiles = target.fileTree(inputRoot)
target.copy {
from(inputFiles)
into(packagedDir.get())
}
}
}
if (sourceFiles.get().files.isNotEmpty()) {
doLast { injectAidlFiles() }
} else {
injectAidlFiles()
}
}
}

/**
* AARs ship with a file called R.txt which already includes all resource ids from dependencies,
* so we shouldn't probably do nothing about it as it comes for free.
Expand Down Expand Up @@ -307,7 +347,7 @@ open class GreasePlugin : Plugin<Project> {
private fun configureVariantResources(
target: Project,
variant: Variant,
configurations: Array<out Configuration>,
configurations: List<Configuration>,
logger: Logger
) {

Expand All @@ -321,7 +361,7 @@ open class GreasePlugin : Plugin<Project> {
val resourcesMergingWorkdir = target.greaseBuildDir.get().dir(variant.name).dir("resources")
val mergedResourcesDir = resourcesMergingWorkdir.dir("merged")
val blameDir = resourcesMergingWorkdir.dir("blame")
val extraAndroidRes = configurations.artifactsOf(AndroidArtifacts.ArtifactType.ANDROID_RES)
val extraAndroidRes = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.ANDROID_RES)
dependsOn(extraAndroidRes)

outputs.upToDateWhen { false } // always execute
Expand Down Expand Up @@ -376,7 +416,7 @@ open class GreasePlugin : Plugin<Project> {
private fun configureVariantSources(
target: Project,
variant: Variant,
configurations: Array<out Configuration>,
configurations: List<Configuration>,
greaseExtension: GreaseExtension,
logger: Logger
) {
Expand All @@ -386,6 +426,7 @@ open class GreasePlugin : Plugin<Project> {
val creationConfig = variant.componentCreationConfigOrThrow()

val workdir = target.greaseBuildDir.get().dir(variant.name)
workdir.asFile.deleteRecursively()
val aarExtractWorkdir = workdir.dir("extract").dir("aar")
val jarExtractWorkdir = workdir.dir("extract").dir("jar")
val jarFileName = "classes.jar"
Expand Down Expand Up @@ -414,7 +455,7 @@ open class GreasePlugin : Plugin<Project> {

// There are many options here. PROCESSED_JAR, PROCESSED_AAR, CLASSES, CLASSES_JAR ...
// CLASSES_JAR seems to be the best though it's not clear if it's jetified or not.
val extraJars = configurations.artifactsOf(AndroidArtifacts.ArtifactType.CLASSES_JAR)
val extraJars = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.CLASSES_JAR)
dependsOn(extraJars)
dependsOn(greaseExpandTask)

Expand Down Expand Up @@ -444,7 +485,7 @@ open class GreasePlugin : Plugin<Project> {
ShadowJar::class.java
) {
val compileTask = creationConfig.taskContainer.javacTask
val extraManifests = configurations.artifactsOf(AndroidArtifacts.ArtifactType.MANIFEST)
val extraManifests = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.MANIFEST)
val greaseShadowDir = workdir.dir("shadow")
val bundleAar = bundleLibraryTask?.get() as BundleAar

Expand Down Expand Up @@ -475,8 +516,8 @@ open class GreasePlugin : Plugin<Project> {

val relocationPrefix = greaseExtension.prefix.get()
if (relocationPrefix.isNotEmpty()) {
greaseProcessTask.get().outputs.files
.asSequence()
val sequence = greaseProcessTask.get().outputs.files.asSequence() + aarExtractWorkdir.dir("aidl").asFile
sequence
.flatMap { inputFile -> inputFile.packageNames }
.distinct()
.map { packageName -> packageName to "${relocationPrefix}.$packageName" }
Expand All @@ -502,13 +543,20 @@ open class GreasePlugin : Plugin<Project> {
into(aarExtractWorkdir)
}

replacePackagesInFile(
replacePackagesInManifest(
aarExtractWorkdir.file("AndroidManifest.xml").asFile,
greaseShadowDir.file("AndroidManifest.xml").asFile,
relocators,
target,
)

relocateAidlFiles(
aarExtractWorkdir.dir("aidl"),
greaseShadowDir.dir("aidl"),
relocators,
target,
)

val oldArchive = bundleAar.archiveFile.get().asFile
val archiveParent = oldArchive.parentFile
val archiveName = oldArchive.name
Expand Down Expand Up @@ -544,7 +592,7 @@ open class GreasePlugin : Plugin<Project> {
}
}

private fun replacePackagesInFile(
private fun replacePackagesInManifest(
input: File,
output: File,
relocators: List<Relocator>,
Expand Down Expand Up @@ -573,6 +621,48 @@ open class GreasePlugin : Plugin<Project> {
}
}


private fun relocateAidlFiles(
inputDir: Directory,
outputDir: Directory,
relocators: List<Relocator>,
target: Project,
) {
if (inputDir.asFileTree.isEmpty) return

inputDir.asFileTree.forEach { file ->
val relocatePathContext = RelocatePathContext().apply {
stats = ShadowStats()
}
val reader = file.bufferedReader()
val relocatedPath = relocators
.filterNot { it is RClassRelocator }
.fold(file.toRelativeString(inputDir.asFile)) { acc, relocator ->
relocator.relocatePath(relocatePathContext.apply { path = acc })
}
val writer = outputDir.asFile.file(relocatedPath).bufferedWriter()
reader.useLines { strings ->
strings
.map { string ->
relocators
.filterNot { it is RClassRelocator }
.fold(string) { acc, relocator ->
relocator.applyToSourceContent(acc)
}
}.forEach {
writer.write(it)
writer.newLine()
}
}
writer.close()
}
inputDir.asFile.deleteRecursively()
target.copy {
from(outputDir)
into(inputDir)
}
}

/**
* Interesting tasks:
* 1. generate<>Assets: See [MutableTaskContainer].
Expand All @@ -585,14 +675,14 @@ open class GreasePlugin : Plugin<Project> {
private fun configureVariantAssets(
target: Project,
variant: Variant,
configurations: Array<out Configuration>,
configurations: List<Configuration>,
logger: Logger
) {
val log = logger.child("configureVariantAssets")
log.d { "Configuring variant ${variant.name}..." }
val creationConfig = variant.componentCreationConfigOrThrow()
creationConfig.taskContainer.mergeAssetsTask.configure {
val extraAssets = configurations.artifactsOf(AndroidArtifacts.ArtifactType.ASSETS)
val extraAssets = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.ASSETS)
dependsOn(extraAssets)
fun injectAssets() {
log.d { "Executing for variant ${variant.name} and ${extraAssets.files.size} roots..." }
Expand Down Expand Up @@ -639,7 +729,7 @@ open class GreasePlugin : Plugin<Project> {
private fun configureVariantProguardFiles(
target: Project,
variant: Variant,
configurations: Array<out Configuration>,
configurations: List<Configuration>,
logger: Logger
) {
val log = logger.child("configureVariantProguardFiles")
Expand All @@ -650,7 +740,7 @@ open class GreasePlugin : Plugin<Project> {
// UNFILTERED_PROGUARD_RULES, FILTERED_PROGUARD_RULES, AAPT_PROGUARD_RULES, ...
// UNFILTERED_PROGUARD_RULES is output of the AarTransform. FILTERED_PROGUARD_RULES
// is processed by another transform and is probably what we want in the end.
val extraInputs = configurations.artifactsOf(AndroidArtifacts.ArtifactType.FILTERED_PROGUARD_RULES)
val extraInputs = configurations.artifactsOf(target, AndroidArtifacts.ArtifactType.FILTERED_PROGUARD_RULES)
dependsOn(extraInputs)

mergeFileTask.inputs.files(extraInputs + mergeFileTask.inputFiles.files)
Expand Down
Loading

0 comments on commit 2eabbb8

Please sign in to comment.