Using the dm utility to interact with Android or FirefoxOS devices

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:

  1. 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]  []
    
    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  - push this package file to the device and install it
      killapp  - kills any processes with a particular name
          on device
      launchapp     - launches
          application on device
      ls  - list files on device
      ps  - get information on running processes on device
      pull  [remote] - copy file/dir from device
      push   - copy file/dir to device
      rm  - remove file from device
      rmdir  - recursively remove directory from device
      screencap  - capture screenshot of device in action
      shell  - 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.

Happy command-lining!