Using the dm utility to interact with Android or FirefoxOS devices
Oct 18th, 2012
I promised a few people I’d blog about this, so here you go.
To help with the business of making Android or FirefoxOS devices do our bidding, Mozilla Automation & Tools developed a Python library called mozdevice which allows you to control these devices either using the Android Debug Bridge protocol (which is actually not Android specific: FirefoxOS devices use it too) or the System Under Test protocol (a Mozilla-specific thing).
Anyone familiar with debugging these devices is doubtless familiar with adb, which provides a command line interface that allows you to push/pull files, run a shell, etc. To help test our python code (as well as expand the scope of what’s possible on the command line), I created a similar utility a few months ago called “dm” which provides a command-line interface to the aforementioned mozdevice code. It’s shipped as part of mozdevice, and testing it out is pretty simple if you have virtualenv installed:
virtualenv mozdevice
cd mozdevice
./bin/pip install mozdevice
source bin/activate
dm --help
I generally use this utility for two things:
- Testing out mozdevice code. For example, today we discovered an (unfortunate) bug in devicemanagerADB’s killProcess routine. It was easy to verify both the problem and my fix did what I expected by starting my custom build of fennec and running this command:
dm —package-name org.mozilla.fennec_wlach killapp org.mozilla.fennec_wlach
(yes, it's a bit unfortunate that this bug occurred in the first place: devicemanagerADB really needs unit tests)
2. Day-to-day menial tasks, like getting device info/status, capturing screenshots, etc. You can get a full list of what this utility is capable of by running :help. E.g.:
```
(mozbase)wlach@eideticker:~/src/eideticker$ dm --help
Usage: dm [options] <command> [<args>]
device commands:
info [os|id|uptime|systime|screen|memory|processes] - get
information on a specified aspect of the device (if no argument
given, print all available information)
install <file> - push this package file to the device and install it
killapp <process name> - kills any processes with a particular name
on device
launchapp <appname> <activity name> <intent> <URL> - launches
application on device
ls <remote> - list files on device
ps - get information on running processes on device
pull <local> [remote] - copy file/dir from device
push <local> <remote> - copy file/dir to device
rm <remote> - remove file from device
rmdir <remote> - recursively remove directory from device
screencap <png file> - capture screenshot of device in action
shell <command> - run shell command on device
Options:
-h, --help show this help message and exit
-v, --verbose Verbose output from DeviceManager
--host=HOST Device hostname (only if using TCP/IP)
-p PORT, --port=PORT Custom device port (if using SUTAgent or adb-over-tcp)
-m DMTYPE, --dmtype=DMTYPE
DeviceManager type (adb or sut, defaults to adb)
-d HWID, --hwid=HWID HWID
--package-name=PACKAGENAME
Packagename (if using DeviceManagerADB)
Before you ask, yes, it's technically possible to do much of this with the original adb utility. But (1) some of our internal stuff can't use adb a variety of reasons and (2) some of the tasks above (e.g. launching an app, getting a screenshot) involve considerably more typing with adb than with dm. So it's still a win. </li> </ol>
Happy command-lining!