├── ResValuesModify ├── jar │ ├── ResValuesModify │ ├── ResValuesModify.jar │ └── config └── src │ ├── Log.java │ ├── ResValuesModify.java │ ├── XMLMerge.java │ ├── make_jar │ └── manifest.txt ├── aapt.exe ├── add_miui_methods_and_variables.sh ├── add_miui_res.sh ├── add_miui_smail.sh ├── apkcerts.py ├── apktool ├── apktool.jar ├── baksmali ├── baksmali.jar ├── build_libra.sh ├── build_target_files.sh ├── change_rom.sh ├── darwin-x86 ├── aapt ├── bsdiff ├── imgdiff ├── lib64 │ ├── libcutils.dylib │ └── liblog.dylib ├── mkbootfs ├── mkbootimg ├── unpackbootimg └── zipalign ├── deoat.sh ├── deodex.sh ├── diffsmali.sh ├── fix_9patch_png.sh ├── fix_plurals.sh ├── gen_desklayout.pl ├── gen_desktop_layout.sh ├── gen_res_conf.sh ├── get_apk_cert.py ├── get_filesystem_config ├── git.apply ├── git.patch ├── git_smali_diff ├── git_upload_no_verify.py ├── hex_replace.py ├── insertkeys.py ├── keys.conf ├── linux-x86 ├── aapt ├── bsdiff ├── imgdiff ├── lib │ └── libc++.so ├── mkbootfs ├── mkbootimg ├── unpackbootimg └── zipalign ├── make_key ├── merge_divide_jar_out.sh ├── multi_format_subst.pl ├── oat2dex ├── oat2dex-0.86.jar ├── oat2dex-0.87.jar ├── oat2dex.jar ├── patch_bootimg.sh ├── patch_for_phones.sh ├── patch_miui_app.sh ├── patch_miui_framework.sh ├── post_process_props.py ├── prepare_preloaded_classes.sh ├── release_source.sh ├── releasetools ├── blockimgdiff.py ├── common.py ├── edify_generator.py ├── getfilesysteminfo ├── miui_releasetools.py ├── ota_from_target_files ├── ota_target_from_phone ├── pylintrc ├── rangelib.py ├── recoverylink.py ├── sign_target_files_apks └── sparse_img.py ├── remove_redef.py ├── replace_package_name.sh ├── replace_res_id.pl ├── replace_smali_method.sh ├── resolve_patch.sh ├── restore_obsolete_keyguard.sh ├── rewrite.py ├── rmline.sh ├── sign.sh ├── signapk.jar ├── smali ├── smali.jar ├── target_files_template ├── BOOTABLE_IMAGES │ └── recovery.img ├── META │ ├── apkcerts.txt │ ├── filesystem_config.txt │ ├── misc_info.txt │ └── otakeys.txt ├── OTA │ ├── android-info.txt │ └── bin │ │ ├── applypatch │ │ ├── applypatch_static │ │ ├── busybox │ │ ├── check_prereq │ │ ├── relink │ │ ├── replace_key │ │ ├── sqlite3 │ │ └── updater ├── RADIO │ ├── bitmap_size.txt │ ├── firmware_error.565 │ └── firmware_install.565 ├── RECOVERY │ └── RAMDISK │ │ └── etc │ │ └── recovery.fstab └── SYSTEM │ └── build.prop └── uniq_first.py /ResValuesModify/jar/ResValuesModify: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | java -jar $PORT_ROOT/tools/ResValuesModify/jar/ResValuesModify.jar $* 4 | 5 | 6 | -------------------------------------------------------------------------------- /ResValuesModify/jar/ResValuesModify.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/ResValuesModify/jar/ResValuesModify.jar -------------------------------------------------------------------------------- /ResValuesModify/jar/config: -------------------------------------------------------------------------------- 1 | # NOTE: 2 | # default operation is replace dest node with src node if the dest node exist or 3 | # append src node to the file if dest node doesn't exist 4 | # 5 | # - type [name] 6 | # explicitly declare don't merge this kind of nodes 7 | # 8 | # + type [name] 9 | # explicitly declare that merge this kind of nodes 10 | # 11 | # I array-type [name] 12 | # explicitly declare that to insert new 'items' for 'array' type instead of default replacement 13 | # insert new items to the head of array 14 | # priority of "+" and "I" is higher then "-" 15 | 16 | - add-resource 17 | 18 | I string-array config_statusBarIcons 19 | -------------------------------------------------------------------------------- /ResValuesModify/src/Log.java: -------------------------------------------------------------------------------- 1 | public class Log { 2 | public static void i(String info){ 3 | System.out.println(info); 4 | } 5 | 6 | public static void i(String tag, String info){ 7 | System.out.println( String.format("INFO[%s]: %s", tag, info)); 8 | } 9 | 10 | public static void e(String tag, String err){ 11 | System.err.println( String.format("ERROR[%s]: %s", tag, err)); 12 | } 13 | 14 | public static void w(String tag, String err){ 15 | System.err.println( String.format("WARING[%s]: %s", tag, err)); 16 | } 17 | 18 | public static void e(String err){ 19 | System.err.println(err); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ResValuesModify/src/ResValuesModify.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.util.ArrayList; 3 | 4 | public class ResValuesModify { 5 | private ArrayList mSrcFiles = new ArrayList(); 6 | private ArrayList mDestFiles = new ArrayList(); 7 | private ArrayList mConfigFiles = new ArrayList(); 8 | private static final String LOG_TAG = "CHECK"; 9 | 10 | public static void main(String[] args) { 11 | ResValuesModify resVM = new ResValuesModify(); 12 | if (!resVM.checkArgs(args) || !resVM.checkPath(args)) { 13 | resVM.usage(); 14 | return; 15 | } 16 | resVM.mergeXML(); 17 | } 18 | 19 | private boolean checkArgs(String[] args) { 20 | boolean ret = true; 21 | if (args.length < 2) { 22 | Log.e(LOG_TAG, "invalid argument count"); 23 | return false; 24 | } 25 | 26 | if (args[0].equals(args[1])) { 27 | Log.e(LOG_TAG, "src dir is the same with dest dir"); 28 | ret = false; 29 | } 30 | 31 | for (int i = 2; i < args.length; i++) { 32 | File f = new File(args[i]); 33 | if (f.exists() && f.isFile()) { 34 | mConfigFiles.add(f); 35 | } else { 36 | Log.i(LOG_TAG, "ignore config file:" + f.getName()); 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | private boolean checkPath(String[] args) { 43 | return perpareXmlFiles(args[0], mSrcFiles) && perpareXmlFiles(args[1], mDestFiles); 44 | } 45 | 46 | private void mergeXML() { 47 | (new XMLMerge(mSrcFiles, mDestFiles, mConfigFiles)).merge(); 48 | } 49 | 50 | private void usage() { 51 | Log.i("USAGE: "); 52 | Log.i("ResValuesModify src-values-dir dest-values-dir [config-files ...]"); 53 | Log.i(" config-files: config file that explicitly declare merge-rule"); 54 | Log.i(""); 55 | } 56 | 57 | private boolean perpareXmlFiles(String path, ArrayList xmlFiles) { 58 | File dir = new File(path); 59 | if (!dir.isDirectory()) { 60 | Log.w(LOG_TAG, path + " : no such directory"); 61 | return false; 62 | } 63 | 64 | File[] files = dir.listFiles(); 65 | for (File f : files) { 66 | if (f.isFile()) { 67 | if (f.getName().endsWith(".xml") || f.getName().endsWith(".xml.part")) { 68 | xmlFiles.add(f); 69 | } 70 | } 71 | } 72 | 73 | if (0 == xmlFiles.size()) { 74 | Log.w(LOG_TAG, "No xml file in " + path); 75 | return false; 76 | } 77 | return true; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /ResValuesModify/src/make_jar: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | javac ResValuesModify.java 3 | jar -cvmf manifest.txt ResValuesModify.jar *.class 4 | find -name "*.class" | xargs rm 5 | mkdir -p ../jar 6 | cp ResValuesModify.jar ../jar/ResValuesModify.jar 7 | rm ResValuesModify.jar 8 | 9 | -------------------------------------------------------------------------------- /ResValuesModify/src/manifest.txt: -------------------------------------------------------------------------------- 1 | Main-Class: ResValuesModify 2 | 3 | -------------------------------------------------------------------------------- /aapt.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/aapt.exe -------------------------------------------------------------------------------- /add_miui_methods_and_variables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2016 Miui Patchrom 4 | # 5 | 6 | BASE_DIR=$1 7 | MOD_DIR=$2 8 | TARGET_DIR=$3 9 | 10 | IFS=$'\x0A' 11 | 12 | tmp_fifo_file="/tmp/$$.fifo" 13 | mkfifo $tmp_fifo_file 14 | exec 9<>$tmp_fifo_file 15 | 16 | # 8 threads 17 | for((i=0;i<8;i++)) 18 | do 19 | echo "" 20 | done >&9 21 | 22 | 23 | for modSmaliFile in $(find $MOD_DIR -name "*.smali" ! -name "*\$[0-9]*.smali" ! -name "R\$*.smali") 24 | do 25 | baseSmaliFile=${modSmaliFile/$MOD_DIR/$BASE_DIR} 26 | targetSmaliFile=${modSmaliFile/$MOD_DIR/$TARGET_DIR} 27 | read -u9 28 | { 29 | if [ -f $baseSmaliFile ];then 30 | if [ "$(diff $baseSmaliFile $modSmaliFile)" == "" ];then 31 | echo "" >&9 32 | continue 33 | fi 34 | methodBeginLines=($(grep -n "^.method " $modSmaliFile)) 35 | methodEndLines=($(grep -n "^.end method" $modSmaliFile)) 36 | for((i=0;i<${#methodBeginLines[@]};i++)) 37 | do 38 | if [ "$(echo ${methodBeginLines[$i]} | grep -E 'static synthetic|clinit')" == "" ];then 39 | grepPattern="[^->]$(echo ${methodBeginLines[$i]##* } | sed 's/\[/\\\[/g')" 40 | if [ "$(grep $grepPattern $baseSmaliFile)" == "" ];then 41 | beginLineNum=$(echo ${methodBeginLines[$i]} | cut -d ':' -f1) 42 | endLineNum=$(echo ${methodEndLines[$i]} | cut -d ':' -f1) 43 | echo "Add method ${methodBeginLines[$i]##* } into $targetSmaliFile" 44 | sed -n ${beginLineNum},${endLineNum}p $modSmaliFile >> $targetSmaliFile 45 | fi 46 | fi 47 | done 48 | 49 | fieldLines=($(grep -En "^.field |^.end field" $modSmaliFile)) 50 | linesCount=${#fieldLines[@]} 51 | for ((i=0;i<$linesCount;i++)) 52 | do 53 | beginLine=${fieldLines[$i]%% =*} 54 | grepPattern="[^->]$(echo ${beginLine##* } | sed 's/\[/\\\[/g')" 55 | if [ "$(grep $grepPattern $baseSmaliFile)" == "" ];then 56 | echo "Add field ${beginLine##* } into $targetSmaliFile" 57 | beginLineNum=$(echo $beginLine | cut -d ":" -f1) 58 | if [ $(($linesCount-$i)) -ne 1 -a "$(echo ${fieldLines[$i+1]} | grep ".end field")" != "" ];then 59 | endLineNum=$(echo ${fieldLines[$i+1]} | cut -d ":" -f1) 60 | sed -n ${beginLineNum},${endLineNum}p $modSmaliFile >> $targetSmaliFile 61 | i=$(($i+1)) 62 | else 63 | sed -n ${beginLineNum}p $modSmaliFile >> $targetSmaliFile 64 | fi 65 | fi 66 | done 67 | fi 68 | echo "" >&9 69 | }& 70 | done 71 | wait 72 | exec 9>&- 73 | 74 | exit 0 75 | -------------------------------------------------------------------------------- /add_miui_res.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # $1: dir for miui overlay framework-res 4 | # $2: dir for target framework-res 5 | # 6 | if [ -f "customize_framework-res.sh" ]; then 7 | ./customize_framework-res.sh $1 $2 8 | fi 9 | -------------------------------------------------------------------------------- /add_miui_smail.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Add miui smali files 4 | # 5 | # $1: android original src dir 6 | # $2: miui src dir 7 | # $3: target src dir 8 | 9 | BASE_DIR=$1 10 | MIUI_DIR=$2 11 | TARGET_DIR=$3 12 | OVERLAY_DIR=$PORT_ROOT/android/overlay 13 | OVERLAY_CLASSES=$OVERLAY_DIR/OVERLAY_CLASSES 14 | 15 | $PORT_ROOT/tools/add_miui_methods_and_variables.sh $BASE_DIR $MIUI_DIR $TARGET_DIR 16 | 17 | 18 | for class in `cat $OVERLAY_CLASSES | grep -Ev "^$|^#.*$"` 19 | do 20 | target_smali=$TARGET_DIR/smali/$class.smali 21 | target_classes=$TARGET_DIR/smali/$class* 22 | if [ -f "$target_smali" ];then 23 | rm -f $target_classes 24 | fi 25 | done 26 | 27 | 28 | for overlay_smali in `find $OVERLAY_DIR -name "*.smali" | sed 's/\$.*/.smali/' | uniq` 29 | do 30 | target_smali=${overlay_smali/$OVERLAY_DIR/$TARGET_DIR} 31 | if [ -f "$target_smali" ];then 32 | cp -f ${overlay_smali/.smali/}*.smali `dirname $target_smali` 33 | fi 34 | done 35 | 36 | 37 | for file in `find $MIUI_DIR -name "*.smali"` 38 | do 39 | newfile=${file/$MIUI_DIR/$TARGET_DIR} 40 | if [ ! -f "$newfile" ] 41 | then 42 | mkdir -p `dirname $newfile` 43 | cp $file $newfile 44 | fi 45 | done 46 | 47 | if [ -f "customize_framework.sh" ]; then 48 | bash ./customize_framework.sh $2 $3 49 | fi 50 | -------------------------------------------------------------------------------- /apkcerts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | import string 6 | import xml 7 | import xml.dom 8 | from xml.dom import minidom 9 | 10 | def getName(pkg, updatedPackages): 11 | codePath = pkg.attributes["codePath"].value 12 | if codePath.startswith("/data/app"): 13 | codePath = "" 14 | pkgName = pkg.attributes["name"].value 15 | for updatedPkg in updatedPackages: 16 | updatedPkgName = updatedPkg.attributes["name"].value 17 | if updatedPkgName == pkgName: 18 | codePath=updatedPkg.attributes["codePath"].value 19 | break 20 | return os.path.basename(codePath) 21 | 22 | def usage(): 23 | print "Usage: python ./apkcerts.py path-to-packages.xml path-to-apkcerts.txt" 24 | 25 | def main(): 26 | if len(sys.argv) != 3: 27 | usage() 28 | sys.exit(1) 29 | 30 | try: 31 | xmldoc = minidom.parse(sys.argv[1]) 32 | except : 33 | print "Error: %s doesn't exist or isn't a vaild xml file" %(sys.argv[1]) 34 | sys.exit(1) 35 | 36 | updatedPackages = xmldoc.getElementsByTagName("updated-package") 37 | packages = xmldoc.getElementsByTagName("package") 38 | sigpkgs = {} 39 | for pkg in packages: 40 | name = getName(pkg, updatedPackages) 41 | cert= pkg.getElementsByTagName("cert") 42 | if not cert or not name: continue 43 | index = cert[0].getAttribute("index") 44 | sigpkgs[index] = sigpkgs.get(index, []) + [name] 45 | 46 | sharedUsers = xmldoc.getElementsByTagName("shared-user") 47 | sigmap = {} 48 | for user in sharedUsers: 49 | name = user.getAttribute("name") 50 | cert = user.getElementsByTagName("cert") 51 | if not cert: continue 52 | index = cert[0].getAttribute("index") 53 | if name == "android.uid.system": 54 | sigmap[index] = "platform" 55 | elif name == "android.media": 56 | sigmap[index] = "media" 57 | elif name == "android.uid.shared": 58 | sigmap[index] = "shared" 59 | 60 | with open(sys.argv[2], "w") as f: 61 | for keyindex, pkgnames in sigpkgs.items(): 62 | sig = sigmap.get(keyindex, None) 63 | for pkgname in pkgnames: 64 | if sig: 65 | line = 'name="{0}.apk" certificate="build/target/product/security/{1}.x509.pem" private_key="build/target/product/security/{1}.pk8"\n'.format(pkgname, sig) 66 | else: 67 | line = 'name="{0}.apk" certificate="PRESIGNED" private_key=""\n'.format(pkgname) 68 | f.write(line) 69 | 70 | if "__main__" == __name__: 71 | main() 72 | -------------------------------------------------------------------------------- /apktool: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2007 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This script is a wrapper for smali.jar, so you can simply call "smali", 18 | # instead of java -jar smali.jar. It is heavily based on the "dx" script 19 | # from the Android SDK 20 | 21 | # Set up prog to be the path of this script, including following symlinks, 22 | # and set up progdir to be the fully-qualified pathname of its directory. 23 | prog="$0" 24 | while [ -h "${prog}" ]; do 25 | newProg=`/bin/ls -ld "${prog}"` 26 | echo ${newProg} 27 | 28 | 29 | newProg=`expr "${newProg}" : ".* -> \(.*\)$"` 30 | if expr "x${newProg}" : 'x/' >/dev/null; then 31 | prog="${newProg}" 32 | else 33 | progdir=`dirname "${prog}"` 34 | prog="${progdir}/${newProg}" 35 | fi 36 | done 37 | oldwd=`pwd` 38 | progdir=`dirname "${prog}"` 39 | cd "${progdir}" 40 | progdir=`pwd` 41 | prog="${progdir}"/`basename "${prog}"` 42 | cd "${oldwd}" 43 | 44 | 45 | jarfile=apktool.jar 46 | libdir="$progdir" 47 | if [ ! -r "$libdir/$jarfile" ] 48 | then 49 | echo `basename "$prog"`": can't find $jarfile" 50 | exit 1 51 | fi 52 | 53 | javaOpts="" 54 | 55 | # If you want DX to have more memory when executing, uncomment the following 56 | # line and adjust the value accordingly. Use "java -X" for a list of options 57 | # you can pass here. 58 | # 59 | javaOpts="-Xmx1024M" 60 | 61 | # Alternatively, this will extract any parameter "-Jxxx" from the command line 62 | # and pass them to Java (instead of to dx). This makes it possible for you to 63 | # add a command-line parameter such as "-JXmx256M" in your ant scripts, for 64 | # example. 65 | while expr "x$1" : 'x-J' >/dev/null; do 66 | opt=`expr "$1" : '-J\(.*\)'` 67 | javaOpts="${javaOpts} -${opt}" 68 | shift 69 | done 70 | 71 | if [ "$OSTYPE" = "cygwin" ] ; then 72 | jarpath=`cygpath -w "$libdir/$jarfile"` 73 | else 74 | jarpath="$libdir/$jarfile" 75 | fi 76 | 77 | exec java $javaOpts -jar "$jarpath" "$@" 78 | -------------------------------------------------------------------------------- /apktool.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/apktool.jar -------------------------------------------------------------------------------- /baksmali: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2007 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # As per the Apache license requirements, this file has been modified 18 | # from its original state. 19 | # 20 | # Such modifications are Copyright (C) 2010 Ben Gruver, and are released 21 | # under the original license 22 | 23 | # This script is a wrapper around baksmali.jar, so you can simply call 24 | # "baksmali", instead of java -jar baksmali.jar. It is heavily based on 25 | # the "dx" script from the Android SDK 26 | 27 | # Set up prog to be the path of this script, including following symlinks, 28 | # and set up progdir to be the fully-qualified pathname of its directory. 29 | prog="$0" 30 | while [ -h "${prog}" ]; do 31 | newProg=`/bin/ls -ld "${prog}"` 32 | echo ${newProg} 33 | 34 | 35 | newProg=`expr "${newProg}" : ".* -> \(.*\)$"` 36 | if expr "x${newProg}" : 'x/' >/dev/null; then 37 | prog="${newProg}" 38 | else 39 | progdir=`dirname "${prog}"` 40 | prog="${progdir}/${newProg}" 41 | fi 42 | done 43 | oldwd=`pwd` 44 | progdir=`dirname "${prog}"` 45 | cd "${progdir}" 46 | progdir=`pwd` 47 | prog="${progdir}"/`basename "${prog}"` 48 | cd "${oldwd}" 49 | 50 | 51 | jarfile=baksmali.jar 52 | libdir="$progdir" 53 | if [ ! -r "$libdir/$jarfile" ] 54 | then 55 | echo `basename "$prog"`": can't find $jarfile" 56 | exit 1 57 | fi 58 | 59 | javaOpts="" 60 | 61 | # If you want DX to have more memory when executing, uncomment the following 62 | # line and adjust the value accordingly. Use "java -X" for a list of options 63 | # you can pass here. 64 | # 65 | javaOpts="-Xmx256M" 66 | 67 | # Alternatively, this will extract any parameter "-Jxxx" from the command line 68 | # and pass them to Java (instead of to dx). This makes it possible for you to 69 | # add a command-line parameter such as "-JXmx256M" in your ant scripts, for 70 | # example. 71 | while expr "x$1" : 'x-J' >/dev/null; do 72 | opt=`expr "$1" : '-J\(.*\)'` 73 | javaOpts="${javaOpts} -${opt}" 74 | shift 75 | done 76 | 77 | if [ "$OSTYPE" = "cygwin" ] ; then 78 | jarpath=`cygpath -w "$libdir/$jarfile"` 79 | else 80 | jarpath="$libdir/$jarfile" 81 | fi 82 | 83 | exec java $javaOpts -jar "$jarpath" "$@" 84 | -------------------------------------------------------------------------------- /baksmali.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/baksmali.jar -------------------------------------------------------------------------------- /build_libra.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ -z $2 ] 3 | then 4 | exit 1 5 | fi 6 | 7 | echo build $2 under $1 8 | cd $1 9 | make $2 10 | -------------------------------------------------------------------------------- /build_target_files.sh: -------------------------------------------------------------------------------- 1 | PRJ_DIR=`pwd` 2 | METADATA_DIR=$PRJ_DIR/metadata 3 | OUT_DIR=$PRJ_DIR/out 4 | ZIP_DIR=$OUT_DIR/ZIP 5 | TARGET_FILES_DIR=$OUT_DIR/target_files 6 | TARGET_FILES_ZIP=$OUT_DIR/target_files.zip 7 | TARGET_FILES_TEMPLATE_DIR=$PORT_ROOT/tools/target_files_template 8 | TOOL_DIR=$PORT_ROOT/tools 9 | OTA_FROM_TARGET_FILES=$TOOL_DIR/releasetools/ota_from_target_files 10 | SIGN_TARGET_FILES_APKS=$TOOL_DIR/releasetools/sign_target_files_apks 11 | OUT_ZIP_FILE= 12 | NO_SIGN=false 13 | CERTIFICATE_DIR=$PORT_ROOT/build/security 14 | 15 | APKCERT=$PORT_ROOT/miui/metadata/apkcert.txt 16 | if [ "$USE_ANDROID_OUT" == "true" ];then 17 | APKCERT=$ANDROID_OUT/obj/PACKAGING/apkcerts_intermediates/*.txt 18 | fi 19 | FILESYSTEM_CONFIG=$PORT_ROOT/miui/metadata/filesystem_config.txt 20 | if [ "$USE_ANDROID_OUT" == "true" ];then 21 | FILESYSTEM_CONFIG=$(find $ANDROID_OUT/obj/PACKAGING/target_files_intermediates/ -name filesystem_config.txt) 22 | fi 23 | 24 | # copy the whole target_files_template dir 25 | function copy_target_files_template { 26 | echo "Copy target file template into current working directory" 27 | rm -rf $TARGET_FILES_DIR 28 | mkdir -p $TARGET_FILES_DIR 29 | cp -r $TARGET_FILES_TEMPLATE_DIR/* $TARGET_FILES_DIR 30 | } 31 | 32 | function copy_bootimage { 33 | echo "Copy bootimage" 34 | for file in boot.img zImage */boot.img */zImage 35 | do 36 | if [ -f $ZIP_DIR/$file ] 37 | then 38 | cp $ZIP_DIR/$file $TARGET_FILES_DIR/BOOTABLE_IMAGES/ 39 | return 40 | fi 41 | done 42 | } 43 | 44 | function copy_system_dir { 45 | echo "Copy system dir" 46 | cp -rf $ZIP_DIR/system/* $TARGET_FILES_DIR/SYSTEM 47 | } 48 | 49 | function copy_data_dir { 50 | #The thirdpart apps have copyed in copy_target_files_template function, 51 | #here, just to decide whether delete them. 52 | if [ $INCLUDE_THIRDPART_APP = "true" ];then 53 | echo "Copy thirdpart apps" 54 | else 55 | rm -rf $TARGET_FILES_DIR/DATA/* 56 | fi 57 | echo "Copy miui preinstall apps" 58 | mkdir -p $TARGET_FILES_DIR/DATA/ 59 | cp -rf $ZIP_DIR/data/miui $TARGET_FILES_DIR/DATA/ 60 | if [ -f customize_data.sh ];then 61 | ./customize_data.sh $PRJ_DIR 62 | fi 63 | } 64 | 65 | function recover_link { 66 | cp -f $METADATA_DIR/linkinfo.txt $TARGET_FILES_DIR/SYSTEM 67 | python $TOOL_DIR/releasetools/recoverylink.py $TARGET_FILES_DIR 68 | rm $TARGET_FILES_DIR/SYSTEM/linkinfo.txt 69 | } 70 | 71 | function process_metadata { 72 | echo "Process metadata" 73 | cp -f $TARGET_FILES_TEMPLATE_DIR/META/filesystem_config.txt $TARGET_FILES_DIR/META 74 | python $TOOL_DIR/uniq_first.py $METADATA_DIR/filesystem_config.txt $TARGET_FILES_DIR/META/filesystem_config.txt 75 | python $TOOL_DIR/uniq_first.py $FILESYSTEM_CONFIG $TARGET_FILES_DIR/META/filesystem_config.txt 76 | cat $TARGET_FILES_DIR/META/filesystem_config.txt | sort > $TARGET_FILES_DIR/META/temp.txt 77 | mv $TARGET_FILES_DIR/META/temp.txt $TARGET_FILES_DIR/META/filesystem_config.txt 78 | 79 | cp -f $METADATA_DIR/recovery.fstab $TARGET_FILES_DIR/RECOVERY/RAMDISK/etc 80 | 81 | cp -rf $APKCERT $TARGET_FILES_DIR/META/apkcerts.txt 82 | python $TOOL_DIR/uniq_first.py $METADATA_DIR/apkcerts.txt $TARGET_FILES_DIR/META/apkcerts.txt 83 | python $TOOL_DIR/uniq_first.py $TARGET_FILES_TEMPLATE_DIR/META/apkcerts.txt $TARGET_FILES_DIR/META/apkcerts.txt 84 | cat $TARGET_FILES_DIR/META/apkcerts.txt | sort > $TARGET_FILES_DIR/META/temp.txt 85 | mv $TARGET_FILES_DIR/META/temp.txt $TARGET_FILES_DIR/META/apkcerts.txt 86 | recover_link 87 | } 88 | 89 | # compress the target_files dir into a zip file 90 | function zip_target_files { 91 | echo "Compress the target_files dir into zip file" 92 | echo $TARGET_FILES_DIR 93 | cd $TARGET_FILES_DIR 94 | echo "zip -q -r -y $TARGET_FILES_ZIP *" 95 | zip -q -r -y $TARGET_FILES_ZIP * 96 | cd - 97 | } 98 | 99 | function sign_target_files { 100 | echo "Sign target files" 101 | $SIGN_TARGET_FILES_APKS -d $CERTIFICATE_DIR $TARGET_FILES_ZIP temp.zip 102 | mv temp.zip $TARGET_FILES_ZIP 103 | } 104 | 105 | # build a new full ota package 106 | function build_ota_package { 107 | echo "Build full ota package: $OUT_DIR/$OUT_ZIP_FILE" 108 | $OTA_FROM_TARGET_FILES -n -k $CERTIFICATE_DIR/testkey $TARGET_FILES_ZIP $OUT_DIR/$OUT_ZIP_FILE 109 | } 110 | 111 | function adjust_replace_key_script { 112 | if [ "$CERTIFICATE_DIR" != "$PORT_ROOT/build/security" -a -f "$CERTIFICATE_DIR/platform.x509.pem" \ 113 | -a -f "$CERTIFICATE_DIR/shared.x509.pem" -a -f "$CERTIFICATE_DIR/media.x509.pem" -a -f "$CERTIFICATE_DIR/shared.x509.pem" ];then 114 | platform_cert=$(cat $CERTIFICATE_DIR/platform.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"') 115 | sed -i "s/@user_platform/$platform_cert/g" out/target_files/OTA/bin/replace_key 116 | shared_cert=$(cat $CERTIFICATE_DIR/shared.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"') 117 | sed -i "s/@user_shared/$shared_cert/g" out/target_files/OTA/bin/replace_key 118 | media_cert=$(cat $CERTIFICATE_DIR/media.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"') 119 | sed -i "s/@user_media/$media_cert/g" out/target_files/OTA/bin/replace_key 120 | testkey_cert=$(cat $CERTIFICATE_DIR/shared.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"') 121 | sed -i "s/@user_testkey/$testkey_cert/g" out/target_files/OTA/bin/replace_key 122 | else 123 | rm -rf out/target_files/OTA/bin/replace_key 124 | fi 125 | } 126 | 127 | if [ $# -eq 3 ];then 128 | OUT_ZIP_FILE=$3 129 | if [ "$2" == "-n" ];then 130 | NO_SIGN=true 131 | elif [ -n "$2" ];then 132 | CERTIFICATE_DIR=$2 133 | fi 134 | INCLUDE_THIRDPART_APP=$1 135 | elif [ $# -eq 2 ];then 136 | OUT_ZIP_FILE=$2 137 | INCLUDE_THIRDPART_APP=$1 138 | elif [ $# -eq 1 ];then 139 | INCLUDE_THIRDPART_APP=$1 140 | fi 141 | 142 | #Set certificate pass word 143 | if [ -f "$CERTIFICATE_DIR/passwd" ];then 144 | export ANDROID_PW_FILE=$CERTIFICATE_DIR/passwd 145 | fi 146 | 147 | copy_target_files_template 148 | adjust_replace_key_script 149 | copy_bootimage 150 | copy_system_dir 151 | copy_data_dir 152 | process_metadata 153 | if [ -f "customize_target_files.sh" ]; then 154 | ./customize_target_files.sh 155 | if [ $? -ne 0 ];then 156 | exit 1 157 | fi 158 | fi 159 | zip_target_files 160 | if [ -n "$OUT_ZIP_FILE" ];then 161 | if [ "$NO_SIGN" == "false" ];then 162 | sign_target_files 163 | fi 164 | build_ota_package 165 | fi 166 | -------------------------------------------------------------------------------- /change_rom.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # $1: the old smali code $2: the new smali code $3: the destination smali code 4 | 5 | if [ $# -ne 5 ];then 6 | echo "Usage: change_rom.sh APP|JAR APP_NAME SUFFIX old_rom.zip new_rom.zip" 7 | exit 8 | fi 9 | 10 | # todo run me under product dir, such as i9100 11 | WS_DIR=`pwd` 12 | APKTOOL=$PORT_ROOT/tools/apktool 13 | 14 | # such as app/Phone (no .apk here) 15 | APPFRM=$1 16 | appname=$4 17 | suffix=$5 18 | app=$APPFRM/$appname.$suffix 19 | 20 | temp_dir=$WS_DIR/temp 21 | old_smali_dir=$WS_DIR/temp_old 22 | dst_smali_dir=$WS_DIR/temp_dst 23 | new_smali_dir=$WS_DIR 24 | 25 | echo ">>> Extract $app from ROM_ZIP file..." 26 | unzip $2 system/$app -d $old_smali_dir 27 | $APKTOOL d $old_smali_dir/system/$app $old_smali_dir/$appname 28 | unzip $3 system/$app -d $dst_smali_dir 29 | $APKTOOL d $dst_smali_dir/system/$app $dst_smali_dir/$appname 30 | echo "<<< Done!" 31 | 32 | temp_old_smali_dir=$temp_dir/old_smali 33 | temp_new_smali_dir=$temp_dir/new_smali 34 | temp_dst_smali_orig_dir=$temp_dir/dst_smali_orig 35 | temp_dst_smali_patched_dir=$temp_dir/dst_smali_patched 36 | reject_dir=$temp_dir/reject 37 | 38 | rm -rf $temp_dir 39 | 40 | echo ">>> create temp directory to store the old, new source and destination smali code with .line removed" 41 | mkdir -p $temp_old_smali_dir 42 | mkdir -p $temp_new_smali_dir 43 | mkdir -p $temp_dst_smali_orig_dir 44 | mkdir -p $temp_dst_smali_patched_dir 45 | mkdir -p $reject_dir 46 | 47 | cp -r $old_smali_dir/$appname $temp_old_smali_dir 48 | cp -r $dst_smali_dir/$appname $temp_dst_smali_orig_dir 49 | if [ "$suffix" = "jar" ];then 50 | cp -r $new_smali_dir/$appname.jar.out $temp_new_smali_dir/$appname 51 | else 52 | cp -r $new_smali_dir/$appname $temp_new_smali_dir 53 | fi 54 | 55 | $PORT_ROOT/tools/rmline.sh $temp_dir 56 | 57 | function apply_miui_patch() { 58 | old_code_noline=$temp_old_smali_dir/$1 59 | new_code_noline=$temp_new_smali_dir/$1 60 | dst_code_noline=$temp_dst_smali_orig_dir/$1 61 | dst_code=$dst_smali_dir/$1 62 | dst_code_orig=$dst_code.orig 63 | 64 | echo ">>> compute the difference between $old_code_noline and $new_code_noline" 65 | cd $old_code_noline 66 | for file in `find ./ -name "*.[sx]*"` 67 | do 68 | if [ -f $new_code_noline/$file ] 69 | then 70 | diff $file $new_code_noline/$file > /dev/null || { 71 | diff -B -c $file $new_code_noline/$file > $file.diff 72 | } 73 | else 74 | echo "$file does not exist at $new_code_noline" 75 | fi 76 | done 77 | 78 | cd $dst_smali_dir 79 | mv $dst_code $dst_code_orig 80 | cp -r $dst_code_noline $dst_code 81 | 82 | echo ">>> apply the patch into the $dst_code" 83 | cd $old_code_noline 84 | for file in `find ./ -name "*.diff"` 85 | do 86 | mkdir -p $reject_dir/$1/`dirname $file` 87 | patch $dst_code/${file%.diff} -r $reject_dir/$1/${file%.diff}.rej < $file 88 | done 89 | 90 | cp -r $dst_code $temp_dst_smali_patched_dir 91 | 92 | cd $dst_code_noline 93 | for file in `find ./ -name "*.smali"` 94 | do 95 | rm -f $file.diff 96 | diff -B -c $file $dst_code_orig/$file > $file.diff 97 | patch -f $dst_code/$file -r /dev/null < $file.diff >/dev/null 2>&1 98 | rm -f $file.diff 99 | done 100 | 101 | find $dst_code -name "*.smali.orig" -exec rm {} \; 102 | find $temp_dst_smali_patched_dir -name "*.smali.orig" -exec rm {} \; 103 | rm -rf $dst_code_orig 104 | } 105 | 106 | apply_miui_patch $appname 107 | 108 | echo ">>> copy out the result smali files and clean the workspace" 109 | mv $new_smali_dir/$appname $new_smali_dir/$appname-old 110 | mv $dst_smali_dir/$appname $new_smali_dir/$appname 111 | rm -rf $old_smali_dir 112 | rm -rf $dst_smali_dir 113 | 114 | echo "<<< patch miui into target $app is done." 115 | echo "Please look at $reject_dir to resolve any conflicts!" 116 | tree -f $reject_dir 117 | -------------------------------------------------------------------------------- /darwin-x86/aapt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/aapt -------------------------------------------------------------------------------- /darwin-x86/bsdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/bsdiff -------------------------------------------------------------------------------- /darwin-x86/imgdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/imgdiff -------------------------------------------------------------------------------- /darwin-x86/lib64/libcutils.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/lib64/libcutils.dylib -------------------------------------------------------------------------------- /darwin-x86/lib64/liblog.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/lib64/liblog.dylib -------------------------------------------------------------------------------- /darwin-x86/mkbootfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/mkbootfs -------------------------------------------------------------------------------- /darwin-x86/mkbootimg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/mkbootimg -------------------------------------------------------------------------------- /darwin-x86/unpackbootimg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/unpackbootimg -------------------------------------------------------------------------------- /darwin-x86/zipalign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/darwin-x86/zipalign -------------------------------------------------------------------------------- /deoat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2016, Miui Patchrom 4 | # 5 | 6 | TARGET_DIR=$1 7 | 8 | function removeDuplicateFiles() { 9 | local bootOat64Path=$(find $TARGET_DIR -name "boot.oat" | grep "64\/") 10 | if [ -n $bootOat64Path ];then 11 | rm -rf ${bootOat64Path/64\///} 12 | rm -rf ${bootOat64Path/64\/boot.oat//boot.art} 13 | fi 14 | local odex 15 | for odex in $(find $TARGET_DIR -name "*.odex" | grep "64\/") 16 | do 17 | echo "rm -rf ${odex/64\///}" 18 | rm -rf ${odex/64\///} 19 | done 20 | } 21 | 22 | function zipDex() { 23 | local zipDir=$1 24 | local dexPath=$2 25 | local suffix=$3 26 | local dexName=$(basename $dexPath .dex) 27 | local zipName=${dexName%%-classes*} 28 | if [ $dexName = $zipName ];then 29 | local zipDexName=classes.dex 30 | else 31 | local zipDexName=classes${dexName##*-classes}.dex 32 | fi 33 | mv $dexPath $zipDexName 34 | if [ -f $zipDir/$zipName.$suffix ];then 35 | zip -m $zipDir/$zipName.$suffix $zipDexName > /dev/null 36 | fi 37 | } 38 | 39 | function decodeBootOat() { 40 | BOOTOAT_PATH=$(find $TARGET_DIR -name "boot.oat") 41 | if [ -z $BOOTOAT_PATH ];then 42 | return 43 | fi 44 | BOOTOAT_DIR=$(dirname $BOOTOAT_PATH) 45 | echo "Decoding $BOOTOAT_PATH" 46 | oat2dex boot $BOOTOAT_PATH > /dev/null 47 | local bootDex 48 | for bootDex in $(find $BOOTOAT_DIR/dex -name "*.dex") 49 | do 50 | zipDex $(dirname $BOOTOAT_DIR) $bootDex jar 51 | done 52 | } 53 | 54 | function decodeOdex() { 55 | local suffix=$1 56 | local zipPath 57 | for zipPath in $(find $TARGET_DIR -name "*.$suffix") 58 | do 59 | local zipDir=$(dirname $zipPath) 60 | local zipName=$(basename $zipPath) 61 | local odexPath=$(find $zipDir -name ${zipName/.$suffix/.odex}) 62 | if [ -z $odexPath ];then 63 | continue 64 | fi 65 | echo "Decoding $odexPath" 66 | local bootClassPath=$BOOTOAT_DIR/odex 67 | if [ "$suffix" = "apk" ];then 68 | bootClassPath=$(dirname $BOOTOAT_DIR) 69 | fi 70 | local ret=$(oat2dex -o $zipDir $odexPath $bootClassPath) 71 | if [ -n "$(echo $ret | grep -i "failed")" -a -f $PORT_ROOT/tools/oat2dex-0.86.jar ];then 72 | echo "Decoding $odexPath failed, try to use old version oat2dex" 73 | java -jar $PORT_ROOT/tools/oat2dex-0.86.jar -o $zipDir $odexPath $bootClassPath > /dev/null 74 | fi 75 | rm -rf $odexPath 76 | local dexPath 77 | for dexPath in $(find $zipDir -maxdepth 1 -name "*.dex") 78 | do 79 | zipDex $zipDir $dexPath $suffix 80 | done 81 | done 82 | } 83 | 84 | removeDuplicateFiles 85 | decodeBootOat 86 | decodeOdex jar 87 | decodeOdex apk 88 | rm -rf $BOOTOAT_DIR/boot.oat $BOOTOAT_DIR/boot.art $BOOTOAT_DIR/odex $BOOTOAT_DIR/dex 89 | -------------------------------------------------------------------------------- /deodex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TOOL_PATH=$PORT_ROOT/tools 4 | SMALI=$TOOL_PATH/smali 5 | BAKSMALI=$TOOL_PATH/baksmali 6 | 7 | function deodex_one_file() { 8 | if [ "$1" = '-a' ] 9 | then 10 | apilevel=$2 11 | classpath=$3 12 | file=$4 13 | tofile=${file/odex/$5} 14 | echo "processing $tofile" 15 | $BAKSMALI -a $apilevel -c $classpath -d framework -x $file || exit -2 16 | else 17 | classpath=$1 18 | file=$2 19 | tofile=${file/odex/$3} 20 | echo "processing $tofile" 21 | $BAKSMALI -c $classpath -d framework -x $file || exit -2 22 | fi 23 | $SMALI out -o classes.dex || exit -2 24 | jar uf $tofile classes.dex 25 | rm classes.dex 26 | rm -rf out 27 | rm $file 28 | zipalign 4 $tofile $tofile.aligned 29 | mv $tofile.aligned $tofile 30 | } 31 | 32 | #usage 33 | if [ $1 = '--help' ] 34 | then 35 | echo "usage: ./deodex.sh [-a APILevel] absolute_path_to_ota_zip_file" 36 | echo " -a specify APILevel, default Level is 15" 37 | exit 0 38 | fi 39 | 40 | if [ ! -x $BAKSMALI -o ! -x $SMALI ] 41 | then 42 | echo "Error: Can not find baksmali/smali" 43 | exit -1 44 | fi 45 | 46 | if [ $1 = '-a' ] 47 | then 48 | apilevel=$2 49 | stockzip=$3 50 | else 51 | stockzip=$1 52 | fi 53 | 54 | temppath=`echo $PWD` 55 | tempdir=`mktemp -p $temppath -d tempdir.XXX` 56 | echo "temp dir: $tempdir" 57 | echo "unzip $stockzip to $tempdir" 58 | unzip -q $stockzip -d $tempdir 59 | 60 | if [ -d $tempdir/system ] 61 | then 62 | cd $tempdir/system 63 | elif [ -d $tempdir/SYSTEM ] 64 | then 65 | cd $tempdir/SYSTEM 66 | else 67 | echo "can't find system or SYSTEM dir in $tempdir" 68 | exit -1 69 | fi 70 | 71 | ls framework/core.odex > /dev/null 72 | if [ $? -eq 0 ] 73 | then 74 | classpath="core.jar:ext.jar:framework.jar:android.policy.jar:services.jar" 75 | if [ $1 = '-a' ] 76 | then 77 | deodex_one_file -a $apilevel $classpath framework/core.odex jar 78 | else 79 | deodex_one_file $classpath framework/core.odex jar 80 | fi 81 | fi 82 | 83 | for f in framework/*.jar 84 | do 85 | classpath=$classpath:$f 86 | done 87 | 88 | echo "classpath=$classpath" 89 | 90 | ls framework/*.odex > /dev/null 91 | if [ $? -eq 0 ] 92 | then 93 | for file in framework/*.odex 94 | do 95 | if [ $1 = '-a' ] 96 | then 97 | deodex_one_file -a $apilevel $classpath $file jar 98 | else 99 | deodex_one_file $classpath $file jar 100 | fi 101 | done 102 | fi 103 | 104 | ls app/*.odex > /dev/null 105 | if [ $? -eq 0 ] 106 | then 107 | for file in app/*.odex 108 | do 109 | if [ $1 = '-a' ] 110 | then 111 | deodex_one_file -a $apilevel $classpath $file apk 112 | else 113 | deodex_one_file $classpath $file apk 114 | fi 115 | done 116 | fi 117 | 118 | cd $tempdir 119 | echo "zip tmp_target_files" 120 | zip -q -r -y "tmp_target_files" * 121 | echo "replaces $stockzip" 122 | cp -f "tmp_target_files.zip" $stockzip 123 | echo "remove $tempdir" 124 | rm -rf $tempdir 125 | echo "deodex done. deodex zip: $stockzip" 126 | -------------------------------------------------------------------------------- /diffsmali.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # NOTE: the options for diff should be after the two filenames 4 | RM_LINE=$PORT_ROOT/tools/rmline.sh 5 | 6 | $RM_LINE $1 7 | $RM_LINE $2 8 | # -B -u 9 | diff $* 10 | $RM_LINE -r $1 11 | $RM_LINE -r $2 12 | -------------------------------------------------------------------------------- /fix_9patch_png.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Fix Grayscale PNG conversion increase brightness bug 4 | # Bug discription 5 | # APKTOOL issue id: 326 6 | # JDK bug uri: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5051418 7 | # Root cause 8 | # 1.when apktool decode gray adn gray-alpha 9Patch png, 9 | # it will use jdk drawImage() method, and the method 10 | # has a bug which increase brightness. 11 | # 2.the bug is only exist 9Patch png, other png without 12 | # the problem, as apktool won't decode it. 13 | # Fix method 14 | # 1.unzip original and target apk, not use apktool. 15 | # 2.copy 9Patch pngs from original apk to target apk. 16 | # 3.re-zip taget apk. 17 | # $1: the original apk name 18 | # $2: the original apk dir 19 | # $3: the out dir 20 | # $4: filter dir 21 | # $5: filter dir 22 | 23 | APK_FILE=$1.apk 24 | ORIGINAL_APK=$2/$APK_FILE 25 | REPLACE_APK=$3/$APK_FILE 26 | 27 | TMP_ORIGINAL_FILE=$3/$1-original.apk 28 | TMP_TARGET_FILE=$3/$1-target.apk 29 | 30 | TMP_ORIGINAL_DIR=$3/$1-original 31 | TMP_TARGET_DIR=$3/$1-target 32 | 33 | HAS_FILTER1=false 34 | HAS_FILTER2=false 35 | if [ $# -gt 3 ];then 36 | HAS_FILTER1=true 37 | fi 38 | if [ $# -gt 4 ];then 39 | HAS_FILTER2=true 40 | fi 41 | 42 | cp -r $ORIGINAL_APK $TMP_ORIGINAL_FILE 43 | mv $REPLACE_APK $TMP_TARGET_FILE 44 | unzip -o $TMP_ORIGINAL_FILE -d $TMP_ORIGINAL_DIR > /dev/null 45 | unzip -o $TMP_TARGET_FILE -d $TMP_TARGET_DIR > /dev/null 46 | for file in `find $TMP_ORIGINAL_DIR -name *.9.png`; do 47 | targetfile=`echo $file | sed -e "s/-original/-target/"` 48 | overlay=`echo $file | sed -e "s/$3\/$1-original\/res\///"` 49 | if [ "$HAS_FILTER1" == "true" -a -f $4/$overlay ];then 50 | continue 51 | elif [ "$HAS_FILTER2" == "true" -a -f $5/$overlay ];then 52 | continue 53 | fi 54 | cp $file $targetfile 55 | done 56 | cd $TMP_TARGET_DIR 57 | #only store all files, not compress files 58 | #as raw resource can't be compressed. 59 | zip -r0 ../$APK_FILE ./ > /dev/null 60 | -------------------------------------------------------------------------------- /fix_plurals.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | resdir=$1 4 | for file in `find $resdir -name "plurals.xml"` 5 | do 6 | $PORT_ROOT/tools/multi_format_subst.pl $file > temp.xml 7 | cp temp.xml $file 8 | done 9 | rm temp.xml 10 | -------------------------------------------------------------------------------- /gen_desklayout.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | my ($sedfile, $outdir) = @ARGV; 6 | 7 | my %sed; 8 | 9 | #double check if the file exists 10 | if ( not -f $sedfile ) { 11 | print "sedfile does not exist\n"; 12 | exit; 13 | } 14 | 15 | open(SED, $sedfile); 16 | while () { 17 | if (/^\s*([^\s]+)\/([^\s]+)\s*=\s*([^\s]+)\/([^\s]+)\s*$/) { 18 | $sed{$1} = $3; 19 | $sed{$2} = $4; 20 | } 21 | } 22 | close(SED); 23 | 24 | my @deskfiles=<$outdir/default_workspace*.xml>; 25 | 26 | my $sedstr = "sed "; 27 | foreach my $key (keys %sed) { 28 | #print stderr "$key => $sed{$key} \n"; 29 | $sedstr .= "-e s/\\\"$key\\\"/\\\"$sed{$key}\\\"/g "; 30 | } 31 | 32 | foreach my $file (@deskfiles) { 33 | system("$sedstr $file > $file.new"); 34 | } 35 | -------------------------------------------------------------------------------- /gen_desktop_layout.sh: -------------------------------------------------------------------------------- 1 | #1) run command to get the following list, and remove the un-necessary lines => sqlite3 launcher.db "select * from favorites;" 2 | #2) run me to get test.xml and put content to the default.. file. 3 | line='1|com.miui.home:string/default_folder_title_tools||-100|3|2|3|1|1|2|-1||||||||1||0 4 | 3|音乐|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.player/.ui.MusicBrowserActivity;end|-100|3|2|2|1|1|0|-1|||com.miui.player|||||1||0 5 | 4|设置|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.settings/.Settings;end|-100|3|0|3|1|1|0|-1|||com.android.settings|||||1||0 6 | 5|文件管理|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.fileexplorer/.FileExplorerTabActivity;end|-100|3|1|3|1|1|0|-1|||com.android.fileexplorer|||||4||0 7 | 6|系统更新|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.updater/.MainActivity;end|1||||1|1|0|-1|||com.android.updater|||||1||0 8 | 7|时钟|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.deskclock/.DeskClock;end|1||||1|1|0|-1|||com.android.deskclock|||||1||0 9 | 8|备份|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.backup/.BackupActivity;end|1||||1|1|0|-1|||com.miui.backup|||||5||0 10 | 9|流量监控|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.monitor/.MainActivity;end|1||||1|1|0|-1|||com.android.monitor|||||1||0 11 | 10|主题风格|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.thememanager/.ThemeResourceTabActivity;end|-100|3|3|2|1|1|0|-1|||com.android.thememanager|||||5||0 12 | 11|电子市场|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.vending/.AssetBrowserActivity;end|-100|4|1|1|1|1|0|-1|||com.android.vending|||||2||0 13 | 12|Gmail|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.google.android.gm/.ConversationListActivityGmail;end|-100|4|2|1|1|1|0|-1|||com.google.android.gm|||||1||0 14 | 13|日历|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.calendar/.LaunchActivity;end|-100|4|0|2|1|1|0|-1|||com.android.calendar|||||1||0 15 | 14|GoogleTalk|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.google.android.talk/.SigningInActivity;end|-100|4|0|1|1|1|0|-1|||com.google.android.talk|||||2||0 16 | 15|拨号|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.contacts/.activities.TwelveKeyDialer;end|-101|0|0|0|1|1|0|-1|||com.android.contacts|||||7||0 17 | 16|联系人|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.contacts/.activities.PeopleActivity;end|-101|0|1|0|1|1|0|-1|||com.android.contacts|||||4||0 18 | 17|浏览器|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.browser/.BrowserActivity;end|-101||||1|1|0|-1|||com.android.browser|||||6||0 19 | 18|信息|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.mms/.ui.MmsTabActivity;end|-101|0|2|0|1|1|0|-1|||com.android.mms|||||5||0 20 | 19|搜索|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.google.android.googlequicksearchbox/.SearchActivity;end|-100|4|3|1|1|1|0|-1||0|com.google.android.googlequicksearchbox|||||1||0 21 | 20|录像|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.videoplayer/.activity.MainTab;end|-100|4|1|0|1|1|0|-1||0|com.sec.android.app.videoplayer|||||1||0 22 | 21|下载管理|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.providers.downloads.ui/.DownloadList;end|-100|4|3|3|1|1|0|-1||0|com.android.providers.downloads.ui|||||1||0 23 | 22|录音机|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.voicerecorder/.VoiceRecorderMainActivity;end|-100|4|3|0|1|1|0|-1||0|com.sec.android.app.voicerecorder|||||1||0 24 | 23|防打扰|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.antispam/.firewall.FirewallTab;end|-100|4|2|3|1|1|0|-1||0|com.miui.antispam|||||1||0 25 | 24|图库|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.cooliris.media/.Gallery;end|-100|3|1|2|1|1|0|-1||0|com.cooliris.media|||||1||0 26 | 25|计算机|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.calculator/.Calculator;end|-100|4|1|2|1|1|0|-1||0|com.sec.android.app.calculator|||||1||0 27 | 26|用户反馈|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.bugreport/.BugReportActivity;end|1|-1|-1|0|1|1|0|-1||0|com.miui.bugreport|||||1||0 28 | 27|时钟|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.clockpackage/.ClockPackage;end|-100|4|2|2|1|1|0|-1||0|com.sec.android.app.clockpackage|||||1||0 29 | 28|照相机|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.camera/.Camera;end|-100|3|0|2|1|1|0|-1||0|com.sec.android.app.camera|||||2||0 30 | 29|FM收音机|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.fm/.MainActivity;end|-100|4|2|0|1|1|0|-1||0|com.sec.android.app.fm|||||2||0 31 | 30|手电筒|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=net.cactii.flash2/.MainActivity;end|1|-1|-1|0|1|1|0|-1||0|net.cactii.flash2|||||1||0 32 | 31|Superuser|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.noshufou.android.su/.Su;end|1|-1|-1|0|1|1|0|-1||0|com.noshufou.android.su|||||1||0 33 | 32|录音机|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.soundrecorder/.SoundRecorder;end|-100|4|0|0|1|1|0|-1||0|com.android.soundrecorder|||||1||0 34 | 33|指南针|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.compass/.CompassActivity;end|-100|4|0|3|1|1|0|-1||0|com.miui.compass|||||1||0 35 | 34|任务管理器|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sec.android.app.controlpanel/.activity.JobManagerActivity;end|-100|4|1|3|1|1|0|-1||0|com.sec.android.app.controlpanel|||||1||0 36 | 35|便签|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.notes/.ui.NotesListActivity;end|-100|4|3|2|1|1|0|-1||0|com.miui.notes|||||1||0 37 | 36|应用超市|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.miui.supermarket/.MainTabActivity;end|-100|3|3|3|1|1|0|-1||0|com.miui.supermarket|||||2||0 38 | 37|CWM|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=eu.chainfire.cfroot.cwmmanager/.MainActivity;end|1|-1|-1|0|1|1|0|-1||0|eu.chainfire.cfroot.cwmmanager|||||2||0 39 | 38|搜索|#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.android.quicksearchbox/.SearchActivity;end|1|-1|-1|0|1|1|0|-1||0|com.android.quicksearchbox|||||1||0' 40 | 41 | for l in $line; do 42 | name=`echo $l | cut -f2 -d"|"` 43 | class=`echo $l | cut -f3 -d"|" | sed -e "s/.*component=//" -e "s/;end//" -e "s/\///g"` 44 | c=`echo $l | cut -f4 -d"|"` 45 | screen=`echo $l | cut -f5 -d"|"` 46 | let screen=$screen-2 47 | x=`echo $l | cut -f6 -d"|"` 48 | y=`echo $l | cut -f7 -d"|"` 49 | package=`echo $l | cut -f14 -d"|"` 50 | if [ -z "$screen" ]; then 51 | screen=-1000 52 | fi 53 | if [ "$screen" -lt 0 ]; then 54 | echo "" >> test.xml 55 | else 56 | echo "" >> test.xml 57 | fi 58 | done 59 | -------------------------------------------------------------------------------- /gen_res_conf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONF=$1 4 | APKDIR=$2 5 | SYSDIR=$3 6 | 7 | for line in `cat $CONF` 8 | do 9 | name=`echo $line | cut -d= -f1` 10 | value=`echo $line | cut -d= -f2` 11 | echo $line - [$name] [$value] 12 | 13 | if [ "$name" = "APK" ]; then 14 | apkfile=$value 15 | elif [ "$name" = "package" ]; then 16 | package=$value 17 | rm -f $SYSDIR/res_overlay_$package.txt 18 | echo "Generate conf file:$SYSDIR/res_overlay_$package.txt" 19 | else 20 | resv=`aapt d resources $APKDIR/$apkfile | sed -n -e "s/^.*spec resource 0x\(.*\) .*$name.*$/\1/p"` 21 | echo "$name=$resv" >> $SYSDIR/res_overlay_$package.txt 22 | echo " Add $name=$resv" 23 | fi 24 | done 25 | 26 | -------------------------------------------------------------------------------- /get_apk_cert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (C) 2016 The Miui Patchrom 4 | # 5 | 6 | import os 7 | import sys 8 | import re 9 | 10 | # Values for "certificate" in apkcerts that mean special things. 11 | SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL") 12 | PUBLIC_KEY_SUFFIX = ".x509.pem" 13 | PRIVATE_KEY_SUFFIX = ".pk8" 14 | 15 | 16 | def ReadApkCerts(apkcerts): 17 | """parse the apkcerts.txt file and return a {package: cert} dict.""" 18 | certmap = {} 19 | with open(apkcerts, 'r') as certs: 20 | for line in certs.readlines(): 21 | m = re.match(r'^name="(.*)"\s+certificate="(.*)"\s+' 22 | r'private_key="(.*)"$', line) 23 | if m: 24 | name, cert, privkey = m.groups() 25 | public_key_suffix_len = len(PUBLIC_KEY_SUFFIX) 26 | private_key_suffix_len = len(PRIVATE_KEY_SUFFIX) 27 | if cert in SPECIAL_CERT_STRINGS and not privkey: 28 | certmap[name] = cert 29 | elif (cert.endswith(PUBLIC_KEY_SUFFIX) and 30 | privkey.endswith(PRIVATE_KEY_SUFFIX) and 31 | cert[:-public_key_suffix_len] == privkey[:-private_key_suffix_len]): 32 | certmap[name] = cert[:-public_key_suffix_len] 33 | else: 34 | raise ValueError("failed to parse line from apkcerts.txt:\n" + line) 35 | return certmap 36 | 37 | if __name__ == '__main__': 38 | apkPath = sys.argv[1] 39 | apkCerts = sys.argv[2] 40 | certmap = ReadApkCerts(apkCerts) 41 | cert = os.path.basename(certmap[os.path.basename(apkPath)]) 42 | print cert 43 | -------------------------------------------------------------------------------- /get_filesystem_config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2016, Miui Patchrom 4 | # 5 | 6 | ACTION=$1 7 | LINE_TERMINATION=$'\r\n' 8 | OLD_IFS=$IFS 9 | IFS=$'\n' 10 | BUSYBOX="$2" 11 | if [ -n "$(adb shell id | grep "uid=0")" ];then 12 | root='true' 13 | elif [ -z "$(adb shell su -c "id" | grep "uid=0")" ];then 14 | echo "Please root your device, and try again." 15 | exit 1 16 | fi 17 | 18 | if [ -n $root ];then 19 | fileSystemInfo=$(adb shell ls -aRZ /system) 20 | else 21 | fileSystemInfo=$(adb shell su -c "ls -aRZ /system") 22 | fi 23 | 24 | if [ "$ACTION" = '--info' ];then 25 | for line in $fileSystemInfo 26 | do 27 | if [ $line == $LINE_TERMINATION -o ${line:0:1} == 'd' ];then 28 | continue 29 | fi 30 | # lrwxrwxrwx root root u:object_r:system_file:s0 chmod -> toybox 31 | # cut line before the string " ->" 32 | line=${line%% ->*} 33 | if [ $(echo $line | cut -d ':' -f2) == $LINE_TERMINATION ];then 34 | dir=$(echo $line | cut -d ':' -f1) 35 | path=$dir 36 | if [ -n $root ];then 37 | line=$(adb shell ls -dZ $path) 38 | else 39 | line=$(adb shell su -c "ls -dZ $path") 40 | fi 41 | else 42 | path=$dir/$(echo ${line##*:s0} | tr -d $LINE_TERMINATION | sed 's/^[ ]*//') 43 | fi 44 | selabel="u:${line##*u:}" 45 | selabel=${selabel%% *} 46 | if [ -n $root ];then 47 | uid=$(adb shell $BUSYBOX stat -c %u $path | tr -d $LINE_TERMINATION) 48 | gid=$(adb shell $BUSYBOX stat -c %g $path | tr -d $LINE_TERMINATION) 49 | perm=$(adb shell $BUSYBOX stat -c %a $path | tr -d $LINE_TERMINATION) 50 | else 51 | uid=$(adb shell su -c "$BUSYBOX stat -c %u $path" | tr -d $LINE_TERMINATION) 52 | gid=$(adb shell su -c "$BUSYBOX stat -c %g $path" | tr -d $LINE_TERMINATION) 53 | perm=$(adb shell su -c "$BUSYBOX stat -c %a $path" | tr -d $LINE_TERMINATION) 54 | fi 55 | #Remove blank in filename, it cause ota_from_target_files failed. 56 | path=$(echo $path | sed 's/ //g') 57 | echo "${path#\/} $uid $gid $perm selabel=$selabel capabilities=0x0" 58 | done 59 | elif [ "$ACTION" = '--link' ];then 60 | for line in $fileSystemInfo 61 | do 62 | if [ $line == $LINE_TERMINATION];then 63 | continue 64 | fi 65 | line=${line%% ->*} 66 | if [ $(echo $line | cut -d ':' -f2) == $LINE_TERMINATION ];then 67 | dir=$(echo $line | cut -d ':' -f1) 68 | path=$dir 69 | if [ -n $root ];then 70 | line=$(adb shell ls -dZ $path) 71 | else 72 | line=$(adb shell su -c "ls -dZ $path") 73 | fi 74 | fi 75 | 76 | if [ ${line:0:1} == 'l' ];then 77 | path=$dir/$(echo ${line##*:s0} | tr -d $LINE_TERMINATION | sed 's/^[ ]*//') 78 | if [ -n $root ];then 79 | link=$(adb shell $BUSYBOX readlink $path | tr -d $LINE_TERMINATION) 80 | else 81 | link=$(adb shell su -c "$BUSYBOX readlink $path" | tr -d $LINE_TERMINATION) 82 | fi 83 | echo "${path#\/}|$link" 84 | fi 85 | done 86 | fi 87 | -------------------------------------------------------------------------------- /git.apply: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # this is a git apply command wrapper 4 | 5 | RM_LINE=$PORT_ROOT/tools/rmline.sh 6 | 7 | bin_files=`grep "^ .*| *Bin[ 0-9]\+->[ 0-9]\+" $1 | sed -e "s/|.*$//" -e "s/ //g"` 8 | patch_files=`grep "^ .*\.smali.*|" $1 | sed -e "s/|.*$//" -e "s/ //g"` 9 | files= 10 | 11 | for f in $patch_files; do 12 | if [ -f "$f" ]; then 13 | files="$files $f" 14 | else 15 | dirfile=`find . -path "${f/.../*}"` 16 | #echo find file [$f]: $dirfile 17 | files="$files $dirfile" 18 | fi 19 | done 20 | 21 | for f in $files; do 22 | $RM_LINE $f 23 | done 24 | 25 | git apply --reject $1 26 | 27 | for f in $files; do 28 | $RM_LINE -r $f 29 | ls $f.rej >/dev/null 2>&1 || rm -f $f.orig 30 | done 31 | 32 | echo 33 | echo +++++++++++ 34 | echo + Summary + 35 | echo +++++++++++ 36 | rej_files=`find . -name "*.rej"` 37 | if [ -n "$rej_files" ]; then 38 | echo + Following patches are rejected and merge is required. 39 | echo $rej_files 40 | fi 41 | if [ -n "$bin_files" ]; then 42 | echo + Binary files need to be copied manully. 43 | echo $bin_files 44 | fi 45 | if [ -z "$ref_files$bin_files" ]; then 46 | echo + Apply patch successfully! 47 | fi 48 | -------------------------------------------------------------------------------- /git.patch: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # this is a git format-patch command wrapper 4 | 5 | git config --global diff.external $PORT_ROOT/tools/git_smali_diff 6 | 7 | git format-patch --ext-diff --stdout $* 8 | 9 | git config --global --remove-section diff 10 | 11 | -------------------------------------------------------------------------------- /git_smali_diff: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${1%.smali}" == "$1" ];then 4 | #echo "not smali file" 5 | [ $# -eq 7 ] && diff "$2" "$5" -B -u -La/$1 -Lb/$1 6 | exit 0 7 | else 8 | #echo "smali files" 9 | [ $# -eq 7 ] && $PORT_ROOT/tools/diffsmali.sh "$2" "$5" -B -u -La/$1 -Lb/$1 10 | exit 0 11 | fi 12 | -------------------------------------------------------------------------------- /git_upload_no_verify.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (C) 2008 The Android Open Source Project 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import copy 17 | import re 18 | import sys 19 | 20 | from command import InteractiveCommand 21 | from editor import Editor 22 | from error import HookError, UploadError 23 | from project import RepoHook 24 | 25 | UNUSUAL_COMMIT_THRESHOLD = 5 26 | 27 | def _ConfirmManyUploads(multiple_branches=False): 28 | if multiple_branches: 29 | print "ATTENTION: One or more branches has an unusually high number of commits." 30 | else: 31 | print "ATTENTION: You are uploading an unusually high number of commits." 32 | print "YOU PROBABLY DO NOT MEAN TO DO THIS. (Did you rebase across branches?)" 33 | answer = raw_input("If you are sure you intend to do this, type 'yes': ").strip() 34 | return answer == "yes" 35 | 36 | def _die(fmt, *args): 37 | msg = fmt % args 38 | print >>sys.stderr, 'error: %s' % msg 39 | sys.exit(1) 40 | 41 | def _SplitEmails(values): 42 | result = [] 43 | for str in values: 44 | result.extend([s.strip() for s in str.split(',')]) 45 | return result 46 | 47 | class Upload(InteractiveCommand): 48 | common = True 49 | helpSummary = "Upload changes for code review" 50 | helpUsage=""" 51 | %prog [--re --cc] []... 52 | """ 53 | helpDescription = """ 54 | The '%prog' command is used to send changes to the Gerrit Code 55 | Review system. It searches for topic branches in local projects 56 | that have not yet been published for review. If multiple topic 57 | branches are found, '%prog' opens an editor to allow the user to 58 | select which branches to upload. 59 | 60 | '%prog' searches for uploadable changes in all projects listed at 61 | the command line. Projects can be specified either by name, or by 62 | a relative or absolute path to the project's local directory. If no 63 | projects are specified, '%prog' will search for uploadable changes 64 | in all projects listed in the manifest. 65 | 66 | If the --reviewers or --cc options are passed, those emails are 67 | added to the respective list of users, and emails are sent to any 68 | new users. Users passed as --reviewers must already be registered 69 | with the code review system, or the upload will fail. 70 | 71 | Configuration 72 | ------------- 73 | 74 | review.URL.autoupload: 75 | 76 | To disable the "Upload ... (y/N)?" prompt, you can set a per-project 77 | or global Git configuration option. If review.URL.autoupload is set 78 | to "true" then repo will assume you always answer "y" at the prompt, 79 | and will not prompt you further. If it is set to "false" then repo 80 | will assume you always answer "n", and will abort. 81 | 82 | review.URL.autocopy: 83 | 84 | To automatically copy a user or mailing list to all uploaded reviews, 85 | you can set a per-project or global Git option to do so. Specifically, 86 | review.URL.autocopy can be set to a comma separated list of reviewers 87 | who you always want copied on all uploads with a non-empty --re 88 | argument. 89 | 90 | review.URL.username: 91 | 92 | Override the username used to connect to Gerrit Code Review. 93 | By default the local part of the email address is used. 94 | 95 | The URL must match the review URL listed in the manifest XML file, 96 | or in the .git/config within the project. For example: 97 | 98 | [remote "origin"] 99 | url = git://git.example.com/project.git 100 | review = http://review.example.com/ 101 | 102 | [review "http://review.example.com/"] 103 | autoupload = true 104 | autocopy = johndoe@company.com,my-team-alias@company.com 105 | 106 | review.URL.uploadtopic: 107 | 108 | To add a topic branch whenever uploading a commit, you can set a 109 | per-project or global Git option to do so. If review.URL.uploadtopic 110 | is set to "true" then repo will assume you always want the equivalent 111 | of the -t option to the repo command. If unset or set to "false" then 112 | repo will make use of only the command line option. 113 | 114 | References 115 | ---------- 116 | 117 | Gerrit Code Review: http://code.google.com/p/gerrit/ 118 | 119 | """ 120 | 121 | def _Options(self, p): 122 | p.add_option('-t', 123 | dest='auto_topic', action='store_true', 124 | help='Send local branch name to Gerrit Code Review') 125 | p.add_option('--re', '--reviewers', 126 | type='string', action='append', dest='reviewers', 127 | help='Request reviews from these people.') 128 | p.add_option('--cc', 129 | type='string', action='append', dest='cc', 130 | help='Also send email to these email addresses.') 131 | p.add_option('--br', 132 | type='string', action='store', dest='branch', 133 | help='Branch to upload.') 134 | p.add_option('--cbr', '--current-branch', 135 | dest='current_branch', action='store_true', 136 | help='Upload current git branch.') 137 | 138 | # Options relating to upload hook. Note that verify and no-verify are NOT 139 | # opposites of each other, which is why they store to different locations. 140 | # We are using them to match 'git commit' syntax. 141 | # 142 | # Combinations: 143 | # - no-verify=False, verify=False (DEFAULT): 144 | # If stdout is a tty, can prompt about running upload hooks if needed. 145 | # If user denies running hooks, the upload is cancelled. If stdout is 146 | # not a tty and we would need to prompt about upload hooks, upload is 147 | # cancelled. 148 | # - no-verify=False, verify=True: 149 | # Always run upload hooks with no prompt. 150 | # - no-verify=True, verify=False: 151 | # Never run upload hooks, but upload anyway (AKA bypass hooks). 152 | # - no-verify=True, verify=True: 153 | # Invalid 154 | p.add_option('--no-verify', 155 | dest='bypass_hooks', action='store_true', 156 | help='Do not run the upload hook.') 157 | p.add_option('--verify', 158 | dest='allow_all_hooks', action='store_true', 159 | help='Run the upload hook without prompting.') 160 | 161 | def _SingleBranch(self, opt, branch, people): 162 | project = branch.project 163 | name = branch.name 164 | remote = project.GetBranch(name).remote 165 | 166 | key = 'review.%s.autoupload' % remote.review 167 | answer = project.config.GetBoolean(key) 168 | 169 | if answer is False: 170 | _die("upload blocked by %s = false" % key) 171 | 172 | if answer is None: 173 | date = branch.date 174 | list = branch.commits 175 | 176 | print 'Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr) 177 | print ' branch %s (%2d commit%s, %s):' % ( 178 | name, 179 | len(list), 180 | len(list) != 1 and 's' or '', 181 | date) 182 | for commit in list: 183 | print ' %s' % commit 184 | 185 | sys.stdout.write('to %s (y/N)? ' % remote.review) 186 | #answer = sys.stdin.readline().strip() 187 | #answer = answer in ('y', 'Y', 'yes', '1', 'true', 't') 188 | 189 | #if True: 190 | #if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: 191 | #answer = _ConfirmManyUploads() 192 | 193 | if True: 194 | self._UploadAndReport(opt, [branch], people) 195 | else: 196 | _die("upload aborted by user") 197 | 198 | def _MultipleBranches(self, opt, pending, people): 199 | projects = {} 200 | branches = {} 201 | 202 | script = [] 203 | script.append('# Uncomment the branches to upload:') 204 | for project, avail in pending: 205 | script.append('#') 206 | script.append('# project %s/:' % project.relpath) 207 | 208 | b = {} 209 | for branch in avail: 210 | name = branch.name 211 | date = branch.date 212 | list = branch.commits 213 | 214 | if b: 215 | script.append('#') 216 | script.append('# branch %s (%2d commit%s, %s) to remote branch %s:' % ( 217 | name, 218 | len(list), 219 | len(list) != 1 and 's' or '', 220 | date, 221 | project.revisionExpr)) 222 | for commit in list: 223 | script.append('# %s' % commit) 224 | b[name] = branch 225 | 226 | projects[project.relpath] = project 227 | branches[project.name] = b 228 | script.append('') 229 | 230 | script = [ x.encode('utf-8') 231 | if issubclass(type(x), unicode) 232 | else x 233 | for x in script ] 234 | 235 | script = Editor.EditString("\n".join(script)).split("\n") 236 | 237 | project_re = re.compile(r'^#?\s*project\s*([^\s]+)/:$') 238 | branch_re = re.compile(r'^\s*branch\s*([^\s(]+)\s*\(.*') 239 | 240 | project = None 241 | todo = [] 242 | 243 | for line in script: 244 | m = project_re.match(line) 245 | if m: 246 | name = m.group(1) 247 | project = projects.get(name) 248 | if not project: 249 | _die('project %s not available for upload', name) 250 | continue 251 | 252 | m = branch_re.match(line) 253 | if m: 254 | name = m.group(1) 255 | if not project: 256 | _die('project for branch %s not in script', name) 257 | branch = branches[project.name].get(name) 258 | if not branch: 259 | _die('branch %s not in %s', name, project.relpath) 260 | todo.append(branch) 261 | if not todo: 262 | _die("nothing uncommented for upload") 263 | 264 | many_commits = False 265 | for branch in todo: 266 | if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: 267 | many_commits = True 268 | break 269 | if many_commits: 270 | if not _ConfirmManyUploads(multiple_branches=True): 271 | _die("upload aborted by user") 272 | 273 | self._UploadAndReport(opt, todo, people) 274 | 275 | def _AppendAutoCcList(self, branch, people): 276 | """ 277 | Appends the list of users in the CC list in the git project's config if a 278 | non-empty reviewer list was found. 279 | """ 280 | 281 | name = branch.name 282 | project = branch.project 283 | key = 'review.%s.autocopy' % project.GetBranch(name).remote.review 284 | raw_list = project.config.GetString(key) 285 | if not raw_list is None and len(people[0]) > 0: 286 | people[1].extend([entry.strip() for entry in raw_list.split(',')]) 287 | 288 | def _FindGerritChange(self, branch): 289 | last_pub = branch.project.WasPublished(branch.name) 290 | if last_pub is None: 291 | return "" 292 | 293 | refs = branch.GetPublishedRefs() 294 | try: 295 | # refs/changes/XYZ/N --> XYZ 296 | return refs.get(last_pub).split('/')[-2] 297 | except: 298 | return "" 299 | 300 | def _UploadAndReport(self, opt, todo, original_people): 301 | have_errors = False 302 | for branch in todo: 303 | try: 304 | people = copy.deepcopy(original_people) 305 | self._AppendAutoCcList(branch, people) 306 | 307 | # Check if there are local changes that may have been forgotten 308 | if branch.project.HasChanges(): 309 | key = 'review.%s.autoupload' % branch.project.remote.review 310 | answer = branch.project.config.GetBoolean(key) 311 | 312 | # if they want to auto upload, let's not ask because it could be automated 313 | if answer is None: 314 | sys.stdout.write('Uncommitted changes in ' + branch.project.name + ' (did you forget to amend?). Continue uploading? (y/N) ') 315 | a = sys.stdin.readline().strip().lower() 316 | if a not in ('y', 'yes', 't', 'true', 'on'): 317 | print >>sys.stderr, "skipping upload" 318 | branch.uploaded = False 319 | branch.error = 'User aborted' 320 | continue 321 | 322 | # Check if topic branches should be sent to the server during upload 323 | if opt.auto_topic is not True: 324 | key = 'review.%s.uploadtopic' % branch.project.remote.review 325 | opt.auto_topic = branch.project.config.GetBoolean(key) 326 | 327 | branch.UploadForReview(people, auto_topic=opt.auto_topic) 328 | branch.uploaded = True 329 | except UploadError, e: 330 | branch.error = e 331 | branch.uploaded = False 332 | have_errors = True 333 | 334 | print >>sys.stderr, '' 335 | print >>sys.stderr, '----------------------------------------------------------------------' 336 | 337 | if have_errors: 338 | for branch in todo: 339 | if not branch.uploaded: 340 | if len(str(branch.error)) <= 30: 341 | fmt = ' (%s)' 342 | else: 343 | fmt = '\n (%s)' 344 | print >>sys.stderr, ('[FAILED] %-15s %-15s' + fmt) % ( 345 | branch.project.relpath + '/', \ 346 | branch.name, \ 347 | str(branch.error)) 348 | print >>sys.stderr, '' 349 | 350 | for branch in todo: 351 | if branch.uploaded: 352 | print >>sys.stderr, '[OK ] %-15s %s' % ( 353 | branch.project.relpath + '/', 354 | branch.name) 355 | 356 | if have_errors: 357 | sys.exit(1) 358 | 359 | def Execute(self, opt, args): 360 | project_list = self.GetProjects(args) 361 | pending = [] 362 | reviewers = [] 363 | cc = [] 364 | branch = None 365 | 366 | if opt.branch: 367 | branch = opt.branch 368 | 369 | for project in project_list: 370 | if opt.current_branch: 371 | cbr = project.CurrentBranch 372 | avail = [project.GetUploadableBranch(cbr)] if cbr else None 373 | else: 374 | avail = project.GetUploadableBranches(branch) 375 | if avail: 376 | pending.append((project, avail)) 377 | 378 | if pending and (not opt.bypass_hooks): 379 | hook = RepoHook('pre-upload', self.manifest.repo_hooks_project, 380 | self.manifest.topdir, abort_if_user_denies=True) 381 | pending_proj_names = [project.name for (project, avail) in pending] 382 | try: 383 | hook.Run(opt.allow_all_hooks, project_list=pending_proj_names) 384 | except HookError, e: 385 | print >>sys.stderr, "ERROR: %s" % str(e) 386 | return 387 | 388 | if opt.reviewers: 389 | reviewers = _SplitEmails(opt.reviewers) 390 | if opt.cc: 391 | cc = _SplitEmails(opt.cc) 392 | people = (reviewers,cc) 393 | 394 | if not pending: 395 | print >>sys.stdout, "no branches ready for upload" 396 | elif len(pending) == 1 and len(pending[0][1]) == 1: 397 | self._SingleBranch(opt, pending[0][1][0], people) 398 | else: 399 | self._MultipleBranches(opt, pending, people) 400 | -------------------------------------------------------------------------------- /hex_replace.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env pyhon 2 | 3 | from sys import argv 4 | import struct 5 | 6 | def usage(): 7 | print "Usage: %s orignal target file" % argv[0] 8 | 9 | 10 | def do_replace(inFile, outFile, oldHex, newHex): 11 | inFp = open(inFile, 'rb') 12 | outFp = open(outFile, 'wb') 13 | oldstr = struct.pack('LH', 4611950241719001088, 18288) 14 | newstr = struct.pack('LH', 5147649559655096320, 18112) 15 | while 1: 16 | s = inFp.read(10) 17 | if s: 18 | print struct.unpack('LH', s) 19 | if s == oldstr: 20 | print "replace" 21 | outFp.write(newstr) 22 | else: 23 | outFp.write(s) 24 | else: 25 | break 26 | 27 | inFp.close() 28 | outFp.close() 29 | 30 | 31 | 32 | if __name__ == "__main__": 33 | #if len(argv) < 4: 34 | # exit(usage()) 35 | 36 | do_replace(argv[1], argv[2], 0, 0) 37 | 38 | 39 | -------------------------------------------------------------------------------- /insertkeys.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from xml.sax import saxutils, handler, make_parser 4 | from optparse import OptionParser 5 | import ConfigParser 6 | import logging 7 | import base64 8 | import sys 9 | import os 10 | 11 | __VERSION = (0, 1) 12 | 13 | ''' 14 | This tool reads a mac_permissions.xml and replaces keywords in the signature 15 | clause with keys provided by pem files. 16 | ''' 17 | 18 | class GenerateKeys(object): 19 | def __init__(self, path): 20 | ''' 21 | Generates an object with Base16 and Base64 encoded versions of the keys 22 | found in the supplied pem file argument. PEM files can contain multiple 23 | certs, however this seems to be unused in Android as pkg manager grabs 24 | the first cert in the APK. This will however support multiple certs in 25 | the resulting generation with index[0] being the first cert in the pem 26 | file. 27 | ''' 28 | 29 | self._base64Key = list() 30 | self._base16Key = list() 31 | 32 | if not os.path.isfile(path): 33 | sys.exit("Path " + path + " does not exist or is not a file!") 34 | 35 | pkFile = open(path, 'rb').readlines() 36 | base64Key = "" 37 | lineNo = 1 38 | certNo = 1 39 | inCert = False 40 | for line in pkFile: 41 | line = line.strip() 42 | # Are we starting the certificate? 43 | if line == "-----BEGIN CERTIFICATE-----": 44 | if inCert: 45 | sys.exit("Encountered another BEGIN CERTIFICATE without END CERTIFICATE on " + 46 | "line: " + str(lineNo)) 47 | 48 | inCert = True 49 | 50 | # Are we ending the ceritifcate? 51 | elif line == "-----END CERTIFICATE-----": 52 | if not inCert: 53 | sys.exit("Encountered END CERTIFICATE before BEGIN CERTIFICATE on line: " 54 | + str(lineNo)) 55 | 56 | # If we ended the certificate trip the flag 57 | inCert = False 58 | 59 | # Sanity check the input 60 | if len(base64Key) == 0: 61 | sys.exit("Empty certficate , certificate "+ str(certNo) + " found in file: " 62 | + path) 63 | 64 | # ... and append the certificate to the list 65 | # Base 64 includes uppercase. DO NOT tolower() 66 | self._base64Key.append(base64Key) 67 | try: 68 | # Pkgmanager and setool see hex strings with lowercase, lets be consistent 69 | self._base16Key.append(base64.b16encode(base64.b64decode(base64Key)).lower()) 70 | except TypeError: 71 | sys.exit("Invalid certificate, certificate "+ str(certNo) + " found in file: " 72 | + path) 73 | 74 | # After adding the key, reset the accumulator as pem files may have subsequent keys 75 | base64Key="" 76 | 77 | # And increment your cert number 78 | certNo = certNo + 1 79 | 80 | # If we haven't started the certificate, then we should not encounter any data 81 | elif not inCert: 82 | if line is not "": 83 | sys.exit("Detected erroneous line \""+ line + "\" on " + str(lineNo) 84 | + " in pem file: " + path) 85 | 86 | # else we have started the certicate and need to append the data 87 | elif inCert: 88 | base64Key += line 89 | 90 | else: 91 | # We should never hit this assert, if we do then an unaccounted for state 92 | # was entered that was NOT addressed by the if/elif statements above 93 | assert(False == True) 94 | 95 | # The last thing to do before looping up is to increment line number 96 | lineNo = lineNo + 1 97 | 98 | def __len__(self): 99 | return len(self._base16Key) 100 | 101 | def __str__(self): 102 | return str(self.getBase16Keys()) 103 | 104 | def getBase16Keys(self): 105 | return self._base16Key 106 | 107 | def getBase64Keys(self): 108 | return self._base64Key 109 | 110 | class ParseConfig(ConfigParser.ConfigParser): 111 | 112 | # This must be lowercase 113 | OPTION_WILDCARD_TAG = "all" 114 | 115 | def generateKeyMap(self, target_build_variant, key_directory): 116 | 117 | keyMap = dict() 118 | 119 | for tag in self.sections(): 120 | 121 | options = self.options(tag) 122 | 123 | for option in options: 124 | 125 | # Only generate the key map for debug or release, 126 | # not both! 127 | if option != target_build_variant and \ 128 | option != ParseConfig.OPTION_WILDCARD_TAG: 129 | logging.info("Skipping " + tag + " : " + option + 130 | " because target build variant is set to " + 131 | str(target_build_variant)) 132 | continue 133 | 134 | if tag in keyMap: 135 | sys.exit("Duplicate tag detected " + tag) 136 | 137 | tag_path = os.path.expandvars(self.get(tag, option)) 138 | path = os.path.join(key_directory, tag_path) 139 | 140 | keyMap[tag] = GenerateKeys(path) 141 | 142 | # Multiple certificates may exist in 143 | # the pem file. GenerateKeys supports 144 | # this however, the mac_permissions.xml 145 | # as well as PMS do not. 146 | assert len(keyMap[tag]) == 1 147 | 148 | return keyMap 149 | 150 | class ReplaceTags(handler.ContentHandler): 151 | 152 | DEFAULT_TAG = "default" 153 | PACKAGE_TAG = "package" 154 | POLICY_TAG = "policy" 155 | SIGNER_TAG = "signer" 156 | SIGNATURE_TAG = "signature" 157 | 158 | TAGS_WITH_CHILDREN = [ DEFAULT_TAG, PACKAGE_TAG, POLICY_TAG, SIGNER_TAG ] 159 | 160 | XML_ENCODING_TAG = '' 161 | 162 | def __init__(self, keyMap, out=sys.stdout): 163 | 164 | handler.ContentHandler.__init__(self) 165 | self._keyMap = keyMap 166 | self._out = out 167 | self._out.write(ReplaceTags.XML_ENCODING_TAG) 168 | self._out.write("") 169 | self._out.write("") 170 | 171 | def __del__(self): 172 | self._out.write("") 173 | 174 | def startElement(self, tag, attrs): 175 | if tag == ReplaceTags.POLICY_TAG: 176 | return 177 | 178 | self._out.write('<' + tag) 179 | 180 | for (name, value) in attrs.items(): 181 | 182 | if name == ReplaceTags.SIGNATURE_TAG and value in self._keyMap: 183 | for key in self._keyMap[value].getBase16Keys(): 184 | logging.info("Replacing " + name + " " + value + " with " + key) 185 | self._out.write(' %s="%s"' % (name, saxutils.escape(key))) 186 | else: 187 | self._out.write(' %s="%s"' % (name, saxutils.escape(value))) 188 | 189 | if tag in ReplaceTags.TAGS_WITH_CHILDREN: 190 | self._out.write('>') 191 | else: 192 | self._out.write('/>') 193 | 194 | def endElement(self, tag): 195 | if tag == ReplaceTags.POLICY_TAG: 196 | return 197 | 198 | if tag in ReplaceTags.TAGS_WITH_CHILDREN: 199 | self._out.write('' % tag) 200 | 201 | def characters(self, content): 202 | if not content.isspace(): 203 | self._out.write(saxutils.escape(content)) 204 | 205 | def ignorableWhitespace(self, content): 206 | pass 207 | 208 | def processingInstruction(self, target, data): 209 | self._out.write('' % (target, data)) 210 | 211 | if __name__ == "__main__": 212 | 213 | # Intentional double space to line up equls signs and opening " for 214 | # readability. 215 | usage = "usage: %prog [options] CONFIG_FILE MAC_PERMISSIONS_FILE [MAC_PERMISSIONS_FILE...]\n" 216 | usage += "This tool allows one to configure an automatic inclusion\n" 217 | usage += "of signing keys into the mac_permision.xml file(s) from the\n" 218 | usage += "pem files. If mulitple mac_permision.xml files are included\n" 219 | usage += "then they are unioned to produce a final version." 220 | 221 | version = "%prog " + str(__VERSION) 222 | 223 | parser = OptionParser(usage=usage, version=version) 224 | 225 | parser.add_option("-v", "--verbose", 226 | action="store_true", dest="verbose", default=False, 227 | help="Print internal operations to stdout") 228 | 229 | parser.add_option("-o", "--output", default="stdout", dest="output_file", 230 | metavar="FILE", help="Specify an output file, default is stdout") 231 | 232 | parser.add_option("-c", "--cwd", default=os.getcwd(), dest="root", 233 | metavar="DIR", help="Specify a root (CWD) directory to run this from, it" \ 234 | "chdirs' AFTER loading the config file") 235 | 236 | parser.add_option("-t", "--target-build-variant", default="eng", dest="target_build_variant", 237 | help="Specify the TARGET_BUILD_VARIANT, defaults to eng") 238 | 239 | parser.add_option("-d", "--key-directory", default="", dest="key_directory", 240 | help="Specify a parent directory for keys") 241 | 242 | (options, args) = parser.parse_args() 243 | 244 | if len(args) < 2: 245 | parser.error("Must specify a config file (keys.conf) AND mac_permissions.xml file(s)!") 246 | 247 | logging.basicConfig(level=logging.INFO if options.verbose == True else logging.WARN) 248 | 249 | # Read the config file 250 | config = ParseConfig() 251 | config.read(args[0]) 252 | 253 | os.chdir(options.root) 254 | 255 | output_file = sys.stdout if options.output_file == "stdout" else open(options.output_file, "w") 256 | logging.info("Setting output file to: " + options.output_file) 257 | 258 | # Generate the key list 259 | key_map = config.generateKeyMap(options.target_build_variant.lower(), options.key_directory) 260 | logging.info("Generate key map:") 261 | for k in key_map: 262 | logging.info(k + " : " + str(key_map[k])) 263 | # Generate the XML file with markup replaced with keys 264 | parser = make_parser() 265 | parser.setContentHandler(ReplaceTags(key_map, output_file)) 266 | for f in args[1:]: 267 | parser.parse(f) 268 | -------------------------------------------------------------------------------- /keys.conf: -------------------------------------------------------------------------------- 1 | # 2 | # Maps an arbitrary tag [TAGNAME] with the string contents found in 3 | # TARGET_BUILD_VARIANT. Common convention is to start TAGNAME with an @ and 4 | # name it after the base file name of the pem file. 5 | # 6 | # Each tag (section) then allows one to specify any string found in 7 | # TARGET_BUILD_VARIANT. Typcially this is user, eng, and userdebug. Another 8 | # option is to use ALL which will match ANY TARGET_BUILD_VARIANT string. 9 | # 10 | 11 | [@PLATFORM] 12 | ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/platform.x509.pem 13 | 14 | [@MEDIA] 15 | ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/media.x509.pem 16 | 17 | [@SHARED] 18 | ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/shared.x509.pem 19 | 20 | # Example of ALL TARGET_BUILD_VARIANTS 21 | [@RELEASE] 22 | ENG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem 23 | USER : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem 24 | USERDEBUG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem 25 | 26 | -------------------------------------------------------------------------------- /linux-x86/aapt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/aapt -------------------------------------------------------------------------------- /linux-x86/bsdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/bsdiff -------------------------------------------------------------------------------- /linux-x86/imgdiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/imgdiff -------------------------------------------------------------------------------- /linux-x86/lib/libc++.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/lib/libc++.so -------------------------------------------------------------------------------- /linux-x86/mkbootfs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/mkbootfs -------------------------------------------------------------------------------- /linux-x86/mkbootimg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/mkbootimg -------------------------------------------------------------------------------- /linux-x86/unpackbootimg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/unpackbootimg -------------------------------------------------------------------------------- /linux-x86/zipalign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/linux-x86/zipalign -------------------------------------------------------------------------------- /make_key: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2009 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Generates a public/private key pair suitable for use in signing 18 | # android .apks and OTA update packages. 19 | 20 | if [ "$#" -lt 2 -o "$#" -gt 3 ]; then 21 | cat < [] 23 | 24 | Creates .pk8 key and .x509.pem cert. Cert contains the 25 | given . A keytype of "rsa" or "ec" is accepted. 26 | EOF 27 | exit 2 28 | fi 29 | 30 | if [[ -e $1.pk8 || -e $1.x509.pem ]]; then 31 | echo "$1.pk8 and/or $1.x509.pem already exist; please delete them first" 32 | echo "if you want to replace them." 33 | exit 1 34 | fi 35 | 36 | # Use named pipes to connect get the raw RSA private key to the cert- 37 | # and .pk8-creating programs, to avoid having the private key ever 38 | # touch the disk. 39 | 40 | tmpdir=$(mktemp -d) 41 | trap 'rm -rf ${tmpdir}; echo; exit 1' EXIT INT QUIT 42 | 43 | one=${tmpdir}/one 44 | two=${tmpdir}/two 45 | mknod ${one} p 46 | mknod ${two} p 47 | chmod 0600 ${one} ${two} 48 | 49 | read -p "Enter password for '$1' (blank for none; password will be visible): " \ 50 | password 51 | 52 | export RANDFILE=".rnd" 53 | 54 | if [ "${3}" = "rsa" -o "$#" -eq 2 ]; then 55 | ( openssl genrsa -f4 2048 | tee ${one} > ${two} ) & 56 | hash="-sha1" 57 | elif [ "${3}" = "ec" ]; then 58 | ( openssl ecparam -name prime256v1 -genkey -noout | tee ${one} > ${two} ) & 59 | hash="-sha256" 60 | else 61 | echo "Only accepts RSA or EC keytypes." 62 | exit 1 63 | fi 64 | 65 | openssl req -new -x509 ${hash} -key ${two} -out $1.x509.pem \ 66 | -days 10000 -subj "$2" & 67 | 68 | if [ "${password}" == "" ]; then 69 | echo "creating ${1}.pk8 with no password" 70 | openssl pkcs8 -in ${one} -topk8 -outform DER -out $1.pk8 -nocrypt 71 | else 72 | echo "creating ${1}.pk8 with password [${password}]" 73 | export password 74 | openssl pkcs8 -in ${one} -topk8 -outform DER -out $1.pk8 \ 75 | -passout env:password 76 | unset password 77 | fi 78 | 79 | wait 80 | wait 81 | -------------------------------------------------------------------------------- /merge_divide_jar_out.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #{JAR_DIVIDE}:i9100:framework.jar.out|framework2.jar.out 4 | #{JAR_DIVIDE}:sensation:framework.jar.out|widget.jar.out 5 | #{JAR_DIVIDE}:razr:framework.jar.out|framework-ext.jar.out 6 | #{JAR_DIVIDE}:vivo:framework.jar.out|framework2.jar.out 7 | #{JAR_DIVIDE}:i9300:framework.jar.out|framework2.jar.out 8 | #{JAR_DIVIDE}:gnote:framework.jar.out|framework2.jar.out 9 | #{JAR_DIVIDE}:onex:framework.jar.out|framework2.jar.out 10 | #{JAR_DIVIDE}:ones:framework.jar.out|framework2.jar.out 11 | #{JAR_DIVIDE}:x515m:framework.jar.out|framework2.jar.out 12 | #{JAR_DIVIDE}:saga:framework.jar.out|framework2.jar.out 13 | #{JAR_DIVIDE}:me865:framework.jar.out|framework-ext.jar.out 14 | #{JAR_DIVIDE}:lu6200:framework.jar.out|framework2.jar.out 15 | 16 | ANDROID_PATH=$PORT_ROOT/android 17 | PATCH_SH=$PORT_ROOT/tools/merge_divide_jar_out.sh 18 | PATCH_SWAP_PATH=$PORT_ROOT/android/patch 19 | 20 | function error_exit { 21 | echo -e "ERROR: $1" 22 | exit 1 23 | } 24 | 25 | function merge_jar { 26 | local phone="$1" 27 | local OLD_PWD=$PWD 28 | local config=`grep "#{JAR_DIVIDE}:$phone:" $PATCH_SH | sed "s/#{JAR_DIVIDE}:$1://g"` 29 | if [ -z "$config" ];then 30 | return 31 | fi 32 | 33 | local jar_out=`echo "$config" | cut -d'|' -f1` 34 | local divide_jar_out=`echo "$config" | cut -d'|' -f2` 35 | 36 | cd $PORT_ROOT/$phone 37 | #git checkout . >/dev/null 38 | #git clean -df >/dev/null 39 | 40 | cd $PORT_ROOT/$phone/$divide_jar_out/smali 41 | mkdir $PATCH_SWAP_PATH/divide_jar/ -p 42 | find -type f >"$PATCH_SWAP_PATH/divide_jar/$phone:$jar_out:$divide_jar_out" 43 | cp $PORT_ROOT/$phone/$divide_jar_out/smali/ $PORT_ROOT/$phone/$jar_out/ -r 44 | rm $PORT_ROOT/$phone/$divide_jar_out/smali/ -rf 45 | cd $OLD_PWD 46 | } 47 | 48 | function divide_jar { 49 | local phone="$1" 50 | local OLD_PWD="$PWD" 51 | local recovery_file="`find $PATCH_SWAP_PATH/divide_jar/ -name $phone:*`" 52 | if [ -z "$recovery_file" ];then 53 | return 54 | fi 55 | local jar_out=`basename "$recovery_file" | cut -d':' -f2` 56 | local divide_jar_out=`echo "$recovery_file" | cut -d':' -f3` 57 | OLD_IFS="$IFS" 58 | IFS=$'\n' 59 | for f in `cat "$recovery_file"` 60 | do 61 | dir=`dirname $f` 62 | mkdir $PORT_ROOT/$phone/$divide_jar_out/smali/$dir -p 63 | mv "$PORT_ROOT/$phone/$jar_out/smali/$f" "$PORT_ROOT/$phone/$divide_jar_out/smali/$f" 64 | done 65 | IFS="$OLD_IFS" 66 | rm "$recovery_file" 67 | cd "$PORT_ROOT/$phone" 68 | git clean -df >/dev/null 69 | cd "$OLD_PWD" 70 | } 71 | 72 | ######START####### 73 | [ -z "$PORT_ROOT" ] && error_exit "Please setup environment firstly" 74 | [[ ! -d "$PORT_ROOT/$2" || -z "$2" ]] && error_exit "$2 is wrong phone's name" 75 | if [ "$1" = "-m" ];then 76 | merge_jar $2 77 | elif [ "$1" = "-d" ];then 78 | divide_jar $2 79 | fi 80 | 81 | -------------------------------------------------------------------------------- /multi_format_subst.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | 5 | open(FILE, $ARGV[0]); 6 | 7 | while( my $line = ) { 8 | 9 | my $n = 0; 10 | while ( $line =~ /%d/ ) { 11 | $n++; 12 | $line =~ s/%d/%$n\$d/; 13 | } 14 | 15 | if ($n==1) { 16 | $line =~ s/%1\$d/%d/ 17 | } 18 | 19 | print $line; 20 | } 21 | -------------------------------------------------------------------------------- /oat2dex: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2007 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # As per the Apache license requirements, this file has been modified 18 | # from its original state. 19 | # 20 | # Such modifications are Copyright (C) 2016 Miui Patchrom Project, and 21 | # are released under the original license 22 | 23 | # This script is a wrapper around oat2dex.jar, so you can simply call 24 | # "oat2dex", instead of java -jar oat2dex.jar. It is heavily based on 25 | # the "dx" script from the Android SDK 26 | 27 | # Set up prog to be the path of this script, including following symlinks, 28 | # and set up progdir to be the fully-qualified pathname of its directory. 29 | prog="$0" 30 | while [ -h "${prog}" ]; do 31 | newProg=`/bin/ls -ld "${prog}"` 32 | echo ${newProg} 33 | 34 | 35 | newProg=`expr "${newProg}" : ".* -> \(.*\)$"` 36 | if expr "x${newProg}" : 'x/' >/dev/null; then 37 | prog="${newProg}" 38 | else 39 | progdir=`dirname "${prog}"` 40 | prog="${progdir}/${newProg}" 41 | fi 42 | done 43 | oldwd=`pwd` 44 | progdir=`dirname "${prog}"` 45 | cd "${progdir}" 46 | progdir=`pwd` 47 | prog="${progdir}"/`basename "${prog}"` 48 | cd "${oldwd}" 49 | 50 | 51 | jarfile=oat2dex.jar 52 | libdir="$progdir" 53 | if [ ! -r "$libdir/$jarfile" ] 54 | then 55 | echo `basename "$prog"`": can't find $jarfile" 56 | exit 1 57 | fi 58 | 59 | javaOpts="" 60 | 61 | # If you want DX to have more memory when executing, uncomment the following 62 | # line and adjust the value accordingly. Use "java -X" for a list of options 63 | # you can pass here. 64 | # 65 | javaOpts="-Xmx1024M" 66 | 67 | # Alternatively, this will extract any parameter "-Jxxx" from the command line 68 | # and pass them to Java (instead of to dx). This makes it possible for you to 69 | # add a command-line parameter such as "-JXmx256M" in your ant scripts, for 70 | # example. 71 | while expr "x$1" : 'x-J' >/dev/null; do 72 | opt=`expr "$1" : '-J\(.*\)'` 73 | javaOpts="${javaOpts} -${opt}" 74 | shift 75 | done 76 | 77 | if [ "$OSTYPE" = "cygwin" ] ; then 78 | jarpath=`cygpath -w "$libdir/$jarfile"` 79 | else 80 | jarpath="$libdir/$jarfile" 81 | fi 82 | 83 | exec java $javaOpts -jar "$jarpath" "$@" 84 | -------------------------------------------------------------------------------- /oat2dex-0.86.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/oat2dex-0.86.jar -------------------------------------------------------------------------------- /oat2dex-0.87.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/oat2dex-0.87.jar -------------------------------------------------------------------------------- /oat2dex.jar: -------------------------------------------------------------------------------- 1 | oat2dex-0.87.jar -------------------------------------------------------------------------------- /patch_bootimg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -f "./patch_bootimg.sh" ];then 4 | bash ./patch_bootimg.sh $1 5 | exit $? 6 | fi 7 | 8 | BOOTIMG=$1 9 | 10 | # Unpack bootimg 11 | rm -rf $TARGET_BOOT_DIR 12 | mkdir -p $TARGET_BOOT_DIR 13 | $UNPACKBOOTIMG -i $BOOTIMG -o $TARGET_BOOT_DIR > /dev/null 14 | 15 | # Unpack ramdisk 16 | gunzip $TARGET_BOOT_DIR/boot.img-ramdisk.gz 17 | mkdir -p $TARGET_BOOT_DIR/ramdisk 18 | cd $TARGET_BOOT_DIR/ramdisk 19 | cpio -i < ../boot.img-ramdisk 20 | cd - > /dev/null 21 | 22 | # Change init 23 | if [ ! -f $TARGET_BOOT_DIR/ramdisk/init_vendor ];then 24 | mv $TARGET_BOOT_DIR/ramdisk/init $TARGET_BOOT_DIR/ramdisk/init_vendor 25 | fi 26 | cp -f $PREBUILT_BOOT_DIR/$TARGET_BIT/init $TARGET_BOOT_DIR/ramdisk/init 27 | 28 | # Pack ramdisk 29 | $MKBOOTFS $TARGET_BOOT_DIR/ramdisk | gzip > $TARGET_BOOT_DIR/ramdisk.gz 30 | 31 | 32 | # Disable selinux 33 | OLDCMDLINE=$(cat $TARGET_BOOT_DIR/boot.img-cmdline) 34 | NEWCMDLINE="androidboot.selinux=disabled" 35 | for prop in $OLDCMDLINE 36 | do 37 | echo $prop | grep "androidboot.selinux=" > /dev/null 38 | if [ $? -eq 0 ];then 39 | continue 40 | fi 41 | NEWCMDLINE="$NEWCMDLINE $prop" 42 | done 43 | 44 | echo "NEWCMDLINE: $NEWCMDLINE" 45 | 46 | BASEADDR=$(cat $TARGET_BOOT_DIR/boot.img-base) 47 | PAGESIZE=$(cat $TARGET_BOOT_DIR/boot.img-pagesize) 48 | RAMDISKOFFSET=$(cat $TARGET_BOOT_DIR/boot.img-ramdisk_offset) 49 | TAGSOFFSET=$(cat $TARGET_BOOT_DIR/boot.img-tags_offset) 50 | 51 | # Pack bootimg 52 | $MKBOOTIMG --kernel $TARGET_BOOT_DIR/boot.img-zImage --ramdisk $TARGET_BOOT_DIR/ramdisk.gz --dt $TARGET_BOOT_DIR/boot.img-dt --base "$BASEADDR" --pagesize "$PAGESIZE" --ramdisk_offset "$RAMDISKOFFSET" --tags_offset "$TAGSOFFSET" --cmdline "$NEWCMDLINE" -o $BOOTIMG 53 | -------------------------------------------------------------------------------- /patch_for_phones.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z "$PORT_ROOT" ] 4 | then 5 | echo -e "\033[91m Please setup environmant firstly \033[1;m" #RED COLOR 6 | echo 7 | exit 8 | fi 9 | 10 | ALL_PHONES=$(sed -n '2p' $PORT_ROOT/build/makefile | sed 's/PRODUCTS := //') 11 | ALL_PHONES="$ALL_PHONES $EXTRA_PHONES" #set environment variable EXTRA_PHONES to other phones that aren't in Makefile 12 | 13 | FACTORYS=(HTC HUAWEI SONY MOTO SAMSUNG) 14 | HTC=(sensation x515m vivo saga onex ones) 15 | HUAWEI=(honor p1 d1) 16 | SONY=(lt18i lt26i) 17 | MOTO=(razr me865) 18 | SAMSUNG=(i9100 i9300 gnote) 19 | 20 | GIT_UPLOAD_TOOL_PATH=$PORT_ROOT/.repo/repo/subcmds 21 | GIT_UPLOAD_TOOL_NO_VERIFY=$PORT_ROOT/tools/git_upload_no_verify.py 22 | PATCH_SH=$PORT_ROOT/tools/patch_for_phones.sh 23 | PATCH_SWAP_PATH=$PORT_ROOT/android/patch 24 | MERGE_DIVIDE_TOOLS=$PORT_ROOT/tools/merge_divide_jar_out.sh 25 | 26 | WHITE='\033[37m' 27 | GRAY='\033[30m' 28 | BLUE='\033[34m' 29 | GREEN='\033[92m' 30 | YELLOW='\033[33m' 31 | RED='\033[91m' 32 | ENDC='\033[1;m' 33 | 34 | ERROR="${RED}ERROR$ENDC" 35 | 36 | TOOL_NAME=${0##*/} 37 | TARGETS= 38 | COMMIT_ARRAY= 39 | TMP_DIR= 40 | STASH= 41 | STASH_MSG="STASH CHANGE FOR AUTO_PATCHING" 42 | BRANCH="for-upload" 43 | RESULT= 44 | COMMIT_MSG= 45 | UPLOAD= 46 | 47 | POS='\033[' 48 | ENDP='H' 49 | LNUM= 50 | CNUM=20 51 | 52 | 53 | get_line_num() 54 | { 55 | local pos 56 | echo -ne '\e[6n'; read -sdR pos 57 | pos=${pos#*[} 58 | LNUM=${pos%%;*} 59 | #col=${pos##*;} 60 | } 61 | 62 | function check_commits_parameter { 63 | local phone="$1" 64 | local pre="$2" 65 | local post="$3" 66 | local all_commit 67 | 68 | [ ${#pre} -ne 7 ] && error_exit "length of \"$pre\" is not 7 chars" 69 | [ ${#post} -ne 7 ] && error_exit "length of \"$post\" is not 7 chars" 70 | 71 | all_commit=$(git log --oneline | cut -d' ' -f1) 72 | [ "$pre" = "$post" ] && error_exit "commit NO. is same" 73 | 74 | echo $all_commit | grep -q "$pre" || error_exit "can't find commit $pre" 75 | echo $all_commit | grep -q "$post" || error_exit "can't find commit $post" 76 | 77 | for commit in $all_commit 78 | do 79 | echo $commit | grep -q $pre && error_exit "$pre is ahead than $post" 80 | echo $commit | grep -q $post && break 81 | done 82 | } 83 | 84 | function get_commit_array { 85 | local phone="$1" 86 | local pre="$2" 87 | local post="$3" 88 | local array 89 | 90 | cd "$PORT_ROOT/$phone" 91 | local all_commit=$(git log --oneline | cut -d' ' -f1) 92 | 93 | array=$(echo $all_commit | sed -e "s/$pre.*$//g" | sed -e "s/^.*$post//g") 94 | eval array="($post $array)" 95 | 96 | local len=${#array[*]} 97 | for ((i = 0; i < $len; i++)) 98 | do 99 | COMMIT_ARRAY[$i]=${array[(($len-$i-1))]} 100 | done 101 | } 102 | 103 | function replace_git_upload_tool { 104 | cp $GIT_UPLOAD_TOOL_NO_VERIFY $GIT_UPLOAD_TOOL_PATH/upload.py 105 | } 106 | 107 | function recovery_git_upload_tool { 108 | cd $GIT_UPLOAD_TOOL_PATH 109 | git checkout . 2>/dev/null 1>/dev/null 110 | cd - 2>/dev/null 1>/dev/null 111 | } 112 | 113 | function backup_untracked_files { 114 | local l1=$(git status | grep -n "# Untracked files:" | cut -d':' -f1) 115 | ((l1=l1+3)) 116 | local l2=$(git status | wc -l) 117 | local files=$(git status | sed -n "${l1},${l2}p" | grep -E "^#\s+" |sed "s/#//g") 118 | for f in $files 119 | do 120 | mkdir -p $TMP_DIR/$(dirname $f)/ 121 | mv $f $TMP_DIR/$(dirname $f)/ 122 | done 123 | } 124 | 125 | function stash_changes { 126 | STASH="[stashed]" 127 | git stash save "$STASH_MSG" 1>/dev/null 2>/dev/null 128 | } 129 | 130 | function backup { 131 | grep -q "tmp.*" .git/info/exclude || echo "tmp.*" >> .git/info/exclude 132 | TMP_DIR=$(mktemp -d tmp.XXX) 133 | git status | grep -q "# Untracked files:" && backup_untracked_files 134 | 135 | STASH= 136 | git status | grep -q -E "(# Changes to be committed:|# Changes not staged for commit:)" && stash_changes 137 | } 138 | 139 | function restore { 140 | cp -r $TMP_DIR/* . 2>/dev/null 1>/dev/null 141 | cp -r $TMP_DIR/.[^.]* . 2>/dev/null 1>/dev/null #cp hide files 142 | rm -rf $TMP_DIR 143 | } 144 | 145 | function print_result { 146 | get_line_num 147 | echo -e "$phone ${POS}${LNUM};${CNUM}${ENDP} $result ${YELLOW}${STASH}${ENDC}" 148 | } 149 | 150 | function patch_for_one_phone { 151 | local from="$1" 152 | local phone="$2" 153 | local commit="$3" 154 | local result="success" 155 | 156 | cd "$PORT_ROOT/$phone" 157 | 158 | backup 159 | if ! git checkout "$BRANCH" 2>/dev/null 1>/dev/null 160 | then 161 | result="${RED}failed [no branch $BRANCH]$ENDC" 162 | print_result "$phone" "$result" 163 | restore 164 | return 165 | fi 166 | 167 | if ! repo sync . 2>/dev/null 1>/dev/null 168 | then 169 | result="${RED}failed [sync failed]$ENDC" 170 | print_result "$phone" "$result" 171 | restore 172 | return 173 | fi 174 | 175 | $MERGE_DIVIDE_TOOLS -m $phone 176 | apply_log=$(git.apply $PATCH_SWAP_PATH/$from-patch.$commit 2>&1) 177 | $MERGE_DIVIDE_TOOLS -d $phone 178 | 179 | echo $apply_log | grep -q "error: while searching for:" && result="${RED}failed$ENDC" 180 | echo $apply_log | grep -q -e "error:.*: No such file or directory" && result="${RED}failed$ENDC" 181 | echo $apply_log | grep -q "Rejected" && result="${RED}failed$ENDC" 182 | git status | grep -q "smali.rej" && result="${RED}failed$ENDC" 183 | 184 | if [ $result = "success" ] 185 | then 186 | git add . 2>/dev/null 1>/dev/null 187 | 188 | IFS_OLD="$IFS" 189 | IFS= 190 | echo $MSG | git commit --file=- 2>/dev/null 1>/dev/null 191 | IFS="$IFS_OLD" 192 | 193 | [ $UPLOAD != "false" ] && repo upload . 2>/dev/null 1>/dev/null 194 | else 195 | git clean -df 2>/dev/null 1>/dev/null 196 | git checkout . 2>/dev/null 1>/dev/null 197 | fi 198 | 199 | restore 200 | print_result "$phone" "$result" 201 | } 202 | 203 | function patch_for_phones { 204 | local from="$1" 205 | local to="$2" 206 | local commit="$3" 207 | 208 | for phone in $to 209 | do 210 | patch_for_one_phone "$from" "$phone" "$commit" 211 | done 212 | } 213 | 214 | function patch_one_commit { 215 | local from="$1" 216 | local to="$2" 217 | local commit="$3" 218 | 219 | cd "$PORT_ROOT/$from" 220 | mkdir $PATCH_SWAP_PATH -p 221 | git.patch ${commit}^..${commit} 2>/dev/null | sed "s/framework2.jar.out/framework.jar.out/g" | sed "s/framework-ext.jar.out/framework.jar.out/g" > ${PATCH_SWAP_PATH}/${from}-patch.${commit} 222 | IFS_OLD="$IFS" 223 | IFS= 224 | MGS= 225 | MSG=$(git log -1 ${commit} | grep "^\s" | grep -v "Signed-off-by:" | sed "s/\s\+//" | sed "/Change-Id:/d") 226 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 227 | echo -ne "" 228 | echo -e "${BLUE}[ID]${ENDC}" 229 | echo " ${commit}" 230 | echo -e "${BLUE}[MSG]${ENDC}" 231 | echo "$MSG" | sed "s/^/ /" 232 | echo ---------------------------------------------------------- 233 | IFS="$IFS_OLD" 234 | #echo "patch_for_phones $from $to ${commit}" 235 | patch_for_phones "$from" "$to" "${commit}" 236 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 237 | echo -e "\n" 238 | } 239 | 240 | function patch_commits { 241 | local from="$1" 242 | local to="$2" 243 | local pre="$3" 244 | local post="$4" 245 | 246 | check_commits_parameter $from $pre $post 247 | get_commit_array $from $pre $post 248 | 249 | echo 250 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 251 | echo -e " ${BLUE}${#COMMIT_ARRAY[*]}$ENDC COMMITS FROM [${RED}$from$ENDC] NEED TO PATCH:" 252 | echo -n " " 253 | echo -e "${YELLOW}|->${COMMIT_ARRAY[*]}->|$ENDC" 254 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 255 | echo 256 | 257 | for ((i = 0; i < ${#COMMIT_ARRAY[*]}; i++)) 258 | do 259 | local commit="${COMMIT_ARRAY[$i]}" 260 | replace_git_upload_tool 261 | 262 | patch_one_commit "$from" "$to" "$commit" 263 | 264 | recovery_git_upload_tool 265 | done 266 | } 267 | 268 | function execute { 269 | local cmdstr="$1" 270 | local cmd 271 | if echo $cmdstr | grep ";" -q 272 | then 273 | for (( i = 1; ; i++ )) 274 | do 275 | cmd=$(echo $cmdstr | cut -d';' -f$i) 276 | [ -z "$cmd" ] && break 277 | echo -e "${YELLOW}++++OUTPUT OF [${GREEN}${cmd}${YELLOW}] @[${GREEN}$(pwd)${YELLOW}]++++$ENDC " 278 | eval $cmd 279 | echo 280 | done 281 | else 282 | echo -e "${YELLOW}++++OUTPUT OF [${GREEN}${cmdstr}${YELLOW}] @[${GREEN}$(pwd)${YELLOW}]++++$ENDC " 283 | eval $cmdstr 284 | fi 285 | } 286 | 287 | function execute_for_phones { 288 | local phones="$1" 289 | local cmdstr="$2" 290 | for phone in $phones 291 | do 292 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 293 | echo -e "${BLUE}EXECUTE [$cmdstr] for [$phone]$ENDC" 294 | echo ---------------------------------------------------------- 295 | cd $PORT_ROOT/$phone 296 | execute "$cmdstr" 297 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 298 | echo 299 | done 300 | } 301 | 302 | function merge_jar_out_for_phones { 303 | local phones="$1" 304 | 305 | for phone in $phones 306 | do 307 | cd "$PORT_ROOT/$phone" 308 | echo -e "${BLUE}MERGE jar.out for [$phone]$ENDC\n" 309 | $MERGE_DIVIDE_TOOLS "-m" "$phone" 310 | done 311 | } 312 | 313 | function divide_jar_out_for_phones { 314 | local phones="$1" 315 | 316 | for phone in $phones 317 | do 318 | cd "$PORT_ROOT/$phone" 319 | echo -e "${BLUE}DIVIDE jar.out for [$phone]$ENDC\n" 320 | $MERGE_DIVIDE_TOOLS "-d" "$phone" 321 | done 322 | } 323 | 324 | function check_phones { 325 | local invalid 326 | local valid 327 | local t 328 | t="$1" 329 | TARGETS= 330 | for (( i=0; i<${#FACTORYS[*]}; i++ )) 331 | do 332 | if [ "$t" = "${FACTORYS[i]}" ] 333 | then 334 | eval t="$""{""$t""[*]}" 335 | break 336 | fi 337 | done 338 | if [ "$t" = "all" ] 339 | then 340 | t="$ALL_PHONES" 341 | fi 342 | 343 | for p in $t 344 | do 345 | if [[ -d $PORT_ROOT/$p && -n "$p" && -n "$ALL_PHONES" && ${ALL_PHONES/$p/} != ${ALL_PHONES} ]] 346 | then 347 | valid="$valid $p" 348 | else 349 | invalid="$invalid $p" 350 | fi 351 | done 352 | [ -z "$valid" ] && error_exit "no valid targets" 353 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 354 | [ -n "$invalid" ] && echo -e "${RED}INVALID TARGETS${ENDC}:\n\t$invalid" 355 | TARGETS=$valid 356 | echo -e "${GREEN}VALID TARGETS${ENDC}:" 357 | echo -e "\t$TARGETS" 358 | [ -z "$UPLOAD" ] || echo -e "${GREEN}UPLOAD${ENDC}:\n\t$UPLOAD" 359 | echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 360 | echo 361 | } 362 | 363 | function error_exit { 364 | echo -e "$ERROR: $1" 365 | exit 1 366 | } 367 | 368 | function usage { 369 | echo "*********************************************** USAGE ******************************************************" 370 | echo "$TOOL_NAME [OPTIN]" 371 | echo "OPTION" 372 | echo -e "CASE 1:" 373 | echo -e "\t --exec --phones {\"[phone1 phone2 ... phoneN] or [all]\"} --cmdstr [\"cmdstring\"]" 374 | echo -e "CASE 2:" 375 | echo -e "\t [--without-upload] --patch --from [phone] --to {\"[phone1 phone2 ... phoneN]\" or \"[FACTORY]\" or \"[all]\"} --head [length]" 376 | echo -e "CASE 3:" 377 | echo -e "\t [--without-upload] --patch --from [phone] --to {\"[phone1 phone2 ... phoneN]\" or \"[FACTORY]\" or \"[all]\"} --commits [pre_commit] [post_commit]" 378 | echo -e "CASE 4:" 379 | echo -e "\t --merge-jar-out --phones {\"[phone1 phone2 ... phoneN]\" or \"[FACTORY]\" or \"[all]\"}" 380 | echo -e "CASE 5:" 381 | echo -e "\t --divide-jar-out --phones {\"[phone1 phone2 ... phoneN]\" or \"[FACTORY]\" or \"[all]\"}" 382 | echo 383 | exit $1 384 | } 385 | 386 | 387 | ####start### 388 | case "$1" in 389 | "--exec") 390 | [[ "$2" = "--phones" && "$4" = "--cmdstr" ]] || usage 1 391 | cd $PORT_ROOT 392 | ALL_PHONES=$(find . -maxdepth 1 -type d | sed "s/\.\///" | grep -v "\.") 393 | check_phones "$3" 394 | cmdstr="$5" 395 | execute_for_phones "$TARGETS" "$cmdstr" 396 | ;; 397 | "--patch" | "--without-upload") 398 | if [ $1 = "--without-upload" ] 399 | then 400 | UPLOAD="false" 401 | shift 402 | else 403 | UPLOAD="true" 404 | fi 405 | 406 | [[ "$1" = "--patch" && "$2" = "--from" && "$4" = "--to" ]] || usage 1 407 | from="$3" 408 | [ ! -d "$PORT_ROOT/$from" ] && error_exit "[$from] is wrong phone's name" #check from 409 | check_phones "$5" 410 | to="$TARGETS" 411 | cd "$PORT_ROOT/$from" 412 | case "$6" in 413 | "--head") 414 | pre=$(git log --oneline HEAD~$7 -1 | cut -d' ' -f1) 415 | post=$(git log --oneline HEAD -1 | cut -d' ' -f1) 416 | ;; 417 | "--commits") 418 | pre="$7" 419 | post="$8" 420 | ;; 421 | *) 422 | usage 1 423 | ;; 424 | esac 425 | [[ -z "$pre" || -z "$post" ]] && usage 1 426 | patch_commits "$from" "$to" "$pre" "$post" 427 | ;; 428 | "--merge-jar-out") 429 | [[ "$2" = "--phones" ]] || usages 1 430 | check_phones "$3" 431 | merge_jar_out_for_phones "$TARGETS" 432 | ;; 433 | "--divide-jar-out") 434 | [[ "$2" = "--phones" ]] || usages 1 435 | check_phones "$3" 436 | divide_jar_out_for_phones "$TARGETS" 437 | ;; 438 | *) 439 | usage 1 440 | ;; 441 | esac 442 | 443 | -------------------------------------------------------------------------------- /patch_miui_app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # $1: dir for original miui app 4 | # $2: dir for target miui app 5 | # 6 | if [ -f "customize_miui_app.sh" ]; then 7 | ./customize_miui_app.sh $1 $2 8 | if [ $? -ne 0 ];then 9 | exit 1 10 | fi 11 | fi 12 | 13 | if [ -f $1 ];then 14 | if [ $1 = "MiuiHome" ];then 15 | if [ -f $1/res/xml/default_workspace.xml.part ]; then 16 | $PORT_ROOT/tools/gen_desklayout.pl $1/res/xml/default_workspace.xml.part $2/res/xml 17 | for file in $2/res/xml/default_workspace*.xml; do 18 | mv $file.new $file 19 | done 20 | fi 21 | fi 22 | 23 | # patch *.smali.method under $1 24 | for file in `find $1 -name "*.smali.method"`; do 25 | $PORT_ROOT/tools/replace_smali_method.sh apply $file 26 | done 27 | fi 28 | -------------------------------------------------------------------------------- /patch_miui_framework.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # $1: the old smali code $2: the new smali code $3: the destination smali code 4 | 5 | if [ $# -ne 3 ];then 6 | echo "Usage: patchmiui.sh old_smali_dir new_smali_dir dst_smali_dir" 7 | fi 8 | 9 | PWD=`pwd` 10 | old_smali_dir=$1 11 | new_smali_dir=$2 12 | dst_smali_dir=$3 13 | temp_dir=$PWD/temp 14 | temp_old_smali_dir=$temp_dir/old_smali 15 | temp_new_smali_dir=$temp_dir/new_smali 16 | temp_dst_smali_orig_dir=$temp_dir/dst_smali_orig 17 | temp_dst_smali_patched_dir=$temp_dir/dst_smali_patched 18 | reject_dir=$temp_dir/reject 19 | 20 | rm -rf $temp_dir 21 | 22 | echo "<<< create temp directory to store the old, new source and destination smali code with .line removed" 23 | mkdir -p $temp_old_smali_dir 24 | mkdir -p $temp_new_smali_dir 25 | mkdir -p $temp_dst_smali_orig_dir 26 | mkdir -p $temp_dst_smali_patched_dir 27 | mkdir -p $reject_dir 28 | 29 | cp -r $old_smali_dir/*.jar.out $temp_old_smali_dir 30 | cp -r $new_smali_dir/*.jar.out $temp_new_smali_dir 31 | cp -r $dst_smali_dir/*.jar.out $temp_dst_smali_orig_dir 32 | $PORT_ROOT/tools/rmline.sh $temp_dir 33 | 34 | function apply_miui_patch() { 35 | old_code_noline=$temp_old_smali_dir/$1 36 | new_code_noline=$temp_new_smali_dir/$1 37 | dst_code_noline=$temp_dst_smali_orig_dir/$1 38 | dst_code=$dst_smali_dir/$1 39 | dst_code_orig=$dst_code.orig 40 | 41 | echo "<<< compute the difference between $old_code_noline and $new_code_noline" 42 | cd $old_code_noline 43 | for file in `find ./ -name "*.smali"` 44 | do 45 | if [ -f $new_code_noline/$file ] 46 | then 47 | diff $file $new_code_noline/$file > /dev/null || { 48 | diff -B -c $file $new_code_noline/$file > $file.diff 49 | } 50 | else 51 | echo "$file does not exist at $new_code_noline" 52 | fi 53 | done 54 | 55 | cd $dst_smali_dir 56 | mv $dst_code $dst_code_orig 57 | cp -r $dst_code_noline $dst_code 58 | 59 | echo "<<< apply the patch into the $dst_code" 60 | cd $old_code_noline 61 | for file in `find ./ -name "*.smali.diff"` 62 | do 63 | mkdir -p $reject_dir/$1/`dirname $file` 64 | patch $dst_code/${file%.diff} -r $reject_dir/$1/${file%.diff}.rej < $file 65 | done 66 | 67 | cp -r $dst_code $temp_dst_smali_patched_dir 68 | 69 | cd $dst_code_noline 70 | for file in `find ./ -name "*.smali"` 71 | do 72 | rm -f $file.diff 73 | diff -B -c $file $dst_code_orig/$file > $file.diff 74 | patch -f $dst_code/$file -r /dev/null < $file.diff >/dev/null 2>&1 75 | rm -f $file.diff 76 | done 77 | 78 | find $dst_code -name "*.smali.orig" -exec rm {} \; 79 | find $temp_dst_smali_patched_dir -name "*.smali.orig" -exec rm {} \; 80 | rm -rf $dst_code_orig 81 | } 82 | 83 | jar_outs=`find $new_smali_dir -name "*.jar.out"` 84 | for out in $jar_outs 85 | do 86 | apply_miui_patch $(basename $out) 87 | done 88 | 89 | echo 90 | echo 91 | echo ">>> patch miui into target framework is done. Please look at $reject_dir to resolve any conflicts!" 92 | -------------------------------------------------------------------------------- /post_process_props.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (C) 2009 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import sys 18 | 19 | # Put the modifications that you need to make into the /system/build.prop into this 20 | # function. The prop object has get(name) and put(name,value) methods. 21 | def mangle_build_prop(prop, overlaylines): 22 | for i in range(0,len(overlaylines)): 23 | pair = overlaylines[i].split('=') 24 | if len(pair) == 2: 25 | name = pair[0].strip() 26 | value = pair[1].strip() 27 | if not name.startswith("#"): 28 | prop.put(name,value) 29 | pass 30 | 31 | class PropFile: 32 | def __init__(self, lines): 33 | self.lines = [s[:-1] for s in lines] 34 | 35 | def get(self, name): 36 | key = name + "=" 37 | for line in self.lines: 38 | if line.startswith(key): 39 | return line[len(key):] 40 | return "" 41 | 42 | def put(self, name, value): 43 | key = name + "=" 44 | for i in range(0,len(self.lines)): 45 | if self.lines[i].startswith(key): 46 | self.lines[i] = key + value 47 | return 48 | self.lines.append(key + value) 49 | 50 | def delete(self, name): 51 | key = name + "=" 52 | i = 0 53 | while i < len(self.lines): 54 | if self.lines[i].startswith(key): 55 | del self.lines[i] 56 | else: 57 | i += 1 58 | 59 | def write(self, f): 60 | f.write("\n".join(self.lines)) 61 | f.write("\n") 62 | 63 | def main(argv): 64 | srcfilename = argv[1] 65 | overlayfilename = argv[2] 66 | fs = open(srcfilename) 67 | srclines = fs.readlines() 68 | fs.close() 69 | 70 | fo = open(overlayfilename) 71 | overlaylines = fo.readlines() 72 | fo.close() 73 | 74 | properties = PropFile(srclines) 75 | if srcfilename.endswith("/build.prop"): 76 | mangle_build_prop(properties, overlaylines) 77 | else: 78 | sys.stderr.write("bad command line: " + str(argv) + "\n") 79 | sys.exit(1) 80 | 81 | fs = open(srcfilename, 'w+') 82 | properties.write(fs) 83 | fs.close() 84 | 85 | if __name__ == "__main__": 86 | main(sys.argv) 87 | -------------------------------------------------------------------------------- /prepare_preloaded_classes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TEMPDIR=out/temp_for_preloaded 4 | JAR_DIR=$(basename $2) 5 | JAR_FILE=${JAR_DIR/.jar.out/}.jar 6 | echo "prepare preloaded for $2" 7 | rm -rf $TEMPDIR/ 8 | if [ -f stockrom/system/framework/${JAR_FILE} ] 9 | then 10 | unzip stockrom/system/framework/${JAR_FILE} -d $TEMPDIR 11 | else 12 | unzip $1 system/framework/${JAR_FILE} -d $TEMPDIR 13 | unzip ${TEMPDIR}/system/framework/${JAR_FILE} -d $TEMPDIR 14 | fi 15 | 16 | if [ -f ${TEMPDIR}/preloaded-classes ] 17 | then 18 | rm -f $2/preloaded-classes 19 | cp ${TEMPDIR}/preloaded-classes $2/ 20 | fi 21 | 22 | rm -rf $TEMPDIR/ 23 | if [ ! -f $3/${JAR_FILE} ] 24 | then 25 | exit 0 26 | fi 27 | 28 | unzip $3/${JAR_FILE} -d $TEMPDIR 29 | if [ -f ${TEMPDIR}/preloaded-classes ] 30 | then 31 | cat ${TEMPDIR}/preloaded-classes >> $2/preloaded-classes 32 | sort $2/preloaded-classes | uniq | grep -v "#" | sed '/^\s*$/d' > $2/temp 33 | cp $2/temp $2/preloaded-classes 34 | fi 35 | rm -rf $TEMPDIR/ 36 | 37 | -------------------------------------------------------------------------------- /release_source.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "The android source code is located at: $1" 3 | echo "The miui source code is located at: $2" 4 | echo "The released source code would be put at: $3" 5 | 6 | echo "[IMPORTANT] make sure the source codes has been put under $1" 7 | 8 | src_dir=frameworks/base 9 | android=$1/$src_dir 10 | android_rlz=$PORT_ROOT/android/src/$src_dir 11 | miui=$2/$src_dir 12 | release=$3/src/$src_dir 13 | 14 | for mf in `find $miui -name "*.java"` 15 | do 16 | af=${mf/$miui/$android} 17 | if [ -f "$af" ] 18 | then 19 | diff $af $mf > /dev/null || { 20 | #echo $af is different with $mf; 21 | arf=${af/$android/$android_rlz} 22 | mkdir -p `dirname $arf` 23 | cp $af $arf 24 | rf=${mf/$miui/$release} 25 | mkdir -p `dirname $rf` 26 | cp $mf $rf 27 | } 28 | else 29 | echo "Have $mf but $af does not exist!" 30 | fi 31 | done 32 | 33 | for mf in `find $miui -name "*.aidl"` 34 | do 35 | af=${mf/$miui/$android} 36 | if [ -f "$af" ] 37 | then 38 | diff $af $mf > /dev/null || { 39 | #echo $af is different with $mf; 40 | arf=${af/$android/$android_rlz} 41 | mkdir -p `dirname $arf` 42 | cp $af $arf 43 | rf=${mf/$miui/$release} 44 | mkdir -p `dirname $rf` 45 | cp $mf $rf 46 | } 47 | else 48 | echo "Have $mf but $af does not exist!" 49 | fi 50 | done 51 | 52 | -------------------------------------------------------------------------------- /releasetools/edify_generator.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import re 16 | 17 | import common 18 | 19 | class EdifyGenerator(object): 20 | """Class to generate scripts in the 'edify' recovery script language 21 | used from donut onwards.""" 22 | 23 | def __init__(self, version, info, fstab=None): 24 | self.script = [] 25 | self.mounts = set() 26 | self.version = version 27 | self.info = info 28 | if fstab is None: 29 | self.fstab = self.info.get("fstab", None) 30 | else: 31 | self.fstab = fstab 32 | 33 | def MakeTemporary(self): 34 | """Make a temporary script object whose commands can latter be 35 | appended to the parent script with AppendScript(). Used when the 36 | caller wants to generate script commands out-of-order.""" 37 | x = EdifyGenerator(self.version, self.info) 38 | x.mounts = self.mounts 39 | return x 40 | 41 | @staticmethod 42 | def WordWrap(cmd, linelen=80): 43 | """'cmd' should be a function call with null characters after each 44 | parameter (eg, "somefun(foo,\0bar,\0baz)"). This function wraps cmd 45 | to a given line length, replacing nulls with spaces and/or newlines 46 | to format it nicely.""" 47 | indent = cmd.index("(")+1 48 | out = [] 49 | first = True 50 | x = re.compile("^(.{,%d})\0" % (linelen-indent,)) 51 | while True: 52 | if not first: 53 | out.append(" " * indent) 54 | first = False 55 | m = x.search(cmd) 56 | if not m: 57 | parts = cmd.split("\0", 1) 58 | out.append(parts[0]+"\n") 59 | if len(parts) == 1: 60 | break 61 | else: 62 | cmd = parts[1] 63 | continue 64 | out.append(m.group(1)+"\n") 65 | cmd = cmd[m.end():] 66 | 67 | return "".join(out).replace("\0", " ").rstrip("\n") 68 | 69 | def AppendScript(self, other): 70 | """Append the contents of another script (which should be created 71 | with temporary=True) to this one.""" 72 | self.script.extend(other.script) 73 | 74 | def AssertOemProperty(self, name, value): 75 | """Assert that a property on the OEM paritition matches a value.""" 76 | if not name: 77 | raise ValueError("must specify an OEM property") 78 | if not value: 79 | raise ValueError("must specify the OEM value") 80 | cmd = ('file_getprop("/oem/oem.prop", "{name}") == "{value}" || ' 81 | 'abort("This package expects the value \\"{value}\\" for ' 82 | '\\"{name}\\" on the OEM partition; this has value \\"" + ' 83 | 'file_getprop("/oem/oem.prop", "{name}") + "\\".");').format( 84 | name=name, value=value) 85 | self.script.append(cmd) 86 | 87 | def AssertSomeFingerprint(self, *fp): 88 | """Assert that the current system build fingerprint is one of *fp.""" 89 | if not fp: 90 | raise ValueError("must specify some fingerprints") 91 | cmd = (' ||\n '.join([('file_getprop("/system/build.prop", "ro.build.fingerprint") == "%s"') % i 92 | for i in fp]) + 93 | ' ||\n abort("Package expects build fingerprint of %s; this ' 94 | 'device has " + getprop("ro.build.fingerprint") + ".");') % ( 95 | " or ".join(fp)) 96 | self.script.append(cmd) 97 | 98 | def AssertSomeThumbprint(self, *fp): 99 | """Assert that the current system build thumbprint is one of *fp.""" 100 | if not fp: 101 | raise ValueError("must specify some thumbprints") 102 | cmd = (' ||\n '.join([('file_getprop("/system/build.prop", "ro.build.thumbprint") == "%s"') % i 103 | for i in fp]) + 104 | ' ||\n abort("Package expects build thumbprint of %s; this ' 105 | 'device has " + getprop("ro.build.thumbprint") + ".");') % ( 106 | " or ".join(fp)) 107 | self.script.append(cmd) 108 | 109 | def AssertOlderBuild(self, timestamp, timestamp_text): 110 | """Assert that the build on the device is older (or the same as) 111 | the given timestamp.""" 112 | self.script.append( 113 | ('(!less_than_int(%s, getprop("ro.build.date.utc"))) || ' 114 | 'abort("Can\'t install this package (%s) over newer ' 115 | 'build (" + getprop("ro.build.date") + ").");') % (timestamp, 116 | timestamp_text)) 117 | 118 | def AssertDevice(self, device): 119 | """Assert that the device identifier is the given string.""" 120 | cmd = ('getprop("ro.product.device") == "%s" || ' 121 | 'abort("This package is for \\"%s\\" devices; ' 122 | 'this is a \\"" + getprop("ro.product.device") + "\\".");') % ( 123 | device, device) 124 | self.script.append(cmd) 125 | 126 | def AssertSomeBootloader(self, *bootloaders): 127 | """Asert that the bootloader version is one of *bootloaders.""" 128 | cmd = ("assert(" + 129 | " ||\0".join(['getprop("ro.bootloader") == "%s"' % (b,) 130 | for b in bootloaders]) + 131 | ");") 132 | self.script.append(self.WordWrap(cmd)) 133 | 134 | def ShowProgress(self, frac, dur): 135 | """Update the progress bar, advancing it over 'frac' over the next 136 | 'dur' seconds. 'dur' may be zero to advance it via SetProgress 137 | commands instead of by time.""" 138 | self.script.append("show_progress(%f, %d);" % (frac, int(dur))) 139 | 140 | def SetProgress(self, frac): 141 | """Set the position of the progress bar within the chunk defined 142 | by the most recent ShowProgress call. 'frac' should be in 143 | [0,1].""" 144 | self.script.append("set_progress(%f);" % (frac,)) 145 | 146 | def PatchCheck(self, filename, *sha1): 147 | """Check that the given file (or MTD reference) has one of the 148 | given *sha1 hashes, checking the version saved in cache if the 149 | file does not match.""" 150 | self.script.append( 151 | 'apply_patch_check("%s"' % (filename,) + 152 | "".join([', "%s"' % (i,) for i in sha1]) + 153 | ') || abort("\\"%s\\" has unexpected contents.");' % (filename,)) 154 | 155 | def FileCheck(self, filename, *sha1): 156 | """Check that the given file (or MTD reference) has one of the 157 | given *sha1 hashes.""" 158 | self.script.append('assert(sha1_check(read_file("%s")' % (filename,) + 159 | "".join([', "%s"' % (i,) for i in sha1]) + 160 | '));') 161 | 162 | def CacheFreeSpaceCheck(self, amount): 163 | """Check that there's at least 'amount' space that can be made 164 | available on /cache.""" 165 | self.script.append(('apply_patch_space(%d) || abort("Not enough free space ' 166 | 'on /system to apply patches.");') % (amount,)) 167 | 168 | def Mount(self, mount_point, mount_options_by_format=""): 169 | """Mount the partition with the given mount_point. 170 | mount_options_by_format: 171 | [fs_type=option[,option]...[|fs_type=option[,option]...]...] 172 | where option is optname[=optvalue] 173 | E.g. ext4=barrier=1,nodelalloc,errors=panic|f2fs=errors=recover 174 | """ 175 | fstab = self.fstab 176 | if fstab: 177 | p = fstab[mount_point] 178 | mount_dict = {} 179 | if mount_options_by_format is not None: 180 | for option in mount_options_by_format.split("|"): 181 | if "=" in option: 182 | key, value = option.split("=", 1) 183 | mount_dict[key] = value 184 | mount_flags = mount_dict.get(p.fs_type, "") 185 | if p.context is not None: 186 | mount_flags = p.context + ("," + mount_flags if mount_flags else "") 187 | self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % ( 188 | p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device, 189 | p.mount_point, mount_flags)) 190 | self.mounts.add(p.mount_point) 191 | 192 | def UnpackPackageDir(self, src, dst): 193 | """Unpack a given directory from the OTA package into the given 194 | destination directory.""" 195 | # MIUI MOD:START 196 | # self.script.append('package_extract_dir("%s", "%s");' % (src, dst)) 197 | self.script.append( 198 | 'package_extract_dir("%s", "%s") || abort("Failed to extract dir from \\"%s\\" to \\"%s\\".");' % 199 | (src, dst, src, dst)) 200 | # END 201 | 202 | def Comment(self, comment): 203 | """Write a comment into the update script.""" 204 | self.script.append("") 205 | for i in comment.split("\n"): 206 | self.script.append("# " + i) 207 | self.script.append("") 208 | 209 | def Print(self, message): 210 | """Log a message to the screen (if the logs are visible).""" 211 | self.script.append('ui_print("%s");' % (message,)) 212 | 213 | def TunePartition(self, partition, *options): 214 | fstab = self.fstab 215 | if fstab: 216 | p = fstab[partition] 217 | if p.fs_type not in ("ext2", "ext3", "ext4"): 218 | raise ValueError("Partition %s cannot be tuned\n" % (partition,)) 219 | self.script.append( 220 | 'tune2fs(' + "".join(['"%s", ' % (i,) for i in options]) + 221 | '"%s") || abort("Failed to tune partition %s");' % ( 222 | p.device, partition)) 223 | 224 | def FormatPartition(self, partition): 225 | """Format the given partition, specified by its mount point (eg, 226 | "/system").""" 227 | 228 | fstab = self.fstab 229 | if fstab: 230 | p = fstab[partition] 231 | self.script.append('format("%s", "%s", "%s", "%s", "%s");' % 232 | (p.fs_type, common.PARTITION_TYPES[p.fs_type], 233 | p.device, p.length, p.mount_point)) 234 | 235 | def WipeBlockDevice(self, partition): 236 | if partition not in ("/system", "/vendor"): 237 | raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,)) 238 | fstab = self.fstab 239 | size = self.info.get(partition.lstrip("/") + "_size", None) 240 | device = fstab[partition].device 241 | 242 | self.script.append('wipe_block_device("%s", %s);' % (device, size)) 243 | 244 | def DeleteFiles(self, file_list): 245 | """Delete all files in file_list.""" 246 | if not file_list: 247 | return 248 | cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");" 249 | self.script.append(self.WordWrap(cmd)) 250 | 251 | def DeleteFilesIfNotMatching(self, file_list): 252 | """Delete the file in file_list if not matching the checksum.""" 253 | if not file_list: 254 | return 255 | for name, sha1 in file_list: 256 | cmd = ('sha1_check(read_file("{name}"), "{sha1}") || ' 257 | 'delete("{name}");'.format(name=name, sha1=sha1)) 258 | self.script.append(self.WordWrap(cmd)) 259 | 260 | def RenameFile(self, srcfile, tgtfile): 261 | """Moves a file from one location to another.""" 262 | if self.info.get("update_rename_support", False): 263 | self.script.append('rename("%s", "%s");' % (srcfile, tgtfile)) 264 | else: 265 | raise ValueError("Rename not supported by update binary") 266 | 267 | def SkipNextActionIfTargetExists(self, tgtfile, tgtsha1): 268 | """Prepend an action with an apply_patch_check in order to 269 | skip the action if the file exists. Used when a patch 270 | is later renamed.""" 271 | cmd = ('sha1_check(read_file("%s"), %s) ||' % (tgtfile, tgtsha1)) 272 | self.script.append(self.WordWrap(cmd)) 273 | 274 | def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs): 275 | """Apply binary patches (in *patchpairs) to the given srcfile to 276 | produce tgtfile (which may be "-" to indicate overwriting the 277 | source file.""" 278 | if len(patchpairs) % 2 != 0 or len(patchpairs) == 0: 279 | raise ValueError("bad patches given to ApplyPatch") 280 | cmd = ['apply_patch("%s",\0"%s",\0%s,\0%d' 281 | % (srcfile, tgtfile, tgtsha1, tgtsize)] 282 | # MIUI MOD:START 283 | # for i in range(0, len(patchpairs), 2): 284 | # cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2]) 285 | # cmd.append(');') 286 | patchfiles = "" 287 | for i in range(0, len(patchpairs), 2): 288 | cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2]) 289 | patchfiles = patchfiles.join('%s ' % patchpairs[i+1]) 290 | cmd.append(') || abort("Failed to apply patch \\"%s\\".");' % (patchfiles,)) 291 | # END 292 | cmd = "".join(cmd) 293 | self.script.append(self.WordWrap(cmd)) 294 | 295 | def WriteRawImage(self, mount_point, fn, mapfn=None): 296 | """Write the given package file into the partition for the given 297 | mount point.""" 298 | 299 | fstab = self.fstab 300 | if fstab: 301 | p = fstab[mount_point] 302 | partition_type = common.PARTITION_TYPES[p.fs_type] 303 | args = {'device': p.device, 'fn': fn} 304 | if partition_type == "MTD": 305 | self.script.append( 306 | 'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");' 307 | % args) 308 | elif partition_type == "EMMC": 309 | if mapfn: 310 | args["map"] = mapfn 311 | self.script.append( 312 | 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args) 313 | else: 314 | self.script.append( 315 | 'package_extract_file("%(fn)s", "%(device)s");' % args) 316 | else: 317 | raise ValueError( 318 | "don't know how to write \"%s\" partitions" % p.fs_type) 319 | 320 | def SetPermissions(self, fn, uid, gid, mode, selabel, capabilities): 321 | """Set file ownership and permissions.""" 322 | if not self.info.get("use_set_metadata", False): 323 | self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn)) 324 | else: 325 | cmd = 'set_metadata("%s", "uid", %d, "gid", %d, "mode", 0%o' % (fn, uid, gid, mode) 326 | if capabilities is not None: 327 | cmd += ', "capabilities", "%s"' % capabilities 328 | if selabel is not None: 329 | cmd += ', "selabel", "%s"' % selabel 330 | cmd += ');' 331 | self.script.append(cmd) 332 | 333 | def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode, selabel, 334 | capabilities): 335 | """Recursively set path ownership and permissions.""" 336 | if not self.info.get("use_set_metadata", False): 337 | self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");' 338 | % (uid, gid, dmode, fmode, fn)) 339 | else: 340 | if capabilities is None: 341 | capabilities = "0x0" 342 | cmd = 'set_metadata_recursive("%s", "uid", %d, "gid", %d, ' \ 343 | '"dmode", 0%o, "fmode", 0%o, "capabilities", %s' \ 344 | % (fn, uid, gid, dmode, fmode, capabilities) 345 | if selabel is not None: 346 | cmd += ', "selabel", "%s"' % selabel 347 | cmd += ');' 348 | self.script.append(cmd) 349 | 350 | def MakeSymlinks(self, symlink_list): 351 | """Create symlinks, given a list of (dest, link) pairs.""" 352 | by_dest = {} 353 | for d, l in symlink_list: 354 | by_dest.setdefault(d, []).append(l) 355 | 356 | for dest, links in sorted(by_dest.iteritems()): 357 | cmd = ('symlink("%s", ' % (dest,) + 358 | ",\0".join(['"' + i + '"' for i in sorted(links)]) + ");") 359 | self.script.append(self.WordWrap(cmd)) 360 | 361 | def AppendExtra(self, extra): 362 | """Append text verbatim to the output script.""" 363 | self.script.append(extra) 364 | 365 | def Unmount(self, mount_point): 366 | self.script.append('unmount("%s");' % mount_point) 367 | self.mounts.remove(mount_point) 368 | 369 | def UnmountAll(self): 370 | for p in sorted(self.mounts): 371 | self.script.append('unmount("%s");' % (p,)) 372 | self.mounts = set() 373 | 374 | def AddToZip(self, input_zip, output_zip, input_path=None): 375 | """Write the accumulated script to the output_zip file. input_zip 376 | is used as the source for the 'updater' binary needed to run 377 | script. If input_path is not None, it will be used as a local 378 | path for the binary instead of input_zip.""" 379 | 380 | self.UnmountAll() 381 | 382 | common.ZipWriteStr(output_zip, "META-INF/com/google/android/updater-script", 383 | "\n".join(self.script) + "\n") 384 | 385 | if input_path is None: 386 | data = input_zip.read("OTA/bin/updater") 387 | else: 388 | data = open(input_path, "rb").read() 389 | common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary", 390 | data, perms=0o755) 391 | -------------------------------------------------------------------------------- /releasetools/getfilesysteminfo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/releasetools/getfilesysteminfo -------------------------------------------------------------------------------- /releasetools/miui_releasetools.py: -------------------------------------------------------------------------------- 1 | 2 | import common 3 | import copy 4 | import edify_generator 5 | 6 | def FullOTA_Assertions(info): 7 | info.script.Mount("/data") 8 | 9 | def IncrementalOTA_Assertions(info): 10 | info.script.Mount("/data") 11 | 12 | def PushBusybox(input_zip, output_zip, script): 13 | try: 14 | data = input_zip.read("OTA/bin/busybox") 15 | common.ZipWriteStr(output_zip, "META-INF/com/miui/busybox", data) 16 | script.AppendExtra("package_extract_file(\"META-INF/com/miui/busybox\", \"/tmp/busybox\");") 17 | script.SetPermissions("/tmp/busybox", 0, 0, 0555, None, None) 18 | except KeyError: 19 | print 'Ignore replace cert' 20 | 21 | def RemoveUseslessFiles(script): 22 | script.DeleteFiles(["/tmp/busybox"]) 23 | 24 | def ProcessSystemFormat(info): 25 | edify = info.script 26 | script_temp = edify_generator.EdifyGenerator(3, info.script.info) 27 | PushBusybox(info.input_zip, info.output_zip, script_temp) 28 | script_temp.AppendExtra("run_program(\"/tmp/busybox\", \"rm\", \"-rf\", \"/system\");") 29 | script_temp_str = "".join(script_temp.script).replace(";", ";\n").strip() 30 | format_system_line = 0 31 | mount_system_line = 0 32 | for i in xrange(len(edify.script)): 33 | if format_system_line > 0 and mount_system_line > 0: 34 | break 35 | if ");" in edify.script[i] and "format" in edify.script[i] and "/system" in edify.script[i]: 36 | format_system_line = i 37 | continue 38 | elif ");" in edify.script[i] and "mount" in edify.script[i] and "/system" in edify.script[i]: 39 | mount_system_line = i 40 | continue 41 | if mount_system_line > format_system_line > 0: 42 | edify.script[format_system_line] = edify.script[format_system_line].replace(edify.script[format_system_line], edify.script[mount_system_line]) 43 | edify.script[mount_system_line] = edify.script[mount_system_line].replace(edify.script[mount_system_line] , script_temp_str) 44 | elif format_system_line > mount_system_line > 0: 45 | edify.script[format_system_line] = edify.script[format_system_line].replace(edify.script[format_system_line], "") 46 | edify.script[mount_system_line] = edify.script[mount_system_line].replace(";", ";\n" + script_temp_str) 47 | else: 48 | PushBusybox(info.input_zip, info.output_zip, info.script) 49 | 50 | def FullOTA_InstallEnd(info): 51 | UnpackData(info.script) 52 | CopyDataFiles(info.input_zip, info.output_zip, info.script) 53 | ProcessSystemFormat(info) 54 | Replace_Cert(info.input_zip, info.output_zip, info.script) 55 | RemoveUseslessFiles(info.script) 56 | SetPermissions(info.script) 57 | RemoveAbandonedPreinstall(info.script) 58 | 59 | 60 | def IncrementalOTA_InstallEnd(info): 61 | UnpackData(info.script) 62 | Replace_Cert(info.target_zip, info.output_zip, info.script) 63 | SetPermissions(info.script) 64 | RemoveAbandonedPreinstall(info.script) 65 | 66 | def CopyDataFiles(input_zip, output_zip, script): 67 | """Copies files underneath data/miui in the input zip to the output zip.""" 68 | 69 | print "[MIUI CUST] OTA: copy data files" 70 | for info in input_zip.infolist(): 71 | if info.filename.startswith("DATA/miui/"): 72 | basefilename = info.filename[5:] 73 | info2 = copy.copy(info) 74 | info2.filename = "data/" + basefilename 75 | data = input_zip.read(info.filename) 76 | output_zip.writestr(info2, data) 77 | 78 | 79 | def UnpackData(script): 80 | script.UnpackPackageDir("data", "/data") 81 | 82 | 83 | def SetPermissions(script): 84 | print "[MIUI CUST] OTA: SetPermissions" 85 | SetPermissionsRecursive(script, "/data/miui", 1000, 1000, 0755, 0644) 86 | 87 | 88 | def SetPermissionsRecursive(script, d, gid, uid, dmod, fmod): 89 | try: 90 | script.SetPermissionsRecursive(d, gid, uid, dmod, fmod) 91 | except TypeError: 92 | script.SetPermissionsRecursive(d, gid, uid, dmod, fmod, None, None) 93 | 94 | 95 | def RemoveAbandonedPreinstall(script): 96 | script.AppendExtra("delete_recursive(\"/data/miui/preinstall_apps\");") 97 | script.AppendExtra("delete_recursive(\"/data/miui/cust/preinstall_apps\");") 98 | 99 | def Replace_Cert(input_zip, output_zip, script): 100 | try: 101 | data = input_zip.read("OTA/bin/replace_key") 102 | common.ZipWriteStr(output_zip, "META-INF/com/miui/replace_key", data) 103 | script.AppendExtra("package_extract_file(\"META-INF/com/miui/replace_key\", \"/tmp/replace_key\");") 104 | script.SetPermissions("/tmp/replace_key", 0, 0, 0555, None, None) 105 | script.AppendExtra("run_program(\"/sbin/sh\", \"/tmp/replace_key\");") 106 | script.DeleteFiles(["/tmp/replace_key"]) 107 | except KeyError: 108 | print 'Ignore replace cert' 109 | 110 | -------------------------------------------------------------------------------- /releasetools/ota_target_from_phone: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PWD=`pwd` 4 | TOOL_DIR=$PORT_ROOT/tools 5 | OTA_FROM_TARGET_FILES=$TOOL_DIR/releasetools/ota_from_target_files 6 | TARGET_FILES_TEMPLATE_DIR=$TOOL_DIR/target_files_template 7 | 8 | TMP_DIR=$PWD/out 9 | TARGET_FILES_DIR=$TMP_DIR/target_files 10 | RECOVERY_ETC_DIR=$TARGET_FILES_DIR/RECOVERY/RAMDISK/etc 11 | SYSTEM_DIR=$TARGET_FILES_DIR/SYSTEM 12 | META_DIR=$TARGET_FILES_DIR/META 13 | TARGET_FILES_ZIP=$TMP_DIR/target_files.zip 14 | 15 | OUTPUT_OTA_PACKAGE=$PWD/stockrom.zip 16 | OUTPUT_METADATA_DIR=$PWD/metadata 17 | 18 | FULL_OTA_PACKAGE=$2 19 | MODE=$1 20 | 21 | # prompt user 22 | function prompt_user { 23 | echo "ota_target_from_phone -n|-r [ota-package]" 24 | echo " -n: run this script in normal mode" 25 | echo " -r: run this script in recovery mode, if you can run adb in recovery mode, use this option" 26 | echo " ota-package: the stock full OTA package which already installed into your phone." 27 | echo " If you can't find a OTA package, this can be empty and we will generate" 28 | echo " a OTA package for you to use for our make process" 29 | echo 30 | echo "Before running this script, please ensure: " 31 | echo "(1) The phone is connected to PC and turn on USB Debug" 32 | echo "(2) The phone has a rooted kernel or have root privilege" 33 | echo 34 | echo "This script will generate two zip files under $OUTPUT_DIR: " 35 | echo "(1) target_files.zip: this is used to generate incremental OTA package" 36 | echo "(2) update.zip: OTA package you can use if you don't have one. This package is ok to install in recovery" 37 | echo 38 | } 39 | 40 | # copy the whole target_files_template dir 41 | function copy_target_files_template { 42 | echo "Copy target file template into current working directory" 43 | rm -rf $TARGET_FILES_DIR 44 | rm -f $TARGET_FILES_ZIP 45 | mkdir -p $TARGET_FILES_DIR 46 | cp -r $TARGET_FILES_TEMPLATE_DIR/* $TARGET_FILES_DIR 47 | } 48 | 49 | # wait for the device to be online or timeout 50 | function wait_for_device_online { 51 | echo "Wait for the device to be online..." 52 | 53 | local timeout=120 54 | while [ $timeout -gt 0 ] 55 | do 56 | if adb shell ls > /dev/null 57 | then 58 | break 59 | fi 60 | sleep 30 61 | timeout=$[$timeout - 30] 62 | done 63 | if [ $timeout -eq 0 ];then 64 | echo "Please ensure adb can find your device and then rerun this script." 65 | exit 1 66 | fi 67 | } 68 | 69 | function ask_for_boot_image { 70 | echo "Warning: the ota package will not contain bootimage!!!" 71 | echo "Maybe you forget to pass the ota-package parameter." 72 | answer="no" 73 | while [ 1 ] 74 | do 75 | echo -n "Are you sure this is really what you want(yes/no):" 76 | read answer 77 | if [ "$answer" == "no" ];then 78 | exit 0 79 | elif [ "$answer" == "yes" ];then 80 | return 81 | fi 82 | done 83 | } 84 | 85 | # In normal mode, extract the boot image from full ota package 86 | function extract_bootimage { 87 | if [ -z $FULL_OTA_PACKAGE ];then 88 | ask_for_boot_image 89 | return 90 | fi 91 | 92 | echo "Extract bootimage from full ota package" 93 | local tempdir=`mktemp -d dir.XXXXXX` 94 | unzip -q $FULL_OTA_PACKAGE -d $tempdir 95 | for file in boot.img zImage */boot.img */zImage 96 | do 97 | if [ -f $tempdir/$file ];then 98 | cp $tempdir/$file $TARGET_FILES_DIR/BOOTABLE_IMAGES/boot.img 99 | rm -rf $tempdir 100 | return 101 | fi 102 | done 103 | ask_for_boot_image 104 | } 105 | 106 | # In recovery mode, dump the boot image from device 107 | function dump_bootimage { 108 | echo "Dump bootimage from device" 109 | if [ -f dumpimage.sh ];then 110 | ./dumpimage.sh $TARGET_FILES_DIR/BOOTABLE_IMAGES 111 | else 112 | local info=`adb shell cat /etc/recovery.fstab | grep boot | sed -e "s/\s\+/:/g"` 113 | local fstype=`echo $info | cut -d":" -f2` 114 | 115 | if [ "$fstype" == "mtd" ]; then 116 | mtdn=`adb shell cat /proc/mtd | grep boot | cut -f1 -d":"` 117 | device=/dev/$fstype/$mtdn 118 | else 119 | device=`echo $info | cut -d":" -f3` 120 | fi 121 | adb pull $device $TARGET_FILES_DIR/BOOTABLE_IMAGES/boot.img 122 | fi 123 | } 124 | 125 | # In recovery mode, extract the recovery.fstab from device 126 | function extract_recovery_fstab { 127 | echo "Extract recovery.fstab from device" 128 | adb shell cat /etc/recovery.fstab | awk '{print $1 "\t" $2 "\t" $3}'> $RECOVERY_ETC_DIR/recovery.fstab 129 | } 130 | 131 | # In normal mode, build the recovery.fstab from device 132 | function build_recovery_fstab { 133 | if [ -f recovery.fstab ];then 134 | cp recovery.fstab $RECOVERY_ETC_DIR/recovery.fstab 135 | return 136 | elif [ -n "$FULL_OTA_PACKAGE" ];then 137 | echo $FULL_OTA_PACKAGE 138 | echo "You should provide a recovery.fstab file in your working directory." 139 | exit 1 140 | fi 141 | 142 | echo "Build recovery.fstab from device" 143 | IFS_OLD=$IFS 144 | IFS=$'\n' 145 | cat /dev/null > $RECOVERY_ETC_DIR/recovery.fstab 146 | for line in `adb shell cat /proc/mounts | grep -E "/system|/data|/cache" | cut -d " " -f1-3` 147 | do 148 | mount_fstype=`echo $line | cut -d " " -f2,3` 149 | device=`echo $line | cut -d " " -f1` 150 | echo $mount_fstype $device >> $RECOVERY_ETC_DIR/recovery.fstab 151 | done 152 | IFS=$IFS_OLD 153 | } 154 | 155 | # build apkcerts.txt 156 | function build_apkcerts { 157 | echo "Build apkcerts.txt" 158 | adb pull /data/system/packages.xml $TARGET_FILES_DIR 159 | python $TOOL_DIR/apkcerts.py $TARGET_FILES_DIR/packages.xml $META_DIR/apkcerts.txt 160 | for file in `ls $SYSTEM_DIR/framework/*.apk` 161 | do 162 | apk=`basename $file` 163 | echo "name=\"$apk\" certificate=\"build/target/product/security/platform.x509.pem\" private_key=\"build/target/product/security/platform.pk8\"" >> $META_DIR/apkcerts.txt 164 | done 165 | cat $META_DIR/apkcerts.txt | sort > $META_DIR/temp.txt 166 | mv $META_DIR/temp.txt $META_DIR/apkcerts.txt 167 | rm $TARGET_FILES_DIR/packages.xml 168 | } 169 | 170 | # build filesystem_config.txt from device 171 | function build_filesystem_config { 172 | echo "Run getfilesysteminfo to build filesystem_config.txt" 173 | if [ $ANDROID_PLATFORM -gt 19 ];then 174 | adb push $TOOL_DIR/target_files_template/OTA/bin/busybox /data/local/tmp/ 175 | adb shell chmod 755 /data/local/tmp/busybox 176 | bash $TOOL_DIR/get_filesystem_config --info /data/local/tmp/busybox | tee $META_DIR/filesystem_config.txt 177 | if [ $? -ne 0 ];then 178 | echo "Get file info failed" 179 | exit 1 180 | fi 181 | else 182 | adb push $TOOL_DIR/releasetools/getfilesysteminfo /system/xbin 183 | adb shell chmod 0777 /system/xbin/getfilesysteminfo 184 | adb shell /system/xbin/getfilesysteminfo --info /system >> $META_DIR/filesystem_config.txt 185 | fs_config=`cat $META_DIR/filesystem_config.txt | col -b | sed -e '/getfilesysteminfo/d'` 186 | OLD_IFS=$IFS 187 | IFS=$'\n' 188 | for line in $fs_config 189 | do 190 | echo $line | grep -q -e "\" && continue 191 | echo $line | grep -q -e "\" && continue 192 | echo $line >> $META_DIR/tmp.txt 193 | done 194 | IFS=$OLD_IFS 195 | cat $META_DIR/tmp.txt | sort > $META_DIR/filesystem_config.txt 196 | rm $META_DIR/tmp.txt 197 | fi 198 | } 199 | 200 | # recover the device files' symlink information 201 | function recover_symlink { 202 | echo "Run getfilesysteminfo and recoverylink.py to recover symlink" 203 | if [ $ANDROID_PLATFORM -gt 19 ];then 204 | bash $TOOL_DIR/get_filesystem_config --link /data/local/tmp/busybox | tee $SYSTEM_DIR/linkinfo.txt 205 | if [ $? -ne 0 ];then 206 | echo "Get file symlink failed" 207 | exit 1 208 | fi 209 | else 210 | adb shell /system/xbin/getfilesysteminfo --link /system | sed -e '/\/d;/\/d' | sort > $SYSTEM_DIR/linkinfo.txt 211 | adb shell rm /system/xbin/getfilesysteminfo 212 | fi 213 | python $TOOL_DIR/releasetools/recoverylink.py $TARGET_FILES_DIR 214 | adb shell rm /system/xbin/getfilesysteminfo 215 | } 216 | 217 | function remount_system_device { 218 | echo "Remount /system to be writable" 219 | 220 | if adb root | grep "cannot run" > /dev/null;then 221 | device=`adb shell cat /proc/mounts | grep "/system" | cut -d " " -f 1` 222 | echo "You don't have a rooted kernel. Please run the following command mannually" 223 | echo "(1) adb shell" 224 | echo "(2) su" 225 | echo "(3) mount -o remount,rw $device /system" 226 | echo "(3) chmod 0777 /system /system/*" 227 | echo 228 | 229 | answer="no" 230 | while [ $answer != "yes" ] 231 | do 232 | echo -n "If you finish running the above commands on your phone(yes/no):" 233 | read answer 234 | done 235 | if adb shell ls /system/xbin/getfilesysteminfo;then 236 | return 237 | else 238 | if adb push $TOOL_DIR/releasetools/getfilesysteminfo /system/xbin;then 239 | return 240 | else 241 | echo "Please double check your answer and if your phone has root privilege" 242 | exit 1 243 | fi 244 | fi 245 | else 246 | sleep 1 247 | adb remount 248 | fi 249 | sleep 1 250 | } 251 | 252 | # build the SYSTEM dir under target_files 253 | function build_SYSTEM { 254 | echo "Extract the whole /system from device" 255 | adb pull /system $SYSTEM_DIR 256 | find $SYSTEM_DIR -name su | xargs rm -f 257 | find $SYSTEM_DIR -name invoke-as | xargs rm -f 258 | remount_system_device 259 | build_filesystem_config 260 | recover_symlink 261 | } 262 | 263 | function deoat { 264 | if [ $ANDROID_PLATFORM -le 19 ];then 265 | return 266 | fi 267 | echo "Decode oat files" 268 | $TOOL_DIR/deoat.sh $TARGET_FILES_DIR 269 | } 270 | 271 | # compress the target_files dir into a zip file 272 | function zip_target_files { 273 | echo "Compress the target_files dir into zip file" 274 | cd $TARGET_FILES_DIR 275 | zip -q -r -y $TARGET_FILES_ZIP * 276 | cd - 277 | } 278 | 279 | # build a new full ota package 280 | function build_ota_package { 281 | echo "Build full ota package: $OUTPUT_OTA_PACKAGE" 282 | $OTA_FROM_TARGET_FILES -n -k $PORT_ROOT/build/security/testkey $TARGET_FILES_ZIP $OUTPUT_OTA_PACKAGE 283 | } 284 | 285 | function gen_metadata { 286 | echo "Generate metadata used to build target files..." 287 | local out=$OUTPUT_METADATA_DIR 288 | rm -rf $out 289 | mkdir -p $out 290 | 291 | cp -f $META_DIR/apkcerts.txt $out 292 | cp -f $META_DIR/filesystem_config.txt $out 293 | mv -f $SYSTEM_DIR/linkinfo.txt $out 294 | cp -f $RECOVERY_ETC_DIR/recovery.fstab $out 295 | } 296 | 297 | if [ $# -eq 0 ] || [ $# -gt 2 ];then 298 | prompt_user 299 | exit 1 300 | fi 301 | 302 | if [ "$MODE" != "-r" ] && [ "$MODE" != "-n" ];then 303 | prompt_user 304 | exit 1 305 | fi 306 | 307 | wait_for_device_online 308 | copy_target_files_template 309 | 310 | if [ "$MODE" == "-r" ];then 311 | dump_bootimage 312 | extract_recovery_fstab 313 | adb shell mount /system 314 | adb shell mount /data 315 | sleep 1 316 | else 317 | extract_bootimage 318 | build_recovery_fstab 319 | fi 320 | 321 | build_SYSTEM 322 | build_apkcerts 323 | gen_metadata 324 | deoat 325 | zip_target_files 326 | build_ota_package 327 | 328 | if [ "$MODE" == "-r" ];then 329 | adb shell umount /system 330 | fi 331 | -------------------------------------------------------------------------------- /releasetools/pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | 3 | # Specify a configuration file. 4 | #rcfile= 5 | 6 | # Python code to execute, usually for sys.path manipulation such as 7 | # pygtk.require(). 8 | #init-hook= 9 | 10 | # Profiled execution. 11 | profile=no 12 | 13 | # Add files or directories to the blacklist. They should be base names, not 14 | # paths. 15 | ignore=CVS 16 | 17 | # Pickle collected data for later comparisons. 18 | persistent=yes 19 | 20 | # List of plugins (as comma separated values of python modules names) to load, 21 | # usually to register additional checkers. 22 | load-plugins= 23 | 24 | # Use multiple processes to speed up Pylint. 25 | jobs=1 26 | 27 | # Allow loading of arbitrary C extensions. Extensions are imported into the 28 | # active Python interpreter and may run arbitrary code. 29 | unsafe-load-any-extension=no 30 | 31 | # A comma-separated list of package or module names from where C extensions may 32 | # be loaded. Extensions are loading into the active Python interpreter and may 33 | # run arbitrary code 34 | extension-pkg-whitelist= 35 | 36 | # Allow optimization of some AST trees. This will activate a peephole AST 37 | # optimizer, which will apply various small optimizations. For instance, it can 38 | # be used to obtain the result of joining multiple strings with the addition 39 | # operator. Joining a lot of strings can lead to a maximum recursion error in 40 | # Pylint and this flag can prevent that. It has one side effect, the resulting 41 | # AST will be different than the one from reality. 42 | optimize-ast=no 43 | 44 | 45 | [MESSAGES CONTROL] 46 | 47 | # Only show warnings with the listed confidence levels. Leave empty to show 48 | # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED 49 | confidence= 50 | 51 | # Enable the message, report, category or checker with the given id(s). You can 52 | # either give multiple identifier separated by comma (,) or put this option 53 | # multiple time. See also the "--disable" option for examples. 54 | #enable= 55 | 56 | # Disable the message, report, category or checker with the given id(s). You 57 | # can either give multiple identifiers separated by comma (,) or put this 58 | # option multiple times (only on the command line, not in the configuration 59 | # file where it should appear only once).You can also use "--disable=all" to 60 | # disable everything first and then reenable specific checks. For example, if 61 | # you want to run only the similarities checker, you can use "--disable=all 62 | # --enable=similarities". If you want to run only the classes checker, but have 63 | # no Warning level messages displayed, use"--disable=all --enable=classes 64 | # --disable=W" 65 | disable=invalid-name,missing-docstring,too-many-branches,too-many-locals,too-many-arguments,too-many-statements,duplicate-code,too-few-public-methods,too-many-instance-attributes,too-many-lines,too-many-public-methods,locally-disabled,fixme 66 | 67 | 68 | [REPORTS] 69 | 70 | # Set the output format. Available formats are text, parseable, colorized, msvs 71 | # (visual studio) and html. You can also give a reporter class, eg 72 | # mypackage.mymodule.MyReporterClass. 73 | output-format=text 74 | 75 | # Put messages in a separate file for each module / package specified on the 76 | # command line instead of printing them on stdout. Reports (if any) will be 77 | # written in a file name "pylint_global.[txt|html]". 78 | files-output=no 79 | 80 | # Tells whether to display a full report or only the messages 81 | reports=yes 82 | 83 | # Python expression which should return a note less than 10 (10 is the highest 84 | # note). You have access to the variables errors warning, statement which 85 | # respectively contain the number of errors / warnings messages and the total 86 | # number of statements analyzed. This is used by the global evaluation report 87 | # (RP0004). 88 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) 89 | 90 | # Add a comment according to your evaluation note. This is used by the global 91 | # evaluation report (RP0004). 92 | comment=no 93 | 94 | # Template used to display messages. This is a python new-style format string 95 | # used to format the message information. See doc for all details 96 | #msg-template= 97 | 98 | 99 | [SIMILARITIES] 100 | 101 | # Minimum lines number of a similarity. 102 | min-similarity-lines=4 103 | 104 | # Ignore comments when computing similarities. 105 | ignore-comments=yes 106 | 107 | # Ignore docstrings when computing similarities. 108 | ignore-docstrings=yes 109 | 110 | # Ignore imports when computing similarities. 111 | ignore-imports=no 112 | 113 | 114 | [TYPECHECK] 115 | 116 | # Tells whether missing members accessed in mixin class should be ignored. A 117 | # mixin class is detected if its name ends with "mixin" (case insensitive). 118 | ignore-mixin-members=yes 119 | 120 | # List of module names for which member attributes should not be checked 121 | # (useful for modules/projects where namespaces are manipulated during runtime 122 | # and thus existing member attributes cannot be deduced by static analysis 123 | ignored-modules= 124 | 125 | # List of classes names for which member attributes should not be checked 126 | # (useful for classes with attributes dynamically set). 127 | ignored-classes=SQLObject 128 | 129 | # When zope mode is activated, add a predefined set of Zope acquired attributes 130 | # to generated-members. 131 | zope=no 132 | 133 | # List of members which are set dynamically and missed by pylint inference 134 | # system, and so shouldn't trigger E0201 when accessed. Python regular 135 | # expressions are accepted. 136 | generated-members=REQUEST,acl_users,aq_parent 137 | 138 | 139 | [MISCELLANEOUS] 140 | 141 | # List of note tags to take in consideration, separated by a comma. 142 | notes=FIXME,XXX,TODO 143 | 144 | 145 | [BASIC] 146 | 147 | # Required attributes for module, separated by a comma 148 | required-attributes= 149 | 150 | # List of builtins function names that should not be used, separated by a comma 151 | bad-functions=map,filter,input 152 | 153 | # Good variable names which should always be accepted, separated by a comma 154 | good-names=i,j,k,ex,Run,_ 155 | 156 | # Bad variable names which should always be refused, separated by a comma 157 | bad-names=foo,bar,baz,toto,tutu,tata 158 | 159 | # Colon-delimited sets of names that determine each other's naming style when 160 | # the name regexes allow several styles. 161 | name-group= 162 | 163 | # Include a hint for the correct naming format with invalid-name 164 | include-naming-hint=no 165 | 166 | # Regular expression matching correct function names 167 | function-rgx=[a-z_][a-z0-9_]{2,30}$ 168 | 169 | # Naming hint for function names 170 | function-name-hint=[a-z_][a-z0-9_]{2,30}$ 171 | 172 | # Regular expression matching correct variable names 173 | variable-rgx=[a-z_][a-z0-9_]{2,30}$ 174 | 175 | # Naming hint for variable names 176 | variable-name-hint=[a-z_][a-z0-9_]{2,30}$ 177 | 178 | # Regular expression matching correct constant names 179 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 180 | 181 | # Naming hint for constant names 182 | const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ 183 | 184 | # Regular expression matching correct attribute names 185 | attr-rgx=[a-z_][a-z0-9_]{2,30}$ 186 | 187 | # Naming hint for attribute names 188 | attr-name-hint=[a-z_][a-z0-9_]{2,30}$ 189 | 190 | # Regular expression matching correct argument names 191 | argument-rgx=[a-z_][a-z0-9_]{2,30}$ 192 | 193 | # Naming hint for argument names 194 | argument-name-hint=[a-z_][a-z0-9_]{2,30}$ 195 | 196 | # Regular expression matching correct class attribute names 197 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 198 | 199 | # Naming hint for class attribute names 200 | class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ 201 | 202 | # Regular expression matching correct inline iteration names 203 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ 204 | 205 | # Naming hint for inline iteration names 206 | inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ 207 | 208 | # Regular expression matching correct class names 209 | class-rgx=[A-Z_][a-zA-Z0-9]+$ 210 | 211 | # Naming hint for class names 212 | class-name-hint=[A-Z_][a-zA-Z0-9]+$ 213 | 214 | # Regular expression matching correct module names 215 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 216 | 217 | # Naming hint for module names 218 | module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ 219 | 220 | # Regular expression matching correct method names 221 | method-rgx=[a-z_][a-z0-9_]{2,30}$ 222 | 223 | # Naming hint for method names 224 | method-name-hint=[a-z_][a-z0-9_]{2,30}$ 225 | 226 | # Regular expression which should only match function or class names that do 227 | # not require a docstring. 228 | no-docstring-rgx=__.*__ 229 | 230 | # Minimum line length for functions/classes that require docstrings, shorter 231 | # ones are exempt. 232 | docstring-min-length=-1 233 | 234 | 235 | [SPELLING] 236 | 237 | # Spelling dictionary name. Available dictionaries: none. To make it working 238 | # install python-enchant package. 239 | spelling-dict= 240 | 241 | # List of comma separated words that should not be checked. 242 | spelling-ignore-words= 243 | 244 | # A path to a file that contains private dictionary; one word per line. 245 | spelling-private-dict-file= 246 | 247 | # Tells whether to store unknown words to indicated private dictionary in 248 | # --spelling-private-dict-file option instead of raising a message. 249 | spelling-store-unknown-words=no 250 | 251 | 252 | [FORMAT] 253 | 254 | # Maximum number of characters on a single line. 255 | max-line-length=80 256 | 257 | # Regexp for a line that is allowed to be longer than the limit. 258 | ignore-long-lines=^\s*(# )??$ 259 | 260 | # Allow the body of an if to be on the same line as the test if there is no 261 | # else. 262 | single-line-if-stmt=no 263 | 264 | # List of optional constructs for which whitespace checking is disabled 265 | no-space-check=trailing-comma,dict-separator 266 | 267 | # Maximum number of lines in a module 268 | max-module-lines=1000 269 | 270 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 271 | # tab). 272 | indent-string=' ' 273 | 274 | # Number of spaces of indent required inside a hanging or continued line. 275 | indent-after-paren=4 276 | 277 | # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. 278 | expected-line-ending-format=LF 279 | 280 | 281 | [LOGGING] 282 | 283 | # Logging modules to check that the string format arguments are in logging 284 | # function parameter format 285 | logging-modules=logging 286 | 287 | 288 | [VARIABLES] 289 | 290 | # Tells whether we should check for unused import in __init__ files. 291 | init-import=no 292 | 293 | # A regular expression matching the name of dummy variables (i.e. expectedly 294 | # not used). 295 | dummy-variables-rgx=_$|dummy 296 | 297 | # List of additional names supposed to be defined in builtins. Remember that 298 | # you should avoid to define new builtins when possible. 299 | additional-builtins= 300 | 301 | # List of strings which can identify a callback function by name. A callback 302 | # name must start or end with one of those strings. 303 | callbacks=cb_,_cb 304 | 305 | 306 | [DESIGN] 307 | 308 | # Maximum number of arguments for function / method 309 | max-args=5 310 | 311 | # Argument names that match this expression will be ignored. Default to name 312 | # with leading underscore 313 | ignored-argument-names=_.* 314 | 315 | # Maximum number of locals for function / method body 316 | max-locals=15 317 | 318 | # Maximum number of return / yield for function / method body 319 | max-returns=6 320 | 321 | # Maximum number of branch for function / method body 322 | max-branches=12 323 | 324 | # Maximum number of statements in function / method body 325 | max-statements=50 326 | 327 | # Maximum number of parents for a class (see R0901). 328 | max-parents=7 329 | 330 | # Maximum number of attributes for a class (see R0902). 331 | max-attributes=7 332 | 333 | # Minimum number of public methods for a class (see R0903). 334 | min-public-methods=2 335 | 336 | # Maximum number of public methods for a class (see R0904). 337 | max-public-methods=20 338 | 339 | 340 | [IMPORTS] 341 | 342 | # Deprecated modules which should not be used, separated by a comma 343 | deprecated-modules=regsub,TERMIOS,Bastion,rexec 344 | 345 | # Create a graph of every (i.e. internal and external) dependencies in the 346 | # given file (report RP0402 must not be disabled) 347 | import-graph= 348 | 349 | # Create a graph of external dependencies in the given file (report RP0402 must 350 | # not be disabled) 351 | ext-import-graph= 352 | 353 | # Create a graph of internal dependencies in the given file (report RP0402 must 354 | # not be disabled) 355 | int-import-graph= 356 | 357 | 358 | [CLASSES] 359 | 360 | # List of interface methods to ignore, separated by a comma. This is used for 361 | # instance to not check methods defines in Zope's Interface base class. 362 | ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by 363 | 364 | # List of method names used to declare (i.e. assign) instance attributes. 365 | defining-attr-methods=__init__,__new__,setUp 366 | 367 | # List of valid names for the first argument in a class method. 368 | valid-classmethod-first-arg=cls 369 | 370 | # List of valid names for the first argument in a metaclass class method. 371 | valid-metaclass-classmethod-first-arg=mcs 372 | 373 | # List of member names, which should be excluded from the protected access 374 | # warning. 375 | exclude-protected=_asdict,_fields,_replace,_source,_make 376 | 377 | 378 | [EXCEPTIONS] 379 | 380 | # Exceptions that will emit a warning when being caught. Defaults to 381 | # "Exception" 382 | overgeneral-exceptions=Exception 383 | -------------------------------------------------------------------------------- /releasetools/rangelib.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2014 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from __future__ import print_function 16 | import heapq 17 | import itertools 18 | 19 | __all__ = ["RangeSet"] 20 | 21 | class RangeSet(object): 22 | """A RangeSet represents a set of nonoverlapping ranges on the 23 | integers (ie, a set of integers, but efficient when the set contains 24 | lots of runs.""" 25 | 26 | def __init__(self, data=None): 27 | self.monotonic = False 28 | if isinstance(data, str): 29 | self._parse_internal(data) 30 | elif data: 31 | self.data = tuple(self._remove_pairs(data)) 32 | else: 33 | self.data = () 34 | 35 | def __iter__(self): 36 | for i in range(0, len(self.data), 2): 37 | yield self.data[i:i+2] 38 | 39 | def __eq__(self, other): 40 | return self.data == other.data 41 | def __ne__(self, other): 42 | return self.data != other.data 43 | def __nonzero__(self): 44 | return bool(self.data) 45 | 46 | def __str__(self): 47 | if not self.data: 48 | return "empty" 49 | else: 50 | return self.to_string() 51 | 52 | def __repr__(self): 53 | return '' 54 | 55 | @classmethod 56 | def parse(cls, text): 57 | """Parse a text string consisting of a space-separated list of 58 | blocks and ranges, eg "10-20 30 35-40". Ranges are interpreted to 59 | include both their ends (so the above example represents 18 60 | individual blocks. Returns a RangeSet object. 61 | 62 | If the input has all its blocks in increasing order, then returned 63 | RangeSet will have an extra attribute 'monotonic' that is set to 64 | True. For example the input "10-20 30" is monotonic, but the input 65 | "15-20 30 10-14" is not, even though they represent the same set 66 | of blocks (and the two RangeSets will compare equal with ==). 67 | """ 68 | return cls(text) 69 | 70 | def _parse_internal(self, text): 71 | data = [] 72 | last = -1 73 | monotonic = True 74 | for p in text.split(): 75 | if "-" in p: 76 | s, e = p.split("-") 77 | data.append(int(s)) 78 | data.append(int(e)+1) 79 | if last <= s <= e: 80 | last = e 81 | else: 82 | monotonic = False 83 | else: 84 | s = int(p) 85 | data.append(s) 86 | data.append(s+1) 87 | if last <= s: 88 | last = s+1 89 | else: 90 | monotonic = True 91 | data.sort() 92 | self.data = tuple(self._remove_pairs(data)) 93 | self.monotonic = monotonic 94 | 95 | @staticmethod 96 | def _remove_pairs(source): 97 | last = None 98 | for i in source: 99 | if i == last: 100 | last = None 101 | else: 102 | if last is not None: 103 | yield last 104 | last = i 105 | if last is not None: 106 | yield last 107 | 108 | def to_string(self): 109 | out = [] 110 | for i in range(0, len(self.data), 2): 111 | s, e = self.data[i:i+2] 112 | if e == s+1: 113 | out.append(str(s)) 114 | else: 115 | out.append(str(s) + "-" + str(e-1)) 116 | return " ".join(out) 117 | 118 | def to_string_raw(self): 119 | return str(len(self.data)) + "," + ",".join(str(i) for i in self.data) 120 | 121 | def union(self, other): 122 | """Return a new RangeSet representing the union of this RangeSet 123 | with the argument. 124 | 125 | >>> RangeSet("10-19 30-34").union(RangeSet("18-29")) 126 | 127 | >>> RangeSet("10-19 30-34").union(RangeSet("22 32")) 128 | 129 | """ 130 | out = [] 131 | z = 0 132 | for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))), 133 | zip(other.data, itertools.cycle((+1, -1)))): 134 | if (z == 0 and d == 1) or (z == 1 and d == -1): 135 | out.append(p) 136 | z += d 137 | return RangeSet(data=out) 138 | 139 | def intersect(self, other): 140 | """Return a new RangeSet representing the intersection of this 141 | RangeSet with the argument. 142 | 143 | >>> RangeSet("10-19 30-34").intersect(RangeSet("18-32")) 144 | 145 | >>> RangeSet("10-19 30-34").intersect(RangeSet("22-28")) 146 | 147 | """ 148 | out = [] 149 | z = 0 150 | for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))), 151 | zip(other.data, itertools.cycle((+1, -1)))): 152 | if (z == 1 and d == 1) or (z == 2 and d == -1): 153 | out.append(p) 154 | z += d 155 | return RangeSet(data=out) 156 | 157 | def subtract(self, other): 158 | """Return a new RangeSet representing subtracting the argument 159 | from this RangeSet. 160 | 161 | >>> RangeSet("10-19 30-34").subtract(RangeSet("18-32")) 162 | 163 | >>> RangeSet("10-19 30-34").subtract(RangeSet("22-28")) 164 | 165 | """ 166 | 167 | out = [] 168 | z = 0 169 | for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))), 170 | zip(other.data, itertools.cycle((-1, +1)))): 171 | if (z == 0 and d == 1) or (z == 1 and d == -1): 172 | out.append(p) 173 | z += d 174 | return RangeSet(data=out) 175 | 176 | def overlaps(self, other): 177 | """Returns true if the argument has a nonempty overlap with this 178 | RangeSet. 179 | 180 | >>> RangeSet("10-19 30-34").overlaps(RangeSet("18-32")) 181 | True 182 | >>> RangeSet("10-19 30-34").overlaps(RangeSet("22-28")) 183 | False 184 | """ 185 | 186 | # This is like intersect, but we can stop as soon as we discover the 187 | # output is going to be nonempty. 188 | z = 0 189 | for _, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))), 190 | zip(other.data, itertools.cycle((+1, -1)))): 191 | if (z == 1 and d == 1) or (z == 2 and d == -1): 192 | return True 193 | z += d 194 | return False 195 | 196 | def size(self): 197 | """Returns the total size of the RangeSet (ie, how many integers 198 | are in the set). 199 | 200 | >>> RangeSet("10-19 30-34").size() 201 | 15 202 | """ 203 | 204 | total = 0 205 | for i, p in enumerate(self.data): 206 | if i % 2: 207 | total += p 208 | else: 209 | total -= p 210 | return total 211 | 212 | def map_within(self, other): 213 | """'other' should be a subset of 'self'. Returns a RangeSet 214 | representing what 'other' would get translated to if the integers 215 | of 'self' were translated down to be contiguous starting at zero. 216 | 217 | >>> RangeSet("0-9").map_within(RangeSet("3-4")) 218 | 219 | >>> RangeSet("10-19").map_within(RangeSet("13-14")) 220 | 221 | >>> RangeSet("10-19 30-39").map_within(RangeSet("17-19 30-32")) 222 | 223 | >>> RangeSet("10-19 30-39").map_within(RangeSet("12-13 17-19 30-32")) 224 | 225 | """ 226 | 227 | out = [] 228 | offset = 0 229 | start = None 230 | for p, d in heapq.merge(zip(self.data, itertools.cycle((-5, +5))), 231 | zip(other.data, itertools.cycle((-1, +1)))): 232 | if d == -5: 233 | start = p 234 | elif d == +5: 235 | offset += p-start 236 | start = None 237 | else: 238 | out.append(offset + p - start) 239 | return RangeSet(data=out) 240 | 241 | def extend(self, n): 242 | """Extend the RangeSet by 'n' blocks. 243 | 244 | The lower bound is guaranteed to be non-negative. 245 | 246 | >>> RangeSet("0-9").extend(1) 247 | 248 | >>> RangeSet("10-19").extend(15) 249 | 250 | >>> RangeSet("10-19 30-39").extend(4) 251 | 252 | >>> RangeSet("10-19 30-39").extend(10) 253 | 254 | """ 255 | out = self 256 | for i in range(0, len(self.data), 2): 257 | s, e = self.data[i:i+2] 258 | s1 = max(0, s - n) 259 | e1 = e + n 260 | out = out.union(RangeSet(str(s1) + "-" + str(e1-1))) 261 | return out 262 | 263 | 264 | if __name__ == "__main__": 265 | import doctest 266 | doctest.testmod() 267 | -------------------------------------------------------------------------------- /releasetools/recoverylink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import os 3 | import sys 4 | 5 | path = sys.argv[1] 6 | linkfile_path = path + '/SYSTEM/linkinfo.txt' 7 | #print linkfile_path 8 | 9 | try: 10 | file_object = open(linkfile_path) 11 | linelist = file_object.read( ).split() 12 | for line in linelist: 13 | line = line.rstrip() 14 | filepath = line.split('|') 15 | link_name = filepath[0].replace('system', 'SYSTEM') 16 | target = filepath[1] 17 | cmd = 'cd ' + path + ';' + 'mkdir -p ' + os.path.dirname(link_name) + ';' + 'ln -sf ' + target + ' ' + link_name + ';' 18 | print cmd 19 | os.popen(cmd) 20 | except IOError: 21 | print r"%s isn't exist" % linkfile_path 22 | sys.exit(1) 23 | file_object.close( ) 24 | print r"Recovery link files success" 25 | sys.exit(0) 26 | -------------------------------------------------------------------------------- /releasetools/sign_target_files_apks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (C) 2008 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | """ 18 | Signs all the APK files in a target-files zipfile, producing a new 19 | target-files zip. 20 | 21 | Usage: sign_target_files_apks [flags] input_target_files output_target_files 22 | 23 | -e (--extra_apks) 24 | Add extra APK name/key pairs as though they appeared in 25 | apkcerts.txt (so mappings specified by -k and -d are applied). 26 | Keys specified in -e override any value for that app contained 27 | in the apkcerts.txt file. Option may be repeated to give 28 | multiple extra packages. 29 | 30 | -k (--key_mapping) 31 | Add a mapping from the key name as specified in apkcerts.txt (the 32 | src_key) to the real key you wish to sign the package with 33 | (dest_key). Option may be repeated to give multiple key 34 | mappings. 35 | 36 | -d (--default_key_mappings) 37 | Set up the following key mappings: 38 | 39 | $devkey/devkey ==> $dir/releasekey 40 | $devkey/testkey ==> $dir/releasekey 41 | $devkey/media ==> $dir/media 42 | $devkey/shared ==> $dir/shared 43 | $devkey/platform ==> $dir/platform 44 | 45 | where $devkey is the directory part of the value of 46 | default_system_dev_certificate from the input target-files's 47 | META/misc_info.txt. (Defaulting to "build/target/product/security" 48 | if the value is not present in misc_info. 49 | 50 | -d and -k options are added to the set of mappings in the order 51 | in which they appear on the command line. 52 | 53 | -o (--replace_ota_keys) 54 | Replace the certificate (public key) used by OTA package 55 | verification with the one specified in the input target_files 56 | zip (in the META/otakeys.txt file). Key remapping (-k and -d) 57 | is performed on this key. 58 | 59 | -t (--tag_changes) <+tag>,<-tag>,... 60 | Comma-separated list of changes to make to the set of tags (in 61 | the last component of the build fingerprint). Prefix each with 62 | '+' or '-' to indicate whether that tag should be added or 63 | removed. Changes are processed in the order they appear. 64 | Default value is "-test-keys,-dev-keys,+release-keys". 65 | 66 | """ 67 | 68 | import sys 69 | 70 | if sys.hexversion < 0x02040000: 71 | print >> sys.stderr, "Python 2.4 or newer is required." 72 | sys.exit(1) 73 | 74 | import cStringIO 75 | import copy 76 | import os 77 | import re 78 | import subprocess 79 | import tempfile 80 | import zipfile 81 | 82 | import common 83 | 84 | OPTIONS = common.OPTIONS 85 | 86 | OPTIONS.extra_apks = {} 87 | OPTIONS.key_map = {} 88 | OPTIONS.replace_ota_keys = False 89 | OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys") 90 | 91 | def GetApkCerts(tf_zip): 92 | certmap = common.ReadApkCerts(tf_zip) 93 | 94 | # apply the key remapping to the contents of the file 95 | for apk, cert in certmap.iteritems(): 96 | certmap[apk] = OPTIONS.key_map.get(cert, cert) 97 | 98 | # apply all the -e options, overriding anything in the file 99 | for apk, cert in OPTIONS.extra_apks.iteritems(): 100 | if not cert: 101 | cert = "PRESIGNED" 102 | certmap[apk] = OPTIONS.key_map.get(cert, cert) 103 | 104 | return certmap 105 | 106 | 107 | def CheckAllApksSigned(input_tf_zip, apk_key_map): 108 | """Check that all the APKs we want to sign have keys specified, and 109 | error out if they don't.""" 110 | unknown_apks = [] 111 | for info in input_tf_zip.infolist(): 112 | if info.filename.endswith(".apk"): 113 | name = os.path.basename(info.filename) 114 | if name not in apk_key_map: 115 | unknown_apks.append(name) 116 | if unknown_apks: 117 | print "ERROR: no key specified for:\n\n ", 118 | print "\n ".join(unknown_apks) 119 | print "\nUse '-e =' to specify a key (which may be an" 120 | print "empty string to not sign this apk)." 121 | sys.exit(1) 122 | 123 | 124 | def SignApk(data, keyname, pw): 125 | unsigned = tempfile.NamedTemporaryFile() 126 | unsigned.write(data) 127 | unsigned.flush() 128 | 129 | signed = tempfile.NamedTemporaryFile() 130 | 131 | common.SignFile(unsigned.name, signed.name, keyname, pw, align=4) 132 | 133 | data = signed.read() 134 | unsigned.close() 135 | signed.close() 136 | 137 | return data 138 | 139 | 140 | def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): 141 | maxsize = max([len(os.path.basename(i.filename)) 142 | for i in input_tf_zip.infolist() 143 | if i.filename.endswith('.apk')]) 144 | 145 | for info in input_tf_zip.infolist(): 146 | data = input_tf_zip.read(info.filename) 147 | out_info = copy.copy(info) 148 | if info.filename.endswith(".apk"): 149 | name = os.path.basename(info.filename) 150 | key = apk_key_map[name] 151 | if key not in common.SPECIAL_CERT_STRINGS: 152 | print " signing: %-*s (%s)" % (maxsize, name, key) 153 | signed_data = SignApk(data, key, key_passwords[key]) 154 | output_tf_zip.writestr(out_info, signed_data) 155 | else: 156 | # an APK we're not supposed to sign. 157 | print "NOT signing: %s" % (name,) 158 | output_tf_zip.writestr(out_info, data) 159 | elif info.filename in ("SYSTEM/build.prop", 160 | "RECOVERY/RAMDISK/default.prop"): 161 | print "rewriting %s:" % (info.filename,) 162 | new_data = RewriteProps(data) 163 | output_tf_zip.writestr(out_info, new_data) 164 | else: 165 | # a non-APK file; copy it verbatim 166 | output_tf_zip.writestr(out_info, data) 167 | 168 | 169 | def EditTags(tags): 170 | """Given a string containing comma-separated tags, apply the edits 171 | specified in OPTIONS.tag_changes and return the updated string.""" 172 | tags = set(tags.split(",")) 173 | for ch in OPTIONS.tag_changes: 174 | if ch[0] == "-": 175 | tags.discard(ch[1:]) 176 | elif ch[0] == "+": 177 | tags.add(ch[1:]) 178 | return ",".join(sorted(tags)) 179 | 180 | 181 | def RewriteProps(data): 182 | output = [] 183 | for line in data.split("\n"): 184 | line = line.strip() 185 | original_line = line 186 | if line and line[0] != '#' and "=" in line: 187 | key, value = line.split("=", 1) 188 | if key == "ro.build.fingerprint": 189 | pieces = value.split("/") 190 | pieces[-1] = EditTags(pieces[-1]) 191 | value = "/".join(pieces) 192 | elif key == "ro.build.description": 193 | pieces = value.split(" ") 194 | assert len(pieces) == 5 195 | pieces[-1] = EditTags(pieces[-1]) 196 | value = " ".join(pieces) 197 | elif key == "ro.build.tags": 198 | value = EditTags(value) 199 | line = key + "=" + value 200 | if line != original_line: 201 | print " replace: ", original_line 202 | print " with: ", line 203 | output.append(line) 204 | return "\n".join(output) + "\n" 205 | 206 | 207 | def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): 208 | try: 209 | keylist = input_tf_zip.read("META/otakeys.txt").split() 210 | except KeyError: 211 | raise ExternalError("can't read META/otakeys.txt from input") 212 | 213 | extra_recovery_keys = misc_info.get("extra_recovery_keys", None) 214 | if extra_recovery_keys: 215 | extra_recovery_keys = [OPTIONS.key_map.get(k, k) + ".x509.pem" 216 | for k in extra_recovery_keys.split()] 217 | if extra_recovery_keys: 218 | print "extra recovery-only key(s): " + ", ".join(extra_recovery_keys) 219 | else: 220 | extra_recovery_keys = [] 221 | 222 | mapped_keys = [] 223 | for k in keylist: 224 | m = re.match(r"^(.*)\.x509\.pem$", k) 225 | if not m: 226 | raise ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,)) 227 | k = m.group(1) 228 | mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem") 229 | 230 | if mapped_keys: 231 | print "using:\n ", "\n ".join(mapped_keys) 232 | print "for OTA package verification" 233 | else: 234 | devkey = misc_info.get("default_system_dev_certificate", 235 | "build/target/product/security/testkey") 236 | mapped_keys.append( 237 | OPTIONS.key_map.get(devkey, devkey) + ".x509.pem") 238 | print "META/otakeys.txt has no keys; using", mapped_keys[0] 239 | 240 | # recovery uses a version of the key that has been slightly 241 | # predigested (by DumpPublicKey.java) and put in res/keys. 242 | # extra_recovery_keys are used only in recovery. 243 | 244 | p = common.Run(["java", "-jar", 245 | os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")] 246 | + mapped_keys + extra_recovery_keys, 247 | stdout=subprocess.PIPE) 248 | data, _ = p.communicate() 249 | if p.returncode != 0: 250 | raise ExternalError("failed to run dumpkeys") 251 | common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data) 252 | 253 | # SystemUpdateActivity uses the x509.pem version of the keys, but 254 | # put into a zipfile system/etc/security/otacerts.zip. 255 | # We DO NOT include the extra_recovery_keys (if any) here. 256 | 257 | tempfile = cStringIO.StringIO() 258 | certs_zip = zipfile.ZipFile(tempfile, "w") 259 | for k in mapped_keys: 260 | certs_zip.write(k) 261 | certs_zip.close() 262 | common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", 263 | tempfile.getvalue()) 264 | 265 | 266 | def BuildKeyMap(misc_info, key_mapping_options): 267 | for s, d in key_mapping_options: 268 | if s is None: # -d option 269 | devkey = misc_info.get("default_system_dev_certificate", 270 | "build/target/product/security/testkey") 271 | devkeydir = os.path.dirname(devkey) 272 | 273 | OPTIONS.key_map.update({ 274 | devkeydir + "/testkey": d + "/testkey", 275 | devkeydir + "/devkey": d + "/testkey", 276 | devkeydir + "/media": d + "/media", 277 | devkeydir + "/shared": d + "/shared", 278 | devkeydir + "/platform": d + "/platform", 279 | }) 280 | devkeydir = os.path.dirname("cts/tests/appsecurity-tests/certs/cts-testkey1") 281 | OPTIONS.key_map.update({ 282 | devkeydir + "/cts-testkey1": d + "/testkey", 283 | devkeydir + "/cts-testkey2": d + "/testkey", 284 | }) 285 | else: 286 | OPTIONS.key_map[s] = d 287 | 288 | 289 | def main(argv): 290 | 291 | key_mapping_options = [] 292 | 293 | def option_handler(o, a): 294 | if o in ("-e", "--extra_apks"): 295 | names, key = a.split("=") 296 | names = names.split(",") 297 | for n in names: 298 | OPTIONS.extra_apks[n] = key 299 | elif o in ("-d", "--default_key_mappings"): 300 | key_mapping_options.append((None, a)) 301 | elif o in ("-k", "--key_mapping"): 302 | key_mapping_options.append(a.split("=", 1)) 303 | elif o in ("-o", "--replace_ota_keys"): 304 | OPTIONS.replace_ota_keys = True 305 | elif o in ("-t", "--tag_changes"): 306 | new = [] 307 | for i in a.split(","): 308 | i = i.strip() 309 | if not i or i[0] not in "-+": 310 | raise ValueError("Bad tag change '%s'" % (i,)) 311 | new.append(i[0] + i[1:].strip()) 312 | OPTIONS.tag_changes = tuple(new) 313 | else: 314 | return False 315 | return True 316 | 317 | args = common.ParseOptions(argv, __doc__, 318 | extra_opts="e:d:k:ot:", 319 | extra_long_opts=["extra_apks=", 320 | "default_key_mappings=", 321 | "key_mapping=", 322 | "replace_ota_keys", 323 | "tag_changes="], 324 | extra_option_handler=option_handler) 325 | 326 | if len(args) != 2: 327 | common.Usage(__doc__) 328 | sys.exit(1) 329 | 330 | input_zip = zipfile.ZipFile(args[0], "r") 331 | output_zip = zipfile.ZipFile(args[1], "w") 332 | 333 | misc_info = common.LoadInfoDict(input_zip) 334 | 335 | BuildKeyMap(misc_info, key_mapping_options) 336 | 337 | apk_key_map = GetApkCerts(input_zip) 338 | CheckAllApksSigned(input_zip, apk_key_map) 339 | 340 | key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) 341 | SignApks(input_zip, output_zip, apk_key_map, key_passwords) 342 | 343 | if OPTIONS.replace_ota_keys: 344 | ReplaceOtaKeys(input_zip, output_zip, misc_info) 345 | 346 | input_zip.close() 347 | output_zip.close() 348 | 349 | print "done." 350 | 351 | 352 | if __name__ == '__main__': 353 | try: 354 | main(sys.argv[1:]) 355 | except common.ExternalError, e: 356 | print 357 | print " ERROR: %s" % (e,) 358 | print 359 | sys.exit(1) 360 | -------------------------------------------------------------------------------- /releasetools/sparse_img.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2014 The Android Open Source Project 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import bisect 16 | import os 17 | import struct 18 | from hashlib import sha1 19 | 20 | import rangelib 21 | 22 | 23 | class SparseImage(object): 24 | """Wraps a sparse image file into an image object. 25 | 26 | Wraps a sparse image file (and optional file map and clobbered_blocks) into 27 | an image object suitable for passing to BlockImageDiff. file_map contains 28 | the mapping between files and their blocks. clobbered_blocks contains the set 29 | of blocks that should be always written to the target regardless of the old 30 | contents (i.e. copying instead of patching). clobbered_blocks should be in 31 | the form of a string like "0" or "0 1-5 8". 32 | """ 33 | 34 | def __init__(self, simg_fn, file_map_fn=None, clobbered_blocks=None): 35 | self.simg_f = f = open(simg_fn, "rb") 36 | 37 | header_bin = f.read(28) 38 | header = struct.unpack("> 2)) 170 | to_read -= this_read 171 | 172 | while to_read > 0: 173 | # continue with following chunks if this range spans multiple chunks. 174 | idx += 1 175 | chunk_start, chunk_len, filepos, fill_data = self.offset_map[idx] 176 | this_read = min(chunk_len, to_read) 177 | if filepos is not None: 178 | f.seek(filepos, os.SEEK_SET) 179 | yield f.read(this_read * self.blocksize) 180 | else: 181 | yield fill_data * (this_read * (self.blocksize >> 2)) 182 | to_read -= this_read 183 | 184 | def LoadFileBlockMap(self, fn, clobbered_blocks): 185 | remaining = self.care_map 186 | self.file_map = out = {} 187 | 188 | with open(fn) as f: 189 | for line in f: 190 | fn, ranges = line.split(None, 1) 191 | ranges = rangelib.RangeSet.parse(ranges) 192 | out[fn] = ranges 193 | assert ranges.size() == ranges.intersect(remaining).size() 194 | 195 | # Currently we assume that blocks in clobbered_blocks are not part of 196 | # any file. 197 | assert not clobbered_blocks.overlaps(ranges) 198 | remaining = remaining.subtract(ranges) 199 | 200 | remaining = remaining.subtract(clobbered_blocks) 201 | 202 | # For all the remaining blocks in the care_map (ie, those that 203 | # aren't part of the data for any file nor part of the clobbered_blocks), 204 | # divide them into blocks that are all zero and blocks that aren't. 205 | # (Zero blocks are handled specially because (1) there are usually 206 | # a lot of them and (2) bsdiff handles files with long sequences of 207 | # repeated bytes especially poorly.) 208 | 209 | zero_blocks = [] 210 | nonzero_blocks = [] 211 | reference = '\0' * self.blocksize 212 | 213 | f = self.simg_f 214 | for s, e in remaining: 215 | for b in range(s, e): 216 | idx = bisect.bisect_right(self.offset_index, b) - 1 217 | chunk_start, _, filepos, fill_data = self.offset_map[idx] 218 | if filepos is not None: 219 | filepos += (b-chunk_start) * self.blocksize 220 | f.seek(filepos, os.SEEK_SET) 221 | data = f.read(self.blocksize) 222 | else: 223 | if fill_data == reference[:4]: # fill with all zeros 224 | data = reference 225 | else: 226 | data = None 227 | 228 | if data == reference: 229 | zero_blocks.append(b) 230 | zero_blocks.append(b+1) 231 | else: 232 | nonzero_blocks.append(b) 233 | nonzero_blocks.append(b+1) 234 | 235 | assert zero_blocks or nonzero_blocks or clobbered_blocks 236 | 237 | if zero_blocks: 238 | out["__ZERO"] = rangelib.RangeSet(data=zero_blocks) 239 | if nonzero_blocks: 240 | out["__NONZERO"] = rangelib.RangeSet(data=nonzero_blocks) 241 | if clobbered_blocks: 242 | out["__COPY"] = clobbered_blocks 243 | 244 | def ResetFileMap(self): 245 | """Throw away the file map and treat the entire image as 246 | undifferentiated data.""" 247 | self.file_map = {"__DATA": self.care_map} 248 | -------------------------------------------------------------------------------- /remove_redef.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | This script is very specific for framework-res/res/values/drawables.xml. 4 | Currently ResValuesModify can't process . 5 | use this script to remove multiple definitions 6 | """ 7 | import sys 8 | import xml 9 | import xml.dom 10 | from xml.dom import minidom 11 | 12 | fdir=sys.argv[1] 13 | filename=fdir +"/res/values/drawables.xml" 14 | xmldoc = minidom.parse(filename) 15 | root = xmldoc.firstChild 16 | elements = [ e for e in root.childNodes if e.nodeType == e.ELEMENT_NODE ] 17 | elem_defs = {} 18 | for elem in elements: 19 | name = elem.attributes["name"].value 20 | elem_defs[name] = elem_defs.get(name, 0) + 1 21 | 22 | repeat_defs = [ name for name in elem_defs.keys() if elem_defs[name] > 1] 23 | xmldoc.unlink() 24 | 25 | f = open(filename, "r") 26 | lines = f.readlines() 27 | f.close() 28 | 29 | for line in lines: 30 | for rdef in repeat_defs: 31 | if rdef in line: 32 | lines.remove(line) 33 | repeat_defs.remove(rdef) 34 | 35 | f = open(filename, "w") 36 | f.writelines(lines) 37 | f.close() 38 | 39 | 40 | -------------------------------------------------------------------------------- /replace_package_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ $# -ne 3 ] 4 | then 5 | echo $0 path src_package_name dest_package_name 6 | echo 7 | exit 8 | fi 9 | 10 | path="$1" 11 | src="$2" 12 | des="$3" 13 | 14 | cd $path 15 | #replace xml 16 | for f in $(find . -name "*.xml") 17 | do 18 | echo $f 19 | sed "s/$src/$des/g" $f > tmp 20 | mv tmp $f 21 | done 22 | 23 | #replace smali 24 | src2=$(echo $src | sed "s#\.#\\\/#g") 25 | des2=$(echo $des | sed "s#\.#\\\/#g") 26 | for f in $(find . -name "*.smali") 27 | do 28 | echo $f 29 | sed "s/$src2/$des2/g" $f > tmp 30 | mv tmp $f 31 | done 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /replace_res_id.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #=============================================================================== 3 | # FILE: replace_res_id.pl 4 | # 5 | # DESCRIPTION: The resource id in source code is referenced as const of 6 | # R.type.name (i.e. application defined resources), and this script 7 | # would replace them with the value from the specified apk. 8 | # This is useful if we want to insert the piece of code to one APK 9 | # in smali format, e.g. to use our implementation for updateInCallNotification() 10 | # for Phone.apk 11 | # USAGE: replace_res_id.pl source.java dest.apk > source.java.new 12 | # rename source.java.new as source.java to build the APK 13 | #=============================================================================== 14 | 15 | use strict; 16 | use warnings; 17 | 18 | my ($srcfile, $apk) = @ARGV; 19 | 20 | open(SRC, "<$srcfile"); 21 | 22 | while(my $line = ){ 23 | 24 | while ( $line =~ /[^\.]R\.([_\.a-zA-Z0-9]+)/g ) 25 | { 26 | my ($id, $oid) = ($1, $1); 27 | $id =~ s/\./\\\//; 28 | #print("aapt d resources $apk | grep spec.*$id\n"); 29 | my $ret = `aapt d resources $apk | grep spec.*$id:`; 30 | $ret =~ s/^\s*spec\s+resource\s+(0x[0-9a-f]+).*$/$1/; 31 | chomp($ret); 32 | if ($ret) { 33 | $line =~ s/R\.$oid/$ret/; 34 | } 35 | else { 36 | warn "No id found for R.$oid\n"; 37 | } 38 | } 39 | print $line; 40 | } 41 | close(SRC); 42 | -------------------------------------------------------------------------------- /replace_smali_method.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | action=$1 4 | file=$2 5 | method=$3 6 | OUT=out 7 | 8 | function get_method_content() { 9 | dir=$1 10 | file=$2 11 | method=$3 12 | 13 | number=`find $dir -name $file.smali | wc -l` 14 | if [ ! "$number" == 1 ]; then 15 | echo "no or more than one file named $file.smali!" 16 | exit -1 17 | fi 18 | 19 | file=`find $dir -name $file.smali` 20 | 21 | patchfile=`basename $file`.method 22 | patchdir=`dirname $file` 23 | patchdir=`echo $patchdir | sed -e "s/$dir\///"` 24 | 25 | echo patch $file at $patchdir/$patchfile 26 | mkdir -p $patchdir 27 | cat $file | sed -n -e "/^\.method.*$method/,/^\.end method/p" > $patchdir/$patchfile 28 | } 29 | 30 | function apply_method() { 31 | dir=$1 32 | patch=$2 33 | 34 | to=$dir/`echo $patch | sed -e "s/.method//"` 35 | # now only support one method in one file 36 | method=`cat $patch | grep "^.method" | sed -e "s/^.* //" -e "s/(.*$//"` 37 | 38 | echo patch method $method to file $to 39 | cat $to | sed -e "/^\.method.*$method/,/^\.end method/d" > $to.patched 40 | cat $patch >> $to.patched 41 | mv $to.patched $to 42 | } 43 | 44 | if [ "$action" == "patch" ]; then 45 | get_method_content $OUT $file $method 46 | fi 47 | 48 | if [ "$action" == "apply" ]; then 49 | apply_method $OUT $file 50 | fi 51 | -------------------------------------------------------------------------------- /resolve_patch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -r tmp 4 | rm -r tmp2 5 | mkdir tmp 6 | mkdir tmp2 7 | 8 | for f in `grep -rn "access" $1 | cut -d: -f1 | uniq | sort` 9 | do 10 | sed -i "s/access\$.*.(/access\$9999(/g" $f 11 | done 12 | 13 | for f in `grep -rn "access" $2 | cut -d: -f1 | uniq | sort` 14 | do 15 | sed -i "s/access\$.*.(/access\$9999(/g" $f 16 | done 17 | 18 | for ori in `find $1 -name *.smali` 19 | do 20 | filepath=`dirname $ori` 21 | filename=`basename $ori .smali` 22 | if [ -f ${ori/$1/$2} ];then 23 | diff -Naur $ori ${ori/$1/$2} > tmp/"$filename.patch" 24 | if [ $? -eq 0 ] ; then 25 | rm tmp/"$filename.patch" 26 | echo "Processing file:$filename.patch" 27 | else java -jar PatchResolver.jar ${ori/$1/$3} ${ori/$1/$4} tmp/"$filename.patch" > tmp2/"$filename.patch" 28 | fi 29 | fi 30 | done 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /restore_obsolete_keyguard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -d "android.policy.jar.out/smali/com/android/internal/policy/impl/keyguard_obsolete" ];then 4 | 5 | cd android.policy.jar.out/smali/com/android/internal/policy/impl 6 | cp keyguard_obsolete/*.smali . 7 | 8 | rm -r ./keyguard_obsolete 9 | mv ./keyguard ../ 10 | 11 | for smali in `find . -name '*.smali'` 12 | do 13 | sed -i "s/\/keyguard_obsolete\//\//g" $smali 14 | sed -i "s/\/keyguard\//\//g" $smali 15 | done 16 | 17 | mv ../keyguard ./ 18 | 19 | cd - 20 | 21 | fi 22 | -------------------------------------------------------------------------------- /rewrite.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | 5 | if len(sys.argv) != 4: 6 | print("Usage: rewrite filename old-string new-string") 7 | sys.exit(1) 8 | 9 | filename = sys.argv[1] 10 | oldstr = sys.argv[2] 11 | newstr = sys.argv[3] 12 | with open(filename) as f: 13 | content = f.read() 14 | content = content.replace(oldstr, newstr) 15 | 16 | with open(filename, "w") as f: 17 | f.write(content) 18 | -------------------------------------------------------------------------------- /rmline.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | who=`whoami` 4 | tmp_loc=/tmp/rmline_$who 5 | 6 | # $2 is the file name with the full absolute path 7 | function rm_line() { 8 | local action=$1 9 | local file=$2 10 | local diff_file=$tmp_loc$file.line 11 | 12 | if [ "$action" == "remove" ]; then 13 | mv $file $file.original 14 | more $file.original | sed -e '/^\s*\.line.*$/d' | sed -e 's/\/jumbo//' > $file 15 | diff $file $file.original > /dev/null || { 16 | mkdir -p `dirname $diff_file` 17 | diff -B -c $file $file.original > $diff_file 18 | } 19 | rm $file.original 20 | else 21 | if [ -f $diff_file ]; then 22 | patch -f $file -r /dev/null < $diff_file >/dev/null 2>&1 23 | rm -f $diff_file 24 | else 25 | echo "Warning: line info file ($diff_file) does not exist" >&2 26 | fi 27 | fi 28 | } 29 | 30 | action=remove 31 | if [ "$1" == "-r" ]; then 32 | action=add 33 | shift 34 | fi 35 | 36 | p=`pwd` 37 | full=`echo $1 | sed -e "s#\(^[^\/]\)#$p/\1#"` 38 | if [ -f "$full" ]; then 39 | echo $full | grep .smali$ > /dev/null && rm_line $action $full 40 | exit 0 41 | fi 42 | 43 | for file in `find $full -name "*.smali"` 44 | do 45 | rm_line $action $file 46 | done 47 | -------------------------------------------------------------------------------- /sign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The path for keys could be set when exec sign.sh as: 4 | # KEY_PATH=/path/to/key sign.sh .. 5 | # If the path is not set, the default value is: 6 | # 1) if PORT_ROOT is set (after running lunch), it is 7 | # $PORT_ROOT/porting/tools 8 | # 2) if not running lunch, the default path is ./ 9 | if [ -z "$PORT_ROOT" ] 10 | then 11 | KEYPATH=${KEY_PATH:=.} 12 | else 13 | KEYPATH=${KEY_PATH:=$PORT_ROOT/build/security} 14 | fi 15 | 16 | SIGNAPK=$PORT_ROOT/tools/signapk.jar 17 | PEMKEY=$KEYPATH/testkey.x509.pem 18 | PK8KEY=$KEYPATH/testkey.pk8 19 | 20 | TMPDIR=.tmp_for_sign 21 | 22 | function delete_meta_info() { 23 | zip -d $1 "META-INF/*" 24 | } 25 | 26 | function sign_for_phone() { 27 | echo ">>> Sign apks under dir $1..." 28 | for apk in `adb shell ls $1/*.apk | col -b` 29 | do 30 | echo ">>> Sign for $apk" 31 | file=`basename $apk` 32 | adb pull $apk $TMPDIR/$file 33 | delete_meta_info $TMPDIR/$file 34 | java -jar $SIGNAPK $PEMKEY $PK8KEY $TMPDIR/$file $TMPDIR/$file.signed 35 | zipalign 4 $TMPDIR/$file.signed $TMPDIR/$file.signed.aligned 36 | adb push $TMPDIR/$file.signed.aligned $1/$file 37 | done 38 | } 39 | 40 | function sign_for_dir() { 41 | echo ">>> Sign apks under dir $1..." 42 | for apk in `find $1 -name "*.apk"` 43 | do 44 | echo ">>> Sign for $apk" 45 | delete_meta_info $apk 46 | java -jar $SIGNAPK $PEMKEY $PK8KEY $apk $apk.signed 47 | zipalign 4 $apk.signed $apk.signed.aligned 48 | mv $apk.signed.aligned $apk 49 | rm $apk.signed 50 | done 51 | } 52 | 53 | if [ -z "$1" ] 54 | then 55 | echo "usage: ./sign.sh sign.phone - to sign all apks for phone" 56 | echo " ./sign.sh sign.zip dir - to sign all apks for the unzip-ed zip-file" 57 | echo " ./sign.sh apk-file [filename] - to sign apk-file and push to phone as filename" 58 | exit 0 59 | fi 60 | 61 | if [ "$1" == "sign.phone" ] 62 | then 63 | adb remount || { echo "Failed to remount the device"; exit 10;} 64 | mkdir -p $TMPDIR 65 | sign_for_phone "/system/app" 66 | sign_for_phone "/system/framework" 67 | rm -rf $TMPDIR 68 | echo Siging Complete 69 | exit 0 70 | fi 71 | 72 | if [ "$1" == "sign.zip" ] 73 | then 74 | ZIP_DIR=$2 75 | sign_for_dir "$ZIP_DIR/system/app" 76 | sign_for_dir "$ZIP_DIR/system/framework" 77 | echo Siging Complete 78 | exit 0 79 | fi 80 | 81 | if [ -f "$1" ] 82 | then 83 | SIGNED=$1.signed 84 | ALIGNED=$SIGNED.aligned 85 | delete_meta_info $1 86 | java -jar $SIGNAPK $PEMKEY $PK8KEY $1 $SIGNED 87 | zipalign 4 $SIGNED $ALIGNED 88 | if [ -n "$2" ] 89 | then 90 | adb remount || { echo "Failed to remount the device"; exit 10;} 91 | echo "push $ALIGNED $2" 92 | adb push $ALIGNED $2 93 | rm $SIGNED 94 | rm $ALIGNED 95 | else 96 | echo "The Signed file: $SIGNED" 97 | fi 98 | exit 0 99 | else 100 | echo "Apk file $1 does not exist" 101 | exit 1 102 | fi 103 | -------------------------------------------------------------------------------- /signapk.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/signapk.jar -------------------------------------------------------------------------------- /smali: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (C) 2007 The Android Open Source Project 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # As per the Apache license requirements, this file has been modified 18 | # from its original state. 19 | # 20 | # Such modifications are Copyright (C) 2010 Ben Gruver, and are released 21 | # under the original license 22 | 23 | # This script is a wrapper for smali.jar, so you can simply call "smali", 24 | # instead of java -jar smali.jar. It is heavily based on the "dx" script 25 | # from the Android SDK 26 | 27 | # Set up prog to be the path of this script, including following symlinks, 28 | # and set up progdir to be the fully-qualified pathname of its directory. 29 | prog="$0" 30 | while [ -h "${prog}" ]; do 31 | newProg=`/bin/ls -ld "${prog}"` 32 | echo ${newProg} 33 | 34 | 35 | newProg=`expr "${newProg}" : ".* -> \(.*\)$"` 36 | if expr "x${newProg}" : 'x/' >/dev/null; then 37 | prog="${newProg}" 38 | else 39 | progdir=`dirname "${prog}"` 40 | prog="${progdir}/${newProg}" 41 | fi 42 | done 43 | oldwd=`pwd` 44 | progdir=`dirname "${prog}"` 45 | cd "${progdir}" 46 | progdir=`pwd` 47 | prog="${progdir}"/`basename "${prog}"` 48 | cd "${oldwd}" 49 | 50 | 51 | jarfile=smali.jar 52 | libdir="$progdir" 53 | if [ ! -r "$libdir/$jarfile" ] 54 | then 55 | echo `basename "$prog"`": can't find $jarfile" 56 | exit 1 57 | fi 58 | 59 | javaOpts="" 60 | 61 | # If you want DX to have more memory when executing, uncomment the following 62 | # line and adjust the value accordingly. Use "java -X" for a list of options 63 | # you can pass here. 64 | # 65 | javaOpts="-Xmx512M" 66 | 67 | # Alternatively, this will extract any parameter "-Jxxx" from the command line 68 | # and pass them to Java (instead of to dx). This makes it possible for you to 69 | # add a command-line parameter such as "-JXmx256M" in your ant scripts, for 70 | # example. 71 | while expr "x$1" : 'x-J' >/dev/null; do 72 | opt=`expr "$1" : '-J\(.*\)'` 73 | javaOpts="${javaOpts} -${opt}" 74 | shift 75 | done 76 | 77 | if [ "$OSTYPE" = "cygwin" ] ; then 78 | jarpath=`cygpath -w "$libdir/$jarfile"` 79 | else 80 | jarpath="$libdir/$jarfile" 81 | fi 82 | 83 | exec java $javaOpts -jar "$jarpath" "$@" 84 | -------------------------------------------------------------------------------- /smali.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/smali.jar -------------------------------------------------------------------------------- /target_files_template/BOOTABLE_IMAGES/recovery.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/BOOTABLE_IMAGES/recovery.img -------------------------------------------------------------------------------- /target_files_template/META/apkcerts.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/META/apkcerts.txt -------------------------------------------------------------------------------- /target_files_template/META/filesystem_config.txt: -------------------------------------------------------------------------------- 1 | system/bin/app_process32_vendor 0 2000 755 selabel=u:object_r:zygote_exec:s0 capabilities=0x0 2 | system/bin/app_process64_vendor 0 2000 755 selabel=u:object_r:zygote_exec:s0 capabilities=0x0 3 | system/xbin/shelld 0 2000 755 selabel=u:object_r:system_file:s0 capabilities=0x0 4 | system/bin/fdpp 0 2000 755 selabel=u:object_r:system_file:s0 capabilities=0x0 5 | -------------------------------------------------------------------------------- /target_files_template/META/misc_info.txt: -------------------------------------------------------------------------------- 1 | recovery_api_version=3 2 | fstab_version=1 3 | use_set_metadata=1 4 | tool_extensions=. 5 | -------------------------------------------------------------------------------- /target_files_template/META/otakeys.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /target_files_template/OTA/android-info.txt: -------------------------------------------------------------------------------- 1 | require mid=P* 2 | require board=mahimahi|nexusone 3 | require version-bootloader=0.35.2017|0.35.0017 4 | require version-microp=0b15|0c15 5 | require version-baseband=5.08.00.04 6 | -------------------------------------------------------------------------------- /target_files_template/OTA/bin/applypatch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/applypatch -------------------------------------------------------------------------------- /target_files_template/OTA/bin/applypatch_static: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/applypatch_static -------------------------------------------------------------------------------- /target_files_template/OTA/bin/busybox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/busybox -------------------------------------------------------------------------------- /target_files_template/OTA/bin/check_prereq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/check_prereq -------------------------------------------------------------------------------- /target_files_template/OTA/bin/relink: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/relink -------------------------------------------------------------------------------- /target_files_template/OTA/bin/sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/sqlite3 -------------------------------------------------------------------------------- /target_files_template/OTA/bin/updater: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/OTA/bin/updater -------------------------------------------------------------------------------- /target_files_template/RADIO/bitmap_size.txt: -------------------------------------------------------------------------------- 1 | 480 800 16 2 | -------------------------------------------------------------------------------- /target_files_template/RADIO/firmware_error.565: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/RADIO/firmware_error.565 -------------------------------------------------------------------------------- /target_files_template/RADIO/firmware_install.565: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiCode/patchrom_tools/1bd99e03321b6b240b440ba738a89ccca795d734/target_files_template/RADIO/firmware_install.565 -------------------------------------------------------------------------------- /target_files_template/RECOVERY/RAMDISK/etc/recovery.fstab: -------------------------------------------------------------------------------- 1 | # mount point fstype device [device2] 2 | 3 | /boot mtd boot 4 | /cache yaffs2 cache 5 | /data yaffs2 userdata 6 | /misc mtd misc 7 | /recovery mtd recovery 8 | /sdcard vfat /dev/block/mmcblk0p1 /dev/block/mmcblk0 9 | /system yaffs2 system 10 | -------------------------------------------------------------------------------- /target_files_template/SYSTEM/build.prop: -------------------------------------------------------------------------------- 1 | # place holder 2 | -------------------------------------------------------------------------------- /uniq_first.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import sys 5 | def uniq_first(src_file, dst_file): 6 | lines = [] 7 | with open(src_file, 'r') as sf: 8 | lines = sf.readlines() 9 | with open(dst_file, 'r') as tf: 10 | content = tf.read() 11 | 12 | with open(dst_file, 'a') as df: 13 | for line in lines: 14 | if not (line.split()[0] + " " in content): 15 | df.write(line) 16 | 17 | def main(args): 18 | if len(args) != 2: 19 | print("Usage: uniq_first src_file dst_file") 20 | sys.exit(1) 21 | 22 | uniq_first(args[0], args[1]) 23 | 24 | 25 | if __name__ == '__main__': 26 | main(sys.argv[1:]) 27 | --------------------------------------------------------------------------------