the last component of the build fingerprint). Prefix each with
'+' or '-' to indicate whether that tag should be added or
removed. Changes are processed in the order they appear.
- Default value is "-test-keys,+ota-rel-keys,+release-keys".
+ Default value is "-test-keys,+release-keys".
"""
OPTIONS.extra_apks = {}
OPTIONS.key_map = {}
OPTIONS.replace_ota_keys = False
-OPTIONS.tag_changes = ("-test-keys", "+ota-rel-keys", "+release-keys")
+OPTIONS.tag_changes = ("-test-keys", "+release-keys")
def GetApkCerts(tf_zip):
- certmap = {}
- for line in tf_zip.read("META/apkcerts.txt").split("\n"):
- line = line.strip()
- if not line: continue
- m = re.match(r'^name="(.*)"\s+certificate="(.*)\.x509\.pem"\s+'
- r'private_key="\2\.pk8"$', line)
- if not m:
- raise SigningError("failed to parse line from apkcerts.txt:\n" + line)
- certmap[m.group(1)] = OPTIONS.key_map.get(m.group(2), m.group(2))
+ certmap = common.ReadApkCerts(tf_zip)
+
+ # apply the key remapping to the contents of the file
+ for apk, cert in certmap.iteritems():
+ 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():
certmap[apk] = OPTIONS.key_map.get(cert, cert)
+
return certmap
sys.exit(1)
-def SharedUserForApk(data):
- tmp = tempfile.NamedTemporaryFile()
- tmp.write(data)
- tmp.flush()
-
- p = common.Run(["aapt", "dump", "xmltree", tmp.name, "AndroidManifest.xml"],
- stdout=subprocess.PIPE)
- data, _ = p.communicate()
- if p.returncode != 0:
- raise ExternalError("failed to run aapt dump")
- lines = data.split("\n")
- for i in lines:
- m = re.match(r'^\s*A: android:sharedUserId\([0-9a-fx]*\)="([^"]*)" .*$', i)
- if m:
- return m.group(1)
- return None
-
-
-def CheckSharedUserIdsConsistent(input_tf_zip, apk_key_map):
- """Check that all packages that request the same shared user id are
- going to be signed with the same key."""
-
- shared_user_apks = {}
- maxlen = len("(unknown key)")
-
- for info in input_tf_zip.infolist():
- if info.filename.endswith(".apk"):
- data = input_tf_zip.read(info.filename)
-
- name = os.path.basename(info.filename)
- shared_user = SharedUserForApk(data)
- key = apk_key_map[name]
- maxlen = max(maxlen, len(key))
-
- if shared_user is not None:
- shared_user_apks.setdefault(
- shared_user, {}).setdefault(key, []).append(name)
-
- errors = []
- for k, v in shared_user_apks.iteritems():
- # each shared user should have exactly one key used for all the
- # apks that want that user.
- if len(v) > 1:
- errors.append((k, v))
-
- if not errors: return
-
- print "ERROR: shared user inconsistency. All apks wanting to use"
- print " a given shared user must be signed with the same key."
- print
- errors.sort()
- for user, keys in errors:
- print 'shared user id "%s":' % (user,)
- for key, apps in keys.iteritems():
- print ' %-*s %s' % (maxlen, key or "(unknown key)", apps[0])
- for a in apps[1:]:
- print (' ' * (maxlen+5)) + a
- print
-
- sys.exit(1)
-
-
def SignApk(data, keyname, pw):
unsigned = tempfile.NamedTemporaryFile()
unsigned.write(data)
if info.filename.endswith(".apk"):
name = os.path.basename(info.filename)
key = apk_key_map[name]
- if key:
+ if key not in common.SPECIAL_CERT_STRINGS:
print " signing: %-*s (%s)" % (maxsize, name, key)
signed_data = SignApk(data, key, key_passwords[key])
output_tf_zip.writestr(out_info, signed_data)
apk_key_map = GetApkCerts(input_zip)
CheckAllApksSigned(input_zip, apk_key_map)
- CheckSharedUserIdsConsistent(input_zip, apk_key_map)
key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
SignApks(input_zip, output_zip, apk_key_map, key_passwords)