Merge branch 'readonly-p4-donut' into donut
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 705ed84..46d3174 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -28,6 +28,7 @@
 class Options(object): pass
 OPTIONS = Options()
 OPTIONS.signapk_jar = "out/host/linux-x86/framework/signapk.jar"
+OPTIONS.dumpkey_jar = "out/host/linux-x86/framework/dumpkey.jar"
 OPTIONS.max_image_size = {}
 OPTIONS.verbose = False
 OPTIONS.tempfiles = []
diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks
index a87d198..33fcf22 100755
--- a/tools/releasetools/sign_target_files_apks
+++ b/tools/releasetools/sign_target_files_apks
@@ -45,6 +45,12 @@
 
       -d and -k options are added to the set of mappings in the order
       in which they appear on the command line.
+
+  -o  (--replace_ota_keys)
+      Replace the certificate (public key) used by OTA package
+      verification with the one specified in the input target_files
+      zip (in the META/otakeys.txt file).  Key remapping (-k and -d)
+      is performed on this key.
 """
 
 import sys
@@ -53,6 +59,8 @@
   print >> sys.stderr, "Python 2.4 or newer is required."
   sys.exit(1)
 
+import cStringIO
+import copy
 import os
 import re
 import subprocess
@@ -65,7 +73,7 @@
 
 OPTIONS.extra_apks = {}
 OPTIONS.key_map = {}
-
+OPTIONS.replace_ota_keys = False
 
 def GetApkCerts(tf_zip):
   certmap = OPTIONS.extra_apks.copy()
@@ -107,18 +115,20 @@
 
   for info in input_tf_zip.infolist():
     data = input_tf_zip.read(info.filename)
+    out_info = copy.copy(info)
     if info.filename.endswith(".apk"):
       name = os.path.basename(info.filename)
       key = apk_key_map.get(name, None)
       if key is not None:
         print "signing: %-*s (%s)" % (maxsize, name, key)
         signed_data = SignApk(data, key, key_passwords[key])
-        output_tf_zip.writestr(info, signed_data)
+        output_tf_zip.writestr(out_info, signed_data)
       else:
         # an APK we're not supposed to sign.
         print "skipping: %s" % (name,)
-        output_tf_zip.writestr(info, data)
-    elif info.filename == "SYSTEM/build.prop":
+        output_tf_zip.writestr(out_info, data)
+    elif info.filename in ("SYSTEM/build.prop",
+                           "RECOVERY/RAMDISK/default.prop"):
       # Change build fingerprint to reflect the fact that apps are signed.
       m = re.search(r"ro\.build\.fingerprint=.*\b(test-keys)\b.*", data)
       if not m:
@@ -130,10 +140,49 @@
         print 'WARNING: ro.build.description does not contain "test-keys"'
       else:
         data = data[:m.start(1)] + "release-keys" + data[m.end(1):]
-      output_tf_zip.writestr(info, data)
+      output_tf_zip.writestr(out_info, data)
     else:
       # a non-APK file; copy it verbatim
-      output_tf_zip.writestr(info, data)
+      output_tf_zip.writestr(out_info, data)
+
+
+def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
+  try:
+    keylist = input_tf_zip.read("META/otakeys.txt").split()
+  except KeyError:
+    raise ExternalError("can't read META/otakeys.txt from input")
+
+  mapped_keys = []
+  for k in keylist:
+    m = re.match(r"^(.*)\.x509\.pem$", k)
+    if not m:
+      raise ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,))
+    k = m.group(1)
+    mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem")
+
+  print "using:\n   ", "\n   ".join(mapped_keys)
+  print "for OTA package verification"
+
+  # recovery uses a version of the key that has been slightly
+  # predigested (by DumpPublicKey.java) and put in res/keys.
+
+  p = common.Run(["java", "-jar", OPTIONS.dumpkey_jar] + mapped_keys,
+                 stdout=subprocess.PIPE)
+  data, _ = p.communicate()
+  if p.returncode != 0:
+    raise ExternalError("failed to run dumpkeys")
+  output_tf_zip.writestr("RECOVERY/RAMDISK/res/keys", data)
+
+  # SystemUpdateActivity uses the x509.pem version of the keys, but
+  # put into a zipfile system/etc/security/otacerts.zip.
+
+  tempfile = cStringIO.StringIO()
+  certs_zip = zipfile.ZipFile(tempfile, "w")
+  for k in mapped_keys:
+    certs_zip.write(k)
+  certs_zip.close()
+  output_tf_zip.writestr("SYSTEM/etc/security/otacerts.zip",
+                         tempfile.getvalue())
 
 
 def main(argv):
@@ -156,16 +205,19 @@
     elif o in ("-k", "--key_mapping"):
       s, d = a.split("=")
       OPTIONS.key_map[s] = d
+    elif o in ("-o", "--replace_ota_keys"):
+      OPTIONS.replace_ota_keys = True
     else:
       return False
     return True
 
   args = common.ParseOptions(argv, __doc__,
-                             extra_opts="s:e:d:k:",
+                             extra_opts="s:e:d:k:o",
                              extra_long_opts=["signapk_jar=",
                                               "extra_apks=",
                                               "default_key_mappings=",
-                                              "key_mapping="],
+                                              "key_mapping=",
+                                              "replace_ota_keys"],
                              extra_option_handler=option_handler)
 
   if len(args) != 2:
@@ -177,6 +229,9 @@
 
   SignApks(input_zip, output_zip)
 
+  if OPTIONS.replace_ota_keys:
+    ReplaceOtaKeys(input_zip, output_zip)
+
   input_zip.close()
   output_zip.close()