41 lines
2.3 KiB
Bash
Executable File
41 lines
2.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Replace an app with a differently signed build while keeping its data, permissions,
|
|
# installer and frozen state. Data is also saved to BACKUP_DIR before the uninstall.
|
|
# Usage: reinstall-keep-data.sh PACKAGE BACKUP_DIR APK [APK ...]
|
|
set -euo pipefail
|
|
pkg=$1 bak=$2; shift 2
|
|
a() { adb shell "$@" </dev/null; }
|
|
su_() { a "su -c '$1'"; }
|
|
|
|
mkdir -p "$bak"
|
|
installer=$(a "pm list packages -3 -i $pkg" | tr -d '\r' | grep "package:$pkg " | sed 's/.*installer=//')
|
|
disabled=$(a "pm list packages -d $pkg" | tr -d '\r' | grep -cx "package:$pkg" || true)
|
|
perms=$(a "dumpsys package $pkg" | sed -n '/runtime permissions:/,/^ *[a-z]* .*:$/p' | grep -oE '[a-zA-Z0-9_.]+: granted=true' | cut -d: -f1 | sort -u | tr '\n' ' ')
|
|
echo "$pkg: installer=$installer disabled=$disabled perms=[$perms]"
|
|
|
|
dirs="/data/data/$pkg /data/user_de/0/$pkg"
|
|
[ "$(su_ "[ -d /data/media/0/Android/data/$pkg ] && echo y")" = y ] && dirs="$dirs /data/media/0/Android/data/$pkg"
|
|
su_ "am force-stop $pkg"
|
|
# The phone writes the tar to stdout; exec-out keeps it binary-safe.
|
|
adb exec-out "su -c 'tar -cf - --exclude=$pkg/cache --exclude=$pkg/code_cache $dirs 2>/dev/null'" > "$bak/$pkg.tar"
|
|
echo "saved $(stat -c %s "$bak/$pkg.tar") bytes to $bak/$pkg.tar"
|
|
[ "$(stat -c %s "$bak/$pkg.tar")" -gt 10240 ] || { echo "backup suspiciously small, aborting"; exit 1; }
|
|
|
|
a "pm uninstall $pkg"
|
|
iopt=(); [ -n "$installer" ] && [ "$installer" != null ] && iopt=(-i "$installer")
|
|
adb install-multiple -r "${iopt[@]}" --bypass-low-target-sdk-block "$@"
|
|
|
|
uid=$(su_ "stat -c %u /data/data/$pkg")
|
|
cache_gid=$((uid - 10000 + 20000))
|
|
adb exec-in "su -c 'tar -xf - -C /'" < "$bak/$pkg.tar"
|
|
su_ "while pgrep -x tar >/dev/null; do sleep 0.3; done"
|
|
for d in /data/data/$pkg /data/user_de/0/$pkg; do
|
|
su_ "chown -R $uid:$uid $d; for c in cache code_cache; do mkdir -p $d/\$c; chown $uid:$cache_gid $d/\$c; chmod 2771 $d/\$c; done; chcon -hR \"\$(stat -c %C $d)\" $d"
|
|
done
|
|
case " $dirs " in *Android/data*)
|
|
su_ "d=/data/media/0/Android/data/$pkg; chown -R $uid:1078 \$d; find \$d -type d -exec chmod 2770 {} +; find \$d -type f -exec chmod 660 {} +; chcon -R u:object_r:media_rw_data_file:s0 \$d" ;;
|
|
esac
|
|
for p in $perms; do a "pm grant $pkg $p" 2>/dev/null || true; done
|
|
[ "$disabled" = 1 ] && su_ "pm disable-user --user 0 $pkg"
|
|
echo "$pkg: reinstalled as uid $uid, $(a "dumpsys package $pkg" | grep -m1 versionName | xargs)"
|