1eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker#!/usr/bin/env python 2eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 3eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# Copyright (C) 2008 The Android Open Source Project 4eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 5eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# Licensed under the Apache License, Version 2.0 (the "License"); 6eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# you may not use this file except in compliance with the License. 7eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# You may obtain a copy of the License at 8eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 9eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# http://www.apache.org/licenses/LICENSE-2.0 10eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 11eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# Unless required by applicable law or agreed to in writing, software 12eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# distributed under the License is distributed on an "AS IS" BASIS, 13eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# See the License for the specific language governing permissions and 15eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# limitations under the License. 16eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 17eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker""" 18eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerGiven a target-files zipfile, produces an OTA package that installs 19eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerthat build. An incremental OTA is produced if -i is given, otherwise 20eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkera full OTA is produced. 21eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 22eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerUsage: ota_from_target_files [flags] input_target_files output_ota_package 23eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 2425568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker --board_config <file> 25fdd8e69c42e66fb70384bcaca1747f504f2c021cDoug Zongker Deprecated. 26eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 27afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker -k (--package_key) <key> Key to use to sign the package (default is 28afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker the value of default_system_dev_certificate from the input 29afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker target-files's META/misc_info.txt, or 30afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker "build/target/product/security/testkey" if that value is not 31afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker specified). 32afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker 33afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker For incremental OTAs, the default value is based on the source 34afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker target-file, not the target build. 35eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 36eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker -i (--incremental_from) <file> 37eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker Generate an incremental OTA using the given target-files zip as 38eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker the starting build. 39eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 40e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge -v (--verify) 41e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge Remount and verify the checksums of the files written to the 42e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge system and vendor (if used) partitions. Incremental builds only. 43e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge 446e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge -o (--oem_settings) <file> 456e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge Use the file to specify the expected OEM-specific properties 466e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge on the OEM partition of the intended device. 476e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 48dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker -w (--wipe_user_data) 49dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker Generate an OTA package that will wipe the user data partition 50dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker when installed. 51dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker 52962069ce59c85949d147874df2728a5ffd9193beDoug Zongker -n (--no_prereq) 53962069ce59c85949d147874df2728a5ffd9193beDoug Zongker Omit the timestamp prereq check normally included at the top of 54962069ce59c85949d147874df2728a5ffd9193beDoug Zongker the build scripts (used for developer OTA packages which 55962069ce59c85949d147874df2728a5ffd9193beDoug Zongker legitimately need to go back and forth). 56962069ce59c85949d147874df2728a5ffd9193beDoug Zongker 571c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker -e (--extra_script) <file> 581c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker Insert the contents of file at the end of the update script. 591c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker 60dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov -a (--aslr_mode) <on|off> 61dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov Specify whether to turn on ASLR for the package (on by default). 6256882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalley 639b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker -2 (--two_step) 649b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker Generate a 'two-step' OTA package, where recovery is updated 659b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker first, so that any changes made to the system partition are done 669b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker using the new recovery (new kernel, etc.). 679b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 6826e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker --block 6926e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker Generate a block-based OTA if possible. Will fall back to a 7026e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker file-based OTA if the target_files is older and doesn't support 7126e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker block-based OTAs. 7226e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker 7325568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker -b (--binary) <file> 7425568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker Use the given binary as the update-binary in the output package, 7525568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker instead of the binary in the build's target_files. Use for 7625568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker development only. 7725568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker 78374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl -t (--worker_threads) <int> 79374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl Specifies the number of worker-threads that will be used when 80374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl generating patches for incremental updates (defaults to 3). 81374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl 82eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker""" 83eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 84eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport sys 85eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 86cf6d5a90740e50e03d9f16c6fd449d90d396f924Doug Zongkerif sys.hexversion < 0x02070000: 87cf6d5a90740e50e03d9f16c6fd449d90d396f924Doug Zongker print >> sys.stderr, "Python 2.7 or newer is required." 88eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sys.exit(1) 89eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 90eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport copy 91c18736b1a777c386dc3c5e3f878249770b5edd78Doug Zongkerimport errno 92fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongkerimport multiprocessing 93eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport os 94eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport re 95eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport subprocess 96eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport tempfile 97eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport time 98eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport zipfile 99eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 100fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongkerfrom hashlib import sha1 as sha1 101cad0bb9f621ff1ccfb584e18249b09768c30a0c0david 102eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport common 103c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongkerimport edify_generator 10436bd365625e6beba77698a93795a603180a5b476Geremy Condraimport build_image 105fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongkerimport blockimgdiff 106fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongkerimport sparse_img 107eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 108eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS = common.OPTIONS 109afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug ZongkerOPTIONS.package_key = None 110eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS.incremental_source = None 111e8269481084df086a04c6bdcd3477d4209d4a7cbMichael RungeOPTIONS.verify = False 112eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS.require_verbatim = set() 113eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS.prohibit_verbatim = set(("system/build.prop",)) 114eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS.patch_threshold = 0.95 115dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug ZongkerOPTIONS.wipe_user_data = False 116962069ce59c85949d147874df2728a5ffd9193beDoug ZongkerOPTIONS.omit_prereq = False 1171c390a2aa97127ef8af8b0df1d4028f501fdce64Doug ZongkerOPTIONS.extra_script = None 118dafb04275588fff8248b6a5360ca047cdffd14a5Hristo BojinovOPTIONS.aslr_mode = True 119fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug ZongkerOPTIONS.worker_threads = multiprocessing.cpu_count() // 2 120fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongkerif OPTIONS.worker_threads == 0: 121fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker OPTIONS.worker_threads = 1 1229b23f2cd786b46991b7c0198e69264b17875288dDoug ZongkerOPTIONS.two_step = False 123e153b3464374155d03bfe47092faaab555b89e81Takeshi KanemotoOPTIONS.no_signing = False 12426e6619c37e294fe2ee63aaa759e0ac861775ce8Doug ZongkerOPTIONS.block_based = False 12525568486e5777f416d2fcb6cc7aa96caafc66880Doug ZongkerOPTIONS.updater_binary = None 1266e836116f764cf5cebf1654df2f17d8222554f6eMichael RungeOPTIONS.oem_source = None 12762d4f18a30aeade677ca814cf6f2aa329cf5066dDoug ZongkerOPTIONS.fallback_to_full = True 128eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 129eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef MostPopularKey(d, default): 130eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker """Given a dict, return the key corresponding to the largest 131eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker value. Returns 'default' if the dict is empty.""" 132eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker x = [(v, k) for (k, v) in d.iteritems()] 133eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if not x: return default 134eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker x.sort() 135eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return x[-1][1] 136eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 137eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 138eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef IsSymlink(info): 139eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker """Return true if the zipfile.ZipInfo object passed in represents a 140eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker symlink.""" 141eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return (info.external_attr >> 16) == 0120777 142eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 14396be7205dce97977909e93b73f48779fcce3bc65Hristo Bojinovdef IsRegular(info): 14496be7205dce97977909e93b73f48779fcce3bc65Hristo Bojinov """Return true if the zipfile.ZipInfo object passed in represents a 14596be7205dce97977909e93b73f48779fcce3bc65Hristo Bojinov symlink.""" 14696be7205dce97977909e93b73f48779fcce3bc65Hristo Bojinov return (info.external_attr >> 28) == 010 147eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1484038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Rungedef ClosestFileMatch(src, tgtfiles, existing): 1494038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge """Returns the closest file match between a source file and list 1504038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge of potential matches. The exact filename match is preferred, 1514038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge then the sha1 is searched for, and finally a file with the same 1524038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge basename is evaluated. Rename support in the updater-binary is 1534038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge required for the latter checks to be used.""" 1544038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge 1554038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge result = tgtfiles.get("path:" + src.name) 1564038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if result is not None: 1574038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return result 1584038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge 1594038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if not OPTIONS.target_info_dict.get("update_rename_support", False): 1604038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return None 1614038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge 1624038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if src.size < 1000: 1634038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return None 1644038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge 1654038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge result = tgtfiles.get("sha1:" + src.sha1) 1664038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if result is not None and existing.get(result.name) is None: 1674038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return result 1684038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge result = tgtfiles.get("file:" + src.name.split("/")[-1]) 1694038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if result is not None and existing.get(result.name) is None: 1704038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return result 1714038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return None 1724038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge 173c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongkerclass ItemSet: 174c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def __init__(self, partition, fs_config): 175c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.partition = partition 176c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.fs_config = fs_config 177c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.ITEMS = {} 178c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 179c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def Get(self, name, dir=False): 180c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if name not in self.ITEMS: 181c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.ITEMS[name] = Item(self, name, dir=dir) 182c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker return self.ITEMS[name] 183c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 184c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def GetMetadata(self, input_zip): 1850eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # The target_files contains a record of what the uid, 1860eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # gid, and mode are supposed to be. 187c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker output = input_zip.read(self.fs_config) 188eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 189eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for line in output.split("\n"): 190eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if not line: continue 1910eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich columns = line.split() 1920eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich name, uid, gid, mode = columns[:4] 1930eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich selabel = None 1940eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich capabilities = None 1950eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich 1960eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # After the first 4 columns, there are a series of key=value 1970eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # pairs. Extract out the fields we care about. 1980eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich for element in columns[4:]: 1990eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich key, value = element.split("=") 2000eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if key == "selabel": 2010eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich selabel = value 2020eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if key == "capabilities": 2030eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich capabilities = value 2040eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich 205c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker i = self.ITEMS.get(name, None) 206283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker if i is not None: 207283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker i.uid = int(uid) 208283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker i.gid = int(gid) 209283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker i.mode = int(mode, 8) 2100eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich i.selabel = selabel 2110eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich i.capabilities = capabilities 212283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker if i.dir: 213283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker i.children.sort(key=lambda i: i.name) 214283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker 215283e2a1e1bae4e21824969a15da6420204633dddDoug Zongker # set metadata for the files generated by this script. 216c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker i = self.ITEMS.get("system/recovery-from-boot.p", None) 2170eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0644, None, None 218c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker i = self.ITEMS.get("system/etc/install-recovery.sh", None) 2190eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if i: i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0544, None, None 220eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 221c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 222c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongkerclass Item: 223c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker """Items represent the metadata (user, group, mode) of files and 224c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker directories in the system image.""" 225c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def __init__(self, itemset, name, dir=False): 226c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.itemset = itemset 227c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.name = name 228c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.uid = None 229c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.gid = None 230c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.mode = None 231c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.selabel = None 232c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.capabilities = None 233c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.dir = dir 234c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 235c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if name: 236c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.parent = itemset.Get(os.path.dirname(name), dir=True) 237c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.parent.children.append(self) 238c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker else: 239c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.parent = None 240c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if dir: 241c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.children = [] 242c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 243c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def Dump(self, indent=0): 244c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if self.uid is not None: 245c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "%s%s %d %d %o" % (" "*indent, self.name, self.uid, self.gid, self.mode) 246c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker else: 247c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "%s%s %s %s %s" % (" "*indent, self.name, self.uid, self.gid, self.mode) 248c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if self.dir: 249c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "%s%s" % (" "*indent, self.descendants) 250c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "%s%s" % (" "*indent, self.best_subtree) 251c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for i in self.children: 252c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker i.Dump(indent=indent+1) 253c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 254eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker def CountChildMetadata(self): 2550eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich """Count up the (uid, gid, mode, selabel, capabilities) tuples for 2560eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich all children and determine the best strategy for using set_perm_recursive and 257eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker set_perm to correctly chown/chmod all the files to their desired 258eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker values. Recursively calls itself for all descendants. 259eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 2600eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich Returns a dict of {(uid, gid, dmode, fmode, selabel, capabilities): count} counting up 261eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker all descendants of this node. (dmode or fmode may be None.) Also 262eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sets the best_subtree of each directory Item to the (uid, gid, 2630eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich dmode, fmode, selabel, capabilities) tuple that will match the most 2640eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich descendants of that Item. 265eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker """ 266eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 267eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker assert self.dir 2680eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich d = self.descendants = {(self.uid, self.gid, self.mode, None, self.selabel, self.capabilities): 1} 269eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for i in self.children: 270eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if i.dir: 271eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for k, v in i.CountChildMetadata().iteritems(): 272eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker d[k] = d.get(k, 0) + v 273eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 2740eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich k = (i.uid, i.gid, None, i.mode, i.selabel, i.capabilities) 275eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker d[k] = d.get(k, 0) + 1 276eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 2770eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # Find the (uid, gid, dmode, fmode, selabel, capabilities) 2780eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # tuple that matches the most descendants. 279eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 280eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # First, find the (uid, gid) pair that matches the most 281eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # descendants. 282eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker ug = {} 2830eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich for (uid, gid, _, _, _, _), count in d.iteritems(): 284eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker ug[(uid, gid)] = ug.get((uid, gid), 0) + count 285eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker ug = MostPopularKey(ug, (0, 0)) 286eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 2870eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # Now find the dmode, fmode, selabel, and capabilities that match 2880eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # the most descendants with that (uid, gid), and choose those. 289eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker best_dmode = (0, 0755) 290eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker best_fmode = (0, 0644) 2910eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich best_selabel = (0, None) 2920eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich best_capabilities = (0, None) 293eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for k, count in d.iteritems(): 294eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if k[:2] != ug: continue 295eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if k[2] is not None and count >= best_dmode[0]: best_dmode = (count, k[2]) 296eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if k[3] is not None and count >= best_fmode[0]: best_fmode = (count, k[3]) 2970eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if k[4] is not None and count >= best_selabel[0]: best_selabel = (count, k[4]) 2980eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich if k[5] is not None and count >= best_capabilities[0]: best_capabilities = (count, k[5]) 2990eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich self.best_subtree = ug + (best_dmode[1], best_fmode[1], best_selabel[1], best_capabilities[1]) 300eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 301eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return d 302eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 303c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker def SetPermissions(self, script): 304eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker """Append set_perm/set_perm_recursive commands to 'script' to 305eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker set all permissions, users, and groups for the tree of files 306c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker rooted at 'self'.""" 307eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 308eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker self.CountChildMetadata() 309eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 310eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker def recurse(item, current): 3110eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich # current is the (uid, gid, dmode, fmode, selabel, capabilities) tuple that the current 312eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # item (and all its children) have already been set to. We only 313eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # need to issue set_perm/set_perm_recursive commands if we're 314eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # supposed to be something different. 315eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if item.dir: 316eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if current != item.best_subtree: 317c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.SetPermissionsRecursive("/"+item.name, *item.best_subtree) 318eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker current = item.best_subtree 319eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 320eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if item.uid != current[0] or item.gid != current[1] or \ 3210eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich item.mode != current[2] or item.selabel != current[4] or \ 3220eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich item.capabilities != current[5]: 3230eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich script.SetPermissions("/"+item.name, item.uid, item.gid, 3240eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich item.mode, item.selabel, item.capabilities) 325eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 326eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for i in item.children: 327eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker recurse(i, current) 328eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 329eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if item.uid != current[0] or item.gid != current[1] or \ 3300eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich item.mode != current[3] or item.selabel != current[4] or \ 3310eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich item.capabilities != current[5]: 3320eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich script.SetPermissions("/"+item.name, item.uid, item.gid, 3330eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich item.mode, item.selabel, item.capabilities) 334eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 3350eb17d944704b3eb140bb9dded299d3be3aed77eNick Kralevich recurse(self, (-1, -1, -1, -1, None, None)) 336eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 337eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 338c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongkerdef CopyPartitionFiles(itemset, input_zip, output_zip=None, substitute=None): 339c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker """Copies files for the partition in the input zip to the output 340eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker zip. Populates the Item class with their metadata, and returns a 3411807e700a568d57901b835370d1b1ae05c3dbb0fDoug Zongker list of symlinks. output_zip may be None, in which case the copy is 3421807e700a568d57901b835370d1b1ae05c3dbb0fDoug Zongker skipped (but the other side effects still happen). substitute is an 3431807e700a568d57901b835370d1b1ae05c3dbb0fDoug Zongker optional dict of {output filename: contents} to be output instead of 3441807e700a568d57901b835370d1b1ae05c3dbb0fDoug Zongker certain input files. 345eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker """ 346eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 347eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker symlinks = [] 348eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 349c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker partition = itemset.partition 350c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 351eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for info in input_zip.infolist(): 352c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if info.filename.startswith(partition.upper() + "/"): 353eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker basefilename = info.filename[7:] 354eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if IsSymlink(info): 355eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker symlinks.append((input_zip.read(info.filename), 356c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker "/" + partition + "/" + basefilename)) 357eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 358eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker info2 = copy.copy(info) 359c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker fn = info2.filename = partition + "/" + basefilename 360eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if substitute and fn in substitute and substitute[fn] is None: 361eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker continue 362eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if output_zip is not None: 363eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if substitute and fn in substitute: 364eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker data = substitute[fn] 365eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 366eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker data = input_zip.read(info.filename) 367eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker output_zip.writestr(info2, data) 368eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if fn.endswith("/"): 369c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker itemset.Get(fn[:-1], dir=True) 370eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 371c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker itemset.Get(fn, dir=False) 372eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 373eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker symlinks.sort() 3741807e700a568d57901b835370d1b1ae05c3dbb0fDoug Zongker return symlinks 375eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 376eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 377eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef SignOutput(temp_zip_name, output_zip_name): 378eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker key_passwords = common.GetKeyPasswords([OPTIONS.package_key]) 379eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker pw = key_passwords[OPTIONS.package_key] 380eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 381951495fc4802a3603f654c02c7acceda4859f5e1Doug Zongker common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw, 382951495fc4802a3603f654c02c7acceda4859f5e1Doug Zongker whole_file=True) 383eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 384eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 385c6e3afd26db72bedcb1d89a71769138a731646a5Michael Rungedef AppendAssertions(script, info_dict, oem_dict = None): 3866e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_props = info_dict.get("oem_fingerprint_properties") 387560569a617c86be7985bd699e20fd19c6b2715c8Michael Runge if oem_props is None or len(oem_props) == 0: 3886e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge device = GetBuildProp("ro.product.device", info_dict) 3896e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge script.AssertDevice(device) 3906e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge else: 3916e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if oem_dict is None: 3926e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge raise common.ExternalError("No OEM file provided to answer expected assertions") 3936e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge for prop in oem_props.split(): 3946e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if oem_dict.get(prop) is None: 3956e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge raise common.ExternalError("The OEM file is missing the property %s" % prop) 3966e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge script.AssertOemProperty(prop, oem_dict.get(prop)) 397eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 398eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 399c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongkerdef HasRecoveryPatch(target_files_zip): 400c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker try: 401c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker target_files_zip.getinfo("SYSTEM/recovery-from-boot.p") 402c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker return True 403c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker except KeyError: 404c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker return False 40573ef8257ce54ce1ddc2d4cfc3b3814ca734c0e11Doug Zongker 406c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongkerdef HasVendorPartition(target_files_zip): 407c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker try: 408c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker target_files_zip.getinfo("VENDOR/") 409c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker return True 410c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker except KeyError: 411c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker return False 412c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 4136e836116f764cf5cebf1654df2f17d8222554f6eMichael Rungedef GetOemProperty(name, oem_props, oem_dict, info_dict): 4146e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if oem_props is not None and name in oem_props: 4156e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge return oem_dict[name] 4166e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge return GetBuildProp(name, info_dict) 4176e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 4186e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 4196e836116f764cf5cebf1654df2f17d8222554f6eMichael Rungedef CalculateFingerprint(oem_props, oem_dict, info_dict): 4206e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if oem_props is None: 4216e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge return GetBuildProp("ro.build.fingerprint", info_dict) 4226e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge return "%s/%s/%s:%s" % ( 4236e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict), 4246e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict), 4256e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict), 4266e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge GetBuildProp("ro.build.thumbprint", info_dict)) 42773ef8257ce54ce1ddc2d4cfc3b3814ca734c0e11Doug Zongker 428fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 4293c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongkerdef GetImage(which, tmpdir, info_dict): 430fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # Return an image object (suitable for passing to BlockImageDiff) 431fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # for the 'which' partition (most be "system" or "vendor"). If a 432fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # prebuilt image and file map are found in tmpdir they are used, 433fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # otherwise they are reconstructed from the individual files. 4343c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker 4353c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker assert which in ("system", "vendor") 4363c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker 4373c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker path = os.path.join(tmpdir, "IMAGES", which + ".img") 438fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker mappath = os.path.join(tmpdir, "IMAGES", which + ".map") 439fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker if os.path.exists(path) and os.path.exists(mappath): 4403c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker print "using %s.img from target-files" % (which,) 4413c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker # This is a 'new' target-files, which already has the image in it. 4423c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker 4433c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker else: 4443c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker print "building %s.img from target-files" % (which,) 4453c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker 4463c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker # This is an 'old' target-files, which does not contain images 4473c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker # already built. Build them. 4483c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker 449fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker mappath = tempfile.mkstemp()[1] 450fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker OPTIONS.tempfiles.append(mappath) 451fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 4523c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker import add_img_to_target_files 4533c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker if which == "system": 454fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker path = add_img_to_target_files.BuildSystem( 455fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker tmpdir, info_dict, block_list=mappath) 4563c84f569487c4e59baa332be33b5430fdefb76b3Doug Zongker elif which == "vendor": 457fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker path = add_img_to_target_files.BuildVendor( 458fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker tmpdir, info_dict, block_list=mappath) 459fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 460fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker return sparse_img.SparseImage(path, mappath) 461fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 462fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 463c77a9ad444d49e2ad777678cf5671f0a94f44ffbDoug Zongkerdef WriteFullOTAPackage(input_zip, output_zip): 4649ce2ebf5d300eba5f6086583b0941ef68a3e4b42Doug Zongker # TODO: how to determine this? We don't know what version it will 4659ce2ebf5d300eba5f6086583b0941ef68a3e4b42Doug Zongker # be installed on top of. For now, we expect the API just won't 4669ce2ebf5d300eba5f6086583b0941ef68a3e4b42Doug Zongker # change very often. 467c77a9ad444d49e2ad777678cf5671f0a94f44ffbDoug Zongker script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict) 468eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 4696e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") 47065f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options") 4716e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_dict = None 472560569a617c86be7985bd699e20fd19c6b2715c8Michael Runge if oem_props is not None and len(oem_props) > 0: 4736e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if OPTIONS.oem_source is None: 4746e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge raise common.ExternalError("OEM source required for this build") 47565f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/oem", recovery_mount_options) 4766e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) 4776e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 4786e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge metadata = {"post-build": CalculateFingerprint( 4796e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_props, oem_dict, OPTIONS.info_dict), 4806e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict, 4811eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker OPTIONS.info_dict), 4821eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker "post-timestamp": GetBuildProp("ro.build.date.utc", 4831eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker OPTIONS.info_dict), 4842ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker } 4852ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker 48605d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific = common.DeviceSpecificParams( 48705d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker input_zip=input_zip, 48837974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker input_version=OPTIONS.info_dict["recovery_api_version"], 48905d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker output_zip=output_zip, 49005d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker script=script, 4912ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker input_tmp=OPTIONS.input_tmp, 49296a57e737707d05333dced5b657c4ef21c44088aDoug Zongker metadata=metadata, 49396a57e737707d05333dced5b657c4ef21c44088aDoug Zongker info_dict=OPTIONS.info_dict) 49405d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker 495c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker has_recovery_patch = HasRecoveryPatch(input_zip) 49626e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker block_based = OPTIONS.block_based and has_recovery_patch 497c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker 498962069ce59c85949d147874df2728a5ffd9193beDoug Zongker if not OPTIONS.omit_prereq: 4991eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict) 5000d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict) 5010d92f1f13ad89bf8ffbb75764bbe83452612792aDoug Zongker script.AssertOlderBuild(ts, ts_text) 502eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 5036e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge AppendAssertions(script, OPTIONS.info_dict, oem_dict) 50405d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific.FullOTA_Assertions() 5059b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 5069b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # Two-step package strategy (in chronological order, which is *not* 5079b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # the order in which the generated script has things): 5089b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # 5099b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # if stage is not "2/3" or "3/3": 5109b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # write recovery image to boot partition 5119b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set stage to "2/3" 5129b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # reboot to boot partition and restart recovery 5139b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # else if stage is "2/3": 5149b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # write recovery image to recovery partition 5159b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set stage to "3/3" 5169b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # reboot to recovery partition and restart recovery 5179b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # else: 5189b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # (stage must be "3/3") 5199b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set stage to "" 5209b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # do normal full package installation: 5219b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # wipe and install system, boot image, etc. 5229b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set up system to update recovery partition on first boot 5239b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # complete script normally (allow recovery to mark itself finished and reboot) 5249b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 5259b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker recovery_img = common.GetBootableImage("recovery.img", "recovery.img", 5269b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker OPTIONS.input_tmp, "RECOVERY") 5279b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if OPTIONS.two_step: 5289b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if not OPTIONS.info_dict.get("multistage_support", None): 5299b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker assert False, "two-step packages not supported by this build" 5309b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker fs = OPTIONS.info_dict["fstab"]["/misc"] 5319b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker assert fs.fs_type.upper() == "EMMC", \ 5329b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker "two-step packages only supported on devices with EMMC /misc partitions" 5339b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker bcb_dev = {"bcb_dev": fs.device} 5349b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data) 5359b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 536f9d181979097af3f4a62dad9fff318a916759597Michael Rungeif get_stage("%(bcb_dev)s") == "2/3" then 5379b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 5389b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.WriteRawImage("/recovery", "recovery.img") 5399b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 5409b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerset_stage("%(bcb_dev)s", "3/3"); 5419b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerreboot_now("%(bcb_dev)s", "recovery"); 542f9d181979097af3f4a62dad9fff318a916759597Michael Rungeelse if get_stage("%(bcb_dev)s") == "3/3" then 5439b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 5449b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 545e5ff5907bef42fa9f3eff2e90ad941423dcc91dcDoug Zongker device_specific.FullOTA_InstallBegin() 546171f1cde104891840b0c3c271935fae5433f1b25Doug Zongker 54701ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker system_progress = 0.75 548eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 549dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker if OPTIONS.wipe_user_data: 55001ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker system_progress -= 0.1 551c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if HasVendorPartition(input_zip): 552c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_progress -= 0.1 553dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker 554f32dc71e49656e16fc8e178f7436706a47e8af52Kenny Root if "selinux_fc" in OPTIONS.info_dict: 555f32dc71e49656e16fc8e178f7436706a47e8af52Kenny Root WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip) 55656882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalley 55765f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options") 55865f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge 559c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items = ItemSet("system", "META/filesystem_config.txt") 5604b9596fe00e3012c8d4b44844ac53b10ee27b579Doug Zongker script.ShowProgress(system_progress, 0) 56126e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker if block_based: 562fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # Full OTA is done as an "incremental" against an empty source 563fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # image. This has the effect of writing new data from the package 564fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # to the entire partition, but lets us reuse the updater code that 565fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker # writes incrementals to do it. 566fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker system_tgt = GetImage("system", OPTIONS.input_tmp, OPTIONS.info_dict) 567fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker system_tgt.ResetFileMap() 568ab7ca1d2861e70d8ef8673d350b634111414039eDoug Zongker system_diff = common.BlockDifference("system", system_tgt, src=None) 569fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker system_diff.WriteScript(script, output_zip) 57001ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker else: 57101ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker script.FormatPartition("/system") 57265f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/system", recovery_mount_options) 57301ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker if not has_recovery_patch: 57401ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker script.UnpackPackageDir("recovery", "/system") 57526e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker script.UnpackPackageDir("system", "/system") 576eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 577c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker symlinks = CopyPartitionFiles(system_items, input_zip, output_zip) 57801ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker script.MakeSymlinks(symlinks) 579eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 58055d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker boot_img = common.GetBootableImage("boot.img", "boot.img", 58155d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker OPTIONS.input_tmp, "BOOT") 582c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker 58391a99c28e0d15a753bc303982c970c96d6dfe0f5Doug Zongker if not block_based: 584c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker def output_sink(fn, data): 585c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker common.ZipWriteStr(output_zip, "recovery/" + fn, data) 586c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items.Get("system/" + fn, dir=False) 587c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker 588c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, 589c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker recovery_img, boot_img) 59073ef8257ce54ce1ddc2d4cfc3b3814ca734c0e11Doug Zongker 591c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items.GetMetadata(input_zip) 592c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items.Get("system").SetPermissions(script) 593c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 594c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if HasVendorPartition(input_zip): 595c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_items = ItemSet("vendor", "META/vendor_filesystem_config.txt") 596c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.ShowProgress(0.1, 0) 597c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 598c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if block_based: 599fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker vendor_tgt = GetImage("vendor", OPTIONS.input_tmp, OPTIONS.info_dict) 600fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker vendor_tgt.ResetFileMap() 601ab7ca1d2861e70d8ef8673d350b634111414039eDoug Zongker vendor_diff = common.BlockDifference("vendor", vendor_tgt) 602fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker vendor_diff.WriteScript(script, output_zip) 603c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker else: 604c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.FormatPartition("/vendor") 60565f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/vendor", recovery_mount_options) 606c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.UnpackPackageDir("vendor", "/vendor") 607c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 608c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker symlinks = CopyPartitionFiles(vendor_items, input_zip, output_zip) 609c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.MakeSymlinks(symlinks) 610c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 611c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_items.GetMetadata(input_zip) 612c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_items.Get("vendor").SetPermissions(script) 613eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 61437974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict) 61573ef8257ce54ce1ddc2d4cfc3b3814ca734c0e11Doug Zongker common.ZipWriteStr(output_zip, "boot.img", boot_img.data) 616c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 61701ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker script.ShowProgress(0.05, 5) 6189ce0fb6e59415669074896cfa01e1f0cf97979b7Doug Zongker script.WriteRawImage("/boot", "boot.img") 61905d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker 62001ce19c95f358ac8ef9bb939d2637ac976320401Doug Zongker script.ShowProgress(0.2, 10) 62105d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific.FullOTA_InstallEnd() 622eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 6231c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker if OPTIONS.extra_script is not None: 624c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.AppendExtra(OPTIONS.extra_script) 6251c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker 62614833605d26bf970cd5335c02af4354b68d93348Doug Zongker script.UnmountAll() 6279b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 628922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker if OPTIONS.wipe_user_data: 629922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker script.ShowProgress(0.1, 10) 630922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker script.FormatPartition("/data") 631c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 6329b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if OPTIONS.two_step: 6339b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 6349b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerset_stage("%(bcb_dev)s", ""); 6359b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 6369b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra("else\n") 6379b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.WriteRawImage("/boot", "recovery.img") 6389b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 6399b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerset_stage("%(bcb_dev)s", "2/3"); 6409b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerreboot_now("%(bcb_dev)s", ""); 6419b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerendif; 6429b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerendif; 6439b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 64425568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary) 6452ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker WriteMetadata(metadata, output_zip) 6462ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker 647fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 64856882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalleydef WritePolicyConfig(file_context, output_zip): 64956882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalley f = open(file_context, 'r'); 65056882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalley basename = os.path.basename(file_context) 65156882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalley common.ZipWriteStr(output_zip, basename, f.read()) 65256882bf9b41dc7f8b98f1dea82633144546450b2Stephen Smalley 6532ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker 6542ea21065b66da9819df92b37a79f0f87552ee331Doug Zongkerdef WriteMetadata(metadata, output_zip): 6552ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker common.ZipWriteStr(output_zip, "META-INF/com/android/metadata", 6562ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker "".join(["%s=%s\n" % kv 6572ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker for kv in sorted(metadata.iteritems())])) 658eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 659fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 660c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongkerdef LoadPartitionFiles(z, partition): 661c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker """Load all the files from the given partition in a given target-files 662eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker ZipFile, and return a dict of {filename: File object}.""" 663eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker out = {} 664c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker prefix = partition.upper() + "/" 665eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for info in z.infolist(): 666c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if info.filename.startswith(prefix) and not IsSymlink(info): 66796be7205dce97977909e93b73f48779fcce3bc65Hristo Bojinov basefilename = info.filename[7:] 668c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker fn = partition + "/" + basefilename 669eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker data = z.read(info.filename) 670ea5d7a9de7660bef5b9c68f6372a92d4b2f2f1f6Doug Zongker out[fn] = common.File(fn, data) 6711807e700a568d57901b835370d1b1ae05c3dbb0fDoug Zongker return out 672eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 673eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 6741eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongkerdef GetBuildProp(prop, info_dict): 6751eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker """Return the fingerprint of the build of a given target-files info_dict.""" 6761eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker try: 6771eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker return info_dict.get("build.prop", {})[prop] 6781eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker except KeyError: 679c73e461537678af2c29fcc38857e26fa57103710Ying Wang raise common.ExternalError("couldn't find %s in build.prop" % (prop,)) 680eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 681fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 6824038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Rungedef AddToKnownPaths(filename, known_paths): 6834038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if filename[-1] == "/": 6844038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge return 6854038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge dirs = filename.split("/")[:-1] 6864038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge while len(dirs) > 0: 6874038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge path = "/".join(dirs) 6884038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge if path in known_paths: 6894038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge break; 6904038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge known_paths.add(path) 6914038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge dirs.pop() 692eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 693c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 69436bd365625e6beba77698a93795a603180a5b476Geremy Condradef WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip): 69536bd365625e6beba77698a93795a603180a5b476Geremy Condra source_version = OPTIONS.source_info_dict["recovery_api_version"] 69636bd365625e6beba77698a93795a603180a5b476Geremy Condra target_version = OPTIONS.target_info_dict["recovery_api_version"] 69736bd365625e6beba77698a93795a603180a5b476Geremy Condra 69836bd365625e6beba77698a93795a603180a5b476Geremy Condra if source_version == 0: 69936bd365625e6beba77698a93795a603180a5b476Geremy Condra print ("WARNING: generating edify script for a source that " 70036bd365625e6beba77698a93795a603180a5b476Geremy Condra "can't install it.") 70136bd365625e6beba77698a93795a603180a5b476Geremy Condra script = edify_generator.EdifyGenerator(source_version, 70236bd365625e6beba77698a93795a603180a5b476Geremy Condra OPTIONS.target_info_dict) 70336bd365625e6beba77698a93795a603180a5b476Geremy Condra 70436bd365625e6beba77698a93795a603180a5b476Geremy Condra metadata = {"pre-device": GetBuildProp("ro.product.device", 70536bd365625e6beba77698a93795a603180a5b476Geremy Condra OPTIONS.source_info_dict), 70636bd365625e6beba77698a93795a603180a5b476Geremy Condra "post-timestamp": GetBuildProp("ro.build.date.utc", 70736bd365625e6beba77698a93795a603180a5b476Geremy Condra OPTIONS.target_info_dict), 70836bd365625e6beba77698a93795a603180a5b476Geremy Condra } 70936bd365625e6beba77698a93795a603180a5b476Geremy Condra 71036bd365625e6beba77698a93795a603180a5b476Geremy Condra device_specific = common.DeviceSpecificParams( 71136bd365625e6beba77698a93795a603180a5b476Geremy Condra source_zip=source_zip, 71236bd365625e6beba77698a93795a603180a5b476Geremy Condra source_version=source_version, 71336bd365625e6beba77698a93795a603180a5b476Geremy Condra target_zip=target_zip, 71436bd365625e6beba77698a93795a603180a5b476Geremy Condra target_version=target_version, 71536bd365625e6beba77698a93795a603180a5b476Geremy Condra output_zip=output_zip, 71636bd365625e6beba77698a93795a603180a5b476Geremy Condra script=script, 71736bd365625e6beba77698a93795a603180a5b476Geremy Condra metadata=metadata, 71836bd365625e6beba77698a93795a603180a5b476Geremy Condra info_dict=OPTIONS.info_dict) 71936bd365625e6beba77698a93795a603180a5b476Geremy Condra 72036bd365625e6beba77698a93795a603180a5b476Geremy Condra source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict) 72136bd365625e6beba77698a93795a603180a5b476Geremy Condra target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict) 72236bd365625e6beba77698a93795a603180a5b476Geremy Condra metadata["pre-build"] = source_fp 72336bd365625e6beba77698a93795a603180a5b476Geremy Condra metadata["post-build"] = target_fp 72436bd365625e6beba77698a93795a603180a5b476Geremy Condra 72536bd365625e6beba77698a93795a603180a5b476Geremy Condra source_boot = common.GetBootableImage( 72636bd365625e6beba77698a93795a603180a5b476Geremy Condra "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", 72736bd365625e6beba77698a93795a603180a5b476Geremy Condra OPTIONS.source_info_dict) 72836bd365625e6beba77698a93795a603180a5b476Geremy Condra target_boot = common.GetBootableImage( 72936bd365625e6beba77698a93795a603180a5b476Geremy Condra "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT") 73036bd365625e6beba77698a93795a603180a5b476Geremy Condra updating_boot = (not OPTIONS.two_step and 73136bd365625e6beba77698a93795a603180a5b476Geremy Condra (source_boot.data != target_boot.data)) 73236bd365625e6beba77698a93795a603180a5b476Geremy Condra 73336bd365625e6beba77698a93795a603180a5b476Geremy Condra source_recovery = common.GetBootableImage( 73436bd365625e6beba77698a93795a603180a5b476Geremy Condra "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY", 73536bd365625e6beba77698a93795a603180a5b476Geremy Condra OPTIONS.source_info_dict) 73636bd365625e6beba77698a93795a603180a5b476Geremy Condra target_recovery = common.GetBootableImage( 73736bd365625e6beba77698a93795a603180a5b476Geremy Condra "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") 73836bd365625e6beba77698a93795a603180a5b476Geremy Condra updating_recovery = (source_recovery.data != target_recovery.data) 73936bd365625e6beba77698a93795a603180a5b476Geremy Condra 740fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker system_src = GetImage("system", OPTIONS.source_tmp, OPTIONS.source_info_dict) 741fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker system_tgt = GetImage("system", OPTIONS.target_tmp, OPTIONS.target_info_dict) 742b34fcce08cc9ab358481e672d83ff16513c4ac37Doug Zongker system_diff = common.BlockDifference("system", system_tgt, system_src, 743b34fcce08cc9ab358481e672d83ff16513c4ac37Doug Zongker check_first_block=True) 744fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker 745c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if HasVendorPartition(target_zip): 746c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if not HasVendorPartition(source_zip): 747c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker raise RuntimeError("can't generate incremental that adds /vendor") 748fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker vendor_src = GetImage("vendor", OPTIONS.source_tmp, OPTIONS.source_info_dict) 749fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker vendor_tgt = GetImage("vendor", OPTIONS.target_tmp, OPTIONS.target_info_dict) 750b34fcce08cc9ab358481e672d83ff16513c4ac37Doug Zongker vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src, 751b34fcce08cc9ab358481e672d83ff16513c4ac37Doug Zongker check_first_block=True) 752fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker else: 753fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker vendor_diff = None 75436bd365625e6beba77698a93795a603180a5b476Geremy Condra 755c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties") 75665f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge recovery_mount_options = OPTIONS.target_info_dict.get("recovery_mount_options") 757c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge oem_dict = None 758560569a617c86be7985bd699e20fd19c6b2715c8Michael Runge if oem_props is not None and len(oem_props) > 0: 759c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge if OPTIONS.oem_source is None: 760c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge raise common.ExternalError("OEM source required for this build") 76165f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/oem", recovery_mount_options) 762c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) 763c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge 764c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge AppendAssertions(script, OPTIONS.target_info_dict, oem_dict) 76536bd365625e6beba77698a93795a603180a5b476Geremy Condra device_specific.IncrementalOTA_Assertions() 76636bd365625e6beba77698a93795a603180a5b476Geremy Condra 76736bd365625e6beba77698a93795a603180a5b476Geremy Condra # Two-step incremental package strategy (in chronological order, 76836bd365625e6beba77698a93795a603180a5b476Geremy Condra # which is *not* the order in which the generated script has 76936bd365625e6beba77698a93795a603180a5b476Geremy Condra # things): 77036bd365625e6beba77698a93795a603180a5b476Geremy Condra # 77136bd365625e6beba77698a93795a603180a5b476Geremy Condra # if stage is not "2/3" or "3/3": 77236bd365625e6beba77698a93795a603180a5b476Geremy Condra # do verification on current system 77336bd365625e6beba77698a93795a603180a5b476Geremy Condra # write recovery image to boot partition 77436bd365625e6beba77698a93795a603180a5b476Geremy Condra # set stage to "2/3" 77536bd365625e6beba77698a93795a603180a5b476Geremy Condra # reboot to boot partition and restart recovery 77636bd365625e6beba77698a93795a603180a5b476Geremy Condra # else if stage is "2/3": 77736bd365625e6beba77698a93795a603180a5b476Geremy Condra # write recovery image to recovery partition 77836bd365625e6beba77698a93795a603180a5b476Geremy Condra # set stage to "3/3" 77936bd365625e6beba77698a93795a603180a5b476Geremy Condra # reboot to recovery partition and restart recovery 78036bd365625e6beba77698a93795a603180a5b476Geremy Condra # else: 78136bd365625e6beba77698a93795a603180a5b476Geremy Condra # (stage must be "3/3") 78236bd365625e6beba77698a93795a603180a5b476Geremy Condra # perform update: 78336bd365625e6beba77698a93795a603180a5b476Geremy Condra # patch system files, etc. 78436bd365625e6beba77698a93795a603180a5b476Geremy Condra # force full install of new boot image 78536bd365625e6beba77698a93795a603180a5b476Geremy Condra # set up system to update recovery partition on first boot 78636bd365625e6beba77698a93795a603180a5b476Geremy Condra # complete script normally (allow recovery to mark itself finished and reboot) 78736bd365625e6beba77698a93795a603180a5b476Geremy Condra 78836bd365625e6beba77698a93795a603180a5b476Geremy Condra if OPTIONS.two_step: 78936bd365625e6beba77698a93795a603180a5b476Geremy Condra if not OPTIONS.info_dict.get("multistage_support", None): 79036bd365625e6beba77698a93795a603180a5b476Geremy Condra assert False, "two-step packages not supported by this build" 79136bd365625e6beba77698a93795a603180a5b476Geremy Condra fs = OPTIONS.info_dict["fstab"]["/misc"] 79236bd365625e6beba77698a93795a603180a5b476Geremy Condra assert fs.fs_type.upper() == "EMMC", \ 79336bd365625e6beba77698a93795a603180a5b476Geremy Condra "two-step packages only supported on devices with EMMC /misc partitions" 79436bd365625e6beba77698a93795a603180a5b476Geremy Condra bcb_dev = {"bcb_dev": fs.device} 79536bd365625e6beba77698a93795a603180a5b476Geremy Condra common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) 79636bd365625e6beba77698a93795a603180a5b476Geremy Condra script.AppendExtra(""" 797f9d181979097af3f4a62dad9fff318a916759597Michael Rungeif get_stage("%(bcb_dev)s") == "2/3" then 79836bd365625e6beba77698a93795a603180a5b476Geremy Condra""" % bcb_dev) 79936bd365625e6beba77698a93795a603180a5b476Geremy Condra script.AppendExtra("sleep(20);\n"); 80036bd365625e6beba77698a93795a603180a5b476Geremy Condra script.WriteRawImage("/recovery", "recovery.img") 80136bd365625e6beba77698a93795a603180a5b476Geremy Condra script.AppendExtra(""" 80236bd365625e6beba77698a93795a603180a5b476Geremy Condraset_stage("%(bcb_dev)s", "3/3"); 80336bd365625e6beba77698a93795a603180a5b476Geremy Condrareboot_now("%(bcb_dev)s", "recovery"); 804f9d181979097af3f4a62dad9fff318a916759597Michael Rungeelse if get_stage("%(bcb_dev)s") != "3/3" then 80536bd365625e6beba77698a93795a603180a5b476Geremy Condra""" % bcb_dev) 80636bd365625e6beba77698a93795a603180a5b476Geremy Condra 80736bd365625e6beba77698a93795a603180a5b476Geremy Condra script.Print("Verifying current system...") 80836bd365625e6beba77698a93795a603180a5b476Geremy Condra 80936bd365625e6beba77698a93795a603180a5b476Geremy Condra device_specific.IncrementalOTA_VerifyBegin() 81036bd365625e6beba77698a93795a603180a5b476Geremy Condra 811c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge if oem_props is None: 812c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge script.AssertSomeFingerprint(source_fp, target_fp) 813c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge else: 814c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge script.AssertSomeThumbprint( 815c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), 816c6e3afd26db72bedcb1d89a71769138a731646a5Michael Runge GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) 81736bd365625e6beba77698a93795a603180a5b476Geremy Condra 81836bd365625e6beba77698a93795a603180a5b476Geremy Condra if updating_boot: 819f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) 82036bd365625e6beba77698a93795a603180a5b476Geremy Condra d = common.Difference(target_boot, source_boot) 82136bd365625e6beba77698a93795a603180a5b476Geremy Condra _, _, d = d.ComputePatch() 822f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker if d is None: 823f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker include_full_boot = True 824f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker common.ZipWriteStr(output_zip, "boot.img", target_boot.data) 825f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker else: 826f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker include_full_boot = False 82736bd365625e6beba77698a93795a603180a5b476Geremy Condra 828f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker print "boot target: %d source: %d diff: %d" % ( 829f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker target_boot.size, source_boot.size, len(d)) 83036bd365625e6beba77698a93795a603180a5b476Geremy Condra 831f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker common.ZipWriteStr(output_zip, "patch/boot.img.p", d) 83236bd365625e6beba77698a93795a603180a5b476Geremy Condra 833f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker script.PatchCheck("%s:%s:%d:%s:%d:%s" % 834f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker (boot_type, boot_device, 835f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker source_boot.size, source_boot.sha1, 836f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker target_boot.size, target_boot.sha1)) 83736bd365625e6beba77698a93795a603180a5b476Geremy Condra 83836bd365625e6beba77698a93795a603180a5b476Geremy Condra device_specific.IncrementalOTA_VerifyEnd() 83936bd365625e6beba77698a93795a603180a5b476Geremy Condra 84036bd365625e6beba77698a93795a603180a5b476Geremy Condra if OPTIONS.two_step: 84136bd365625e6beba77698a93795a603180a5b476Geremy Condra script.WriteRawImage("/boot", "recovery.img") 84236bd365625e6beba77698a93795a603180a5b476Geremy Condra script.AppendExtra(""" 84336bd365625e6beba77698a93795a603180a5b476Geremy Condraset_stage("%(bcb_dev)s", "2/3"); 84436bd365625e6beba77698a93795a603180a5b476Geremy Condrareboot_now("%(bcb_dev)s", ""); 84536bd365625e6beba77698a93795a603180a5b476Geremy Condraelse 84636bd365625e6beba77698a93795a603180a5b476Geremy Condra""" % bcb_dev) 84736bd365625e6beba77698a93795a603180a5b476Geremy Condra 84836bd365625e6beba77698a93795a603180a5b476Geremy Condra script.Comment("---- start making changes here ----") 84936bd365625e6beba77698a93795a603180a5b476Geremy Condra 85036bd365625e6beba77698a93795a603180a5b476Geremy Condra device_specific.IncrementalOTA_InstallBegin() 85136bd365625e6beba77698a93795a603180a5b476Geremy Condra 852ab7ca1d2861e70d8ef8673d350b634111414039eDoug Zongker system_diff.WriteScript(script, output_zip, 853ab7ca1d2861e70d8ef8673d350b634111414039eDoug Zongker progress=0.8 if vendor_diff else 0.9) 854fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker if vendor_diff: 855ab7ca1d2861e70d8ef8673d350b634111414039eDoug Zongker vendor_diff.WriteScript(script, output_zip, progress=0.1) 85636bd365625e6beba77698a93795a603180a5b476Geremy Condra 85736bd365625e6beba77698a93795a603180a5b476Geremy Condra if OPTIONS.two_step: 85836bd365625e6beba77698a93795a603180a5b476Geremy Condra common.ZipWriteStr(output_zip, "boot.img", target_boot.data) 85936bd365625e6beba77698a93795a603180a5b476Geremy Condra script.WriteRawImage("/boot", "boot.img") 86036bd365625e6beba77698a93795a603180a5b476Geremy Condra print "writing full boot image (forced by two-step mode)" 86136bd365625e6beba77698a93795a603180a5b476Geremy Condra 86236bd365625e6beba77698a93795a603180a5b476Geremy Condra if not OPTIONS.two_step: 86336bd365625e6beba77698a93795a603180a5b476Geremy Condra if updating_boot: 864f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker if include_full_boot: 865f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker print "boot image changed; including full." 866f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker script.Print("Installing boot image...") 867f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker script.WriteRawImage("/boot", "boot.img") 868f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker else: 869f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker # Produce the boot image by applying a patch to the current 870f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker # contents of the boot partition, and write it back to the 871f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker # partition. 872f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker print "boot image changed; including patch." 873f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker script.Print("Patching boot image...") 874f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker script.ShowProgress(0.1, 10) 875f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker script.ApplyPatch("%s:%s:%d:%s:%d:%s" 876f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker % (boot_type, boot_device, 877f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker source_boot.size, source_boot.sha1, 878f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker target_boot.size, target_boot.sha1), 879f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker "-", 880f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker target_boot.size, target_boot.sha1, 881f83400896de5e8bc2b21a0dce98382d9ed0ab537Doug Zongker source_boot.sha1, "patch/boot.img.p") 88236bd365625e6beba77698a93795a603180a5b476Geremy Condra else: 88336bd365625e6beba77698a93795a603180a5b476Geremy Condra print "boot image unchanged; skipping." 88436bd365625e6beba77698a93795a603180a5b476Geremy Condra 88536bd365625e6beba77698a93795a603180a5b476Geremy Condra # Do device-specific installation (eg, write radio image). 88636bd365625e6beba77698a93795a603180a5b476Geremy Condra device_specific.IncrementalOTA_InstallEnd() 88736bd365625e6beba77698a93795a603180a5b476Geremy Condra 88836bd365625e6beba77698a93795a603180a5b476Geremy Condra if OPTIONS.extra_script is not None: 88936bd365625e6beba77698a93795a603180a5b476Geremy Condra script.AppendExtra(OPTIONS.extra_script) 89036bd365625e6beba77698a93795a603180a5b476Geremy Condra 891922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker if OPTIONS.wipe_user_data: 892922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker script.Print("Erasing user data...") 893922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker script.FormatPartition("/data") 894922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker 89536bd365625e6beba77698a93795a603180a5b476Geremy Condra if OPTIONS.two_step: 89636bd365625e6beba77698a93795a603180a5b476Geremy Condra script.AppendExtra(""" 89736bd365625e6beba77698a93795a603180a5b476Geremy Condraset_stage("%(bcb_dev)s", ""); 89836bd365625e6beba77698a93795a603180a5b476Geremy Condraendif; 89936bd365625e6beba77698a93795a603180a5b476Geremy Condraendif; 90036bd365625e6beba77698a93795a603180a5b476Geremy Condra""" % bcb_dev) 90136bd365625e6beba77698a93795a603180a5b476Geremy Condra 90236bd365625e6beba77698a93795a603180a5b476Geremy Condra script.SetProgress(1) 90325568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) 90436bd365625e6beba77698a93795a603180a5b476Geremy Condra WriteMetadata(metadata, output_zip) 90536bd365625e6beba77698a93795a603180a5b476Geremy Condra 90632b527d6cb951335f06c37c4d9a7a8216974a86aDoug Zongker 907c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongkerclass FileDifference: 908c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def __init__(self, partition, source_zip, target_zip, output_zip): 909c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "Loading target..." 910c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.target_data = target_data = LoadPartitionFiles(target_zip, partition) 911c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "Loading source..." 912c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.source_data = source_data = LoadPartitionFiles(source_zip, partition) 913c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 914c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.verbatim_targets = verbatim_targets = [] 915c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.patch_list = patch_list = [] 916c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker diffs = [] 917c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.renames = renames = {} 918c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker known_paths = set() 919c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker largest_source_size = 0 920c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 921c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker matching_file_cache = {} 922c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for fn, sf in source_data.items(): 923c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker assert fn == sf.name 924c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker matching_file_cache["path:" + fn] = sf 925c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if fn in target_data.keys(): 926c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker AddToKnownPaths(fn, known_paths) 927c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # Only allow eligibility for filename/sha matching 928c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # if there isn't a perfect path match. 929c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if target_data.get(sf.name) is None: 930c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker matching_file_cache["file:" + fn.split("/")[-1]] = sf 931c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker matching_file_cache["sha:" + sf.sha1] = sf 932c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 933c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for fn in sorted(target_data.keys()): 934c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker tf = target_data[fn] 935c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker assert fn == tf.name 936c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker sf = ClosestFileMatch(tf, matching_file_cache, renames) 937c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if sf is not None and sf.name != tf.name: 938c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "File has moved from " + sf.name + " to " + tf.name 939c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker renames[sf.name] = tf 940c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 941c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if sf is None or fn in OPTIONS.require_verbatim: 942c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # This file should be included verbatim 943c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if fn in OPTIONS.prohibit_verbatim: 944c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker raise common.ExternalError("\"%s\" must be sent verbatim" % (fn,)) 945c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "send", fn, "verbatim" 946c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker tf.AddToZip(output_zip) 947e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge verbatim_targets.append((fn, tf.size, tf.sha1)) 948c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if fn in target_data.keys(): 949c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker AddToKnownPaths(fn, known_paths) 950c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker elif tf.sha1 != sf.sha1: 951c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # File is different; consider sending as a patch 952c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker diffs.append(common.Difference(tf, sf)) 953c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker else: 954c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # Target file data identical to source (may still be renamed) 955c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker pass 956c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 957c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker common.ComputeDifferences(diffs) 958c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 959c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for diff in diffs: 960c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker tf, sf, d = diff.GetPatch() 961c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker path = "/".join(tf.name.split("/")[:-1]) 962c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \ 963c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker path not in known_paths: 964c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # patch is almost as big as the file; don't bother patching 965c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # or a patch + rename cannot take place due to the target 966c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # directory not existing 967c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker tf.AddToZip(output_zip) 968e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge verbatim_targets.append((tf.name, tf.size, tf.sha1)) 969c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if sf.name in renames: 970c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker del renames[sf.name] 971c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker AddToKnownPaths(tf.name, known_paths) 972c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker else: 973c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker common.ZipWriteStr(output_zip, "patch/" + sf.name + ".p", d) 974c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker patch_list.append((tf, sf, tf.size, common.sha1(d).hexdigest())) 975c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker largest_source_size = max(largest_source_size, sf.size) 976c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 977c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.largest_source_size = largest_source_size 978c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 979c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def EmitVerification(self, script): 980c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far = 0 981c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for tf, sf, size, patch_sha in self.patch_list: 982c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if tf.name != sf.name: 983c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.SkipNextActionIfTargetExists(tf.name, tf.sha1) 984c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.PatchCheck("/"+sf.name, tf.sha1, sf.sha1) 985c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far += sf.size 986c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker return so_far 987c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 988e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge def EmitExplicitTargetVerification(self, script): 989e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge for fn, size, sha1 in self.verbatim_targets: 990e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge if (fn[-1] != "/"): 991e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.FileCheck("/"+fn, sha1) 992e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge for tf, _, _, _ in self.patch_list: 993e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.FileCheck(tf.name, tf.sha1) 994e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge 995c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def RemoveUnneededFiles(self, script, extras=()): 996c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.DeleteFiles(["/"+i[0] for i in self.verbatim_targets] + 997c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker ["/"+i for i in sorted(self.source_data) 998c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if i not in self.target_data and 999c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker i not in self.renames] + 1000c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker list(extras)) 1001c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1002c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def TotalPatchSize(self): 1003c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker return sum(i[1].size for i in self.patch_list) 1004c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1005c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def EmitPatches(self, script, total_patch_size, so_far): 1006c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker self.deferred_patch_list = deferred_patch_list = [] 1007c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for item in self.patch_list: 1008c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker tf, sf, size, _ = item 1009c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if tf.name == "system/build.prop": 1010c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker deferred_patch_list.append(item) 1011c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker continue 1012c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if (sf.name != tf.name): 1013c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.SkipNextActionIfTargetExists(tf.name, tf.sha1) 1014c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") 1015c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far += tf.size 1016c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.SetProgress(so_far / total_patch_size) 1017c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker return so_far 1018c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1019c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def EmitDeferredPatches(self, script): 1020c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for item in self.deferred_patch_list: 1021c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker tf, sf, size, _ = item 1022c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1, "patch/"+sf.name+".p") 1023c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.SetPermissions("/system/build.prop", 0, 0, 0644, None, None) 1024c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1025c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker def EmitRenames(self, script): 1026c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if len(self.renames) > 0: 1027c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.Print("Renaming files...") 1028c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker for src, tgt in self.renames.iteritems(): 1029c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker print "Renaming " + src + " to " + tgt.name 1030c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.RenameFile(src, tgt.name) 1031c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1032c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1033c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1034c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1035c77a9ad444d49e2ad777678cf5671f0a94f44ffbDoug Zongkerdef WriteIncrementalOTAPackage(target_zip, source_zip, output_zip): 103636bd365625e6beba77698a93795a603180a5b476Geremy Condra target_has_recovery_patch = HasRecoveryPatch(target_zip) 103736bd365625e6beba77698a93795a603180a5b476Geremy Condra source_has_recovery_patch = HasRecoveryPatch(source_zip) 103836bd365625e6beba77698a93795a603180a5b476Geremy Condra 103926e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker if (OPTIONS.block_based and 104026e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker target_has_recovery_patch and 104126e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker source_has_recovery_patch): 104236bd365625e6beba77698a93795a603180a5b476Geremy Condra return WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip) 104336bd365625e6beba77698a93795a603180a5b476Geremy Condra 104437974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker source_version = OPTIONS.source_info_dict["recovery_api_version"] 104537974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker target_version = OPTIONS.target_info_dict["recovery_api_version"] 1046c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 10479ce2ebf5d300eba5f6086583b0941ef68a3e4b42Doug Zongker if source_version == 0: 10489ce2ebf5d300eba5f6086583b0941ef68a3e4b42Doug Zongker print ("WARNING: generating edify script for a source that " 10499ce2ebf5d300eba5f6086583b0941ef68a3e4b42Doug Zongker "can't install it.") 10501eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker script = edify_generator.EdifyGenerator(source_version, 10511eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker OPTIONS.target_info_dict) 1052eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 10536e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties") 105465f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options") 10556e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_dict = None 1056560569a617c86be7985bd699e20fd19c6b2715c8Michael Runge if oem_props is not None and len(oem_props) > 0: 10576e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if OPTIONS.oem_source is None: 10586e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge raise common.ExternalError("OEM source required for this build") 105965f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/oem", recovery_mount_options) 10606e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge oem_dict = common.LoadDictionaryFromLines(open(OPTIONS.oem_source).readlines()) 10616e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 10626e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge metadata = {"pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict, 10631eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker OPTIONS.source_info_dict), 10641eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker "post-timestamp": GetBuildProp("ro.build.date.utc", 10651eb74dd9a01ec14a2e41309986ef7efba790be8fDoug Zongker OPTIONS.target_info_dict), 10662ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker } 10672ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker 106805d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific = common.DeviceSpecificParams( 106905d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker source_zip=source_zip, 107014833605d26bf970cd5335c02af4354b68d93348Doug Zongker source_version=source_version, 107105d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker target_zip=target_zip, 107214833605d26bf970cd5335c02af4354b68d93348Doug Zongker target_version=target_version, 107305d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker output_zip=output_zip, 10742ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker script=script, 107596a57e737707d05333dced5b657c4ef21c44088aDoug Zongker metadata=metadata, 107696a57e737707d05333dced5b657c4ef21c44088aDoug Zongker info_dict=OPTIONS.info_dict) 107705d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker 1078c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_diff = FileDifference("system", source_zip, target_zip, output_zip) 107965f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/system", recovery_mount_options) 1080c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if HasVendorPartition(target_zip): 1081c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_diff = FileDifference("vendor", source_zip, target_zip, output_zip) 108265f3282099a16e266bc61e0ed3016e15f6bd8959Michael Runge script.Mount("/vendor", recovery_mount_options) 1083c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker else: 1084c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_diff = None 10856e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 10866e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge target_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.target_info_dict) 10876e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge source_fp = CalculateFingerprint(oem_props, oem_dict, OPTIONS.source_info_dict) 10886e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 10896e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge if oem_props is None: 10906e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge script.AssertSomeFingerprint(source_fp, target_fp) 10916e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge else: 10926e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge script.AssertSomeThumbprint( 10936e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict), 10946e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict)) 10956e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge 10962ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker metadata["pre-build"] = source_fp 10972ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker metadata["post-build"] = target_fp 1098eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 109955d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker source_boot = common.GetBootableImage( 1100d513160b76a189899ba01f87a3987b4c6f428caeDoug Zongker "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", 1101d513160b76a189899ba01f87a3987b4c6f428caeDoug Zongker OPTIONS.source_info_dict) 110255d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker target_boot = common.GetBootableImage( 110355d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT") 11049b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker updating_boot = (not OPTIONS.two_step and 11059b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker (source_boot.data != target_boot.data)) 1106eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 110755d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker source_recovery = common.GetBootableImage( 1108d513160b76a189899ba01f87a3987b4c6f428caeDoug Zongker "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY", 1109d513160b76a189899ba01f87a3987b4c6f428caeDoug Zongker OPTIONS.source_info_dict) 111055d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker target_recovery = common.GetBootableImage( 111155d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY") 1112f6a8bada5f0966762eadaec96de6430d0cd577e3Doug Zongker updating_recovery = (source_recovery.data != target_recovery.data) 1113eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1114881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker # Here's how we divide up the progress bar: 1115881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker # 0.1 for verifying the start state (PatchCheck calls) 1116881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker # 0.8 for applying patches (ApplyPatch calls) 1117881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker # 0.1 for unpacking verbatim files, symlinking, and doing the 1118881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker # device-specific commands. 1119eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 11206e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge AppendAssertions(script, OPTIONS.target_info_dict, oem_dict) 112105d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific.IncrementalOTA_Assertions() 1122eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 11239b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # Two-step incremental package strategy (in chronological order, 11249b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # which is *not* the order in which the generated script has 11259b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # things): 11269b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # 11279b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # if stage is not "2/3" or "3/3": 11289b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # do verification on current system 11299b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # write recovery image to boot partition 11309b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set stage to "2/3" 11319b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # reboot to boot partition and restart recovery 11329b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # else if stage is "2/3": 11339b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # write recovery image to recovery partition 11349b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set stage to "3/3" 11359b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # reboot to recovery partition and restart recovery 11369b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # else: 11379b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # (stage must be "3/3") 11389b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # perform update: 11399b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # patch system files, etc. 11409b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # force full install of new boot image 11419b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # set up system to update recovery partition on first boot 11429b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # complete script normally (allow recovery to mark itself finished and reboot) 11439b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 11449b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if OPTIONS.two_step: 11459b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if not OPTIONS.info_dict.get("multistage_support", None): 11469b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker assert False, "two-step packages not supported by this build" 11479b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker fs = OPTIONS.info_dict["fstab"]["/misc"] 11489b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker assert fs.fs_type.upper() == "EMMC", \ 11499b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker "two-step packages only supported on devices with EMMC /misc partitions" 11509b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker bcb_dev = {"bcb_dev": fs.device} 11519b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data) 11529b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 1153f9d181979097af3f4a62dad9fff318a916759597Michael Rungeif get_stage("%(bcb_dev)s") == "2/3" then 11549b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 11559b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra("sleep(20);\n"); 11569b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.WriteRawImage("/recovery", "recovery.img") 11579b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 11589b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerset_stage("%(bcb_dev)s", "3/3"); 11599b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerreboot_now("%(bcb_dev)s", "recovery"); 1160f9d181979097af3f4a62dad9fff318a916759597Michael Rungeelse if get_stage("%(bcb_dev)s") != "3/3" then 11619b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 11629b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 1163c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.Print("Verifying current system...") 1164c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 1165e5ff5907bef42fa9f3eff2e90ad941423dcc91dcDoug Zongker device_specific.IncrementalOTA_VerifyBegin() 1166e5ff5907bef42fa9f3eff2e90ad941423dcc91dcDoug Zongker 1167881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker script.ShowProgress(0.1, 0) 1168c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far = system_diff.EmitVerification(script) 1169c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1170c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far += vendor_diff.EmitVerification(script) 1171eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 11725da317e51d1832cb1ec67dd20fbcff7708bbadb5Doug Zongker if updating_boot: 1173ea5d7a9de7660bef5b9c68f6372a92d4b2f2f1f6Doug Zongker d = common.Difference(target_boot, source_boot) 1174761e642d54eec743699c6c2ce1ea587853d08f33Doug Zongker _, _, d = d.ComputePatch() 11755da317e51d1832cb1ec67dd20fbcff7708bbadb5Doug Zongker print "boot target: %d source: %d diff: %d" % ( 11765da317e51d1832cb1ec67dd20fbcff7708bbadb5Doug Zongker target_boot.size, source_boot.size, len(d)) 11775da317e51d1832cb1ec67dd20fbcff7708bbadb5Doug Zongker 1178048e7ca15f6391681490ce564bc71194adf146aaDoug Zongker common.ZipWriteStr(output_zip, "patch/boot.img.p", d) 11795da317e51d1832cb1ec67dd20fbcff7708bbadb5Doug Zongker 118096a57e737707d05333dced5b657c4ef21c44088aDoug Zongker boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict) 1181f2ab290550d6f1b1ea9bab91eb4c3c77ceeb5df4Doug Zongker 1182f2ab290550d6f1b1ea9bab91eb4c3c77ceeb5df4Doug Zongker script.PatchCheck("%s:%s:%d:%s:%d:%s" % 1183f2ab290550d6f1b1ea9bab91eb4c3c77ceeb5df4Doug Zongker (boot_type, boot_device, 118467369983cf23e12724c135c3850c98326558256bDoug Zongker source_boot.size, source_boot.sha1, 1185c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker target_boot.size, target_boot.sha1)) 1186881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker so_far += source_boot.size 11875da317e51d1832cb1ec67dd20fbcff7708bbadb5Doug Zongker 1188c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker size = [] 1189c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if system_diff.patch_list: size.append(system_diff.largest_source_size) 1190c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1191c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff.patch_list: size.append(vendor_diff.largest_source_size) 1192c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if size or updating_recovery or updating_boot: 1193c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.CacheFreeSpaceCheck(max(size)) 11945a48209541d5eed602bfb8e2c4ff51e31443daf2Doug Zongker 119505d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific.IncrementalOTA_VerifyEnd() 119605d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker 11979b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if OPTIONS.two_step: 11989b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.WriteRawImage("/boot", "recovery.img") 11999b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 12009b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerset_stage("%(bcb_dev)s", "2/3"); 12019b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerreboot_now("%(bcb_dev)s", ""); 12029b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerelse 12039b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 12049b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 1205c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.Comment("---- start making changes here ----") 1206eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1207e5ff5907bef42fa9f3eff2e90ad941423dcc91dcDoug Zongker device_specific.IncrementalOTA_InstallBegin() 1208e5ff5907bef42fa9f3eff2e90ad941423dcc91dcDoug Zongker 12099b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if OPTIONS.two_step: 12109b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker common.ZipWriteStr(output_zip, "boot.img", target_boot.data) 12119b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.WriteRawImage("/boot", "boot.img") 12129b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker print "writing full boot image (forced by two-step mode)" 12139b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 1214c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.Print("Removing unneeded files...") 1215c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_diff.RemoveUnneededFiles(script, ("/system/recovery.img",)) 1216c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1217c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_diff.RemoveUnneededFiles(script) 1218eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1219881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker script.ShowProgress(0.8, 0) 1220c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker total_patch_size = 1.0 + system_diff.TotalPatchSize() 1221c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1222c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker total_patch_size += vendor_diff.TotalPatchSize() 1223881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker if updating_boot: 1224881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker total_patch_size += target_boot.size 1225881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker 1226881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker script.Print("Patching system files...") 1227c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far = system_diff.EmitPatches(script, total_patch_size, 0) 1228c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1229c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.Print("Patching vendor files...") 1230c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker so_far = vendor_diff.EmitPatches(script, total_patch_size, so_far) 1231881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker 12329b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if not OPTIONS.two_step: 12339b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if updating_boot: 12349b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # Produce the boot image by applying a patch to the current 12359b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # contents of the boot partition, and write it back to the 12369b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker # partition. 12379b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.Print("Patching boot image...") 12389b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.ApplyPatch("%s:%s:%d:%s:%d:%s" 12399b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker % (boot_type, boot_device, 12409b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker source_boot.size, source_boot.sha1, 12419b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker target_boot.size, target_boot.sha1), 12429b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker "-", 12439b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker target_boot.size, target_boot.sha1, 12449b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker source_boot.sha1, "patch/boot.img.p") 12459b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker so_far += target_boot.size 12469b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.SetProgress(so_far / total_patch_size) 12479b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker print "boot image changed; including." 12489b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker else: 12499b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker print "boot image unchanged; skipping." 1250eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1251c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items = ItemSet("system", "META/filesystem_config.txt") 1252c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1253c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_items = ItemSet("vendor", "META/vendor_filesystem_config.txt") 1254c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1255eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if updating_recovery: 1256b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # Recovery is generated as a patch using both the boot image 1257b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # (which contains the same linux kernel as recovery) and the file 1258b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # /system/etc/recovery-resource.dat (which contains all the images 1259b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # used in the recovery UI) as sources. This lets us minimize the 1260b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # size of the patch, which must be included in every OTA package. 126173ef8257ce54ce1ddc2d4cfc3b3814ca734c0e11Doug Zongker # 1262b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # For older builds where recovery-resource.dat is not present, we 1263b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker # use only the boot image as the source. 1264b32161a2a54706efc0d3493123a971aae93e5261Doug Zongker 1265c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker if not target_has_recovery_patch: 1266c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker def output_sink(fn, data): 1267c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker common.ZipWriteStr(output_zip, "recovery/" + fn, data) 1268c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items.Get("system/" + fn, dir=False) 1269c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker 1270c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker common.MakeRecoveryPatch(OPTIONS.target_tmp, output_sink, 1271c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker target_recovery, target_boot) 1272c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker script.DeleteFiles(["/system/recovery-from-boot.p", 1273c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker "/system/etc/install-recovery.sh"]) 127473ef8257ce54ce1ddc2d4cfc3b3814ca734c0e11Doug Zongker print "recovery image changed; including as patch from boot." 1275eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 1276eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print "recovery image unchanged; skipping." 1277eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1278881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker script.ShowProgress(0.1, 10) 1279eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1280c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker target_symlinks = CopyPartitionFiles(system_items, target_zip, None) 1281c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1282c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker target_symlinks.extend(CopyPartitionFiles(vendor_items, target_zip, None)) 1283eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1284c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker temp_script = script.MakeTemporary() 1285c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items.GetMetadata(target_zip) 1286c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_items.Get("system").SetPermissions(temp_script) 1287c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1288c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_items.GetMetadata(target_zip) 1289c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_items.Get("vendor").SetPermissions(temp_script) 1290c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker 1291c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # Note that this call will mess up the trees of Items, so make sure 1292c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker # we're done with them. 1293c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker source_symlinks = CopyPartitionFiles(system_items, source_zip, None) 1294c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1295c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker source_symlinks.extend(CopyPartitionFiles(vendor_items, source_zip, None)) 1296eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1297c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks]) 1298eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker source_symlinks_d = dict([(i[1], i[0]) for i in source_symlinks]) 1299eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1300eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # Delete all the symlinks in source that aren't in target. This 1301eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # needs to happen before verbatim files are unpacked, in case a 1302eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # symlink in the source is replaced by a real file in the target. 1303eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker to_delete = [] 1304eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for dest, link in source_symlinks: 1305eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if link not in target_symlinks_d: 1306eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker to_delete.append(link) 1307c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.DeleteFiles(to_delete) 1308eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1309c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if system_diff.verbatim_targets: 1310c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.Print("Unpacking new system files...") 1311c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.UnpackPackageDir("system", "/system") 1312c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff and vendor_diff.verbatim_targets: 1313c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.Print("Unpacking new vendor files...") 1314c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker script.UnpackPackageDir("vendor", "/vendor") 1315c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker 1316c9253822ea31c1d35d3fc2b495b45b476c240a1dDoug Zongker if updating_recovery and not target_has_recovery_patch: 131742265390d993664e7797abc12d7e6bd1c2a6dc6bDoug Zongker script.Print("Unpacking new recovery...") 131842265390d993664e7797abc12d7e6bd1c2a6dc6bDoug Zongker script.UnpackPackageDir("recovery", "/system") 131942265390d993664e7797abc12d7e6bd1c2a6dc6bDoug Zongker 1320c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_diff.EmitRenames(script) 1321c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker if vendor_diff: 1322c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker vendor_diff.EmitRenames(script) 13234038aa8fff8c68733bff8b55d8c8d1b59713ca37Michael Runge 132405d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker script.Print("Symlinks and permissions...") 1325eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1326eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # Create all the symlinks that don't already exist, or point to 1327eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # somewhere different than what we want. Delete each symlink before 1328eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # creating it, since the 'symlink' command won't overwrite. 1329eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker to_create = [] 1330eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for dest, link in target_symlinks: 1331eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if link in source_symlinks_d: 1332eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if dest != source_symlinks_d[link]: 1333eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker to_create.append((dest, link)) 1334eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 1335eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker to_create.append((dest, link)) 1336c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.DeleteFiles([i[1] for i in to_create]) 1337c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.MakeSymlinks(to_create) 1338eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1339eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # Now that the symlinks are created, we can set all the 1340eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # permissions. 1341c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker script.AppendScript(temp_script) 1342eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1343881dd40ffb683fed465df955f3fd21812fae59aaDoug Zongker # Do device-specific installation (eg, write radio image). 134405d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker device_specific.IncrementalOTA_InstallEnd() 134505d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker 13461c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker if OPTIONS.extra_script is not None: 134767369983cf23e12724c135c3850c98326558256bDoug Zongker script.AppendExtra(OPTIONS.extra_script) 13481c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker 1349e92f15a85885de8db24b6f2ab536d25cf20a5ca5Doug Zongker # Patch the build.prop file last, so if something fails but the 1350e92f15a85885de8db24b6f2ab536d25cf20a5ca5Doug Zongker # device can still come up, it appears to be the old build and will 1351e92f15a85885de8db24b6f2ab536d25cf20a5ca5Doug Zongker # get set the OTA package again to retry. 1352e92f15a85885de8db24b6f2ab536d25cf20a5ca5Doug Zongker script.Print("Patching remaining system files...") 1353c8b4e849f10f3a382694b00453b3f49608c83b48Doug Zongker system_diff.EmitDeferredPatches(script) 1354e92f15a85885de8db24b6f2ab536d25cf20a5ca5Doug Zongker 1355922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker if OPTIONS.wipe_user_data: 1356922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker script.Print("Erasing user data...") 1357922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker script.FormatPartition("/data") 1358922206ec2aeea98491e3edfc297a28b0a39df698Doug Zongker 13599b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker if OPTIONS.two_step: 13609b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker script.AppendExtra(""" 13619b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerset_stage("%(bcb_dev)s", ""); 13629b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerendif; 13639b23f2cd786b46991b7c0198e69264b17875288dDoug Zongkerendif; 13649b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker""" % bcb_dev) 13659b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker 1366e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge if OPTIONS.verify and system_diff: 1367e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.Print("Remounting and verifying system partition files...") 1368e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.Unmount("/system") 1369e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.Mount("/system") 1370e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge system_diff.EmitExplicitTargetVerification(script) 1371e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge 1372e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge if OPTIONS.verify and vendor_diff: 1373e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.Print("Remounting and verifying vendor partition files...") 1374e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.Unmount("/vendor") 1375e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge script.Mount("/vendor") 1376e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge vendor_diff.EmitExplicitTargetVerification(script) 137725568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary) 1378e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge 13792ea21065b66da9819df92b37a79f0f87552ee331Doug Zongker WriteMetadata(metadata, output_zip) 1380eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1381eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1382eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef main(argv): 1383eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1384eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker def option_handler(o, a): 138525568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker if o == "--board_config": 1386fdd8e69c42e66fb70384bcaca1747f504f2c021cDoug Zongker pass # deprecated 1387eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker elif o in ("-k", "--package_key"): 1388eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker OPTIONS.package_key = a 1389eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker elif o in ("-i", "--incremental_from"): 1390eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker OPTIONS.incremental_source = a 1391dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker elif o in ("-w", "--wipe_user_data"): 1392dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker OPTIONS.wipe_user_data = True 1393962069ce59c85949d147874df2728a5ffd9193beDoug Zongker elif o in ("-n", "--no_prereq"): 1394962069ce59c85949d147874df2728a5ffd9193beDoug Zongker OPTIONS.omit_prereq = True 13956e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge elif o in ("-o", "--oem_settings"): 13966e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge OPTIONS.oem_source = a 13971c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker elif o in ("-e", "--extra_script"): 13981c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker OPTIONS.extra_script = a 1399dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov elif o in ("-a", "--aslr_mode"): 1400dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov if a in ("on", "On", "true", "True", "yes", "Yes"): 1401dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov OPTIONS.aslr_mode = True 1402dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov else: 1403dafb04275588fff8248b6a5360ca047cdffd14a5Hristo Bojinov OPTIONS.aslr_mode = False 1404374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl elif o in ("-t", "--worker_threads"): 1405374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl if a.isdigit(): 1406374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl OPTIONS.worker_threads = int(a) 1407374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl else: 1408374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl raise ValueError("Cannot parse value %r for option %r - only " 1409374e114d1691a47918a3972dc287615f25650725Martin Blumenstingl "integers are allowed." % (a, o)) 14109b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker elif o in ("-2", "--two_step"): 14119b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker OPTIONS.two_step = True 141226e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker elif o == "--no_signing": 1413e153b3464374155d03bfe47092faaab555b89e81Takeshi Kanemoto OPTIONS.no_signing = True 1414e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge elif o in ("--verify"): 1415e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge OPTIONS.verify = True 141626e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker elif o == "--block": 141726e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker OPTIONS.block_based = True 141825568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker elif o in ("-b", "--binary"): 141925568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker OPTIONS.updater_binary = a 142062d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker elif o in ("--no_fallback_to_full",): 142162d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.fallback_to_full = False 1422eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 1423eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return False 1424dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker return True 1425eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1426eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker args = common.ParseOptions(argv, __doc__, 1427f5770d78da76ce49ca1ab8334874abdaa6cc7115Ying Wang extra_opts="b:k:i:d:wne:t:a:2o:", 1428eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker extra_long_opts=["board_config=", 1429eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker "package_key=", 1430dbfaae5567dbbfcc17e15b31e65178ad367e6d13Doug Zongker "incremental_from=", 1431962069ce59c85949d147874df2728a5ffd9193beDoug Zongker "wipe_user_data", 14321c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker "no_prereq", 1433c494d7cee85d980647ca915ea64355b71fe817ebDoug Zongker "extra_script=", 143496be7205dce97977909e93b73f48779fcce3bc65Hristo Bojinov "worker_threads=", 1435c60c1bafa0c20166c53666655e2dea7ff5bfd157Doug Zongker "aslr_mode=", 14369b23f2cd786b46991b7c0198e69264b17875288dDoug Zongker "two_step", 1437e153b3464374155d03bfe47092faaab555b89e81Takeshi Kanemoto "no_signing", 143826e6619c37e294fe2ee63aaa759e0ac861775ce8Doug Zongker "block", 143925568486e5777f416d2fcb6cc7aa96caafc66880Doug Zongker "binary=", 14406e836116f764cf5cebf1654df2f17d8222554f6eMichael Runge "oem_settings=", 1441e8269481084df086a04c6bdcd3477d4209d4a7cbMichael Runge "verify", 144262d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker "no_fallback_to_full", 1443c60c1bafa0c20166c53666655e2dea7ff5bfd157Doug Zongker ], 1444eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker extra_option_handler=option_handler) 1445eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1446eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if len(args) != 2: 1447eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker common.Usage(__doc__) 1448eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sys.exit(1) 1449eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 14501c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker if OPTIONS.extra_script is not None: 14511c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker OPTIONS.extra_script = open(OPTIONS.extra_script).read() 14521c390a2aa97127ef8af8b0df1d4028f501fdce64Doug Zongker 1453eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print "unzipping target target-files..." 145455d932840f1a5b412f2961f79368ecec2d28f647Doug Zongker OPTIONS.input_tmp, input_zip = common.UnzipTemp(args[0]) 1455fdd8e69c42e66fb70384bcaca1747f504f2c021cDoug Zongker 1456eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker OPTIONS.target_tmp = OPTIONS.input_tmp 145737974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker OPTIONS.info_dict = common.LoadInfoDict(input_zip) 1458e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root 1459e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root # If this image was originally labelled with SELinux contexts, make sure we 1460e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root # also apply the labels in our new image. During building, the "file_contexts" 1461e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root # is in the out/ directory tree, but for repacking from target-files.zip it's 1462e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root # in the root directory of the ramdisk. 1463e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root if "selinux_fc" in OPTIONS.info_dict: 1464e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root OPTIONS.info_dict["selinux_fc"] = os.path.join(OPTIONS.input_tmp, "BOOT", "RAMDISK", 1465e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root "file_contexts") 1466e2e9f613b5259313c5216d4dad719998a2fbf014Kenny Root 146737974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker if OPTIONS.verbose: 146837974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker print "--- target info ---" 146937974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker common.DumpInfoDict(OPTIONS.info_dict) 147037974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker 1471eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker # If the caller explicitly specified the device-specific extensions 1472eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker # path via -s/--device_specific, use that. Otherwise, use 1473eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker # META/releasetools.py if it is present in the target target_files. 1474eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker # Otherwise, take the path of the file from 'tool_extensions' in the 1475eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker # info dict and look for that in the local filesystem, relative to 1476eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker # the current directory. 1477eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker 147837974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker if OPTIONS.device_specific is None: 1479eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py") 1480eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker if os.path.exists(from_input): 1481eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker print "(using device-specific extensions from target_files)" 1482eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker OPTIONS.device_specific = from_input 1483eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker else: 1484eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None) 1485eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker 148637974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker if OPTIONS.device_specific is not None: 1487eb0a78afc00265479c002364fa62c9e09c3f613dDoug Zongker OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific) 148837974731fcb4e32b1de5f213d34bd832ca889869Doug Zongker 148962d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker while True: 149062d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker 149162d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if OPTIONS.no_signing: 149262d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if os.path.exists(args[1]): os.unlink(args[1]) 149362d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED) 149462d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker else: 149562d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker temp_zip_file = tempfile.NamedTemporaryFile() 149662d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker output_zip = zipfile.ZipFile(temp_zip_file, "w", 149762d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker compression=zipfile.ZIP_DEFLATED) 149862d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker 149962d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if OPTIONS.incremental_source is None: 150062d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker WriteFullOTAPackage(input_zip, output_zip) 150162d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if OPTIONS.package_key is None: 150262d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.package_key = OPTIONS.info_dict.get( 150362d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker "default_system_dev_certificate", 150462d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker "build/target/product/security/testkey") 150562d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker break 150662d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker 150762d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker else: 150862d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker print "unzipping source target-files..." 150962d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source) 151062d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.target_info_dict = OPTIONS.info_dict 151162d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.source_info_dict = common.LoadInfoDict(source_zip) 151262d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if "selinux_fc" in OPTIONS.source_info_dict: 151362d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.source_info_dict["selinux_fc"] = os.path.join(OPTIONS.source_tmp, "BOOT", "RAMDISK", 151462d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker "file_contexts") 151562d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if OPTIONS.package_key is None: 151662d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.package_key = OPTIONS.source_info_dict.get( 151762d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker "default_system_dev_certificate", 151862d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker "build/target/product/security/testkey") 151962d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if OPTIONS.verbose: 152062d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker print "--- source info ---" 152162d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker common.DumpInfoDict(OPTIONS.source_info_dict) 152262d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker try: 152362d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker WriteIncrementalOTAPackage(input_zip, source_zip, output_zip) 152462d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker break 152562d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker except ValueError: 152662d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker if not OPTIONS.fallback_to_full: raise 152762d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker print "--- failed to build incremental; falling back to full ---" 152862d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker OPTIONS.incremental_source = None 152962d4f18a30aeade677ca814cf6f2aa329cf5066dDoug Zongker output_zip.close() 1530eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1531eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker output_zip.close() 1532afb32eaca0b0f424f7d7fc5f5979d1b8acf042e4Doug Zongker 1533e153b3464374155d03bfe47092faaab555b89e81Takeshi Kanemoto if not OPTIONS.no_signing: 1534e153b3464374155d03bfe47092faaab555b89e81Takeshi Kanemoto SignOutput(temp_zip_file.name, args[1]) 1535e153b3464374155d03bfe47092faaab555b89e81Takeshi Kanemoto temp_zip_file.close() 1536eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1537eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print "done." 1538eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1539eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 1540eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerif __name__ == '__main__': 1541eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker try: 15427e6d4e45d92fd51f42812ae63ac6e532887bfe0aYing Wang common.CloseInheritedPipes() 1543eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker main(sys.argv[1:]) 1544eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker except common.ExternalError, e: 1545eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print 1546eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print " ERROR: %s" % (e,) 1547eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print 1548eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sys.exit(1) 1549fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker finally: 1550fc44a515d46e6f4d5eaa0d32659b1cf3b9492305Doug Zongker common.Cleanup() 1551