Backed out e7739a472f09, 3fd142236a0f, and 382ec69cdfb1 (Bug 863445) for Android rc1 and rc2 failures on a CLOSED TREE. r=me
authorNick Alexander <nalexander@mozilla.com>
Fri, 10 May 2013 21:38:52 -0700
changeset 142600 c26aa2631a5070d537371ae1c0dbf90269c2fc0b
parent 142599 a5af2642d1d701f595971e3a679ef6d59124d050
child 142601 bfe5a09bd4db3d86671170a8801fecac018abf23
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersme
bugs863445
milestone23.0a1
backs oute7739a472f09934bfeb5e04dff63b4a39bd832ce
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out e7739a472f09, 3fd142236a0f, and 382ec69cdfb1 (Bug 863445) for Android rc1 and rc2 failures on a CLOSED TREE. r=me
build/mobile/robocop/Makefile.in
build/mobile/robocop/README
build/mobile/robocop/parse_ids.py
mobile/android/base/Makefile.in
mobile/android/base/fennec-ids-generator.py
mobile/android/base/tests/README.rst
testing/mochitest/runtestsremote.py
testing/testsuite-targets.mk
toolkit/mozapps/installer/packager.mk
--- a/build/mobile/robocop/Makefile.in
+++ b/build/mobile/robocop/Makefile.in
@@ -59,65 +59,62 @@ manifest_TARGET   := AndroidManifest.xml
 
 # Install robocop configs and helper
 INSTALL_TARGETS += robocop
 robocop_TARGET  := libs
 robocop_DEST    := $(CURDIR)
 robocop_FILES   := \
   $(TESTPATH)/robocop.ini \
   $(TESTPATH)/robocop_autophone.ini \
+  $(srcdir)/parse_ids.py \
   $(NULL)
 robocop-deps := $(notdir $(robocop_FILES))
 
 MOCHITEST_ROBOCOP_FILES := \
   $(wildcard $(TESTPATH)/*.html) \
   $(wildcard $(TESTPATH)/*.jpg) \
   $(wildcard $(TESTPATH)/*.sjs) \
   $(wildcard $(TESTPATH)/test*.js) \
   $(wildcard $(TESTPATH)/robocop*.js) \
   $(NULL)
 
 GARBAGE += \
   AndroidManifest.xml \
   $(java-tests-dep) \
   $(_JAVA_HARNESS) \
   classes.dex \
+  robocop.apk \
   robocop.ap_ \
-  robocop-debug-signed.apk \
-  robocop-debug-signed-unaligned.apk \
+  robocop-unsigned-unaligned.apk \
+  robocop-unaligned.apk \
   $(robocop-deps) \
   $(NULL)
 
 DEFINES += \
   -DANDROID_PACKAGE_NAME=$(ANDROID_PACKAGE_NAME) \
   $(NULL)
 
 JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar:$(ROBOTIUM_PATH)
 
 include $(topsrcdir)/config/rules.mk
 
 # Override rules.mk java flags with the android specific ones
 include $(topsrcdir)/config/android-common.mk
 
 GENERATED_DIRS_tools = classes $(dir-tests)
 
-libs:: robocop-debug-signed.apk
+tools:: $(robocop-deps) robocop.apk
 
 classes.dex: robocop.ap_
 classes.dex: $(robocop-deps)
 classes.dex: $(java-harness-dep)
 classes.dex: $(java-tests-dep)
 	$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(java-tests-dep)
 	$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH) $(ANDROID_COMPT_LIB)
 
+robocop.apk: $(robocop-deps) robocop.ap_ classes.dex
 robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
 	$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
 
-robocop-debug-signed-unaligned.apk: robocop.ap_ classes.dex
-	$(APKBUILDER) $@ -v $(APKBUILDER_FLAGS) -z robocop.ap_ -f classes.dex
-
-robocop-debug-signed.apk: robocop-debug-signed-unaligned.apk
-	$(ZIPALIGN) -f -v 4 $^ $@
-
 # PP_java-tests not fully usable here
 # Intermediate step toward a library rule.
 $(dir-tests)/%.java: $(TESTPATH)/%.java.in $(call mkdir_deps,$(dir-tests))
 	$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $< > $@
--- a/build/mobile/robocop/README
+++ b/build/mobile/robocop/README
@@ -2,11 +2,8 @@ Robocop is a Mozilla project which uses 
 
 Robotium is an open source tool licensed under the Apache 2.0 license and the original 
 source can be found here:
 http://code.google.com/p/robotium/
 
 We are including robotium-solo-3.6.jar as a binary and are not modifying it in any way 
 from the original download found at: 
 http://code.google.com/p/robotium/
-
-Firefox for Android developers should read the documentation in
-mobile/android/base/tests/README.rst.
rename from mobile/android/base/fennec-ids-generator.py
rename to build/mobile/robocop/parse_ids.py
--- a/mobile/android/base/fennec-ids-generator.py
+++ b/build/mobile/robocop/parse_ids.py
@@ -7,57 +7,58 @@ import os
 import sys
 import optparse
 
 def getFile(filename):
   fHandle = open(filename, 'r')
   data = fHandle.read()
   fHandle.close()
   return data
-
+  
 def findIDs(data):
   start_function = False
   reID = re.compile('.*public static final class id {.*')
   reEnd = re.compile('.*}.*')
   idlist = []
-
+  
   for line in data.split('\n'):
     if reEnd.match(line):
       start_function = False
-
+      
     if start_function:
       id_value = line.split(' ')[-1]
       idlist.append(id_value.split(';')[0].split('='))
-
+      
     if reID.match(line):
       start_function = True
-
+      
   return idlist
-
-
+  
+  
 def printIDs(outputFile, idlist):
   fOutput = open(outputFile, 'w')
   for item in idlist:
     fOutput.write("%s=%s\n" % (item[0], item[1]))
   fOutput.close()
 
 def main(args=sys.argv[1:]):
   parser = optparse.OptionParser()
   parser.add_option('-o', '--output', dest='outputFile', default='',
                     help="output file with the id=value pairs")
   parser.add_option('-i', '--input', dest='inputFile', default='',
                     help="filename of the input R.java file")
   options, args = parser.parse_args(args)
-
+  
   if options.inputFile == '':
     print "Error: please provide input file: -i <filename>"
     sys.exit(1)
 
   if options.outputFile == '':
     print "Error: please provide output file: -o <filename>"
     sys.exit(1)
 
   data = getFile(os.path.abspath(options.inputFile));
   idlist = findIDs(data)
   printIDs(os.path.abspath(options.outputFile), idlist)
 
 if __name__ == "__main__":
     main()
+
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -1086,20 +1086,16 @@ ALL_JARS = \
   jars/sync-thirdparty.jar \
   jars/gecko-mozglue.jar \
   $(NULL)
 
 ifdef MOZ_WEBRTC
 ALL_JARS += jars/webrtc.jar
 endif
 
-INSTALL_TARGETS += fennec_ids
-fennec_ids_FILES := fennec_ids.txt
-fennec_ids_DEST := $(DIST)
-
 include $(topsrcdir)/config/rules.mk
 
 # Override the Java settings with some specific android settings
 include $(topsrcdir)/config/android-common.mk
 
 # Note that we're going to set up a dependency directly between embed_android.dex and the java files
 # Instead of on the .class files, since more than one .class file might be produced per .java file
 # Sync dependencies are provided in a single jar. Sync classes themselves are delivered as source,
@@ -1256,16 +1252,13 @@ RES_BRANDING_DRAWABLE_MDPI = $(addprefix
 
 
 R.java: $(MOZ_APP_ICON) $(RESOURCES) $(RES_DRAWABLE) $(RES_BRANDING_DRAWABLE_MDPI) $(PP_RES_XML) res/drawable-mdpi/icon.png res/drawable-hdpi/icon.png res/drawable-xhdpi/icon.png res/drawable-xxhdpi/icon.png res/values/strings.xml AndroidManifest.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
 
 gecko.ap_: AndroidManifest.xml res/drawable-mdpi/icon.png res/drawable-hdpi/icon.png res/drawable-xhdpi/icon.png res/drawable-xxhdpi/icon.png $(RESOURCES) $(RES_DRAWABLE) $(RES_BRANDING_DRAWABLE_MDPI) $(PP_RES_XML) res/values/strings.xml FORCE
 	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar  -S res -F $@
 
-fennec_ids.txt: fennec-ids-generator.py R.java
-	$(PYTHON) $(topsrcdir)/mobile/android/base/fennec-ids-generator.py -i R.java -o $@
-
 libs:: classes.dex package-name.txt jni-stubs.inc
 	$(INSTALL) classes.dex $(FINAL_TARGET)
 	$(INSTALL) package-name.txt $(FINAL_TARGET)
 	@(diff jni-stubs.inc $(topsrcdir)/mozglue/android/jni-stubs.inc >/dev/null) || \
 	 (echo "*** Error: The jni-stubs have changed. Copy $(CURDIR)/jni-stubs.inc to $(topsrcdir)/mozglue/android" && exit 1)
deleted file mode 100644
--- a/mobile/android/base/tests/README.rst
+++ /dev/null
@@ -1,43 +0,0 @@
-Robocop Mochitest
-=================
-
-*Robocop Mochitest* tests run on Native Android builds marked with an
-'rc' in TBPL.  These are Java based tests which run from the mochitest
-harness and generate similar log files.  These are designed for
-testing the native UI of Android devices by sending events to the
-front end.
-
-See the documentation at
-https://wiki.mozilla.org/Auto-tools/Projects/Robocop/WritingTests for
-details.
-
-Development cycle
------------------
-
-To deploy the robocop APK to your device and start the robocop test
-suite, use::
-
-    make -C $OBJDIR mochitest-robocop
-
-The Java files in ``mobile/android/base/tests`` are dependencies of the
-robocop APK built by ``build/mobile/robocop``.  If you modify Java files
-in ``mobile/android/base/tests``, you need to rebuild the robocop APK
-with::
-
-    mach build/mobile/robocop
-
-Changes to ``.html``, ``.css``, ``.sjs``, and ``.js`` files in
-``mobile/android/base/tests`` do not require rebuilding the robocop
-APK -- these changes are always 'live', since they are served by the
-mochitest HTTP server and downloaded each test run by your device.
-
-``mach package`` does build and sign a robocop APK, but ``make
-mochitest-robocop`` does not use it.  (This signed APK is used to test
-signed releases on the buildbots).
-
-As always, changes to ``mobile/android/base``, ``mobile/android/chrome``,
-``mobile/android/modules``, etc., require::
-
-    mach mobile/android/base && mach package && mach install
-
-as usual.
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -75,34 +75,24 @@ class RemoteOptions(MochitestOptions):
                     help = "ssl port of the remote web server")
         defaults["sslPort"] = automation.DEFAULT_SSL_PORT
 
         self.add_option("--pidfile", action = "store",
                     type = "string", dest = "pidFile",
                     help = "name of the pidfile to generate")
         defaults["pidFile"] = ""
 
-        self.add_option("--robocop-ini", action = "store",
-                    type = "string", dest = "robocopIni",
-                    help = "name of the .ini file containing the list of tests to run")
-        defaults["robocopIni"] = ""
-
         self.add_option("--robocop", action = "store",
                     type = "string", dest = "robocop",
-                    help = "name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini")
+                    help = "name of the .ini file containing the list of tests to run")
         defaults["robocop"] = ""
 
-        self.add_option("--robocop-apk", action = "store",
-                    type = "string", dest = "robocopApk",
-                    help = "name of the Robocop APK to use for ADB test running")
-        defaults["robocopApk"] = ""
-
         self.add_option("--robocop-path", action = "store",
                     type = "string", dest = "robocopPath",
-                    help = "Path to the folder where robocop.apk is located at.  Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk]")
+                    help = "Path to the folder where robocop.apk is located at.  Primarily used for ADB test running")
         defaults["robocopPath"] = ""
 
         self.add_option("--robocop-ids", action = "store",
                     type = "string", dest = "robocopIds",
                     help = "name of the file containing the view ID map (fennec_ids.txt)")
         defaults["robocopIds"] = ""
 
         self.add_option("--remoteTestRoot", action = "store",
@@ -163,47 +153,32 @@ class RemoteOptions(MochitestOptions):
             else:
                 options.xrePath = options.utilityPath
 
         if (options.pidFile != ""):
             f = open(options.pidFile, 'w')
             f.write("%s" % os.getpid())
             f.close()
 
-        # Robocop specific deprecated options.
-        if options.robocop:
-            if options.robocopIni:
-                print "ERROR: can not use deprecated --robocop and replacement --robocop-ini together"
-                return None
-            options.robocopIni = options.robocop
-            del options.robocop
-
-        if options.robocopPath:
-            if options.robocopApk:
-                print "ERROR: can not use deprecated --robocop-path and replacement --robocop-apk together"
+        # Robocop specific options
+        if options.robocop != "":
+            if not os.path.exists(options.robocop):
+                print "ERROR: Unable to find specified manifest '%s'" % options.robocop
                 return None
-            options.robocopApk = os.path.join(options.robocopPath, 'robocop.apk')
-            del options.robocopPath
+            options.robocop = os.path.abspath(options.robocop)
 
-        # Robocop specific options
-        if options.robocopIni != "":
-            if not os.path.exists(options.robocopIni):
-                print "ERROR: Unable to find specified robocop .ini manifest '%s'" % options.robocopIni
+        if options.robocopPath != "":
+            if not os.path.exists(os.path.join(options.robocopPath, 'robocop.apk')):
+                print "ERROR: Unable to find robocop.apk in path '%s'" % options.robocopPath
                 return None
-            options.robocopIni = os.path.abspath(options.robocopIni)
-
-        if options.robocopApk != "":
-            if not os.path.exists(options.robocopApk):
-                print "ERROR: Unable to find robocop APK '%s'" % options.robocopApk
-                return None
-            options.robocopApk = os.path.abspath(options.robocopApk)
+            options.robocopPath = os.path.abspath(options.robocopPath)
 
         if options.robocopIds != "":
             if not os.path.exists(options.robocopIds):
-                print "ERROR: Unable to find specified robocop IDs file '%s'" % options.robocopIds
+                print "ERROR: Unable to find specified IDs file '%s'" % options.robocopIds
                 return None
             options.robocopIds = os.path.abspath(options.robocopIds)
 
         # allow us to keep original application around for cleanup while running robocop via 'am'
         options.remoteappname = options.app
         return options
 
     def verifyOptions(self, options, mochitest):
@@ -328,17 +303,17 @@ class MochiRemote(Mochitest):
     def buildProfile(self, options):
         if self.localProfile:
             options.profilePath = self.localProfile
         manifest = Mochitest.buildProfile(self, options)
         self.localProfile = options.profilePath
         self._dm.removeDir(self.remoteProfile)
 
         # we do not need this for robotium based tests, lets save a LOT of time
-        if options.robocopIni:
+        if options.robocop:
             shutil.rmtree(os.path.join(options.profilePath, 'webapps'))
             shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'mochikit@mozilla.org'))
             shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'worker-test@mozilla.org'))
             shutil.rmtree(os.path.join(options.profilePath, 'extensions', 'staged', 'workerbootstrap-test@mozilla.org'))
             os.remove(os.path.join(options.profilePath, 'userChrome.css'))
             if os.path.exists(os.path.join(options.profilePath, 'tests.jar')):
                 os.remove(os.path.join(options.profilePath, 'tests.jar'))
             if os.path.exists(os.path.join(options.profilePath, 'tests.manifest')):
@@ -355,17 +330,17 @@ class MochiRemote(Mochitest):
     
     def buildURLOptions(self, options, env):
         self.localLog = options.logFile
         options.logFile = self.remoteLog
         options.profilePath = self.localProfile
         env["MOZ_HIDE_RESULTS_TABLE"] = "1"
         retVal = Mochitest.buildURLOptions(self, options, env)
 
-        if not options.robocopIni:
+        if not options.robocop:
             #we really need testConfig.js (for browser chrome)
             try:
                 self._dm.pushDir(options.profilePath, self.remoteProfile)
             except devicemanager.DMError:
                 print "Automation Error: Unable to copy profile to device."
                 raise
 
         options.profilePath = self.remoteProfile
@@ -510,17 +485,16 @@ class MochiRemote(Mochitest):
         return browserEnv
 
         
 def main():
     scriptdir = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
     auto = RemoteAutomation(None, "fennec")
     parser = RemoteOptions(auto, scriptdir)
     options, args = parser.parse_args()
-
     if (options.dm_trans == "adb"):
         if (options.deviceIP):
             dm = droid.DroidADB(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
         else:
             dm = droid.DroidADB(deviceRoot=options.remoteTestRoot)
     else:
          dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
     auto.setDeviceManager(dm)
@@ -547,22 +521,22 @@ def main():
     auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)
 
     print dm.getInfo()
 
     procName = options.app.split('/')[-1]
     if (dm.processExist(procName)):
         dm.killProcess(procName)
 
-    if options.robocopIni != "":
+    if options.robocop != "":
         # sut may wait up to 300 s for a robocop am process before returning
         dm.default_timeout = 320
         mp = manifestparser.TestManifest(strict=False)
         # TODO: pull this in dynamically
-        mp.read(options.robocopIni)
+        mp.read(options.robocop)
         robocop_tests = mp.active_tests(exists=False)
         tests = []
         my_tests = tests
         for test in robocop_tests:
             tests.append(test['name'])
 
         if options.totalChunks:
             tests_per_chunk = math.ceil(len(tests) / (options.totalChunks * 1.0))
@@ -580,18 +554,18 @@ def main():
             fennec_ids = options.robocopIds
         dm.pushFile(fennec_ids, os.path.join(deviceRoot, "fennec_ids.txt"))
         options.extraPrefs.append('robocop.logfile="%s/robocop.log"' % deviceRoot)
         options.extraPrefs.append('browser.search.suggest.enabled=true')
         options.extraPrefs.append('browser.search.suggest.prompted=true')
         options.extraPrefs.append('browser.viewport.scaleRatio=100')
         options.extraPrefs.append('browser.chrome.dynamictoolbar=false')
 
-        if (options.dm_trans == 'adb' and options.robocopApk):
-          dm._checkCmd(["install", "-r", options.robocopApk])
+        if (options.dm_trans == 'adb' and options.robocopPath):
+          dm._checkCmd(["install", "-r", os.path.join(options.robocopPath, "robocop.apk")])
 
         retVal = None
         for test in robocop_tests:
             if options.testPath and options.testPath != test['name']:
                 continue
 
             if not test['name'] in my_tests:
                 continue
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -58,25 +58,23 @@ RERUN_MOCHITEST = \
 RUN_MOCHITEST_REMOTE = \
   rm -f ./$@.log && \
   $(PYTHON) _tests/testing/mochitest/runtestsremote.py --autorun --close-when-done \
     --console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) --dm_trans=$(DM_TRANS) \
     --app=$(TEST_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \
     --testing-modules-dir=$(call core_abspath,_tests/modules) \
     $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
-RUN_MOCHITEST_ROBOCOP = \
+RUN_MOCHITEST_ROBOTIUM = \
   rm -f ./$@.log && \
-  $(PYTHON) _tests/testing/mochitest/runtestsremote.py \
-    --robocop-apk=$(DEPTH)/build/mobile/robocop/robocop-debug-signed.apk \
-    --robocop-ini=$(DEPTH)/build/mobile/robocop/robocop.ini \
-    --robocop-ids=$(DIST)/fennec_ids.txt \
+  $(PYTHON) _tests/testing/mochitest/runtestsremote.py --robocop-path=$(DEPTH)/dist \
+    --robocop-ids=$(DEPTH)/build/mobile/robocop/fennec_ids.txt \
     --console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) --dm_trans=$(DM_TRANS) \
     --app=$(TEST_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \
-    $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
+    --robocop=$(DEPTH)/build/mobile/robocop/robocop.ini $(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
 
 ifndef NO_FAIL_ON_TEST_ERRORS
 define check_test_error_internal
   @errors=`grep "TEST-UNEXPECTED-" $@.log` ;\
   if test "$$errors" ; then \
 	  echo "$@ failed:"; \
 	  echo "$$errors"; \
           $(if $(1),echo $(1)) \
@@ -92,27 +90,25 @@ mochitest-remote:
 	@if [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \
         echo "please prepare your host with the environment variable MOZ_HOST_BIN"; \
     elif [ "${TEST_DEVICE}" = "" -a "$(DM_TRANS)" != "adb" ]; then \
         echo "please prepare your host with the environment variable TEST_DEVICE"; \
     else \
         $(RUN_MOCHITEST_REMOTE); \
     fi
 
-mochitest-robotium: mochitest-robocop
-	@echo "mochitest-robotium is deprecated -- please use mochitest-robocop"
-
-mochitest-robocop: DM_TRANS?=adb
-mochitest-robocop:
+mochitest-robotium: robotium-id-map
+mochitest-robotium: DM_TRANS?=adb
+mochitest-robotium:
 	@if [ ! -f ${MOZ_HOST_BIN}/xpcshell ]; then \
         echo "please prepare your host with the environment variable MOZ_HOST_BIN"; \
     elif [ "${TEST_DEVICE}" = "" -a "$(DM_TRANS)" != "adb" ]; then \
         echo "please prepare your host with the environment variable TEST_DEVICE"; \
     else \
-        $(RUN_MOCHITEST_ROBOCOP); \
+        $(RUN_MOCHITEST_ROBOTIUM); \
     fi
 
 ifdef MOZ_B2G
 mochitest-plain:
 	@if [ "${GAIA_PROFILE_DIR}"  = "" ]; then \
         echo "please specify the GAIA_PROFILE_DIR env variable"; \
     else \
         $(RUN_MOCHITEST_B2G_DESKTOP); \
@@ -434,18 +430,27 @@ make-stage-dir:
 	$(NSINSTALL) -D $(PKG_STAGE)/jetpack
 	$(NSINSTALL) -D $(PKG_STAGE)/peptest
 	$(NSINSTALL) -D $(PKG_STAGE)/mozbase
 	$(NSINSTALL) -D $(PKG_STAGE)/modules
 
 stage-b2g: make-stage-dir
 	$(NSINSTALL) $(topsrcdir)/b2g/test/b2g-unittest-requirements.txt $(PKG_STAGE)/b2g
 
+robotium-id-map:
+ifeq ($(MOZ_BUILD_APP),mobile/android)
+	$(PYTHON) $(DEPTH)/build/mobile/robocop/parse_ids.py -i $(DEPTH)/mobile/android/base/R.java -o $(DEPTH)/build/mobile/robocop/fennec_ids.txt
+endif
+
+stage-mochitest: robotium-id-map
 stage-mochitest: make-stage-dir
 	$(MAKE) -C $(DEPTH)/testing/mochitest stage-package
+ifeq ($(MOZ_BUILD_APP),mobile/android)
+	$(NSINSTALL) $(DEPTH)/build/mobile/robocop/fennec_ids.txt $(PKG_STAGE)/mochitest
+endif
 
 stage-reftest: make-stage-dir
 	$(MAKE) -C $(DEPTH)/layout/tools/reftest stage-package
 
 stage-xpcshell: make-stage-dir
 	$(MAKE) -C $(DEPTH)/testing/xpcshell stage-package
 
 stage-jstests: make-stage-dir
--- a/toolkit/mozapps/installer/packager.mk
+++ b/toolkit/mozapps/installer/packager.mk
@@ -323,19 +323,21 @@ GECKO_APP_AP_PATH = $(call core_abspath,
 
 ifdef ENABLE_TESTS
 INNER_ROBOCOP_PACKAGE=echo
 ifeq ($(MOZ_BUILD_APP),mobile/android)
 UPLOAD_EXTRA_FILES += robocop.apk
 UPLOAD_EXTRA_FILES += fennec_ids.txt
 ROBOCOP_PATH = $(call core_abspath,$(_ABS_DIST)/../build/mobile/robocop)
 INNER_ROBOCOP_PACKAGE= \
-  cp $(ROBOCOP_PATH)/robocop-debug-signed-unaligned.apk $(_ABS_DIST)/robocop-unaligned.apk && \
-  $(JARSIGNER) $(_ABS_DIST)/robocop-unaligned.apk && \
-  $(ZIPALIGN) -f -v 4 $(_ABS_DIST)/robocop-unaligned.apk $(_ABS_DIST)/robocop.apk
+  $(PYTHON) $(abspath $(topsrcdir)/build/mobile/robocop/parse_ids.py) -i $(call core_abspath,$(DEPTH)/mobile/android/base/R.java) -o $(call core_abspath,$(DEPTH)/build/mobile/robocop/fennec_ids.txt) && \
+  $(NSINSTALL) $(call core_abspath,$(DEPTH)/build/mobile/robocop/fennec_ids.txt) $(_ABS_DIST) && \
+  $(APKBUILDER) $(_ABS_DIST)/robocop-raw.apk -v $(APKBUILDER_FLAGS) -z $(ROBOCOP_PATH)/robocop.ap_ -f $(ROBOCOP_PATH)/classes.dex && \
+  $(JARSIGNER) $(_ABS_DIST)/robocop-raw.apk && \
+  $(ZIPALIGN) -f -v 4 $(_ABS_DIST)/robocop-raw.apk $(_ABS_DIST)/robocop.apk
 endif
 else
 INNER_ROBOCOP_PACKAGE=echo 'Testing is disabled - No Robocop for you'
 endif
 
 ifdef MOZ_OMX_PLUGIN
 DIST_FILES += libomxplugin.so libomxplugingb.so libomxplugingb235.so libomxpluginhc.so libomxpluginsony.so libomxpluginfroyo.so libomxpluginjb-htc.so
 endif