diff --git a/Xposed.pm b/Xposed.pm index 56176ba..4a49dd8 100644 --- a/Xposed.pm +++ b/Xposed.pm @@ -14,6 +14,7 @@ use File::Tail; use FindBin qw($Bin); use POSIX qw(strftime); use Term::ANSIColor; +use Archive::Zip qw(:ERROR_CODES :CONSTANTS); our $cfg; my $MAX_SUPPORTED_SDK = 23; @@ -119,21 +120,30 @@ sub expand_targets($;$) { my @result; my %seen; - foreach (split(m/[\/ ]+/, $spec)) { - my ($pfspec, $sdkspec) = split(m/[: ]+/, $_, 2); - my @pflist = ($pfspec ne 'all' && $pfspec ne 'all+') ? split(m/[, ]/, $pfspec) : ('arm', 'x86', 'arm64', 'armv5'); - if ($pfspec eq 'all+') { - push @pflist, 'host'; - push @pflist, 'hostd'; - $pfspec = 'all'; - } - my @sdklist = ($sdkspec ne 'all') ? split(m/[, ]/, $sdkspec) : $cfg->Parameters('AospDir'); - foreach my $sdk (@sdklist) { - foreach my $pf (@pflist) { - next if !check_target_sdk_platform($pf, $sdk, $pfspec eq 'all' || $sdkspec eq 'all'); - next if $seen{"$pf/$sdk"}++; - push @result, { platform => $pf, sdk => $sdk }; - print " SDK $sdk, platform $pf\n" if $print; + my ($pfspec, $sdkspec) = split(m/[: ]+/, $spec, 2); + my @pflist = ($pfspec ne 'bundle' && $pfspec ne 'all' && $pfspec ne 'all+') ? split(m/[, ]/, $pfspec) : ('arm', 'x86', 'arm64', 'armv5'); + if ($pfspec eq 'all+') { + push @pflist, 'host'; + push @pflist, 'hostd'; + $pfspec = 'all'; + } + my $bundle; + if ($pfspec eq 'bundle') { + $bundle = 1; + $pfspec = 'all'; + } else { + $bundle = 0 + } + my @sdklist = ($sdkspec ne 'all') ? split(m/[, ]/, $sdkspec) : $cfg->Parameters('AospDir'); + foreach my $sdk (@sdklist) { + foreach my $pf (@pflist) { + next if !check_target_sdk_platform($pf, $sdk, $pfspec eq 'all' || $sdkspec eq 'all'); + next if $seen{"$pf/$sdk"}++; + push @result, { platform => $pf, sdk => $sdk, bundle => $bundle }; + if ($print) { + print " SDK $sdk, platform $pf"; + print " (bundle)" if ($bundle); + print "\n"; } } } @@ -186,7 +196,7 @@ sub get_version() { # Returns the Xposed version number and the suffix to be used in file names sub get_version_for_filename(;$) { my $version = shift || get_version(); - $version =~ m/^(\d+)(.*)/; + $version =~ m/^(\d+(?:\.\d+)?)(.*)/; my ($version_num, $suffix) = ($1, $2); if ($suffix) { $suffix =~ s/[\s\/|*"?<:>%()]+/-/g; @@ -241,10 +251,20 @@ sub get_collection_dir($$) { return sprintf('%s/sdk%d/%s', $cfg->val('General', 'outdir'), $sdk, $platform); } +# Determines the sdk directory where compiled files etc. are collected +sub get_bundle_dir($) { + my $sdk = shift; + return sprintf('%s/sdk%d', $cfg->val('General', 'outdir'), $sdk); +} + # Returns the directory to store symlinks to the ZIPs per versions sub get_version_dir(;$) { my ($version, $suffix) = get_version_for_filename(shift); - return sprintf('%s/versions/v%d%s', $cfg->val('General', 'outdir'), $version, $suffix); + if ($version =~ m/^\d+\./) { + return sprintf('%s/versions/v%.1f%s', $cfg->val('General', 'outdir'), $version, $suffix); + } else { + return sprintf('%s/versions/v%d%s', $cfg->val('General', 'outdir'), $version, $suffix); + } } # Determines the mode that has to be passed to the "lunch" command @@ -354,7 +374,10 @@ sub sign_zip($) { my $signed = $file . '.signed'; my $cmd = "java -jar $Bin/signapk.jar -w $Bin/signkey.x509.pem $Bin/signkey.pk8 $file $signed"; system("bash -c \"$cmd\"") == 0 || return 0; - rename($signed, $file); + # Re-zip the file to fix zip headers + my $zip = Archive::Zip->new($signed); + $zip->writeToFileNamed($file) == AZ_OK || return 0; + unlink $signed; return 1; } diff --git a/build.pl b/build.pl index ac4bc85..237c9a2 100755 --- a/build.pl +++ b/build.pl @@ -47,23 +47,27 @@ () # Determine build targets my $target_spec = $opts{'t'} || ''; - print_status("Expanding targets from '$target_spec'...", 0); - my @targets = Xposed::expand_targets($target_spec, 1); - if (!@targets) { - print_error('No valid targets specified'); - usage(2); - } - print "\n"; + foreach (split(m/[\/ ]+/, $target_spec)) { + print_status("Expanding targets from '$_'...", 0); + my @targets = Xposed::expand_targets($_, 1); + if (!@targets) { + print_error('No valid targets specified'); + usage(2); + } + print "\n"; - # Check whether flashing is possible - if ($opts{'f'} && $#targets != 0) { - print_error('Flashing is only supported for a single target!'); - exit 1; - } + # Check whether flashing is possible + if ($opts{'f'} && $#targets != 0) { + print_error('Flashing is only supported for a single target!'); + exit 1; + } + + # Build the specified targets + foreach my $target (@targets) { + all_in_one($target->{'platform'}, $target->{'sdk'}, $target->{'bundle'}, !$opts{'v'}) || exit 1; + } - # Build the specified targets - foreach my $target (@targets) { - all_in_one($target->{'platform'}, $target->{'sdk'}, !$opts{'v'}) || exit 1; + bundle_zip($targets[0]->{'sdk'}) if ($targets[0]->{'bundle'}) } } elsif ($action eq 'java') { # Build XposedBridge.jar @@ -71,6 +75,9 @@ () } elsif ($action eq 'prunelogs') { # Remove old logs prune_logs() || exit 1; + } elsif ($action eq 'uninstaller') { + # Build uninstaller + uninstaller_zip() || exit 1; } else { print_error("Unknown action specified: $action"); usage(2); @@ -96,14 +103,19 @@ ($) -v Verbose mode. Display the build log instead of redirecting it to a file. Possible actions are: - build Builds the native executables and libraries. - java Builds the Java part (XposedBridge). - prunelogs Removes logs which are older than 24 hours. + build Builds the native executables and libraries. + java Builds the Java part (XposedBridge). + prunelogs Removes logs which are older than 24 hours. + uninstaller Create uninstaller ZIP file Format of is: :[/:/...] is a comma-separated list of: arm, x86, arm64 (and up to SDK 17, also armv5) is a comma-separated list of integers (e.g. 21 for Android 5.0) Both platform and SDK accept the wildcard "all". + For platform, the "all" option will create seperate package for all platforms. + Platform also accepts wildcard "bundle". + The "bundle" option will create an all-in-one package for a certain SDK version. + Values for are provided as a comma-separated list of: compile Compile executables and libraries. @@ -113,6 +125,8 @@ ($) Examples: +$0 -t bundle:23 + (build an all-in-one package for SDK 23) $0 -t arm:all/x86,arm64:21 (build ARM files for all SDKs, plus x86 and arm64 files for SDK 21) @@ -140,9 +154,10 @@ ($) } # Performs all build steps for one platform/SDK combination -sub all_in_one($$;$) { +sub all_in_one($$$;$) { my $platform = shift; my $sdk = shift; + my $bundle = shift; my $silent = shift || 0; print_status("Processing SDK $sdk, platform $platform...", 0); @@ -151,7 +166,7 @@ ($$;$) if ($platform ne 'host' && $platform ne 'hostd') { collect($platform, $sdk) || return 0; create_xposed_prop($platform, $sdk, !$silent) || return 0; - create_zip($platform, $sdk) || return 0; + create_zip($platform, $sdk) if (!$bundle) || return $bundle; } print "\n\n"; @@ -356,7 +371,7 @@ ($$) $zip->addFile("$outdir/java/XposedBridge.jar", 'system/framework/XposedBridge.jar') || return 0; # TODO: We probably need different files for older releases $zip->addTree($Bin . '/zipstatic/_all/', '') == AZ_OK || return 0; - $zip->addTree($Bin . '/zipstatic/' . $platform . '/', '') == AZ_OK || return 0; + $zip->addTree($Bin . '/zipstatic/single/', '') == AZ_OK || return 0; # Set last modification time to "now" my $now = time(); @@ -366,7 +381,12 @@ ($$) # Write the ZIP file to disk my ($version, $suffix) = Xposed::get_version_for_filename(); - my $zipname = sprintf('xposed-v%d-sdk%d-%s%s.zip', $version, $sdk, $platform, $suffix); + my $zipname; + if ($version =~ m/^\d+\./) { + $zipname = sprintf('xposed-v%.1f-sdk%d-%s%s.zip', $version, $sdk, $platform, $suffix); + } else { + $zipname = sprintf('xposed-v%d-sdk%d-%s%s.zip', $version, $sdk, $platform, $suffix); + } my $zippath = $coldir . '/' . $zipname; print "$zippath\n"; $zip->writeToFileNamed($zippath) == AZ_OK || return 0; @@ -404,6 +424,93 @@ ($$) return 1; } +# Create an all-in-one bundled flashable ZIP file with the compiled and some static files +sub bundle_zip($) { + my $sdk = shift; + + should_perform_step('zip') || return 1; + print_status("Creating all-in-one bundled flashable ZIP file...", 1); + + # Create a new ZIP file + my $zip = Archive::Zip->new(); + my $outdir = $Xposed::cfg->val('General', 'outdir'); + my $armdir = Xposed::get_collection_dir('arm', $sdk); + my $arm64dir = Xposed::get_collection_dir('arm64', $sdk); + my $x86dir = Xposed::get_collection_dir('x86', $sdk); + $zip->addTree($armdir . '/files/', 'arm/') == AZ_OK || return 0; + $zip->addTree($arm64dir . '/files/', 'arm64/') == AZ_OK || return 0; + $zip->addTree($x86dir . '/files/', 'x86/') == AZ_OK || return 0; + $zip->addDirectory('common/') || return 0; + $zip->addFile("$outdir/java/XposedBridge.jar", 'common/XposedBridge.jar') || return 0; + # TODO: We probably need different files for older releases + $zip->addTree($Bin . '/zipstatic/_all/', '') == AZ_OK || return 0; + $zip->addTree($Bin . '/zipstatic/bundle/', '') == AZ_OK || return 0; + + # Set last modification time to "now" + my $now = time(); + foreach my $member($zip->members()) { + $member->setLastModFileDateTimeFromUnix($now); + } + + # Write the ZIP file to disk + my ($version, $suffix) = Xposed::get_version_for_filename(); + my $zipname; + if ($version =~ m/^\d+\./) { + $zipname = sprintf('xposed-v%.1f-sdk%d%s.zip', $version, $sdk, $suffix); + } else { + $zipname = sprintf('xposed-v%d-sdk%d%s.zip', $version, $sdk, $suffix); + } + my $zippath = Xposed::get_bundle_dir($sdk) . '/' . $zipname; + print "$zippath\n"; + $zip->writeToFileNamed($zippath) == AZ_OK || return 0; + + Xposed::sign_zip($zippath); + Xposed::gpg_sign($zippath, $opts{'r'}); + + # Create a symlink in a version-specific directory for easier collection + my $versiondir = Xposed::get_version_dir(); + my $versionlink = $versiondir . '/' . $zipname; + make_path($versiondir); + unlink($versionlink); + if (!symlink($zippath, $versionlink)) { + print_error("Could not create link $versionlink -> $zippath: $!"); + } + + print "\n\n"; + print_status('Bundle ZIP Done!', 0); + + return 1; +} + +# Create a flashable ZIP file with the compiled and some static files +sub uninstaller_zip() { + + print_status("Creating uninstaller ZIP file...", 1); + + # Create a new ZIP file + my $zip = Archive::Zip->new(); + my $outdir = $Xposed::cfg->val('General', 'outdir'); + $zip->addTree($Bin . '/zipstatic/_uninstaller/', '') == AZ_OK || return 0; + + # Set last modification time to "now" + my $now = time(); + foreach my $member($zip->members()) { + $member->setLastModFileDateTimeFromUnix($now); + } + + # Write the ZIP file to disk + my ($version, $suffix) = Xposed::get_version_for_filename(); + my $zipname = sprintf('xposed-uninstaller%s.zip', $suffix); + my $zippath = $outdir . '/' . $zipname; + print "$zippath\n"; + $zip->writeToFileNamed($zippath) == AZ_OK || return 0; + + Xposed::sign_zip($zippath); + Xposed::gpg_sign($zippath, $opts{'r'}); + + return 1; +} + # Build XposedBridge.jar sub build_java() { print_status('Building the Java part...', 0); diff --git a/zipstatic/_all/META-INF/com/google/android/flash-script.sh b/zipstatic/_all/META-INF/com/google/android/flash-script.sh deleted file mode 100644 index 3cce8a0..0000000 --- a/zipstatic/_all/META-INF/com/google/android/flash-script.sh +++ /dev/null @@ -1,192 +0,0 @@ -########################################################################################## -# -# Xposed framework installer zip. -# -# This script installs the Xposed framework files to the system partition. -# The Xposed Installer app is needed as well to manage the installed modules. -# -########################################################################################## - -grep_prop() { - REGEX="s/^$1=//p" - shift - FILES=$@ - if [ -z "$FILES" ]; then - FILES='/system/build.prop' - fi - cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1 -} - -android_version() { - case $1 in - 15) echo '4.0 / SDK'$1;; - 16) echo '4.1 / SDK'$1;; - 17) echo '4.2 / SDK'$1;; - 18) echo '4.3 / SDK'$1;; - 19) echo '4.4 / SDK'$1;; - 21) echo '5.0 / SDK'$1;; - 22) echo '5.1 / SDK'$1;; - 23) echo '6.0 / SDK'$1;; - *) echo 'SDK'$1;; - esac -} - -cp_perm() { - cp -f $1 $2 || exit 1 - set_perm $2 $3 $4 $5 $6 -} - -set_perm() { - chown $2:$3 $1 || exit 1 - chmod $4 $1 || exit 1 - if [ "$5" ]; then - chcon $5 $1 2>/dev/null - else - chcon 'u:object_r:system_file:s0' $1 2>/dev/null - fi -} - -install_nobackup() { - cp_perm ./$1 $1 $2 $3 $4 $5 -} - -install_and_link() { - TARGET=$1 - XPOSED="${1}_xposed" - BACKUP="${1}_original" - if [ ! -f ./$XPOSED ]; then - return - fi - cp_perm ./$XPOSED $XPOSED $2 $3 $4 $5 - if [ ! -f $BACKUP ]; then - mv $TARGET $BACKUP || exit 1 - ln -s $XPOSED $TARGET || exit 1 - chcon -h 'u:object_r:system_file:s0' $TARGET 2>/dev/null - fi -} - -install_overwrite() { - TARGET=$1 - if [ ! -f ./$TARGET ]; then - return - fi - BACKUP="${1}.orig" - NO_ORIG="${1}.no_orig" - if [ ! -f $TARGET ]; then - touch $NO_ORIG || exit 1 - set_perm $NO_ORIG 0 0 600 - elif [ -f $BACKUP ]; then - rm -f $TARGET - gzip $BACKUP || exit 1 - set_perm "${BACKUP}.gz" 0 0 600 - elif [ ! -f "${BACKUP}.gz" -a ! -f $NO_ORIG ]; then - mv $TARGET $BACKUP || exit 1 - gzip $BACKUP || exit 1 - set_perm "${BACKUP}.gz" 0 0 600 - fi - cp_perm ./$TARGET $TARGET $2 $3 $4 $5 -} - -########################################################################################## - -echo "******************************" -echo "Xposed framework installer zip" -echo "******************************" - -if [ ! -f "system/xposed.prop" ]; then - echo "! Failed: Extracted file system/xposed.prop not found!" - exit 1 -fi - -echo "- Mounting /system and /vendor read-write" -mount /system >/dev/null 2>&1 -mount /vendor >/dev/null 2>&1 -mount -o remount,rw /system -mount -o remount,rw /vendor >/dev/null 2>&1 -if [ ! -f '/system/build.prop' ]; then - echo "! Failed: /system could not be mounted!" - exit 1 -fi - -echo "- Checking environment" -API=$(grep_prop ro.build.version.sdk) -APINAME=$(android_version $API) -ABI=$(grep_prop ro.product.cpu.abi | cut -c-3) -ABI2=$(grep_prop ro.product.cpu.abi2 | cut -c-3) -ABILONG=$(grep_prop ro.product.cpu.abi) - -XVERSION=$(grep_prop version system/xposed.prop) -XARCH=$(grep_prop arch system/xposed.prop) -XMINSDK=$(grep_prop minsdk system/xposed.prop) -XMAXSDK=$(grep_prop maxsdk system/xposed.prop) - -XEXPECTEDSDK=$(android_version $XMINSDK) -if [ "$XMINSDK" != "$XMAXSDK" ]; then - XEXPECTEDSDK=$XEXPECTEDSDK' - '$(android_version $XMAXSDK) -fi - -ARCH=arm -IS64BIT= -if [ "$ABI" = "x86" ]; then ARCH=x86; fi; -if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; -if [ "$API" -ge "21" ]; then - if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=1; fi; - if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=1; fi; -fi - -# echo "DBG [$API] [$ABI] [$ABI2] [$ABILONG] [$ARCH] [$XARCH] [$XMINSDK] [$XMAXSDK] [$XVERSION]" - -echo " Xposed version: $XVERSION" - -XVALID= -if [ "$ARCH" = "$XARCH" ]; then - if [ "$API" -ge "$XMINSDK" ]; then - if [ "$API" -le "$XMAXSDK" ]; then - XVALID=1 - else - echo "! Wrong Android version: $APINAME" - echo "! This file is for: $XEXPECTEDSDK" - fi - else - echo "! Wrong Android version: $APINAME" - echo "! This file is for: $XEXPECTEDSDK" - fi -else - echo "! Wrong platform: $ARCH" - echo "! This file is for: $XARCH" -fi - -if [ -z $XVALID ]; then - echo "! Please download the correct package" - echo "! for your platform/ROM!" - exit 1 -fi - -echo "- Placing files" -install_nobackup /system/xposed.prop 0 0 0644 -install_nobackup /system/framework/XposedBridge.jar 0 0 0644 - -install_and_link /system/bin/app_process32 0 2000 0755 u:object_r:zygote_exec:s0 -install_overwrite /system/bin/dex2oat 0 2000 0755 u:object_r:dex2oat_exec:s0 -install_overwrite /system/bin/oatdump 0 2000 0755 -install_overwrite /system/bin/patchoat 0 2000 0755 u:object_r:dex2oat_exec:s0 -install_overwrite /system/lib/libart.so 0 0 0644 -install_overwrite /system/lib/libart-compiler.so 0 0 0644 -install_overwrite /system/lib/libart-disassembler.so 0 0 0644 -install_overwrite /system/lib/libsigchain.so 0 0 0644 -install_nobackup /system/lib/libxposed_art.so 0 0 0644 -if [ $IS64BIT ]; then - install_and_link /system/bin/app_process64 0 2000 0755 u:object_r:zygote_exec:s0 - install_overwrite /system/lib64/libart.so 0 0 0644 - install_overwrite /system/lib64/libart-compiler.so 0 0 0644 - install_overwrite /system/lib64/libart-disassembler.so 0 0 0644 - install_overwrite /system/lib64/libsigchain.so 0 0 0644 - install_overwrite /system/lib64/libxposed_art.so 0 0 0644 -fi - -if [ "$API" -ge "22" ]; then - find /system /vendor -type f -name '*.odex.gz' 2>/dev/null | while read f; do mv "$f" "$f.xposed"; done -fi - -echo "- Done" -exit 0 diff --git a/zipstatic/_all/META-INF/com/google/android/updater-script b/zipstatic/_all/META-INF/com/google/android/updater-script index 4086a0b..67d2902 100644 --- a/zipstatic/_all/META-INF/com/google/android/updater-script +++ b/zipstatic/_all/META-INF/com/google/android/updater-script @@ -1 +1 @@ -# this is a dummy file, the magic is in update-binary and flash-script.sh \ No newline at end of file +# this is a dummy file, the magic is in update-binary \ No newline at end of file diff --git a/zipstatic/_all/common/00xposed b/zipstatic/_all/common/00xposed new file mode 100644 index 0000000..f0b9057 --- /dev/null +++ b/zipstatic/_all/common/00xposed @@ -0,0 +1,55 @@ +#!/system/bin/sh + +XPOSEDPATH=/su/xposed +DISABLEPATH=/data/data/de.robv.android.xposed.installer/conf/disabled + +log_xposed() { + echo $1 + log -p i -t Xposed "Mount: $1" +} + +bind_mount() { + if [ -f "$XPOSEDPATH$1" ]; then + mount -o bind $XPOSEDPATH/$1 $1 + if [ "$?" -eq "0" ]; then log_xposed "$XPOSEDPATH$1 -> $1"; + else log_xposed "$1 bind mount failed!"; exit 1; fi + fi +} + +bind_mount_app_process() { + if [ ! -f "$DISABLEPATH" ]; then + if [ -f "$XPOSEDPATH$1_xposed" ]; then + mount -o bind $XPOSEDPATH$1_xposed $1 + if [ "$?" -eq "0" ]; then log_xposed "$XPOSEDPATH$1_xposed -> $1"; + else log_xposed "$1 bind mount failed!"; exit 1; fi + fi + fi +} + +# Handle /cache merged Xposed +if [ -d /su/xposed_cache ]; then + rm -rf /su/xposed + mv /su/xposed_cache /su/xposed +fi + +# Make sure things got correct SELinux contexts +chcon u:object_r:zygote_exec:s0 $XPOSEDPATH/system/bin/app_process32_xposed +chcon u:object_r:zygote_exec:s0 $XPOSEDPATH/system/bin/app_process64_xposed +chcon u:object_r:dex2oat_exec:s0 $XPOSEDPATH/system/bin/dex2oat +chcon u:object_r:dex2oat_exec:s0 $XPOSEDPATH/system/bin/patchoat + +# Bind mount start + +log_xposed "Bind mount start" + +bind_mount_app_process /system/bin/app_process32 +bind_mount_app_process /system/bin/app_process64 +bind_mount /system/bin/dex2oat +bind_mount /system/bin/oatdump +bind_mount /system/bin/patchoat +bind_mount /system/lib/libart.so +bind_mount /system/lib/libart-compiler.so +bind_mount /system/lib/libsigchain.so +bind_mount /system/lib64/libart.so +bind_mount /system/lib64/libart-disassembler.so +bind_mount /system/lib64/libsigchain.so diff --git a/zipstatic/_all/common/file_contexts_image b/zipstatic/_all/common/file_contexts_image new file mode 100644 index 0000000..1fdc6aa --- /dev/null +++ b/zipstatic/_all/common/file_contexts_image @@ -0,0 +1 @@ +/su(/.*)? u:object_r:system_file:s0 diff --git a/zipstatic/_uninstaller/META-INF/com/google/android/flash-script.sh b/zipstatic/_uninstaller/META-INF/com/google/android/flash-script.sh deleted file mode 100644 index f15ab16..0000000 --- a/zipstatic/_uninstaller/META-INF/com/google/android/flash-script.sh +++ /dev/null @@ -1,130 +0,0 @@ -########################################################################################## -# -# Xposed framework uninstaller zip. -# -# This script removes the Xposed framework files from the system partition. -# It doesn't touch the Xposed Installer app. -# -########################################################################################## - -grep_prop() { - REGEX="s/^$1=//p" - shift - FILES=$@ - if [ -z "$FILES" ]; then - FILES='/system/build.prop' - fi - cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1 -} - -mv_perm() { - mv -f $1 $2 || exit 1 - set_perm $2 $3 $4 $5 $6 -} - -set_perm() { - chown $2:$3 $1 || exit 1 - chmod $4 $1 || exit 1 - if [ "$5" ]; then - chcon $5 $1 2>/dev/null - else - chcon 'u:object_r:system_file:s0' $1 2>/dev/null - fi -} - -restore_link() { - TARGET=$1 - XPOSED="${1}_xposed" - BACKUP="${1}_original" - # Don't touch $TARGET if the link was created by something else (e.g. SuperSU) - if [ -f $BACKUP -a -L $TARGET -a "$(readlink $TARGET)" = $XPOSED ]; then - rm -f $TARGET - mv_perm $BACKUP $TARGET $2 $3 $4 $5 - fi - rm -f $XPOSED -} - -restore_backup() { - TARGET=$1 - BACKUP="${1}.orig" - NO_ORIG="${1}.no_orig" - if [ -f $BACKUP ]; then - mv_perm $BACKUP $TARGET $2 $3 $4 $5 - rm -f $NO_ORIG - elif [ -f "${BACKUP}.gz" ]; then - rm -f $TARGET $NO_ORIG - gunzip "${BACKUP}.gz" - mv_perm $BACKUP $TARGET $2 $3 $4 $5 - elif [ -f $NO_ORIG ]; then - rm -f $TARGET $NO_ORIG - fi -} - -########################################################################################## - -echo "********************************" -echo "Xposed framework uninstaller zip" -echo "********************************" - -echo "- Mounting /system and /vendor read-write" -mount /system >/dev/null 2>&1 -mount /vendor >/dev/null 2>&1 -mount -o remount,rw /system -mount -o remount,rw /vendor >/dev/null 2>&1 -if [ ! -f '/system/build.prop' ]; then - echo "! Failed: /system could not be mounted!" - exit 1 -fi - -echo "- Checking environment" -API=$(grep_prop ro.build.version.sdk) -ABI=$(grep_prop ro.product.cpu.abi | cut -c-3) -ABI2=$(grep_prop ro.product.cpu.abi2 | cut -c-3) -ABILONG=$(grep_prop ro.product.cpu.abi) - -ARCH=arm -IS64BIT= -if [ "$ABI" = "x86" ]; then ARCH=x86; fi; -if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; -if [ "$API" -ge "21" ]; then - if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=1; fi; - if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=1; fi; -else - echo "! This script doesn't work for SDK < 21 (yet)" - exit 1 -fi - -# echo "DBG [$API] [$ABI] [$ABI2] [$ABILONG] [$ARCH]" - -echo "- Restoring/removing files" -rm -f /system/xposed.prop -rm -f /system/framework/XposedBridge.jar - -restore_link /system/bin/app_process32 0 2000 0755 u:object_r:zygote_exec:s0 -restore_backup /system/bin/dex2oat 0 2000 0755 u:object_r:dex2oat_exec:s0 -restore_backup /system/bin/oatdump 0 2000 0755 -restore_backup /system/bin/patchoat 0 2000 0755 u:object_r:dex2oat_exec:s0 -restore_backup /system/lib/libart.so 0 0 0644 -restore_backup /system/lib/libart-compiler.so 0 0 0644 -restore_backup /system/lib/libart-disassembler.so 0 0 0644 -restore_backup /system/lib/libsigchain.so 0 0 0644 -restore_backup /system/lib/libxposed_art.so 0 0 0644 -if [ $IS64BIT ]; then - restore_link /system/bin/app_process64 0 2000 0755 u:object_r:zygote_exec:s0 - restore_backup /system/lib64/libart.so 0 0 0644 - restore_backup /system/lib64/libart-compiler.so 0 0 0644 - restore_backup /system/lib64/libart-disassembler.so 0 0 0644 - restore_backup /system/lib64/libsigchain.so 0 0 0644 - restore_backup /system/lib64/libxposed_art.so 0 0 0644 -fi - -if [ "$API" -ge "22" ]; then - find /system /vendor -type f -name '*.odex.gz.xposed' 2>/dev/null | while read f; do mv "$f" "${f%.xposed}"; done -fi - -echo "- Done" -echo -echo "It's recommended that you wipe the" -echo "Dalvik cache now." - -exit 0 diff --git a/zipstatic/_uninstaller/META-INF/com/google/android/update-binary b/zipstatic/_uninstaller/META-INF/com/google/android/update-binary new file mode 100644 index 0000000..00acadc --- /dev/null +++ b/zipstatic/_uninstaller/META-INF/com/google/android/update-binary @@ -0,0 +1,288 @@ +#!/sbin/sh +########################################################################################## +# +# Xposed framework uninstaller zip. +# +# This script removes the Xposed framework files. +# It doesn't touch the Xposed Installer app. +# +########################################################################################## + +########################################################################################## +# Flashable update-binary preparation +########################################################################################## + +OUTFD=$2 +ZIP=$3 + +readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null +if [ "$?" -eq "0" ]; then + OUTFD=0 + + for FD in `ls /proc/$$/fd`; do + readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null + if [ "$?" -eq "0" ]; then + ps | grep " 3 $FD " | grep -v grep >/dev/null + if [ "$?" -eq "0" ]; then + OUTFD=$FD + break + fi + fi + done +fi + +rm -rf /tmp/xposed 2>/dev/null +mkdir /tmp/xposed +cd /tmp/xposed +unzip -o "$ZIP" +INSTALLER=/tmp/xposed + +########################################################################################## +# Functions +########################################################################################## + +ui_print() { + echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD + echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD +} + +is_mounted() { + if [ ! -z "$2" ]; then + cat /proc/mounts | grep $1 | grep $2, >/dev/null + else + cat /proc/mounts | grep $1 >/dev/null + fi + return $? +} + +prepare_systemless() { + VALID= + + # Check system installed Xposed + if [ -f /system/xposed.prop ]; then + VALID=false + ui_print "- System Installed Xposed detected!" + return + fi + + # Start systemless preparation + # Make sure su is not mounted to random images and /su exists + umount /su 2>/dev/null + mkdir /su 2>/dev/null + + SUIMG= + + if (is_mounted /data); then + SUIMG=/data/su.img + if [ -f $SUIMG ]; then + ui_print "- $SUIMG detected!" + else + ui_print "! $SUIMG not found!" + ui_print "! No Xposed Installed!" + exit 1 + fi + else + SUIMG=/cache/su.img + if [ -f $SUIMG ]; then + ui_print "- $SUIMG detected!" + else + ui_print "- Creating $SUIMG" + make_ext4fs -l 32M -a /su -S $INSTALLER/common/file_contexts_image $SUIMG + fi + fi + + VALID=true + + ui_print "- Mounting $SUIMG to /su" + LOOPDEVICE= + for LOOP in 0 1 2 3 4 5 6 7; do + if (! is_mounted /su); then + LOOPDEVICE=/dev/block/loop$LOOP + if [ ! -f "$LOOPDEVICE" ]; then + mknod $LOOPDEVICE b 7 $LOOP + fi + losetup $LOOPDEVICE $SUIMG + if [ "$?" -eq "0" ]; then + mount -t ext4 -o loop $LOOPDEVICE /su + if (! is_mounted /su); then + /system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE /su + fi + if (! is_mounted /su); then + /system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE /su + fi + fi + if (is_mounted /su); then + break; + fi + fi + done + + mkdir /su/su.d 2> /dev/null +} + +grep_prop() { + REGEX="s/^$1=//p" + shift + FILES=$@ + if [ -z "$FILES" ]; then + FILES='/system/build.prop' + fi + cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1 +} + +android_version() { + case $1 in + 15) echo '4.0 / SDK'$1;; + 16) echo '4.1 / SDK'$1;; + 17) echo '4.2 / SDK'$1;; + 18) echo '4.3 / SDK'$1;; + 19) echo '4.4 / SDK'$1;; + 21) echo '5.0 / SDK'$1;; + 22) echo '5.1 / SDK'$1;; + 23) echo '6.0 / SDK'$1;; + *) echo 'SDK'$1;; + esac +} + +mv_perm() { + mv -f $1 $2 || exit 1 + set_perm $2 $3 $4 $5 $6 +} + +set_perm() { + chown $2:$3 $1 || exit 1 + chmod $4 $1 || exit 1 + if [ "$5" ]; then + chcon $5 $1 2>/dev/null + else + chcon 'u:object_r:system_file:s0' $1 2>/dev/null + fi +} + +restore_link() { + TARGET=$1 + XPOSED="${1}_xposed" + BACKUP="${1}_original" + # Don't touch $TARGET if the link was created by something else (e.g. SuperSU) + if [ -f $BACKUP -a -L $TARGET -a "$(readlink $TARGET)" = $XPOSED ]; then + rm -f $TARGET + mv_perm $BACKUP $TARGET $2 $3 $4 $5 + fi + rm -f $XPOSED +} + +restore_backup() { + TARGET=$1 + BACKUP="${1}.orig" + NO_ORIG="${1}.no_orig" + if [ -f $BACKUP ]; then + mv_perm $BACKUP $TARGET $2 $3 $4 $5 + rm -f $NO_ORIG + elif [ -f "${BACKUP}.gz" ]; then + rm -f $TARGET $NO_ORIG + gunzip "${BACKUP}.gz" + mv_perm $BACKUP $TARGET $2 $3 $4 $5 + elif [ -f $NO_ORIG ]; then + rm -f $TARGET $NO_ORIG + fi +} + +########################################################################################## +# Start +########################################################################################## + +ui_print "********************************" +ui_print "Xposed framework uninstaller zip" +ui_print "********************************" + +if [ ! -d "$INSTALLER/common" ]; then + ui_print "! Failed: Unable to extract zip file!" + exit 1 +fi + +ui_print "- Mounting /system(ro), /cache, /data" +mount -o ro /system 2>/dev/null +mount /cache 2>/dev/null +mount /data 2>/dev/null + +if [ ! -f '/system/build.prop' ]; then + ui_print "! Failed: /system could not be mounted!" + exit 1 +fi + +API=$(grep_prop ro.build.version.sdk) +APINAME=$(android_version $API) +ABI=$(grep_prop ro.product.cpu.abi | cut -c-3) +ABI2=$(grep_prop ro.product.cpu.abi2 | cut -c-3) +ABILONG=$(grep_prop ro.product.cpu.abi) + +ARCH=arm +IS64BIT= +if [ "$ABI" = "x86" ]; then ARCH=x86; fi; +if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; +if [ "$API" -ge "21" ]; then + if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=1; fi; + if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=1; fi; +else + ui_print "! This script doesn't work for SDK < 21 (yet)" + exit 1 +fi + +prepare_systemless + +SYSTEMLESS=$VALID + +if [ "$SYSTEMLESS" = "true" ]; then + ui_print "- Remove systemless Xposed" +else + ui_print "- Remove system Xposed" + ui_print "- Re-mounting /system to rw" + mount -o rw,remount /system +fi + +########################################################################################## +# Detection all done, start uninstalling +########################################################################################## + +ui_print "- Uninstalling/restoring files" + +if [ "$SYSTEMLESS" = "true" ]; then + if [ -d /su/xposed ]; then + rm -rf /su/xposed + rm -f /su/su.d/00xposed + else + # Cache workaround + cp $INSTALLER/common/00uninstall /su/su.d/00uninstall + chmod 755 /su/su.d/00uninstall + fi +else + rm -f /system/xposed.prop + rm -f /system/framework/XposedBridge.jar + + restore_link /system/bin/app_process32 0 2000 0755 u:object_r:zygote_exec:s0 + restore_backup /system/bin/dex2oat 0 2000 0755 u:object_r:dex2oat_exec:s0 + restore_backup /system/bin/oatdump 0 2000 0755 + restore_backup /system/bin/patchoat 0 2000 0755 u:object_r:dex2oat_exec:s0 + restore_backup /system/lib/libart.so 0 0 0644 + restore_backup /system/lib/libart-compiler.so 0 0 0644 + restore_backup /system/lib/libart-disassembler.so 0 0 0644 + restore_backup /system/lib/libsigchain.so 0 0 0644 + restore_backup /system/lib/libxposed_art.so 0 0 0644 + if [ $IS64BIT ]; then + restore_link /system/bin/app_process64 0 2000 0755 u:object_r:zygote_exec:s0 + restore_backup /system/lib64/libart.so 0 0 0644 + restore_backup /system/lib64/libart-compiler.so 0 0 0644 + restore_backup /system/lib64/libart-disassembler.so 0 0 0644 + restore_backup /system/lib64/libsigchain.so 0 0 0644 + restore_backup /system/lib64/libxposed_art.so 0 0 0644 + fi + if [ "$API" -ge "22" ]; then + find /system /vendor -type f -name '*.odex.gz.xposed' 2>/dev/null | while read f; do mv "$f" "${f%.xposed}"; done + fi +fi + +umount /su 2>/dev/null +umount /system + +ui_print "- Done" +exit 0 diff --git a/zipstatic/_uninstaller/common/00uninstall b/zipstatic/_uninstaller/common/00uninstall new file mode 100644 index 0000000..92e661c --- /dev/null +++ b/zipstatic/_uninstaller/common/00uninstall @@ -0,0 +1,5 @@ +#!/system/bin/sh + +rm -rf /su/xposed +rm -rf /su/su.d/00xposed +rm -rf /su/su.d/00uninstall diff --git a/zipstatic/_uninstaller/common/file_contexts_image b/zipstatic/_uninstaller/common/file_contexts_image new file mode 100644 index 0000000..1fdc6aa --- /dev/null +++ b/zipstatic/_uninstaller/common/file_contexts_image @@ -0,0 +1 @@ +/su(/.*)? u:object_r:system_file:s0 diff --git a/zipstatic/arm/META-INF/com/google/android/update-binary b/zipstatic/arm/META-INF/com/google/android/update-binary deleted file mode 100644 index e24b68e..0000000 Binary files a/zipstatic/arm/META-INF/com/google/android/update-binary and /dev/null differ diff --git a/zipstatic/arm64 b/zipstatic/arm64 deleted file mode 120000 index 78504ba..0000000 --- a/zipstatic/arm64 +++ /dev/null @@ -1 +0,0 @@ -arm \ No newline at end of file diff --git a/zipstatic/armv5/META-INF/com/google/android/update-binary b/zipstatic/armv5/META-INF/com/google/android/update-binary deleted file mode 100644 index 67cf96b..0000000 Binary files a/zipstatic/armv5/META-INF/com/google/android/update-binary and /dev/null differ diff --git a/zipstatic/bundle/META-INF/com/google/android/update-binary b/zipstatic/bundle/META-INF/com/google/android/update-binary new file mode 100644 index 0000000..65c071e --- /dev/null +++ b/zipstatic/bundle/META-INF/com/google/android/update-binary @@ -0,0 +1,394 @@ +#!/sbin/sh +########################################################################################## +# +# Xposed framework installer zip. +# +# This script installs the Xposed framework files to xposed.img +# The Xposed Installer app is needed as well to manage the installed modules. +# +########################################################################################## + +########################################################################################## +# Flashable update-binary preparation +########################################################################################## + +OUTFD=$2 +ZIP=$3 + +readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null +if [ "$?" -eq "0" ]; then + OUTFD=0 + + for FD in `ls /proc/$$/fd`; do + readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null + if [ "$?" -eq "0" ]; then + ps | grep " 3 $FD " | grep -v grep >/dev/null + if [ "$?" -eq "0" ]; then + OUTFD=$FD + break + fi + fi + done +fi + +rm -rf /tmp/xposed 2>/dev/null +mkdir /tmp/xposed +cd /tmp/xposed +unzip -o "$ZIP" +INSTALLER=/tmp/xposed + +########################################################################################## +# Functions +########################################################################################## + +getvar() { + local VARNAME=$1 + local VALUE=$(eval echo \$"$VARNAME"); + for FILE in /data/.xposed /cache/.xposed /system/.xposed; do + if [ -z "$VALUE" ]; then + LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=") + if [ ! -z "$LINE" ]; then + VALUE=${LINE#*=} + fi + fi + done + eval $VARNAME=\$VALUE +} + +ui_print() { + echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD + echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD +} + +is_mounted() { + if [ ! -z "$2" ]; then + cat /proc/mounts | grep $1 | grep $2, >/dev/null + else + cat /proc/mounts | grep $1 >/dev/null + fi + return $? +} + +prepare_systemless() { + VALID= + + # Check user config + if [ "$SYSTEMLESS" == "false" ]; then + VALID=false + return + fi + + # Check Android version + if [ "$API" -lt "23" ]; then + VALID=false + ui_print "! Systemless not supported in $APINAME" + return + fi + + # Check system installed SuperSU + SUPERSU_CHECK=$(cat /system/xbin/su | grep SuperSU) + if [ $? -eq 0 ]; then + VALID=false + ui_print "! System installed SuperSU detected!" + return + fi + + # Start systemless preparation + # Make sure su is not mounted to random images and /su exists + umount /su 2>/dev/null + mkdir /su 2>/dev/null + + SUIMG= + XPATH= + + if (is_mounted /data); then + SUIMG=/data/su.img + XPATH=/su/xposed + if [ -f $SUIMG ]; then + ui_print "- $SUIMG detected!" + else + ui_print "! Unable to find systemless SuperSU!" + VALID=false + return + fi + else + SUIMG=/cache/su.img + XPATH=/su/xposed_cache + ui_print " " + ui_print "***********************************" + ui_print "* !! Data unavalible !! *" + ui_print "* SuperSU detection is impossible *" + ui_print "* Will attempt to use systemless. *" + ui_print "* Installation will still proceed *" + ui_print "* But please make sure you have *" + ui_print "* SuperSU 2.76+ installed!! *" + ui_print "***********************************" + ui_print " " + if [ -f $SUIMG ]; then + ui_print "- $SUIMG detected!" + else + ui_print "- Creating $SUIMG" + make_ext4fs -l 32M -a /su -S $INSTALLER/common/file_contexts_image $SUIMG + fi + fi + + VALID=true + + ui_print "- Mounting $SUIMG to /su" + LOOPDEVICE= + for LOOP in 0 1 2 3 4 5 6 7; do + if (! is_mounted /su); then + LOOPDEVICE=/dev/block/loop$LOOP + if [ ! -f "$LOOPDEVICE" ]; then + mknod $LOOPDEVICE b 7 $LOOP + fi + losetup $LOOPDEVICE $SUIMG + if [ "$?" -eq "0" ]; then + mount -t ext4 -o loop $LOOPDEVICE /su + if (! is_mounted /su); then + /system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE /su + fi + if (! is_mounted /su); then + /system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE /su + fi + fi + if (is_mounted /su); then + break; + fi + fi + done + + # Check SuperSU version > 2.76 + if [ -d "/su/bin" ]; then + SU_VERSION=$(/su/bin/su -v) + VERSION=${SU_VERSION%:*} + RESULT=$(awk -v C=$VERSION -v M=2.76 'BEGIN {if (C >= M) printf("true"); else printf("false");}') + if [ "$RESULT" = "false" ]; then + ui_print "! Installed SuperSU: $VERSION < 2.76" + ui_print "! Minumum requirement is SuperSU 2.76!!" + ui_print "aborting..." + exit 1 + else + ui_print "- Installed SuperSU: $VERSION >= 2.76 ...supported!" + fi + fi + + rm -rf $XPATH 2> /dev/null + mkdir /su/su.d 2> /dev/null + mkdir $XPATH + mkdir $XPATH/system + mkdir $XPATH/system/bin + mkdir $XPATH/system/framework + mkdir $XPATH/system/lib + if [ $IS64BIT ]; then + mkdir $XPATH/system/lib64 + fi +} + +grep_prop() { + REGEX="s/^$1=//p" + shift + FILES=$@ + if [ -z "$FILES" ]; then + FILES='/system/build.prop' + fi + cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1 +} + +android_version() { + case $1 in + 15) echo '4.0 / SDK'$1;; + 16) echo '4.1 / SDK'$1;; + 17) echo '4.2 / SDK'$1;; + 18) echo '4.3 / SDK'$1;; + 19) echo '4.4 / SDK'$1;; + 21) echo '5.0 / SDK'$1;; + 22) echo '5.1 / SDK'$1;; + 23) echo '6.0 / SDK'$1;; + *) echo 'SDK'$1;; + esac +} + +cp_perm() { + cp -f $1 $2 || exit 1 + set_perm $2 $3 $4 $5 $6 +} + +set_perm() { + chown $2:$3 $1 || exit 1 + chmod $4 $1 || exit 1 + if [ "$5" ]; then + chcon $5 $1 2>/dev/null + else + chcon 'u:object_r:system_file:s0' $1 2>/dev/null + fi +} + +install_nobackup() { + cp_perm $INSTALLER/$ARCH$1 $XPATH$1 $2 $3 $4 $5 +} + +install_and_link() { + TARGET=$1 + XPOSED="${1}_xposed" + BACKUP="${1}_original" + if [ ! -f $INSTALLER/$ARCH$XPOSED ]; then + return + fi + install_nobackup $XPOSED $2 $3 $4 $5 + if [ "$SYSTEMLESS" = "false" ]; then + if [ ! -f $BACKUP ]; then + mv $TARGET $BACKUP || exit 1 + ln -s $XPOSED $TARGET || exit 1 + chcon -h 'u:object_r:system_file:s0' $TARGET 2>/dev/null + fi + fi +} + +install_overwrite() { + TARGET=$1 + if [ ! -f $INSTALLER/$ARCH$TARGET ]; then + return + fi + BACKUP="${1}.orig" + NO_ORIG="${1}.no_orig" + if [ "$SYSTEMLESS" = "false" ]; then + if [ ! -f $TARGET ]; then + touch $NO_ORIG || exit 1 + set_perm $NO_ORIG 0 0 600 + elif [ -f $BACKUP ]; then + rm -f $TARGET + gzip $BACKUP || exit 1 + set_perm "${BACKUP}.gz" 0 0 600 + elif [ ! -f "${BACKUP}.gz" -a ! -f $NO_ORIG ]; then + mv $TARGET $BACKUP || exit 1 + gzip $BACKUP || exit 1 + set_perm "${BACKUP}.gz" 0 0 600 + fi + fi + install_nobackup $TARGET $2 $3 $4 $5 +} + +########################################################################################## +# Start +########################################################################################## + +ui_print "******************************" +ui_print "Xposed framework installer zip" +ui_print "******************************" + +if [ ! -d "$INSTALLER/common" ]; then + ui_print "! Failed: Unable to extract zip file!" + exit 1 +fi + +ui_print "- Mounting /system(ro), /cache, /data" +mount -o ro /system 2>/dev/null +mount /cache 2>/dev/null +mount /data 2>/dev/null + +if [ ! -f '/system/build.prop' ]; then + ui_print "! Failed: /system could not be mounted!" + exit 1 +fi + +API=$(grep_prop ro.build.version.sdk) +APINAME=$(android_version $API) +ABI=$(grep_prop ro.product.cpu.abi | cut -c-3) +ABI2=$(grep_prop ro.product.cpu.abi2 | cut -c-3) +ABILONG=$(grep_prop ro.product.cpu.abi) + +ARCH=arm +IS64BIT= +if [ "$ABI" = "x86" ]; then ARCH=x86; fi; +if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; +if [ "$API" -ge "21" ]; then + if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=1; fi; + if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=1; fi; +fi + +XVERSION=$(grep_prop version $ARCH/system/xposed.prop) +XMINSDK=$(grep_prop minsdk $ARCH/system/xposed.prop) +XMAXSDK=$(grep_prop maxsdk $ARCH/system/xposed.prop) + +XEXPECTEDSDK=$(android_version $XMINSDK) +if [ "$XMINSDK" != "$XMAXSDK" ]; then + XEXPECTEDSDK=$XEXPECTEDSDK' - '$(android_version $XMAXSDK) +fi + +ui_print "- Xposed version: $XVERSION" +ui_print "- Device platform: $ARCH" + +XVALID= +if [ "$API" -ge "$XMINSDK" ]; then + if [ "$API" -le "$XMAXSDK" ]; then + XVALID=1 + else + ui_print "! Wrong Android version: $APINAME" + ui_print "! This file is for: $XEXPECTEDSDK" + fi +else + ui_print "! Wrong Android version: $APINAME" + ui_print "! This file is for: $XEXPECTEDSDK" +fi + +if [ -z $XVALID ]; then + ui_print "! Please download the correct package" + ui_print "! for your Android version!" + exit 1 +fi + +getvar SYSTEMLESS +prepare_systemless + +if [ "$SYSTEMLESS" = "true" -a "$VALID" = "false" ]; then + ui_print "! Config forces systemless install but requirements aren't met" + ui_print "aborting..." + exit 1 +fi + +SYSTEMLESS=$VALID + +if [ "$SYSTEMLESS" = "true" ]; then + ui_print "- Using systemless mode" +else + XPATH="" + ui_print "- Using system mode" + ui_print "- Re-mounting /system to rw" + mount -o rw,remount /system +fi + +########################################################################################## +# Detection all done, start installing +########################################################################################## + +ui_print "- Placing files" + +cp_perm $INSTALLER/common/XposedBridge.jar $XPATH/system/framework/XposedBridge.jar 0 0 0644 +if [ "$SYSTEMLESS" = "true" ]; then + cp_perm $INSTALLER/common/00xposed /su/su.d/00xposed 0 0 0755 +fi +install_nobackup /system/xposed.prop 0 0 0644 +install_and_link /system/bin/app_process32 0 2000 0755 u:object_r:zygote_exec:s0 +install_overwrite /system/bin/dex2oat 0 2000 0755 u:object_r:dex2oat_exec:s0 +install_overwrite /system/bin/oatdump 0 2000 0755 +install_overwrite /system/bin/patchoat 0 2000 0755 u:object_r:dex2oat_exec:s0 +install_overwrite /system/lib/libart.so 0 0 0644 +install_overwrite /system/lib/libart-compiler.so 0 0 0644 +install_overwrite /system/lib/libart-disassembler.so 0 0 0644 +install_overwrite /system/lib/libsigchain.so 0 0 0644 +install_nobackup /system/lib/libxposed_art.so 0 0 0644 +if [ $IS64BIT ]; then + install_and_link /system/bin/app_process64 0 2000 0755 u:object_r:zygote_exec:s0 + install_overwrite /system/lib64/libart.so 0 0 0644 + install_overwrite /system/lib64/libart-compiler.so 0 0 0644 + install_overwrite /system/lib64/libart-disassembler.so 0 0 0644 + install_overwrite /system/lib64/libsigchain.so 0 0 0644 + install_nobackup /system/lib64/libxposed_art.so 0 0 0644 +fi + +umount /su 2>/dev/null +umount /system + +ui_print "- Done" +exit 0 diff --git a/zipstatic/single/META-INF/com/google/android/update-binary b/zipstatic/single/META-INF/com/google/android/update-binary new file mode 100644 index 0000000..5017933 --- /dev/null +++ b/zipstatic/single/META-INF/com/google/android/update-binary @@ -0,0 +1,399 @@ +#!/sbin/sh +########################################################################################## +# +# Xposed framework installer zip. +# +# This script installs the Xposed framework files to xposed.img +# The Xposed Installer app is needed as well to manage the installed modules. +# +########################################################################################## + +########################################################################################## +# Flashable update-binary preparation +########################################################################################## + +OUTFD=$2 +ZIP=$3 + +readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null +if [ "$?" -eq "0" ]; then + OUTFD=0 + + for FD in `ls /proc/$$/fd`; do + readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null + if [ "$?" -eq "0" ]; then + ps | grep " 3 $FD " | grep -v grep >/dev/null + if [ "$?" -eq "0" ]; then + OUTFD=$FD + break + fi + fi + done +fi + +rm -rf /tmp/xposed 2>/dev/null +mkdir /tmp/xposed +cd /tmp/xposed +unzip -o "$ZIP" +INSTALLER=/tmp/xposed + +########################################################################################## +# Functions +########################################################################################## + +getvar() { + local VARNAME=$1 + local VALUE=$(eval echo \$"$VARNAME"); + for FILE in /data/.xposed /cache/.xposed /system/.xposed; do + if [ -z "$VALUE" ]; then + LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=") + if [ ! -z "$LINE" ]; then + VALUE=${LINE#*=} + fi + fi + done + eval $VARNAME=\$VALUE +} + +ui_print() { + echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD + echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD +} + +is_mounted() { + if [ ! -z "$2" ]; then + cat /proc/mounts | grep $1 | grep $2, >/dev/null + else + cat /proc/mounts | grep $1 >/dev/null + fi + return $? +} + +prepare_systemless() { + VALID= + + # Check user config + if [ "$SYSTEMLESS" == "false" ]; then + VALID=false + return + fi + + # Check Android version + if [ "$API" -lt "23" ]; then + VALID=false + ui_print "! Systemless not supported in $APINAME" + return + fi + + # Check system installed SuperSU + SUPERSU_CHECK=$(cat /system/xbin/su | grep SuperSU) + if [ $? -eq 0 ]; then + VALID=false + ui_print "! System installed SuperSU detected!" + return + fi + + # Start systemless preparation + # Make sure su is not mounted to random images and /su exists + umount /su 2>/dev/null + mkdir /su 2>/dev/null + + SUIMG= + XPATH= + + if (is_mounted /data); then + SUIMG=/data/su.img + XPATH=/su/xposed + if [ -f $SUIMG ]; then + ui_print "- $SUIMG detected!" + else + ui_print "! Unable to find systemless SuperSU!" + VALID=false + return + fi + else + SUIMG=/cache/su.img + XPATH=/su/xposed_cache + ui_print " " + ui_print "***********************************" + ui_print "* !! Data unavalible !! *" + ui_print "* SuperSU detection is impossible *" + ui_print "* Will attempt to use systemless. *" + ui_print "* Installation will still proceed *" + ui_print "* But please make sure you have *" + ui_print "* SuperSU 2.76+ installed!! *" + ui_print "***********************************" + ui_print " " + if [ -f $SUIMG ]; then + ui_print "- $SUIMG detected!" + else + ui_print "- Creating $SUIMG" + make_ext4fs -l 32M -a /su -S $INSTALLER/common/file_contexts_image $SUIMG + fi + fi + + VALID=true + + ui_print "- Mounting $SUIMG to /su" + LOOPDEVICE= + for LOOP in 0 1 2 3 4 5 6 7; do + if (! is_mounted /su); then + LOOPDEVICE=/dev/block/loop$LOOP + if [ ! -f "$LOOPDEVICE" ]; then + mknod $LOOPDEVICE b 7 $LOOP + fi + losetup $LOOPDEVICE $SUIMG + if [ "$?" -eq "0" ]; then + mount -t ext4 -o loop $LOOPDEVICE /su + if (! is_mounted /su); then + /system/bin/toolbox mount -t ext4 -o loop $LOOPDEVICE /su + fi + if (! is_mounted /su); then + /system/bin/toybox mount -t ext4 -o loop $LOOPDEVICE /su + fi + fi + if (is_mounted /su); then + break; + fi + fi + done + + # Check SuperSU version > 2.76 + if [ -d "/su/bin" ]; then + SU_VERSION=$(/su/bin/su -v) + VERSION=${SU_VERSION%:*} + RESULT=$(awk -v C=$VERSION -v M=2.76 'BEGIN {if (C >= M) printf("true"); else printf("false");}') + if [ "$RESULT" = "false" ]; then + ui_print "! Installed SuperSU: $VERSION < 2.76" + ui_print "! Minumum requirement is SuperSU 2.76!!" + ui_print "aborting..." + exit 1 + else + ui_print "- Installed SuperSU: $VERSION >= 2.76 ...supported!" + fi + fi + + rm -rf $XPATH 2> /dev/null + mkdir /su/su.d 2> /dev/null + mkdir $XPATH + mkdir $XPATH/system + mkdir $XPATH/system/bin + mkdir $XPATH/system/framework + mkdir $XPATH/system/lib + if [ $IS64BIT ]; then + mkdir $XPATH/system/lib64 + fi +} + +grep_prop() { + REGEX="s/^$1=//p" + shift + FILES=$@ + if [ -z "$FILES" ]; then + FILES='/system/build.prop' + fi + cat $FILES 2>/dev/null | sed -n $REGEX | head -n 1 +} + +android_version() { + case $1 in + 15) echo '4.0 / SDK'$1;; + 16) echo '4.1 / SDK'$1;; + 17) echo '4.2 / SDK'$1;; + 18) echo '4.3 / SDK'$1;; + 19) echo '4.4 / SDK'$1;; + 21) echo '5.0 / SDK'$1;; + 22) echo '5.1 / SDK'$1;; + 23) echo '6.0 / SDK'$1;; + *) echo 'SDK'$1;; + esac +} + +cp_perm() { + cp -f $1 $2 || exit 1 + set_perm $2 $3 $4 $5 $6 +} + +set_perm() { + chown $2:$3 $1 || exit 1 + chmod $4 $1 || exit 1 + if [ "$5" ]; then + chcon $5 $1 2>/dev/null + else + chcon 'u:object_r:system_file:s0' $1 2>/dev/null + fi +} + +install_nobackup() { + cp_perm $INSTALLER$1 $XPATH$1 $2 $3 $4 $5 +} + +install_and_link() { + TARGET=$1 + XPOSED="${1}_xposed" + BACKUP="${1}_original" + if [ ! -f $INSTALLER$XPOSED ]; then + return + fi + install_nobackup $XPOSED $2 $3 $4 $5 + if [ "$SYSTEMLESS" = "false" ]; then + if [ ! -f $BACKUP ]; then + mv $TARGET $BACKUP || exit 1 + ln -s $XPOSED $TARGET || exit 1 + chcon -h 'u:object_r:system_file:s0' $TARGET 2>/dev/null + fi + fi +} + +install_overwrite() { + TARGET=$1 + if [ ! -f $INSTALLER$TARGET ]; then + return + fi + BACKUP="${1}.orig" + NO_ORIG="${1}.no_orig" + if [ "$SYSTEMLESS" = "false" ]; then + if [ ! -f $TARGET ]; then + touch $NO_ORIG || exit 1 + set_perm $NO_ORIG 0 0 600 + elif [ -f $BACKUP ]; then + rm -f $TARGET + gzip $BACKUP || exit 1 + set_perm "${BACKUP}.gz" 0 0 600 + elif [ ! -f "${BACKUP}.gz" -a ! -f $NO_ORIG ]; then + mv $TARGET $BACKUP || exit 1 + gzip $BACKUP || exit 1 + set_perm "${BACKUP}.gz" 0 0 600 + fi + fi + install_nobackup $TARGET $2 $3 $4 $5 +} + +########################################################################################## +# Start +########################################################################################## + +ui_print "******************************" +ui_print "Xposed framework installer zip" +ui_print "******************************" + +if [ ! -d "$INSTALLER/common" ]; then + ui_print "! Failed: Unable to extract zip file!" + exit 1 +fi + +ui_print "- Mounting /system(ro), /cache, /data" +mount -o ro /system 2>/dev/null +mount /cache 2>/dev/null +mount /data 2>/dev/null + +if [ ! -f '/system/build.prop' ]; then + ui_print "! Failed: /system could not be mounted!" + exit 1 +fi + +API=$(grep_prop ro.build.version.sdk) +APINAME=$(android_version $API) +ABI=$(grep_prop ro.product.cpu.abi | cut -c-3) +ABI2=$(grep_prop ro.product.cpu.abi2 | cut -c-3) +ABILONG=$(grep_prop ro.product.cpu.abi) + +ARCH=arm +IS64BIT= +if [ "$ABI" = "x86" ]; then ARCH=x86; fi; +if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; +if [ "$API" -ge "21" ]; then + if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=1; fi; + if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=1; fi; +fi + +XVERSION=$(grep_prop version system/xposed.prop) +XARCH=$(grep_prop arch system/xposed.prop) +XMINSDK=$(grep_prop minsdk system/xposed.prop) +XMAXSDK=$(grep_prop maxsdk system/xposed.prop) + +XEXPECTEDSDK=$(android_version $XMINSDK) +if [ "$XMINSDK" != "$XMAXSDK" ]; then + XEXPECTEDSDK=$XEXPECTEDSDK' - '$(android_version $XMAXSDK) +fi + +ui_print "- Xposed version: $XVERSION" + +XVALID= +if [ "$ARCH" = "$XARCH" ]; then + if [ "$API" -ge "$XMINSDK" ]; then + if [ "$API" -le "$XMAXSDK" ]; then + XVALID=1 + else + ui_print "! Wrong Android version: $APINAME" + ui_print "! This file is for: $XEXPECTEDSDK" + fi + else + ui_print "! Wrong Android version: $APINAME" + ui_print "! This file is for: $XEXPECTEDSDK" + fi +else + ui_print "! Wrong platform: $ARCH" + ui_print "! This file is for: $XARCH" +fi + +if [ -z $XVALID ]; then + ui_print "! Please download the correct package" + ui_print "! for your platform/Android version!" + exit 1 +fi + +getvar SYSTEMLESS +prepare_systemless + +if [ "$SYSTEMLESS" = "true" -a "$VALID" = "false" ]; then + ui_print "! Config forces systemless install but requirements aren't met" + ui_print "aborting..." + exit 1 +fi + +SYSTEMLESS=$VALID + +if [ "$SYSTEMLESS" = "true" ]; then + ui_print "- Using systemless mode" +else + XPATH="" + ui_print "- Using system mode" + ui_print "- Re-mounting /system to rw" + mount -o rw,remount /system +fi + +########################################################################################## +# Detection all done, start installing +########################################################################################## + +ui_print "- Placing files" + +if [ "$SYSTEMLESS" = "true" ]; then + cp_perm $INSTALLER/common/00xposed /su/su.d/00xposed 0 0 0755 +fi +install_nobackup /system/xposed.prop 0 0 0644 +install_nobackup /system/framework/XposedBridge.jar 0 0 0644 +install_and_link /system/bin/app_process32 0 2000 0755 u:object_r:zygote_exec:s0 +install_overwrite /system/bin/dex2oat 0 2000 0755 u:object_r:dex2oat_exec:s0 +install_overwrite /system/bin/oatdump 0 2000 0755 +install_overwrite /system/bin/patchoat 0 2000 0755 u:object_r:dex2oat_exec:s0 +install_overwrite /system/lib/libart.so 0 0 0644 +install_overwrite /system/lib/libart-compiler.so 0 0 0644 +install_overwrite /system/lib/libart-disassembler.so 0 0 0644 +install_overwrite /system/lib/libsigchain.so 0 0 0644 +install_nobackup /system/lib/libxposed_art.so 0 0 0644 +if [ $IS64BIT ]; then + install_and_link /system/bin/app_process64 0 2000 0755 u:object_r:zygote_exec:s0 + install_overwrite /system/lib64/libart.so 0 0 0644 + install_overwrite /system/lib64/libart-compiler.so 0 0 0644 + install_overwrite /system/lib64/libart-disassembler.so 0 0 0644 + install_overwrite /system/lib64/libsigchain.so 0 0 0644 + install_nobackup /system/lib64/libxposed_art.so 0 0 0644 +fi + +umount /su 2>/dev/null +umount /system + +ui_print "- Done" +exit 0 diff --git a/zipstatic/x86/META-INF/com/google/android/genymotion-ready b/zipstatic/x86/META-INF/com/google/android/genymotion-ready deleted file mode 100644 index 4e6c2bc..0000000 --- a/zipstatic/x86/META-INF/com/google/android/genymotion-ready +++ /dev/null @@ -1,2 +0,0 @@ -In order to flash this archive on the Genymotion emulator, please see: -https://github.com/rovo89/GenyFlash diff --git a/zipstatic/x86/META-INF/com/google/android/update-binary b/zipstatic/x86/META-INF/com/google/android/update-binary deleted file mode 100644 index 7825113..0000000 Binary files a/zipstatic/x86/META-INF/com/google/android/update-binary and /dev/null differ