#This file is part of The Open GApps script of @mfonville. # # The Open GApps scripts are free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # These scripts are distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # preparebuildarea() { build="$BUILD/$ARCH/$API/$VARIANT" echo "Cleaning build area: $build" rm -rf "$build" install -d "$build" install -d "$CACHE" logfile="" if [ -n "$VERSIONLOG" ]; then logfile="$(eval "echo \"$VERSIONLOG\"")" install -d "$(dirname "$logfile")" printf "%-6s%3s| %-61s| %-50s| %s\n-----------------------------------------------------------------------------------------------------------------------------------\n" "Arch." "API" "Application / File / Folder" "Version Name" "DPIs" > "$logfile" fi } copy() { if [ -d "$1" ]; then for f in $1/*; do copy "$f" "$2/$(basename "$f")" done fi if [ -f "$1" ]; then install -D -p "$1" "$2" fi } buildfile() { if [ -z "$4" ]; then usearch="$ARCH" else usearch="$4"; fi #allows for an override case "$usearch" in all) targetarch="common";; # technically with our currrent APKs-set, every that is 'all' is de-facto also 'common' *) targetarch="$usearch";; esac if [ -e "$SOURCES/$usearch/$1" ]; then #check if directory or file exists if [ -d "$SOURCES/$usearch/$1" ]; then #if we are handling a directory targetdir="$build/$2-$targetarch/$3/$1" else targetdir="$build/$2-$targetarch/$3/$(dirname "$1")" fi install -d "$targetdir" printf "%6s %s\n" "$usearch" "$1" if [ -n "$logfile" ]; then printf "%6s | %-s\n" "$usearch" "$1">> "$logfile" fi copy "$SOURCES/$usearch/$1" "$targetdir" #if we have a file specific to this architecture # rename etc/sysconfig/google_go.xml to etc/sysconfig/google.xml if [ "$1" = "etc/sysconfig/google_go.xml" ]; then mv "$targetdir/google_go.xml" "$targetdir/google.xml" fi else get_fallback_arch "$usearch" if [ "$usearch" != "$fallback_arch" ]; then buildfile "$1" "$2" "$3" "$fallback_arch" else echo "ERROR: No fallback available. Failed to build file $1" exit 1 fi fi } buildframework() { frameworkname="$1" ziplocation="$2" targetlocation="$3" if [ -z "$4" ]; then usearch="$ARCH" else usearch="$4"; fi #allows for an override case "$usearch" in all) targetarch="common";; # technically with our currrent APKs-set, every that is 'all' is de-facto also 'common' *) targetarch="$usearch";; esac if getframeworkforapi "$frameworkname" "$usearch" "$API"; then printf "%6s-%s %s\n" "$usearch" "$api" "$frameworkname" if [ -n "$logfile" ]; then printf "%6s-%s| %-s\n" "$usearch" "$api" "$frameworkname" >> "$logfile" fi install -D -p "$sourceframework" "$build/$ziplocation-$targetarch/$targetlocation/$targetframework" else get_fallback_arch "$usearch" if [ "$usearch" != "$fallback_arch" ]; then buildframework "$frameworkname" "$ziplocation" "$targetlocation" "$fallback_arch" else echo "ERROR: No fallback available. Failed to build framework $frameworkname" exit 1 fi fi } buildsystemlib() { libname="$1" ziplocation="$2" targetlocation="$3" if [ -z "$4" ]; then usearch="$ARCH" else usearch="$4"; fi #allows for an override fallback="" case "$libname" in *+fallback) libname="$(echo "$libname" | sed 's/+fallback//')" fallback="true";; esac case "$usearch" in all) targetarch="common";; # technically with our currrent APKs-set, every that is 'all' is de-facto also 'common' *) targetarch="$usearch";; esac if getsystemlibforapi "$libname" "$usearch" "$API"; then printf "%6s-%s %s\n" "$usearch" "$api" "$libname" if [ -n "$logfile" ]; then printf "%6s-%s| %-s\n" "$usearch" "$api" "$libname" >> "$logfile" fi install -D -p "$sourcelib" "$build/$ziplocation-lib-$targetarch/$targetlocation/$targetlib" else fallback="true" fi if [ -n "$fallback" ]; then get_fallback_arch "$usearch" if [ "$usearch" != "$fallback_arch" ]; then buildsystemlib "$libname" "$ziplocation" "$targetlocation" "$fallback_arch" else echo "ERROR: No fallback available. Failed to build lib $libname" exit 1 fi fi } getpathsystemlib(){ libname="$1" if [ -z "$2" ]; then usearch="$ARCH" else usearch="$2"; fi #allows for an override fallback="" case "$libname" in *+fallback) libname="$(echo "$libname" | sed 's/+fallback//')" fallback="true";; esac if getsystemlibforapi "$libname" "$usearch" "$API"; then systemlibpath="$targetlib $systemlibpath" else fallback="true" fi if [ -n "$fallback" ]; then get_fallback_arch "$usearch" if [ "$usearch" != "$fallback_arch" ]; then getpathsystemlib "$libname" "$fallback_arch" fi fi } buildapp() { package="$1" usemaxapi="$2" ziplocation="$3" targetlocation="$4" if [ -z "$5" ]; then usearch="$ARCH" else usearch="$5"; fi #allows for an override packagedirsuffix="$6" minapihack #Some packages need a minimal api level to maintain compatibility with the OS if getapksforapi "$package" "$usearch" "$usemaxapi" "$useminapi" "$packagedirsuffix"; then baseversionname="" for dpivariant in $(echo "$sourceapks" | tr ' ' ''); do #we replace the spaces with a special char to survive the for-loop dpivariant="$(echo "$dpivariant" | tr '' ' ')" #and we place the spaces back again getapkproperties "$dpivariant" #get versionname versionname="$(printf "%s" "$versionname" | cut -d ' ' -f 1)" #always cut off everything in the versionname after the space since that indicates a part that is ALWAYS at minimum dpi-specific versionnamehack #Some packages have a different versionname, when the actual version is equal systemlibhack #Some packages want their libs installed as system libs if [ "$API" -le "19" ] || [ "$systemlib" = "true" ]; then liblocation="$ziplocation-$usearch/common" else liblocation="$ziplocation-$usearch/common/$targetlocation" fi if [ -z "$baseversionname" ]; then baseversionname=$versionname buildlib "$dpivariant" "$liblocation" "$usearch" #Use the libs from this baseversion printf "%6s-%-2s %-61s %50s" "$usearch" "$api" "$1" "$baseversionname" # use $1 instead of $package to show the foldername packagename instead of the getapkproperties-name to get the setupwizard name right if [ -n "$logfile" ]; then printf "%6s-%-2s| %-61s| %-50s|" "$usearch" "$api" "$1" "$baseversionname" >> "$logfile" fi fi if [ "$versionname" = "$baseversionname" ]; then density=$(basename "$(dirname "$dpivariant")") buildapk "$dpivariant" "$ziplocation-$usearch/$density/$targetlocation" printf " %s" "$density" if [ -n "$logfile" ]; then printf " %s" "$density" >> "$logfile" fi echo "$ziplocation-$usearch/$density/" >> "$build/app_densities.txt" fi done printf "\n" if [ -n "$logfile" ]; then printf "\n" >> "$logfile" fi else get_fallback_arch "$usearch" if [ "$usearch" != "$fallback_arch" ]; then buildapp "$package" "$usemaxapi" "$ziplocation" "$targetlocation" "$fallback_arch" "$packagedirsuffix" else echo "ERROR: No fallback available. Failed to build package $package" exit 1 fi fi } getapksforapi() { #this functions finds the highest available acceptable apk for a given api and architecture #$1 package, $2 arch, $3 api, $4 minapi, $5 packagedirsuffix if [ -z "$4" ]; then minapi="0" else minapi="$4"; fi #specify minimal api if ! stat --printf='' "$SOURCES/$2/"*"app$5/$1" 2>/dev/null; then return 1 #appname is not there, error!? fi sourceapks="" OLDIFS="$IFS" IFS=" " #We set IFS to newline here so that spaces can survive the for loop #sed copies filename to the beginning, to compare version, and later we remove it with cut maxsdkerrorapi="" for foundapk in $(find $SOURCES/$2/*app$5/$1 -iname '*.apk' 2>/dev/null| sed 's!.*/\(.*\)!\1/&!' | sort -r -n -t/ -k1,1 | cut -d/ -f2-); do foundpath="$(dirname "$(dirname "$foundapk")")" api="$(basename "$foundpath")" if [ "$maxsdkerrorapi" = "$api" ]; then continue #if we already know that this api hit the maxsdk error, do not try it again fi if [ "$api" -le "$3" ] && [ "$api" -ge "$minapi" ]; then #We need to keep them sorted sourceapks="$(find "$foundpath" -iname '*.apk' | sed 's!.*/\(.*\)!\1/&!' | sort -r -n -t/ -k1,1 | cut -d/ -f2-)" for maxsdkapk in $sourceapks; do maxsdk="$(aapt dump badging "$maxsdkapk" 2>/dev/null | grep -a "maxSdkVersion:" | sed 's/maxSdkVersion://' | sed "s/'//g")" if [ -n "$maxsdk" ] && [ "$maxsdk" -lt "$3" ]; then echo "WARNING: Newest APK found is incompatible with API level $3 for package $1 on $2, maxSdk: $maxsdk, falling back to higher SDK" maxsdkerrorapi="$api" continue 2 fi break done break fi done IFS="$OLDIFS" if [ -z "$sourceapks" ]; then echo "WARNING: No APK found compatible with API level $3 for package $1 on $2, lowest found: $api" return 1 #error fi #$sourceapks and $api have the useful returnvalues return 0 #return that it was a success } getframeworkforapi() { #this functions finds the highest available acceptable framework for a given api and architecture #$1 frameworkname, $2 arch, $3 api sourceframework="" OLDIFS="$IFS" IFS=" " #We set IFS to newline here so that spaces can survive the for loop for foundframework in $(find $SOURCES/$2/framework/ -iname "$1" 2>/dev/null| sort -r); do api="$(basename "$(dirname "$foundframework")")" if [ "$api" -le "$3" ]; then sourceframework="$foundframework" break fi done IFS="$OLDIFS" if [ -z "$sourceframework" ]; then #echo "WARNING: No framework found compatible with API level $3 for framework $1 on $2, lowest found: $api" return 1 #error fi apiframeworkpath="$(echo "$sourceframework" | awk -F'/' '{print $(NF-1)}')" # is api number targetframework="$(echo "$sourceframework" | sed "s:^$SOURCES/$2/::" | sed "s:/$apiframeworkpath/:/:g")" # framework/frameworkname.jar #$sourceframework, $targetframework and $api have the useful returnvalues return 0 #return that it was a success } getsystemlibforapi() { #this functions finds the highest available acceptable lib for a given api and architecture #$1 libname, $2 arch, $3 api sourcelib="" OLDIFS="$IFS" IFS=" " #We set IFS to newline here so that spaces can survive the for loop for foundlib in $(find $SOURCES/$2/lib*/ $SOURCES/$2/vendor/lib*/ -iname "$1" 2>/dev/null| sort -r); do api="$(basename "$(dirname "$foundlib")")" if [ "$api" -le "$3" ]; then sourcelib="$foundlib" break fi done IFS="$OLDIFS" if [ -z "$sourcelib" ]; then #echo "WARNING: No lib found compatible with API level $3 for lib $1 on $2, lowest found: $api" return 1 #error fi apilibpath="$(echo "$sourcelib" | awk -F'/' '{print $(NF-1)}')" # is api number targetlib="$(echo "$sourcelib" | sed "s:^$SOURCES/$2/::" | sed "s:/$apilibpath/:/:g")" # lib/libname.so #$sourcelib, $targetlib and $api have the useful returnvalues return 0 #return that it was a success } buildapk() { sourceapk="$1" targetdir="$build/$2" targetapk="$targetdir/$(basename "$targetdir").apk" if [ "$API" -le "19" ]; then #We will do this as long as we support KitKat targetapk="$targetdir.apk" targetdir="$(dirname "$targetapk")" fi if [ -f "$targetapk" ]; then rm "$targetapk" fi install -D "$sourceapk" "$targetapk" if (unzip -v "$targetapk" | grep "lib/" | grep -qv "Stored"); then #check if there are compressed libs present if [ "$API" -lt "23" ]; then #only if pre-Marshmallow unzip -Z -1 "$targetapk" | grep "lib/" | grep -v "/crazy." | xargs zip -q -d "$targetapk" #delete all libs, except crazy-linked else #Marshmallow and above needs libs to be stored without compression within the APK unzip -qqq -o "$targetapk" -d "$targetdir" "lib/*" zip -q -d "$targetapk" "lib/*" #delete all libs ( cd "$targetdir" zip -q -r -D -Z store -b "$targetdir" "$targetapk" "lib/" #no parameter for output and mode, we are in 'add and update existing' mode which is default. Lib files have to be stored without compression. ) rm -rf "$targetdir/lib/" fi fi } buildlib() { sourceapk="$1" targetdir="$build/$2" apkarch="$3" libsearchpath="lib/*" #default that should never happen: all libs if [ "$apkarch" = "arm" ]; then libsearchpath="lib/armeabi*/*" #mind the wildcard libfallbacksearchpath="" elif [ "$apkarch" = "arm64" ]; then libsearchpath="lib/arm64*/*" #mind the wildcard libfallbacksearchpath="lib/armeabi*/*" #mind the wildcard elif [ "$apkarch" = "x86" ]; then libsearchpath="lib/x86/*" libfallbacksearchpath="" elif [ "$apkarch" = "x86_64" ]; then libsearchpath="lib/x86_64/*" libfallbacksearchpath="lib/x86/*" elif [ "$apkarch" = "mips" ]; then libsearchpath="lib/mips/*" libfallbacksearchpath="" elif [ "$apkarch" = "mips64" ]; then libsearchpath="lib/mips64/*" libfallbacksearchpath="lib/mips/*" fi get_fallback_arch "$apkarch" if [ "$(basename "$targetdir")" = "common" ]; then #if we are installing systemwide libs libpath="$LIBFOLDER" fallbacklibpath="lib" else #Lollipop-style libs bundled in the APK's folder libpath="lib/$apkarch" fallbacklibpath="lib/$fallback_arch" #notice that this sometimes gives 'illegal' paths like 'lib/all', but the path is not used in those situations fi if [ "$API" -lt "23" ]; then #libextraction is only necessary on pre-Marshmallow if [ -n "$(unzip -Z -1 "$sourceapk" "$libsearchpath" 2>/dev/null)" ]; then install -d "$targetdir/$libpath" unzip -qqq -j -o "$sourceapk" "$libsearchpath" -x "lib/*/crazy.*" -d "$targetdir/$libpath" 2>/dev/null fi if [ "$apkarch" != "$fallback_arch" ] && [ -n "$(unzip -Z -1 "$sourceapk" "$libfallbacksearchpath" 2>/dev/null)" ]; then install -d "$targetdir/$fallbacklibpath" unzip -qqq -j -o "$sourceapk" "$libfallbacksearchpath" -x "lib/*/crazy.*" -d "$targetdir/$fallbacklibpath" 2>/dev/null fi fi }