diff --git a/README b/README
new file mode 100644
index 0000000..f938081
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+This is a place holder, please fill in real text when you add stuff.
diff --git a/aapt b/aapt
new file mode 100755
index 0000000..5d1fbb5
Binary files /dev/null and b/aapt differ
diff --git a/aapt.exe b/aapt.exe
index 54718d6..1f51b87 100755
Binary files a/aapt.exe and b/aapt.exe differ
diff --git a/add_miui_methods_and_variables.sh b/add_miui_methods_and_variables.sh
deleted file mode 100755
index 341e45c..0000000
--- a/add_miui_methods_and_variables.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash
-#
-# Copyright 2016 Miui Patchrom
-#
-
-BASE_DIR=$1
-MOD_DIR=$2
-TARGET_DIR=$3
-
-IFS=$'\x0A'
-
-tmp_fifo_file="/tmp/$$.fifo"
-mkfifo $tmp_fifo_file
-exec 9<>$tmp_fifo_file
-
-# 8 threads
-for((i=0;i<8;i++))
-do
- echo ""
-done >&9
-
-
-for modSmaliFile in $(find $MOD_DIR -name "*.smali" ! -name "*\$[0-9]*.smali" ! -name "R\$*.smali")
-do
- baseSmaliFile=${modSmaliFile/$MOD_DIR/$BASE_DIR}
- targetSmaliFile=${modSmaliFile/$MOD_DIR/$TARGET_DIR}
- read -u9
- {
- if [ -f $baseSmaliFile ];then
- if [ "$(diff $baseSmaliFile $modSmaliFile)" == "" ];then
- echo "" >&9
- continue
- fi
- methodBeginLines=($(grep -n "^.method " $modSmaliFile))
- methodEndLines=($(grep -n "^.end method" $modSmaliFile))
- for((i=0;i<${#methodBeginLines[@]};i++))
- do
- if [ "$(echo ${methodBeginLines[$i]} | grep -E 'static synthetic|clinit')" == "" ];then
- grepPattern="[^->]$(echo ${methodBeginLines[$i]##* } | sed 's/\[/\\\[/g')"
- if [ "$(grep $grepPattern $baseSmaliFile)" == "" ];then
- beginLineNum=$(echo ${methodBeginLines[$i]} | cut -d ':' -f1)
- endLineNum=$(echo ${methodEndLines[$i]} | cut -d ':' -f1)
- echo "Add method ${methodBeginLines[$i]##* } into $targetSmaliFile"
- sed -n ${beginLineNum},${endLineNum}p $modSmaliFile >> $targetSmaliFile
- fi
- fi
- done
-
- fieldLines=($(grep -En "^.field |^.end field" $modSmaliFile))
- linesCount=${#fieldLines[@]}
- for ((i=0;i<$linesCount;i++))
- do
- beginLine=${fieldLines[$i]%% =*}
- grepPattern="[^->]$(echo ${beginLine##* } | sed 's/\[/\\\[/g')"
- if [ "$(grep $grepPattern $baseSmaliFile)" == "" ];then
- echo "Add field ${beginLine##* } into $targetSmaliFile"
- beginLineNum=$(echo $beginLine | cut -d ":" -f1)
- if [ $(($linesCount-$i)) -ne 1 -a "$(echo ${fieldLines[$i+1]} | grep ".end field")" != "" ];then
- endLineNum=$(echo ${fieldLines[$i+1]} | cut -d ":" -f1)
- sed -n ${beginLineNum},${endLineNum}p $modSmaliFile >> $targetSmaliFile
- i=$(($i+1))
- else
- sed -n ${beginLineNum}p $modSmaliFile >> $targetSmaliFile
- fi
- fi
- done
- fi
- echo "" >&9
- }&
-done
-wait
-exec 9>&-
-
-exit 0
diff --git a/add_miui_smail.sh b/add_miui_smail.sh
index 2e4cc54..9b2e751 100755
--- a/add_miui_smail.sh
+++ b/add_miui_smail.sh
@@ -1,49 +1,19 @@
#!/bin/bash
#
-# Add miui smali files
+# $1: dir for miui
+# $2: dir for original
#
-# $1: android original src dir
-# $2: miui src dir
-# $3: target src dir
-
-BASE_DIR=$1
-MIUI_DIR=$2
-TARGET_DIR=$3
-OVERLAY_DIR=$PORT_ROOT/android/overlay
-OVERLAY_CLASSES=$OVERLAY_DIR/OVERLAY_CLASSES
-
-$PORT_ROOT/tools/add_miui_methods_and_variables.sh $BASE_DIR $MIUI_DIR $TARGET_DIR
-
-
-for class in `cat $OVERLAY_CLASSES | grep -Ev "^$|^#.*$"`
-do
- target_smali=$TARGET_DIR/smali/$class.smali
- target_classes=$TARGET_DIR/smali/$class*
- if [ -f "$target_smali" ];then
- rm -f $target_classes
- fi
-done
-
-
-for overlay_smali in `find $OVERLAY_DIR -name "*.smali" | sed 's/\$.*/.smali/' | uniq`
-do
- target_smali=${overlay_smali/$OVERLAY_DIR/$TARGET_DIR}
- if [ -f "$target_smali" ];then
- cp -f ${overlay_smali/.smali/}*.smali `dirname $target_smali`
- fi
-done
-
-
-for file in `find $MIUI_DIR -name "*.smali"`
+for file in `find $1 -name "*.smali"`
do
- newfile=${file/$MIUI_DIR/$TARGET_DIR}
+ newfile=${file/$1/$2}
if [ ! -f "$newfile" ]
then
mkdir -p `dirname $newfile`
+ echo "add smali from miui: $file"
cp $file $newfile
fi
done
if [ -f "customize_framework.sh" ]; then
- bash ./customize_framework.sh $2 $3
+ ./customize_framework.sh $1 $2
fi
diff --git a/apkcerts.py b/apkcerts.py
index 62f5c6f..3f72c72 100755
--- a/apkcerts.py
+++ b/apkcerts.py
@@ -1,23 +1,16 @@
#!/usr/bin/env python
-import os
import sys
import string
import xml
import xml.dom
from xml.dom import minidom
-def getName(pkg, updatedPackages):
- codePath = pkg.attributes["codePath"].value
- if codePath.startswith("/data/app"):
- codePath = ""
- pkgName = pkg.attributes["name"].value
- for updatedPkg in updatedPackages:
- updatedPkgName = updatedPkg.attributes["name"].value
- if updatedPkgName == pkgName:
- codePath=updatedPkg.attributes["codePath"].value
- break
- return os.path.basename(codePath)
+def getName(codePath):
+ if codePath.startswith("/system/app"):
+ return codePath.replace("/system/app/", "")
+ else :
+ return ""
def usage():
print "Usage: python ./apkcerts.py path-to-packages.xml path-to-apkcerts.txt"
@@ -33,11 +26,10 @@ def main():
print "Error: %s doesn't exist or isn't a vaild xml file" %(sys.argv[1])
sys.exit(1)
- updatedPackages = xmldoc.getElementsByTagName("updated-package")
packages = xmldoc.getElementsByTagName("package")
sigpkgs = {}
for pkg in packages:
- name = getName(pkg, updatedPackages)
+ name = getName(pkg.attributes["codePath"].value)
cert= pkg.getElementsByTagName("cert")
if not cert or not name: continue
index = cert[0].getAttribute("index")
@@ -62,9 +54,9 @@ def main():
sig = sigmap.get(keyindex, None)
for pkgname in pkgnames:
if sig:
- line = 'name="{0}.apk" certificate="build/target/product/security/{1}.x509.pem" private_key="build/target/product/security/{1}.pk8"\n'.format(pkgname, sig)
+ line = 'name="{0}" certificate="build/target/product/security/{1}.x509.pem" private_key="build/target/product/security/{1}.pk8"\n'.format(pkgname, sig)
else:
- line = 'name="{0}.apk" certificate="PRESIGNED" private_key=""\n'.format(pkgname)
+ line = 'name="{0}" certificate="PRESIGNED" private_key=""\n'.format(pkgname)
f.write(line)
if "__main__" == __name__:
diff --git a/apktool b/apktool
index 0c887be..b439eff 100755
--- a/apktool
+++ b/apktool
@@ -56,7 +56,7 @@ javaOpts=""
# line and adjust the value accordingly. Use "java -X" for a list of options
# you can pass here.
#
-javaOpts="-Xmx1024M"
+javaOpts="-Xmx256M"
# Alternatively, this will extract any parameter "-Jxxx" from the command line
# and pass them to Java (instead of to dx). This makes it possible for you to
diff --git a/apktool.jar b/apktool.jar
index 58dd293..3d5fc2a 100644
Binary files a/apktool.jar and b/apktool.jar differ
diff --git a/baksmali b/baksmali
index bd3f820..31f782f 100755
--- a/baksmali
+++ b/baksmali
@@ -14,12 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# As per the Apache license requirements, this file has been modified
-# from its original state.
-#
-# Such modifications are Copyright (C) 2010 Ben Gruver, and are released
-# under the original license
-
# This script is a wrapper around baksmali.jar, so you can simply call
# "baksmali", instead of java -jar baksmali.jar. It is heavily based on
# the "dx" script from the Android SDK
@@ -61,7 +55,7 @@ javaOpts=""
# If you want DX to have more memory when executing, uncomment the following
# line and adjust the value accordingly. Use "java -X" for a list of options
# you can pass here.
-#
+#
javaOpts="-Xmx256M"
# Alternatively, this will extract any parameter "-Jxxx" from the command line
diff --git a/baksmali.jar b/baksmali.jar
index 2ff1ae3..d2ba043 100644
Binary files a/baksmali.jar and b/baksmali.jar differ
diff --git a/build_target_files.sh b/build_target_files.sh
index 4106282..eed0c6e 100755
--- a/build_target_files.sh
+++ b/build_target_files.sh
@@ -10,16 +10,6 @@ OTA_FROM_TARGET_FILES=$TOOL_DIR/releasetools/ota_from_target_files
SIGN_TARGET_FILES_APKS=$TOOL_DIR/releasetools/sign_target_files_apks
OUT_ZIP_FILE=
NO_SIGN=false
-CERTIFICATE_DIR=$PORT_ROOT/build/security
-
-APKCERT=$PORT_ROOT/miui/metadata/apkcert.txt
-if [ "$USE_ANDROID_OUT" == "true" ];then
- APKCERT=$ANDROID_OUT/obj/PACKAGING/apkcerts_intermediates/*.txt
-fi
-FILESYSTEM_CONFIG=$PORT_ROOT/miui/metadata/filesystem_config.txt
-if [ "$USE_ANDROID_OUT" == "true" ];then
- FILESYSTEM_CONFIG=$(find $ANDROID_OUT/obj/PACKAGING/target_files_intermediates/ -name filesystem_config.txt)
-fi
# copy the whole target_files_template dir
function copy_target_files_template {
@@ -35,7 +25,7 @@ function copy_bootimage {
do
if [ -f $ZIP_DIR/$file ]
then
- cp $ZIP_DIR/$file $TARGET_FILES_DIR/BOOTABLE_IMAGES/
+ cp $ZIP_DIR/$file $TARGET_FILES_DIR/BOOTABLE_IMAGES/boot.img
return
fi
done
@@ -70,19 +60,12 @@ function recover_link {
function process_metadata {
echo "Process metadata"
- cp -f $TARGET_FILES_TEMPLATE_DIR/META/filesystem_config.txt $TARGET_FILES_DIR/META
- python $TOOL_DIR/uniq_first.py $METADATA_DIR/filesystem_config.txt $TARGET_FILES_DIR/META/filesystem_config.txt
- python $TOOL_DIR/uniq_first.py $FILESYSTEM_CONFIG $TARGET_FILES_DIR/META/filesystem_config.txt
- cat $TARGET_FILES_DIR/META/filesystem_config.txt | sort > $TARGET_FILES_DIR/META/temp.txt
- mv $TARGET_FILES_DIR/META/temp.txt $TARGET_FILES_DIR/META/filesystem_config.txt
-
+ cp -f $METADATA_DIR/filesystem_config.txt $TARGET_FILES_DIR/META
+ cat $TOOL_DIR/target_files_template/META/filesystem_config.txt >> $TARGET_FILES_DIR/META/filesystem_config.txt
cp -f $METADATA_DIR/recovery.fstab $TARGET_FILES_DIR/RECOVERY/RAMDISK/etc
-
- cp -rf $APKCERT $TARGET_FILES_DIR/META/apkcerts.txt
- python $TOOL_DIR/uniq_first.py $METADATA_DIR/apkcerts.txt $TARGET_FILES_DIR/META/apkcerts.txt
- python $TOOL_DIR/uniq_first.py $TARGET_FILES_TEMPLATE_DIR/META/apkcerts.txt $TARGET_FILES_DIR/META/apkcerts.txt
- cat $TARGET_FILES_DIR/META/apkcerts.txt | sort > $TARGET_FILES_DIR/META/temp.txt
- mv $TARGET_FILES_DIR/META/temp.txt $TARGET_FILES_DIR/META/apkcerts.txt
+ python $TOOL_DIR/uniq_first.py $METADATA_DIR/apkcerts.txt $TARGET_FILES_DIR/META/apkcerts.txt $PRJ_DIR
+ cat $TARGET_FILES_DIR/META/apkcerts.txt | sort > $TARGET_FILES_DIR/temp.txt
+ mv $TARGET_FILES_DIR/temp.txt $TARGET_FILES_DIR/META/apkcerts.txt
recover_link
}
@@ -98,39 +81,20 @@ function zip_target_files {
function sign_target_files {
echo "Sign target files"
- $SIGN_TARGET_FILES_APKS -d $CERTIFICATE_DIR $TARGET_FILES_ZIP temp.zip
+ $SIGN_TARGET_FILES_APKS -d $PORT_ROOT/build/security $TARGET_FILES_ZIP temp.zip
mv temp.zip $TARGET_FILES_ZIP
}
# build a new full ota package
function build_ota_package {
echo "Build full ota package: $OUT_DIR/$OUT_ZIP_FILE"
- $OTA_FROM_TARGET_FILES -n -k $CERTIFICATE_DIR/testkey $TARGET_FILES_ZIP $OUT_DIR/$OUT_ZIP_FILE
+ $OTA_FROM_TARGET_FILES -n -k $PORT_ROOT/build/security/testkey $TARGET_FILES_ZIP $OUT_DIR/$OUT_ZIP_FILE
}
-function adjust_replace_key_script {
- if [ "$CERTIFICATE_DIR" != "$PORT_ROOT/build/security" -a -f "$CERTIFICATE_DIR/platform.x509.pem" \
- -a -f "$CERTIFICATE_DIR/shared.x509.pem" -a -f "$CERTIFICATE_DIR/media.x509.pem" -a -f "$CERTIFICATE_DIR/shared.x509.pem" ];then
- platform_cert=$(cat $CERTIFICATE_DIR/platform.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"')
- sed -i "s/@user_platform/$platform_cert/g" out/target_files/OTA/bin/replace_key
- shared_cert=$(cat $CERTIFICATE_DIR/shared.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"')
- sed -i "s/@user_shared/$shared_cert/g" out/target_files/OTA/bin/replace_key
- media_cert=$(cat $CERTIFICATE_DIR/media.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"')
- sed -i "s/@user_media/$media_cert/g" out/target_files/OTA/bin/replace_key
- testkey_cert=$(cat $CERTIFICATE_DIR/shared.x509.pem | sed 's/-----/#/g' | cut -d'#' -f1 | tr -d ["\n"] | base64 --decode | hexdump -v -e '/1 "%02x"')
- sed -i "s/@user_testkey/$testkey_cert/g" out/target_files/OTA/bin/replace_key
- else
- rm -rf out/target_files/OTA/bin/replace_key
- fi
-}
if [ $# -eq 3 ];then
+ NO_SIGN=true
OUT_ZIP_FILE=$3
- if [ "$2" == "-n" ];then
- NO_SIGN=true
- elif [ -n "$2" ];then
- CERTIFICATE_DIR=$2
- fi
INCLUDE_THIRDPART_APP=$1
elif [ $# -eq 2 ];then
OUT_ZIP_FILE=$2
@@ -139,13 +103,7 @@ elif [ $# -eq 1 ];then
INCLUDE_THIRDPART_APP=$1
fi
-#Set certificate pass word
-if [ -f "$CERTIFICATE_DIR/passwd" ];then
- export ANDROID_PW_FILE=$CERTIFICATE_DIR/passwd
-fi
-
copy_target_files_template
-adjust_replace_key_script
copy_bootimage
copy_system_dir
copy_data_dir
diff --git a/darwin-x86/aapt b/darwin-x86/aapt
deleted file mode 100755
index 2a0db5d..0000000
Binary files a/darwin-x86/aapt and /dev/null differ
diff --git a/darwin-x86/bsdiff b/darwin-x86/bsdiff
deleted file mode 100755
index 0f5cd34..0000000
Binary files a/darwin-x86/bsdiff and /dev/null differ
diff --git a/darwin-x86/imgdiff b/darwin-x86/imgdiff
deleted file mode 100755
index d9eba10..0000000
Binary files a/darwin-x86/imgdiff and /dev/null differ
diff --git a/darwin-x86/lib64/libcutils.dylib b/darwin-x86/lib64/libcutils.dylib
deleted file mode 100755
index 18d64f0..0000000
Binary files a/darwin-x86/lib64/libcutils.dylib and /dev/null differ
diff --git a/darwin-x86/lib64/liblog.dylib b/darwin-x86/lib64/liblog.dylib
deleted file mode 100755
index 412814f..0000000
Binary files a/darwin-x86/lib64/liblog.dylib and /dev/null differ
diff --git a/darwin-x86/mkbootfs b/darwin-x86/mkbootfs
deleted file mode 100755
index f190aee..0000000
Binary files a/darwin-x86/mkbootfs and /dev/null differ
diff --git a/darwin-x86/mkbootimg b/darwin-x86/mkbootimg
deleted file mode 100755
index f3f1d16..0000000
Binary files a/darwin-x86/mkbootimg and /dev/null differ
diff --git a/darwin-x86/unpackbootimg b/darwin-x86/unpackbootimg
deleted file mode 100755
index 5c97816..0000000
Binary files a/darwin-x86/unpackbootimg and /dev/null differ
diff --git a/darwin-x86/zipalign b/darwin-x86/zipalign
deleted file mode 100755
index 0e3827d..0000000
Binary files a/darwin-x86/zipalign and /dev/null differ
diff --git a/deoat.sh b/deoat.sh
deleted file mode 100755
index 97f9206..0000000
--- a/deoat.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2016, Miui Patchrom
-#
-
-TARGET_DIR=$1
-
-function removeDuplicateFiles() {
- local bootOat64Path=$(find $TARGET_DIR -name "boot.oat" | grep "64\/")
- if [ -n $bootOat64Path ];then
- rm -rf ${bootOat64Path/64\///}
- rm -rf ${bootOat64Path/64\/boot.oat//boot.art}
- fi
- local odex
- for odex in $(find $TARGET_DIR -name "*.odex" | grep "64\/")
- do
- echo "rm -rf ${odex/64\///}"
- rm -rf ${odex/64\///}
- done
-}
-
-function zipDex() {
- local zipDir=$1
- local dexPath=$2
- local suffix=$3
- local dexName=$(basename $dexPath .dex)
- local zipName=${dexName%%-classes*}
- if [ $dexName = $zipName ];then
- local zipDexName=classes.dex
- else
- local zipDexName=classes${dexName##*-classes}.dex
- fi
- mv $dexPath $zipDexName
- if [ -f $zipDir/$zipName.$suffix ];then
- zip -m $zipDir/$zipName.$suffix $zipDexName > /dev/null
- fi
-}
-
-function decodeBootOat() {
- BOOTOAT_PATH=$(find $TARGET_DIR -name "boot.oat")
- if [ -z $BOOTOAT_PATH ];then
- return
- fi
- BOOTOAT_DIR=$(dirname $BOOTOAT_PATH)
- echo "Decoding $BOOTOAT_PATH"
- oat2dex boot $BOOTOAT_PATH > /dev/null
- local bootDex
- for bootDex in $(find $BOOTOAT_DIR/dex -name "*.dex")
- do
- zipDex $(dirname $BOOTOAT_DIR) $bootDex jar
- done
-}
-
-function decodeOdex() {
- local suffix=$1
- local zipPath
- for zipPath in $(find $TARGET_DIR -name "*.$suffix")
- do
- local zipDir=$(dirname $zipPath)
- local zipName=$(basename $zipPath)
- local odexPath=$(find $zipDir -name ${zipName/.$suffix/.odex})
- if [ -z $odexPath ];then
- continue
- fi
- echo "Decoding $odexPath"
- local bootClassPath=$BOOTOAT_DIR/odex
- if [ "$suffix" = "apk" ];then
- bootClassPath=$(dirname $BOOTOAT_DIR)
- fi
- local ret=$(oat2dex -o $zipDir $odexPath $bootClassPath)
- if [ -n "$(echo $ret | grep -i "failed")" -a -f $PORT_ROOT/tools/oat2dex-0.86.jar ];then
- echo "Decoding $odexPath failed, try to use old version oat2dex"
- java -jar $PORT_ROOT/tools/oat2dex-0.86.jar -o $zipDir $odexPath $bootClassPath > /dev/null
- fi
- rm -rf $odexPath
- local dexPath
- for dexPath in $(find $zipDir -maxdepth 1 -name "*.dex")
- do
- zipDex $zipDir $dexPath $suffix
- done
- done
-}
-
-removeDuplicateFiles
-decodeBootOat
-decodeOdex jar
-decodeOdex apk
-rm -rf $BOOTOAT_DIR/boot.oat $BOOTOAT_DIR/boot.art $BOOTOAT_DIR/odex $BOOTOAT_DIR/dex
diff --git a/deodex.sh b/deodex.sh
index 1ecd2f8..4e3da55 100755
--- a/deodex.sh
+++ b/deodex.sh
@@ -12,13 +12,13 @@ function deodex_one_file() {
file=$4
tofile=${file/odex/$5}
echo "processing $tofile"
- $BAKSMALI -a $apilevel -c $classpath -d framework -x $file || exit -2
+ $BAKSMALI -a $apilevel -c $classpath -d framework -I -x $file || exit -2
else
classpath=$1
file=$2
tofile=${file/odex/$3}
echo "processing $tofile"
- $BAKSMALI -c $classpath -d framework -x $file || exit -2
+ $BAKSMALI -c $classpath -d framework -I -x $file || exit -2
fi
$SMALI out -o classes.dex || exit -2
jar uf $tofile classes.dex
@@ -71,12 +71,11 @@ fi
ls framework/core.odex > /dev/null
if [ $? -eq 0 ]
then
- classpath="core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"
if [ $1 = '-a' ]
then
- deodex_one_file -a $apilevel $classpath framework/core.odex jar
+ deodex_one_file -a $apilevel "" framework/core.odex jar
else
- deodex_one_file $classpath framework/core.odex jar
+ deodex_one_file "" framework/core.odex jar
fi
fi
diff --git a/get_apk_cert.py b/get_apk_cert.py
deleted file mode 100755
index 7797e05..0000000
--- a/get_apk_cert.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2016 The Miui Patchrom
-#
-
-import os
-import sys
-import re
-
-# Values for "certificate" in apkcerts that mean special things.
-SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL")
-PUBLIC_KEY_SUFFIX = ".x509.pem"
-PRIVATE_KEY_SUFFIX = ".pk8"
-
-
-def ReadApkCerts(apkcerts):
- """parse the apkcerts.txt file and return a {package: cert} dict."""
- certmap = {}
- with open(apkcerts, 'r') as certs:
- for line in certs.readlines():
- m = re.match(r'^name="(.*)"\s+certificate="(.*)"\s+'
- r'private_key="(.*)"$', line)
- if m:
- name, cert, privkey = m.groups()
- public_key_suffix_len = len(PUBLIC_KEY_SUFFIX)
- private_key_suffix_len = len(PRIVATE_KEY_SUFFIX)
- if cert in SPECIAL_CERT_STRINGS and not privkey:
- certmap[name] = cert
- elif (cert.endswith(PUBLIC_KEY_SUFFIX) and
- privkey.endswith(PRIVATE_KEY_SUFFIX) and
- cert[:-public_key_suffix_len] == privkey[:-private_key_suffix_len]):
- certmap[name] = cert[:-public_key_suffix_len]
- else:
- raise ValueError("failed to parse line from apkcerts.txt:\n" + line)
- return certmap
-
-if __name__ == '__main__':
- apkPath = sys.argv[1]
- apkCerts = sys.argv[2]
- certmap = ReadApkCerts(apkCerts)
- cert = os.path.basename(certmap[os.path.basename(apkPath)])
- print cert
diff --git a/get_filesystem_config b/get_filesystem_config
deleted file mode 100755
index ddbdf8f..0000000
--- a/get_filesystem_config
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2016, Miui Patchrom
-#
-
-ACTION=$1
-LINE_TERMINATION=$'\r\n'
-OLD_IFS=$IFS
-IFS=$'\n'
-BUSYBOX="$2"
-if [ -n "$(adb shell id | grep "uid=0")" ];then
- root='true'
-elif [ -z "$(adb shell su -c "id" | grep "uid=0")" ];then
- echo "Please root your device, and try again."
- exit 1
-fi
-
-if [ -n $root ];then
- fileSystemInfo=$(adb shell ls -aRZ /system)
-else
- fileSystemInfo=$(adb shell su -c "ls -aRZ /system")
-fi
-
-if [ "$ACTION" = '--info' ];then
- for line in $fileSystemInfo
- do
- if [ $line == $LINE_TERMINATION -o ${line:0:1} == 'd' ];then
- continue
- fi
- # lrwxrwxrwx root root u:object_r:system_file:s0 chmod -> toybox
- # cut line before the string " ->"
- line=${line%% ->*}
- if [ $(echo $line | cut -d ':' -f2) == $LINE_TERMINATION ];then
- dir=$(echo $line | cut -d ':' -f1)
- path=$dir
- if [ -n $root ];then
- line=$(adb shell ls -dZ $path)
- else
- line=$(adb shell su -c "ls -dZ $path")
- fi
- else
- path=$dir/$(echo ${line##*:s0} | tr -d $LINE_TERMINATION | sed 's/^[ ]*//')
- fi
- selabel="u:${line##*u:}"
- selabel=${selabel%% *}
- if [ -n $root ];then
- uid=$(adb shell $BUSYBOX stat -c %u $path | tr -d $LINE_TERMINATION)
- gid=$(adb shell $BUSYBOX stat -c %g $path | tr -d $LINE_TERMINATION)
- perm=$(adb shell $BUSYBOX stat -c %a $path | tr -d $LINE_TERMINATION)
- else
- uid=$(adb shell su -c "$BUSYBOX stat -c %u $path" | tr -d $LINE_TERMINATION)
- gid=$(adb shell su -c "$BUSYBOX stat -c %g $path" | tr -d $LINE_TERMINATION)
- perm=$(adb shell su -c "$BUSYBOX stat -c %a $path" | tr -d $LINE_TERMINATION)
- fi
- #Remove blank in filename, it cause ota_from_target_files failed.
- path=$(echo $path | sed 's/ //g')
- echo "${path#\/} $uid $gid $perm selabel=$selabel capabilities=0x0"
- done
-elif [ "$ACTION" = '--link' ];then
- for line in $fileSystemInfo
- do
- if [ $line == $LINE_TERMINATION];then
- continue
- fi
- line=${line%% ->*}
- if [ $(echo $line | cut -d ':' -f2) == $LINE_TERMINATION ];then
- dir=$(echo $line | cut -d ':' -f1)
- path=$dir
- if [ -n $root ];then
- line=$(adb shell ls -dZ $path)
- else
- line=$(adb shell su -c "ls -dZ $path")
- fi
- fi
-
- if [ ${line:0:1} == 'l' ];then
- path=$dir/$(echo ${line##*:s0} | tr -d $LINE_TERMINATION | sed 's/^[ ]*//')
- if [ -n $root ];then
- link=$(adb shell $BUSYBOX readlink $path | tr -d $LINE_TERMINATION)
- else
- link=$(adb shell su -c "$BUSYBOX readlink $path" | tr -d $LINE_TERMINATION)
- fi
- echo "${path#\/}|$link"
- fi
- done
-fi
diff --git a/hex_replace.py b/hex_replace.py
deleted file mode 100644
index 818c1ec..0000000
--- a/hex_replace.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env pyhon
-
-from sys import argv
-import struct
-
-def usage():
- print "Usage: %s orignal target file" % argv[0]
-
-
-def do_replace(inFile, outFile, oldHex, newHex):
- inFp = open(inFile, 'rb')
- outFp = open(outFile, 'wb')
- oldstr = struct.pack('LH', 4611950241719001088, 18288)
- newstr = struct.pack('LH', 5147649559655096320, 18112)
- while 1:
- s = inFp.read(10)
- if s:
- print struct.unpack('LH', s)
- if s == oldstr:
- print "replace"
- outFp.write(newstr)
- else:
- outFp.write(s)
- else:
- break
-
- inFp.close()
- outFp.close()
-
-
-
-if __name__ == "__main__":
- #if len(argv) < 4:
- # exit(usage())
-
- do_replace(argv[1], argv[2], 0, 0)
-
-
diff --git a/insertkeys.py b/insertkeys.py
deleted file mode 100755
index ca1e432..0000000
--- a/insertkeys.py
+++ /dev/null
@@ -1,267 +0,0 @@
-#!/usr/bin/env python
-
-from xml.sax import saxutils, handler, make_parser
-from optparse import OptionParser
-import ConfigParser
-import logging
-import base64
-import sys
-import os
-
-__VERSION = (0, 1)
-
-'''
-This tool reads a mac_permissions.xml and replaces keywords in the signature
-clause with keys provided by pem files.
-'''
-
-class GenerateKeys(object):
- def __init__(self, path):
- '''
- Generates an object with Base16 and Base64 encoded versions of the keys
- found in the supplied pem file argument. PEM files can contain multiple
- certs, however this seems to be unused in Android as pkg manager grabs
- the first cert in the APK. This will however support multiple certs in
- the resulting generation with index[0] being the first cert in the pem
- file.
- '''
-
- self._base64Key = list()
- self._base16Key = list()
-
- if not os.path.isfile(path):
- sys.exit("Path " + path + " does not exist or is not a file!")
-
- pkFile = open(path, 'rb').readlines()
- base64Key = ""
- lineNo = 1
- certNo = 1
- inCert = False
- for line in pkFile:
- line = line.strip()
- # Are we starting the certificate?
- if line == "-----BEGIN CERTIFICATE-----":
- if inCert:
- sys.exit("Encountered another BEGIN CERTIFICATE without END CERTIFICATE on " +
- "line: " + str(lineNo))
-
- inCert = True
-
- # Are we ending the ceritifcate?
- elif line == "-----END CERTIFICATE-----":
- if not inCert:
- sys.exit("Encountered END CERTIFICATE before BEGIN CERTIFICATE on line: "
- + str(lineNo))
-
- # If we ended the certificate trip the flag
- inCert = False
-
- # Sanity check the input
- if len(base64Key) == 0:
- sys.exit("Empty certficate , certificate "+ str(certNo) + " found in file: "
- + path)
-
- # ... and append the certificate to the list
- # Base 64 includes uppercase. DO NOT tolower()
- self._base64Key.append(base64Key)
- try:
- # Pkgmanager and setool see hex strings with lowercase, lets be consistent
- self._base16Key.append(base64.b16encode(base64.b64decode(base64Key)).lower())
- except TypeError:
- sys.exit("Invalid certificate, certificate "+ str(certNo) + " found in file: "
- + path)
-
- # After adding the key, reset the accumulator as pem files may have subsequent keys
- base64Key=""
-
- # And increment your cert number
- certNo = certNo + 1
-
- # If we haven't started the certificate, then we should not encounter any data
- elif not inCert:
- if line is not "":
- sys.exit("Detected erroneous line \""+ line + "\" on " + str(lineNo)
- + " in pem file: " + path)
-
- # else we have started the certicate and need to append the data
- elif inCert:
- base64Key += line
-
- else:
- # We should never hit this assert, if we do then an unaccounted for state
- # was entered that was NOT addressed by the if/elif statements above
- assert(False == True)
-
- # The last thing to do before looping up is to increment line number
- lineNo = lineNo + 1
-
- def __len__(self):
- return len(self._base16Key)
-
- def __str__(self):
- return str(self.getBase16Keys())
-
- def getBase16Keys(self):
- return self._base16Key
-
- def getBase64Keys(self):
- return self._base64Key
-
-class ParseConfig(ConfigParser.ConfigParser):
-
- # This must be lowercase
- OPTION_WILDCARD_TAG = "all"
-
- def generateKeyMap(self, target_build_variant, key_directory):
-
- keyMap = dict()
-
- for tag in self.sections():
-
- options = self.options(tag)
-
- for option in options:
-
- # Only generate the key map for debug or release,
- # not both!
- if option != target_build_variant and \
- option != ParseConfig.OPTION_WILDCARD_TAG:
- logging.info("Skipping " + tag + " : " + option +
- " because target build variant is set to " +
- str(target_build_variant))
- continue
-
- if tag in keyMap:
- sys.exit("Duplicate tag detected " + tag)
-
- tag_path = os.path.expandvars(self.get(tag, option))
- path = os.path.join(key_directory, tag_path)
-
- keyMap[tag] = GenerateKeys(path)
-
- # Multiple certificates may exist in
- # the pem file. GenerateKeys supports
- # this however, the mac_permissions.xml
- # as well as PMS do not.
- assert len(keyMap[tag]) == 1
-
- return keyMap
-
-class ReplaceTags(handler.ContentHandler):
-
- DEFAULT_TAG = "default"
- PACKAGE_TAG = "package"
- POLICY_TAG = "policy"
- SIGNER_TAG = "signer"
- SIGNATURE_TAG = "signature"
-
- TAGS_WITH_CHILDREN = [ DEFAULT_TAG, PACKAGE_TAG, POLICY_TAG, SIGNER_TAG ]
-
- XML_ENCODING_TAG = ''
-
- def __init__(self, keyMap, out=sys.stdout):
-
- handler.ContentHandler.__init__(self)
- self._keyMap = keyMap
- self._out = out
- self._out.write(ReplaceTags.XML_ENCODING_TAG)
- self._out.write("")
- self._out.write("")
-
- def __del__(self):
- self._out.write("")
-
- def startElement(self, tag, attrs):
- if tag == ReplaceTags.POLICY_TAG:
- return
-
- self._out.write('<' + tag)
-
- for (name, value) in attrs.items():
-
- if name == ReplaceTags.SIGNATURE_TAG and value in self._keyMap:
- for key in self._keyMap[value].getBase16Keys():
- logging.info("Replacing " + name + " " + value + " with " + key)
- self._out.write(' %s="%s"' % (name, saxutils.escape(key)))
- else:
- self._out.write(' %s="%s"' % (name, saxutils.escape(value)))
-
- if tag in ReplaceTags.TAGS_WITH_CHILDREN:
- self._out.write('>')
- else:
- self._out.write('/>')
-
- def endElement(self, tag):
- if tag == ReplaceTags.POLICY_TAG:
- return
-
- if tag in ReplaceTags.TAGS_WITH_CHILDREN:
- self._out.write('%s>' % tag)
-
- def characters(self, content):
- if not content.isspace():
- self._out.write(saxutils.escape(content))
-
- def ignorableWhitespace(self, content):
- pass
-
- def processingInstruction(self, target, data):
- self._out.write('%s %s?>' % (target, data))
-
-if __name__ == "__main__":
-
- # Intentional double space to line up equls signs and opening " for
- # readability.
- usage = "usage: %prog [options] CONFIG_FILE MAC_PERMISSIONS_FILE [MAC_PERMISSIONS_FILE...]\n"
- usage += "This tool allows one to configure an automatic inclusion\n"
- usage += "of signing keys into the mac_permision.xml file(s) from the\n"
- usage += "pem files. If mulitple mac_permision.xml files are included\n"
- usage += "then they are unioned to produce a final version."
-
- version = "%prog " + str(__VERSION)
-
- parser = OptionParser(usage=usage, version=version)
-
- parser.add_option("-v", "--verbose",
- action="store_true", dest="verbose", default=False,
- help="Print internal operations to stdout")
-
- parser.add_option("-o", "--output", default="stdout", dest="output_file",
- metavar="FILE", help="Specify an output file, default is stdout")
-
- parser.add_option("-c", "--cwd", default=os.getcwd(), dest="root",
- metavar="DIR", help="Specify a root (CWD) directory to run this from, it" \
- "chdirs' AFTER loading the config file")
-
- parser.add_option("-t", "--target-build-variant", default="eng", dest="target_build_variant",
- help="Specify the TARGET_BUILD_VARIANT, defaults to eng")
-
- parser.add_option("-d", "--key-directory", default="", dest="key_directory",
- help="Specify a parent directory for keys")
-
- (options, args) = parser.parse_args()
-
- if len(args) < 2:
- parser.error("Must specify a config file (keys.conf) AND mac_permissions.xml file(s)!")
-
- logging.basicConfig(level=logging.INFO if options.verbose == True else logging.WARN)
-
- # Read the config file
- config = ParseConfig()
- config.read(args[0])
-
- os.chdir(options.root)
-
- output_file = sys.stdout if options.output_file == "stdout" else open(options.output_file, "w")
- logging.info("Setting output file to: " + options.output_file)
-
- # Generate the key list
- key_map = config.generateKeyMap(options.target_build_variant.lower(), options.key_directory)
- logging.info("Generate key map:")
- for k in key_map:
- logging.info(k + " : " + str(key_map[k]))
- # Generate the XML file with markup replaced with keys
- parser = make_parser()
- parser.setContentHandler(ReplaceTags(key_map, output_file))
- for f in args[1:]:
- parser.parse(f)
diff --git a/keys.conf b/keys.conf
deleted file mode 100644
index 7a307b5..0000000
--- a/keys.conf
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Maps an arbitrary tag [TAGNAME] with the string contents found in
-# TARGET_BUILD_VARIANT. Common convention is to start TAGNAME with an @ and
-# name it after the base file name of the pem file.
-#
-# Each tag (section) then allows one to specify any string found in
-# TARGET_BUILD_VARIANT. Typcially this is user, eng, and userdebug. Another
-# option is to use ALL which will match ANY TARGET_BUILD_VARIANT string.
-#
-
-[@PLATFORM]
-ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/platform.x509.pem
-
-[@MEDIA]
-ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/media.x509.pem
-
-[@SHARED]
-ALL : $DEFAULT_SYSTEM_DEV_CERTIFICATE/shared.x509.pem
-
-# Example of ALL TARGET_BUILD_VARIANTS
-[@RELEASE]
-ENG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem
-USER : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem
-USERDEBUG : $DEFAULT_SYSTEM_DEV_CERTIFICATE/testkey.x509.pem
-
diff --git a/linux-x86/aapt b/linux-x86/aapt
deleted file mode 100755
index 9a119c4..0000000
Binary files a/linux-x86/aapt and /dev/null differ
diff --git a/linux-x86/lib/libc++.so b/linux-x86/lib/libc++.so
deleted file mode 100755
index 0101d43..0000000
Binary files a/linux-x86/lib/libc++.so and /dev/null differ
diff --git a/linux-x86/mkbootimg b/linux-x86/mkbootimg
deleted file mode 100755
index 8b3b315..0000000
Binary files a/linux-x86/mkbootimg and /dev/null differ
diff --git a/linux-x86/unpackbootimg b/linux-x86/unpackbootimg
deleted file mode 100755
index 1c4eac2..0000000
Binary files a/linux-x86/unpackbootimg and /dev/null differ
diff --git a/linux-x86/zipalign b/linux-x86/zipalign
deleted file mode 100755
index 8186151..0000000
Binary files a/linux-x86/zipalign and /dev/null differ
diff --git a/make_key b/make_key
deleted file mode 100755
index 03ed880..0000000
--- a/make_key
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Generates a public/private key pair suitable for use in signing
-# android .apks and OTA update packages.
-
-if [ "$#" -lt 2 -o "$#" -gt 3 ]; then
- cat < []
-
-Creates .pk8 key and .x509.pem cert. Cert contains the
-given . A keytype of "rsa" or "ec" is accepted.
-EOF
- exit 2
-fi
-
-if [[ -e $1.pk8 || -e $1.x509.pem ]]; then
- echo "$1.pk8 and/or $1.x509.pem already exist; please delete them first"
- echo "if you want to replace them."
- exit 1
-fi
-
-# Use named pipes to connect get the raw RSA private key to the cert-
-# and .pk8-creating programs, to avoid having the private key ever
-# touch the disk.
-
-tmpdir=$(mktemp -d)
-trap 'rm -rf ${tmpdir}; echo; exit 1' EXIT INT QUIT
-
-one=${tmpdir}/one
-two=${tmpdir}/two
-mknod ${one} p
-mknod ${two} p
-chmod 0600 ${one} ${two}
-
-read -p "Enter password for '$1' (blank for none; password will be visible): " \
- password
-
-export RANDFILE=".rnd"
-
-if [ "${3}" = "rsa" -o "$#" -eq 2 ]; then
- ( openssl genrsa -f4 2048 | tee ${one} > ${two} ) &
- hash="-sha1"
-elif [ "${3}" = "ec" ]; then
- ( openssl ecparam -name prime256v1 -genkey -noout | tee ${one} > ${two} ) &
- hash="-sha256"
-else
- echo "Only accepts RSA or EC keytypes."
- exit 1
-fi
-
-openssl req -new -x509 ${hash} -key ${two} -out $1.x509.pem \
- -days 10000 -subj "$2" &
-
-if [ "${password}" == "" ]; then
- echo "creating ${1}.pk8 with no password"
- openssl pkcs8 -in ${one} -topk8 -outform DER -out $1.pk8 -nocrypt
-else
- echo "creating ${1}.pk8 with password [${password}]"
- export password
- openssl pkcs8 -in ${one} -topk8 -outform DER -out $1.pk8 \
- -passout env:password
- unset password
-fi
-
-wait
-wait
diff --git a/linux-x86/mkbootfs b/mkbootfs
similarity index 100%
rename from linux-x86/mkbootfs
rename to mkbootfs
diff --git a/mkbootimg b/mkbootimg
new file mode 100755
index 0000000..6ff4b84
Binary files /dev/null and b/mkbootimg differ
diff --git a/oat2dex b/oat2dex
deleted file mode 100755
index f91a83f..0000000
--- a/oat2dex
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2007 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# As per the Apache license requirements, this file has been modified
-# from its original state.
-#
-# Such modifications are Copyright (C) 2016 Miui Patchrom Project, and
-# are released under the original license
-
-# This script is a wrapper around oat2dex.jar, so you can simply call
-# "oat2dex", instead of java -jar oat2dex.jar. It is heavily based on
-# the "dx" script from the Android SDK
-
-# Set up prog to be the path of this script, including following symlinks,
-# and set up progdir to be the fully-qualified pathname of its directory.
-prog="$0"
-while [ -h "${prog}" ]; do
- newProg=`/bin/ls -ld "${prog}"`
- echo ${newProg}
-
-
- newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
- if expr "x${newProg}" : 'x/' >/dev/null; then
- prog="${newProg}"
- else
- progdir=`dirname "${prog}"`
- prog="${progdir}/${newProg}"
- fi
-done
-oldwd=`pwd`
-progdir=`dirname "${prog}"`
-cd "${progdir}"
-progdir=`pwd`
-prog="${progdir}"/`basename "${prog}"`
-cd "${oldwd}"
-
-
-jarfile=oat2dex.jar
-libdir="$progdir"
-if [ ! -r "$libdir/$jarfile" ]
-then
- echo `basename "$prog"`": can't find $jarfile"
- exit 1
-fi
-
-javaOpts=""
-
-# If you want DX to have more memory when executing, uncomment the following
-# line and adjust the value accordingly. Use "java -X" for a list of options
-# you can pass here.
-#
-javaOpts="-Xmx1024M"
-
-# Alternatively, this will extract any parameter "-Jxxx" from the command line
-# and pass them to Java (instead of to dx). This makes it possible for you to
-# add a command-line parameter such as "-JXmx256M" in your ant scripts, for
-# example.
-while expr "x$1" : 'x-J' >/dev/null; do
- opt=`expr "$1" : '-J\(.*\)'`
- javaOpts="${javaOpts} -${opt}"
- shift
-done
-
-if [ "$OSTYPE" = "cygwin" ] ; then
- jarpath=`cygpath -w "$libdir/$jarfile"`
-else
- jarpath="$libdir/$jarfile"
-fi
-
-exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/oat2dex-0.86.jar b/oat2dex-0.86.jar
deleted file mode 100644
index 8f1a611..0000000
Binary files a/oat2dex-0.86.jar and /dev/null differ
diff --git a/oat2dex-0.87.jar b/oat2dex-0.87.jar
deleted file mode 100644
index bf0eab8..0000000
Binary files a/oat2dex-0.87.jar and /dev/null differ
diff --git a/oat2dex.jar b/oat2dex.jar
deleted file mode 120000
index 696f33d..0000000
--- a/oat2dex.jar
+++ /dev/null
@@ -1 +0,0 @@
-oat2dex-0.87.jar
\ No newline at end of file
diff --git a/patch_bootimg.sh b/patch_bootimg.sh
deleted file mode 100755
index 17f0775..0000000
--- a/patch_bootimg.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-
-if [ -f "./patch_bootimg.sh" ];then
- bash ./patch_bootimg.sh $1
- exit $?
-fi
-
-BOOTIMG=$1
-
-# Unpack bootimg
-rm -rf $TARGET_BOOT_DIR
-mkdir -p $TARGET_BOOT_DIR
-$UNPACKBOOTIMG -i $BOOTIMG -o $TARGET_BOOT_DIR > /dev/null
-
-# Unpack ramdisk
-gunzip $TARGET_BOOT_DIR/boot.img-ramdisk.gz
-mkdir -p $TARGET_BOOT_DIR/ramdisk
-cd $TARGET_BOOT_DIR/ramdisk
-cpio -i < ../boot.img-ramdisk
-cd - > /dev/null
-
-# Change init
-if [ ! -f $TARGET_BOOT_DIR/ramdisk/init_vendor ];then
-mv $TARGET_BOOT_DIR/ramdisk/init $TARGET_BOOT_DIR/ramdisk/init_vendor
-fi
-cp -f $PREBUILT_BOOT_DIR/$TARGET_BIT/init $TARGET_BOOT_DIR/ramdisk/init
-
-# Pack ramdisk
-$MKBOOTFS $TARGET_BOOT_DIR/ramdisk | gzip > $TARGET_BOOT_DIR/ramdisk.gz
-
-
-# Disable selinux
-OLDCMDLINE=$(cat $TARGET_BOOT_DIR/boot.img-cmdline)
-NEWCMDLINE="androidboot.selinux=disabled"
-for prop in $OLDCMDLINE
-do
- echo $prop | grep "androidboot.selinux=" > /dev/null
- if [ $? -eq 0 ];then
- continue
- fi
- NEWCMDLINE="$NEWCMDLINE $prop"
-done
-
-echo "NEWCMDLINE: $NEWCMDLINE"
-
-BASEADDR=$(cat $TARGET_BOOT_DIR/boot.img-base)
-PAGESIZE=$(cat $TARGET_BOOT_DIR/boot.img-pagesize)
-RAMDISKOFFSET=$(cat $TARGET_BOOT_DIR/boot.img-ramdisk_offset)
-TAGSOFFSET=$(cat $TARGET_BOOT_DIR/boot.img-tags_offset)
-
-# Pack bootimg
-$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
diff --git a/patch_miui_app.sh b/patch_miui_app.sh
index 8cc67ae..bb4d001 100755
--- a/patch_miui_app.sh
+++ b/patch_miui_app.sh
@@ -10,18 +10,16 @@ if [ -f "customize_miui_app.sh" ]; then
fi
fi
-if [ -f $1 ];then
- if [ $1 = "MiuiHome" ];then
- if [ -f $1/res/xml/default_workspace.xml.part ]; then
- $PORT_ROOT/tools/gen_desklayout.pl $1/res/xml/default_workspace.xml.part $2/res/xml
- for file in $2/res/xml/default_workspace*.xml; do
- mv $file.new $file
- done
- fi
- fi
-
- # patch *.smali.method under $1
- for file in `find $1 -name "*.smali.method"`; do
- $PORT_ROOT/tools/replace_smali_method.sh apply $file
- done
+if [ $1 = "MiuiHome" ];then
+ if [ -f $1/res/xml/default_workspace.xml.part ]; then
+ $PORT_ROOT/tools/gen_desklayout.pl $1/res/xml/default_workspace.xml.part $2/res/xml
+ for file in $2/res/xml/default_workspace*.xml; do
+ mv $file.new $file
+ done
+ fi
fi
+
+# patch *.smali.method under $1
+for file in `find $1 -name "*.smali.method"`; do
+ $PORT_ROOT/tools/replace_smali_method.sh apply $file
+done
diff --git a/patch_miui_framework.sh b/patch_miui_framework.sh
index 7ef2f65..96ce5be 100755
--- a/patch_miui_framework.sh
+++ b/patch_miui_framework.sh
@@ -80,10 +80,10 @@ function apply_miui_patch() {
rm -rf $dst_code_orig
}
-jar_outs=`find $new_smali_dir -name "*.jar.out"`
+jar_outs=`grep -rn "JAR_OUTS" $new_smali_dir/README | cut -d'=' -f2`
for out in $jar_outs
do
- apply_miui_patch $(basename $out)
+ apply_miui_patch $out
done
echo
diff --git a/post_process_props.py b/post_process_props.py
deleted file mode 100755
index 0387d6e..0000000
--- a/post_process_props.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-
-# Put the modifications that you need to make into the /system/build.prop into this
-# function. The prop object has get(name) and put(name,value) methods.
-def mangle_build_prop(prop, overlaylines):
- for i in range(0,len(overlaylines)):
- pair = overlaylines[i].split('=')
- if len(pair) == 2:
- name = pair[0].strip()
- value = pair[1].strip()
- if not name.startswith("#"):
- prop.put(name,value)
- pass
-
-class PropFile:
- def __init__(self, lines):
- self.lines = [s[:-1] for s in lines]
-
- def get(self, name):
- key = name + "="
- for line in self.lines:
- if line.startswith(key):
- return line[len(key):]
- return ""
-
- def put(self, name, value):
- key = name + "="
- for i in range(0,len(self.lines)):
- if self.lines[i].startswith(key):
- self.lines[i] = key + value
- return
- self.lines.append(key + value)
-
- def delete(self, name):
- key = name + "="
- i = 0
- while i < len(self.lines):
- if self.lines[i].startswith(key):
- del self.lines[i]
- else:
- i += 1
-
- def write(self, f):
- f.write("\n".join(self.lines))
- f.write("\n")
-
-def main(argv):
- srcfilename = argv[1]
- overlayfilename = argv[2]
- fs = open(srcfilename)
- srclines = fs.readlines()
- fs.close()
-
- fo = open(overlayfilename)
- overlaylines = fo.readlines()
- fo.close()
-
- properties = PropFile(srclines)
- if srcfilename.endswith("/build.prop"):
- mangle_build_prop(properties, overlaylines)
- else:
- sys.stderr.write("bad command line: " + str(argv) + "\n")
- sys.exit(1)
-
- fs = open(srcfilename, 'w+')
- properties.write(fs)
- fs.close()
-
-if __name__ == "__main__":
- main(sys.argv)
diff --git a/releasetools/blockimgdiff.py b/releasetools/blockimgdiff.py
deleted file mode 100644
index 6ed9ca2..0000000
--- a/releasetools/blockimgdiff.py
+++ /dev/null
@@ -1,910 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import print_function
-
-from collections import deque, OrderedDict
-from hashlib import sha1
-import heapq
-import itertools
-import multiprocessing
-import os
-import re
-import subprocess
-import threading
-import tempfile
-
-from rangelib import RangeSet
-
-
-__all__ = ["EmptyImage", "DataImage", "BlockImageDiff"]
-
-
-def compute_patch(src, tgt, imgdiff=False):
- srcfd, srcfile = tempfile.mkstemp(prefix="src-")
- tgtfd, tgtfile = tempfile.mkstemp(prefix="tgt-")
- patchfd, patchfile = tempfile.mkstemp(prefix="patch-")
- os.close(patchfd)
-
- try:
- with os.fdopen(srcfd, "wb") as f_src:
- for p in src:
- f_src.write(p)
-
- with os.fdopen(tgtfd, "wb") as f_tgt:
- for p in tgt:
- f_tgt.write(p)
- try:
- os.unlink(patchfile)
- except OSError:
- pass
- if imgdiff:
- p = subprocess.call(["imgdiff", "-z", srcfile, tgtfile, patchfile],
- stdout=open("/dev/null", "a"),
- stderr=subprocess.STDOUT)
- else:
- p = subprocess.call(["bsdiff", srcfile, tgtfile, patchfile])
-
- if p:
- raise ValueError("diff failed: " + str(p))
-
- with open(patchfile, "rb") as f:
- return f.read()
- finally:
- try:
- os.unlink(srcfile)
- os.unlink(tgtfile)
- os.unlink(patchfile)
- except OSError:
- pass
-
-
-class Image(object):
- def ReadRangeSet(self, ranges):
- raise NotImplementedError
-
- def TotalSha1(self, include_clobbered_blocks=False):
- raise NotImplementedError
-
-
-class EmptyImage(Image):
- """A zero-length image."""
- blocksize = 4096
- care_map = RangeSet()
- clobbered_blocks = RangeSet()
- extended = RangeSet()
- total_blocks = 0
- file_map = {}
- def ReadRangeSet(self, ranges):
- return ()
- def TotalSha1(self, include_clobbered_blocks=False):
- # EmptyImage always carries empty clobbered_blocks, so
- # include_clobbered_blocks can be ignored.
- assert self.clobbered_blocks.size() == 0
- return sha1().hexdigest()
-
-
-class DataImage(Image):
- """An image wrapped around a single string of data."""
-
- def __init__(self, data, trim=False, pad=False):
- self.data = data
- self.blocksize = 4096
-
- assert not (trim and pad)
-
- partial = len(self.data) % self.blocksize
- if partial > 0:
- if trim:
- self.data = self.data[:-partial]
- elif pad:
- self.data += '\0' * (self.blocksize - partial)
- else:
- raise ValueError(("data for DataImage must be multiple of %d bytes "
- "unless trim or pad is specified") %
- (self.blocksize,))
-
- assert len(self.data) % self.blocksize == 0
-
- self.total_blocks = len(self.data) / self.blocksize
- self.care_map = RangeSet(data=(0, self.total_blocks))
- self.clobbered_blocks = RangeSet()
- self.extended = RangeSet()
-
- zero_blocks = []
- nonzero_blocks = []
- reference = '\0' * self.blocksize
-
- for i in range(self.total_blocks):
- d = self.data[i*self.blocksize : (i+1)*self.blocksize]
- if d == reference:
- zero_blocks.append(i)
- zero_blocks.append(i+1)
- else:
- nonzero_blocks.append(i)
- nonzero_blocks.append(i+1)
-
- self.file_map = {"__ZERO": RangeSet(zero_blocks),
- "__NONZERO": RangeSet(nonzero_blocks)}
-
- def ReadRangeSet(self, ranges):
- return [self.data[s*self.blocksize:e*self.blocksize] for (s, e) in ranges]
-
- def TotalSha1(self, include_clobbered_blocks=False):
- # DataImage always carries empty clobbered_blocks, so
- # include_clobbered_blocks can be ignored.
- assert self.clobbered_blocks.size() == 0
- return sha1(self.data).hexdigest()
-
-
-class Transfer(object):
- def __init__(self, tgt_name, src_name, tgt_ranges, src_ranges, style, by_id):
- self.tgt_name = tgt_name
- self.src_name = src_name
- self.tgt_ranges = tgt_ranges
- self.src_ranges = src_ranges
- self.style = style
- self.intact = (getattr(tgt_ranges, "monotonic", False) and
- getattr(src_ranges, "monotonic", False))
-
- # We use OrderedDict rather than dict so that the output is repeatable;
- # otherwise it would depend on the hash values of the Transfer objects.
- self.goes_before = OrderedDict()
- self.goes_after = OrderedDict()
-
- self.stash_before = []
- self.use_stash = []
-
- self.id = len(by_id)
- by_id.append(self)
-
- def NetStashChange(self):
- return (sum(sr.size() for (_, sr) in self.stash_before) -
- sum(sr.size() for (_, sr) in self.use_stash))
-
- def __str__(self):
- return (str(self.id) + ": <" + str(self.src_ranges) + " " + self.style +
- " to " + str(self.tgt_ranges) + ">")
-
-
-# BlockImageDiff works on two image objects. An image object is
-# anything that provides the following attributes:
-#
-# blocksize: the size in bytes of a block, currently must be 4096.
-#
-# total_blocks: the total size of the partition/image, in blocks.
-#
-# care_map: a RangeSet containing which blocks (in the range [0,
-# total_blocks) we actually care about; i.e. which blocks contain
-# data.
-#
-# file_map: a dict that partitions the blocks contained in care_map
-# into smaller domains that are useful for doing diffs on.
-# (Typically a domain is a file, and the key in file_map is the
-# pathname.)
-#
-# clobbered_blocks: a RangeSet containing which blocks contain data
-# but may be altered by the FS. They need to be excluded when
-# verifying the partition integrity.
-#
-# ReadRangeSet(): a function that takes a RangeSet and returns the
-# data contained in the image blocks of that RangeSet. The data
-# is returned as a list or tuple of strings; concatenating the
-# elements together should produce the requested data.
-# Implementations are free to break up the data into list/tuple
-# elements in any way that is convenient.
-#
-# TotalSha1(): a function that returns (as a hex string) the SHA-1
-# hash of all the data in the image (ie, all the blocks in the
-# care_map minus clobbered_blocks, or including the clobbered
-# blocks if include_clobbered_blocks is True).
-#
-# When creating a BlockImageDiff, the src image may be None, in which
-# case the list of transfers produced will never read from the
-# original image.
-
-class BlockImageDiff(object):
- def __init__(self, tgt, src=None, threads=None, version=3):
- if threads is None:
- threads = multiprocessing.cpu_count() // 2
- if threads == 0:
- threads = 1
- self.threads = threads
- self.version = version
- self.transfers = []
- self.src_basenames = {}
- self.src_numpatterns = {}
-
- assert version in (1, 2, 3)
-
- self.tgt = tgt
- if src is None:
- src = EmptyImage()
- self.src = src
-
- # The updater code that installs the patch always uses 4k blocks.
- assert tgt.blocksize == 4096
- assert src.blocksize == 4096
-
- # The range sets in each filemap should comprise a partition of
- # the care map.
- self.AssertPartition(src.care_map, src.file_map.values())
- self.AssertPartition(tgt.care_map, tgt.file_map.values())
-
- def Compute(self, prefix):
- # When looking for a source file to use as the diff input for a
- # target file, we try:
- # 1) an exact path match if available, otherwise
- # 2) a exact basename match if available, otherwise
- # 3) a basename match after all runs of digits are replaced by
- # "#" if available, otherwise
- # 4) we have no source for this target.
- self.AbbreviateSourceNames()
- self.FindTransfers()
-
- # Find the ordering dependencies among transfers (this is O(n^2)
- # in the number of transfers).
- self.GenerateDigraph()
- # Find a sequence of transfers that satisfies as many ordering
- # dependencies as possible (heuristically).
- self.FindVertexSequence()
- # Fix up the ordering dependencies that the sequence didn't
- # satisfy.
- if self.version == 1:
- self.RemoveBackwardEdges()
- else:
- self.ReverseBackwardEdges()
- self.ImproveVertexSequence()
-
- # Double-check our work.
- self.AssertSequenceGood()
-
- self.ComputePatches(prefix)
- self.WriteTransfers(prefix)
-
- def HashBlocks(self, source, ranges): # pylint: disable=no-self-use
- data = source.ReadRangeSet(ranges)
- ctx = sha1()
-
- for p in data:
- ctx.update(p)
-
- return ctx.hexdigest()
-
- def WriteTransfers(self, prefix):
- out = []
-
- total = 0
- performs_read = False
-
- stashes = {}
- stashed_blocks = 0
- max_stashed_blocks = 0
-
- free_stash_ids = []
- next_stash_id = 0
-
- for xf in self.transfers:
-
- if self.version < 2:
- assert not xf.stash_before
- assert not xf.use_stash
-
- for s, sr in xf.stash_before:
- assert s not in stashes
- if free_stash_ids:
- sid = heapq.heappop(free_stash_ids)
- else:
- sid = next_stash_id
- next_stash_id += 1
- stashes[s] = sid
- stashed_blocks += sr.size()
- if self.version == 2:
- out.append("stash %d %s\n" % (sid, sr.to_string_raw()))
- else:
- sh = self.HashBlocks(self.src, sr)
- if sh in stashes:
- stashes[sh] += 1
- else:
- stashes[sh] = 1
- out.append("stash %s %s\n" % (sh, sr.to_string_raw()))
-
- if stashed_blocks > max_stashed_blocks:
- max_stashed_blocks = stashed_blocks
-
- free_string = []
-
- if self.version == 1:
- src_str = xf.src_ranges.to_string_raw()
- elif self.version >= 2:
-
- # <# blocks>
- # OR
- # <# blocks>
- # OR
- # <# blocks> -
-
- size = xf.src_ranges.size()
- src_str = [str(size)]
-
- unstashed_src_ranges = xf.src_ranges
- mapped_stashes = []
- for s, sr in xf.use_stash:
- sid = stashes.pop(s)
- stashed_blocks -= sr.size()
- unstashed_src_ranges = unstashed_src_ranges.subtract(sr)
- sh = self.HashBlocks(self.src, sr)
- sr = xf.src_ranges.map_within(sr)
- mapped_stashes.append(sr)
- if self.version == 2:
- src_str.append("%d:%s" % (sid, sr.to_string_raw()))
- else:
- assert sh in stashes
- src_str.append("%s:%s" % (sh, sr.to_string_raw()))
- stashes[sh] -= 1
- if stashes[sh] == 0:
- free_string.append("free %s\n" % (sh))
- stashes.pop(sh)
- heapq.heappush(free_stash_ids, sid)
-
- if unstashed_src_ranges:
- src_str.insert(1, unstashed_src_ranges.to_string_raw())
- if xf.use_stash:
- mapped_unstashed = xf.src_ranges.map_within(unstashed_src_ranges)
- src_str.insert(2, mapped_unstashed.to_string_raw())
- mapped_stashes.append(mapped_unstashed)
- self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
- else:
- src_str.insert(1, "-")
- self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
-
- src_str = " ".join(src_str)
-
- # all versions:
- # zero
- # new
- # erase
- #
- # version 1:
- # bsdiff patchstart patchlen
- # imgdiff patchstart patchlen
- # move
- #
- # version 2:
- # bsdiff patchstart patchlen
- # imgdiff patchstart patchlen
- # move
- #
- # version 3:
- # bsdiff patchstart patchlen srchash tgthash
- # imgdiff patchstart patchlen srchash tgthash
- # move hash
-
- tgt_size = xf.tgt_ranges.size()
-
- if xf.style == "new":
- assert xf.tgt_ranges
- out.append("%s %s\n" % (xf.style, xf.tgt_ranges.to_string_raw()))
- total += tgt_size
- elif xf.style == "move":
- performs_read = True
- assert xf.tgt_ranges
- assert xf.src_ranges.size() == tgt_size
- if xf.src_ranges != xf.tgt_ranges:
- if self.version == 1:
- out.append("%s %s %s\n" % (
- xf.style,
- xf.src_ranges.to_string_raw(), xf.tgt_ranges.to_string_raw()))
- elif self.version == 2:
- out.append("%s %s %s\n" % (
- xf.style,
- xf.tgt_ranges.to_string_raw(), src_str))
- elif self.version >= 3:
- # take into account automatic stashing of overlapping blocks
- if xf.src_ranges.overlaps(xf.tgt_ranges):
- temp_stash_usage = stashed_blocks + xf.src_ranges.size()
- if temp_stash_usage > max_stashed_blocks:
- max_stashed_blocks = temp_stash_usage
-
- out.append("%s %s %s %s\n" % (
- xf.style,
- self.HashBlocks(self.tgt, xf.tgt_ranges),
- xf.tgt_ranges.to_string_raw(), src_str))
- total += tgt_size
- elif xf.style in ("bsdiff", "imgdiff"):
- performs_read = True
- assert xf.tgt_ranges
- assert xf.src_ranges
- if self.version == 1:
- out.append("%s %d %d %s %s\n" % (
- xf.style, xf.patch_start, xf.patch_len,
- xf.src_ranges.to_string_raw(), xf.tgt_ranges.to_string_raw()))
- elif self.version == 2:
- out.append("%s %d %d %s %s\n" % (
- xf.style, xf.patch_start, xf.patch_len,
- xf.tgt_ranges.to_string_raw(), src_str))
- elif self.version >= 3:
- # take into account automatic stashing of overlapping blocks
- if xf.src_ranges.overlaps(xf.tgt_ranges):
- temp_stash_usage = stashed_blocks + xf.src_ranges.size()
- if temp_stash_usage > max_stashed_blocks:
- max_stashed_blocks = temp_stash_usage
-
- out.append("%s %d %d %s %s %s %s\n" % (
- xf.style,
- xf.patch_start, xf.patch_len,
- self.HashBlocks(self.src, xf.src_ranges),
- self.HashBlocks(self.tgt, xf.tgt_ranges),
- xf.tgt_ranges.to_string_raw(), src_str))
- total += tgt_size
- elif xf.style == "zero":
- assert xf.tgt_ranges
- to_zero = xf.tgt_ranges.subtract(xf.src_ranges)
- if to_zero:
- out.append("%s %s\n" % (xf.style, to_zero.to_string_raw()))
- total += to_zero.size()
- else:
- raise ValueError("unknown transfer style '%s'\n" % xf.style)
-
- if free_string:
- out.append("".join(free_string))
-
- # sanity check: abort if we're going to need more than 512 MB if
- # stash space
- assert max_stashed_blocks * self.tgt.blocksize < (512 << 20)
-
- # Zero out extended blocks as a workaround for bug 20881595.
- if self.tgt.extended:
- out.append("zero %s\n" % (self.tgt.extended.to_string_raw(),))
-
- # We erase all the blocks on the partition that a) don't contain useful
- # data in the new image and b) will not be touched by dm-verity.
- all_tgt = RangeSet(data=(0, self.tgt.total_blocks))
- all_tgt_minus_extended = all_tgt.subtract(self.tgt.extended)
- new_dontcare = all_tgt_minus_extended.subtract(self.tgt.care_map)
- if new_dontcare:
- out.append("erase %s\n" % (new_dontcare.to_string_raw(),))
-
- out.insert(0, "%d\n" % (self.version,)) # format version number
- out.insert(1, str(total) + "\n")
- if self.version >= 2:
- # version 2 only: after the total block count, we give the number
- # of stash slots needed, and the maximum size needed (in blocks)
- out.insert(2, str(next_stash_id) + "\n")
- out.insert(3, str(max_stashed_blocks) + "\n")
-
- with open(prefix + ".transfer.list", "wb") as f:
- for i in out:
- f.write(i)
-
- if self.version >= 2:
- print("max stashed blocks: %d (%d bytes)\n" % (
- max_stashed_blocks, max_stashed_blocks * self.tgt.blocksize))
-
- def ComputePatches(self, prefix):
- print("Reticulating splines...")
- diff_q = []
- patch_num = 0
- with open(prefix + ".new.dat", "wb") as new_f:
- for xf in self.transfers:
- if xf.style == "zero":
- pass
- elif xf.style == "new":
- for piece in self.tgt.ReadRangeSet(xf.tgt_ranges):
- new_f.write(piece)
- elif xf.style == "diff":
- src = self.src.ReadRangeSet(xf.src_ranges)
- tgt = self.tgt.ReadRangeSet(xf.tgt_ranges)
-
- # We can't compare src and tgt directly because they may have
- # the same content but be broken up into blocks differently, eg:
- #
- # ["he", "llo"] vs ["h", "ello"]
- #
- # We want those to compare equal, ideally without having to
- # actually concatenate the strings (these may be tens of
- # megabytes).
-
- src_sha1 = sha1()
- for p in src:
- src_sha1.update(p)
- tgt_sha1 = sha1()
- tgt_size = 0
- for p in tgt:
- tgt_sha1.update(p)
- tgt_size += len(p)
-
- if src_sha1.digest() == tgt_sha1.digest():
- # These are identical; we don't need to generate a patch,
- # just issue copy commands on the device.
- xf.style = "move"
- else:
- # For files in zip format (eg, APKs, JARs, etc.) we would
- # like to use imgdiff -z if possible (because it usually
- # produces significantly smaller patches than bsdiff).
- # This is permissible if:
- #
- # - the source and target files are monotonic (ie, the
- # data is stored with blocks in increasing order), and
- # - we haven't removed any blocks from the source set.
- #
- # If these conditions are satisfied then appending all the
- # blocks in the set together in order will produce a valid
- # zip file (plus possibly extra zeros in the last block),
- # which is what imgdiff needs to operate. (imgdiff is
- # fine with extra zeros at the end of the file.)
- imgdiff = (xf.intact and
- xf.tgt_name.split(".")[-1].lower()
- in ("apk", "jar", "zip"))
- xf.style = "imgdiff" if imgdiff else "bsdiff"
- diff_q.append((tgt_size, src, tgt, xf, patch_num))
- patch_num += 1
-
- else:
- assert False, "unknown style " + xf.style
-
- if diff_q:
- if self.threads > 1:
- print("Computing patches (using %d threads)..." % (self.threads,))
- else:
- print("Computing patches...")
- diff_q.sort()
-
- patches = [None] * patch_num
-
- # TODO: Rewrite with multiprocessing.ThreadPool?
- lock = threading.Lock()
- def diff_worker():
- while True:
- with lock:
- if not diff_q:
- return
- tgt_size, src, tgt, xf, patchnum = diff_q.pop()
- patch = compute_patch(src, tgt, imgdiff=(xf.style == "imgdiff"))
- size = len(patch)
- with lock:
- patches[patchnum] = (patch, xf)
- print("%10d %10d (%6.2f%%) %7s %s" % (
- size, tgt_size, size * 100.0 / tgt_size, xf.style,
- xf.tgt_name if xf.tgt_name == xf.src_name else (
- xf.tgt_name + " (from " + xf.src_name + ")")))
-
- threads = [threading.Thread(target=diff_worker)
- for _ in range(self.threads)]
- for th in threads:
- th.start()
- while threads:
- threads.pop().join()
- else:
- patches = []
-
- p = 0
- with open(prefix + ".patch.dat", "wb") as patch_f:
- for patch, xf in patches:
- xf.patch_start = p
- xf.patch_len = len(patch)
- patch_f.write(patch)
- p += len(patch)
-
- def AssertSequenceGood(self):
- # Simulate the sequences of transfers we will output, and check that:
- # - we never read a block after writing it, and
- # - we write every block we care about exactly once.
-
- # Start with no blocks having been touched yet.
- touched = RangeSet()
-
- # Imagine processing the transfers in order.
- for xf in self.transfers:
- # Check that the input blocks for this transfer haven't yet been touched.
-
- x = xf.src_ranges
- if self.version >= 2:
- for _, sr in xf.use_stash:
- x = x.subtract(sr)
-
- assert not touched.overlaps(x)
- # Check that the output blocks for this transfer haven't yet been touched.
- assert not touched.overlaps(xf.tgt_ranges)
- # Touch all the blocks written by this transfer.
- touched = touched.union(xf.tgt_ranges)
-
- # Check that we've written every target block.
- assert touched == self.tgt.care_map
-
- def ImproveVertexSequence(self):
- print("Improving vertex order...")
-
- # At this point our digraph is acyclic; we reversed any edges that
- # were backwards in the heuristically-generated sequence. The
- # previously-generated order is still acceptable, but we hope to
- # find a better order that needs less memory for stashed data.
- # Now we do a topological sort to generate a new vertex order,
- # using a greedy algorithm to choose which vertex goes next
- # whenever we have a choice.
-
- # Make a copy of the edge set; this copy will get destroyed by the
- # algorithm.
- for xf in self.transfers:
- xf.incoming = xf.goes_after.copy()
- xf.outgoing = xf.goes_before.copy()
-
- L = [] # the new vertex order
-
- # S is the set of sources in the remaining graph; we always choose
- # the one that leaves the least amount of stashed data after it's
- # executed.
- S = [(u.NetStashChange(), u.order, u) for u in self.transfers
- if not u.incoming]
- heapq.heapify(S)
-
- while S:
- _, _, xf = heapq.heappop(S)
- L.append(xf)
- for u in xf.outgoing:
- del u.incoming[xf]
- if not u.incoming:
- heapq.heappush(S, (u.NetStashChange(), u.order, u))
-
- # if this fails then our graph had a cycle.
- assert len(L) == len(self.transfers)
-
- self.transfers = L
- for i, xf in enumerate(L):
- xf.order = i
-
- def RemoveBackwardEdges(self):
- print("Removing backward edges...")
- in_order = 0
- out_of_order = 0
- lost_source = 0
-
- for xf in self.transfers:
- lost = 0
- size = xf.src_ranges.size()
- for u in xf.goes_before:
- # xf should go before u
- if xf.order < u.order:
- # it does, hurray!
- in_order += 1
- else:
- # it doesn't, boo. trim the blocks that u writes from xf's
- # source, so that xf can go after u.
- out_of_order += 1
- assert xf.src_ranges.overlaps(u.tgt_ranges)
- xf.src_ranges = xf.src_ranges.subtract(u.tgt_ranges)
- xf.intact = False
-
- if xf.style == "diff" and not xf.src_ranges:
- # nothing left to diff from; treat as new data
- xf.style = "new"
-
- lost = size - xf.src_ranges.size()
- lost_source += lost
-
- print((" %d/%d dependencies (%.2f%%) were violated; "
- "%d source blocks removed.") %
- (out_of_order, in_order + out_of_order,
- (out_of_order * 100.0 / (in_order + out_of_order))
- if (in_order + out_of_order) else 0.0,
- lost_source))
-
- def ReverseBackwardEdges(self):
- print("Reversing backward edges...")
- in_order = 0
- out_of_order = 0
- stashes = 0
- stash_size = 0
-
- for xf in self.transfers:
- for u in xf.goes_before.copy():
- # xf should go before u
- if xf.order < u.order:
- # it does, hurray!
- in_order += 1
- else:
- # it doesn't, boo. modify u to stash the blocks that it
- # writes that xf wants to read, and then require u to go
- # before xf.
- out_of_order += 1
-
- overlap = xf.src_ranges.intersect(u.tgt_ranges)
- assert overlap
-
- u.stash_before.append((stashes, overlap))
- xf.use_stash.append((stashes, overlap))
- stashes += 1
- stash_size += overlap.size()
-
- # reverse the edge direction; now xf must go after u
- del xf.goes_before[u]
- del u.goes_after[xf]
- xf.goes_after[u] = None # value doesn't matter
- u.goes_before[xf] = None
-
- print((" %d/%d dependencies (%.2f%%) were violated; "
- "%d source blocks stashed.") %
- (out_of_order, in_order + out_of_order,
- (out_of_order * 100.0 / (in_order + out_of_order))
- if (in_order + out_of_order) else 0.0,
- stash_size))
-
- def FindVertexSequence(self):
- print("Finding vertex sequence...")
-
- # This is based on "A Fast & Effective Heuristic for the Feedback
- # Arc Set Problem" by P. Eades, X. Lin, and W.F. Smyth. Think of
- # it as starting with the digraph G and moving all the vertices to
- # be on a horizontal line in some order, trying to minimize the
- # number of edges that end up pointing to the left. Left-pointing
- # edges will get removed to turn the digraph into a DAG. In this
- # case each edge has a weight which is the number of source blocks
- # we'll lose if that edge is removed; we try to minimize the total
- # weight rather than just the number of edges.
-
- # Make a copy of the edge set; this copy will get destroyed by the
- # algorithm.
- for xf in self.transfers:
- xf.incoming = xf.goes_after.copy()
- xf.outgoing = xf.goes_before.copy()
-
- # We use an OrderedDict instead of just a set so that the output
- # is repeatable; otherwise it would depend on the hash values of
- # the transfer objects.
- G = OrderedDict()
- for xf in self.transfers:
- G[xf] = None
- s1 = deque() # the left side of the sequence, built from left to right
- s2 = deque() # the right side of the sequence, built from right to left
-
- while G:
-
- # Put all sinks at the end of the sequence.
- while True:
- sinks = [u for u in G if not u.outgoing]
- if not sinks:
- break
- for u in sinks:
- s2.appendleft(u)
- del G[u]
- for iu in u.incoming:
- del iu.outgoing[u]
-
- # Put all the sources at the beginning of the sequence.
- while True:
- sources = [u for u in G if not u.incoming]
- if not sources:
- break
- for u in sources:
- s1.append(u)
- del G[u]
- for iu in u.outgoing:
- del iu.incoming[u]
-
- if not G:
- break
-
- # Find the "best" vertex to put next. "Best" is the one that
- # maximizes the net difference in source blocks saved we get by
- # pretending it's a source rather than a sink.
-
- max_d = None
- best_u = None
- for u in G:
- d = sum(u.outgoing.values()) - sum(u.incoming.values())
- if best_u is None or d > max_d:
- max_d = d
- best_u = u
-
- u = best_u
- s1.append(u)
- del G[u]
- for iu in u.outgoing:
- del iu.incoming[u]
- for iu in u.incoming:
- del iu.outgoing[u]
-
- # Now record the sequence in the 'order' field of each transfer,
- # and by rearranging self.transfers to be in the chosen sequence.
-
- new_transfers = []
- for x in itertools.chain(s1, s2):
- x.order = len(new_transfers)
- new_transfers.append(x)
- del x.incoming
- del x.outgoing
-
- self.transfers = new_transfers
-
- def GenerateDigraph(self):
- print("Generating digraph...")
- for a in self.transfers:
- for b in self.transfers:
- if a is b:
- continue
-
- # If the blocks written by A are read by B, then B needs to go before A.
- i = a.tgt_ranges.intersect(b.src_ranges)
- if i:
- if b.src_name == "__ZERO":
- # the cost of removing source blocks for the __ZERO domain
- # is (nearly) zero.
- size = 0
- else:
- size = i.size()
- b.goes_before[a] = size
- a.goes_after[b] = size
-
- def FindTransfers(self):
- empty = RangeSet()
- for tgt_fn, tgt_ranges in self.tgt.file_map.items():
- if tgt_fn == "__ZERO":
- # the special "__ZERO" domain is all the blocks not contained
- # in any file and that are filled with zeros. We have a
- # special transfer style for zero blocks.
- src_ranges = self.src.file_map.get("__ZERO", empty)
- Transfer(tgt_fn, "__ZERO", tgt_ranges, src_ranges,
- "zero", self.transfers)
- continue
-
- elif tgt_fn == "__COPY":
- # "__COPY" domain includes all the blocks not contained in any
- # file and that need to be copied unconditionally to the target.
- Transfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
- continue
-
- elif tgt_fn in self.src.file_map:
- # Look for an exact pathname match in the source.
- Transfer(tgt_fn, tgt_fn, tgt_ranges, self.src.file_map[tgt_fn],
- "diff", self.transfers)
- continue
-
- b = os.path.basename(tgt_fn)
- if b in self.src_basenames:
- # Look for an exact basename match in the source.
- src_fn = self.src_basenames[b]
- Transfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
- "diff", self.transfers)
- continue
-
- b = re.sub("[0-9]+", "#", b)
- if b in self.src_numpatterns:
- # Look for a 'number pattern' match (a basename match after
- # all runs of digits are replaced by "#"). (This is useful
- # for .so files that contain version numbers in the filename
- # that get bumped.)
- src_fn = self.src_numpatterns[b]
- Transfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
- "diff", self.transfers)
- continue
-
- Transfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
-
- def AbbreviateSourceNames(self):
- for k in self.src.file_map.keys():
- b = os.path.basename(k)
- self.src_basenames[b] = k
- b = re.sub("[0-9]+", "#", b)
- self.src_numpatterns[b] = k
-
- @staticmethod
- def AssertPartition(total, seq):
- """Assert that all the RangeSets in 'seq' form a partition of the
- 'total' RangeSet (ie, they are nonintersecting and their union
- equals 'total')."""
- so_far = RangeSet()
- for i in seq:
- assert not so_far.overlaps(i)
- so_far = so_far.union(i)
- assert so_far == total
diff --git a/linux-x86/bsdiff b/releasetools/bsdiff
similarity index 100%
rename from linux-x86/bsdiff
rename to releasetools/bsdiff
diff --git a/releasetools/common.py b/releasetools/common.py
index f6eae50..c404cef 100644
--- a/releasetools/common.py
+++ b/releasetools/common.py
@@ -20,7 +20,6 @@
import os
import platform
import re
-import shlex
import shutil
import subprocess
import sys
@@ -29,43 +28,30 @@
import time
import zipfile
-import blockimgdiff
-import rangelib
-
-from hashlib import sha1 as sha1
-
-
-class Options(object):
- def __init__(self):
- self.search_path = os.path.join(os.environ["PORT_ROOT"], "tools");
- self.signapk_path = "signapk.jar" # Relative to search_path
- self.extra_signapk_args = []
- self.java_path = "java" # Use the one on the path by default.
- self.java_args = "-Xmx2048m" # JVM Args
- self.public_key_suffix = ".x509.pem"
- self.private_key_suffix = ".pk8"
- # use otatools built boot_signer by default
- self.boot_signer_path = "boot_signer"
- self.boot_signer_args = []
- self.verity_signer_path = None
- self.verity_signer_args = []
- self.verbose = False
- self.tempfiles = []
- self.device_specific = None
- self.extras = {}
- self.info_dict = None
- self.worker_threads = None
+try:
+ from hashlib import sha1 as sha1
+except ImportError:
+ from sha import sha as sha1
+# missing in Python 2.4 and before
+if not hasattr(os, "SEEK_SET"):
+ os.SEEK_SET = 0
+class Options(object): pass
OPTIONS = Options()
+OPTIONS.search_path = os.path.join(os.environ["PORT_ROOT"], "tools");
+OPTIONS.verbose = False
+OPTIONS.tempfiles = []
+OPTIONS.device_specific = None
+OPTIONS.extras = {}
+OPTIONS.info_dict = None
# Values for "certificate" in apkcerts that mean special things.
SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL")
-class ExternalError(RuntimeError):
- pass
+class ExternalError(RuntimeError): pass
def Run(args, **kwargs):
@@ -92,24 +78,17 @@ def CloseInheritedPipes():
pass
-def LoadInfoDict(input_file):
+def LoadInfoDict(zip):
"""Read and parse the META/misc_info.txt key/value pairs from the
input target files and return a dict."""
- def read_helper(fn):
- if isinstance(input_file, zipfile.ZipFile):
- return input_file.read(fn)
- else:
- path = os.path.join(input_file, *fn.split("/"))
- try:
- with open(path) as f:
- return f.read()
- except IOError as e:
- if e.errno == errno.ENOENT:
- raise KeyError(fn)
d = {}
try:
- d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n"))
+ for line in zip.read("META/misc_info.txt").split("\n"):
+ line = line.strip()
+ if not line or line.startswith("#"): continue
+ k, v = line.split("=", 1)
+ d[k] = v
except KeyError:
# ok if misc_info.txt doesn't exist
pass
@@ -120,37 +99,30 @@ def read_helper(fn):
if "mkyaffs2_extra_flags" not in d:
try:
- d["mkyaffs2_extra_flags"] = read_helper(
- "META/mkyaffs2-extra-flags.txt").strip()
+ d["mkyaffs2_extra_flags"] = zip.read("META/mkyaffs2-extra-flags.txt").strip()
except KeyError:
# ok if flags don't exist
pass
if "recovery_api_version" not in d:
try:
- d["recovery_api_version"] = read_helper(
- "META/recovery-api-version.txt").strip()
+ d["recovery_api_version"] = zip.read("META/recovery-api-version.txt").strip()
except KeyError:
raise ValueError("can't find recovery API version in input target-files")
if "tool_extensions" not in d:
try:
- d["tool_extensions"] = read_helper("META/tool-extensions.txt").strip()
+ d["tool_extensions"] = zip.read("META/tool-extensions.txt").strip()
except KeyError:
# ok if extensions don't exist
pass
- if "fstab_version" not in d:
- d["fstab_version"] = "1"
-
try:
- data = read_helper("META/imagesizes.txt")
+ data = zip.read("META/imagesizes.txt")
for line in data.split("\n"):
- if not line:
- continue
+ if not line: continue
name, value = line.split(" ", 1)
- if not value:
- continue
+ if not value: continue
if name == "blocksize":
d[name] = value
else:
@@ -165,129 +137,57 @@ def makeint(key):
makeint("recovery_api_version")
makeint("blocksize")
makeint("system_size")
- makeint("vendor_size")
makeint("userdata_size")
- makeint("cache_size")
- makeint("cust_size")
makeint("recovery_size")
makeint("boot_size")
- makeint("fstab_version")
- d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"])
- d["build.prop"] = LoadBuildProp(read_helper)
+ d["fstab"] = LoadRecoveryFSTab(zip)
return d
-def LoadBuildProp(read_helper):
- try:
- data = read_helper("SYSTEM/build.prop")
- except KeyError:
- print "Warning: could not find SYSTEM/build.prop in %s" % zip
- data = ""
- return LoadDictionaryFromLines(data.split("\n"))
-
-def LoadDictionaryFromLines(lines):
- d = {}
- for line in lines:
- line = line.strip()
- if not line or line.startswith("#"):
- continue
- if "=" in line:
- name, value = line.split("=", 1)
- d[name] = value
- return d
-
-def LoadRecoveryFSTab(read_helper, fstab_version):
+def LoadRecoveryFSTab(zip):
class Partition(object):
- def __init__(self, mount_point, fs_type, device, length, device2, context):
- self.mount_point = mount_point
- self.fs_type = fs_type
- self.device = device
- self.length = length
- self.device2 = device2
- self.context = context
+ pass
try:
- data = read_helper("RECOVERY/RAMDISK/etc/recovery.fstab")
+ data = zip.read("RECOVERY/RAMDISK/etc/recovery.fstab")
except KeyError:
- print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab"
+ print "Warning: could not find RECOVERY/RAMDISK/etc/recovery.fstab in %s." % zip
data = ""
- if fstab_version == 1:
- d = {}
- for line in data.split("\n"):
- line = line.strip()
- if not line or line.startswith("#"):
- continue
- pieces = line.split()
- if not 3 <= len(pieces) <= 4:
- raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
- options = None
- if len(pieces) >= 4:
- if pieces[3].startswith("/"):
- device2 = pieces[3]
- if len(pieces) >= 5:
- options = pieces[4]
- else:
- device2 = None
- options = pieces[3]
+ d = {}
+ for line in data.split("\n"):
+ line = line.strip()
+ if not line or line.startswith("#"): continue
+ pieces = line.split()
+ if not (3 <= len(pieces) <= 4):
+ raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
+
+ p = Partition()
+ p.mount_point = pieces[0]
+ p.fs_type = pieces[1]
+ p.device = pieces[2]
+ p.length = 0
+ options = None
+ if len(pieces) >= 4:
+ if pieces[3].startswith("/"):
+ p.device2 = pieces[3]
+ if len(pieces) >= 5:
+ options = pieces[4]
else:
- device2 = None
-
- mount_point = pieces[0]
- length = 0
- if options:
- options = options.split(",")
- for i in options:
- if i.startswith("length="):
- length = int(i[7:])
- else:
- print "%s: unknown option \"%s\"" % (mount_point, i)
-
- d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[1],
- device=pieces[2], length=length,
- device2=device2, context=None)
-
- elif fstab_version == 2:
- d = {}
- for line in data.split("\n"):
- line = line.strip()
- if not line or line.startswith("#"):
- continue
- #
- pieces = line.split()
- if len(pieces) != 5:
- raise ValueError("malformed recovery.fstab line: \"%s\"" % (line,))
-
- # Ignore entries that are managed by vold
- options = pieces[4]
- if "voldmanaged=" in options:
- continue
-
- # It's a good line, parse it
- length = 0
+ p.device2 = None
+ options = pieces[3]
+ else:
+ p.device2 = None
+
+ if options:
options = options.split(",")
for i in options:
if i.startswith("length="):
- length = int(i[7:])
+ p.length = int(i[7:])
else:
- # Ignore all unknown options in the unified fstab
- continue
-
- mount_flags = pieces[3]
- # Honor the SELinux context if present.
- context = None
- for i in mount_flags.split(","):
- if i.startswith("context="):
- context = i
-
- mount_point = pieces[1]
- d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[2],
- device=pieces[0], length=length,
- device2=None, context=context)
-
- else:
- raise ValueError("Unknown fstab_version: \"%d\"" % (fstab_version,))
+ print "%s: unknown option \"%s\"" % (p.mount_point, i)
+ d[p.mount_point] = p
return d
@@ -295,8 +195,7 @@ def DumpInfoDict(d):
for k, v in sorted(d.items()):
print "%-25s = (%s) %s" % (k, type(v).__name__, v)
-
-def BuildBootableImage(sourcedir, fs_config_file, info_dict=None):
+def BuildBootableImage(sourcedir):
"""Take a kernel, cmdline, and ramdisk directory from the input (in
'sourcedir'), and turn them into a boot image. Return the image
data, or None if sourcedir does not appear to contains files for
@@ -306,34 +205,20 @@ def BuildBootableImage(sourcedir, fs_config_file, info_dict=None):
not os.access(os.path.join(sourcedir, "kernel"), os.F_OK)):
return None
- if info_dict is None:
- info_dict = OPTIONS.info_dict
-
ramdisk_img = tempfile.NamedTemporaryFile()
img = tempfile.NamedTemporaryFile()
- if os.access(fs_config_file, os.F_OK):
- cmd = ["mkbootfs", "-f", fs_config_file, os.path.join(sourcedir, "RAMDISK")]
- else:
- cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
- p1 = Run(cmd, stdout=subprocess.PIPE)
+ p1 = Run(["mkbootfs", os.path.join(sourcedir, "RAMDISK")],
+ stdout=subprocess.PIPE)
p2 = Run(["minigzip"],
stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
p2.wait()
p1.wait()
- assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (sourcedir,)
- assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (sourcedir,)
-
- # use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
- mkbootimg = os.getenv('MKBOOTIMG') or "mkbootimg"
+ assert p1.returncode == 0, "mkbootfs of %s ramdisk failed" % (targetname,)
+ assert p2.returncode == 0, "minigzip of %s ramdisk failed" % (targetname,)
- cmd = [mkbootimg, "--kernel", os.path.join(sourcedir, "kernel")]
-
- fn = os.path.join(sourcedir, "second")
- if os.access(fn, os.F_OK):
- cmd.append("--second")
- cmd.append(fn)
+ cmd = ["mkbootimg", "--kernel", os.path.join(sourcedir, "kernel")]
fn = os.path.join(sourcedir, "cmdline")
if os.access(fn, os.F_OK):
@@ -350,52 +235,14 @@ def BuildBootableImage(sourcedir, fs_config_file, info_dict=None):
cmd.append("--pagesize")
cmd.append(open(fn).read().rstrip("\n"))
- args = info_dict.get("mkbootimg_args", None)
- if args and args.strip():
- cmd.extend(shlex.split(args))
-
- img_unsigned = None
- if info_dict.get("vboot", None):
- img_unsigned = tempfile.NamedTemporaryFile()
- cmd.extend(["--ramdisk", ramdisk_img.name,
- "--output", img_unsigned.name])
- else:
- cmd.extend(["--ramdisk", ramdisk_img.name,
- "--output", img.name])
+ cmd.extend(["--ramdisk", ramdisk_img.name,
+ "--output", img.name])
p = Run(cmd, stdout=subprocess.PIPE)
p.communicate()
assert p.returncode == 0, "mkbootimg of %s image failed" % (
os.path.basename(sourcedir),)
- if (info_dict.get("boot_signer", None) == "true" and
- info_dict.get("verity_key", None)):
- path = "/" + os.path.basename(sourcedir).lower()
- cmd = [OPTIONS.boot_signer_path]
- cmd.extend(OPTIONS.boot_signer_args)
- cmd.extend([path, img.name,
- info_dict["verity_key"] + ".pk8",
- info_dict["verity_key"] + ".x509.pem", img.name])
- p = Run(cmd, stdout=subprocess.PIPE)
- p.communicate()
- assert p.returncode == 0, "boot_signer of %s image failed" % path
-
- # Sign the image if vboot is non-empty.
- elif info_dict.get("vboot", None):
- path = "/" + os.path.basename(sourcedir).lower()
- img_keyblock = tempfile.NamedTemporaryFile()
- cmd = [info_dict["vboot_signer_cmd"], info_dict["futility"],
- img_unsigned.name, info_dict["vboot_key"] + ".vbpubk",
- info_dict["vboot_key"] + ".vbprivk", img_keyblock.name,
- img.name]
- p = Run(cmd, stdout=subprocess.PIPE)
- p.communicate()
- assert p.returncode == 0, "vboot_signer of %s image failed" % path
-
- # Clean up the temp files.
- img_unsigned.close()
- img_keyblock.close()
-
img.seek(os.SEEK_SET, 0)
data = img.read()
@@ -405,32 +252,20 @@ def BuildBootableImage(sourcedir, fs_config_file, info_dict=None):
return data
-def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
- info_dict=None):
+def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir):
"""Return a File object (with name 'name') with the desired bootable
image. Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name
- 'prebuilt_name', otherwise look for it under 'unpack_dir'/IMAGES,
- otherwise construct it from the source files in
+ 'prebuilt_name', otherwise construct it from the source files in
'unpack_dir'/'tree_subdir'."""
prebuilt_path = os.path.join(unpack_dir, "BOOTABLE_IMAGES", prebuilt_name)
if os.path.exists(prebuilt_path):
- print "using prebuilt %s from BOOTABLE_IMAGES..." % (prebuilt_name,)
+ print "using prebuilt %s..." % (prebuilt_name,)
return File.FromLocalFile(name, prebuilt_path)
-
- prebuilt_path = os.path.join(unpack_dir, "IMAGES", prebuilt_name)
- if os.path.exists(prebuilt_path):
- print "using prebuilt %s from IMAGES..." % (prebuilt_name,)
- return File.FromLocalFile(name, prebuilt_path)
-
- print "building image from target_files %s..." % (tree_subdir,)
- fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
- data = BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
- os.path.join(unpack_dir, fs_config),
- info_dict)
- if data:
- return File(name, data)
- return None
+ else:
+ return None
+ #print "building image from target_files %s..." % (tree_subdir,)
+ #return File(name, BuildBootableImage(os.path.join(unpack_dir, tree_subdir)))
def UnzipTemp(filename, pattern=None):
@@ -474,7 +309,6 @@ def GetKeyPasswords(keylist):
no_passwords = []
need_passwords = []
- key_passwords = {}
devnull = open("/dev/null", "w+b")
for k in sorted(keylist):
# We don't need a password for things that aren't really keys.
@@ -482,36 +316,19 @@ def GetKeyPasswords(keylist):
no_passwords.append(k)
continue
- p = Run(["openssl", "pkcs8", "-in", k+OPTIONS.private_key_suffix,
+ p = Run(["openssl", "pkcs8", "-in", k+".pk8",
"-inform", "DER", "-nocrypt"],
stdin=devnull.fileno(),
stdout=devnull.fileno(),
stderr=subprocess.STDOUT)
p.communicate()
if p.returncode == 0:
- # Definitely an unencrypted key.
no_passwords.append(k)
else:
- p = Run(["openssl", "pkcs8", "-in", k+OPTIONS.private_key_suffix,
- "-inform", "DER", "-passin", "pass:"],
- stdin=devnull.fileno(),
- stdout=devnull.fileno(),
- stderr=subprocess.PIPE)
- _, stderr = p.communicate()
- if p.returncode == 0:
- # Encrypted key with empty string as password.
- key_passwords[k] = ''
- elif stderr.startswith('Error decrypting key'):
- # Definitely encrypted key.
- # It would have said "Error reading key" if it didn't parse correctly.
- need_passwords.append(k)
- else:
- # Potentially, a type of key that openssl doesn't understand.
- # We'll let the routines in signapk.jar handle it.
- no_passwords.append(k)
+ need_passwords.append(k)
devnull.close()
- key_passwords.update(PasswordManager().GetPasswords(need_passwords))
+ key_passwords = PasswordManager().GetPasswords(need_passwords)
key_passwords.update(dict.fromkeys(no_passwords, None))
return key_passwords
@@ -539,13 +356,11 @@ def SignFile(input_name, output_name, key, password, align=None,
else:
sign_name = output_name
- cmd = [OPTIONS.java_path, OPTIONS.java_args, "-jar",
- os.path.join(OPTIONS.search_path, OPTIONS.signapk_path)]
- cmd.extend(OPTIONS.extra_signapk_args)
+ cmd = ["java", "-Xmx4096m", "-jar",
+ os.path.join(OPTIONS.search_path, "signapk.jar")]
if whole_file:
cmd.append("-w")
- cmd.extend([key + OPTIONS.public_key_suffix,
- key + OPTIONS.private_key_suffix,
+ cmd.extend([key + ".x509.pem", key + ".pk8",
input_name, sign_name])
p = Run(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
@@ -556,7 +371,7 @@ def SignFile(input_name, output_name, key, password, align=None,
raise ExternalError("signapk.jar failed: return code %s" % (p.returncode,))
if align:
- p = Run(["zipalign", "-f", "-p", str(align), sign_name, output_name])
+ p = Run(["zipalign", "-f", str(align), sign_name, output_name])
p.communicate()
if p.returncode != 0:
raise ExternalError("zipalign failed: return code %s" % (p.returncode,))
@@ -568,39 +383,31 @@ def CheckSize(data, target, info_dict):
any, for the given target. Raise exception if the data is too big.
Print a warning if the data is nearing the maximum size."""
- if target.endswith(".img"):
- target = target[:-4]
+ if target.endswith(".img"): target = target[:-4]
mount_point = "/" + target
- fs_type = None
- limit = None
if info_dict["fstab"]:
- if mount_point == "/userdata":
- mount_point = "/data"
+ if mount_point == "/userdata": mount_point = "/data"
p = info_dict["fstab"][mount_point]
fs_type = p.fs_type
- device = p.device
- if "/" in device:
- device = device[device.rfind("/")+1:]
- limit = info_dict.get(device + "_size", None)
- if not fs_type or not limit:
- return
+ limit = info_dict.get(p.device + "_size", None)
+ if not fs_type or not limit: return
if fs_type == "yaffs2":
# image size should be increased by 1/64th to account for the
# spare area (64 bytes per 2k page)
limit = limit / 2048 * (2048+64)
- size = len(data)
- pct = float(size) * 100.0 / limit
- msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
- if pct >= 99.0:
- raise ExternalError(msg)
- elif pct >= 95.0:
- print
- print " WARNING: ", msg
- print
- elif OPTIONS.verbose:
- print " ", msg
+ size = len(data)
+ pct = float(size) * 100.0 / limit
+ msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
+ if pct >= 99.0:
+ raise ExternalError(msg)
+ elif pct >= 95.0:
+ print
+ print " WARNING: ", msg
+ print
+ elif OPTIONS.verbose:
+ print " ", msg
def ReadApkCerts(tf_zip):
@@ -609,20 +416,17 @@ def ReadApkCerts(tf_zip):
certmap = {}
for line in tf_zip.read("META/apkcerts.txt").split("\n"):
line = line.strip()
- if not line:
- continue
+ if not line: continue
m = re.match(r'^name="(.*)"\s+certificate="(.*)"\s+'
r'private_key="(.*)"$', line)
if m:
name, cert, privkey = m.groups()
- public_key_suffix_len = len(OPTIONS.public_key_suffix)
- private_key_suffix_len = len(OPTIONS.private_key_suffix)
if cert in SPECIAL_CERT_STRINGS and not privkey:
certmap[name] = cert
- elif (cert.endswith(OPTIONS.public_key_suffix) and
- privkey.endswith(OPTIONS.private_key_suffix) and
- cert[:-public_key_suffix_len] == privkey[:-private_key_suffix_len]):
- certmap[name] = cert[:-public_key_suffix_len]
+ elif (cert.endswith(".x509.pem") and
+ privkey.endswith(".pk8") and
+ cert[:-9] == privkey[:-4]):
+ certmap[name] = cert[:-9]
else:
raise ValueError("failed to parse line from apkcerts.txt:\n" + line)
return certmap
@@ -666,17 +470,15 @@ def ParseOptions(argv,
try:
opts, args = getopt.getopt(
argv, "hvp:s:x:" + extra_opts,
- ["help", "verbose", "path=", "signapk_path=", "extra_signapk_args=",
- "java_path=", "java_args=", "public_key_suffix=",
- "private_key_suffix=", "boot_signer_path=", "boot_signer_args=",
- "verity_signer_path=", "verity_signer_args=", "device_specific=",
- "extra="] +
- list(extra_long_opts))
- except getopt.GetoptError as err:
+ ["help", "verbose", "path=", "device_specific=", "extra="] +
+ list(extra_long_opts))
+ except getopt.GetoptError, err:
Usage(docstring)
print "**", str(err), "**"
sys.exit(2)
+ path_specified = False
+
for o, a in opts:
if o in ("-h", "--help"):
Usage(docstring)
@@ -685,26 +487,6 @@ def ParseOptions(argv,
OPTIONS.verbose = True
elif o in ("-p", "--path"):
OPTIONS.search_path = a
- elif o in ("--signapk_path",):
- OPTIONS.signapk_path = a
- elif o in ("--extra_signapk_args",):
- OPTIONS.extra_signapk_args = shlex.split(a)
- elif o in ("--java_path",):
- OPTIONS.java_path = a
- elif o in ("--java_args",):
- OPTIONS.java_args = a
- elif o in ("--public_key_suffix",):
- OPTIONS.public_key_suffix = a
- elif o in ("--private_key_suffix",):
- OPTIONS.private_key_suffix = a
- elif o in ("--boot_signer_path",):
- OPTIONS.boot_signer_path = a
- elif o in ("--boot_signer_args",):
- OPTIONS.boot_signer_args = shlex.split(a)
- elif o in ("--verity_signer_path",):
- OPTIONS.verity_signer_path = a
- elif o in ("--verity_signer_args",):
- OPTIONS.verity_signer_args = shlex.split(a)
elif o in ("-s", "--device_specific"):
OPTIONS.device_specific = a
elif o in ("-x", "--extra"):
@@ -714,22 +496,12 @@ def ParseOptions(argv,
if extra_option_handler is None or not extra_option_handler(o, a):
assert False, "unknown option \"%s\"" % (o,)
- if OPTIONS.search_path:
- os.environ["PATH"] = (os.path.join(OPTIONS.search_path, "bin") +
- os.pathsep + os.environ["PATH"])
+ os.environ["PATH"] = (os.path.join(OPTIONS.search_path, "bin") +
+ os.pathsep + os.environ["PATH"])
return args
-def MakeTempFile(prefix=None, suffix=None):
- """Make a temp file and add it to the list of things to be deleted
- when Cleanup() is called. Return the filename."""
- fd, fn = tempfile.mkstemp(prefix=prefix, suffix=suffix)
- os.close(fd)
- OPTIONS.tempfiles.append(fn)
- return fn
-
-
def Cleanup():
for i in OPTIONS.tempfiles:
if os.path.isdir(i):
@@ -763,8 +535,7 @@ def GetPasswords(self, items):
if i not in current or not current[i]:
missing.append(i)
# Are all the passwords already in the file?
- if not missing:
- return current
+ if not missing: return current
for i in missing:
current[i] = ""
@@ -778,7 +549,7 @@ def GetPasswords(self, items):
current = self.UpdateAndReadFile(current)
- def PromptResult(self, current): # pylint: disable=no-self-use
+ def PromptResult(self, current):
"""Prompt the user to enter a value (password) for each key in
'current' whose value is fales. Returns a new dict with all the
values.
@@ -789,10 +560,9 @@ def PromptResult(self, current): # pylint: disable=no-self-use
result[k] = v
else:
while True:
- result[k] = getpass.getpass(
- "Enter password for %s key> " % k).strip()
- if result[k]:
- break
+ result[k] = getpass.getpass("Enter password for %s key> "
+ % (k,)).strip()
+ if result[k]: break
return result
def UpdateAndReadFile(self, current):
@@ -800,13 +570,14 @@ def UpdateAndReadFile(self, current):
return self.PromptResult(current)
f = open(self.pwfile, "w")
- os.chmod(self.pwfile, 0o600)
+ os.chmod(self.pwfile, 0600)
f.write("# Enter key passwords between the [[[ ]]] brackets.\n")
f.write("# (Additional spaces are harmless.)\n\n")
first_line = None
- sorted_list = sorted([(not v, k, v) for (k, v) in current.iteritems()])
- for i, (_, k, v) in enumerate(sorted_list):
+ sorted = [(not v, k, v) for (k, v) in current.iteritems()]
+ sorted.sort()
+ for i, (_, k, v) in enumerate(sorted):
f.write("[[[ %s ]]] %s\n" % (v, k))
if not v and first_line is None:
# position cursor on first line with no password.
@@ -820,115 +591,31 @@ def UpdateAndReadFile(self, current):
def ReadFile(self):
result = {}
- if self.pwfile is None:
- return result
+ if self.pwfile is None: return result
try:
f = open(self.pwfile, "r")
for line in f:
line = line.strip()
- if not line or line[0] == '#':
- continue
+ if not line or line[0] == '#': continue
m = re.match(r"^\[\[\[\s*(.*?)\s*\]\]\]\s*(\S+)$", line)
if not m:
print "failed to parse password file: ", line
else:
result[m.group(2)] = m.group(1)
f.close()
- except IOError as e:
+ except IOError, e:
if e.errno != errno.ENOENT:
print "error reading password file: ", str(e)
return result
-def ZipWrite(zip_file, filename, arcname=None, perms=0o644,
- compress_type=None):
- import datetime
-
- # http://b/18015246
- # Python 2.7's zipfile implementation wrongly thinks that zip64 is required
- # for files larger than 2GiB. We can work around this by adjusting their
- # limit. Note that `zipfile.writestr()` will not work for strings larger than
- # 2GiB. The Python interpreter sometimes rejects strings that large (though
- # it isn't clear to me exactly what circumstances cause this).
- # `zipfile.write()` must be used directly to work around this.
- #
- # This mess can be avoided if we port to python3.
- saved_zip64_limit = zipfile.ZIP64_LIMIT
- zipfile.ZIP64_LIMIT = (1 << 32) - 1
-
- if compress_type is None:
- compress_type = zip_file.compression
- if arcname is None:
- arcname = filename
-
- saved_stat = os.stat(filename)
-
- try:
- # `zipfile.write()` doesn't allow us to pass ZipInfo, so just modify the
- # file to be zipped and reset it when we're done.
- os.chmod(filename, perms)
-
- # Use a fixed timestamp so the output is repeatable.
- epoch = datetime.datetime.fromtimestamp(0)
- timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
- os.utime(filename, (timestamp, timestamp))
-
- zip_file.write(filename, arcname=arcname, compress_type=compress_type)
- finally:
- os.chmod(filename, saved_stat.st_mode)
- os.utime(filename, (saved_stat.st_atime, saved_stat.st_mtime))
- zipfile.ZIP64_LIMIT = saved_zip64_limit
-
-
-def ZipWriteStr(zip_file, zinfo_or_arcname, data, perms=None,
- compress_type=None):
- """Wrap zipfile.writestr() function to work around the zip64 limit.
-
- Even with the ZIP64_LIMIT workaround, it won't allow writing a string
- longer than 2GiB. It gives 'OverflowError: size does not fit in an int'
- when calling crc32(bytes).
-
- But it still works fine to write a shorter string into a large zip file.
- We should use ZipWrite() whenever possible, and only use ZipWriteStr()
- when we know the string won't be too long.
- """
-
- saved_zip64_limit = zipfile.ZIP64_LIMIT
- zipfile.ZIP64_LIMIT = (1 << 32) - 1
-
- if not isinstance(zinfo_or_arcname, zipfile.ZipInfo):
- zinfo = zipfile.ZipInfo(filename=zinfo_or_arcname)
- zinfo.compress_type = zip_file.compression
- if perms is None:
- perms = 0o644
- else:
- zinfo = zinfo_or_arcname
-
- # If compress_type is given, it overrides the value in zinfo.
- if compress_type is not None:
- zinfo.compress_type = compress_type
-
- # If perms is given, it has a priority.
- if perms is not None:
- zinfo.external_attr = perms << 16
-
- # Use a fixed timestamp so the output is repeatable.
- zinfo.date_time = (2009, 1, 1, 0, 0, 0)
-
- zip_file.writestr(zinfo, data)
- zipfile.ZIP64_LIMIT = saved_zip64_limit
-
-
-def ZipClose(zip_file):
- # http://b/18015246
- # zipfile also refers to ZIP64_LIMIT during close() when it writes out the
- # central directory.
- saved_zip64_limit = zipfile.ZIP64_LIMIT
- zipfile.ZIP64_LIMIT = (1 << 32) - 1
-
- zip_file.close()
-
- zipfile.ZIP64_LIMIT = saved_zip64_limit
+def ZipWriteStr(zip, filename, data, perms=0644):
+ # use a fixed timestamp so the output is repeatable.
+ zinfo = zipfile.ZipInfo(filename=filename,
+ date_time=(2009, 1, 1, 0, 0, 0))
+ zinfo.compress_type = zip.compression
+ zinfo.external_attr = perms << 16
+ zip.writestr(zinfo, data)
class DeviceSpecificParams(object):
@@ -948,8 +635,7 @@ def __init__(self, **kwargs):
if self.module is None:
path = OPTIONS.device_specific
- if not path:
- return
+ if not path: return
try:
if os.path.isdir(path):
info = imp.find_module("releasetools", [path])
@@ -959,7 +645,6 @@ def __init__(self, **kwargs):
if x == ".py":
f = b
info = imp.find_module(f, [d])
- print "loaded device-specific extensions from", path
self.module = imp.load_module("device_specific", *info)
except ImportError:
print "unable to load device-specific module; assuming none"
@@ -1004,10 +689,6 @@ def FullOTA_Assertions(self):
assertions they like."""
return self._DoCall("FullOTA_Assertions")
- def FullOTA_InstallBegin(self):
- """Called at the start of full OTA installation."""
- return self._DoCall("FullOTA_InstallBegin")
-
def FullOTA_InstallEnd(self):
"""Called at the end of full OTA installation; typically this is
used to install the image for the device's baseband processor."""
@@ -1019,29 +700,21 @@ def IncrementalOTA_Assertions(self):
additional assertions they like."""
return self._DoCall("IncrementalOTA_Assertions")
- def IncrementalOTA_VerifyBegin(self):
- """Called at the start of the verification phase of incremental
- OTA installation; additional checks can be placed here to abort
- the script before any changes are made."""
- return self._DoCall("IncrementalOTA_VerifyBegin")
-
def IncrementalOTA_VerifyEnd(self):
"""Called at the end of the verification phase of incremental OTA
installation; additional checks can be placed here to abort the
script before any changes are made."""
return self._DoCall("IncrementalOTA_VerifyEnd")
- def IncrementalOTA_InstallBegin(self):
- """Called at the start of incremental OTA installation (after
- verification is complete)."""
- return self._DoCall("IncrementalOTA_InstallBegin")
-
def IncrementalOTA_InstallEnd(self):
"""Called at the end of incremental OTA installation; typically
this is used to install the image for the device's baseband
processor."""
return self._DoCall("IncrementalOTA_InstallEnd")
+ def WriteRawImage(self, *args):
+ return self._DoCall("WriteRawImage")
+
class File(object):
def __init__(self, name, data):
self.name = name
@@ -1062,8 +735,8 @@ def WriteToTemp(self):
t.flush()
return t
- def AddToZip(self, z, compression=None):
- ZipWriteStr(z, self.name, self.data, compress_type=compression)
+ def AddToZip(self, z):
+ ZipWriteStr(z, self.name, self.data)
DIFF_PROGRAM_BY_EXT = {
".gz" : "imgdiff",
@@ -1074,11 +747,10 @@ def AddToZip(self, z, compression=None):
}
class Difference(object):
- def __init__(self, tf, sf, diff_program=None):
+ def __init__(self, tf, sf):
self.tf = tf
self.sf = sf
self.patch = None
- self.diff_program = diff_program
def ComputePatch(self):
"""Compute the patch (as a string of data) needed to turn sf into
@@ -1087,11 +759,11 @@ def ComputePatch(self):
tf = self.tf
sf = self.sf
- if self.diff_program:
- diff_program = self.diff_program
- else:
- ext = os.path.splitext(tf.name)[1]
- diff_program = DIFF_PROGRAM_BY_EXT.get(ext, "bsdiff")
+ if tf.name.startswith("data/preinstall_apps"):
+ return self.tf, self.sf, self.patch
+
+ ext = os.path.splitext(tf.name)[1]
+ diff_program = DIFF_PROGRAM_BY_EXT.get(ext, "bsdiff")
ttemp = tf.WriteToTemp()
stemp = sf.WriteToTemp()
@@ -1101,36 +773,19 @@ def ComputePatch(self):
try:
ptemp = tempfile.NamedTemporaryFile()
if isinstance(diff_program, list):
+ diff_program[0] = os.path.join(OPTIONS.search_path, "releasetools", diff_program[0])
cmd = copy.copy(diff_program)
else:
+ diff_program = os.path.join(OPTIONS.search_path, "releasetools", diff_program)
cmd = [diff_program]
cmd.append(stemp.name)
cmd.append(ttemp.name)
cmd.append(ptemp.name)
p = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- err = []
- def run():
- _, e = p.communicate()
- if e:
- err.append(e)
- th = threading.Thread(target=run)
- th.start()
- # MIUI MOD : START
- #th.join(timeout=300) # 5 mins
- th.join(timeout=1200) # 20 mins
- if th.is_alive():
- print "WARNING: diff command timed out"
- p.terminate()
- th.join(5)
- if th.is_alive():
- p.kill()
- th.join()
-
+ _, err = p.communicate()
if err or p.returncode != 0:
- print "WARNING: failure running %s:\n%s\n" % (
- diff_program, "".join(err))
- self.patch = None
- return None, None, None
+ print "WARNING: failure running %s:\n%s\n" % (diff_program, err)
+ return None
diff = ptemp.read()
finally:
ptemp.close()
@@ -1181,7 +836,7 @@ def worker():
print "%8.2f sec %8d / %8d bytes (%6.2f%%) %s" % (
dur, len(patch), tf.size, 100.0 * len(patch) / tf.size, name)
lock.release()
- except Exception as e:
+ except Exception, e:
print e
raise
@@ -1194,264 +849,14 @@ def worker():
threads.pop().join()
-class BlockDifference(object):
- def __init__(self, partition, tgt, src=None, check_first_block=False,
- version=None):
- self.tgt = tgt
- self.src = src
- self.partition = partition
- self.check_first_block = check_first_block
-
- # Due to http://b/20939131, check_first_block is disabled temporarily.
- assert not self.check_first_block
-
- if version is None:
- version = 1
- if OPTIONS.info_dict:
- version = max(
- int(i) for i in
- OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
- self.version = version
-
- b = blockimgdiff.BlockImageDiff(tgt, src, threads=OPTIONS.worker_threads,
- version=self.version)
- tmpdir = tempfile.mkdtemp()
- OPTIONS.tempfiles.append(tmpdir)
- self.path = os.path.join(tmpdir, partition)
- b.Compute(self.path)
-
- _, self.device = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
-
- def WriteScript(self, script, output_zip, progress=None):
- if not self.src:
- # write the output unconditionally
- script.Print("Patching %s image unconditionally..." % (self.partition,))
- else:
- script.Print("Patching %s image after verification." % (self.partition,))
-
- if progress:
- script.ShowProgress(progress, 0)
- self._WriteUpdate(script, output_zip)
- self._WritePostInstallVerifyScript(script)
-
- def WriteVerifyScript(self, script):
- partition = self.partition
- if not self.src:
- script.Print("Image %s will be patched unconditionally." % (partition,))
- else:
- ranges = self.src.care_map.subtract(self.src.clobbered_blocks)
- ranges_str = ranges.to_string_raw()
- if self.version >= 3:
- script.AppendExtra(('if (range_sha1("%s", "%s") == "%s" || '
- 'block_image_verify("%s", '
- 'package_extract_file("%s.transfer.list"), '
- '"%s.new.dat", "%s.patch.dat")) then') % (
- self.device, ranges_str, self.src.TotalSha1(),
- self.device, partition, partition, partition))
- else:
- script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
- self.device, ranges_str, self.src.TotalSha1()))
- script.Print('Verified %s image...' % (partition,))
- script.AppendExtra('else')
-
- # When generating incrementals for the system and vendor partitions,
- # explicitly check the first block (which contains the superblock) of
- # the partition to see if it's what we expect. If this check fails,
- # give an explicit log message about the partition having been
- # remounted R/W (the most likely explanation) and the need to flash to
- # get OTAs working again.
- if self.check_first_block:
- self._CheckFirstBlock(script)
-
- # Abort the OTA update. Note that the incremental OTA cannot be applied
- # even if it may match the checksum of the target partition.
- # a) If version < 3, operations like move and erase will make changes
- # unconditionally and damage the partition.
- # b) If version >= 3, it won't even reach here.
- script.AppendExtra(('abort("%s partition has unexpected contents");\n'
- 'endif;') % (partition,))
-
- def _WritePostInstallVerifyScript(self, script):
- partition = self.partition
- script.Print('Verifying the updated %s image...' % (partition,))
- # Unlike pre-install verification, clobbered_blocks should not be ignored.
- ranges = self.tgt.care_map
- ranges_str = ranges.to_string_raw()
- script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
- self.device, ranges_str,
- self.tgt.TotalSha1(include_clobbered_blocks=True)))
-
- # Bug: 20881595
- # Verify that extended blocks are really zeroed out.
- if self.tgt.extended:
- ranges_str = self.tgt.extended.to_string_raw()
- script.AppendExtra('if range_sha1("%s", "%s") == "%s" then' % (
- self.device, ranges_str,
- self._HashZeroBlocks(self.tgt.extended.size())))
- script.Print('Verified the updated %s image.' % (partition,))
- script.AppendExtra(
- 'else\n'
- ' abort("%s partition has unexpected non-zero contents after OTA '
- 'update");\n'
- 'endif;' % (partition,))
- else:
- script.Print('Verified the updated %s image.' % (partition,))
-
- script.AppendExtra(
- 'else\n'
- ' abort("%s partition has unexpected contents after OTA update");\n'
- 'endif;' % (partition,))
-
- def _WriteUpdate(self, script, output_zip):
- ZipWrite(output_zip,
- '{}.transfer.list'.format(self.path),
- '{}.transfer.list'.format(self.partition))
- ZipWrite(output_zip,
- '{}.new.dat'.format(self.path),
- '{}.new.dat'.format(self.partition))
- ZipWrite(output_zip,
- '{}.patch.dat'.format(self.path),
- '{}.patch.dat'.format(self.partition),
- compress_type=zipfile.ZIP_STORED)
-
- call = ('block_image_update("{device}", '
- 'package_extract_file("{partition}.transfer.list"), '
- '"{partition}.new.dat", "{partition}.patch.dat");\n'.format(
- device=self.device, partition=self.partition))
- script.AppendExtra(script.WordWrap(call))
-
- def _HashBlocks(self, source, ranges): # pylint: disable=no-self-use
- data = source.ReadRangeSet(ranges)
- ctx = sha1()
-
- for p in data:
- ctx.update(p)
-
- return ctx.hexdigest()
-
- def _HashZeroBlocks(self, num_blocks): # pylint: disable=no-self-use
- """Return the hash value for all zero blocks."""
- zero_block = '\x00' * 4096
- ctx = sha1()
- for _ in range(num_blocks):
- ctx.update(zero_block)
-
- return ctx.hexdigest()
-
- # TODO(tbao): Due to http://b/20939131, block 0 may be changed without
- # remounting R/W. Will change the checking to a finer-grained way to
- # mask off those bits.
- def _CheckFirstBlock(self, script):
- r = rangelib.RangeSet((0, 1))
- srchash = self._HashBlocks(self.src, r)
-
- script.AppendExtra(('(range_sha1("%s", "%s") == "%s") || '
- 'abort("%s has been remounted R/W; '
- 'reflash device to reenable OTA updates");')
- % (self.device, r.to_string_raw(), srchash,
- self.device))
-
-DataImage = blockimgdiff.DataImage
-
-
# map recovery.fstab's fs_types to mount/format "partition types"
-PARTITION_TYPES = {
- "yaffs2": "MTD",
- "mtd": "MTD",
- "ext4": "EMMC",
- "emmc": "EMMC",
- "f2fs": "EMMC",
- "squashfs": "EMMC"
-}
+PARTITION_TYPES = { "yaffs2": "MTD", "mtd": "MTD", "ext3": "EMMC",
+ "ext4": "EMMC", "emmc": "EMMC", "vfat": "EMMC",
+ "auto": "EMMC"}
def GetTypeAndDevice(mount_point, info):
fstab = info["fstab"]
if fstab:
- return (PARTITION_TYPES[fstab[mount_point].fs_type],
- fstab[mount_point].device)
- else:
- raise KeyError
-
-
-def ParseCertificate(data):
- """Parse a PEM-format certificate."""
- cert = []
- save = False
- for line in data.split("\n"):
- if "--END CERTIFICATE--" in line:
- break
- if save:
- cert.append(line)
- if "--BEGIN CERTIFICATE--" in line:
- save = True
- cert = "".join(cert).decode('base64')
- return cert
-
-def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
- info_dict=None):
- """Generate a binary patch that creates the recovery image starting
- with the boot image. (Most of the space in these images is just the
- kernel, which is identical for the two, so the resulting patch
- should be efficient.) Add it to the output zip, along with a shell
- script that is run from init.rc on first boot to actually do the
- patching and install the new recovery image.
-
- recovery_img and boot_img should be File objects for the
- corresponding images. info should be the dictionary returned by
- common.LoadInfoDict() on the input target_files.
- """
-
- if info_dict is None:
- info_dict = OPTIONS.info_dict
-
- diff_program = ["imgdiff"]
- path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat")
- if os.path.exists(path):
- diff_program.append("-b")
- diff_program.append(path)
- bonus_args = "-b /system/etc/recovery-resource.dat"
+ return PARTITION_TYPES[fstab[mount_point].fs_type], fstab[mount_point].device
else:
- bonus_args = ""
-
- d = Difference(recovery_img, boot_img, diff_program=diff_program)
- _, _, patch = d.ComputePatch()
- output_sink("recovery-from-boot.p", patch)
-
- try:
- boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
- recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
- except KeyError:
- return
-
- sh = """#!/system/bin/sh
-if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then
- applypatch %(bonus_args)s %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p && log -t recovery "Installing new recovery image: succeeded" || log -t recovery "Installing new recovery image: failed"
-else
- log -t recovery "Recovery image already installed"
-fi
-""" % {'boot_size': boot_img.size,
- 'boot_sha1': boot_img.sha1,
- 'recovery_size': recovery_img.size,
- 'recovery_sha1': recovery_img.sha1,
- 'boot_type': boot_type,
- 'boot_device': boot_device,
- 'recovery_type': recovery_type,
- 'recovery_device': recovery_device,
- 'bonus_args': bonus_args}
-
- # The install script location moved from /system/etc to /system/bin
- # in the L release. Parse the init.rc file to find out where the
- # target-files expects it to be, and put it there.
- sh_location = "etc/install-recovery.sh"
- try:
- with open(os.path.join(input_dir, "BOOT", "RAMDISK", "init.rc")) as f:
- for line in f:
- m = re.match(r"^service flash_recovery /system/(\S+)\s*$", line)
- if m:
- sh_location = m.group(1)
- print "putting script in", sh_location
- break
- except (OSError, IOError) as e:
- print "failed to read init.rc: %s" % (e,)
-
- output_sink(sh_location, sh)
+ return None
diff --git a/releasetools/edify_generator.py b/releasetools/edify_generator.py
index 77e0e04..656eca3 100644
--- a/releasetools/edify_generator.py
+++ b/releasetools/edify_generator.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import re
import common
@@ -20,15 +21,11 @@ class EdifyGenerator(object):
"""Class to generate scripts in the 'edify' recovery script language
used from donut onwards."""
- def __init__(self, version, info, fstab=None):
+ def __init__(self, version, info):
self.script = []
self.mounts = set()
self.version = version
self.info = info
- if fstab is None:
- self.fstab = self.info.get("fstab", None)
- else:
- self.fstab = fstab
def MakeTemporary(self):
"""Make a temporary script object whose commands can latter be
@@ -39,7 +36,7 @@ def MakeTemporary(self):
return x
@staticmethod
- def WordWrap(cmd, linelen=80):
+ def _WordWrap(cmd, linelen=80):
"""'cmd' should be a function call with null characters after each
parameter (eg, "somefun(foo,\0bar,\0baz)"). This function wraps cmd
to a given line length, replacing nulls with spaces and/or newlines
@@ -71,57 +68,28 @@ def AppendScript(self, other):
with temporary=True) to this one."""
self.script.extend(other.script)
- def AssertOemProperty(self, name, value):
- """Assert that a property on the OEM paritition matches a value."""
- if not name:
- raise ValueError("must specify an OEM property")
- if not value:
- raise ValueError("must specify the OEM value")
- cmd = ('file_getprop("/oem/oem.prop", "{name}") == "{value}" || '
- 'abort("This package expects the value \\"{value}\\" for '
- '\\"{name}\\" on the OEM partition; this has value \\"" + '
- 'file_getprop("/oem/oem.prop", "{name}") + "\\".");').format(
- name=name, value=value)
- self.script.append(cmd)
-
def AssertSomeFingerprint(self, *fp):
"""Assert that the current system build fingerprint is one of *fp."""
if not fp:
raise ValueError("must specify some fingerprints")
- cmd = (' ||\n '.join([('file_getprop("/system/build.prop", "ro.build.fingerprint") == "%s"') % i
- for i in fp]) +
- ' ||\n abort("Package expects build fingerprint of %s; this '
- 'device has " + getprop("ro.build.fingerprint") + ".");') % (
- " or ".join(fp))
- self.script.append(cmd)
-
- def AssertSomeThumbprint(self, *fp):
- """Assert that the current system build thumbprint is one of *fp."""
- if not fp:
- raise ValueError("must specify some thumbprints")
- cmd = (' ||\n '.join([('file_getprop("/system/build.prop", "ro.build.thumbprint") == "%s"') % i
- for i in fp]) +
- ' ||\n abort("Package expects build thumbprint of %s; this '
- 'device has " + getprop("ro.build.thumbprint") + ".");') % (
- " or ".join(fp))
- self.script.append(cmd)
-
- def AssertOlderBuild(self, timestamp, timestamp_text):
+ cmd = ('assert(' +
+ ' ||\0'.join([('file_getprop("/system/build.prop", '
+ '"ro.build.fingerprint") == "%s"')
+ % i for i in fp]) +
+ ');')
+ self.script.append(self._WordWrap(cmd))
+
+ def AssertOlderBuild(self, timestamp):
"""Assert that the build on the device is older (or the same as)
the given timestamp."""
- self.script.append(
- ('(!less_than_int(%s, getprop("ro.build.date.utc"))) || '
- 'abort("Can\'t install this package (%s) over newer '
- 'build (" + getprop("ro.build.date") + ").");') % (timestamp,
- timestamp_text))
+ self.script.append(('assert(!less_than_int(%s, '
+ 'getprop("ro.build.date.utc")));') % (timestamp,))
def AssertDevice(self, device):
"""Assert that the device identifier is the given string."""
- cmd = ('getprop("ro.product.device") == "%s" || '
- 'abort("This package is for \\"%s\\" devices; '
- 'this is a \\"" + getprop("ro.product.device") + "\\".");') % (
- device, device)
- self.script.append(cmd)
+ cmd = ('assert(getprop("ro.product.device") == "%s" ||\0'
+ 'getprop("ro.build.product") == "%s");' % (device, device))
+ self.script.append(self._WordWrap(cmd))
def AssertSomeBootloader(self, *bootloaders):
"""Asert that the bootloader version is one of *bootloaders."""
@@ -129,7 +97,7 @@ def AssertSomeBootloader(self, *bootloaders):
" ||\0".join(['getprop("ro.bootloader") == "%s"' % (b,)
for b in bootloaders]) +
");")
- self.script.append(self.WordWrap(cmd))
+ self.script.append(self._WordWrap(cmd))
def ShowProgress(self, frac, dur):
"""Update the progress bar, advancing it over 'frac' over the next
@@ -147,10 +115,9 @@ def PatchCheck(self, filename, *sha1):
"""Check that the given file (or MTD reference) has one of the
given *sha1 hashes, checking the version saved in cache if the
file does not match."""
- self.script.append(
- 'apply_patch_check("%s"' % (filename,) +
- "".join([', "%s"' % (i,) for i in sha1]) +
- ') || abort("\\"%s\\" has unexpected contents.");' % (filename,))
+ self.script.append('assert(apply_patch_check("%s"' % (filename,) +
+ "".join([', "%s"' % (i,) for i in sha1]) +
+ '));')
def FileCheck(self, filename, *sha1):
"""Check that the given file (or MTD reference) has one of the
@@ -162,42 +129,25 @@ def FileCheck(self, filename, *sha1):
def CacheFreeSpaceCheck(self, amount):
"""Check that there's at least 'amount' space that can be made
available on /cache."""
- self.script.append(('apply_patch_space(%d) || abort("Not enough free space '
- 'on /system to apply patches.");') % (amount,))
-
- def Mount(self, mount_point, mount_options_by_format=""):
- """Mount the partition with the given mount_point.
- mount_options_by_format:
- [fs_type=option[,option]...[|fs_type=option[,option]...]...]
- where option is optname[=optvalue]
- E.g. ext4=barrier=1,nodelalloc,errors=panic|f2fs=errors=recover
- """
- fstab = self.fstab
+ self.script.append("assert(apply_patch_space(%d));" % (amount,))
+
+ def Mount(self, mount_point):
+ """Mount the partition with the given mount_point."""
+ fstab = self.info.get("fstab", None)
if fstab:
p = fstab[mount_point]
- mount_dict = {}
- if mount_options_by_format is not None:
- for option in mount_options_by_format.split("|"):
- if "=" in option:
- key, value = option.split("=", 1)
- mount_dict[key] = value
- mount_flags = mount_dict.get(p.fs_type, "")
- if p.context is not None:
- mount_flags = p.context + ("," + mount_flags if mount_flags else "")
- self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % (
- p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device,
- p.mount_point, mount_flags))
+ self.script.append('mount("%s", "%s", "%s", "%s");' %
+ (p.fs_type, common.PARTITION_TYPES[p.fs_type],
+ p.device, p.mount_point))
self.mounts.add(p.mount_point)
+ def Unmount(self, mount_point):
+ self.script.append('unmount("%s");' % mount_point)
+
def UnpackPackageDir(self, src, dst):
"""Unpack a given directory from the OTA package into the given
destination directory."""
- # MIUI MOD:START
- # self.script.append('package_extract_dir("%s", "%s");' % (src, dst))
- self.script.append(
- 'package_extract_dir("%s", "%s") || abort("Failed to extract dir from \\"%s\\" to \\"%s\\".");' %
- (src, dst, src, dst))
- # END
+ self.script.append('package_extract_dir("%s", "%s");' % (src, dst))
def Comment(self, comment):
"""Write a comment into the update script."""
@@ -210,66 +160,23 @@ def Print(self, message):
"""Log a message to the screen (if the logs are visible)."""
self.script.append('ui_print("%s");' % (message,))
- def TunePartition(self, partition, *options):
- fstab = self.fstab
- if fstab:
- p = fstab[partition]
- if p.fs_type not in ("ext2", "ext3", "ext4"):
- raise ValueError("Partition %s cannot be tuned\n" % (partition,))
- self.script.append(
- 'tune2fs(' + "".join(['"%s", ' % (i,) for i in options]) +
- '"%s") || abort("Failed to tune partition %s");' % (
- p.device, partition))
-
def FormatPartition(self, partition):
"""Format the given partition, specified by its mount point (eg,
"/system")."""
- fstab = self.fstab
+ reserve_size = 0
+ fstab = self.info.get("fstab", None)
if fstab:
p = fstab[partition]
- self.script.append('format("%s", "%s", "%s", "%s", "%s");' %
+ self.script.append('format("%s", "%s", "%s", "%s");' %
(p.fs_type, common.PARTITION_TYPES[p.fs_type],
- p.device, p.length, p.mount_point))
-
- def WipeBlockDevice(self, partition):
- if partition not in ("/system", "/vendor"):
- raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,))
- fstab = self.fstab
- size = self.info.get(partition.lstrip("/") + "_size", None)
- device = fstab[partition].device
-
- self.script.append('wipe_block_device("%s", %s);' % (device, size))
+ p.device, p.length))
def DeleteFiles(self, file_list):
"""Delete all files in file_list."""
- if not file_list:
- return
+ if not file_list: return
cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");"
- self.script.append(self.WordWrap(cmd))
-
- def DeleteFilesIfNotMatching(self, file_list):
- """Delete the file in file_list if not matching the checksum."""
- if not file_list:
- return
- for name, sha1 in file_list:
- cmd = ('sha1_check(read_file("{name}"), "{sha1}") || '
- 'delete("{name}");'.format(name=name, sha1=sha1))
- self.script.append(self.WordWrap(cmd))
-
- def RenameFile(self, srcfile, tgtfile):
- """Moves a file from one location to another."""
- if self.info.get("update_rename_support", False):
- self.script.append('rename("%s", "%s");' % (srcfile, tgtfile))
- else:
- raise ValueError("Rename not supported by update binary")
-
- def SkipNextActionIfTargetExists(self, tgtfile, tgtsha1):
- """Prepend an action with an apply_patch_check in order to
- skip the action if the file exists. Used when a patch
- is later renamed."""
- cmd = ('sha1_check(read_file("%s"), %s) ||' % (tgtfile, tgtsha1))
- self.script.append(self.WordWrap(cmd))
+ self.script.append(self._WordWrap(cmd))
def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
"""Apply binary patches (in *patchpairs) to the given srcfile to
@@ -279,24 +186,17 @@ def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
raise ValueError("bad patches given to ApplyPatch")
cmd = ['apply_patch("%s",\0"%s",\0%s,\0%d'
% (srcfile, tgtfile, tgtsha1, tgtsize)]
- # MIUI MOD:START
- # for i in range(0, len(patchpairs), 2):
- # cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2])
- # cmd.append(');')
- patchfiles = ""
for i in range(0, len(patchpairs), 2):
cmd.append(',\0%s, package_extract_file("%s")' % patchpairs[i:i+2])
- patchfiles = patchfiles.join('%s ' % patchpairs[i+1])
- cmd.append(') || abort("Failed to apply patch \\"%s\\".");' % (patchfiles,))
- # END
+ cmd.append(');')
cmd = "".join(cmd)
- self.script.append(self.WordWrap(cmd))
+ self.script.append(self._WordWrap(cmd))
- def WriteRawImage(self, mount_point, fn, mapfn=None):
+ def WriteRawImage(self, mount_point, fn):
"""Write the given package file into the partition for the given
mount point."""
- fstab = self.fstab
+ fstab = self.info["fstab"]
if fstab:
p = fstab[mount_point]
partition_type = common.PARTITION_TYPES[p.fs_type]
@@ -306,46 +206,19 @@ def WriteRawImage(self, mount_point, fn, mapfn=None):
'write_raw_image(package_extract_file("%(fn)s"), "%(device)s");'
% args)
elif partition_type == "EMMC":
- if mapfn:
- args["map"] = mapfn
- self.script.append(
- 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args)
- else:
- self.script.append(
- 'package_extract_file("%(fn)s", "%(device)s");' % args)
+ self.script.append(
+ 'package_extract_file("%(fn)s", "%(device)s");' % args)
else:
- raise ValueError(
- "don't know how to write \"%s\" partitions" % p.fs_type)
+ raise ValueError("don't know how to write \"%s\" partitions" % (p.fs_type,))
- def SetPermissions(self, fn, uid, gid, mode, selabel, capabilities):
+ def SetPermissions(self, fn, uid, gid, mode):
"""Set file ownership and permissions."""
- if not self.info.get("use_set_metadata", False):
- self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn))
- else:
- cmd = 'set_metadata("%s", "uid", %d, "gid", %d, "mode", 0%o' % (fn, uid, gid, mode)
- if capabilities is not None:
- cmd += ', "capabilities", "%s"' % capabilities
- if selabel is not None:
- cmd += ', "selabel", "%s"' % selabel
- cmd += ');'
- self.script.append(cmd)
-
- def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode, selabel,
- capabilities):
+ self.script.append('set_perm(%d, %d, 0%o, "%s");' % (uid, gid, mode, fn))
+
+ def SetPermissionsRecursive(self, fn, uid, gid, dmode, fmode):
"""Recursively set path ownership and permissions."""
- if not self.info.get("use_set_metadata", False):
- self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");'
- % (uid, gid, dmode, fmode, fn))
- else:
- if capabilities is None:
- capabilities = "0x0"
- cmd = 'set_metadata_recursive("%s", "uid", %d, "gid", %d, ' \
- '"dmode", 0%o, "fmode", 0%o, "capabilities", %s' \
- % (fn, uid, gid, dmode, fmode, capabilities)
- if selabel is not None:
- cmd += ', "selabel", "%s"' % selabel
- cmd += ');'
- self.script.append(cmd)
+ self.script.append('set_perm_recursive(%d, %d, 0%o, 0%o, "%s");'
+ % (uid, gid, dmode, fmode, fn))
def MakeSymlinks(self, symlink_list):
"""Create symlinks, given a list of (dest, link) pairs."""
@@ -356,16 +229,26 @@ def MakeSymlinks(self, symlink_list):
for dest, links in sorted(by_dest.iteritems()):
cmd = ('symlink("%s", ' % (dest,) +
",\0".join(['"' + i + '"' for i in sorted(links)]) + ");")
- self.script.append(self.WordWrap(cmd))
+ self.script.append(self._WordWrap(cmd))
+
+ def RetouchBinaries(self, file_list):
+ """Execute the retouch instructions in files listed."""
+ cmd = ('retouch_binaries(' +
+ ', '.join(['"' + i[0] + '", "' + i[1] + '"' for i in file_list]) +
+ ');')
+ self.script.append(self._WordWrap(cmd))
+
+ def UndoRetouchBinaries(self, file_list):
+ """Undo the retouching (retouch to zero offset)."""
+ cmd = ('undo_retouch_binaries(' +
+ ', '.join(['"' + i[0] + '", "' + i[1] + '"' for i in file_list]) +
+ ');')
+ self.script.append(self._WordWrap(cmd))
def AppendExtra(self, extra):
"""Append text verbatim to the output script."""
self.script.append(extra)
- def Unmount(self, mount_point):
- self.script.append('unmount("%s");' % mount_point)
- self.mounts.remove(mount_point)
-
def UnmountAll(self):
for p in sorted(self.mounts):
self.script.append('unmount("%s");' % (p,))
@@ -385,6 +268,6 @@ def AddToZip(self, input_zip, output_zip, input_path=None):
if input_path is None:
data = input_zip.read("OTA/bin/updater")
else:
- data = open(input_path, "rb").read()
+ data = open(os.path.join(input_path, "updater")).read()
common.ZipWriteStr(output_zip, "META-INF/com/google/android/update-binary",
- data, perms=0o755)
+ data, perms=0755)
diff --git a/linux-x86/imgdiff b/releasetools/imgdiff
similarity index 100%
rename from linux-x86/imgdiff
rename to releasetools/imgdiff
diff --git a/releasetools/miui_releasetools.py b/releasetools/miui_releasetools.py
index 73d563b..f82ce63 100644
--- a/releasetools/miui_releasetools.py
+++ b/releasetools/miui_releasetools.py
@@ -1,7 +1,6 @@
import common
import copy
-import edify_generator
def FullOTA_Assertions(info):
info.script.Mount("/data")
@@ -9,60 +8,37 @@ def FullOTA_Assertions(info):
def IncrementalOTA_Assertions(info):
info.script.Mount("/data")
-def PushBusybox(input_zip, output_zip, script):
- try:
- data = input_zip.read("OTA/bin/busybox")
- common.ZipWriteStr(output_zip, "META-INF/com/miui/busybox", data)
- script.AppendExtra("package_extract_file(\"META-INF/com/miui/busybox\", \"/tmp/busybox\");")
- script.SetPermissions("/tmp/busybox", 0, 0, 0555, None, None)
- except KeyError:
- print 'Ignore replace cert'
-
-def RemoveUseslessFiles(script):
- script.DeleteFiles(["/tmp/busybox"])
-
-def ProcessSystemFormat(info):
- edify = info.script
- script_temp = edify_generator.EdifyGenerator(3, info.script.info)
- PushBusybox(info.input_zip, info.output_zip, script_temp)
- script_temp.AppendExtra("run_program(\"/tmp/busybox\", \"rm\", \"-rf\", \"/system\");")
- script_temp_str = "".join(script_temp.script).replace(";", ";\n").strip()
- format_system_line = 0
- mount_system_line = 0
- for i in xrange(len(edify.script)):
- if format_system_line > 0 and mount_system_line > 0:
- break
- if ");" in edify.script[i] and "format" in edify.script[i] and "/system" in edify.script[i]:
- format_system_line = i
- continue
- elif ");" in edify.script[i] and "mount" in edify.script[i] and "/system" in edify.script[i]:
- mount_system_line = i
- continue
- if mount_system_line > format_system_line > 0:
- edify.script[format_system_line] = edify.script[format_system_line].replace(edify.script[format_system_line], edify.script[mount_system_line])
- edify.script[mount_system_line] = edify.script[mount_system_line].replace(edify.script[mount_system_line] , script_temp_str)
- elif format_system_line > mount_system_line > 0:
- edify.script[format_system_line] = edify.script[format_system_line].replace(edify.script[format_system_line], "")
- edify.script[mount_system_line] = edify.script[mount_system_line].replace(";", ";\n" + script_temp_str)
- else:
- PushBusybox(info.input_zip, info.output_zip, info.script)
-
def FullOTA_InstallEnd(info):
UnpackData(info.script)
CopyDataFiles(info.input_zip, info.output_zip, info.script)
- ProcessSystemFormat(info)
- Replace_Cert(info.input_zip, info.output_zip, info.script)
- RemoveUseslessFiles(info.script)
+ Relink(info.input_zip, info.output_zip, info.script)
SetPermissions(info.script)
RemoveAbandonedPreinstall(info.script)
def IncrementalOTA_InstallEnd(info):
UnpackData(info.script)
- Replace_Cert(info.target_zip, info.output_zip, info.script)
+ Relink(info.target_zip, info.output_zip, info.script)
SetPermissions(info.script)
RemoveAbandonedPreinstall(info.script)
+
+
+def Relink(input_zip, output_zip, script):
+ """relink tool to rebuilding cust variant file and cust link
+for backward compatibility that update with ota"""
+
+ print "[MIUI CUST] OTA: handle relink"
+ # copy relink
+ data = input_zip.read("OTA/bin/relink")
+ common.ZipWriteStr(output_zip, "META-INF/com/miui/relink", data)
+ # add to script
+ script.AppendExtra("package_extract_file(\"META-INF/com/miui/relink\", \"/tmp/relink\");")
+ script.AppendExtra("set_perm(0, 0, 0555, \"/tmp/relink\");")
+ script.AppendExtra("run_program(\"/tmp/relink\");")
+ script.AppendExtra("delete(\"/tmp/relink\");")
+
+
def CopyDataFiles(input_zip, output_zip, script):
"""Copies files underneath data/miui in the input zip to the output zip."""
@@ -74,6 +50,8 @@ def CopyDataFiles(input_zip, output_zip, script):
info2.filename = "data/" + basefilename
data = input_zip.read(info.filename)
output_zip.writestr(info2, data)
+ common.ZipWriteStr(output_zip, "data/miui/reinstall_apps", "reinstall_apps")
+ script.AppendExtra("set_perm(1000, 1000, 0666, \"/data/miui/reinstall_apps\");")
def UnpackData(script):
@@ -83,6 +61,7 @@ def UnpackData(script):
def SetPermissions(script):
print "[MIUI CUST] OTA: SetPermissions"
SetPermissionsRecursive(script, "/data/miui", 1000, 1000, 0755, 0644)
+ SetPermissionsRecursive(script, "/data/miui/cust", 1000, 1000, 0755, 0644)
def SetPermissionsRecursive(script, d, gid, uid, dmod, fmod):
@@ -96,14 +75,3 @@ def RemoveAbandonedPreinstall(script):
script.AppendExtra("delete_recursive(\"/data/miui/preinstall_apps\");")
script.AppendExtra("delete_recursive(\"/data/miui/cust/preinstall_apps\");")
-def Replace_Cert(input_zip, output_zip, script):
- try:
- data = input_zip.read("OTA/bin/replace_key")
- common.ZipWriteStr(output_zip, "META-INF/com/miui/replace_key", data)
- script.AppendExtra("package_extract_file(\"META-INF/com/miui/replace_key\", \"/tmp/replace_key\");")
- script.SetPermissions("/tmp/replace_key", 0, 0, 0555, None, None)
- script.AppendExtra("run_program(\"/sbin/sh\", \"/tmp/replace_key\");")
- script.DeleteFiles(["/tmp/replace_key"])
- except KeyError:
- print 'Ignore replace cert'
-
diff --git a/releasetools/ota_from_target_files b/releasetools/ota_from_target_files
index 00e2a46..6293317 100755
--- a/releasetools/ota_from_target_files
+++ b/releasetools/ota_from_target_files
@@ -21,7 +21,7 @@ a full OTA is produced.
Usage: ota_from_target_files [flags] input_target_files output_ota_package
- --board_config
+ -b (--board_config)
Deprecated.
-k (--package_key) Key to use to sign the package (default is
@@ -37,19 +37,6 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package
Generate an incremental OTA using the given target-files zip as
the starting build.
- --full_radio
- When generating an incremental OTA, always include a full copy of
- radio image. This option is only meaningful when -i is specified,
- because a full radio is always included in a full OTA if applicable.
-
- -v (--verify)
- Remount and verify the checksums of the files written to the
- system and vendor (if used) partitions. Incremental builds only.
-
- -o (--oem_settings)
- Use the file to specify the expected OEM-specific properties
- on the OEM partition of the intended device.
-
-w (--wipe_user_data)
Generate an OTA package that will wipe the user data partition
when installed.
@@ -64,47 +51,34 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package
-a (--aslr_mode)
Specify whether to turn on ASLR for the package (on by default).
-
- -2 (--two_step)
- Generate a 'two-step' OTA package, where recovery is updated
- first, so that any changes made to the system partition are done
- using the new recovery (new kernel, etc.).
-
- --block
- Generate a block-based OTA if possible. Will fall back to a
- file-based OTA if the target_files is older and doesn't support
- block-based OTAs.
-
- -b (--binary)
- Use the given binary as the update-binary in the output package,
- instead of the binary in the build's target_files. Use for
- development only.
-
- -t (--worker_threads)
- Specifies the number of worker-threads that will be used when
- generating patches for incremental updates (defaults to 3).
-
"""
import sys
-if sys.hexversion < 0x02070000:
- print >> sys.stderr, "Python 2.7 or newer is required."
+if sys.hexversion < 0x02040000:
+ print >> sys.stderr, "Python 2.4 or newer is required."
sys.exit(1)
-import multiprocessing
+import copy
+import errno
import os
+import re
+import subprocess
import tempfile
+import time
import zipfile
+try:
+ from hashlib import sha1 as sha1
+except ImportError:
+ from sha import sha as sha1
+
import common
import edify_generator
-import sparse_img
OPTIONS = common.OPTIONS
OPTIONS.package_key = None
OPTIONS.incremental_source = None
-OPTIONS.verify = False
OPTIONS.require_verbatim = set()
OPTIONS.prohibit_verbatim = set(("system/build.prop",))
OPTIONS.patch_threshold = 0.95
@@ -112,23 +86,13 @@ OPTIONS.wipe_user_data = False
OPTIONS.omit_prereq = False
OPTIONS.extra_script = None
OPTIONS.aslr_mode = True
-OPTIONS.worker_threads = multiprocessing.cpu_count() // 2
-if OPTIONS.worker_threads == 0:
- OPTIONS.worker_threads = 1
-OPTIONS.two_step = False
-OPTIONS.no_signing = False
-OPTIONS.block_based = False
-OPTIONS.updater_binary = None
-OPTIONS.oem_source = None
-OPTIONS.fallback_to_full = True
-OPTIONS.full_radio = False
+OPTIONS.worker_threads = 3
def MostPopularKey(d, default):
"""Given a dict, return the key corresponding to the largest
value. Returns 'default' if the dict is empty."""
x = [(v, k) for (k, v) in d.iteritems()]
- if not x:
- return default
+ if not x: return default
x.sort()
return x[-1][1]
@@ -136,187 +100,134 @@ def MostPopularKey(d, default):
def IsSymlink(info):
"""Return true if the zipfile.ZipInfo object passed in represents a
symlink."""
- return (info.external_attr >> 28) == 0o12
+ return (info.external_attr >> 16) == 0120777
def IsRegular(info):
"""Return true if the zipfile.ZipInfo object passed in represents a
symlink."""
- return (info.external_attr >> 28) == 0o10
-
-def ClosestFileMatch(src, tgtfiles, existing):
- """Returns the closest file match between a source file and list
- of potential matches. The exact filename match is preferred,
- then the sha1 is searched for, and finally a file with the same
- basename is evaluated. Rename support in the updater-binary is
- required for the latter checks to be used."""
-
- result = tgtfiles.get("path:" + src.name)
- if result is not None:
- return result
-
- # MIUI ADD:
- # disable rename support
- return None
-
- if not OPTIONS.target_info_dict.get("update_rename_support", False):
- return None
-
- if src.size < 1000:
- return None
-
- result = tgtfiles.get("sha1:" + src.sha1)
- if result is not None and existing.get(result.name) is None:
- return result
- result = tgtfiles.get("file:" + src.name.split("/")[-1])
- if result is not None and existing.get(result.name) is None:
- return result
- return None
-
-class ItemSet(object):
- def __init__(self, partition, fs_config):
- self.partition = partition
- self.fs_config = fs_config
- self.ITEMS = {}
-
- def Get(self, name, is_dir=False):
- if name not in self.ITEMS:
- self.ITEMS[name] = Item(self, name, is_dir=is_dir)
- return self.ITEMS[name]
-
- def GetMetadata(self, input_zip):
- # The target_files contains a record of what the uid,
- # gid, and mode are supposed to be.
- output = input_zip.read(self.fs_config)
-
- for line in output.split("\n"):
- if not line:
- continue
- columns = line.split()
- name, uid, gid, mode = columns[:4]
- selabel = None
- capabilities = None
-
- # After the first 4 columns, there are a series of key=value
- # pairs. Extract out the fields we care about.
- for element in columns[4:]:
- key, value = element.split("=")
- if key == "selabel":
- selabel = value
- if key == "capabilities":
- capabilities = value
-
- i = self.ITEMS.get(name, None)
- if i is not None:
- i.uid = int(uid)
- i.gid = int(gid)
- i.mode = int(mode, 8)
- i.selabel = selabel
- i.capabilities = capabilities
- if i.is_dir:
- i.children.sort(key=lambda i: i.name)
-
- # set metadata for the files generated by this script.
- # MIUI MOD:
- if self.partition == "system":
- i = self.ITEMS.get("system/recovery-from-boot.p", None)
- if i:
- i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0o644, None, None
- i = self.ITEMS.get("system/etc/install-recovery.sh", None)
- if i:
- i.uid, i.gid, i.mode, i.selabel, i.capabilities = 0, 0, 0o544, None, None
+ return (info.external_attr >> 28) == 010
-
-class Item(object):
+class Item:
"""Items represent the metadata (user, group, mode) of files and
directories in the system image."""
- def __init__(self, itemset, name, is_dir=False):
- self.itemset = itemset
+ ITEMS = {}
+ def __init__(self, name, dir=False):
self.name = name
self.uid = 0
self.gid = 0
- self.mode = 0o644
- self.selabel = None
- self.capabilities = None
- self.is_dir = is_dir
- self.descendants = None
- self.best_subtree = None
+ self.mode = 0644
+ self.dir = dir
+ if dir:
+ self.mode = 0755
if name:
- self.parent = itemset.Get(os.path.dirname(name), is_dir=True)
+ self.parent = Item.Get(os.path.dirname(name), dir=True)
self.parent.children.append(self)
else:
self.parent = None
- if self.is_dir:
+ if dir:
self.children = []
def Dump(self, indent=0):
if self.uid is not None:
- print "%s%s %d %d %o" % (
- " " * indent, self.name, self.uid, self.gid, self.mode)
+ print "%s%s %d %d %o" % (" "*indent, self.name, self.uid, self.gid, self.mode)
else:
- print "%s%s %s %s %s" % (
- " " * indent, self.name, self.uid, self.gid, self.mode)
- if self.is_dir:
+ print "%s%s %s %s %s" % (" "*indent, self.name, self.uid, self.gid, self.mode)
+ if self.dir:
print "%s%s" % (" "*indent, self.descendants)
print "%s%s" % (" "*indent, self.best_subtree)
for i in self.children:
i.Dump(indent=indent+1)
+ @classmethod
+ def Get(cls, name, dir=False):
+ if name not in cls.ITEMS:
+ cls.ITEMS[name] = Item(name, dir=dir)
+ return cls.ITEMS[name]
+
+ @classmethod
+ def GetMetadata(cls, input_zip):
+
+ try:
+ # See if the target_files contains a record of what the uid,
+ # gid, and mode is supposed to be.
+ output = input_zip.read("META/filesystem_config.txt")
+ except KeyError:
+ # Run the external 'fs_config' program to determine the desired
+ # uid, gid, and mode for every Item object. Note this uses the
+ # one in the client now, which might not be the same as the one
+ # used when this target_files was built.
+ p = common.Run(["fs_config"], stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ suffix = { False: "", True: "/" }
+ input = "".join(["%s%s\n" % (i.name, suffix[i.dir])
+ for i in cls.ITEMS.itervalues() if i.name])
+ output, error = p.communicate(input)
+ assert not error
+
+ for line in output.split("\n"):
+ if not line: continue
+ rows = line.split()
+ length = len(rows)
+ if length<4: continue
+ name = ' '.join(rows[0:length-3])
+ uid, gid, mode = rows[length-3:]
+ i = cls.ITEMS.get(name, None)
+ if i is not None:
+ i.uid = int(uid)
+ i.gid = int(gid)
+ i.mode = int(mode, 8)
+ if i.dir:
+ i.children.sort(key=lambda i: i.name)
+
+ # set metadata for the files generated by this script.
+ i = cls.ITEMS.get("system/recovery-from-boot.p", None)
+ if i: i.uid, i.gid, i.mode = 0, 0, 0644
+ i = cls.ITEMS.get("system/etc/install-recovery.sh", None)
+ if i: i.uid, i.gid, i.mode = 0, 0, 0544
+
def CountChildMetadata(self):
- """Count up the (uid, gid, mode, selabel, capabilities) tuples for
- all children and determine the best strategy for using set_perm_recursive
- and set_perm to correctly chown/chmod all the files to their desired
+ """Count up the (uid, gid, mode) tuples for all children and
+ determine the best strategy for using set_perm_recursive and
+ set_perm to correctly chown/chmod all the files to their desired
values. Recursively calls itself for all descendants.
- Returns a dict of {(uid, gid, dmode, fmode, selabel, capabilities): count}
- counting up all descendants of this node. (dmode or fmode may be None.)
- Also sets the best_subtree of each directory Item to the (uid, gid, dmode,
- fmode, selabel, capabilities) tuple that will match the most descendants of
- that Item.
+ Returns a dict of {(uid, gid, dmode, fmode): count} counting up
+ all descendants of this node. (dmode or fmode may be None.) Also
+ sets the best_subtree of each directory Item to the (uid, gid,
+ dmode, fmode) tuple that will match the most descendants of that
+ Item.
"""
- assert self.is_dir
- key = (self.uid, self.gid, self.mode, None, self.selabel,
- self.capabilities)
- self.descendants = {key: 1}
- d = self.descendants
+ assert self.dir
+ d = self.descendants = {(self.uid, self.gid, self.mode, None): 1}
for i in self.children:
- if i.is_dir:
+ if i.dir:
for k, v in i.CountChildMetadata().iteritems():
d[k] = d.get(k, 0) + v
else:
- k = (i.uid, i.gid, None, i.mode, i.selabel, i.capabilities)
+ k = (i.uid, i.gid, None, i.mode)
d[k] = d.get(k, 0) + 1
- # Find the (uid, gid, dmode, fmode, selabel, capabilities)
- # tuple that matches the most descendants.
+ # Find the (uid, gid, dmode, fmode) tuple that matches the most
+ # descendants.
# First, find the (uid, gid) pair that matches the most
# descendants.
ug = {}
- for (uid, gid, _, _, _, _), count in d.iteritems():
+ for (uid, gid, _, _), count in d.iteritems():
ug[(uid, gid)] = ug.get((uid, gid), 0) + count
ug = MostPopularKey(ug, (0, 0))
- # Now find the dmode, fmode, selabel, and capabilities that match
- # the most descendants with that (uid, gid), and choose those.
- best_dmode = (0, 0o755)
- best_fmode = (0, 0o644)
- best_selabel = (0, None)
- best_capabilities = (0, None)
+ # Now find the dmode and fmode that match the most descendants
+ # with that (uid, gid), and choose those.
+ best_dmode = (0, 0755)
+ best_fmode = (0, 0644)
for k, count in d.iteritems():
- if k[:2] != ug:
- continue
- if k[2] is not None and count >= best_dmode[0]:
- best_dmode = (count, k[2])
- if k[3] is not None and count >= best_fmode[0]:
- best_fmode = (count, k[3])
- if k[4] is not None and count >= best_selabel[0]:
- best_selabel = (count, k[4])
- if k[5] is not None and count >= best_capabilities[0]:
- best_capabilities = (count, k[5])
- self.best_subtree = ug + (
- best_dmode[1], best_fmode[1], best_selabel[1], best_capabilities[1])
+ if k[:2] != ug: continue
+ if k[2] is not None and count >= best_dmode[0]: best_dmode = (count, k[2])
+ if k[3] is not None and count >= best_fmode[0]: best_fmode = (count, k[3])
+ self.best_subtree = ug + (best_dmode[1], best_fmode[1])
return d
@@ -328,57 +239,52 @@ class Item(object):
self.CountChildMetadata()
def recurse(item, current):
- # current is the (uid, gid, dmode, fmode, selabel, capabilities) tuple
- # that the current item (and all its children) have already been set to.
- # We only need to issue set_perm/set_perm_recursive commands if we're
+ # current is the (uid, gid, dmode, fmode) tuple that the current
+ # item (and all its children) have already been set to. We only
+ # need to issue set_perm/set_perm_recursive commands if we're
# supposed to be something different.
- if item.is_dir:
+ if item.dir:
if current != item.best_subtree:
script.SetPermissionsRecursive("/"+item.name, *item.best_subtree)
current = item.best_subtree
if item.uid != current[0] or item.gid != current[1] or \
- item.mode != current[2] or item.selabel != current[4] or \
- item.capabilities != current[5]:
- script.SetPermissions("/"+item.name, item.uid, item.gid,
- item.mode, item.selabel, item.capabilities)
+ item.mode != current[2]:
+ script.SetPermissions("/"+item.name, item.uid, item.gid, item.mode)
for i in item.children:
recurse(i, current)
else:
if item.uid != current[0] or item.gid != current[1] or \
- item.mode != current[3] or item.selabel != current[4] or \
- item.capabilities != current[5]:
- script.SetPermissions("/"+item.name, item.uid, item.gid,
- item.mode, item.selabel, item.capabilities)
+ item.mode != current[3]:
+ script.SetPermissions("/"+item.name, item.uid, item.gid, item.mode)
- recurse(self, (-1, -1, -1, -1, None, None))
+ recurse(self, (-1, -1, -1, -1))
-def CopyPartitionFiles(itemset, input_zip, output_zip=None, substitute=None):
- """Copies files for the partition in the input zip to the output
+def CopySystemFiles(input_zip, output_zip=None,
+ substitute=None):
+ """Copies files underneath system/ in the input zip to the output
zip. Populates the Item class with their metadata, and returns a
- list of symlinks. output_zip may be None, in which case the copy is
- skipped (but the other side effects still happen). substitute is an
- optional dict of {output filename: contents} to be output instead of
- certain input files.
+ list of symlinks as well as a list of files that will be retouched.
+ output_zip may be None, in which case the copy is skipped (but the
+ other side effects still happen). substitute is an optional dict
+ of {output filename: contents} to be output instead of certain input
+ files.
"""
symlinks = []
-
- partition = itemset.partition
+ retouch_files = []
for info in input_zip.infolist():
- prefix = partition.upper() + "/"
- if info.filename.startswith(prefix):
- basefilename = info.filename[len(prefix):]
+ if info.filename.startswith("SYSTEM/"):
+ basefilename = info.filename[7:]
if IsSymlink(info):
symlinks.append((input_zip.read(info.filename),
- "/" + partition + "/" + basefilename))
+ "/system/" + basefilename))
else:
- import copy
info2 = copy.copy(info)
- fn = info2.filename = partition + "/" + basefilename
+ fn = info2.filename = "system/" + basefilename
if substitute and fn in substitute and substitute[fn] is None:
continue
if output_zip is not None:
@@ -386,15 +292,17 @@ def CopyPartitionFiles(itemset, input_zip, output_zip=None, substitute=None):
data = substitute[fn]
else:
data = input_zip.read(info.filename)
- common.ZipWriteStr(output_zip, info2, data)
+ if info.filename.startswith("SYSTEM/lib/") and IsRegular(info):
+ retouch_files.append(("/system/" + basefilename,
+ common.sha1(data).hexdigest()))
+ output_zip.writestr(info2, data)
if fn.endswith("/"):
- itemset.Get(fn[:-1], is_dir=True)
+ Item.Get(fn[:-1], dir=True)
else:
- itemset.Get(fn)
+ Item.Get(fn, dir=False)
symlinks.sort()
- return symlinks
-
+ return (symlinks, retouch_files)
def SignOutput(temp_zip_name, output_zip_name):
key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
@@ -404,124 +312,65 @@ def SignOutput(temp_zip_name, output_zip_name):
whole_file=True)
-def AppendAssertions(script, info_dict, oem_dict=None):
- oem_props = info_dict.get("oem_fingerprint_properties")
- if oem_props is None or len(oem_props) == 0:
- device = GetBuildProp("ro.product.device", info_dict)
- script.AssertDevice(device)
- else:
- if oem_dict is None:
- raise common.ExternalError(
- "No OEM file provided to answer expected assertions")
- for prop in oem_props.split():
- if oem_dict.get(prop) is None:
- raise common.ExternalError(
- "The OEM file is missing the property %s" % prop)
- script.AssertOemProperty(prop, oem_dict.get(prop))
-
-
-def HasRecoveryPatch(target_files_zip):
- try:
- target_files_zip.getinfo("SYSTEM/recovery-from-boot.p")
- return True
- except KeyError:
- return False
-
-def HasVendorPartition(target_files_zip):
- try:
- target_files_zip.getinfo("VENDOR/")
- return True
- except KeyError:
- return False
-
-# MIUI ADD
-def HasCustPartition(target_files_zip):
- try:
- target_files_zip.getinfo("CUST/")
- return True
- except KeyError:
- return False
-
-def GetOemProperty(name, oem_props, oem_dict, info_dict):
- if oem_props is not None and name in oem_props:
- return oem_dict[name]
- return GetBuildProp(name, info_dict)
-
-
-def CalculateFingerprint(oem_props, oem_dict, info_dict):
- if oem_props is None:
- return GetBuildProp("ro.build.fingerprint", info_dict)
- return "%s/%s/%s:%s" % (
- GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict),
- GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict),
- GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict),
- GetBuildProp("ro.build.thumbprint", info_dict))
-
-
-def GetImage(which, tmpdir, info_dict):
- # Return an image object (suitable for passing to BlockImageDiff)
- # for the 'which' partition (most be "system" or "vendor"). If a
- # prebuilt image and file map are found in tmpdir they are used,
- # otherwise they are reconstructed from the individual files.
-
- assert which in ("system", "vendor")
+def AppendAssertions(script, input_zip):
+ device = GetBuildProp("ro.product.device", input_zip)
+ script.AssertDevice(device)
- path = os.path.join(tmpdir, "IMAGES", which + ".img")
- mappath = os.path.join(tmpdir, "IMAGES", which + ".map")
- if os.path.exists(path) and os.path.exists(mappath):
- print "using %s.img from target-files" % (which,)
- # This is a 'new' target-files, which already has the image in it.
- else:
- print "building %s.img from target-files" % (which,)
+def MakeRecoveryPatch(output_zip, recovery_img, boot_img):
+ """Generate a binary patch that creates the recovery image starting
+ with the boot image. (Most of the space in these images is just the
+ kernel, which is identical for the two, so the resulting patch
+ should be efficient.) Add it to the output zip, along with a shell
+ script that is run from init.rc on first boot to actually do the
+ patching and install the new recovery image.
- # This is an 'old' target-files, which does not contain images
- # already built. Build them.
+ recovery_img and boot_img should be File objects for the
+ corresponding images. info should be the dictionary returned by
+ common.LoadInfoDict() on the input target_files.
- mappath = tempfile.mkstemp()[1]
- OPTIONS.tempfiles.append(mappath)
+ Returns an Item for the shell script, which must be made
+ executable.
+ """
- import add_img_to_target_files
- if which == "system":
- path = add_img_to_target_files.BuildSystem(
- tmpdir, info_dict, block_list=mappath)
- elif which == "vendor":
- path = add_img_to_target_files.BuildVendor(
- tmpdir, info_dict, block_list=mappath)
+ d = common.Difference(recovery_img, boot_img)
+ _, _, patch = d.ComputePatch()
+ common.ZipWriteStr(output_zip, "recovery/recovery-from-boot.p", patch)
+ Item.Get("system/recovery-from-boot.p", dir=False)
- # Bug: http://b/20939131
- # In ext4 filesystems, block 0 might be changed even being mounted
- # R/O. We add it to clobbered_blocks so that it will be written to the
- # target unconditionally. Note that they are still part of care_map.
- clobbered_blocks = "0"
+ boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict)
+ recovery_type, recovery_device = common.GetTypeAndDevice("/recovery", OPTIONS.info_dict)
- return sparse_img.SparseImage(path, mappath, clobbered_blocks)
+ sh = """#!/system/bin/sh
+if ! applypatch -c %(recovery_type)s:%(recovery_device)s:%(recovery_size)d:%(recovery_sha1)s; then
+ log -t recovery "Installing new recovery image"
+ applypatch %(boot_type)s:%(boot_device)s:%(boot_size)d:%(boot_sha1)s %(recovery_type)s:%(recovery_device)s %(recovery_sha1)s %(recovery_size)d %(boot_sha1)s:/system/recovery-from-boot.p
+else
+ log -t recovery "Recovery image already installed"
+fi
+""" % { 'boot_size': boot_img.size,
+ 'boot_sha1': boot_img.sha1,
+ 'recovery_size': recovery_img.size,
+ 'recovery_sha1': recovery_img.sha1,
+ 'boot_type': boot_type,
+ 'boot_device': boot_device,
+ 'recovery_type': recovery_type,
+ 'recovery_device': recovery_device,
+ }
+ common.ZipWriteStr(output_zip, "recovery/etc/install-recovery.sh", sh)
+ return Item.Get("system/etc/install-recovery.sh", dir=False)
def WriteFullOTAPackage(input_zip, output_zip):
# TODO: how to determine this? We don't know what version it will
- # be installed on top of. For now, we expect the API just won't
- # change very often. Similarly for fstab, it might have changed
- # in the target build.
+ # be installed on top of. For now, we expect the API just won't
+ # change very often.
script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
- oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
- recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
- oem_dict = None
- if oem_props is not None and len(oem_props) > 0:
- if OPTIONS.oem_source is None:
- raise common.ExternalError("OEM source required for this build")
- script.Mount("/oem", recovery_mount_options)
- oem_dict = common.LoadDictionaryFromLines(
- open(OPTIONS.oem_source).readlines())
-
- metadata = {
- "post-build": CalculateFingerprint(oem_props, oem_dict,
- OPTIONS.info_dict),
- "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
- OPTIONS.info_dict),
- "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict),
- }
+ metadata = {"post-build": GetBuildProp("ro.build.fingerprint", input_zip),
+ "pre-device": GetBuildProp("ro.product.device", input_zip),
+ "post-timestamp": GetBuildProp("ro.build.date.utc", input_zip),
+ }
device_specific = common.DeviceSpecificParams(
input_zip=input_zip,
@@ -532,239 +381,122 @@ def WriteFullOTAPackage(input_zip, output_zip):
metadata=metadata,
info_dict=OPTIONS.info_dict)
- has_recovery_patch = HasRecoveryPatch(input_zip)
- block_based = OPTIONS.block_based and has_recovery_patch
-
if not OPTIONS.omit_prereq:
- ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict)
- ts_text = GetBuildProp("ro.build.date", OPTIONS.info_dict)
- script.AssertOlderBuild(ts, ts_text)
+ ts = GetBuildProp("ro.build.date.utc", input_zip)
+ script.AssertOlderBuild(ts)
- AppendAssertions(script, OPTIONS.info_dict, oem_dict)
+ AppendAssertions(script, input_zip)
device_specific.FullOTA_Assertions()
- # Two-step package strategy (in chronological order, which is *not*
- # the order in which the generated script has things):
- #
- # if stage is not "2/3" or "3/3":
- # write recovery image to boot partition
- # set stage to "2/3"
- # reboot to boot partition and restart recovery
- # else if stage is "2/3":
- # write recovery image to recovery partition
- # set stage to "3/3"
- # reboot to recovery partition and restart recovery
- # else:
- # (stage must be "3/3")
- # set stage to ""
- # do normal full package installation:
- # wipe and install system, boot image, etc.
- # set up system to update recovery partition on first boot
- # complete script normally
- # (allow recovery to mark itself finished and reboot)
-
- #recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
- # OPTIONS.input_tmp, "RECOVERY")
- #if OPTIONS.two_step:
- # if not OPTIONS.info_dict.get("multistage_support", None):
- # assert False, "two-step packages not supported by this build"
- # fs = OPTIONS.info_dict["fstab"]["/misc"]
- # assert fs.fs_type.upper() == "EMMC", \
- # "two-step packages only supported on devices with EMMC /misc partitions"
- # bcb_dev = {"bcb_dev": fs.device}
- # common.ZipWriteStr(output_zip, "recovery.img", recovery_img.data)
- # script.AppendExtra("""
-#if get_stage("%(bcb_dev)s") == "2/3" then
-#""" % bcb_dev)
-# script.WriteRawImage("/recovery", "recovery.img")
-# script.AppendExtra("""
-#set_stage("%(bcb_dev)s", "3/3");
-#reboot_now("%(bcb_dev)s", "recovery");
-#else if get_stage("%(bcb_dev)s") == "3/3" then
-#""" % bcb_dev)
-
- # Dump fingerprints
- script.Print("Target: %s" % CalculateFingerprint(
- oem_props, oem_dict, OPTIONS.info_dict))
-
- device_specific.FullOTA_InstallBegin()
-
- system_progress = 0.75
+ script.ShowProgress(0.5, 0)
if OPTIONS.wipe_user_data:
- system_progress -= 0.1
- if HasVendorPartition(input_zip):
- system_progress -= 0.1
- # MIUI ADD:
- if HasCustPartition(input_zip):
- system_progress -= 0.1
-
- if "selinux_fc" in OPTIONS.info_dict:
- WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip)
-
- recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
-
- system_items = ItemSet("system", "META/filesystem_config.txt")
- script.ShowProgress(system_progress, 0)
-
- if block_based:
- # Full OTA is done as an "incremental" against an empty source
- # image. This has the effect of writing new data from the package
- # to the entire partition, but lets us reuse the updater code that
- # writes incrementals to do it.
- system_tgt = GetImage("system", OPTIONS.input_tmp, OPTIONS.info_dict)
- system_tgt.ResetFileMap()
- system_diff = common.BlockDifference("system", system_tgt, src=None)
- system_diff.WriteScript(script, output_zip)
- else:
- script.FormatPartition("/system")
- script.Mount("/system", recovery_mount_options)
- if not has_recovery_patch:
- script.UnpackPackageDir("recovery", "/system")
- script.UnpackPackageDir("system", "/system")
-
- symlinks = CopyPartitionFiles(system_items, input_zip, output_zip)
- script.MakeSymlinks(symlinks)
-
- boot_img = common.GetBootableImage("boot.img", "boot.img",
- OPTIONS.input_tmp, "BOOT")
-
- if not block_based:
- def output_sink(fn, data):
- common.ZipWriteStr(output_zip, "recovery/" + fn, data)
- system_items.Get("system/" + fn)
-
- #common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink,
- # recovery_img, boot_img)
-
- system_items.GetMetadata(input_zip)
- system_items.Get("system").SetPermissions(script)
-
- if HasVendorPartition(input_zip):
- vendor_items = ItemSet("vendor", "META/vendor_filesystem_config.txt")
- script.ShowProgress(0.1, 0)
+ script.FormatPartition("/data")
- if block_based:
- vendor_tgt = GetImage("vendor", OPTIONS.input_tmp, OPTIONS.info_dict)
- vendor_tgt.ResetFileMap()
- vendor_diff = common.BlockDifference("vendor", vendor_tgt)
- vendor_diff.WriteScript(script, output_zip)
- else:
- script.FormatPartition("/vendor")
- script.Mount("/vendor", recovery_mount_options)
- script.UnpackPackageDir("vendor", "/vendor")
+ script.Print("Formatting system...")
+ script.Unmount("/system")
+ script.FormatPartition("/system")
- symlinks = CopyPartitionFiles(vendor_items, input_zip, output_zip)
- script.MakeSymlinks(symlinks)
+ script.Print("Installing system files...")
+ script.Mount("/system")
+ #script.UnpackPackageDir("recovery", "/system")
+ script.UnpackPackageDir("system", "/system")
- vendor_items.GetMetadata(input_zip)
- vendor_items.Get("vendor").SetPermissions(script)
+ script.Print("Creating system links...")
+ (symlinks, retouch_files) = CopySystemFiles(input_zip, output_zip)
+ script.MakeSymlinks(symlinks)
+ # if OPTIONS.aslr_mode:
+ # script.RetouchBinaries(retouch_files)
+ # else:
+ # script.UndoRetouchBinaries(retouch_files)
- if HasCustPartition(input_zip):
- cust_items = ItemSet("cust", "META/cust_filesystem_config.txt")
- script.ShowProgress(0.1, 0)
- script.Mount("/cust", recovery_mount_options)
- script.UnpackPackageDir("cust", "/cust")
- symlinks = CopyPartitionFiles(cust_items, input_zip, output_zip)
- script.MakeSymlinks(symlinks)
- cust_items.GetMetadata(input_zip)
- cust_items.Get("cust").SetPermissions(script)
+ boot_img = common.GetBootableImage("boot.img", "boot.img",
+ OPTIONS.input_tmp, "BOOT")
+ # recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
+ # OPTIONS.input_tmp, "RECOVERY")
+ # MakeRecoveryPatch(output_zip, recovery_img, boot_img)
- #common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict)
- common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
+ script.Print("Set permission...")
+ Item.GetMetadata(input_zip)
+ Item.Get("system").SetPermissions(script)
- script.ShowProgress(0.05, 5)
- script.WriteRawImage("/boot", "boot.img")
+ script.Print("Update Boot image...")
+ if boot_img:
+ common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict)
+ common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
+ script.ShowProgress(0.2, 0)
script.ShowProgress(0.2, 10)
+ if boot_img and not device_specific.WriteRawImage("/boot", "boot.img"):
+ script.WriteRawImage("/boot", "boot.img")
+
+ script.ShowProgress(0.1, 0)
device_specific.FullOTA_InstallEnd()
if OPTIONS.extra_script is not None:
script.AppendExtra(OPTIONS.extra_script)
script.UnmountAll()
-
- if OPTIONS.wipe_user_data:
- script.ShowProgress(0.1, 10)
- script.FormatPartition("/data")
-
- if OPTIONS.two_step:
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "");
-""" % bcb_dev)
- script.AppendExtra("else\n")
- script.WriteRawImage("/boot", "recovery.img")
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "2/3");
-reboot_now("%(bcb_dev)s", "");
-endif;
-endif;
-""" % bcb_dev)
- script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary)
+ script.AddToZip(input_zip, output_zip)
WriteMetadata(metadata, output_zip)
-def WritePolicyConfig(file_name, output_zip):
- common.ZipWrite(output_zip, file_name, os.path.basename(file_name))
-
-
def WriteMetadata(metadata, output_zip):
common.ZipWriteStr(output_zip, "META-INF/com/android/metadata",
"".join(["%s=%s\n" % kv
for kv in sorted(metadata.iteritems())]))
-def LoadPartitionFiles(z, partition):
- """Load all the files from the given partition in a given target-files
+
+
+def LoadSystemFiles(z):
+ """Load all the files from SYSTEM/... in a given target-files
ZipFile, and return a dict of {filename: File object}."""
out = {}
- prefix = partition.upper() + "/"
+ retouch_files = []
for info in z.infolist():
- if info.filename.startswith(prefix) and not IsSymlink(info):
- basefilename = info.filename[len(prefix):]
- fn = partition + "/" + basefilename
+ if info.filename.startswith("SYSTEM/") and not IsSymlink(info):
+ basefilename = info.filename[7:]
+ fn = "system/" + basefilename
data = z.read(info.filename)
out[fn] = common.File(fn, data)
- return out
-
-
-def GetBuildProp(prop, info_dict):
- """Return the fingerprint of the build of a given target-files info_dict."""
- try:
- return info_dict.get("build.prop", {})[prop]
- except KeyError:
- raise common.ExternalError("couldn't find %s in build.prop" % (prop,))
+ if info.filename.startswith("SYSTEM/lib/") and IsRegular(info):
+ retouch_files.append(("/system/" + basefilename,
+ out[fn].sha1))
+ # MIUI ADDD:
+ # load /data/miui files
+ elif info.filename.startswith("DATA/miui/") and not IsSymlink(info):
+ basefilename = info.filename[5:]
+ fn = "data/" + basefilename
+ data = z.read(info.filename)
+ out[fn] = common.File(fn, data)
+ return (out, retouch_files)
-def AddToKnownPaths(filename, known_paths):
- if filename[-1] == "/":
- return
- dirs = filename.split("/")[:-1]
- while len(dirs) > 0:
- path = "/".join(dirs)
- if path in known_paths:
- break
- known_paths.add(path)
- dirs.pop()
+def GetBuildProp(property, z):
+ """Return the fingerprint of the build of a given target-files
+ ZipFile object."""
+ bp = z.read("SYSTEM/build.prop")
+ if not property:
+ return bp
+ m = re.search(re.escape(property) + r"=(.*)\n", bp)
+ if not m:
+ raise common.ExternalError("couldn't find %s in build.prop" % (property,))
+ return m.group(1).strip()
-def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
+def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
source_version = OPTIONS.source_info_dict["recovery_api_version"]
target_version = OPTIONS.target_info_dict["recovery_api_version"]
if source_version == 0:
print ("WARNING: generating edify script for a source that "
"can't install it.")
- script = edify_generator.EdifyGenerator(
- source_version, OPTIONS.target_info_dict,
- fstab=OPTIONS.source_info_dict["fstab"])
+ script = edify_generator.EdifyGenerator(source_version, OPTIONS.target_info_dict)
- metadata = {
- "pre-device": GetBuildProp("ro.product.device",
- OPTIONS.source_info_dict),
- "post-timestamp": GetBuildProp("ro.build.date.utc",
- OPTIONS.target_info_dict),
- }
+ metadata = {"pre-device": GetBuildProp("ro.product.device", source_zip),
+ "post-timestamp": GetBuildProp("ro.build.date.utc", target_zip),
+ }
device_specific = common.DeviceSpecificParams(
source_zip=source_zip,
@@ -776,575 +508,94 @@ def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
metadata=metadata,
info_dict=OPTIONS.info_dict)
- # MIUI ADD: START
- if "selinux_fc" in OPTIONS.info_dict:
- WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip)
- # END
-
- # TODO: Currently this works differently from WriteIncrementalOTAPackage().
- # This function doesn't consider thumbprints when writing
- # metadata["pre/post-build"]. One possible reason is that the current
- # devices with thumbprints are all using file-based OTAs. Long term we
- # should factor out the common parts into a shared one to avoid further
- # divergence.
- source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict)
- target_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.target_info_dict)
- metadata["pre-build"] = source_fp
- metadata["post-build"] = target_fp
-
- source_boot = common.GetBootableImage(
- "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT",
- OPTIONS.source_info_dict)
- target_boot = common.GetBootableImage(
- "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT")
- updating_boot = (not OPTIONS.two_step and
- (source_boot.data != target_boot.data))
-
- target_recovery = common.GetBootableImage(
- "/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY")
-
- system_src = GetImage("system", OPTIONS.source_tmp, OPTIONS.source_info_dict)
- system_tgt = GetImage("system", OPTIONS.target_tmp, OPTIONS.target_info_dict)
-
- blockimgdiff_version = 1
- if OPTIONS.info_dict:
- blockimgdiff_version = max(
- int(i) for i in
- OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
-
- system_diff = common.BlockDifference("system", system_tgt, system_src,
- version=blockimgdiff_version)
-
- if HasVendorPartition(target_zip):
- if not HasVendorPartition(source_zip):
- raise RuntimeError("can't generate incremental that adds /vendor")
- vendor_src = GetImage("vendor", OPTIONS.source_tmp,
- OPTIONS.source_info_dict)
- vendor_tgt = GetImage("vendor", OPTIONS.target_tmp,
- OPTIONS.target_info_dict)
- vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src,
- version=blockimgdiff_version)
- else:
- vendor_diff = None
-
- oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties")
- recovery_mount_options = OPTIONS.source_info_dict.get(
- "recovery_mount_options")
- oem_dict = None
- if oem_props is not None and len(oem_props) > 0:
- if OPTIONS.oem_source is None:
- raise common.ExternalError("OEM source required for this build")
- script.Mount("/oem", recovery_mount_options)
- oem_dict = common.LoadDictionaryFromLines(
- open(OPTIONS.oem_source).readlines())
-
- AppendAssertions(script, OPTIONS.target_info_dict, oem_dict)
- device_specific.IncrementalOTA_Assertions()
-
- # MIUI ADD: support cust
- cust_diff = None
- if HasCustPartition(target_zip):
- if not HasCustPartition(source_zip):
- cust_items = ItemSet("cust", "META/cust_filesystem_config.txt")
-
- script.FormatPartition("/cust")
- script.Mount("/cust", recovery_mount_options)
- script.UnpackPackageDir("cust", "/cust")
-
- symlinks = CopyPartitionFiles(cust_items, target_zip, output_zip)
- script.MakeSymlinks(symlinks)
-
- cust_items.GetMetadata(target_zip)
- cust_items.Get("cust").SetPermissions(script)
- else:
- # cust_diff = FileDifference("cust", source_zip, target_zip, output_zip)
- # script.Mount("/cust", recovery_mount_options)
- cust_items = ItemSet("cust", "META/cust_filesystem_config.txt")
-
- script.Mount("/cust", recovery_mount_options)
- script.UnpackPackageDir("cust", "/cust")
-
- symlinks = CopyPartitionFiles(cust_items, target_zip, output_zip)
- script.MakeSymlinks(symlinks)
-
- cust_items.GetMetadata(target_zip)
- cust_items.Get("cust").SetPermissions(script)
-
- # Two-step incremental package strategy (in chronological order,
- # which is *not* the order in which the generated script has
- # things):
- #
- # if stage is not "2/3" or "3/3":
- # do verification on current system
- # write recovery image to boot partition
- # set stage to "2/3"
- # reboot to boot partition and restart recovery
- # else if stage is "2/3":
- # write recovery image to recovery partition
- # set stage to "3/3"
- # reboot to recovery partition and restart recovery
- # else:
- # (stage must be "3/3")
- # perform update:
- # patch system files, etc.
- # force full install of new boot image
- # set up system to update recovery partition on first boot
- # complete script normally
- # (allow recovery to mark itself finished and reboot)
-
- if OPTIONS.two_step:
- if not OPTIONS.source_info_dict.get("multistage_support", None):
- assert False, "two-step packages not supported by this build"
- fs = OPTIONS.source_info_dict["fstab"]["/misc"]
- assert fs.fs_type.upper() == "EMMC", \
- "two-step packages only supported on devices with EMMC /misc partitions"
- bcb_dev = {"bcb_dev": fs.device}
- common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data)
- script.AppendExtra("""
-if get_stage("%(bcb_dev)s") == "2/3" then
-""" % bcb_dev)
- script.AppendExtra("sleep(20);\n")
- script.WriteRawImage("/recovery", "recovery.img")
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "3/3");
-reboot_now("%(bcb_dev)s", "recovery");
-else if get_stage("%(bcb_dev)s") != "3/3" then
-""" % bcb_dev)
-
- # Dump fingerprints
- script.Print("Source: %s" % CalculateFingerprint(
- oem_props, oem_dict, OPTIONS.source_info_dict))
- script.Print("Target: %s" % CalculateFingerprint(
- oem_props, oem_dict, OPTIONS.target_info_dict))
-
- script.Print("Verifying current system...")
-
- device_specific.IncrementalOTA_VerifyBegin()
-
- if oem_props is None:
- # When blockimgdiff version is less than 3 (non-resumable block-based OTA),
- # patching on a device that's already on the target build will damage the
- # system. Because operations like move don't check the block state, they
- # always apply the changes unconditionally.
- if blockimgdiff_version <= 2:
- script.AssertSomeFingerprint(source_fp)
- else:
- script.AssertSomeFingerprint(source_fp, target_fp)
- else:
- if blockimgdiff_version <= 2:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
- else:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
-
- if updating_boot:
- boot_type, boot_device = common.GetTypeAndDevice(
- "/boot", OPTIONS.source_info_dict)
- d = common.Difference(target_boot, source_boot)
- _, _, d = d.ComputePatch()
- if d is None:
- include_full_boot = True
- common.ZipWriteStr(output_zip, "boot.img", target_boot.data)
+ print "Loading target..."
+ (target_data, target_retouch_files) = LoadSystemFiles(target_zip)
+ print "Loading source..."
+ (source_data, source_retouch_files) = LoadSystemFiles(source_zip)
+
+ verbatim_targets = []
+ patch_list = []
+ diffs = []
+ largest_source_size = 0
+ for fn in sorted(target_data.keys()):
+ tf = target_data[fn]
+ assert fn == tf.name
+ sf = source_data.get(fn, None)
+
+ if sf is None or fn in OPTIONS.require_verbatim:
+ # This file should be included verbatim
+ if fn in OPTIONS.prohibit_verbatim:
+ raise common.ExternalError("\"%s\" must be sent verbatim" % (fn,))
+ print "send", fn, "verbatim"
+ tf.AddToZip(output_zip)
+ verbatim_targets.append((fn, tf.size))
+ elif tf.sha1 != sf.sha1:
+ # File is different; consider sending as a patch
+ diffs.append(common.Difference(tf, sf))
else:
- include_full_boot = False
-
- print "boot target: %d source: %d diff: %d" % (
- target_boot.size, source_boot.size, len(d))
-
- common.ZipWriteStr(output_zip, "patch/boot.img.p", d)
-
- script.PatchCheck("%s:%s:%d:%s:%d:%s" %
- (boot_type, boot_device,
- source_boot.size, source_boot.sha1,
- target_boot.size, target_boot.sha1))
-
- device_specific.IncrementalOTA_VerifyEnd()
-
- if OPTIONS.two_step:
- script.WriteRawImage("/boot", "recovery.img")
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "2/3");
-reboot_now("%(bcb_dev)s", "");
-else
-""" % bcb_dev)
-
- # Verify the existing partitions.
- system_diff.WriteVerifyScript(script)
- if vendor_diff:
- vendor_diff.WriteVerifyScript(script)
-
- script.Comment("---- start making changes here ----")
+ # Target file identical to source.
+ pass
- device_specific.IncrementalOTA_InstallBegin()
+ common.ComputeDifferences(diffs)
- system_diff.WriteScript(script, output_zip,
- progress=0.8 if vendor_diff else 0.9)
- if vendor_diff:
- vendor_diff.WriteScript(script, output_zip, progress=0.1)
-
- if OPTIONS.two_step:
- common.ZipWriteStr(output_zip, "boot.img", target_boot.data)
- script.WriteRawImage("/boot", "boot.img")
- print "writing full boot image (forced by two-step mode)"
-
- if not OPTIONS.two_step:
- if updating_boot:
- if include_full_boot:
- print "boot image changed; including full."
- script.Print("Installing boot image...")
- script.WriteRawImage("/boot", "boot.img")
- else:
- # Produce the boot image by applying a patch to the current
- # contents of the boot partition, and write it back to the
- # partition.
- print "boot image changed; including patch."
- script.Print("Patching boot image...")
- script.ShowProgress(0.1, 10)
- script.ApplyPatch("%s:%s:%d:%s:%d:%s"
- % (boot_type, boot_device,
- source_boot.size, source_boot.sha1,
- target_boot.size, target_boot.sha1),
- "-",
- target_boot.size, target_boot.sha1,
- source_boot.sha1, "patch/boot.img.p")
+ for diff in diffs:
+ tf, sf, d = diff.GetPatch()
+ if d is None or len(d) > tf.size * OPTIONS.patch_threshold:
+ # patch is almost as big as the file; don't bother patching
+ tf.AddToZip(output_zip)
+ verbatim_targets.append((tf.name, tf.size))
else:
- print "boot image unchanged; skipping."
-
- # Do device-specific installation (eg, write radio image).
- device_specific.IncrementalOTA_InstallEnd()
-
- if OPTIONS.extra_script is not None:
- script.AppendExtra(OPTIONS.extra_script)
-
- if OPTIONS.wipe_user_data:
- script.Print("Erasing user data...")
- script.FormatPartition("/data")
-
- if OPTIONS.two_step:
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "");
-endif;
-endif;
-""" % bcb_dev)
-
- script.SetProgress(1)
- script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary)
- WriteMetadata(metadata, output_zip)
-
-
-class FileDifference(object):
- def __init__(self, partition, source_zip, target_zip, output_zip):
- self.deferred_patch_list = None
- print "Loading target..."
- self.target_data = target_data = LoadPartitionFiles(target_zip, partition)
- print "Loading source..."
- self.source_data = source_data = LoadPartitionFiles(source_zip, partition)
-
- self.verbatim_targets = verbatim_targets = []
- self.patch_list = patch_list = []
- diffs = []
- self.renames = renames = {}
- known_paths = set()
- largest_source_size = 0
-
- matching_file_cache = {}
- for fn, sf in source_data.items():
- assert fn == sf.name
- matching_file_cache["path:" + fn] = sf
- if fn in target_data.keys():
- AddToKnownPaths(fn, known_paths)
- # Only allow eligibility for filename/sha matching
- # if there isn't a perfect path match.
- if target_data.get(sf.name) is None:
- matching_file_cache["file:" + fn.split("/")[-1]] = sf
- matching_file_cache["sha:" + sf.sha1] = sf
-
- for fn in sorted(target_data.keys()):
- tf = target_data[fn]
- assert fn == tf.name
- # MIUI ADD: START
- if fn.startswith("data/") and not fn.startswith("data/miui/"):
- continue
- # END
- sf = ClosestFileMatch(tf, matching_file_cache, renames)
- if sf is not None and sf.name != tf.name:
- print "File has moved from " + sf.name + " to " + tf.name
- renames[sf.name] = tf
-
- if sf is None or fn in OPTIONS.require_verbatim:
- # This file should be included verbatim
- if fn in OPTIONS.prohibit_verbatim:
- raise common.ExternalError("\"%s\" must be sent verbatim" % (fn,))
- print "send", fn, "verbatim"
- tf.AddToZip(output_zip)
- verbatim_targets.append((fn, tf.size, tf.sha1))
- if fn in target_data.keys():
- AddToKnownPaths(fn, known_paths)
- elif tf.sha1 != sf.sha1:
- # File is different; consider sending as a patch
- diffs.append(common.Difference(tf, sf))
- else:
- # Target file data identical to source (may still be renamed)
- pass
-
- common.ComputeDifferences(diffs)
-
- for diff in diffs:
- tf, sf, d = diff.GetPatch()
- path = "/".join(tf.name.split("/")[:-1])
- if d is None or len(d) > tf.size * OPTIONS.patch_threshold or \
- path not in known_paths:
- # patch is almost as big as the file; don't bother patching
- # or a patch + rename cannot take place due to the target
- # directory not existing
- tf.AddToZip(output_zip)
- verbatim_targets.append((tf.name, tf.size, tf.sha1))
- if sf.name in renames:
- del renames[sf.name]
- AddToKnownPaths(tf.name, known_paths)
- else:
- common.ZipWriteStr(output_zip, "patch/" + sf.name + ".p", d)
- patch_list.append((tf, sf, tf.size, common.sha1(d).hexdigest()))
- largest_source_size = max(largest_source_size, sf.size)
-
- self.largest_source_size = largest_source_size
-
- def EmitVerification(self, script):
- so_far = 0
- for tf, sf, _, _ in self.patch_list:
- if tf.name != sf.name:
- script.SkipNextActionIfTargetExists(tf.name, tf.sha1)
- script.PatchCheck("/"+sf.name, tf.sha1, sf.sha1)
- so_far += sf.size
- return so_far
-
- def EmitExplicitTargetVerification(self, script):
- for fn, _, sha1 in self.verbatim_targets:
- if fn[-1] != "/":
- script.FileCheck("/"+fn, sha1)
- for tf, _, _, _ in self.patch_list:
- script.FileCheck(tf.name, tf.sha1)
-
- def RemoveUnneededFiles(self, script, extras=()):
- script.DeleteFiles(
- ["/" + i[0] for i in self.verbatim_targets] +
- ["/" + i for i in sorted(self.source_data)
- if i not in self.target_data and i not in self.renames] +
- list(extras))
-
- def TotalPatchSize(self):
- return sum(i[1].size for i in self.patch_list)
-
- def EmitPatches(self, script, total_patch_size, so_far):
- self.deferred_patch_list = deferred_patch_list = []
- for item in self.patch_list:
- tf, sf, _, _ = item
- if tf.name == "system/build.prop":
- deferred_patch_list.append(item)
- continue
- if sf.name != tf.name:
- script.SkipNextActionIfTargetExists(tf.name, tf.sha1)
- script.ApplyPatch("/" + sf.name, "-", tf.size, tf.sha1, sf.sha1,
- "patch/" + sf.name + ".p")
- so_far += tf.size
- script.SetProgress(so_far / total_patch_size)
- return so_far
-
- def EmitDeferredPatches(self, script):
- for item in self.deferred_patch_list:
- tf, sf, _, _ = item
- script.ApplyPatch("/"+sf.name, "-", tf.size, tf.sha1, sf.sha1,
- "patch/" + sf.name + ".p")
- script.SetPermissions("/system/build.prop", 0, 0, 0o644, None, None)
-
- def EmitRenames(self, script):
- if len(self.renames) > 0:
- script.Print("Renaming files...")
- for src, tgt in self.renames.iteritems():
- print "Renaming " + src + " to " + tgt.name
- script.RenameFile(src, tgt.name)
-
-
-def WriteIncrementalOTAPackage(target_zip, source_zip, output_zip):
- target_has_recovery_patch = HasRecoveryPatch(target_zip)
- source_has_recovery_patch = HasRecoveryPatch(source_zip)
-
- if (OPTIONS.block_based and
- target_has_recovery_patch and
- source_has_recovery_patch):
- return WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip)
-
- source_version = OPTIONS.source_info_dict["recovery_api_version"]
- target_version = OPTIONS.target_info_dict["recovery_api_version"]
-
- if source_version == 0:
- print ("WARNING: generating edify script for a source that "
- "can't install it.")
- script = edify_generator.EdifyGenerator(
- source_version, OPTIONS.target_info_dict,
- fstab=OPTIONS.source_info_dict["fstab"])
-
- oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
- recovery_mount_options = OPTIONS.source_info_dict.get(
- "recovery_mount_options")
- oem_dict = None
- if oem_props is not None and len(oem_props) > 0:
- if OPTIONS.oem_source is None:
- raise common.ExternalError("OEM source required for this build")
- script.Mount("/oem", recovery_mount_options)
- oem_dict = common.LoadDictionaryFromLines(
- open(OPTIONS.oem_source).readlines())
-
- metadata = {
- "pre-device": GetOemProperty("ro.product.device", oem_props, oem_dict,
- OPTIONS.source_info_dict),
- "post-timestamp": GetBuildProp("ro.build.date.utc",
- OPTIONS.target_info_dict),
- }
-
- device_specific = common.DeviceSpecificParams(
- source_zip=source_zip,
- source_version=source_version,
- target_zip=target_zip,
- target_version=target_version,
- output_zip=output_zip,
- script=script,
- metadata=metadata,
- info_dict=OPTIONS.info_dict)
-
- # MIUI ADD:
- data_diff = FileDifference("data", source_zip, target_zip, output_zip)
-
- # MIUI ADD: START
- if "selinux_fc" in OPTIONS.info_dict:
- WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip)
- # END
-
- system_diff = FileDifference("system", source_zip, target_zip, output_zip)
- script.Mount("/system", recovery_mount_options)
- if HasVendorPartition(target_zip):
- vendor_diff = FileDifference("vendor", source_zip, target_zip, output_zip)
- script.Mount("/vendor", recovery_mount_options)
- else:
- vendor_diff = None
-
- target_fp = CalculateFingerprint(oem_props, oem_dict,
- OPTIONS.target_info_dict)
- source_fp = CalculateFingerprint(oem_props, oem_dict,
- OPTIONS.source_info_dict)
-
- if oem_props is None:
- script.AssertSomeFingerprint(source_fp, target_fp)
- else:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
+ common.ZipWriteStr(output_zip, "patch/" + tf.name + ".p", d)
+ patch_list.append((tf.name, tf, sf, tf.size, common.sha1(d).hexdigest()))
+ largest_source_size = max(largest_source_size, sf.size)
+ source_fp = GetBuildProp("ro.build.fingerprint", source_zip)
+ target_fp = GetBuildProp("ro.build.fingerprint", target_zip)
metadata["pre-build"] = source_fp
metadata["post-build"] = target_fp
+ script.Mount("/system")
+ script.AssertSomeFingerprint(source_fp, target_fp)
+
source_boot = common.GetBootableImage(
- "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT",
- OPTIONS.source_info_dict)
+ "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT")
target_boot = common.GetBootableImage(
"/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT")
- updating_boot = (not OPTIONS.two_step and
- (source_boot.data != target_boot.data))
+ # updating_boot = (source_boot != None and target_boot != None and source_boot.data != target_boot.data)
+ updating_boot = False
+ need_install_boot = (source_boot != None and target_boot != None and source_boot.data != target_boot.data)
source_recovery = common.GetBootableImage(
- "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY",
- OPTIONS.source_info_dict)
+ "/tmp/recovery.img", "recovery.img", OPTIONS.source_tmp, "RECOVERY")
target_recovery = common.GetBootableImage(
"/tmp/recovery.img", "recovery.img", OPTIONS.target_tmp, "RECOVERY")
- updating_recovery = (source_recovery.data != target_recovery.data)
-
+ #updating_recovery = (source_recovery.data != target_recovery.data)
+ updating_recovery = False
# Here's how we divide up the progress bar:
# 0.1 for verifying the start state (PatchCheck calls)
# 0.8 for applying patches (ApplyPatch calls)
# 0.1 for unpacking verbatim files, symlinking, and doing the
# device-specific commands.
- AppendAssertions(script, OPTIONS.target_info_dict, oem_dict)
+ AppendAssertions(script, target_zip)
device_specific.IncrementalOTA_Assertions()
- # MIUI ADD
- cust_diff = None
- if HasCustPartition(target_zip):
- if not HasCustPartition(source_zip):
- cust_items = ItemSet("cust", "META/cust_filesystem_config.txt")
-
- script.FormatPartition("/cust")
- script.Mount("/cust", recovery_mount_options)
- script.UnpackPackageDir("cust", "/cust")
-
- symlinks = CopyPartitionFiles(cust_items, target_zip, output_zip)
- script.MakeSymlinks(symlinks)
-
- cust_items.GetMetadata(target_zip)
- cust_items.Get("cust").SetPermissions(script)
- else:
- cust_diff = FileDifference("cust", source_zip, target_zip, output_zip)
- script.Mount("/cust", recovery_mount_options)
-
- # Two-step incremental package strategy (in chronological order,
- # which is *not* the order in which the generated script has
- # things):
- #
- # if stage is not "2/3" or "3/3":
- # do verification on current system
- # write recovery image to boot partition
- # set stage to "2/3"
- # reboot to boot partition and restart recovery
- # else if stage is "2/3":
- # write recovery image to recovery partition
- # set stage to "3/3"
- # reboot to recovery partition and restart recovery
- # else:
- # (stage must be "3/3")
- # perform update:
- # patch system files, etc.
- # force full install of new boot image
- # set up system to update recovery partition on first boot
- # complete script normally
- # (allow recovery to mark itself finished and reboot)
-
- if OPTIONS.two_step:
- if not OPTIONS.source_info_dict.get("multistage_support", None):
- assert False, "two-step packages not supported by this build"
- fs = OPTIONS.source_info_dict["fstab"]["/misc"]
- assert fs.fs_type.upper() == "EMMC", \
- "two-step packages only supported on devices with EMMC /misc partitions"
- bcb_dev = {"bcb_dev": fs.device}
- common.ZipWriteStr(output_zip, "recovery.img", target_recovery.data)
- script.AppendExtra("""
-if get_stage("%(bcb_dev)s") == "2/3" then
-""" % bcb_dev)
- script.AppendExtra("sleep(20);\n")
- script.WriteRawImage("/recovery", "recovery.img")
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "3/3");
-reboot_now("%(bcb_dev)s", "recovery");
-else if get_stage("%(bcb_dev)s") != "3/3" then
-""" % bcb_dev)
-
- # Dump fingerprints
- script.Print("Source: %s" % (source_fp,))
- script.Print("Target: %s" % (target_fp,))
-
script.Print("Verifying current system...")
- device_specific.IncrementalOTA_VerifyBegin()
-
script.ShowProgress(0.1, 0)
- so_far = system_diff.EmitVerification(script)
- if vendor_diff:
- so_far += vendor_diff.EmitVerification(script)
-
- # MIUI ADD
- if cust_diff:
- so_far += cust_diff.EmitVerification(script)
+ total_verify_size = float(sum([i[2].size for i in patch_list]) + 1)
+ if updating_boot:
+ total_verify_size += source_boot.size
+ so_far = 0
+
+ for fn, tf, sf, size, patch_sha in patch_list:
+ # MIUI ADD:
+ # skip to check /data patch
+ if fn.startswith("data/"):
+ continue
+ script.PatchCheck("/"+fn, tf.sha1, sf.sha1)
+ so_far += sf.size
+ script.SetProgress(so_far / total_verify_size)
if updating_boot:
d = common.Difference(target_boot, source_boot)
@@ -1354,215 +605,127 @@ else if get_stage("%(bcb_dev)s") != "3/3" then
common.ZipWriteStr(output_zip, "patch/boot.img.p", d)
- boot_type, boot_device = common.GetTypeAndDevice(
- "/boot", OPTIONS.source_info_dict)
+ boot_type, boot_device = common.GetTypeAndDevice("/boot", OPTIONS.info_dict)
script.PatchCheck("%s:%s:%d:%s:%d:%s" %
(boot_type, boot_device,
source_boot.size, source_boot.sha1,
target_boot.size, target_boot.sha1))
so_far += source_boot.size
+ script.SetProgress(so_far / total_verify_size)
- size = []
- if system_diff.patch_list:
- size.append(system_diff.largest_source_size)
- if vendor_diff:
- if vendor_diff.patch_list:
- size.append(vendor_diff.largest_source_size)
- # MIUI ADD
- if cust_diff:
- if cust_diff.patch_list:
- size.append(cust_diff.largest_source_size)
-
- if size or updating_recovery or updating_boot:
- script.CacheFreeSpaceCheck(max(size))
+ if patch_list or updating_recovery or updating_boot:
+ script.CacheFreeSpaceCheck(largest_source_size)
device_specific.IncrementalOTA_VerifyEnd()
- if OPTIONS.two_step:
- script.WriteRawImage("/boot", "recovery.img")
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "2/3");
-reboot_now("%(bcb_dev)s", "");
-else
-""" % bcb_dev)
-
script.Comment("---- start making changes here ----")
- device_specific.IncrementalOTA_InstallBegin()
-
- if OPTIONS.two_step:
- common.ZipWriteStr(output_zip, "boot.img", target_boot.data)
- script.WriteRawImage("/boot", "boot.img")
- print "writing full boot image (forced by two-step mode)"
+ if OPTIONS.wipe_user_data:
+ script.Print("Erasing user data...")
+ script.FormatPartition("/data")
script.Print("Removing unneeded files...")
- system_diff.RemoveUnneededFiles(script, ("/system/recovery.img",))
- if vendor_diff:
- vendor_diff.RemoveUnneededFiles(script)
- # MIUI ADD
- if cust_diff:
- cust_diff.RemoveUnneededFiles(script)
+ script.DeleteFiles(["/"+i[0] for i in verbatim_targets] +
+ ["/"+i for i in sorted(source_data)
+ if i not in target_data] +
+ ["/system/recovery.img"])
script.ShowProgress(0.8, 0)
- total_patch_size = 1.0 + system_diff.TotalPatchSize()
- if vendor_diff:
- total_patch_size += vendor_diff.TotalPatchSize()
- # MIUI ADD
- if cust_diff:
- total_patch_size += cust_diff.TotalPatchSize()
-
+ total_patch_size = float(sum([i[1].size for i in patch_list]) + 1)
if updating_boot:
total_patch_size += target_boot.size
+ so_far = 0
script.Print("Patching system files...")
- so_far = system_diff.EmitPatches(script, total_patch_size, 0)
- if vendor_diff:
- script.Print("Patching vendor files...")
- so_far = vendor_diff.EmitPatches(script, total_patch_size, so_far)
- # MIUI ADD
- if cust_diff:
- script.Print("Patching cust files...")
- so_far = cust_diff.EmitPatches(script, total_patch_size, so_far)
-
-
- if not OPTIONS.two_step:
- if updating_boot:
- # Produce the boot image by applying a patch to the current
- # contents of the boot partition, and write it back to the
- # partition.
- script.Print("Patching boot image...")
- script.ApplyPatch("%s:%s:%d:%s:%d:%s"
- % (boot_type, boot_device,
- source_boot.size, source_boot.sha1,
- target_boot.size, target_boot.sha1),
- "-",
- target_boot.size, target_boot.sha1,
- source_boot.sha1, "patch/boot.img.p")
- so_far += target_boot.size
- script.SetProgress(so_far / total_patch_size)
- print "boot image changed; including."
- else:
- print "boot image unchanged; skipping."
+ deferred_patch_list = []
+ for item in patch_list:
+ fn, tf, sf, size, _ = item
+ if tf.name == "system/build.prop":
+ deferred_patch_list.append(item)
+ continue
+ script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1, sf.sha1, "patch/"+fn+".p")
+ so_far += tf.size
+ script.SetProgress(so_far / total_patch_size)
- system_items = ItemSet("system", "META/filesystem_config.txt")
- if vendor_diff:
- vendor_items = ItemSet("vendor", "META/vendor_filesystem_config.txt")
- # MIUI ADD
- if cust_diff:
- cust_items = ItemSet("cust", "META/cust_filesystem_config.txt")
+ if updating_boot:
+ # Produce the boot image by applying a patch to the current
+ # contents of the boot partition, and write it back to the
+ # partition.
+ script.Print("Patching boot image...")
+ script.ApplyPatch("%s:%s:%d:%s:%d:%s"
+ % (boot_type, boot_device,
+ source_boot.size, source_boot.sha1,
+ target_boot.size, target_boot.sha1),
+ "-",
+ target_boot.size, target_boot.sha1,
+ source_boot.sha1, "patch/boot.img.p")
+ so_far += target_boot.size
+ script.SetProgress(so_far / total_patch_size)
+ print "boot image changed; including."
+ else:
+ print "boot image unchanged; skipping."
+
+ if need_install_boot:
+ boot_img = common.GetBootableImage("boot.img", "boot.img",
+ OPTIONS.input_tmp, "BOOT")
+ script.Print("Update Boot image...")
+ if boot_img:
+ common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict)
+ common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
+ if boot_img and not device_specific.WriteRawImage("/boot", "boot.img"):
+ script.WriteRawImage("/boot", "boot.img")
if updating_recovery:
- # Recovery is generated as a patch using both the boot image
- # (which contains the same linux kernel as recovery) and the file
- # /system/etc/recovery-resource.dat (which contains all the images
- # used in the recovery UI) as sources. This lets us minimize the
- # size of the patch, which must be included in every OTA package.
+ # Is it better to generate recovery as a patch from the current
+ # boot image, or from the previous recovery image? For large
+ # updates with significant kernel changes, probably the former.
+ # For small updates where the kernel hasn't changed, almost
+ # certainly the latter. We pick the first option. Future
+ # complicated schemes may let us effectively use both.
#
- # For older builds where recovery-resource.dat is not present, we
- # use only the boot image as the source.
-
- if not target_has_recovery_patch:
- def output_sink(fn, data):
- common.ZipWriteStr(output_zip, "recovery/" + fn, data)
- system_items.Get("system/" + fn)
-
- common.MakeRecoveryPatch(OPTIONS.target_tmp, output_sink,
- target_recovery, target_boot)
- script.DeleteFiles(["/system/recovery-from-boot.p",
- "/system/etc/install-recovery.sh"])
+ # A wacky possibility: as long as there is room in the boot
+ # partition, include the binaries and image files from recovery in
+ # the boot image (though not in the ramdisk) so they can be used
+ # as fodder for constructing the recovery image.
+ MakeRecoveryPatch(output_zip, target_recovery, target_boot)
+ script.DeleteFiles(["/system/recovery-from-boot.p",
+ "/system/etc/install-recovery.sh"])
print "recovery image changed; including as patch from boot."
else:
print "recovery image unchanged; skipping."
script.ShowProgress(0.1, 10)
- target_symlinks = CopyPartitionFiles(system_items, target_zip, None)
- if vendor_diff:
- target_symlinks.extend(CopyPartitionFiles(vendor_items, target_zip, None))
- # MIUI ADD
- if cust_diff:
- target_symlinks.extend(CopyPartitionFiles(cust_items, target_zip, None))
+ (target_symlinks, target_retouch_dummies) = CopySystemFiles(target_zip, None)
+ target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks])
temp_script = script.MakeTemporary()
- system_items.GetMetadata(target_zip)
- system_items.Get("system").SetPermissions(temp_script)
- if vendor_diff:
- vendor_items.GetMetadata(target_zip)
- vendor_items.Get("vendor").SetPermissions(temp_script)
- # MIUI ADD
- if cust_diff:
- cust_items.GetMetadata(target_zip)
- cust_items.Get("cust").SetPermissions(temp_script)
-
- # Note that this call will mess up the trees of Items, so make sure
- # we're done with them.
- source_symlinks = CopyPartitionFiles(system_items, source_zip, None)
- if vendor_diff:
- source_symlinks.extend(CopyPartitionFiles(vendor_items, source_zip, None))
- # MIUI ADD
- if cust_diff:
- source_symlinks.extend(CopyPartitionFiles(cust_items, source_zip, None))
+ Item.GetMetadata(target_zip)
+ Item.Get("system").SetPermissions(temp_script)
- target_symlinks_d = dict([(i[1], i[0]) for i in target_symlinks])
+ # Note that this call will mess up the tree of Items, so make sure
+ # we're done with it.
+ (source_symlinks, source_retouch_dummies) = CopySystemFiles(source_zip, None)
source_symlinks_d = dict([(i[1], i[0]) for i in source_symlinks])
# Delete all the symlinks in source that aren't in target. This
# needs to happen before verbatim files are unpacked, in case a
# symlink in the source is replaced by a real file in the target.
-
- # If a symlink in the source will be replaced by a regular file, we cannot
- # delete the symlink/file in case the package gets applied again. For such
- # a symlink, we prepend a sha1_check() to detect if it has been updated.
- # (Bug: 23646151)
- replaced_symlinks = dict()
- if system_diff:
- for i in system_diff.verbatim_targets:
- replaced_symlinks["/%s" % (i[0],)] = i[2]
- if vendor_diff:
- for i in vendor_diff.verbatim_targets:
- replaced_symlinks["/%s" % (i[0],)] = i[2]
-
- if system_diff:
- for tf in system_diff.renames.values():
- replaced_symlinks["/%s" % (tf.name,)] = tf.sha1
- if vendor_diff:
- for tf in vendor_diff.renames.values():
- replaced_symlinks["/%s" % (tf.name,)] = tf.sha1
-
- always_delete = []
- may_delete = []
+ to_delete = []
for dest, link in source_symlinks:
if link not in target_symlinks_d:
- if link in replaced_symlinks:
- may_delete.append((link, replaced_symlinks[link]))
- else:
- always_delete.append(link)
- script.DeleteFiles(always_delete)
- script.DeleteFilesIfNotMatching(may_delete)
+ to_delete.append(link)
+ script.DeleteFiles(to_delete)
- if system_diff.verbatim_targets:
- script.Print("Unpacking new system files...")
+ if verbatim_targets:
+ script.Print("Unpacking new files...")
script.UnpackPackageDir("system", "/system")
- if vendor_diff and vendor_diff.verbatim_targets:
- script.Print("Unpacking new vendor files...")
- script.UnpackPackageDir("vendor", "/vendor")
- # MIUI ADD
- if cust_diff and cust_diff.verbatim_targets:
- script.Print("Unpacking new cust files...")
- script.UnpackPackageDir("cust", "/cust")
-
- if updating_recovery and not target_has_recovery_patch:
+
+ if updating_recovery:
script.Print("Unpacking new recovery...")
script.UnpackPackageDir("recovery", "/system")
- system_diff.EmitRenames(script)
- if vendor_diff:
- vendor_diff.EmitRenames(script)
- # MIUI ADD
- if cust_diff:
- cust_diff.EmitRenames(script)
-
script.Print("Symlinks and permissions...")
# Create all the symlinks that don't already exist, or point to
@@ -1577,13 +740,16 @@ else
to_create.append((dest, link))
script.DeleteFiles([i[1] for i in to_create])
script.MakeSymlinks(to_create)
+ # if OPTIONS.aslr_mode:
+ # script.RetouchBinaries(target_retouch_files)
+ # else:
+ # script.UndoRetouchBinaries(target_retouch_files)
# Now that the symlinks are created, we can set all the
# permissions.
script.AppendScript(temp_script)
# Do device-specific installation (eg, write radio image).
- device_specific.IncrementalOTA_InstallEnd()
if OPTIONS.extra_script is not None:
script.AppendExtra(OPTIONS.extra_script)
@@ -1592,52 +758,31 @@ else
# device can still come up, it appears to be the old build and will
# get set the OTA package again to retry.
script.Print("Patching remaining system files...")
- system_diff.EmitDeferredPatches(script)
-
- if OPTIONS.wipe_user_data:
- script.Print("Erasing user data...")
- script.FormatPartition("/data")
+ for item in deferred_patch_list:
+ fn, tf, sf, size, _ = item
+ script.ApplyPatch("/"+fn, "-", tf.size, tf.sha1, sf.sha1, "patch/"+fn+".p")
+
+ device_specific.IncrementalOTA_InstallEnd()
- if OPTIONS.two_step:
- script.AppendExtra("""
-set_stage("%(bcb_dev)s", "");
-endif;
-endif;
-""" % bcb_dev)
-
- if OPTIONS.verify and system_diff:
- script.Print("Remounting and verifying system partition files...")
- script.Unmount("/system")
- script.Mount("/system")
- system_diff.EmitExplicitTargetVerification(script)
-
- if OPTIONS.verify and vendor_diff:
- script.Print("Remounting and verifying vendor partition files...")
- script.Unmount("/vendor")
- script.Mount("/vendor")
- vendor_diff.EmitExplicitTargetVerification(script)
- script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary)
+ script.SetPermissions("/system/build.prop", 0, 0, 0644)
+ script.AddToZip(target_zip, output_zip)
WriteMetadata(metadata, output_zip)
def main(argv):
def option_handler(o, a):
- if o == "--board_config":
+ if o in ("-b", "--board_config"):
pass # deprecated
elif o in ("-k", "--package_key"):
OPTIONS.package_key = a
elif o in ("-i", "--incremental_from"):
OPTIONS.incremental_source = a
- elif o == "--full_radio":
- OPTIONS.full_radio = True
elif o in ("-w", "--wipe_user_data"):
OPTIONS.wipe_user_data = True
elif o in ("-n", "--no_prereq"):
OPTIONS.omit_prereq = True
- elif o in ("-o", "--oem_settings"):
- OPTIONS.oem_source = a
elif o in ("-e", "--extra_script"):
OPTIONS.extra_script = a
elif o in ("-a", "--aslr_mode"):
@@ -1645,48 +790,24 @@ def main(argv):
OPTIONS.aslr_mode = True
else:
OPTIONS.aslr_mode = False
- elif o in ("-t", "--worker_threads"):
- if a.isdigit():
- OPTIONS.worker_threads = int(a)
- else:
- raise ValueError("Cannot parse value %r for option %r - only "
- "integers are allowed." % (a, o))
- elif o in ("-2", "--two_step"):
- OPTIONS.two_step = True
- elif o == "--no_signing":
- OPTIONS.no_signing = True
- elif o == "--verify":
- OPTIONS.verify = True
- elif o == "--block":
- OPTIONS.block_based = True
- elif o in ("-b", "--binary"):
- OPTIONS.updater_binary = a
- elif o in ("--no_fallback_to_full",):
- OPTIONS.fallback_to_full = False
+ elif o in ("--worker_threads"):
+ OPTIONS.worker_threads = int(a)
else:
return False
return True
args = common.ParseOptions(argv, __doc__,
- extra_opts="b:k:i:d:wne:t:a:2o:",
- extra_long_opts=[
- "board_config=",
- "package_key=",
- "incremental_from=",
- "full_radio",
- "wipe_user_data",
- "no_prereq",
- "extra_script=",
- "worker_threads=",
- "aslr_mode=",
- "two_step",
- "no_signing",
- "block",
- "binary=",
- "oem_settings=",
- "verify",
- "no_fallback_to_full",
- ], extra_option_handler=option_handler)
+ extra_opts="b:k:i:d:wne:a:",
+ extra_long_opts=["board_config=",
+ "package_key=",
+ "incremental_from=",
+ "wipe_user_data",
+ "no_prereq",
+ "extra_script=",
+ "worker_threads=",
+ "aslr_mode=",
+ ],
+ extra_option_handler=option_handler)
if len(args) != 2:
common.Usage(__doc__)
@@ -1700,88 +821,46 @@ def main(argv):
OPTIONS.target_tmp = OPTIONS.input_tmp
OPTIONS.info_dict = common.LoadInfoDict(input_zip)
-
- # If this image was originally labelled with SELinux contexts, make sure we
- # also apply the labels in our new image. During building, the "file_contexts"
- # is in the out/ directory tree, but for repacking from target-files.zip it's
- # in the root directory of the ramdisk.
- if "selinux_fc" in OPTIONS.info_dict:
- OPTIONS.info_dict["selinux_fc"] = os.path.join(
- OPTIONS.input_tmp, "BOOT", "RAMDISK", "file_contexts")
-
if OPTIONS.verbose:
print "--- target info ---"
common.DumpInfoDict(OPTIONS.info_dict)
- # If the caller explicitly specified the device-specific extensions
- # path via -s/--device_specific, use that. Otherwise, use
- # META/releasetools.py if it is present in the target target_files.
- # Otherwise, take the path of the file from 'tool_extensions' in the
- # info dict and look for that in the local filesystem, relative to
- # the current directory.
-
if OPTIONS.device_specific is None:
- from_input = os.path.join(OPTIONS.input_tmp, "META", "releasetools.py")
- if os.path.exists(from_input):
- print "(using device-specific extensions from target_files)"
- OPTIONS.device_specific = from_input
- else:
- OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None)
-
+ OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None)
if OPTIONS.device_specific is not None:
- OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific)
-
- while True:
-
- if OPTIONS.no_signing:
- if os.path.exists(args[1]):
- os.unlink(args[1])
- output_zip = zipfile.ZipFile(args[1], "w",
- compression=zipfile.ZIP_DEFLATED)
- else:
- temp_zip_file = tempfile.NamedTemporaryFile()
- output_zip = zipfile.ZipFile(temp_zip_file, "w",
- compression=zipfile.ZIP_DEFLATED)
-
- if OPTIONS.incremental_source is None:
- WriteFullOTAPackage(input_zip, output_zip)
- if OPTIONS.package_key is None:
- OPTIONS.package_key = OPTIONS.info_dict.get(
- "default_system_dev_certificate",
- "build/target/product/security/testkey")
- common.ZipClose(output_zip)
- break
-
- else:
- print "unzipping source target-files..."
- OPTIONS.source_tmp, source_zip = common.UnzipTemp(
- OPTIONS.incremental_source)
- OPTIONS.target_info_dict = OPTIONS.info_dict
- OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
- if "selinux_fc" in OPTIONS.source_info_dict:
- OPTIONS.source_info_dict["selinux_fc"] = os.path.join(
- OPTIONS.source_tmp, "BOOT", "RAMDISK", "file_contexts")
- if OPTIONS.package_key is None:
- OPTIONS.package_key = OPTIONS.source_info_dict.get(
- "default_system_dev_certificate",
- "build/target/product/security/testkey")
- if OPTIONS.verbose:
- print "--- source info ---"
- common.DumpInfoDict(OPTIONS.source_info_dict)
- try:
- WriteIncrementalOTAPackage(input_zip, source_zip, output_zip)
- common.ZipClose(output_zip)
- break
- except ValueError:
- if not OPTIONS.fallback_to_full:
- raise
- print "--- failed to build incremental; falling back to full ---"
- OPTIONS.incremental_source = None
- common.ZipClose(output_zip)
-
- if not OPTIONS.no_signing:
- SignOutput(temp_zip_file.name, args[1])
- temp_zip_file.close()
+ OPTIONS.device_specific = os.path.normpath(OPTIONS.device_specific)
+ print "using device-specific extensions in", OPTIONS.device_specific
+
+ temp_zip_file = tempfile.NamedTemporaryFile()
+ output_zip = zipfile.ZipFile(temp_zip_file, "w",
+ compression=zipfile.ZIP_DEFLATED)
+
+ if OPTIONS.incremental_source is None:
+ WriteFullOTAPackage(input_zip, output_zip)
+ if OPTIONS.package_key is None:
+ OPTIONS.package_key = OPTIONS.info_dict.get(
+ "default_system_dev_certificate",
+ "build/target/product/security/testkey")
+ else:
+ print "unzipping source target-files..."
+ OPTIONS.source_tmp, source_zip = common.UnzipTemp(OPTIONS.incremental_source)
+ OPTIONS.target_info_dict = OPTIONS.info_dict
+ OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
+ if OPTIONS.package_key is None:
+ OPTIONS.package_key = OPTIONS.source_info_dict.get(
+ "default_system_dev_certificate",
+ "build/target/product/security/testkey")
+ if OPTIONS.verbose:
+ print "--- source info ---"
+ common.DumpInfoDict(OPTIONS.source_info_dict)
+ WriteIncrementalOTAPackage(input_zip, source_zip, output_zip)
+
+ output_zip.close()
+
+ SignOutput(temp_zip_file.name, args[1])
+ temp_zip_file.close()
+
+ common.Cleanup()
print "done."
@@ -1790,10 +869,8 @@ if __name__ == '__main__':
try:
common.CloseInheritedPipes()
main(sys.argv[1:])
- except common.ExternalError as e:
+ except common.ExternalError, e:
print
print " ERROR: %s" % (e,)
print
sys.exit(1)
- finally:
- common.Cleanup()
diff --git a/releasetools/ota_target_from_phone b/releasetools/ota_target_from_phone
index 218d02d..677b5d7 100755
--- a/releasetools/ota_target_from_phone
+++ b/releasetools/ota_target_from_phone
@@ -170,46 +170,28 @@ function build_apkcerts {
# build filesystem_config.txt from device
function build_filesystem_config {
echo "Run getfilesysteminfo to build filesystem_config.txt"
- if [ $ANDROID_PLATFORM -gt 19 ];then
- adb push $TOOL_DIR/target_files_template/OTA/bin/busybox /data/local/tmp/
- adb shell chmod 755 /data/local/tmp/busybox
- bash $TOOL_DIR/get_filesystem_config --info /data/local/tmp/busybox | tee $META_DIR/filesystem_config.txt
- if [ $? -ne 0 ];then
- echo "Get file info failed"
- exit 1
- fi
- else
- adb push $TOOL_DIR/releasetools/getfilesysteminfo /system/xbin
- adb shell chmod 0777 /system/xbin/getfilesysteminfo
- adb shell /system/xbin/getfilesysteminfo --info /system >> $META_DIR/filesystem_config.txt
- fs_config=`cat $META_DIR/filesystem_config.txt | col -b | sed -e '/getfilesysteminfo/d'`
- OLD_IFS=$IFS
- IFS=$'\n'
- for line in $fs_config
- do
- echo $line | grep -q -e "\" && continue
- echo $line | grep -q -e "\" && continue
- echo $line >> $META_DIR/tmp.txt
- done
- IFS=$OLD_IFS
- cat $META_DIR/tmp.txt | sort > $META_DIR/filesystem_config.txt
- rm $META_DIR/tmp.txt
- fi
+
+ adb push $TOOL_DIR/releasetools/getfilesysteminfo /system/xbin
+ adb shell chmod 0777 /system/xbin/getfilesysteminfo
+ adb shell /system/xbin/getfilesysteminfo --info /system >> $META_DIR/filesystem_config.txt
+ fs_config=`cat $META_DIR/filesystem_config.txt | col -b | sed -e '/getfilesysteminfo/d'`
+ OLD_IFS=$IFS
+ IFS=$'\n'
+ for line in $fs_config
+ do
+ echo $line | grep -q -e "\" && continue
+ echo $line | grep -q -e "\" && continue
+ echo $line >> $META_DIR/tmp.txt
+ done
+ IFS=$OLD_IFS
+ cat $META_DIR/tmp.txt | sort > $META_DIR/filesystem_config.txt
+ rm $META_DIR/tmp.txt
}
# recover the device files' symlink information
function recover_symlink {
echo "Run getfilesysteminfo and recoverylink.py to recover symlink"
- if [ $ANDROID_PLATFORM -gt 19 ];then
- bash $TOOL_DIR/get_filesystem_config --link /data/local/tmp/busybox | tee $SYSTEM_DIR/linkinfo.txt
- if [ $? -ne 0 ];then
- echo "Get file symlink failed"
- exit 1
- fi
- else
- adb shell /system/xbin/getfilesysteminfo --link /system | sed -e '/\/d;/\/d' | sort > $SYSTEM_DIR/linkinfo.txt
- adb shell rm /system/xbin/getfilesysteminfo
- fi
+ adb shell /system/xbin/getfilesysteminfo --link /system | sed -e '/\/d;/\/d' | sort > $SYSTEM_DIR/linkinfo.txt
python $TOOL_DIR/releasetools/recoverylink.py $TARGET_FILES_DIR
adb shell rm /system/xbin/getfilesysteminfo
}
@@ -260,14 +242,6 @@ function build_SYSTEM {
recover_symlink
}
-function deoat {
- if [ $ANDROID_PLATFORM -le 19 ];then
- return
- fi
- echo "Decode oat files"
- $TOOL_DIR/deoat.sh $TARGET_FILES_DIR
-}
-
# compress the target_files dir into a zip file
function zip_target_files {
echo "Compress the target_files dir into zip file"
@@ -321,7 +295,6 @@ fi
build_SYSTEM
build_apkcerts
gen_metadata
-deoat
zip_target_files
build_ota_package
diff --git a/releasetools/pylintrc b/releasetools/pylintrc
deleted file mode 100644
index 90de1af..0000000
--- a/releasetools/pylintrc
+++ /dev/null
@@ -1,382 +0,0 @@
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-# Use multiple processes to speed up Pylint.
-jobs=1
-
-# Allow loading of arbitrary C extensions. Extensions are imported into the
-# active Python interpreter and may run arbitrary code.
-unsafe-load-any-extension=no
-
-# A comma-separated list of package or module names from where C extensions may
-# be loaded. Extensions are loading into the active Python interpreter and may
-# run arbitrary code
-extension-pkg-whitelist=
-
-# Allow optimization of some AST trees. This will activate a peephole AST
-# optimizer, which will apply various small optimizations. For instance, it can
-# be used to obtain the result of joining multiple strings with the addition
-# operator. Joining a lot of strings can lead to a maximum recursion error in
-# Pylint and this flag can prevent that. It has one side effect, the resulting
-# AST will be different than the one from reality.
-optimize-ast=no
-
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
-confidence=
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time. See also the "--disable" option for examples.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-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
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of module names for which member attributes should not be checked
-# (useful for modules/projects where namespaces are manipulated during runtime
-# and thus existing member attributes cannot be deduced by static analysis
-ignored-modules=
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=SQLObject
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=REQUEST,acl_users,aq_parent
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[BASIC]
-
-# Required attributes for module, separated by a comma
-required-attributes=
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,input
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Colon-delimited sets of names that determine each other's naming style when
-# the name regexes allow several styles.
-name-group=
-
-# Include a hint for the correct naming format with invalid-name
-include-naming-hint=no
-
-# Regular expression matching correct function names
-function-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for function names
-function-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for variable names
-variable-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct constant names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Naming hint for constant names
-const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression matching correct attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for attribute names
-attr-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for argument names
-argument-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression matching correct class attribute names
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
-
-# Naming hint for class attribute names
-class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
-
-# Regular expression matching correct inline iteration names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Naming hint for inline iteration names
-inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
-
-# Regular expression matching correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Naming hint for class names
-class-name-hint=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression matching correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Naming hint for module names
-module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression matching correct method names
-method-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Naming hint for method names
-method-name-hint=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=__.*__
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=-1
-
-
-[SPELLING]
-
-# Spelling dictionary name. Available dictionaries: none. To make it working
-# install python-enchant package.
-spelling-dict=
-
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-
-# A path to a file that contains private dictionary; one word per line.
-spelling-private-dict-file=
-
-# Tells whether to store unknown words to indicated private dictionary in
-# --spelling-private-dict-file option instead of raising a message.
-spelling-store-unknown-words=no
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=80
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )??$
-
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=no
-
-# List of optional constructs for which whitespace checking is disabled
-no-space-check=trailing-comma,dict-separator
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string=' '
-
-# Number of spaces of indent required inside a hanging or continued line.
-indent-after-paren=4
-
-# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
-expected-line-ending-format=LF
-
-
-[LOGGING]
-
-# Logging modules to check that the string format arguments are in logging
-# function parameter format
-logging-modules=logging
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the name of dummy variables (i.e. expectedly
-# not used).
-dummy-variables-rgx=_$|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=cb_,_cb
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=5
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branches=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
-
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,_fields,_replace,_source,_make
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
diff --git a/releasetools/rangelib.py b/releasetools/rangelib.py
deleted file mode 100644
index 1506658..0000000
--- a/releasetools/rangelib.py
+++ /dev/null
@@ -1,266 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from __future__ import print_function
-import heapq
-import itertools
-
-__all__ = ["RangeSet"]
-
-class RangeSet(object):
- """A RangeSet represents a set of nonoverlapping ranges on the
- integers (ie, a set of integers, but efficient when the set contains
- lots of runs."""
-
- def __init__(self, data=None):
- self.monotonic = False
- if isinstance(data, str):
- self._parse_internal(data)
- elif data:
- self.data = tuple(self._remove_pairs(data))
- else:
- self.data = ()
-
- def __iter__(self):
- for i in range(0, len(self.data), 2):
- yield self.data[i:i+2]
-
- def __eq__(self, other):
- return self.data == other.data
- def __ne__(self, other):
- return self.data != other.data
- def __nonzero__(self):
- return bool(self.data)
-
- def __str__(self):
- if not self.data:
- return "empty"
- else:
- return self.to_string()
-
- def __repr__(self):
- return ''
-
- @classmethod
- def parse(cls, text):
- """Parse a text string consisting of a space-separated list of
- blocks and ranges, eg "10-20 30 35-40". Ranges are interpreted to
- include both their ends (so the above example represents 18
- individual blocks. Returns a RangeSet object.
-
- If the input has all its blocks in increasing order, then returned
- RangeSet will have an extra attribute 'monotonic' that is set to
- True. For example the input "10-20 30" is monotonic, but the input
- "15-20 30 10-14" is not, even though they represent the same set
- of blocks (and the two RangeSets will compare equal with ==).
- """
- return cls(text)
-
- def _parse_internal(self, text):
- data = []
- last = -1
- monotonic = True
- for p in text.split():
- if "-" in p:
- s, e = p.split("-")
- data.append(int(s))
- data.append(int(e)+1)
- if last <= s <= e:
- last = e
- else:
- monotonic = False
- else:
- s = int(p)
- data.append(s)
- data.append(s+1)
- if last <= s:
- last = s+1
- else:
- monotonic = True
- data.sort()
- self.data = tuple(self._remove_pairs(data))
- self.monotonic = monotonic
-
- @staticmethod
- def _remove_pairs(source):
- last = None
- for i in source:
- if i == last:
- last = None
- else:
- if last is not None:
- yield last
- last = i
- if last is not None:
- yield last
-
- def to_string(self):
- out = []
- for i in range(0, len(self.data), 2):
- s, e = self.data[i:i+2]
- if e == s+1:
- out.append(str(s))
- else:
- out.append(str(s) + "-" + str(e-1))
- return " ".join(out)
-
- def to_string_raw(self):
- return str(len(self.data)) + "," + ",".join(str(i) for i in self.data)
-
- def union(self, other):
- """Return a new RangeSet representing the union of this RangeSet
- with the argument.
-
- >>> RangeSet("10-19 30-34").union(RangeSet("18-29"))
-
- >>> RangeSet("10-19 30-34").union(RangeSet("22 32"))
-
- """
- out = []
- z = 0
- for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))),
- zip(other.data, itertools.cycle((+1, -1)))):
- if (z == 0 and d == 1) or (z == 1 and d == -1):
- out.append(p)
- z += d
- return RangeSet(data=out)
-
- def intersect(self, other):
- """Return a new RangeSet representing the intersection of this
- RangeSet with the argument.
-
- >>> RangeSet("10-19 30-34").intersect(RangeSet("18-32"))
-
- >>> RangeSet("10-19 30-34").intersect(RangeSet("22-28"))
-
- """
- out = []
- z = 0
- for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))),
- zip(other.data, itertools.cycle((+1, -1)))):
- if (z == 1 and d == 1) or (z == 2 and d == -1):
- out.append(p)
- z += d
- return RangeSet(data=out)
-
- def subtract(self, other):
- """Return a new RangeSet representing subtracting the argument
- from this RangeSet.
-
- >>> RangeSet("10-19 30-34").subtract(RangeSet("18-32"))
-
- >>> RangeSet("10-19 30-34").subtract(RangeSet("22-28"))
-
- """
-
- out = []
- z = 0
- for p, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))),
- zip(other.data, itertools.cycle((-1, +1)))):
- if (z == 0 and d == 1) or (z == 1 and d == -1):
- out.append(p)
- z += d
- return RangeSet(data=out)
-
- def overlaps(self, other):
- """Returns true if the argument has a nonempty overlap with this
- RangeSet.
-
- >>> RangeSet("10-19 30-34").overlaps(RangeSet("18-32"))
- True
- >>> RangeSet("10-19 30-34").overlaps(RangeSet("22-28"))
- False
- """
-
- # This is like intersect, but we can stop as soon as we discover the
- # output is going to be nonempty.
- z = 0
- for _, d in heapq.merge(zip(self.data, itertools.cycle((+1, -1))),
- zip(other.data, itertools.cycle((+1, -1)))):
- if (z == 1 and d == 1) or (z == 2 and d == -1):
- return True
- z += d
- return False
-
- def size(self):
- """Returns the total size of the RangeSet (ie, how many integers
- are in the set).
-
- >>> RangeSet("10-19 30-34").size()
- 15
- """
-
- total = 0
- for i, p in enumerate(self.data):
- if i % 2:
- total += p
- else:
- total -= p
- return total
-
- def map_within(self, other):
- """'other' should be a subset of 'self'. Returns a RangeSet
- representing what 'other' would get translated to if the integers
- of 'self' were translated down to be contiguous starting at zero.
-
- >>> RangeSet("0-9").map_within(RangeSet("3-4"))
-
- >>> RangeSet("10-19").map_within(RangeSet("13-14"))
-
- >>> RangeSet("10-19 30-39").map_within(RangeSet("17-19 30-32"))
-
- >>> RangeSet("10-19 30-39").map_within(RangeSet("12-13 17-19 30-32"))
-
- """
-
- out = []
- offset = 0
- start = None
- for p, d in heapq.merge(zip(self.data, itertools.cycle((-5, +5))),
- zip(other.data, itertools.cycle((-1, +1)))):
- if d == -5:
- start = p
- elif d == +5:
- offset += p-start
- start = None
- else:
- out.append(offset + p - start)
- return RangeSet(data=out)
-
- def extend(self, n):
- """Extend the RangeSet by 'n' blocks.
-
- The lower bound is guaranteed to be non-negative.
-
- >>> RangeSet("0-9").extend(1)
-
- >>> RangeSet("10-19").extend(15)
-
- >>> RangeSet("10-19 30-39").extend(4)
-
- >>> RangeSet("10-19 30-39").extend(10)
-
- """
- out = self
- for i in range(0, len(self.data), 2):
- s, e = self.data[i:i+2]
- s1 = max(0, s - n)
- e1 = e + n
- out = out.union(RangeSet(str(s1) + "-" + str(e1-1)))
- return out
-
-
-if __name__ == "__main__":
- import doctest
- doctest.testmod()
diff --git a/releasetools/recoverylink.py b/releasetools/recoverylink.py
index 5f9fe9d..e53b078 100644
--- a/releasetools/recoverylink.py
+++ b/releasetools/recoverylink.py
@@ -13,10 +13,12 @@
line = line.rstrip()
filepath = line.split('|')
link_name = filepath[0].replace('system', 'SYSTEM')
- target = filepath[1]
- cmd = 'cd ' + path + ';' + 'mkdir -p ' + os.path.dirname(link_name) + ';' + 'ln -sf ' + target + ' ' + link_name + ';'
- print cmd
- os.popen(cmd)
+ target = '/' + filepath[1]
+ rm = 'rm -f ' + path+ '/' + link_name
+ os.popen(rm)
+ ln = 'cd ' + path + ';' + 'ln -s ' + target + ' ' + link_name
+ #print ln
+ os.popen(ln)
except IOError:
print r"%s isn't exist" % linkfile_path
sys.exit(1)
diff --git a/releasetools/sign_target_files_apks b/releasetools/sign_target_files_apks
index ab97b13..fc71b51 100755
--- a/releasetools/sign_target_files_apks
+++ b/releasetools/sign_target_files_apks
@@ -183,7 +183,7 @@ def RewriteProps(data):
for line in data.split("\n"):
line = line.strip()
original_line = line
- if line and line[0] != '#' and "=" in line:
+ if line and line[0] != '#':
key, value = line.split("=", 1)
if key == "ro.build.fingerprint":
pieces = value.split("/")
diff --git a/releasetools/sparse_img.py b/releasetools/sparse_img.py
deleted file mode 100644
index 07f3c1c..0000000
--- a/releasetools/sparse_img.py
+++ /dev/null
@@ -1,247 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import bisect
-import os
-import struct
-from hashlib import sha1
-
-import rangelib
-
-
-class SparseImage(object):
- """Wraps a sparse image file into an image object.
-
- Wraps a sparse image file (and optional file map and clobbered_blocks) into
- an image object suitable for passing to BlockImageDiff. file_map contains
- the mapping between files and their blocks. clobbered_blocks contains the set
- of blocks that should be always written to the target regardless of the old
- contents (i.e. copying instead of patching). clobbered_blocks should be in
- the form of a string like "0" or "0 1-5 8".
- """
-
- def __init__(self, simg_fn, file_map_fn=None, clobbered_blocks=None):
- self.simg_f = f = open(simg_fn, "rb")
-
- header_bin = f.read(28)
- header = struct.unpack("> 2))
- to_read -= this_read
-
- while to_read > 0:
- # continue with following chunks if this range spans multiple chunks.
- idx += 1
- chunk_start, chunk_len, filepos, fill_data = self.offset_map[idx]
- this_read = min(chunk_len, to_read)
- if filepos is not None:
- f.seek(filepos, os.SEEK_SET)
- yield f.read(this_read * self.blocksize)
- else:
- yield fill_data * (this_read * (self.blocksize >> 2))
- to_read -= this_read
-
- def LoadFileBlockMap(self, fn, clobbered_blocks):
- remaining = self.care_map
- self.file_map = out = {}
-
- with open(fn) as f:
- for line in f:
- fn, ranges = line.split(None, 1)
- ranges = rangelib.RangeSet.parse(ranges)
- out[fn] = ranges
- assert ranges.size() == ranges.intersect(remaining).size()
-
- # Currently we assume that blocks in clobbered_blocks are not part of
- # any file.
- assert not clobbered_blocks.overlaps(ranges)
- remaining = remaining.subtract(ranges)
-
- remaining = remaining.subtract(clobbered_blocks)
-
- # For all the remaining blocks in the care_map (ie, those that
- # aren't part of the data for any file nor part of the clobbered_blocks),
- # divide them into blocks that are all zero and blocks that aren't.
- # (Zero blocks are handled specially because (1) there are usually
- # a lot of them and (2) bsdiff handles files with long sequences of
- # repeated bytes especially poorly.)
-
- zero_blocks = []
- nonzero_blocks = []
- reference = '\0' * self.blocksize
-
- f = self.simg_f
- for s, e in remaining:
- for b in range(s, e):
- idx = bisect.bisect_right(self.offset_index, b) - 1
- chunk_start, _, filepos, fill_data = self.offset_map[idx]
- if filepos is not None:
- filepos += (b-chunk_start) * self.blocksize
- f.seek(filepos, os.SEEK_SET)
- data = f.read(self.blocksize)
- else:
- if fill_data == reference[:4]: # fill with all zeros
- data = reference
- else:
- data = None
-
- if data == reference:
- zero_blocks.append(b)
- zero_blocks.append(b+1)
- else:
- nonzero_blocks.append(b)
- nonzero_blocks.append(b+1)
-
- assert zero_blocks or nonzero_blocks or clobbered_blocks
-
- if zero_blocks:
- out["__ZERO"] = rangelib.RangeSet(data=zero_blocks)
- if nonzero_blocks:
- out["__NONZERO"] = rangelib.RangeSet(data=nonzero_blocks)
- if clobbered_blocks:
- out["__COPY"] = clobbered_blocks
-
- def ResetFileMap(self):
- """Throw away the file map and treat the entire image as
- undifferentiated data."""
- self.file_map = {"__DATA": self.care_map}
diff --git a/replace_package_name.sh b/replace_package_name.sh
index 20a68a7..511aefc 100755
--- a/replace_package_name.sh
+++ b/replace_package_name.sh
@@ -13,7 +13,7 @@ des="$3"
cd $path
#replace xml
-for f in $(find . -name "*.xml")
+for f in $(find -name "*.xml")
do
echo $f
sed "s/$src/$des/g" $f > tmp
@@ -23,7 +23,7 @@ done
#replace smali
src2=$(echo $src | sed "s#\.#\\\/#g")
des2=$(echo $des | sed "s#\.#\\\/#g")
-for f in $(find . -name "*.smali")
+for f in $(find -name "*.smali")
do
echo $f
sed "s/$src2/$des2/g" $f > tmp
diff --git a/resolve_patch.sh b/resolve_patch.sh
deleted file mode 100644
index ff7bd66..0000000
--- a/resolve_patch.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-
-rm -r tmp
-rm -r tmp2
-mkdir tmp
-mkdir tmp2
-
-for f in `grep -rn "access" $1 | cut -d: -f1 | uniq | sort`
-do
- sed -i "s/access\$.*.(/access\$9999(/g" $f
-done
-
-for f in `grep -rn "access" $2 | cut -d: -f1 | uniq | sort`
-do
- sed -i "s/access\$.*.(/access\$9999(/g" $f
-done
-
-for ori in `find $1 -name *.smali`
-do
- filepath=`dirname $ori`
- filename=`basename $ori .smali`
- if [ -f ${ori/$1/$2} ];then
- diff -Naur $ori ${ori/$1/$2} > tmp/"$filename.patch"
- if [ $? -eq 0 ] ; then
- rm tmp/"$filename.patch"
- echo "Processing file:$filename.patch"
- else java -jar PatchResolver.jar ${ori/$1/$3} ${ori/$1/$4} tmp/"$filename.patch" > tmp2/"$filename.patch"
- fi
- fi
-done
-
-
-
-
diff --git a/set_build_prop.sh b/set_build_prop.sh
new file mode 100755
index 0000000..0fdc254
--- /dev/null
+++ b/set_build_prop.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+build_prop_file=$1
+# other arguments: # product=$2 # number=$3 # version=$4
+
+cat $build_prop_file | sed -e "s/ro\.build\.version\.incremental=.*/ro\.build\.version\.incremental=$3/" \
+ | sed -e "s/ro\.product\.mod_device=.*//" > $build_prop_file.new
+
+echo "ro.product.mod_device=$2" >> $build_prop_file.new
+echo "ro.skia.use_data_fonts=1" >> $build_prop_file.new
+mv $build_prop_file.new $build_prop_file
+
diff --git a/signapk.jar b/signapk.jar
index fbf121f..f6fe372 100644
Binary files a/signapk.jar and b/signapk.jar differ
diff --git a/smali b/smali
index 9ede675..e8bed94 100755
--- a/smali
+++ b/smali
@@ -14,12 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# As per the Apache license requirements, this file has been modified
-# from its original state.
-#
-# Such modifications are Copyright (C) 2010 Ben Gruver, and are released
-# under the original license
-
# This script is a wrapper for smali.jar, so you can simply call "smali",
# instead of java -jar smali.jar. It is heavily based on the "dx" script
# from the Android SDK
@@ -61,8 +55,8 @@ javaOpts=""
# If you want DX to have more memory when executing, uncomment the following
# line and adjust the value accordingly. Use "java -X" for a list of options
# you can pass here.
-#
-javaOpts="-Xmx512M"
+#
+javaOpts="-Xmx256M"
# Alternatively, this will extract any parameter "-Jxxx" from the command line
# and pass them to Java (instead of to dx). This makes it possible for you to
@@ -75,9 +69,9 @@ while expr "x$1" : 'x-J' >/dev/null; do
done
if [ "$OSTYPE" = "cygwin" ] ; then
- jarpath=`cygpath -w "$libdir/$jarfile"`
+ jarpath=`cygpath -w "$libdir/$jarfile"`
else
- jarpath="$libdir/$jarfile"
+ jarpath="$libdir/$jarfile"
fi
exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/smali.jar b/smali.jar
index 36df92e..920a567 100644
Binary files a/smali.jar and b/smali.jar differ
diff --git a/target_files_template/DATA/media/preset_apps/91xiongmaokanshu.apk b/target_files_template/DATA/media/preset_apps/91xiongmaokanshu.apk
new file mode 100644
index 0000000..01a3e10
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/91xiongmaokanshu.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/duokanyuedu.apk b/target_files_template/DATA/media/preset_apps/duokanyuedu.apk
new file mode 100644
index 0000000..84557e0
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/duokanyuedu.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/jinshandianchiyisheng.apk b/target_files_template/DATA/media/preset_apps/jinshandianchiyisheng.apk
new file mode 100644
index 0000000..b016621
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/jinshandianchiyisheng.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/jinshankuaipan.apk b/target_files_template/DATA/media/preset_apps/jinshankuaipan.apk
new file mode 100644
index 0000000..8461f4d
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/jinshankuaipan.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/jinshanshoujiweishi.apk b/target_files_template/DATA/media/preset_apps/jinshanshoujiweishi.apk
new file mode 100644
index 0000000..266dce1
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/jinshanshoujiweishi.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/kuaijiejiudianguanjia.apk b/target_files_template/DATA/media/preset_apps/kuaijiejiudianguanjia.apk
new file mode 100644
index 0000000..b96970b
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/kuaijiejiudianguanjia.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/kuwoyinyue.apk b/target_files_template/DATA/media/preset_apps/kuwoyinyue.apk
new file mode 100644
index 0000000..268dda0
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/kuwoyinyue.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/laohuditu.apk b/target_files_template/DATA/media/preset_apps/laohuditu.apk
new file mode 100644
index 0000000..1a14c49
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/laohuditu.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/meilishuo.apk b/target_files_template/DATA/media/preset_apps/meilishuo.apk
new file mode 100644
index 0000000..b34218c
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/meilishuo.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/miliao.apk b/target_files_template/DATA/media/preset_apps/miliao.apk
new file mode 100644
index 0000000..24c4b53
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/miliao.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/oupengliulanqi.apk b/target_files_template/DATA/media/preset_apps/oupengliulanqi.apk
new file mode 100644
index 0000000..04fe624
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/oupengliulanqi.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/souhuxinwen.apk b/target_files_template/DATA/media/preset_apps/souhuxinwen.apk
new file mode 100644
index 0000000..13c47f5
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/souhuxinwen.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/ucliulanqi.apk b/target_files_template/DATA/media/preset_apps/ucliulanqi.apk
new file mode 100644
index 0000000..5f97aeb
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/ucliulanqi.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/vancl.apk b/target_files_template/DATA/media/preset_apps/vancl.apk
new file mode 100644
index 0000000..11052cd
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/vancl.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/wangyixinwen.apk b/target_files_template/DATA/media/preset_apps/wangyixinwen.apk
new file mode 100644
index 0000000..7d9d83c
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/wangyixinwen.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/xiechengwuxian.apk b/target_files_template/DATA/media/preset_apps/xiechengwuxian.apk
new file mode 100644
index 0000000..7b91e22
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/xiechengwuxian.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/xinlangweibo.apk b/target_files_template/DATA/media/preset_apps/xinlangweibo.apk
new file mode 100644
index 0000000..66e80c4
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/xinlangweibo.apk differ
diff --git a/target_files_template/DATA/media/preset_apps/youjia.apk b/target_files_template/DATA/media/preset_apps/youjia.apk
new file mode 100644
index 0000000..36f539f
Binary files /dev/null and b/target_files_template/DATA/media/preset_apps/youjia.apk differ
diff --git a/target_files_template/META/apkcerts.txt b/target_files_template/META/apkcerts.txt
index e69de29..0131cfa 100644
--- a/target_files_template/META/apkcerts.txt
+++ b/target_files_template/META/apkcerts.txt
@@ -0,0 +1,437 @@
+name="CtsVerifier.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsTestStubs.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAccelerationTestStubs.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsDelegatingAccessibilityService.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ApiDemosReferenceTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAppAccessData.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey2.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey2.pk8"
+name="CtsAppWithData.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey1.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey1.pk8"
+name="CtsInstrumentationAppDiffCert.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey2.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey2.pk8"
+name="CtsPermissionDeclareApp.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey1.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey1.pk8"
+name="CtsSharedUidInstall.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey1.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey1.pk8"
+name="CtsSharedUidInstallDiffCert.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey2.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey2.pk8"
+name="CtsSimpleAppInstall.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey1.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey1.pk8"
+name="CtsSimpleAppInstallDiffCert.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey2.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey2.pk8"
+name="CtsTargetInstrumentationApp.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey1.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey1.pk8"
+name="CtsUsePermissionDiffCert.apk" certificate="cts/tests/appsecurity-tests/certs/cts-testkey2.x509.pem" private_key="cts/tests/appsecurity-tests/certs/cts-testkey2.pk8"
+name="android.core.tests.libcore.package.com.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.com.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.dalvik.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.dalvik.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.libcore.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.libcore.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.org.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.org.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.sun.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.sun.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.tests.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.libcore.package.tests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.runner.no-core-tests-res.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="android.core.tests.runner.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsDeviceAdmin.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ProcessTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NoShareUidApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ShareUidApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SignatureTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SignatureTestTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAccelerationTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAccessibilityServiceTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAccountManagerTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAdminTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsAppTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsBluetoothTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsContentTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsDatabaseTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsDpiTestCases2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsDpiTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsDrmTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsExampleTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsGestureTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsGraphicsTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsHardwareTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsHoloTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsJniTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsLocationTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsMediaTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsNdefTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsNetTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsOsTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsPermission2TestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsPermissionTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsPreferenceTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsProviderTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsRenderscriptTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsSaxTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsSecurityTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsSpeechTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsTelephonyTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsTextTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsUtilTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsViewTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsWebkitTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CtsWidgetTestCases.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TestDeviceSetup.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BluetoothDebug.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BuildWidget.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CustomLocale.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Development.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Fallback.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FontLab.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GestureBuilder.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NinePatchLab.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SdkSetup.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="WidgetPreview.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="launchperf.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AccelerometerPlay.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ActionBarCompat.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AliasActivity.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AndroidBeamDemo.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ApiDemos.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ApiDemosTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BackupRestore.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BasicGLSurfaceView.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BluetoothChat.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BluetoothHDP.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SampleBrowserPlugin.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BusinessCard.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Compass.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ContactManager.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CubeLiveWallpapers.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FixedGridLayout.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GlobalTime.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="HelloActivity.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="HelloActivityTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Home.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="HoneycombGallery.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="JETBoy.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="LunarLander.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="LunarLanderTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MultiResolution.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NFCDemo.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NotePad.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ObbApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RSSReader.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RandomMusicPlayer.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RsBalls.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RsFountain.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RsFountainFbo.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RsHelloCompute.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RsHelloWorld.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RsMiscSamples.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SampleSyncAdapter.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SearchableDictionary.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SimpleJNI.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SipDemo.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SkeletonApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SkeletonAppTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Snake.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SnakeTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SoftKeyboard.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="HelloSpellChecker.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SampleSpellChecker.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="StackWidget.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Support13Demos.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Support4Demos.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ToyVpn.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TtsEngine.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AdbTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MissileLauncher.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VoiceRecognitionService.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VoicemailProviderDemo.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="WeatherListWidget.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="WiFiDirectDemo.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Wiktionary.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="WiktionarySimple.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="xmladapters.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ConnectivityTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GpsLocationTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Notepadv1.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Notepadv1Solution.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Notepadv2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Notepadv2Solution.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Notepadv3.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Notepadv3Solution.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ChromeBookmarksSyncAdapter.apk" certificate="PRESIGNED" private_key=""
+name="FaceLock.apk" certificate="PRESIGNED" private_key=""
+name="GameCenterSDKService.apk" certificate="PRESIGNED" private_key=""
+name="Gmail.apk" certificate="PRESIGNED" private_key=""
+name="Gmail_Data.apk" certificate="PRESIGNED" private_key=""
+name="GoogleBackupTransport.apk" certificate="PRESIGNED" private_key=""
+name="GoogleCalendarSyncAdapter.apk" certificate="PRESIGNED" private_key=""
+name="GoogleContactsSyncAdapter.apk" certificate="PRESIGNED" private_key=""
+name="GoogleLoginService.apk" certificate="PRESIGNED" private_key=""
+name="GooglePartnerSetup.apk" certificate="PRESIGNED" private_key=""
+name="GoogleServicesFramework.apk" certificate="PRESIGNED" private_key=""
+name="Maps.apk" certificate="PRESIGNED" private_key=""
+name="Maps_Data.apk" certificate="PRESIGNED" private_key=""
+name="NetworkLocation.apk" certificate="PRESIGNED" private_key=""
+name="Talk.apk" certificate="PRESIGNED" private_key=""
+name="Talk_Data.apk" certificate="PRESIGNED" private_key=""
+name="Vending.apk" certificate="PRESIGNED" private_key=""
+name="VoiceSearch.apk" certificate="PRESIGNED" private_key=""
+name="VoiceSearch_Data.apk" certificate="PRESIGNED" private_key=""
+name="PlatformLibraryClient.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SampleEmailPolicy.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="UpgradeExample.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Quake.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="PicoTts.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="framework-res.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="ConnectivityManagerTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BandwidthTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BluetoothTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="FrameworksCoreTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="FrameworkCoreTests_install_decl_perm.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_loc_auto.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_loc_internal.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_loc_sdcard.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_loc_unspecified.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_use_perm_good.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_uses_feature.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_verifier_bad.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkCoreTests_install_verifier_good.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DisabledTestApp.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="EnabledTestApp.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="AutoLocTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AutoLocVersionedTestApp_v1.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AutoLocVersionedTestApp_v2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DownloadManagerTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalLocAllPermsTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalLocPermFLTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalLocTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalLocVersionedTestApp_v1.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalLocVersionedTestApp_v2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalSharedPermsTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalSharedPermsBTTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExternalSharedPermsDiffKeyTestApp.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="ExternalSharedPermsFLTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="InternalLocTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NoLocTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NoLocVersionedTestApp_v1.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NoLocVersionedTestApp_v2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SimpleTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="UpdateExternalLocTestApp_v1_ext.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="UpdateExternalLocTestApp_v2_none.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="UpdateExtToIntLocTestApp_v1_ext.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="UpdateExtToIntLocTestApp_v2_int.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VersatileTestApp_Auto.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VersatileTestApp_External.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VersatileTestApp_Internal.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VersatileTestApp_None.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NotificationStressTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworksCoreSystemPropertiesTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="FrameworksGraphicsTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="KeyStoreTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="CameraBrowser.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MediaDump.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="mediaframeworktest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="scoaudiotest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SoundPoolTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GL2CameraEye.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GL2Java.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GL2JNI.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GLDual.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GLJNI.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GLPerf.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="LightingTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="TestFramerate.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TestLatency.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TestEGL.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TestViewport.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BackupRestoreConfirmation.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="DefaultContainerService.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SettingsProvider.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SharedStorageBackup.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SystemUI.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SystemUITests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="VpnDialogs.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="WAPPushManager.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="WAPPushManagerTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkPolicyTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworksSaxTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworksServicesTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="TelephonyMockRilTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworksTelephonyTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkTestRunnerTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ActivityTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BandwidthEnforcementTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BatteryWaster.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BrowserPowerTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BrowserTestPlugin.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CoreTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DataIdleTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="DensityTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DumpRenderTree.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DumpRenderTree2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FixVibrateSetting.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="FrameworkPerf.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GridLayoutTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="HugeBackup.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="HwAccelerationTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ImfTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ImfTestTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="LargeAssetTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="LocationTracker.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="LotsOfApps.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="lowstoragetest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="RsComputePerf.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FBOTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ImageProcessing.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ModelViewer.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="PerfTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ShadersTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="RSTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SmokeTestApp.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SmokeTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SslLoad.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="StatusBarTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="TileBenchmark.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TileBenchmarkTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TransformTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AppWidgetHostTest.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="AppWidgetProvider.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BackupTest.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FrameworkPermissionTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AndroidCommonTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="framework-miui-res.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="LBESEC_MIUI.apk" certificate="PRESIGNED" private_key=""
+name="TelocationProvider.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="TelocationProviderTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="CalendarCommonTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MailCommonTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="AndroidVCardTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="AntiSpam.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Backup.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BasicSmsReceiver.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BasicSmsReceiverTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Bluetooth.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Browser.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BrowserTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="BugReport.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Calculator.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CalculatorTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Calendar.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CalendarTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Camera.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CameraTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CellBroadcastReceiver.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CellBroadcastReceiverTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="CertInstaller.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="CloudService.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="MiuiCompass.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Contacts.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="ContactsTests.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="DeskClock.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="DeskClockTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Email.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="EmailTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Exchange.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Exchange2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ExchangeTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="FileExplorer.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Gallery.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Gallery2.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MiuiGallery.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Gallery2Tests.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="HTMLViewer.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="KeyChain.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="KeyChainTestsSupport.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="KeyChainTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Launcher2.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="LauncherRotationStressTest.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="MiuiHome.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="Music.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="MiuiSystemUI.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="MiuiSystemUITests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Mms.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MmsAppTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="MmsTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="NetworkAssistant.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="MusicFX.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Nfc.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="NfcTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Notes.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="PackageInstaller.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Phone.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="PhoneAppTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Protips.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Provision.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="QuickSearchBox.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="QuickSearchBoxBenchmarks.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="QuickSearchBoxTests.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="NaughtySuggestions.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="PartialSuggestions.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="SlowSuggestions.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="SpammySuggestions.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="Settings.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SettingsTests.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SoundRecorder.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SpareParts.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="SpeechRecorder.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Stk.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="SuperMarket.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Tag.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ThemeManager.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Torch.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Updater.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="VideoEditor.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VoiceDialer.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="VoiceDialerTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="Weather.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="LatinIME.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="LatinIMETests.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="ApplicationsProvider.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="ApplicationsProviderTests.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="CalendarProvider.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CalendarProviderTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="ContactsProvider.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="ContactsProviderTests.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="DownloadProvider.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="DownloadProviderTests.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="DownloadProviderPermissionTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DownloadPublicApiAccessTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="DownloadProviderUi.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="DrmProvider.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="MediaProvider.apk" certificate="build/target/product/security/media.x509.pem" private_key="build/target/product/security/media.pk8"
+name="TelephonyProvider.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="UserDictionaryProvider.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="LiveWallpapers.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="Galaxy4.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="HoloSpiralWallpaper.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="LiveWallpapersPicker.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="MagicSmokeWallpapers.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="VisualizationWallpapers.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="NoiseField.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="PhaseBeam.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="CameraEffectsRecordingSample.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="CameraEffectsTests.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="native-media.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="WeatherProvider.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="GuardProvider.apk" certificate="PRESIGNED" private_key=""
+name="XiaomiServiceFramework.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="MiuiVideoPlayer.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="VoiceAssist.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="GameCenter.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="InputMethod.apk" certificate="PRESIGNED" private_key=""
+name="AlipayMsp.apk" certificate="PRESIGNED" private_key=""
+name="MiuiVideo.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="StockSettings.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Userbook.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="AirkanPhoneService.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="DataHubProvider.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="Transfer.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="YellowPage.apk" certificate="build/target/product/security/shared.x509.pem" private_key="build/target/product/security/shared.pk8"
+name="baidushurufa_52.apk" certificate="PRESIGNED" private_key=""
+name="MiWallpaper.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="BaiduNetworkLocation.apk" certificate="PRESIGNED" private_key=""
+name="FusedLocation.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="PaymentService.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="AMAPNetworkLocation.apk" certificate="PRESIGNED" private_key=""
+name="VoiceRecognizerXunfei.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="KingSoftCleaner.apk" certificate="PRESIGNED" private_key=""
+name="O2O.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="NetworkAssistant2.apk" certificate="build/target/product/security/platform.x509.pem" private_key="build/target/product/security/platform.pk8"
+name="ota-miui-MiShop.apk" certificate="PRESIGNED" private_key=""
+name="ota-partner-NetworkAssistant.apk" certificate="PRESIGNED" private_key=""
+name="ota-partner-XunfeiSpeechService3.apk" certificate="PRESIGNED" private_key=""
+name="ota-MiuiForum.apk" certificate="PRESIGNED" private_key=""
+name="MiLinkService.apk" certificate="build/target/product/security/testkey.x509.pem" private_key="build/target/product/security/testkey.pk8"
+name="TrafficControl.apk" certificate="PRESIGNED" private_key=""
diff --git a/target_files_template/META/filesystem_config.txt b/target_files_template/META/filesystem_config.txt
index a17445c..7762521 100644
--- a/target_files_template/META/filesystem_config.txt
+++ b/target_files_template/META/filesystem_config.txt
@@ -1,4 +1,7 @@
-system/bin/app_process32_vendor 0 2000 755 selabel=u:object_r:zygote_exec:s0 capabilities=0x0
-system/bin/app_process64_vendor 0 2000 755 selabel=u:object_r:zygote_exec:s0 capabilities=0x0
-system/xbin/shelld 0 2000 755 selabel=u:object_r:system_file:s0 capabilities=0x0
-system/bin/fdpp 0 2000 755 selabel=u:object_r:system_file:s0 capabilities=0x0
+system/xbin/invoke-as 0 0 6755
+system/xbin/su 0 0 6755
+system/xbin/busybox 0 0 6755
+system/xbin/insecure 0 2000 6755
+system/xbin/shelld 0 1000 6750
+system/xbin/oemfix 0 2000 6755
+system/lib/liblbesec.so 0 0 744
diff --git a/target_files_template/META/misc_info.txt b/target_files_template/META/misc_info.txt
index 446d190..33d303e 100644
--- a/target_files_template/META/misc_info.txt
+++ b/target_files_template/META/misc_info.txt
@@ -1,4 +1,7 @@
recovery_api_version=3
-fstab_version=1
-use_set_metadata=1
+blocksize=131072
+boot_size=0x00280000
+recovery_size=0x00500000
+system_size=0x08400000
+userdata_size=0x0c440000
tool_extensions=.
diff --git a/target_files_template/OTA/bin/busybox b/target_files_template/OTA/bin/busybox
deleted file mode 100644
index 9539dea..0000000
Binary files a/target_files_template/OTA/bin/busybox and /dev/null differ
diff --git a/target_files_template/OTA/bin/relink b/target_files_template/OTA/bin/relink
index 98615ac..9086eed 100644
Binary files a/target_files_template/OTA/bin/relink and b/target_files_template/OTA/bin/relink differ
diff --git a/target_files_template/OTA/bin/replace_key b/target_files_template/OTA/bin/replace_key
deleted file mode 100644
index 300a598..0000000
--- a/target_files_template/OTA/bin/replace_key
+++ /dev/null
@@ -1,22 +0,0 @@
-debug_platform="308204a830820390a003020102020900b3998086d056cffa300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353232343035305a170d3335303930313232343035305a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d003082010802820101009c780592ac0d5d381cdeaa65ecc8a6006e36480c6d7207b12011be50863aabe2b55d009adf7146d6f2202280c7cd4d7bdb26243b8a806c26b34b137523a49268224904dc01493e7c0acf1a05c874f69b037b60309d9074d24280e16bad2a8734361951eaf72a482d09b204b1875e12ac98c1aa773d6800b9eafde56d58bed8e8da16f9a360099c37a834a6dfedb7b6b44a049e07a269fccf2c5496f2cf36d64df90a3b8d8f34a3baab4cf53371ab27719b3ba58754ad0c53fc14e1db45d51e234fbbe93c9ba4edf9ce54261350ec535607bf69a2ff4aa07db5f7ea200d09a6c1b49e21402f89ed1190893aab5a9180f152e82f85a45753cf5fc19071c5eec827020103a381fc3081f9301d0603551d0e041604144fe4a0b3dd9cba29f71d7287c4e7c38f2086c2993081c90603551d230481c13081be80144fe4a0b3dd9cba29f71d7287c4e7c38f2086c299a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900b3998086d056cffa300c0603551d13040530030101ff300d06092a864886f70d01010405000382010100572551b8d93a1f73de0f6d469f86dad6701400293c88a0cd7cd778b73dafcc197fab76e6212e56c1c761cfc42fd733de52c50ae08814cefc0a3b5a1a4346054d829f1d82b42b2048bf88b5d14929ef85f60edd12d72d55657e22e3e85d04c831d613d19938bb8982247fa321256ba12d1d6a8f92ea1db1c373317ba0c037f0d1aff645aef224979fba6e7a14bc025c71b98138cef3ddfc059617cf24845cf7b40d6382f7275ed738495ab6e5931b9421765c491b72fb68e080dbdb58c2029d347c8b328ce43ef6a8b15533edfbe989bd6a48dd4b202eda94c6ab8dd5b8399203daae2ed446232e4fe9bd961394c6300e5138e3cfd285e6e4e483538cb8b1b357"
-debug_shared="308204a830820390a003020102020900b3998086d056cffa300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353232343035305a170d3335303930313232343035305a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d003082010802820101009c780592ac0d5d381cdeaa65ecc8a6006e36480c6d7207b12011be50863aabe2b55d009adf7146d6f2202280c7cd4d7bdb26243b8a806c26b34b137523a49268224904dc01493e7c0acf1a05c874f69b037b60309d9074d24280e16bad2a8734361951eaf72a482d09b204b1875e12ac98c1aa773d6800b9eafde56d58bed8e8da16f9a360099c37a834a6dfedb7b6b44a049e07a269fccf2c5496f2cf36d64df90a3b8d8f34a3baab4cf53371ab27719b3ba58754ad0c53fc14e1db45d51e234fbbe93c9ba4edf9ce54261350ec535607bf69a2ff4aa07db5f7ea200d09a6c1b49e21402f89ed1190893aab5a9180f152e82f85a45753cf5fc19071c5eec827020103a381fc3081f9301d0603551d0e041604144fe4a0b3dd9cba29f71d7287c4e7c38f2086c2993081c90603551d230481c13081be80144fe4a0b3dd9cba29f71d7287c4e7c38f2086c299a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900b3998086d056cffa300c0603551d13040530030101ff300d06092a864886f70d01010405000382010100572551b8d93a1f73de0f6d469f86dad6701400293c88a0cd7cd778b73dafcc197fab76e6212e56c1c761cfc42fd733de52c50ae08814cefc0a3b5a1a4346054d829f1d82b42b2048bf88b5d14929ef85f60edd12d72d55657e22e3e85d04c831d613d19938bb8982247fa321256ba12d1d6a8f92ea1db1c373317ba0c037f0d1aff645aef224979fba6e7a14bc025c71b98138cef3ddfc059617cf24845cf7b40d6382f7275ed738495ab6e5931b9421765c491b72fb68e080dbdb58c2029d347c8b328ce43ef6a8b15533edfbe989bd6a48dd4b202eda94c6ab8dd5b8399203daae2ed446232e4fe9bd961394c6300e5138e3cfd285e6e4e483538cb8b1b357"
-debug_media="308204a830820390a003020102020900f2b98e6123572c4e300d06092a864886f70d0101040500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303431353233343035375a170d3335303930313233343035375a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100ae250c5a16ef97fc2869ac651b3217cc36ba0e86964168d58a049f40ce85867123a3ffb4f6d949c33cf2da3a05c23eacaa57d803889b1759bcf59e7c6f21890ae25085b7ed56aa626c0989ef9ccd36362ca0e8d1b9603fd4d8328767926ccc090c68b775ae7ff30934cc369ef2855a2667df0c667fd0c7cf5d8eba655806737303bb624726eabaedfb72f07ed7a76ab3cb9a381c4b7dcd809b140d891f00213be401f58d6a06a61eadc3a9c2f1c6567285b09ae09342a66fa421eaf93adf7573a028c331d70601ab3af7cc84033ece7c772a3a5b86b0dbe9d777c3a48aa9801edcee2781589f44d9e4113979600576a99410ba81091259dad98c6c68ff784b8f020103a381fc3081f9301d0603551d0e04160414ca293caa8bc0ed3e542eef4205a2bff2b57e4d753081c90603551d230481c13081be8014ca293caa8bc0ed3e542eef4205a2bff2b57e4d75a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900f2b98e6123572c4e300c0603551d13040530030101ff300d06092a864886f70d0101040500038201010084de9516d5e4a87217a73da8487048f53373a5f733f390d61bdf3cc9e5251625bfcaa7c3159cae275d172a9ae1e876d5458127ac542f68290dd510c0029d8f51e0ee156b7b7b5acdb394241b8ec78b74e5c42c5cafae156caf5bd199a23a27524da072debbe378464a533630b0e4d0ffb7e08ecb701fadb6379c74467f6e00c6ed888595380792038756007872c8e3007af423a57a2cab3a282869b64c4b7bd5fc187d0a7e2415965d5aae4e07a6df751b4a75e9793c918a612b81cd0b628aee0168dc44e47b10d3593260849d6adf6d727dc24444c221d3f9ecc368cad07999f2b8105bc1f20d38d41066cc1411c257a96ea4349f5746565507e4e8020a1a81"
-debug_testkey="308204a830820390a003020102020900936eacbe07f201df300d06092a864886f70d0101050500308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d301e170d3038303232393031333334365a170d3335303731373031333334365a308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d30820120300d06092a864886f70d01010105000382010d00308201080282010100d6931904dec60b24b1edc762e0d9d8253e3ecd6ceb1de2ff068ca8e8bca8cd6bd3786ea70aa76ce60ebb0f993559ffd93e77a943e7e83d4b64b8e4fea2d3e656f1e267a81bbfb230b578c20443be4c7218b846f5211586f038a14e89c2be387f8ebecf8fcac3da1ee330c9ea93d0a7c3dc4af350220d50080732e0809717ee6a053359e6a694ec2cb3f284a0a466c87a94d83b31093a67372e2f6412c06e6d42f15818dffe0381cc0cd444da6cddc3b82458194801b32564134fbfde98c9287748dbf5676a540d8154c8bbca07b9e247553311c46b9af76fdeeccc8e69e7c8a2d08e782620943f99727d3c04fe72991d99df9bae38a0b2177fa31d5b6afee91f020103a381fc3081f9301d0603551d0e04160414485900563d272c46ae118605a47419ac09ca8c113081c90603551d230481c13081be8014485900563d272c46ae118605a47419ac09ca8c11a1819aa48197308194310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e20566965773110300e060355040a1307416e64726f69643110300e060355040b1307416e64726f69643110300e06035504031307416e64726f69643122302006092a864886f70d0109011613616e64726f696440616e64726f69642e636f6d820900936eacbe07f201df300c0603551d13040530030101ff300d06092a864886f70d010105050003820101007aaf968ceb50c441055118d0daabaf015b8a765a27a715a2c2b44f221415ffdace03095abfa42df70708726c2069e5c36eddae0400be29452c084bc27eb6a17eac9dbe182c204eb15311f455d824b656dbe4dc2240912d7586fe88951d01a8feb5ae5a4260535df83431052422468c36e22c2a5ef994d61dd7306ae4c9f6951ba3c12f1d1914ddc61f1a62da2df827f603fea5603b2c540dbd7c019c36bab29a4271c117df523cdbc5f3817a49e0efa60cbd7f74177e7a4f193d43f4220772666e4c4d83e1bd5a86087cf34f2dec21e245ca6c2bb016e683638050d2c430eea7c26a1c49d3760a58ab7f1a82cc938b4831384324bd0401fa12163a50570e684d"
-patchrom_platform="308203e5308202cda003020102020900b8efb85271e7e740300d06092a864886f70d0101050500308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d301e170d3136303132303039303232365a170d3433303630373039303232365a308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100b85b306dc881873256284ea4c77a0b3b55f718afe3de21af829697ca4d348641b55ffb80abf13656c88c16606f0f439ae3d1edd62154bd58b17120b0a184493f9c1170003041f4b2b3e9bb61257f7de1499e8c35a606a81c70c305bd8ea325e4572871ec44e62666b30afb5ffc24148e4194e65478547cd13787284f83da5c6b50bd2223adc8b57e786fb1e49e52eba6a06bfa1c6b44b289a8d6d06906e22eb8a527fc123e1faf387548a026e785dbec5bd2dc207f3b2eef18b5a499f245cec19fa8623556caf1d5e41d5c3274d5413c2b1d4cf15eff297fc36894e80344769f6022afe5bf920f271091e438d98425e3953bedf9967ead1d0646e3967b65ed770203010001a350304e301d0603551d0e04160414a1e9aed0be13a7be6d1299f0f4b9993e53d30d8f301f0603551d23041830168014a1e9aed0be13a7be6d1299f0f4b9993e53d30d8f300c0603551d13040530030101ff300d06092a864886f70d010105050003820101009f3e79672817e5aa5202b5e6120b0f952c51dcc1d8b887271dc326e1ebc7cc33c13eab7f284e009ceea5345af916f4c9d2b7a12ef9eb46ee5c799c82664d744256656ad28815d90676b7d01fcbc1eddaf1dfc8d71472a73dc8ecaf630ccdf91a0ff4e624f8892443a2199ad85b0b037163416dd2207ba499efdb7c95193ed17dbef5875fb7ecfe45359ea57007724b0597d7aaf1e458d1f93a21ca10bd145f73c99e7d1208a5aab091b1f16446e329bd12440509711f2a58f40221dffa10a043a85481667516362931b00b1822851678323fef4596c83cc8f332fa3ff736ceb6b10cb1499a28cefb0c3a19157356adaabef7bd953caca1a7b402a8816951ed78"
-patchrom_shared="308203e5308202cda003020102020900f716cbd07088bb40300d06092a864886f70d0101050500308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d301e170d3136303132303039303235375a170d3433303630373039303235375a308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100e293b3780f0da7a69fedd06f9922436b1f0fb4605d4287a0f62826d2db767febc4438cafb1addfe888f57cf9720f1fdf5bf9b8f342de1fbc31c8617aaa23c2b50fdb8d95b292798e8dee84a46a304224a9b80735f2abb966dc5b73c7e34693d00a0b9931aa87595ae35582c4d0ad6dd2eefc1372dd4cc776de7fb046e0c6af7867cb9366c73f8fbce9d7b186384e7b3c299217181677b0bc16d69cea6ac26bc5e8424faa4d3caa89e3fa31c822095e45a08697fcb13054c7f17de86e72b09e0e7be627c25a105b327bb0614eecfe37dcfd0b906930c4ab84eb051f430f493a43158bbf7bc0b474e0409378076cc8ea475b76e5f7ea2cb03194aa7184f5f3ce3b0203010001a350304e301d0603551d0e04160414b449dd6f51e3b354619a47dda7c897323ed723c0301f0603551d23041830168014b449dd6f51e3b354619a47dda7c897323ed723c0300c0603551d13040530030101ff300d06092a864886f70d01010505000382010100b2091ff1a0c23b0027d62101918225fad31d9d37e6bfcc126574324a23611a69f2450db2cc10fbdfd96448386d122a6f8b1b6685a9aa538abcbc659958d9038c5d53c2657bac65d951374716648eee9feab23e85c04bae366d9b8027d283f0e6389b03674a0e98a1859d8e2868be49ad199662c6fe0a98f43232c494622e70b74be77f077833464647d909ae5657b63ec58dbd5d91b6fe2be3981a58a6c8f24d04605a0fcbc86f4a298d9f32bef72fb8123f1a323ee3cd95601863ad07fd6e3ba52da120169eadff6b80ca653d730b94a58ae051682b7c9a8a6c06bd0efdd4a9f5d0320fa08419a749b20c66092bc5ee63864850435b381aac789e6be081cd49"
-patchrom_media="308203e5308202cda003020102020900b87815ea377b5c04300d06092a864886f70d0101050500308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d301e170d3136303132303039303334325a170d3433303630373039303334325a308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d30820122300d06092a864886f70d01010105000382010f003082010a02820101009874294fb2f7fcc01605bc4183a001e0f2fc88b130b3b9531ef3a57ddece1628d26b999ba68969c4c575f56105bcfcc62fca5b6183b8fddc93258cb760edca1b71c4c04f492c985e653195bb0f8791304a82989b379d737cb9aaa14d602fe2bde3df68c909175e99673fbb1ecc2a53adf799f620fcd491ec92b42c779ca5460fca443ea777035ee0771c60945fe0ea2fb88be9b60f3e194053c4366887c9609b7891f3019aaa80129f933c3843013292b84d28041fef05852238a860fa33c955c83f139f646c864d7ddda0c57f6d7aa3f03163f401151a2b982b5c895e5fe1aeef47078b4269255070b600a28f4ac0ec8598e04525aa6939ee62459256ec91b90203010001a350304e301d0603551d0e04160414f6807b81a390e6098014f1722fa0aff1fae60240301f0603551d23041830168014f6807b81a390e6098014f1722fa0aff1fae60240300c0603551d13040530030101ff300d06092a864886f70d01010505000382010100658261e32cfe877b2821423285f404f4eeaecf81a3b0b7fb5d3e7b47e0b5ab79d96fc4a032ebb95dba82a04baa96c9780f81328033e405e72040c69733d47bf1bd5e27e07be3deb8fd94595dda580dbe6251a7dcc8e850f9ec85f64b884f0be0f0aac6e029c4f5d1ed857aa42ddbb7792d76b391dc451c8fe881e6dbbfd61c6482e8c1039b32c3afe03eb1fb213f1e629e329d568392e177c0c1dfd80a4171adfdeb346b9dcd1fbd2b24bf4925ac74c53367bf091772b861c4b90b108b759b2192cec83354a8f092bcdfc52b3051abaebc6cda7b1dd0c8f2c21493742dac4d4497b7ecbb2a83882fea9b6f23ce871f4df49f5cde7bd8480cd7a8a4ab8ba503c6"
-patchrom_testkey="308203e5308202cda003020102020900eaf7ddf89372f4d4300d06092a864886f70d0101050500308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d301e170d3136303132303039303331385a170d3433303630373039303331385a308188310b300906035504061302434e3110300e06035504080c074265696a696e673110300e06035504070c074265696a696e67310f300d060355040a0c065869616f6d69310d300b060355040b0c044d4955493111300f06035504030c085061746368526f6d3122302006092a864886f70d01090116137061746368726f6d407869616f6d692e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100bc35fd9be394cdf0872674ce64a5377fe00739ab9a0719d8371aef6ab10e3efd871d735f0aee09eb4f64f50711f2b974ba7b47b61357782786e6a0ae73e26e965ba2032e73caadad5d21b47f0680b742d78c6526a5de33a6100ce0cc3ad6900115d654294f0c8b5a2f810883c7ece88e41eff55a8b0afbf7710bdf86d450fc433aaf46d38f6e1a97bf52a67857ade83b9047e9db23bdf13ceb98d093597d46cc4e495b1a0e2c07dd2e68f79ddbc0aa68f7c949a845ffef02971560cb50781f615f186e653ef39b8fe77ca85ddaeb7c61875830803d474604cf758049d3c47b68bc2aae91fd39ee9e546fb9afe6b5ac0811f80e9bb4f44f106504dc3fca0983910203010001a350304e301d0603551d0e04160414b8c84855c24ae06e1be97879f727f473db2e7b0c301f0603551d23041830168014b8c84855c24ae06e1be97879f727f473db2e7b0c300c0603551d13040530030101ff300d06092a864886f70d0101050500038201010020f9b9414f0fbfcbf3ab84bd327cb14d5f17fce0f4718cb78a5b2ded7f8b1b05dca9b59227deb342736995b1cfb51d19e602466f84d652b2614491485a8677e87283db3c315dae9784868862ec52c08eaa4860b6d1bf53f9e0d6c718f55580404923c7e30fbed93d98bacd53eb1fd05d69116e98cee4ee42f8eca3bad566c06b04a764a799f513531ae594ca7daf3f7c30a93ad859ce9f8b7ed97ab5575b322480215d2f7bcad419a1b742a042708bfba2c912072e9f1f9e0044a1405b4abc4c25291f660340d2cf30f37f06ddbc37345a8937093df9d75b81aa76f618791f162966721dc7830964b443cefaa8448ddba84199053710b2c99b8b8dcf7d965c42"
-user_platform="@user_platform"
-user_shared="@user_shared"
-user_media="@user_media"
-user_testkey="@user_testkey"
-
-/tmp/busybox sed -i "s/$debug_platform/$user_platform/g" /data/system/packages.xml
-/tmp/busybox sed -i "s/$debug_shared/$user_shared/g" /data/system/packages.xml
-/tmp/busybox sed -i "s/$debug_media/$user_media/g" /data/system/packages.xml
-/tmp/busybox sed -i "s/$debug_testkey/$user_testkey/g" /data/system/packages.xml
-
-/tmp/busybox sed -i "s/$patchrom_platform/$user_platform/g" /data/system/packages.xml
-/tmp/busybox sed -i "s/$patchrom_shared/$user_shared/g" /data/system/packages.xml
-/tmp/busybox sed -i "s/$patchrom_media/$user_media/g" /data/system/packages.xml
-/tmp/busybox sed -i "s/$patchrom_testkey/$user_testkey/g" /data/system/packages.xml
diff --git a/target_files_template/OTA/bin/updater b/target_files_template/OTA/bin/updater
index fe34944..29fbc64 100644
Binary files a/target_files_template/OTA/bin/updater and b/target_files_template/OTA/bin/updater differ
diff --git a/uniq_first.py b/uniq_first.py
index 11b6896..bbb3404 100755
--- a/uniq_first.py
+++ b/uniq_first.py
@@ -11,16 +11,30 @@ def uniq_first(src_file, dst_file):
with open(dst_file, 'a') as df:
for line in lines:
- if not (line.split()[0] + " " in content):
+ if not (line.split()[0] in content):
df.write(line)
+def filter_miui(miui_file, filter_file, make_dir):
+ lines = []
+ miui_apps = os.popen("make -C "+ make_dir + " miui-apps-included").read()
+ with open(miui_file, 'r') as mf:
+ lines = mf.readlines()
+
+ with open(filter_file, 'w') as ff:
+ for line in lines:
+ if line.split():
+ if (line.split()[0].split('"')[1] in miui_apps):
+ ff.write(line)
+
def main(args):
- if len(args) != 2:
- print("Usage: uniq_first src_file dst_file")
+ if len(args) != 3:
+ print("Usage: uniq_first src_file dst_file make_dir")
sys.exit(1)
- uniq_first(args[0], args[1])
-
+ filtered = args[1] + '.filter'
+ filter_miui(args[1], filtered, args[2])
+ uniq_first(args[0], filtered)
+ os.rename(filtered, args[1])
if __name__ == '__main__':
main(sys.argv[1:])
diff --git a/unpackbootimg b/unpackbootimg
new file mode 100755
index 0000000..067cd63
Binary files /dev/null and b/unpackbootimg differ