Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Enable GPU acceleration for new instances #1991

Merged
merged 2 commits into from
Jun 1, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import flank.corellium.client.core.getProjectInstancesList
import flank.corellium.client.core.startInstance
import flank.corellium.client.core.waitUntilInstanceIsReady
import flank.corellium.client.data.Instance
import flank.corellium.client.data.Instance.BootOptions.AdditionalTags.GPU
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.channelFlow
@@ -20,23 +21,24 @@ private const val SCREEN = "720x1280:280"

fun invokeAndroidDevices(
projectName: String,
) = AndroidInstance.Invoke { (amount) ->
) = AndroidInstance.Invoke { config ->
channelFlow<String> {
val projectId = getProjectId(projectName)
val instances = getCreatedInstances(projectId, amount)
val instances = getCreatedInstances(projectId, config.amount)
startNotRunningInstances(instances)

val ids = instances.map(Instance::id) + let {
// When existing instances size match required amount
// there is not needs for creating more instances.
if (instances.size == amount) emptyList()
if (instances.size == config.amount) emptyList()
// Otherwise is required to create some additional instances
else createInstances(
projectId = projectId,
gpuAcceleration = config.gpuAcceleration,
indexes = calculateAdditionalIndexes(
current = instances,
requiredAmount = amount
)
requiredAmount = config.amount
),
)
}

@@ -87,7 +89,8 @@ private suspend fun startNotRunningInstances(
*/
private suspend fun createInstances(
projectId: String,
indexes: List<Int>
indexes: List<Int>,
gpuAcceleration: Boolean,
) = indexes
.apply { println("Creating additional ${indexes.size} instances. Connecting to the agents may take longer.") }
.map { index ->
@@ -98,7 +101,10 @@ private suspend fun createInstances(
flavor = FLAVOUR,
os = OS,
bootOptions = Instance.BootOptions(
screen = SCREEN
screen = SCREEN,
additionalTags = listOfNotNull(
GPU.takeIf { gpuAcceleration }
)
)
)
)
Original file line number Diff line number Diff line change
@@ -12,18 +12,20 @@ object AndroidInstance {
/**
* Configuration for devices to invoke.
*
* @property amount the amount of devices to invoke.
* @property amount The amount of devices to invoke.
* @property gpuAcceleration Enables gpu acceleration for virtual devices.
*/
data class Config(
val amount: Int
val amount: Int,
val gpuAcceleration: Boolean
)

/**
* Invoke the android corellium devices.
*
* After successful invoke, the devices specified in th [Config] should be running and ready for use.
*
* @return list of invoked device ids.
* @return List of invoked device ids.
*/
fun interface Invoke : (Config) -> Flow<String>
}
Original file line number Diff line number Diff line change
@@ -90,6 +90,17 @@ class RunTestCorelliumAndroidCommand :
]
)
var obfuscate: Boolean? by data

@set:CommandLine.Option(
names = ["--gpu-acceleration"],
description = [
"Enable cloud GPU acceleration (Extra costs incurred)." +
"Currently this option only works for newly devices created." +
"To create new device pool with gpu-acceleration, remove old devices manually and let Flank recreate the pool."
]
)
@set:JsonProperty("gpu-acceleration")
var gpuAcceleration: Boolean? by data
}

@CommandLine.Mixin
@@ -119,6 +130,7 @@ private fun defaultConfig() = Config().apply {
maxTestShards = 1
localResultsDir = null
obfuscate = false
gpuAcceleration = true
}

private fun RunTestCorelliumAndroidCommand.yamlConfig(): Config =
@@ -130,4 +142,5 @@ private fun RunTestCorelliumAndroidCommand.createArgs() = Args(
maxShardsCount = config.maxTestShards!!,
outputDir = config.localResultsDir ?: Args.DefaultOutputDir.new,
obfuscateDumpShards = config.obfuscate!!,
gpuAcceleration = config.gpuAcceleration!!
)
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ class RunTestCorelliumAndroidCommandTest {
maxTestShards = Int.MAX_VALUE
localResultsDir = "test_result_dir"
obfuscate = true
gpuAcceleration = false
}

/**
@@ -57,6 +58,7 @@ class RunTestCorelliumAndroidCommandTest {
"--max-test-shards=$maxTestShards",
"--local-result-dir=$localResultsDir",
"--obfuscate=$obfuscate",
"--gpu-acceleration=$gpuAcceleration",
)
}

@@ -75,6 +77,7 @@ apks:
max-test-shards: $maxTestShards
local-result-dir: $localResultsDir
obfuscate: $obfuscate
gpu-acceleration: $gpuAcceleration
""".trimIndent()
}

@@ -136,7 +139,8 @@ obfuscate: $obfuscate
apks = apks!!,
maxShardsCount = maxTestShards!!,
outputDir = localResultsDir!!,
obfuscateDumpShards = obfuscate!!
obfuscateDumpShards = obfuscate!!,
gpuAcceleration = gpuAcceleration!!,
)
}

Original file line number Diff line number Diff line change
@@ -38,14 +38,29 @@ data class Instance(
val info: String = ""
)

/**
* @param udid Predefined Unique Device ID (UDID) for iOS device
* @param screen Change the screen metrics for Ranchu devices `XxY[:DPI]`, e.g. `720x1280:280`
* @param additionalTags features to utilize for the device, valid options include. Check [AdditionalTags]
*/
@Serializable
data class BootOptions(
val bootArgs: String = "",
val restoreBootArgs: String = "",
val udid: String = "",
val ecid: String = "",
val screen: String = ""
)
val screen: String = "",
val additionalTags: List<String> = emptyList(),
) {
/**
* @property GPU Enable cloud GPU acceleration (Extra costs incurred, cloud only).
* @property KALLOC Enable kalloc/kfree trace access via GDB (Enterprise only).
*/
object AdditionalTags {
const val GPU = "gpu"
const val KALLOC = "kalloc"
}
}
}

@Serializable
Original file line number Diff line number Diff line change
@@ -49,13 +49,15 @@ object RunTestCorelliumAndroid {
* @param maxShardsCount Maximum amount of shards to create. For each shard Flank is invoking dedicated device instance, so do not use values grater than maximum number available instances in the Corellium account.
* @param obfuscateDumpShards Obfuscate the test names in shards before dumping to file.
* @param outputDir Set output dir. Default value is [DefaultOutputDir.new]
* @param gpuAcceleration Enable gpu acceleration for newly created virtual devices.
*/
data class Args(
val credentials: Authorization.Credentials,
val apks: List<Apk.App>,
val maxShardsCount: Int,
val obfuscateDumpShards: Boolean = false,
val outputDir: String = DefaultOutputDir.new,
val gpuAcceleration: Boolean = true,
) {
/**
* Default output directory scheme.
Original file line number Diff line number Diff line change
@@ -16,5 +16,9 @@ import kotlinx.coroutines.flow.toList
*/
internal fun RunTestCorelliumAndroid.Context.invokeDevices() = RunTestCorelliumAndroid.step {
println("* Invoking devices")
copy(ids = api.invokeAndroidDevices(AndroidInstance.Config(shards.size)).toList())
val config = AndroidInstance.Config(
amount = shards.size,
gpuAcceleration = args.gpuAcceleration
)
copy(ids = api.invokeAndroidDevices(config).toList())
}