Merge "releasetools: Prefer the avbtool specified in target_files."
diff --git a/core/Makefile b/core/Makefile
index ec9029b..e921dfa 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -658,45 +658,105 @@
 # $(2): output dir
 # $(3): mount point
 # $(4): staging dir
+# $(5): module load list
+# $(6): module load list filename
 # Returns the a list of src:dest pairs to install the modules using copy-many-files.
 define build-image-kernel-modules
   $(foreach module,$(1),$(module):$(2)/lib/modules/$(notdir $(module))) \
-  $(eval $(call build-image-kernel-modules-depmod,$(1),$(2),$(3),$(4))) \
+  $(eval $(call build-image-kernel-modules-depmod,$(1),$(3),$(4),$(5),$(6))) \
   $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep:$(2)/lib/modules/modules.dep \
-  $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias:$(2)/lib/modules/modules.alias
+  $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias:$(2)/lib/modules/modules.alias \
+  $(4)/$(DEPMOD_STAGING_SUBDIR)/$(6):$(2)/lib/modules/$(6)
 endef
 
 # $(1): modules list
-# $(2): output dir
-# $(3): mount point
-# $(4): staging dir
+# $(2): mount point
+# $(3): staging dir
+# $(4): module load list
+# $(5): module load list filename
 define build-image-kernel-modules-depmod
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: .KATI_IMPLICIT_OUTPUTS := $(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(DEPMOD)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULES := $(1)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_OUTPUT_DIR := $(2)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MOUNT_POINT := $(3)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_STAGING_DIR := $(4)
-$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(1)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: .KATI_IMPLICIT_OUTPUTS := $(3)/$(DEPMOD_STAGING_SUBDIR)/modules.alias $(3)/$(DEPMOD_STAGING_SUBDIR)/$(5)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(DEPMOD)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULES := $(1)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MOUNT_POINT := $(2)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULE_DIR := $(3)/$(DEPMOD_STAGING_SUBDIR)/$(2)/lib/modules
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_STAGING_DIR := $(3)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_MODULES := $(4)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_FILE := $(3)/$(DEPMOD_STAGING_SUBDIR)/$(5)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(1)
 	@echo depmod $$(PRIVATE_STAGING_DIR)
 	rm -rf $$(PRIVATE_STAGING_DIR)
-	mkdir -p $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/$$(PRIVATE_MOUNT_POINT)/lib/modules
-	cp $$(PRIVATE_MODULES) $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/$$(PRIVATE_MOUNT_POINT)/lib/modules
+	mkdir -p $$(PRIVATE_MODULE_DIR)
+	cp $$(PRIVATE_MODULES) $$(PRIVATE_MODULE_DIR)/
 	$(DEPMOD) -b $$(PRIVATE_STAGING_DIR) 0.0
 	# Turn paths in modules.dep into absolute paths
-	sed -i.tmp -e 's|\([^: ]*/lib/modules/[^: ]*\)|/\1|g' $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/modules.dep
+	sed -i.tmp -e 's|\([^: ]*lib/modules/[^: ]*\)|/\1|g' $$(PRIVATE_STAGING_DIR)/$$(DEPMOD_STAGING_SUBDIR)/modules.dep
+	touch $$(PRIVATE_LOAD_FILE)
+	(for MODULE in $$(PRIVATE_LOAD_MODULES); do basename $$$$MODULE >> $$(PRIVATE_LOAD_FILE); done)
 endef
 
+# $(1): staging dir
+# $(2): module load list
+# $(3): module load list filename
+# $(4): output dir
+define module-load-list-copy-paths
+  $(eval $(call build-image-module-load-list,$(1),$(2),$(3))) \
+  $(1)/$(DEPMOD_STAGING_SUBDIR)/$(3):$(4)/lib/modules/$(3)
+endef
+
+# $(1): staging dir
+# $(2): module load list
+# $(3): module load list filename
+define build-image-module-load-list
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_STAGING_DIR := $(1)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_LOAD_MODULES := $(2)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_LOAD_FILENAME := $(3)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): $(2)
+	rm -f $$@
+	(for MODULE in $$(PRIVATE_LOAD_MODULES); do basename $$$$MODULE >> $$@; done)
+endef
+
+
+ifeq ($(BOARD_RECOVERY_KERNEL_MODULES_LOAD),)
+  BOARD_RECOVERY_KERNEL_MODULES_LOAD := $(BOARD_RECOVERY_KERNEL_MODULES)
+endif
+ifeq ($(BOARD_RAMDISK_KERNEL_MODULES_LOAD),)
+  BOARD_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_RAMDISK_KERNEL_MODULES)
+endif
+
+ifdef BOARD_RAMDISK_KERNEL_MODULES
+  ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
+    BOARD_RECOVERY_KERNEL_MODULES += $(BOARD_RAMDISK_KERNEL_MODULES)
+  endif
+endif
+
 ifdef BOARD_RECOVERY_KERNEL_MODULES
-  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery)))
+  ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
+    ifdef BOARD_RAMDISK_KERNEL_MODULES_LOAD
+      ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,ramdisk_modules),$(BOARD_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(TARGET_RECOVERY_ROOT_OUT)))
+    endif
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery),$(BOARD_RECOVERY_KERNEL_MODULES_LOAD),modules.load.recovery))
+endif
+
+ifneq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
+  ifdef BOARD_RAMDISK_KERNEL_MODULES
+    ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RAMDISK_KERNEL_MODULES),$(TARGET_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_ramdisk),$(BOARD_RAMDISK_KERNEL_MODULES_LOAD),modules.load))
+  endif
 endif
 
 ifdef BOARD_VENDOR_KERNEL_MODULES
-  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor)))
+  ifeq ($(BOARD_VENDOR_KERNEL_MODULES_LOAD),)
+    BOARD_VENDOR_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_KERNEL_MODULES)
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),modules.load))
 endif
 
 ifdef BOARD_ODM_KERNEL_MODULES
-  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_ODM_KERNEL_MODULES),$(TARGET_OUT_ODM),odm,$(call intermediates-dir-for,PACKAGING,depmod_odm)))
+  ifeq ($(BOARD_RECOVERY_KERNEL_MODULES_LOAD),)
+    BOARD_ODM_KERNEL_MODULES_LOAD := $(BOARD_ODM_KERNEL_MODULES)
+  endif
+  ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_ODM_KERNEL_MODULES),$(TARGET_OUT_ODM),odm,$(call intermediates-dir-for,PACKAGING,depmod_odm),$(BOARD_ODM_KERNEL_MODULES_LOAD),modules.load))
 endif
 
 # -----------------------------------------------------------------
@@ -1088,6 +1148,7 @@
 # Remove when b/63676296 is resolved.
 $(error Prebuilt bootimage is only supported for AB targets)
 endif
+INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
 $(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
 else # BOARD_PREBUILT_BOOTIMAGE not defined
 INSTALLED_BOOTIMAGE_TARGET :=
diff --git a/core/definitions.mk b/core/definitions.mk
index f9816e7..c5e8456 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -2450,7 +2450,7 @@
 # Host init verifier doesn't exist on darwin.
 ifneq ($(HOST_OS),darwin)
 $(2): $(1) $(HOST_INIT_VERIFIER) $(call intermediates-dir-for,ETC,passwd)/passwd
-	$(hide) $(HOST_INIT_VERIFIER) $$< $(call intermediates-dir-for,ETC,passwd)/passwd
+	$(hide) $(HOST_INIT_VERIFIER) -p $(call intermediates-dir-for,ETC,passwd)/passwd $$<
 else
 $(2): $(1)
 endif
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 5693147..570dbd8 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -138,9 +138,7 @@
   $(call end_json_map)
 
   $(call add_json_str,  DirtyImageObjects,                  $(DIRTY_IMAGE_OBJECTS))
-  $(call add_json_str,  PreloadedClasses,                   $(PRELOADED_CLASSES))
   $(call add_json_list, BootImageProfiles,                  $(PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION))
-  $(call add_json_bool, UseProfileForBootImage,             $(call invert_bool,$(filter false,$(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE))))
   $(call add_json_str,  BootFlags,                          $(PRODUCT_DEX_PREOPT_BOOT_FLAGS))
   $(call add_json_str,  Dex2oatImageXmx,                    $(DEX2OAT_IMAGE_XMX))
   $(call add_json_str,  Dex2oatImageXms,                    $(DEX2OAT_IMAGE_XMS))
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index f09493e..e226260 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -187,6 +187,7 @@
     libwifi-service \
     libwilhelm \
     linker \
+    linkerconfig \
     lmkd \
     locksettings \
     logcat \
diff --git a/target/product/mainline_system.mk b/target/product/mainline_system.mk
index 87393d4..f836bd3 100644
--- a/target/product/mainline_system.mk
+++ b/target/product/mainline_system.mk
@@ -99,8 +99,6 @@
 
 # Enable stats logging in LMKD
 TARGET_LMKD_STATS_LOG := true
-PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
-    ro.lmk.log_stats=true
 
 # Enable dynamic partition size
 PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 44719ed..6994430 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -126,7 +126,7 @@
   if not image_size:
     return None
 
-  image_blocks = int(image_size) / 4096 - 1
+  image_blocks = int(image_size) // 4096 - 1
   assert image_blocks > 0, "blocks for {} must be positive".format(which)
 
   # For sparse images, we will only check the blocks that are listed in the care
@@ -154,16 +154,16 @@
     return img.name
 
   def output_sink(fn, data):
-    ofile = open(os.path.join(OPTIONS.input_tmp, "SYSTEM", fn), "w")
-    ofile.write(data)
-    ofile.close()
+    output_file = os.path.join(OPTIONS.input_tmp, "SYSTEM", fn)
+    with open(output_file, "wb") as ofile:
+      ofile.write(data)
 
     if output_zip:
       arc_name = "SYSTEM/" + fn
       if arc_name in output_zip.namelist():
         OPTIONS.replace_updated_files_list.append(arc_name)
       else:
-        common.ZipWrite(output_zip, ofile.name, arc_name)
+        common.ZipWrite(output_zip, output_file, arc_name)
 
   if (OPTIONS.rebuild_recovery and recovery_img is not None and
       boot_img is not None):
@@ -290,7 +290,7 @@
 
 
 def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
-  logger.info("creating " + what + ".img...")
+  logger.info("creating %s.img...", what)
 
   image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
   fstab = info_dict["fstab"]
@@ -778,7 +778,7 @@
   partitions = dict()
 
   def banner(s):
-    logger.info("\n\n++++ " + s + " ++++\n\n")
+    logger.info("\n\n++++ %s  ++++\n\n", s)
 
   boot_image = None
   if has_boot:
@@ -901,7 +901,7 @@
   ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
                                    "ab_partitions.txt")
   if os.path.exists(ab_partitions_txt):
-    with open(ab_partitions_txt, 'r') as f:
+    with open(ab_partitions_txt) as f:
       ab_partitions = f.readlines()
 
     # For devices using A/B update, make sure we have all the needed images
@@ -916,7 +916,7 @@
   pack_radioimages_txt = os.path.join(
       OPTIONS.input_tmp, "META", "pack_radioimages.txt")
   if os.path.exists(pack_radioimages_txt):
-    with open(pack_radioimages_txt, 'r') as f:
+    with open(pack_radioimages_txt) as f:
       AddPackRadioImages(output_zip, f.readlines())
 
   if output_zip:
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index 4b0d4c7..60200a3 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -39,8 +39,11 @@
 
 """
 
+from __future__ import print_function
+
 import logging
 import os
+import os.path
 import re
 import subprocess
 import sys
@@ -49,7 +52,7 @@
 import common
 
 if sys.hexversion < 0x02070000:
-  print >> sys.stderr, "Python 2.7 or newer is required."
+  print("Python 2.7 or newer is required.", file=sys.stderr)
   sys.exit(1)
 
 
@@ -65,8 +68,10 @@
 class MyZipInfo(zipfile.ZipInfo):
   def _decodeExtra(self):
     pass
+
 zipfile.ZipInfo = MyZipInfo
 
+
 OPTIONS = common.OPTIONS
 
 OPTIONS.text = False
@@ -76,28 +81,34 @@
 PROBLEMS = []
 PROBLEM_PREFIX = []
 
+
 def AddProblem(msg):
   PROBLEMS.append(" ".join(PROBLEM_PREFIX) + " " + msg)
+
+
 def Push(msg):
   PROBLEM_PREFIX.append(msg)
+
+
 def Pop():
   PROBLEM_PREFIX.pop()
 
 
 def Banner(msg):
-  print "-" * 70
-  print "  ", msg
-  print "-" * 70
+  print("-" * 70)
+  print("  ", msg)
+  print("-" * 70)
 
 
 def GetCertSubject(cert):
   p = common.Run(["openssl", "x509", "-inform", "DER", "-text"],
                  stdin=subprocess.PIPE,
-                 stdout=subprocess.PIPE)
+                 stdout=subprocess.PIPE,
+                 universal_newlines=False)
   out, err = p.communicate(cert)
   if err and not err.strip():
     return "(error reading cert subject)"
-  for line in out.split("\n"):
+  for line in out.decode().split("\n"):
     line = line.strip()
     if line.startswith("Subject:"):
       return line[8:].strip()
@@ -105,6 +116,7 @@
 
 
 class CertDB(object):
+
   def __init__(self):
     self.certs = {}
 
@@ -132,13 +144,13 @@
           to_load.extend(certs)
 
     for i in to_load:
-      f = open(i)
-      cert = common.ParseCertificate(f.read())
-      f.close()
+      with open(i) as f:
+        cert = common.ParseCertificate(f.read())
       name, _ = os.path.splitext(i)
       name, _ = os.path.splitext(name)
       self.Add(cert, name)
 
+
 ALL_CERTS = CertDB()
 
 
@@ -152,13 +164,14 @@
                     "-outform", "PEM",
                     "-print_certs"],
                    stdin=subprocess.PIPE,
-                   stdout=subprocess.PIPE)
+                   stdout=subprocess.PIPE,
+                   universal_newlines=False)
     out, err = p.communicate(data)
     if err and not err.strip():
-      AddProblem("error reading cert:\n" + err)
+      AddProblem("error reading cert:\n" + err.decode())
       return None
 
-    cert = common.ParseCertificate(out)
+    cert = common.ParseCertificate(out.decode())
     if not cert:
       AddProblem("error parsing cert output")
       return None
@@ -184,22 +197,20 @@
 
   def RecordCerts(self, full_filename):
     out = set()
-    try:
-      f = open(full_filename)
-      apk = zipfile.ZipFile(f, "r")
+    with zipfile.ZipFile(full_filename) as apk:
       pkcs7 = None
       for info in apk.infolist():
-        if info.filename.startswith("META-INF/") and \
-           (info.filename.endswith(".DSA") or info.filename.endswith(".RSA")):
-          pkcs7 = apk.read(info.filename)
-          cert = CertFromPKCS7(pkcs7, info.filename)
+        filename = info.filename
+        if (filename.startswith("META-INF/") and
+            info.filename.endswith((".DSA", ".RSA"))):
+          pkcs7 = apk.read(filename)
+          cert = CertFromPKCS7(pkcs7, filename)
           out.add(cert)
           ALL_CERTS.Add(cert)
       if not pkcs7:
         AddProblem("no signature")
-    finally:
-      f.close()
-      self.certs = frozenset(out)
+
+    self.certs = frozenset(out)
 
   def ReadManifest(self, full_filename):
     p = common.Run(["aapt", "dump", "xmltree", full_filename,
@@ -247,8 +258,8 @@
     # This is the list of wildcards of files we extract from |filename|.
     apk_extensions = ['*.apk', '*.apex']
 
-    self.certmap, compressed_extension = common.ReadApkCerts(
-        zipfile.ZipFile(filename))
+    with zipfile.ZipFile(filename) as input_zip:
+      self.certmap, compressed_extension = common.ReadApkCerts(input_zip)
     if compressed_extension:
       apk_extensions.append('*.apk' + compressed_extension)
 
@@ -287,7 +298,7 @@
     """Look for any instances where packages signed with different
     certs request the same sharedUserId."""
     apks_by_uid = {}
-    for apk in self.apks.itervalues():
+    for apk in self.apks.values():
       if apk.shared_uid:
         apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
 
@@ -302,15 +313,15 @@
 
       AddProblem("different cert sets for packages with uid %s" % (uid,))
 
-      print "uid %s is shared by packages with different cert sets:" % (uid,)
+      print("uid %s is shared by packages with different cert sets:" % (uid,))
       for apk in apks:
-        print "%-*s  [%s]" % (self.max_pkg_len, apk.package, apk.filename)
+        print("%-*s  [%s]" % (self.max_pkg_len, apk.package, apk.filename))
         for cert in apk.certs:
-          print "   ", ALL_CERTS.Get(cert)
-      print
+          print("   ", ALL_CERTS.Get(cert))
+      print()
 
   def CheckExternalSignatures(self):
-    for apk_filename, certname in self.certmap.iteritems():
+    for apk_filename, certname in self.certmap.items():
       if certname == "EXTERNAL":
         # Apps marked EXTERNAL should be signed with the test key
         # during development, then manually re-signed after
@@ -326,25 +337,25 @@
   def PrintCerts(self):
     """Display a table of packages grouped by cert."""
     by_cert = {}
-    for apk in self.apks.itervalues():
+    for apk in self.apks.values():
       for cert in apk.certs:
         by_cert.setdefault(cert, []).append((apk.package, apk))
 
-    order = [(-len(v), k) for (k, v) in by_cert.iteritems()]
+    order = [(-len(v), k) for (k, v) in by_cert.items()]
     order.sort()
 
     for _, cert in order:
-      print "%s:" % (ALL_CERTS.Get(cert),)
+      print("%s:" % (ALL_CERTS.Get(cert),))
       apks = by_cert[cert]
       apks.sort()
       for _, apk in apks:
         if apk.shared_uid:
-          print "  %-*s  %-*s  [%s]" % (self.max_fn_len, apk.filename,
+          print("  %-*s  %-*s  [%s]" % (self.max_fn_len, apk.filename,
                                         self.max_pkg_len, apk.package,
-                                        apk.shared_uid)
+                                        apk.shared_uid))
         else:
-          print "  %-*s  %s" % (self.max_fn_len, apk.filename, apk.package)
-      print
+          print("  %-*s  %s" % (self.max_fn_len, apk.filename, apk.package))
+      print()
 
   def CompareWith(self, other):
     """Look for instances where a given package that exists in both
@@ -365,12 +376,12 @@
             by_certpair.setdefault((other.apks[i].certs,
                                     self.apks[i].certs), []).append(i)
         else:
-          print "%s [%s]: new APK (not in comparison target_files)" % (
-              i, self.apks[i].filename)
+          print("%s [%s]: new APK (not in comparison target_files)" % (
+              i, self.apks[i].filename))
       else:
         if i in other.apks:
-          print "%s [%s]: removed APK (only in comparison target_files)" % (
-              i, other.apks[i].filename)
+          print("%s [%s]: removed APK (only in comparison target_files)" % (
+              i, other.apks[i].filename))
 
     if by_certpair:
       AddProblem("some APKs changed certs")
@@ -378,23 +389,23 @@
       for (old, new), packages in sorted(by_certpair.items()):
         for i, o in enumerate(old):
           if i == 0:
-            print "was", ALL_CERTS.Get(o)
+            print("was", ALL_CERTS.Get(o))
           else:
-            print "   ", ALL_CERTS.Get(o)
+            print("   ", ALL_CERTS.Get(o))
         for i, n in enumerate(new):
           if i == 0:
-            print "now", ALL_CERTS.Get(n)
+            print("now", ALL_CERTS.Get(n))
           else:
-            print "   ", ALL_CERTS.Get(n)
+            print("   ", ALL_CERTS.Get(n))
         for i in sorted(packages):
           old_fn = other.apks[i].filename
           new_fn = self.apks[i].filename
           if old_fn == new_fn:
-            print "  %-*s  [%s]" % (max_pkg_len, i, old_fn)
+            print("  %-*s  [%s]" % (max_pkg_len, i, old_fn))
           else:
-            print "  %-*s  [was: %s; now: %s]" % (max_pkg_len, i,
-                                                  old_fn, new_fn)
-        print
+            print("  %-*s  [was: %s; now: %s]" % (max_pkg_len, i,
+                                                  old_fn, new_fn))
+        print()
 
 
 def main(argv):
@@ -451,9 +462,9 @@
     target_files.CompareWith(compare_files)
 
   if PROBLEMS:
-    print "%d problem(s) found:\n" % (len(PROBLEMS),)
+    print("%d problem(s) found:\n" % (len(PROBLEMS),))
     for p in PROBLEMS:
-      print p
+      print(p)
     return 1
 
   return 0
@@ -464,9 +475,7 @@
     r = main(sys.argv[1:])
     sys.exit(r)
   except common.ExternalError as e:
-    print
-    print "   ERROR: %s" % (e,)
-    print
+    print("\n   ERROR: %s\n" % (e,))
     sys.exit(1)
   finally:
     common.Cleanup()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 995b6d3..edde89c 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -54,7 +54,9 @@
       base_search_path = os.path.join(base_out_path,
                                       os.path.basename(os.getcwd()))
 
+    # Python >= 3.3 returns 'linux', whereas Python 2.7 gives 'linux2'.
     platform_search_path = {
+        "linux": os.path.join(base_search_path, "host/linux-x86"),
         "linux2": os.path.join(base_search_path, "host/linux-x86"),
         "darwin": os.path.join(base_search_path, "host/darwin-x86"),
     }
@@ -459,6 +461,13 @@
   return LoadDictionaryFromLines(data.split("\n"))
 
 
+def LoadDictionaryFromFile(file_path):
+  with open(file_path) as f:
+    lines = list(f.read().splitlines())
+
+  return LoadDictionaryFromLines(lines)
+
+
 def LoadDictionaryFromLines(lines):
   d = {}
   for line in lines:
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index f0ae217..e2b0e3d 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -334,9 +334,9 @@
     in_vendor = any(item.startswith(partition) for item in vendor_item_list)
     if in_framework and in_vendor:
       logger.error(
-          'Cannot extract items from {0} for both the framework and vendor builds. '
-          'Please ensure only one merge config item list includes {0}.'.format(
-              partition))
+          'Cannot extract items from {0} for both the framework and vendor'
+          ' builds. Please ensure only one merge config item list'
+          ' includes {0}.'.format(partition))
       has_error = True
 
   if ('dynamic_partition_list' in framework_misc_info_keys) or (
@@ -500,18 +500,14 @@
       instance.
   """
 
-  def read_helper(d):
-    misc_info_txt = os.path.join(d, 'META', 'misc_info.txt')
-    with open(misc_info_txt) as f:
-      return list(f.read().splitlines())
-
-  framework_dict = common.LoadDictionaryFromLines(
-      read_helper(framework_target_files_temp_dir))
+  misc_info_path = ['META', 'misc_info.txt']
+  framework_dict = common.LoadDictionaryFromFile(
+      os.path.join(framework_target_files_temp_dir, *misc_info_path))
 
   # We take most of the misc info from the vendor target files.
 
-  merged_dict = common.LoadDictionaryFromLines(
-      read_helper(vendor_target_files_temp_dir))
+  merged_dict = common.LoadDictionaryFromFile(
+      os.path.join(vendor_target_files_temp_dir, *misc_info_path))
 
   # Replace certain values in merged_dict with values from
   # framework_dict.
@@ -578,16 +574,12 @@
                    'dynamic_partitions_info.txt')):
     return
 
-  def read_helper(d):
-    dynamic_partitions_info_txt = os.path.join(d, 'META',
-                                               'dynamic_partitions_info.txt')
-    with open(dynamic_partitions_info_txt) as f:
-      return list(f.read().splitlines())
+  dynamic_partitions_info_path = ['META', 'dynamic_partitions_info.txt']
 
-  framework_dynamic_partitions_dict = common.LoadDictionaryFromLines(
-      read_helper(framework_target_files_dir))
-  vendor_dynamic_partitions_dict = common.LoadDictionaryFromLines(
-      read_helper(vendor_target_files_dir))
+  framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
+      os.path.join(framework_target_files_dir, *dynamic_partitions_info_path))
+  vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
+      os.path.join(vendor_target_files_dir, *dynamic_partitions_info_path))
 
   merged_dynamic_partitions_dict = merge_dynamic_partition_info_dicts(
       framework_dict=framework_dynamic_partitions_dict,
@@ -854,12 +846,8 @@
   misc_info_txt = os.path.join(output_target_files_temp_dir, 'META',
                                'misc_info.txt')
 
-  def read_helper():
-    with open(misc_info_txt) as f:
-      return list(f.read().splitlines())
-
-  use_dynamic_partitions = common.LoadDictionaryFromLines(
-      read_helper()).get('use_dynamic_partitions')
+  use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
+      'use_dynamic_partitions')
 
   if use_dynamic_partitions != 'true' and output_super_empty:
     raise ValueError(
@@ -1000,7 +988,8 @@
       OPTIONS.framework_item_list = a
     elif o == '--system-misc-info-keys':
       logger.warning(
-          '--system-misc-info-keys has been renamed to --framework-misc-info-keys'
+          '--system-misc-info-keys has been renamed to '
+          '--framework-misc-info-keys'
       )
       OPTIONS.framework_misc_info_keys = a
     elif o == '--framework-misc-info-keys':
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 3442b27..0e84327 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -1938,7 +1938,7 @@
   target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
   shutil.copyfile(input_file, target_file)
 
-  with zipfile.ZipFile(input_file, 'r') as input_zip:
+  with zipfile.ZipFile(input_file) as input_zip:
     namelist = input_zip.namelist()
 
   input_tmp = common.UnzipTemp(input_file, RETROFIT_DAP_UNZIP_PATTERN)
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 5d0efc3..a7e6bb0 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -154,11 +154,11 @@
 
 def GetApkCerts(certmap):
   # apply the key remapping to the contents of the file
-  for apk, cert in certmap.iteritems():
+  for apk, cert in certmap.items():
     certmap[apk] = OPTIONS.key_map.get(cert, cert)
 
   # apply all the -e options, overriding anything in the file
-  for apk, cert in OPTIONS.extra_apks.iteritems():
+  for apk, cert in OPTIONS.extra_apks.items():
     if not cert:
       cert = "PRESIGNED"
     certmap[apk] = OPTIONS.key_map.get(cert, cert)
@@ -520,14 +520,14 @@
       if stat.S_ISLNK(info.external_attr >> 16):
         new_data = data
       else:
-        new_data = RewriteProps(data)
+        new_data = RewriteProps(data.decode())
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
 
     # Replace the certs in *mac_permissions.xml (there could be multiple, such
     # as {system,vendor}/etc/selinux/{plat,nonplat}_mac_permissions.xml).
     elif filename.endswith("mac_permissions.xml"):
       print("Rewriting %s with new keys." % (filename,))
-      new_data = ReplaceCerts(data)
+      new_data = ReplaceCerts(data.decode())
       common.ZipWriteStr(output_tf_zip, out_info, new_data)
 
     # Ask add_img_to_target_files to rebuild the recovery patch if needed.
@@ -632,17 +632,17 @@
   Raises:
     AssertionError: On finding duplicate entries.
   """
-  for old, new in OPTIONS.key_map.iteritems():
+  for old, new in OPTIONS.key_map.items():
     if OPTIONS.verbose:
       print("    Replacing %s.x509.pem with %s.x509.pem" % (old, new))
 
     try:
       with open(old + ".x509.pem") as old_fp:
         old_cert16 = base64.b16encode(
-            common.ParseCertificate(old_fp.read())).lower()
+            common.ParseCertificate(old_fp.read())).decode().lower()
       with open(new + ".x509.pem") as new_fp:
         new_cert16 = base64.b16encode(
-            common.ParseCertificate(new_fp.read())).lower()
+            common.ParseCertificate(new_fp.read())).decode().lower()
     except IOError as e:
       if OPTIONS.verbose or e.errno != errno.ENOENT:
         print("    Error accessing %s: %s.\nSkip replacing %s.x509.pem with "
@@ -860,7 +860,7 @@
         writable.
     key_path: The path to the PEM encoded X.509 certificate.
   """
-  in_cmdline = input_zip.read("BOOT/cmdline")
+  in_cmdline = input_zip.read("BOOT/cmdline").decode()
   # Copy in_cmdline to output_zip if veritykeyid is not present.
   if "veritykeyid" not in in_cmdline:
     common.ZipWriteStr(output_zip, "BOOT/cmdline", in_cmdline)
@@ -893,7 +893,7 @@
   current in-memory dict contains additional items computed at runtime.
   """
   misc_info_old = common.LoadDictionaryFromLines(
-      input_zip.read('META/misc_info.txt').split('\n'))
+      input_zip.read('META/misc_info.txt').decode().split('\n'))
   items = []
   for key in sorted(misc_info):
     if key in misc_info_old:
@@ -959,7 +959,7 @@
 
 
 def GetApiLevelAndCodename(input_tf_zip):
-  data = input_tf_zip.read("SYSTEM/build.prop")
+  data = input_tf_zip.read("SYSTEM/build.prop").decode()
   api_level = None
   codename = None
   for line in data.split("\n"):
@@ -981,7 +981,7 @@
 
 
 def GetCodenameToApiLevelMap(input_tf_zip):
-  data = input_tf_zip.read("SYSTEM/build.prop")
+  data = input_tf_zip.read("SYSTEM/build.prop").decode()
   api_level = None
   codenames = None
   for line in data.split("\n"):
@@ -999,7 +999,7 @@
   if codenames is None:
     raise ValueError("No ro.build.version.all_codenames in SYSTEM/build.prop")
 
-  result = dict()
+  result = {}
   for codename in codenames:
     codename = codename.strip()
     if codename:
@@ -1023,7 +1023,7 @@
         key.
   """
   keys = {}
-  for line in tf_zip.read("META/apexkeys.txt").split("\n"):
+  for line in tf_zip.read('META/apexkeys.txt').decode().split('\n'):
     line = line.strip()
     if not line:
       continue
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index e142ebb..9a1d163 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -136,7 +136,7 @@
       ReplaceVerityKeyId(input_zip, output_zip, cert_file)
 
     with zipfile.ZipFile(output_file) as output_zip:
-      self.assertEqual(BOOT_CMDLINE1, output_zip.read('BOOT/cmdline'))
+      self.assertEqual(BOOT_CMDLINE1, output_zip.read('BOOT/cmdline').decode())
 
     # Test with the second certificate.
     cert_file = os.path.join(self.testdata_dir, 'testkey.x509.pem')
@@ -146,7 +146,7 @@
       ReplaceVerityKeyId(input_zip, output_zip, cert_file)
 
     with zipfile.ZipFile(output_file) as output_zip:
-      self.assertEqual(BOOT_CMDLINE2, output_zip.read('BOOT/cmdline'))
+      self.assertEqual(BOOT_CMDLINE2, output_zip.read('BOOT/cmdline').decode())
 
   def test_ReplaceVerityKeyId_no_veritykeyid(self):
     BOOT_CMDLINE = (
@@ -164,7 +164,7 @@
       ReplaceVerityKeyId(input_zip, output_zip, None)
 
     with zipfile.ZipFile(output_file) as output_zip:
-      self.assertEqual(BOOT_CMDLINE, output_zip.read('BOOT/cmdline'))
+      self.assertEqual(BOOT_CMDLINE, output_zip.read('BOOT/cmdline').decode())
 
   def test_ReplaceCerts(self):
     cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index 70e3b49..0f0d773 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -98,7 +98,7 @@
     with open(boot_image, 'r+b') as boot_fp:
       boot_fp.seek(-1, os.SEEK_END)
       last_byte = boot_fp.read(1)
-      last_byte = chr(255 - ord(last_byte))
+      last_byte = bytes([255 - ord(last_byte)])
       boot_fp.seek(-1, os.SEEK_END)
       boot_fp.write(last_byte)