Re: [Gradle-plugin] how to support more than one device and emulator in InstallTask/instrumentTest?

1,667 views
Skip to first unread message

Xavier Ducrohet

unread,
Apr 4, 2013, 12:49:07 PM4/4/13
to adt...@googlegroups.com
Are you writing custom code in your build.gradle to manually install, run tests and uninstall apks? I'll have to add the ability to add a serial number to the task. There's nothing right now to deal with this.

I haven't looked at figuring out how to deal with build servers launching emulators in parallel yet.
It's something I want to look at. One thing I've been thinking about is relying on the fact that emulators can be queried for their AVD names so we could just use this to make sure the test apks are deployed to the right emulator.
This would work in combination with the ability to declare AVDs in build.gradle and have the test runner deal with launching the AVD, installing, running the test, uninstalling and closing the emulator.


On Thu, Apr 4, 2013 at 7:45 AM, Per Christian Henden <perh...@gmail.com> wrote:
Hi group!

When executing the build I have multiple devices available for adb, and this makes the InstallTask fail with an adb error ("more than one device and emulator"). 
The reason for the multiple devices is that this happens on a build server (Jenkins) where there are multiple Android projects building at the same time, each using their own emulator. 
To install an apk in this environment 'adb' must be given a device serial, for example 'adb -s emulator-5554 install myapp.apk'.

Do you have any suggestions on a workaround for this limitation in the gradle plugin? 
My ideas so far are to overwrite the InstallTask or to somehow supply the ANDROID_SERIAL environment variable to the InstallTask. 
When ANDROID_SERIAL is available, adb will use that device. 

Cheers
PC:

--
You received this message because you are subscribed to the Google Groups "adt-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to adt-dev+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Xavier Ducrohet
Android SDK Tech Lead
Google Inc.
http://developer.android.com | http://tools.android.com

Please do not send me questions directly. Thanks!

Per Christian Henden

unread,
Apr 8, 2013, 6:01:38 PM4/8/13
to adt...@googlegroups.com
kl. 18:49:07 UTC+2 torsdag 4. april 2013 skrev Xavier Ducrohet følgende:
Are you writing custom code in your build.gradle to manually install, run tests and uninstall apks? I'll have to add the ability to add a serial number to the task. There's nothing right now to deal with this.
 
That's right. A 'deviceId' commandline property also proved necessary, to be able to choose which device to use, in addition to the startEmulator/stopEmulator tasks. 
It would've been prettier to modify your Android plugin directly, but my customer didn't like that approach. 

I haven't looked at figuring out how to deal with build servers launching emulators in parallel yet.
It's something I want to look at. One thing I've been thinking about is relying on the fact that emulators can be queried for their AVD names so we could just use this to make sure the test apks are deployed to the right emulator.
This would work in combination with the ability to declare AVDs in build.gradle and have the test runner deal with launching the AVD, installing, running the test, uninstalling and closing the emulator.

Sounds good! 
The build script would create the AVD with a unique, known name, like 'test-<UUID>' and query for that name? 
Maybe if the 'deviceId' property (or similar) was given on the commandline, the tests would run on the specified (physical or emulator) device?  E.g. 'gradle -PdeviceId=emulator-5556 clean assemble instrumentTest'
Perhaps starting the emulator before running the instrument/uiautomator-tests could be the default behaviour when the 'deviceId' property is not specified. 

I did it slightly differently:
1 Deleted and re-created the emulator during startEmulator with 'android create' to have a known starting point for the tests 
2 Found the serial of this emulator by setting a property at create time, emu.id to a known, unique value, and querying all emulators for it in loop until the matching emu.id was found
3 Waited for the emulator to boot, before running the next task, by waiting for the property "init.svc.bootanim" to become "stopped"

This last step (or something equivalent) is probably necessary in your approach too. 

Kevin Brotcke

unread,
Nov 4, 2014, 2:07:24 PM11/4/14
to adt...@googlegroups.com
Reviving this thread in case others stumble upon it. I recently added the ANDROID_SERIAL property support released in Android Gradle plugin 0.14.0 (2014/10/31).

https://code.google.com/p/android/issues/detail?id=75407

Sebastian Gröbler

unread,
Jan 25, 2015, 12:55:30 PM1/25/15
to adt...@googlegroups.com
From my experience I know that three parameters are extremely useful when working with multiple devices on CI:

1. The timeout for installing apks, which can easily be reached if devices are connected through a socket from a remote machine and when uploading big apks.
2. The number of threads which access one adb server at the same time in parallel. The broken pipe error seems to be system dependent, e.g. ubuntu is worse than mac. For mac I found that 4 threads is the sweet spot.
3. A list of device serials which identify the devices to run tests on.

I wish all of these parameters would be configureable through the android gradle plugin or from cli.

I know that the abstract DeviceProvider class has a getMaxThreads() method which is currently hardcoded to 0 which causes the subsequent logic to use as many threads as the system has processors. Maybe that logic could be refactored to use 0 as a default and allow the property to be set from cli, like: ./gradlew connectedCheck -DandroidMaxThreads=4.

Concerning the timeout I think the getTimeout() method of the DeviceProvider would be the right place to start, though it seems that the timeout is not used consistently. I found at least three different timeouts used for running install/sync commands: DdmPreferences.getTimeout(), System.getenv("ADB_INSTALL_TIMEOUT") and DeviceProvider.getTimeout(). Obviously one can be configured from the user already, although it might not have the expected effect. Maybe the internals of the android tools could find some common ground to specify those seemingly equivalent timeouts and maybe it would also allow to set the timeout from within the gradle config or from cli (e.g. ./gradlew connectedCheck -DandroidInstallTimeout=60000).

Concerning the serials (emphasis on plural), I am currently running a self-patched version of the android gradle plugin which supports a system property which allows to specify a set of serials to run on, e.g.  ./gradlew connectedCheck -DandroidSerials=emulator-5554,emulator-5556


If there is an agreement, I would be happy to contribute this change to upstream and I would also like to contribute to solutions for the timeout and maxThreads problem.
Reply all
Reply to author
Forward
0 new messages