blob: b4d9c5d11fa51d1d6d424d80f0447d18d24daea3 [file] [log] [blame]
/*
* Copyright (C) 2016 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.build.gradle.tasks
import com.android.build.api.artifact.ArtifactTransformationRequest
import com.android.build.api.artifact.Artifact
import com.android.build.api.variant.impl.BuiltArtifactsImpl
import com.android.build.gradle.internal.component.ApkCreationConfig
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.build.gradle.internal.scope.InternalArtifactType.APK_IDE_MODEL
import com.android.builder.profile.ProcessProfileWriter
import com.google.wireless.android.sdk.stats.GradleBuildProjectMetrics
import org.gradle.api.file.Directory
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskProvider
import java.io.File
import java.io.IOException
import java.nio.file.Files
/** Task to package an Android application (APK). */
abstract class PackageApplication : PackageAndroidArtifact() {
private lateinit var transformationRequest: ArtifactTransformationRequest<PackageApplication>
@Internal
override fun getTransformationRequest(): ArtifactTransformationRequest<PackageApplication> {
return transformationRequest
}
// ----- CreationAction -----
/**
* Configures the task to perform the "standard" packaging, including all files that should end
* up in the APK.
*/
class CreationAction(
creationConfig: ApkCreationConfig,
private val outputDirectory: File,
useResourceShrinker: Boolean,
manifests: Provider<Directory?>,
manifestType: Artifact<Directory>,
packageCustomClassDependencies: Boolean
) : PackageAndroidArtifact.CreationAction<PackageApplication>(
creationConfig,
useResourceShrinker,
manifests,
manifestType,
packageCustomClassDependencies
) {
private var transformationRequest: ArtifactTransformationRequest<PackageApplication>? = null
private var task: PackageApplication? = null
override val name: String
get() = computeTaskName("package")
override val type: Class<PackageApplication>
get() = PackageApplication::class.java
override fun handleProvider(
taskProvider: TaskProvider<PackageApplication>
) {
super.handleProvider(taskProvider)
creationConfig.taskContainer.packageAndroidTask = taskProvider
val operationRequest = creationConfig.artifacts.use(taskProvider)
.wiredWithDirectories(
PackageAndroidArtifact::getResourceFiles,
PackageApplication::getOutputDirectory)
transformationRequest = (if (useResourceShrinker)
operationRequest.toTransformMany(
InternalArtifactType.SHRUNK_PROCESSED_RES,
InternalArtifactType.APK,
outputDirectory.absolutePath)
else
operationRequest.toTransformMany(
InternalArtifactType.PROCESSED_RES,
InternalArtifactType.APK,
outputDirectory.absolutePath))
// in case configure is called before handleProvider, we need to save the request.
transformationRequest?.let {
task?.let { t -> t.transformationRequest = it }
}
creationConfig
.artifacts
.setInitialProvider(taskProvider, PackageApplication::getIdeModelOutputFile)
.atLocation { obj: PackageApplication -> obj.outputDirectory }
.withName(BuiltArtifactsImpl.METADATA_FILE_NAME)
.on(APK_IDE_MODEL)
}
override fun finalConfigure(task: PackageApplication) {
super.finalConfigure(task)
this.task = task
transformationRequest?.let {
task.transformationRequest = it
}
}
}
companion object {
@JvmStatic
fun recordMetrics(
projectPath: String?,
apkOutputFile: File?,
resourcesApFile: File?
) {
val metricsStartTime = System.nanoTime()
val metrics = GradleBuildProjectMetrics.newBuilder()
val apkSize = getSize(apkOutputFile)
if (apkSize != null) {
metrics.apkSize = apkSize
}
val resourcesApSize =
getSize(resourcesApFile)
if (resourcesApSize != null) {
metrics.resourcesApSize = resourcesApSize
}
metrics.metricsTimeNs = System.nanoTime() - metricsStartTime
ProcessProfileWriter.getProject(projectPath!!).setMetrics(metrics)
}
private fun getSize(file: File?): Long? {
return if (file == null) {
null
} else try {
Files.size(file.toPath())
} catch (e: IOException) {
null
}
}
}
}