1plugins { 2 alias(libs.plugins.android.library) 3} 4 5description = 'Conscrypt: Android Benchmarks' 6 7ext { 8 androidHome = "$System.env.ANDROID_HOME" 9 androidSdkInstalled = file("$androidHome").exists() 10 androidVersionCode = 1 11 androidVersionName = "$version" 12 androidMinSdkVersion = 26 13 androidTargetSdkVersion = 26 14} 15 16android { 17 namespace "org.conscrypt" 18 compileSdkVersion androidTargetSdkVersion 19 20 defaultConfig { 21 minSdkVersion androidMinSdkVersion 22 targetSdkVersion androidTargetSdkVersion 23 versionCode androidVersionCode 24 versionName androidVersionName 25 } 26 lintOptions { 27 // Some Caliper classes reference packages that don't exist on Android 28 disable 'InvalidPackage' 29 } 30 sourceSets.main { 31 java { 32 srcDirs = [ 33 "src/main/java" 34 ] 35 } 36 } 37} 38 39configurations { 40 // For the depsJar task, we need to create a config we can pull libraries from to 41 // make the complete JAR. Some we do not want the transitive dependencies because 42 // they are already included on the Android system. 43 depsJarApi 44 depsJarApi.transitive = true 45 46 depsJarImplementation 47 depsJarImplementation.transitive = false 48 49 implementation.extendsFrom(depsJarApi) 50 implementation.extendsFrom(depsJarImplementation) 51} 52 53dependencies { 54 depsJarApi project(path: ':conscrypt-android'), 55 libs.bouncycastle.provider, 56 libs.bouncycastle.apis 57 58 depsJarImplementation project(':conscrypt-benchmark-base'), 59 project(path: ":conscrypt-testing", configuration: "shadow"), 60 project(':conscrypt-libcore-stub') 61 62 implementation libs.caliper 63} 64 65// This task bundles up everything we're going to send to the device into a single jar. 66// We need to include all the Conscrypt code plus the Bouncy Castle jar because the platform 67// version of Bouncy Castle is jarjared. 68// 69// Since we're examining the contents of the archive files, we need to prevent evaluation of 70// the .aar and .jar contents before the actual archives are built. To do this we create a 71// configure task where the "from" contents is set inside a doLast stanza to ensure it is run 72// after the execution phase of the "assemble" task. 73def configureDepsJar = tasks.register("configureDepsJar") { 74 dependsOn assemble, \ 75 configurations.depsJarApi.artifacts, \ 76 configurations.depsJarImplementation.artifacts 77 doLast { 78 depsJar.from { 79 [ 80 configurations.depsJarApi, 81 configurations.depsJarImplementation, 82 configurations.archives.artifacts.file 83 ].collect { config -> 84 config.findResults { archive -> 85 // For Android library archives (.aar), we need to expand the classes.jar 86 // inside as well as including all the jni libraries. 87 if (archive.name.endsWith(".aar")) { 88 [ 89 zipTree(archive).matching { 90 include 'classes.jar' 91 }.collect { file -> 92 zipTree(file) 93 }, 94 zipTree(archive).matching { 95 include '**/*.so' 96 } 97 ] 98 } else if (archive.name.endsWith(".jar")) { 99 // Bouncy Castle signs their jar, which causes our combined jar to fail 100 // to verify. Just strip out the signature files. 101 zipTree(archive).matching { 102 exclude 'META-INF/*.SF' 103 exclude 'META-INF/*.DSA' 104 exclude 'META-INF/*.EC' 105 exclude 'META-INF/*.RSA' 106 } 107 } 108 } 109 } 110 } 111 } 112} 113 114def depsJar = tasks.register("depsJar", Jar) { 115 dependsOn configureDepsJar 116 archiveName = 'bundled-deps.jar' 117} 118 119def getAndroidDeviceAbi = tasks.register("getAndroidDeviceAbi") { 120 doLast { 121 new ByteArrayOutputStream().withStream { os -> 122 def result = exec { 123 executable android.adbExecutable 124 args 'shell', 'getprop', 'ro.product.cpu.abi' 125 standardOutput = os 126 } 127 project.ext.androidDeviceAbi = os.toString().trim() 128 project.ext.androidDevice64Bit = androidDeviceAbi.contains('64') 129 } 130 } 131} 132 133def configureExtractNativeLib = tasks.register("configureExtractNativeLib") { 134 dependsOn getAndroidDeviceAbi, depsJar 135 doLast { 136 extractNativeLib.from { 137 zipTree(depsJar.archivePath).matching { 138 include "jni/${androidDeviceAbi}/*.so" 139 }.collect { 140 // Using collect flattens out the directory. 141 it 142 } 143 } 144 } 145} 146 147def extractNativeLib = tasks.register("extractNativeLib", Copy) { 148 dependsOn configureExtractNativeLib 149 into "$buildDir/extracted-native-libs" 150} 151 152def configurePushNativeLibrary = tasks.register("configurePushNativeLibrary") { 153 dependsOn extractNativeLib 154 doLast { 155 project.ext.nativeLibPath = "/system/lib${androidDevice64Bit ? '64' : ''}/libconscrypt_jni.so" 156 pushNativeLibrary.args 'push', "${extractNativeLib.destinationDir}/libconscrypt_jni.so", nativeLibPath 157 } 158} 159 160def pushNativeLibrary = tasks.register("pushNativeLibrary", Exec) { 161 dependsOn configurePushNativeLibrary 162 pushNativeLibrary.executable android.adbExecutable 163} 164 165def runBenchmarks = tasks.register("runBenchmarks") { 166 dependsOn depsJar, pushNativeLibrary 167 doLast { 168 // Execute the benchmarks 169 exec { 170 workingDir "${rootDir}" 171 environment PATH: "${android.sdkDirectory}/build-tools/${android.buildToolsVersion}:$System.env.PATH" 172 environment JACK_JAR: "${android.sdkDirectory}/build-tools/${android.buildToolsVersion}/jack.jar" 173 174 executable 'java' 175 args '-cp', 'benchmark-android/vogar.jar', 'vogar.Vogar' 176 args '--classpath', depsJar.archivePath 177 args '--benchmark' 178 args '--language=JN' 179 args '--mode=app_process' 180 args 'org.conscrypt.CaliperAlpnBenchmark' 181 args 'org.conscrypt.CaliperClientSocketBenchmark' 182 args 'org.conscrypt.CaliperEngineHandshakeBenchmark' 183 args 'org.conscrypt.CaliperEngineWrapBenchmark' 184 } 185 // Clean up the native library 186 exec { 187 executable android.adbExecutable 188 args 'shell', 'rm', '-f', nativeLibPath 189 } 190 } 191} 192