1 package com.android.ndkports 2 3 import java.io.File 4 5 data class AdbException(val args: Iterable<String>, val output: String) : 6 RuntimeException("${formatCmd(args)}:\n$output") { <lambda>null7 val cmd: String by lazy { formatCmd(args) } 8 9 companion object { formatCmdnull10 fun formatCmd(args: Iterable<String>) = args.joinToString(" ") 11 } 12 } 13 14 private fun adb(args: Iterable<String>, serial: String? = null): String { 15 val adbCmd = if (serial == null) { 16 listOf("adb") 17 } else { 18 listOf("adb", "-s", serial) 19 } 20 val result = ProcessBuilder(adbCmd + args).redirectErrorStream(true).start() 21 val output = result.inputStream.bufferedReader().use { it.readText() } 22 if (result.waitFor() != 0) { 23 throw AdbException(args, output) 24 } 25 return output 26 } 27 28 data class Device(val serial: String) { <lambda>null29 private val abis: List<Abi> by lazy { 30 val abiProps = listOf( 31 "ro.product.cpu.abi", 32 "ro.product.cpu.abi2", 33 "ro.product.cpu.abilist", 34 ) 35 val abiSet = mutableSetOf<Abi>() 36 for (abiProp in abiProps) { 37 for (abiName in getProp(abiProp).trim().split(",")) { 38 Abi.fromAbiName(abiName)?.let { abiSet.add(it) } 39 } 40 } 41 abiSet.toList().sortedBy { it.abiName } 42 } 43 <lambda>null44 private val version: Int by lazy { 45 getProp("ro.build.version.sdk").trim().toInt() 46 } 47 compatibleWithnull48 fun compatibleWith(abi: Abi, minSdkVersion: Int) = 49 abi in abis && minSdkVersion <= version 50 51 fun push(src: File, dest: File) = 52 run(listOf("push", src.toString(), dest.toString())) 53 54 fun shell(cmd: Iterable<String>) = run(listOf("shell") + cmd) 55 56 private fun getProp(name: String): String = shell(listOf("getprop", name)) 57 58 private fun run(args: Iterable<String>): String = adb(args, serial) 59 } 60 61 class DeviceFleet { 62 private fun lineHasUsableDevice(line: String): Boolean { 63 if (line.isBlank()) { 64 return false 65 } 66 if (line == "List of devices attached") { 67 return false 68 } 69 if (line.contains("offline")) { 70 return false 71 } 72 if (line.contains("unauthorized")) { 73 return false 74 } 75 if (line.startsWith("* daemon")) { 76 return false 77 } 78 return true 79 } 80 81 private val devices: List<Device> by lazy { 82 adb(listOf("devices")).lines().filter { lineHasUsableDevice(it) }.map { 83 Device(it.split("\\s".toRegex()).first()) 84 } 85 } 86 87 fun findDeviceFor(abi: Abi, minSdkVersion: Int): Device? = 88 devices.find { it.compatibleWith(abi, minSdkVersion) } 89 }