You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
NanoDroid/CommonInstaller

2386 lines
75 KiB
Bash

#!/sbin/sh
VERSION=23.2.99999999
NANODROID_UPGRADE=0
INSTALL_SUCCESS=TRUE
NANODROID_LIST=/system/addon.d/NanoDroid_FileList
NANODROID_LIST_OLD=/data/adb/NanoDroid_FileList
STORAGE=/data/media/0
curdate=$(date +%Y%m%d_%H.%M.%S)
nanodroid_logfile="${STORAGE}/nanodroid_logs/${MODID}_${VERSION}_log_${curdate}.log"
config_locations="${STORAGE} /external_sd /sdcard /sdcard1 /data /system/addon.d /tmp"
nanodroid_all_init='"10_sqlite 20_fstrim 30_logcat 40_external_sd 50_logscleaner"'
##########################################################################################
# NanoDroid Installer Setup Function
##########################################################################################
setup_installer () {
detect_bootmode
detect_outfd
! ${BOOTMODE} && [ "${MODID}" = "NanoDroid" ] && check_space
show_progress 1.0 0
show_banner
set_progress 0.1
unpack_zip
setup_busybox
mount_partitions
detect_arch
set_progress 0.2
if ${BOOTMODE}; then
media_rw=$(grep "^/dev/block.*/mnt/media_rw" /proc/mounts \
| cut -d " " -f 2 \
| cut -d "/" -f 4)
ext_storage="/storage/${media_rw}"
[ -r "${ext_storage}" ] && config_locations="${ext_storage} ${config_locations}"
fi
[ -n "${1}" ] && get_cfg_setup
[ -n "${2}" ] && get_cfg_overlay
[ -n "${3}" ] && get_cfg_apps
detect_mode
set_progress 0.3
}
##########################################################################################
# Misc. Functions
##########################################################################################
##########################################################################################
# Debug Echo: only echo in TWRP, in Magisk Manager print to logfile
##########################################################################################
decho () {
mkdir -p "${STORAGE}/nanodroid_logs"
if ${BOOTMODE}; then
echo "$@" >> "${nanodroid_logfile}"
else
echo "$@"
fi
}
##########################################################################################
# use print_info() instead of ui_print() to avoid spamming Magisk Manager output
##########################################################################################
print_info () {
if ${BOOTMODE}; then
echo "${@}"
decho "${@}"
else
echo -e "ui_print ${@}" >> /proc/self/fd/${OUTFD}
echo -e "ui_print" >> /proc/self/fd/${OUTFD}
fi
}
show_progress () {
${BOOTMODE} || echo "progress ${1} ${2}" >> /proc/self/fd/${OUTFD}
}
set_progress () {
${BOOTMODE} || echo "set_progress ${1}" >> /proc/self/fd/${OUTFD}
}
##########################################################################################
# Error out with proper cleanup
##########################################################################################
error () {
print_info " !!"
print_info "${@}"
print_info " !!"
if is_mounted /data; then
[ "${MODE}" = "MAGISK" ] && rm -rf "${MODPATH}"
installer_cleanup_env
INSTALL_SUCCESS=FALSE
nanodroid_storelogs
fi
${BOOTMODE} || umount_partitions
exit 1
}
##########################################################################################
# Taken from Magisk, check where to print to
##########################################################################################
detect_outfd () {
if [ -z $OUTFD ] || readlink /proc/$$/fd/$OUTFD | grep -q /tmp; then
# We will have to manually find out OUTFD
for FD in `ls /proc/$$/fd`; do
if readlink /proc/$$/fd/$FD | grep -q pipe; then
if ps | grep -v grep | grep -q " 3 $FD "; then
OUTFD=$FD
break
fi
fi
done
fi
}
##########################################################################################
# XXX - unused - Check if enough free space in /dev/tmp
##########################################################################################
check_space () {
space_required=524288
space_available=$(df /dev 2>/dev/null | awk '/tmpfs/{print $4}')
decho " required space : ${space_required}"
decho " available space: ${space_available}"
if [ ${space_available} -lt ${space_required} ]; then
error "Less than 512 MB free space availabe from TWRP!"
fi
}
##########################################################################################
# Taken from Magisk, check whether we're in Magisk Manager or TWRP
##########################################################################################
detect_bootmode () {
[ -z ${BOOTMODE} ] && ps | grep zygote | grep -qv grep && BOOTMODE=true
[ -z ${BOOTMODE} ] && ps -A 2>/dev/null | grep zygote | grep -qv grep && BOOTMODE=true
[ -z ${BOOTMODE} ] && BOOTMODE=false
}
##########################################################################################
# Taken from Magisk, grep build_props / /proc/cmdline for value
##########################################################################################
grep_prop () {
sed -n "s/^${1}=//p" /system/build.prop ${2} | head -n 1
}
grep_cmdline () {
local REGEX="s/^${1}=//p"
sed -E 's/ +/\n/g' /proc/cmdline | \
sed -n "${REGEX}" 2>/dev/null
}
##########################################################################################
# Set permissions for installed files
##########################################################################################
set_perm () {
chown ${2}:${3} ${1} || error "failed change owner for ${1}"
chmod ${4} ${1} || error "failed to change mode for ${1}"
if [ -n "${5}" ]; then
chcon ${5} ${1} 2>/dev/null
else chcon 'u:object_r:system_file:s0' ${1} 2>/dev/null
fi
}
set_perm_recursive () {
find ${1} -type d 2>/dev/null | while read dir; do
set_perm ${dir} ${2} ${3} ${4} ${6}
done
find ${1} -type f 2>/dev/null | while read file; do
set_perm ${file} ${2} ${3} ${5} ${6}
done
}
set_perm_data () {
if [ "${1}" = "-r" ]; then
decho " perm: data [recursive] {${2}}"
set_perm_recursive ${2} 0 0 0755 0644
else
decho " perm: data [single] {${1}}"
set_perm ${1} 0 0 0644
fi
}
set_perm_bin () {
if [ "${1}" = "-r" ]; then
decho " perm: exec [recursive] {${2}}"
set_perm_recursive ${2} 0 0 0755 0755
else
decho " perm: exec [single] {${1}}"
set_perm ${1} 0 0 0755
fi
}
##########################################################################################
# Taken from Magisk, mount functions
# Modified for NanoDroid
##########################################################################################
is_mounted () {
grep -q " $(readlink -f ${1}) " /proc/mounts 2>/dev/null
return $?
}
##########################################################################################
# taken from Magisk, with minor modifications for NanoDroid
# mount partitions
##########################################################################################
toupper() {
echo "$@" | tr '[:lower:]' '[:upper:]'
}
find_block () {
local block partname devname device
for block in "${@}"; do
block=${block}${SLOT}
device=$(find /dev/block \( -type b -o -type c -o -type l \) -name ${block} | head -n 1)
if [ -n "$device" ]; then
readlink -f "$device"
return 0
fi
done
for block in "${@}"; do
block=${block}${SLOT}
for uevent in /sys/dev/block/*/uevent; do
partname=$(awk -F= '/PARTNAME/{print $2}' ${uevent})
devname=$(awk -F= '/DEVNAME/{print $2}' ${uevent})
if [ "$(toupper ${block})" = "$(toupper ${partname})" ]; then
echo /dev/block/${devname}
return 0
fi
done
done
for block in "${@}"; do
block=${block}${SLOT}
device=$(find /dev \( -type b -o -type c -o -type l \) -maxdepth 1 -iname ${block} | head -n 1)
if [ -n "$device" ]; then
readlink -f "$device"
return 0
fi
done
return 1
}
mount_partitions () {
if ! ${BOOTMODE}; then
VENDOR_COMPAT=FALSE
SYSTEM_AS_ROOT=FALSE
SLOT=$(grep_cmdline androidboot.slot_suffix)
if [ -z ${SLOT} ]; then
SLOT=$(grep_cmdline androidboot.slot)
[ -z ${SLOT} ] || SLOT=_${SLOT}
fi
[ -z ${SLOT} ] && DEVICE_AB=FALSE || DEVICE_AB=TRUE
decho " INFO: #1 [SLOT] ${SLOT}"
is_mounted /data || mount /data || decho "failed to mount /data!"
mount -o bind /dev/urandom /dev/random
SYSTEM_BLOCK=$(find_block system app)
decho " INFO: #5 [SYSTEM_BLOCK] ${SYSTEM_BLOCK}"
[ -z "${SYSTEM_BLOCK}" ] && error "failed to detect block device for /system"
if is_mounted /system_root; then
umount /system 2&>/dev/null
umount /system_root 2&>/dev/null
fi
mkdir -p /system /system_root
mount -o rw ${SYSTEM_BLOCK} /system
if [ -f /system/build.prop ]; then
SYSTEM=/system
elif [ -f /system/system/build.prop -o -f /system/init -o -L /system/init ]; then
SYSTEM_AS_ROOT=true
SYSTEM=/system/system
if ! mount --move /system /system_root; then
umount /system
umount -l /system
mount -o rw ${SYSTEM_BLOCK} /system_root
fi
mount -o bind /system_root/system /system
fi
VENDOR_BLOCK=$(find_block vendor vnr)
decho " INFO: #7 [VENDOR_BLOCK] ${VENDOR_BLOCK}"
[ -z "${VENDOR_BLOCK}" ] && error "failed to detect block device for /vendor"
! is_mounted /vendor && mount -o ro /vendor
! is_mounted /vendor && mount -o ro ${VENDOR_BLOCK} /vendor
if [[ ! $(is_mounted /vendor) && -d /system/vendor ]]; then
### XXX work-around required for some devices
VENDOR_COMPAT=TRUE
ln -sf /system/vendor /vendor >/dev/null
fi
decho " INFO: #8 [prop]"
ls -l /system/*.prop
[ -d /system/apex ] && mount_apex
fi
[ ! -f /system/build.prop ] && error "failed to mount /system (unsupported A/B device?)"
export ANDROID_RUNTIME_ROOT=/apex/com.android.runtime
export ANDROID_TZDATA_ROOT=/apex/com.android.tzdata
export ANDROID_ART_ROOT=/apex/com.android.art
export ANDROID_I18N_ROOT=/apex/com.android.i18n
}
##########################################################################################
# taken from Magisk, with minor modifications for NanoDroid
# mount APEX directories or images
##########################################################################################
mount_apex () {
mkdir -p /apex
local pattern='s/.*"name":[^"]*"\([^"]*\).*/\1/p'
mount -t tmpfs tmpfs /apex -o mode=755
for apex in /system/apex/*; do
apex_loop="/dev/loop_apex_$(basename ${apex} .apex)"
if [ -f "${apex}" ]; then
unzip -oq "${apex}" apex_payload.img -d /apex
apex_mount=$(unzip -qp ${apex} apex_manifest.pb | strings | head -n 1)
[ -z ${apex_mount} ] && apex_mount=$(unzip -qp ${apex} apex_manifest.json | sed -n ${pattern})
[ -z ${apex_mount} ] && continue
mkdir -p "${apex_mount}"
mount_apex_loop "${apex_mount}" || error "APEX loop setup failed!"
elif [ -d "${apex}" ]; then
if [ -f ${apex}/apex_manifest.json ]; then
apex_mount=/apex/$(sed -n ${pattern} ${apex}/apex_manifest.json)
elif [ -f ${apex}/apex_manifest.pb ]; then
apex_mount=/apex/$(strings ${apex}/apex_manifest.pb | head -n 1)
else
continue
fi
mkdir -p "${apex_mount}"
mount -o bind "${apex}" "${apex_mount}"
fi
done
echo " INFO: #10 [APEX [ALL]] $(ls /system/apex/*)"
}
##########################################################################################
# taken from Magisk, with minor modifications for NanoDroid
# helper function for mounting APEX directories or images
##########################################################################################
mount_apex_loop () {
local number=0
local minorx=1
local loop
[ -e /dev/block/loop1 ] && minorx=$(stat -Lc '%T' /dev/block/loop1)
apex_mount="${1}"
decho " *** mount_apex_loop [apex_mount]: ${apex_mount}"
while [ ${number} -lt 64 ]; do
loop=/dev/block/loop${number}
[ -e ${loop} ] || mknod ${loop} b 7 $((number * minorx))
if losetup "${loop}" /apex/apex_payload.img 2>/dev/null; then
decho " *** mount_apex_loop [loop]: ${loop}"
if mount -text4 -oro,noatime "${loop}" "${apex_mount}"; then
rm -f /apex/apex_payload.img
break
fi
fi
number=$((number + 1))
done
}
##########################################################################################
# unmount partitions
##########################################################################################
umount_partitions () {
umount -l /system_root 2>/dev/null
umount -l /system 2>/dev/null
umount -l /system/vendor 2>/dev/null
umount -l /vendor 2>/dev/null
umount -l /dev/random 2>/dev/null
mount | awk '/ \/apex/{print $1 " " $3}' | while read apex_loop apex_mount; do
umount -l "${apex_mount}" 2>/dev/null
losetup -d "${apex_loop}" 2>/dev/null
done
rm -rf /apex
unset ANDROID_RUNTIME_ROOT
unset ANDROID_TZDATA_ROOT
unset ANDROID_ART_ROOT
unset ANDROID_I18N_ROOT
}
##########################################################################################
# migrate from Nanolx to Official APKs and vice-versa
##########################################################################################
detect_migrate_apk () {
local app_id="${1}"
local app_name="${2}"
USER_PATH=$(find /data/app -type d -name "${app_id}-*" &>/dev/null)
if [ -n ${USER_PATH} ]; then
if ${UNZIP} -l "${MODPATH}/system/priv-app/${app_name}/${app_name}.apk" | grep META-INF/NANOLX.RSA &>/dev/null; then
BUILD_INST=Nanolx
else BUILD_INST=Official
fi
if ${UNZIP} -l "${USER_PATH}/base.apk" | grep META-INF/NANOLX.RSA &>/dev/null; then
BUILD_USER=Nanolx
else BUILD_USER=Official
fi
if [ "${BUILD_INST}" != "${BUILD_USER}" ]; then
decho " + Removing ${BUILD_USER} ${app_name} in favor of ${BUILD_INST} ${app_name}"
rm -rf "${USER_PATH}"
if [ "${app_id}" = "com.google.android.gms" ]; then
decho " + Resetting GCM/FCM connection of all apps to allow re-registration"
find /data/data/*/shared_prefs -name com.google.android.gms.*.xml -delete
fi
fi
fi
}
##########################################################################################
# check if ROM has native fake signature spoofing support
# origingally by @ale5000 - revised by me
##########################################################################################
check_fake_package_signature () {
PERMISSION=android.permission.FAKE_PACKAGE_SIGNATURE
PERMISSION_OD=$(echo -n "${PERMISSION}" | od -A n -t x1 | tr -d '\n' | sed -e 's/^ //g;s/ /00/g')
PATCH_TYPE=""
FRAMEWORKRES_PATCH=false
SERVICESJAR_PATCH=false
mkdir -p ${TMPDIR}/sigcheck
# natively patched ROM: only framework-res.apk patched (old)
# natively patched ROM: both framework-res.apk and services.jar patched (new)
# self patched ROM: only services.jar patched
# check framework-res.apk for the patch
unzip -oq /system/framework/framework-res.apk -d "${TMPDIR}/sigcheck" \
|| error "failed to unpack framework-res.apk"
grep -qF "${PERMISSION}" "${TMPDIR}"/sigcheck/AndroidManifest.xml && FRAMEWORKRES_PATCH=true
od -A n -t x1 "${TMPDIR}"/sigcheck/AndroidManifest.xml | tr -d ' \n' | grep -qF "${PERMISSION_OD}" && FRAMEWORKRES_PATCH=true
# check services.jar for the patch
unzip -oq /system/framework/services.jar -d "${TMPDIR}/sigcheck" \
|| error "failed to unpack services.jar"
grep -qF "${PERMISSION}" "${TMPDIR}"/sigcheck/*.dex && SERVICESJAR_PATCH=true
od -A n -t x1 "${TMPDIR}"/sigcheck/*.dex | tr -d ' \n' | grep -qF "${PERMISSION_OD}" && SERVICESJAR_PATCH=true
# we don't use this anywhere (except in SysTest log),
# but may still come in hand in the future
if ${FRAMEWORKRES_PATCH} && ! ${SERVICESJAR_PATCH}; then
PATCH_TYPE="native_old"
elif ${FRAMEWORKRES_PATCH} && ${SERVICESJAR_PATCH}; then
PATCH_TYPE="native_new"
elif ! ${FRAMEWORKRES_PATCH} && ${SERVICESJAR_PATCH}; then
PATCH_TYPE="self_patched"
fi
[ -n "${PATCH_TYPE}" ] && return 0 || return 1
}
##########################################################################################
# parse output from "aapt dump xmltree" back to xml
##########################################################################################
parse_aapt_dump_xmltree(){
local i step indent prev_indent cur_type prev_type entity_stack key value tmp
while IFS=$'\n' read -r i; do
cur_type="$(echo "${i}" | awk '{print $1}')"
case "${cur_type}" in
E:) # entity
indent="$(echo "${i}" | awk -F'[^ ]' '{print length($1)}')"
[ -z "${prev_type}" ] || [ "${prev_type}" = "C:" ] || echo -n ">"
[ -z "${prev_type}" ] || [ "$((${prev_indent:=0}-${indent}))" -lt 0 ] || for j in $(seq "$((${prev_indent:=0}-${indent}))" "-${step:=2}" "$((${indent}-${step}))"); do
echo -ne "\n</${entity_stack##* }>"
entity_stack="${entity_stack% *}"
done
echo -ne "\n<$(echo -n "${i}" | awk '{print $2}')"
entity_stack="${entity_stack} $(echo "${i}" | awk '{print $2}')"
prev_indent="${indent}"
;;
A:) # attribute
key="$(echo "${i}" | awk '{print $2}' | awk -F= '{print $1}')"
value="${i#*=}"
case "${value}" in
"(type 0x12)"*) [ "${value#*)}" = "0x0" ] && value='"false"' || value='"true"';;
"(type 0x10)"*) value="$(printf '%d' "${value#*)}")";;
*) value="${value% \(Raw:*}"
esac
echo -n " ${key}=${value}"
unset key value
;;
C:) # content
tmp="${i#*C: \"}"
echo -n ">${tmp%*\"}"
unset tmp
;;
esac
prev_type="${cur_type}"
done <&0
[ "${prev_type}" = "C:" ] || echo -n ">"
until [ -z "${entity_stack}" ]; do
echo -ne "\n</${entity_stack##* }>"
entity_stack="${entity_stack% *}"
done
}
##########################################################################################
# sign package with test keys
##########################################################################################
byte_split(){ local i; for i in $(seq 0 2 $((${#1}-1))); do echo "${1:${i}:2}"; done; }
hex2bin(){ local i; for i in $(seq 0 2 $((${#1}-1))); do printf "\x${1:${i}:2}"; done; }
jar_sign(){
local tmpdir="${TMPDIR}/$(tr -cd '0-9a-z' 2>/dev/null </dev/urandom | head -c8)" apk="${1}" i
mkdir -p "${tmpdir}/META-INF"
cd "${tmpdir}"; echo A | unzip -qo "${apk}"
cat <<EOF >"${tmpdir}/META-INF/MANIFEST.MF"
Manifest-Version: 1.0
Built-By: NanoDroid
Created-By: 1.0 (Android)
EOF
for i in $(find "${tmpdir}" -type f); do
echo "${i}" | grep -qvE "^${tmpdir}/META-INF/" || continue
cat <<EOF >>"${tmpdir}/META-INF/MANIFEST.MF"
Name: ${i#${tmpdir}/*}
SHA-256-Digest: $(hex2bin "$(sha256sum "${i}" | awk '{print $1}')" | base64 | tr -d '[:space:]')
EOF
done
cat <<EOF >"${tmpdir}/META-INF/CERT.SF"
Signature-Version: 1.0
Created-By: 1.0 (Android)
SHA-256-Digest-Manifest: $(hex2bin "$(sha256sum "${tmpdir}/META-INF/MANIFEST.MF" | awk '{print $1}')" | base64 | tr -d '[:space:]')
X-Android-APK-Signed: 2, 3
EOF
for i in $(find "${tmpdir}" -type f); do
echo "${i}" | grep -qvE "^${tmpdir}/META-INF/" || continue
cat <<EOF >>"${tmpdir}/META-INF/CERT.SF"
Name: ${i#${tmpdir}/*}
SHA-256-Digest: $(hex2bin "$(sha256sum "${i}" | awk '{print $1}')" | base64 | tr -d '[:space:]')
EOF
done
"${OPENSSL}" smime -sign -binary -noattr -in "${tmpdir}/META-INF/CERT.SF" -outform der -out "${tmpdir}/META-INF/CERT.RSA" -signer "${INSTALLER}/testkey.crt" -md sha256 -inkey "${INSTALLER}/testkey.key"
"${ZIP}" -r "${apk}" ./META-INF
}
generate_signed_data(){
local idx=0 apk="${1}" segment_sz=1048576 tmpfile="${INSTALLER}/tmpfile"
local apk_content="$(od -v -tx1 -An "${apk}" | tr -dc '[0-9a-fA-F]')"
local eocd_base="$(($(echo -n "${apk_content%504b0506*}" | wc -c)/2))"; unset apk_content
local cd_base="$(printf '%d' "0x$(od -v -tx1 -An -j$((${eocd_base}+16)) -N4 "${apk}" | tr -c '[0-9a-fA-F]' '\n' | tac | tr -dc '[0-9a-fA-F]')")"
local cd_size="$(printf '%d' "0x$(od -v -tx1 -An -j$((${eocd_base}+12)) -N4 "${apk}" | tr -c '[0-9a-fA-F]' '\n' | tac | tr -dc '[0-9a-fA-F]')")"
dd bs=1 count="${cd_base}" if="${apk}" of="${INSTALLER}/contents"
dd bs=1 skip="${cd_base}" count="${cd_size}" if="${apk}" of="${INSTALLER}/cd"
dd bs=1 skip="${eocd_base}" if="${apk}" of="${INSTALLER}/eocd"
echo -n >"${tmpfile}"; segment_sz=1048576; while [ $((${idx}*1048576)) -lt ${cd_base} ]; do
[ $(($((${idx}+1))*1048576)) -lt ${cd_base} ] || segment_sz=$((${cd_base}-$((${idx}*1048576))))
hex2bin "a5$(byte_split $(printf '%08x' ${segment_sz}) | tac | tr -dc '[0-9a-fA-F]')$(dd bs=1 skip="$((${idx}*1048576))" count="${segment_sz}" if="${INSTALLER}/contents" | sha512sum | awk '{print $1}')" >> "${tmpfile}"
idx=$((${idx}+1))
done
local cd_idx=0 segment_sz=1048576; while [ $((${cd_idx}*1048576)) -lt ${cd_size} ]; do
[ $(($((${cd_idx}+1))*1048576)) -lt ${cd_size} ] || segment_sz=$((${cd_size}-$((${cd_idx}*1048576))))
hex2bin "a5$(byte_split $(printf '%08x' ${segment_sz}) | tac | tr -dc '[0-9a-fA-F]')$(dd bs=1 skip="$((${cd_idx}*1048576))" count="${segment_sz}" if="${INSTALLER}/cd" | sha512sum | awk '{print $1}')" >> "${tmpfile}"
cd_idx=$((${cd_idx}+1))
done
local eocd_idx=0 eocd_sz="$(stat -c '%s' "${INSTALLER}/eocd")" segment_sz=1048576
while [ $((${eocd_idx}*1048576)) -lt ${eocd_sz} ]; do
[ $(($((${eocd_idx}+1))*1048576)) -lt ${eocd_sz} ] || segment_sz=$((${eocd_sz}-$((${eocd_idx}*1048576))))
hex2bin "a5$(byte_split $(printf '%08x' ${segment_sz}) | tac | tr -dc '[0-9a-fA-F]')$(dd bs=1 skip="$((${eocd_idx}*1048576))" count="${segment_sz}" if="${INSTALLER}/eocd" | sha512sum | awk '{print $1}')" >> "${tmpfile}"
eocd_idx=$((${eocd_idx}+1))
done
local digest_le="$(hex2bin "5a$(byte_split $(printf '%08x' $((${idx}+${cd_idx}+${eocd_idx}))) | tac | tr -dc '[0-9a-fA-F]')$(od -v -An -tx1 "${tmpfile}" | tr -dc '[0-9a-fA-F]')" | "${OPENSSL}" dgst -hex -c -sha512 | awk '{print $NF}' | tr ':' '\n' | tac | tr -dc '[0-9a-fA-F]')"
local digest_field="$(byte_split 00000104 | tac | tr -dc '[0-9a-fA-F]')$(byte_split $(printf '%08x' $((${#digest_le}/2))) | tac | tr -dc '[0-9a-fA-F]')${digest_le}"
local digest_record="$(byte_split $(printf '%08x' $((${#digest_field}/2))) | tac | tr -dc '[0-9a-fA-F]')${digest_field}"
local digest_seq="$(byte_split $(printf '%08x' $((${#digest_record}/2))) | tac | tr -dc '[0-9a-fA-F]')${digest_record}"
local cert_len="$("${OPENSSL}" x509 -in "${INSTALLER}/testkey.crt" -outform DER | wc -c)"
local cert_head="$(byte_split $(printf '%08x' ${cert_len}) | tac | tr -dc '[0-9a-fA-F]')"
local cert_seq_head="$(byte_split $(printf '%08x' $((${cert_len}+4))) | tac | tr -dc '[0-9a-fA-F]')"
hex2bin "${digest_seq}${cert_seq_head}${cert_head}" > "${INSTALLER}/signed_data"
"${OPENSSL}" x509 -in "${INSTALLER}/testkey.crt" -outform DER >> "${INSTALLER}/signed_data"
}
apk_sign(){
local apk="${1}" min_sdk="$(byte_split $(printf '%08x' 23) | tac | tr -dc '[0-9a-fA-F]')" max_sdk="ffffff7f" attrib_seq="00000000" sdk_spec i block_id
generate_signed_data "${apk}"
"${OPENSSL}" x509 -in "${INSTALLER}/testkey.crt" -pubkey -noout | tail -n+2 | head -n-1 | base64 -d >"${INSTALLER}/testkey.pub"
local pub_footer="$(byte_split $(printf '%08x' $(stat -c '%s' "${INSTALLER}/testkey.pub")) | tac | tr -dc '[0-9a-fA-F]')$(od -v -An -tx1 "${INSTALLER}/testkey.pub" | tr -dc '[0-9a-fA-F]')"
rm "${INSTALLER}/testkey.pub"
echo -n >"${INSTALLER}/sigblock"
for i in $(seq 2 3); do
case "${i}" in
2)
block_id="$(byte_split 7109871a | tac | tr -dc '[0-9a-fA-F]')"
;;
3)
block_id="$(byte_split f05368c0 | tac | tr -dc '[0-9a-fA-F]')"
sdk_spec="${min_sdk}${max_sdk}"
;;
esac
cat "${INSTALLER}/signed_data" > "${INSTALLER}/signed_data.v${i}"
hex2bin "${sdk_spec}${attrib_seq}" >> "${INSTALLER}/signed_data.v${i}"
local signed_data="$(byte_split "$(printf '%08x' "$(stat -c '%s' "${INSTALLER}/signed_data.v${i}")")" | tac | tr -dc '[0-9a-fA-F]')$(od -v -An -tx1 "${INSTALLER}/signed_data.v${i}" | tr -dc '[0-9a-fA-F]')"
"${OPENSSL}" dgst -sha512 -sign "${INSTALLER}/testkey.key" "${INSTALLER}/signed_data.v${i}" > "${INSTALLER}/signed_data.v${i}.sig"
local sig_len="$(stat -c '%s' "${INSTALLER}/signed_data.v${i}.sig")"
local sig_seq="${sdk_spec}$(byte_split $(printf '%08x' $((${sig_len}+12))) | tac | tr -dc '[0-9a-fA-F]')$(byte_split $(printf '%08x' $((${sig_len}+8))) | tac | tr -dc '[0-9a-fA-F]')$(byte_split 00000104 | tac | tr -dc '[0-9a-fA-F]')$(byte_split $(printf '%08x' ${sig_len}) | tac | tr -dc '[0-9a-fA-F]')$(od -v -An -tx1 "${INSTALLER}/signed_data.v${i}.sig" | tr -dc '[0-9a-fA-F]')"
rm "${INSTALLER}/signed_data.v${i}" "${INSTALLER}/signed_data.v${i}.sig"
local signer="${signed_data}${sig_seq}${pub_footer}"
local sigblock="${block_id}$(byte_split $(printf '%08x' $((${#signer}/2+4))) | tac | tr -dc '[0-9a-fA-F]')$(byte_split $(printf '%08x' $((${#signer}/2))) | tac | tr -dc '[0-9a-fA-F]')${signer}"
hex2bin "$(byte_split $(printf '%016x' $((${#sigblock}/2))) | tac | tr -dc '[0-9a-fA-F]')${sigblock}" >> "${INSTALLER}/sigblock"
done
rm "${INSTALLER}/signed_data"
local sigblock_len="$(byte_split $(printf '%016x' "$(($(stat -c '%s' "${INSTALLER}/sigblock")+24))") | tac | tr -dc '[0-9a-fA-F]')"
cat "${INSTALLER}/contents" >"${apk}.tmp"
hex2bin "${sigblock_len}" >>"${apk}.tmp"
cat "${INSTALLER}/sigblock" >>"${apk}.tmp"
hex2bin "${sigblock_len}" >>"${apk}.tmp"
echo -n "APK Sig Block 42" >>"${apk}.tmp"
sync
local new_cd_base="$(byte_split $(printf '%08x' "$(stat -c '%s' "${apk}.tmp")") | tac | tr -dc '[0-9a-fA-F]')"
cat "${INSTALLER}/cd" >>"${apk}.tmp"
dd bs=1 count=16 if="${INSTALLER}/eocd" >>"${apk}.tmp"
hex2bin "${new_cd_base}" >>"${apk}.tmp"
dd bs=1 skip=20 if="${INSTALLER}/eocd" >> "${apk}.tmp"
mv "${apk}.tmp" "${apk}"
}
##########################################################################################
# privapp permission whitelist generation
##########################################################################################
dump_system_privapp_permissions () {
local sys_list="${TMPDIR}/privapp-permissions.list"
local tmp_list="${TMPDIR}/privapp-permissions.dump"
rm -f "${sys_list}"
"${AAPT}" dump xmltree /system/framework/framework-res.apk AndroidManifest.xml | \
tr -d '\n' | sed -e 's/E:/\n/g' > "${tmp_list}"
for pattern in "(type 0x11)0x[1357]2" "(type 0x11)0xc212" \
"(type 0x11)0x[02]" "(type 0x11)0x[13]02" \
"(type 0x11)0x1[01]2" "(type 0x11)0x1001" \
"(type 0x11)0x[15]2" "(type 0x11)0x1000072"; do
grep "${pattern}" "${tmp_list}" | \
awk -F\" '{print $2}' >> "${sys_list}"
done
# XXX pre-patched custom ROM
check_fake_package_signature && \
echo "android.permission.FAKE_PACKAGE_SIGNATURE" >> "${sys_list}"
}
create_privapp_permissions_whitelist () {
local apk="${MODPATH}/system/priv-app/${1}/${1}.apk"
local apk_name="$("${AAPT}" dump badging "${apk}" | awk -F \' '/^package: name/{print $2}')"
local apk_list="${TMPDIR}/${apk_name}.list"
local sys_list="${TMPDIR}/privapp-permissions.list"
local app_whitelist="${TMPDIR}/${apk_name}.xml"
local inst_whitelist="/system/etc/permissions/${apk_name}.xml"
[ ! -f "${sys_list}" ] && dump_system_privapp_permissions
"${AAPT}" dump permissions "${apk}" | \
awk -F \' '/^uses-permission:/{print $2}' > "${apk_list}"
echo '<?xml version="1.0" encoding="utf-8"?>
<permissions>
<privapp-permissions package="'${apk_name}'">' > "${app_whitelist}"
cat "${apk_list}" | while read perm; do
if grep -q "${perm}" "${sys_list}"; then
decho " ++ package ${apk_Name} needs privapp-whitelist ${perm}"
echo ' <permission name="'${perm}'" />' >> "${app_whitelist}"
fi
done
echo ' </privapp-permissions>
</permissions>' >> "${app_whitelist}"
mkdir -p "${MODPATH}/system/etc/permissions/"
cp "${app_whitelist}" "${MODPATH}/${inst_whitelist}"
set_perm_data "${MODPATH}/${inst_whitelist}"
installinfo_add "${inst_whitelist}"
}
##########################################################################################
# Reset System Runtime permissions
##########################################################################################
reset_runtime_permissions () {
# required on Android 10, else all apps bundled with NanoDroid will not
# show a permission prompt for android.permission.WRITE_EXTERNAL_STORAGE
if [ "${SDK_VERSION}" -ge 29 ]; then
if ${BOOTMODE}; then
pm reset-permissions
else
find /data/system/users -type f -name 'runtime-permissions.xml' 2>/dev/null | while read file; do
rm -f "${file}"
decho " ++ resetting permissions: ${file}"
done
fi
fi
}
##########################################################################################
# Unpack NanoDroid zip
##########################################################################################
unpack_zip () {
TMPDIR=/dev/tmp
TMP_LIBDIR=${TMPDIR}/nanodroid-lib
INSTALLER=${TMPDIR}/install
rm -rf ${INSTALLER}
mkdir -p ${INSTALLER} || error "failed to prepare environment!"
print_info " > prepare installation"
unzip -oq "${ZIP}" -d "${INSTALLER}" || \
error "failed to prepare environment!"
rm -rf ${TMPDIR}/framework-res
rm -f ${TMPDIR}/*.xml
rm -f ${TMPDIR}/*.list
chmod 0755 ${INSTALLER}/*.*
}
##########################################################################################
# Print NanoDroid banner
##########################################################################################
show_banner () {
print_info " "
print_info "*****************************"
print_info " NanoDroid "
case ${MODID} in
NanoDroid )
print_info " > Full package "
;;
NanoDroid_microG )
print_info " > microG package "
;;
NanoDroid_FDroid )
print_info " > F-Droid package "
;;
NanoDroid_BromiteWebView )
print_info " > Bromite WebView package "
;;
NanoDroid_OsmAnd )
print_info " > OsmAnd package "
;;
NanoDroid_Google )
print_info " > Google package "
;;
esac
if [ "${ZIP}" == *${VERSION}* ]; then
print_info " ${VERSION} "
else
print_info " ${VERSION} (snapshot) "
fi
print_info "*****************************"
print_info " "
}
##########################################################################################
# Architecture detection
##########################################################################################
detect_arch () {
SDK_VERSION=$(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
[ "$ABI" = "x86" ] && ARCH=x86
[ "$ABI2" = "x86" ] && ARCH=x86
[ "$ABILONG" = "arm64-v8a" ] && ARCH=arm64
[ "$ABILONG" = "x86_64" ] && ARCH=x86_64
case ${ARCH} in
arm ) BIN_ARCH="arm"
LIB_ARCHES="armeabi-v7a armeabi"
SWIPE_LIBDIR=lib ;;
arm64 ) BIN_ARCH="arm"
LIB_ARCHES="arm64-v8a armeabi-v7a armeabi"
SWIPE_LIBDIR=lib64 ;;
x86 ) BIN_ARCH="x86"
LIB_ARCHES="x86 armeabi-v7a armeabi"
SWIPE_LIBDIR=lib ;;
x86_64 ) BIN_ARCH="x86"
LIB_ARCHES="x86_64 x86 armeabi-v7a armeabi"
SWIPE_LIBDIR=lib64 ;;
esac
UNZIP="${INSTALLER}/unzip.${BIN_ARCH}"
AAPT="${INSTALLER}/aapt.${BIN_ARCH}"
ZSTD="${INSTALLER}/zstd.${BIN_ARCH}"
OPENSSL="${INSTALLER}/openssl.${BIN_ARCH}"
ZIP="${INSTALLER}/zip.${BIN_ARCH}"
ZIPALIGN="${INSTALLER}/zipalign.${BIN_ARCH}"
chmod +x "${UNZIP}" "${AAPT}" "${ZSTD}"
case ${SDK_VERSION} in
19 ) GSYNC_VER=K ;;
21 | 22 ) GSYNC_VER=L ;;
23 ) GSYNC_VER=M ;;
24 | 25 ) GSYNC_VER=N ;;
26 | 27 ) GSYNC_VER=O ;;
28 ) GSYNC_VER=P ;;
29 ) GSYNC_VER=Q ;;
30 ) GSYNC_VER=R ;;
* ) GSYNC_UNSUPPORTED=1 ;;
esac
case ${ARCH} in
arm )
case ${SDK_VERSION} in
29 | 30 )
LIBJNI_IME=libjni_latinimegoogle.so_28
;;
19 | 21 | 22 | 23 | 27 | 28 )
LIBJNI_IME=libjni_latinimegoogle.so_${SDK_VERSION}
;;
24 | 25 | 26 )
LIBJNI_IME=libjni_latinimegoogle.so_23
;;
* )
SWIPE_UNSUPPORTED=1
;;
esac
;;
arm64 )
case ${SDK_VERSION} in
29 | 30 )
LIBJNI_IME=libjni_latinimegoogle.so_28
;;
21 | 22 | 23 | 27 | 28 )
LIBJNI_IME=libjni_latinimegoogle.so_${SDK_VERSION}
;;
24 | 25 | 26 )
LIBJNI_IME=libjni_latinimegoogle.so_23
;;
* )
SWIPE_UNSUPPORTED=1
;;
esac
;;
x86 | x86_64 )
case ${SDK_VERSION} in
19 | 21 | 22 )
SWIPE_UNSUPPORTED=1
;;
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 )
LIBJNI_IME=libjni_latinimegoogle.so
;;
* )
SWIPE_UNSUPPORTED=1
;;
esac
;;
esac
if [[ "${SDK_VERSION}" -lt 21 ]]; then
UNFOLD_APP_DIR=1
else UNFOLD_APP_DIR=0
fi
if [[ "${SDK_VERSION}" -lt 19 ]]; then
print_info " "
print_info " ++ Installing on pre-KitKat ROM, full"
print_info " ++ compatibility is not guaranteed!"
print_info " "
fi
[ ! -d /data/adb ] && mkdir /data/adb
}
##########################################################################################
# Detect and setup installation mode
##########################################################################################
detect_mode () {
[ -f "${NANODROID_LIST_OLD}" ] && mv "${NANODROID_LIST_OLD}" "${NANODROID_LIST}"
case "${nanodroid_forcesystem}" in
1 )
if ${BOOTMODE}; then
print_info "nanodroid_forcesystem set to true"
error "can't install to /system from Magisk Manager"
fi
MODE_DETECT=forced
MODE=SYSTEM
;;
0 | *)
MODE_DETECT=detected
MODE=SYSTEM
MAGISK_VER_CODE=0
if [ ! -f "${NANODROID_LIST}" ]; then
if [ -f /data/adb/magisk/util_functions.sh ]; then
. /data/adb/magisk/util_functions.sh
elif [ -f /data/magisk/util_functions.sh ]; then
. /data/magisk/util_functions.sh
fi
if [ ${MAGISK_VER_CODE} -ge 19000 ]; then
MODE=MAGISK
else
MODE=SYSTEM
fi
fi
;;
esac
print_info " > Mode | ${MODE} | ${MODE_DETECT}"
print_info " "
case ${MODE} in
SYSTEM )
installer_setup_env
unset MODPATH
mkdir -p /system/addon.d
[ -f "${NANODROID_LIST}" ] && NANODROID_UPGRADE=1
;;
MAGISK )
magisk_install_setup
case ${MODID} in
NanoDroid | NanoDroid_microG )
magisk_install_preinst
;;
esac
;;
esac
NANODROID_BINDIR="${MODPATH}/system/bin"
}
##########################################################################################
# Finalize NanoDroid Installation
##########################################################################################
nanodroid_finalize () {
case ${MODID} in
NanoDroid | NanoDroid_microG )
if [ "${nanodroid_overlay}" -eq 1 ]; then
print_info " << with /system applications overlays"
${NANODROID_BINDIR}/nanodroid-overlay --create
else
print_info " << without /system applications overlays"
fi
;;
esac
if [ "${MODE}" = "MAGISK" ]; then
magisk_install_finish
else
install_addond
sync
nanodroid_storelogs
sort ${NANODROID_LIST} | uniq > /tmp/nanodroid-list
mv /tmp/nanodroid-list ${NANODROID_LIST}
installer_cleanup_env
fi
[ "${NANODROID_UPGRADE}" -eq 0 ] && reset_runtime_permissions
print_info " "
print_info " Thanks for using NanoDroid "
print_info " "
${BOOTMODE} || umount_partitions
rm -rf ${INSTALLER}
}
##########################################################################################
# Setup Environment
##########################################################################################
##########################################################################################
# Setup Busybox
##########################################################################################
setup_busybox () {
case $(uname -m) in
arm* | aarch* ) local bb_arch=arm ;;
x86* ) local bb_arch=x86 ;;
* ) error "arch \"$(uname -m)\" is not supported"
esac
mkdir -p ${INSTALLER}/busybox
ln -s ${INSTALLER}/busybox.${bb_arch} ${INSTALLER}/busybox/busybox
chmod 0755 ${INSTALLER}/busybox.${bb_arch}
${INSTALLER}/busybox.${bb_arch} --install -s ${INSTALLER}/busybox/
OLD_PATH=${PATH}
export PATH=${INSTALLER}/busybox:/system/bin:/vendor/bin
}
##########################################################################################
# Move envvars out of the way
##########################################################################################
installer_setup_env () {
if ! ${BOOTMODE}; then
OLD_PATH=${PATH}
OLD_LD_LIB=${LD_LIBRARY_PATH}
OLD_LD_PRE=${LD_PRELOAD}
OLD_LD_CFG=${LD_CONFIG_FILE}
unset LD_LIBRARY_PATH
unset LD_PRELOAD
unset LD_CONFIG_FILE
fi
}
##########################################################################################
# Restore envvars
##########################################################################################
installer_cleanup_env () {
if ${BOOTMODE}; then
[ -n ${OLD_PATH} ] && PATH=${OLD_PATH}
else
[ -n ${OLD_PATH} ] && PATH=${OLD_PATH}
[ -n ${OLD_LD_LIB} ] && LD_LIBRARY_PATH=${OLD_LD_LIB}
[ -n ${OLD_LD_PRE} ] && LD_PRELOAD=${OLD_LD_PRE}
[ -n ${OLD_LD_CFG} ] && LD_CONFIG_FILE=${OLD_LD_CFG}
fi
}
##########################################################################################
# Magisk Mode Installation
##########################################################################################
##########################################################################################
# Setup Magisk Mode Installation
##########################################################################################
magisk_install_setup () {
print_info " "
print_info "******************************"
print_info "Powered by Magisk (@topjohnwu)"
print_info "******************************"
print_info " "
print_info " > setup Magisk environment"
MAGISKBASE=/data/adb
installer_setup_env
case ${MODID} in
NanoDroid )
# check for sub-modules which are not
# supposed to be installed alongside
for dir in NanoDroid_microG NanoDroid_FDroid; do
if [ -d ${MAGISKBASE}/modules/${dir} ]; then
print_info " !! ${dir} module detected - uninstalling!"
rm -rf ${MAGISKBASE}/modules/${dir}
NANODROID_UPGRADE=1
fi
if [ -d ${MAGISKBASE}/modules_update/${dir} ]; then
print_info " !! ${dir} module detected - uninstalling!"
rm -rf ${MAGISKBASE}/modules_update/${dir}
fi
done
;;
NanoDroid_microG | NanoDroid_FDroid )
# check for Full package and abort if found
[ -d ${MAGISKBASE}/modules/NanoDroid -o -d ${MAGISKBASE}/modules_update/NanoDroid ] && \
error "${MODID} can't be installed along side the Full package"
;;
NanoDroid_OsmAnd | NanoDroid_Google | NanoDroid_BromiteWebView )
true
;;
* )
error "unknown module intended to be installed!?"
;;
esac
[ -d ${MODPATH} ] && NANODROID_UPGRADE=1
if [ "${NANODROID_UPGRADE}" -eq 1 ]; then
MODPATH=${MAGISKBASE}/modules_update/${MODID}
rm -rf ${MODPATH}
else
MODPATH=${MAGISKBASE}/modules/${MODID}
fi
}
##########################################################################################
# Magisk Mode Installation: Pre-Installation Tasks
##########################################################################################
magisk_install_preinst () {
if [ -f ${MODPATH}/system.prop ]; then
print_info " << backing up module's system.prop"
cp ${MODPATH}/system.prop ${TMPDIR}/system.prop
fi
if [ -d ${MODPATH}/logs ]; then
print_info " << backing up init.d script logs"
cp -r ${MODPATH}/logs ${TMPDIR}/logs
fi
if [ -d ${MODPATH}/logcats ]; then
print_info " << backing up logcats"
cp -r ${MODPATH}/logcats ${TMPDIR}/logcats
fi
}
##########################################################################################
# Magisk Mode Installation: Post-Installation Tasks
##########################################################################################
magisk_install_postinst () {
if [ -f ${TMPDIR}/system.prop ]; then
print_info " << restoring system.prop"
cp ${TMPDIR}/system.prop ${MODPATH}/system.prop
fi
if [ "${nanodroid_microg}" -ne 0 -o "${MODID}" = "NanoDroid_microG" ]; then
if [ -n $(grep_prop ro.setupwizard.mode) ]; then
echo "ro.setupwizard.mode=DISABLED" >> ${MODPATH}/system.prop
fi
fi
if [ -d ${TMPDIR}/logs ]; then
print_info " << restoring init.d script logs"
cp -r ${TMPDIR}/logs ${MODPATH}/logs
fi
if [ -d ${TMPDIR}/logcats ]; then
print_info " << restoring logcats"
cp -r ${TMPDIR}/logcats ${MODPATH}/logcats
fi
}
##########################################################################################
# Finalize Magisk Mode Installation
##########################################################################################
magisk_install_finish () {
# Magisk Module files
cp -af ${INSTALLER}/module.prop ${MODPATH}/module.prop
if [ -f ${INSTALLER}/service.sh ]; then
cp -af ${INSTALLER}/service.sh ${MODPATH}/service.sh
chmod +x ${MODPATH}/service.sh
fi
case ${MODID} in
NanoDroid | NanoDroid_microG )
magisk_install_postinst
;;
esac
if ${BOOTMODE}; then
touch "${MAGISKBASE}/modules/${MODID}/update" 2>/dev/null
cp -af "${INSTALLER}/module.prop" "${MAGISKBASE}/modules/${MODID}/module.prop" 2>/dev/null
fi
sync
nanodroid_storelogs
installer_cleanup_env
}
##########################################################################################
# Generic Installation
##########################################################################################
##########################################################################################
# Install microG
##########################################################################################
install_microg () {
# install microG if requested
# respectively force if it's the microG package
if [ "${nanodroid_microg}" -ne 0 -o "${MODID}" = "NanoDroid_microG" ]; then
gapps_solve_conflicts
gapps_destroy_artifacts
print_info " << with microg"
print_info " ++ microG GmsCore"
nanodroid_install_apk GmsCore
detect_migrate_apk com.google.android.gms GmsCore
[ "${nanodroid_microg}" -ne 2 ] && nanodroid_install_apk GsfProxy
NLPBACKEND="nlpBackendNominatim"
print_info " ++ Nominatim geocoder backend"
${NANODROID_BINDIR}/nanodroid-overlay --add NominatimGeocoderBackend
${NANODROID_BINDIR}/nanodroid-overlay --add NominatimNlpBackend
if [ "${nanodroid_nlpbackend:0:1}" -eq 1 ]; then
NLPBACKEND="${NLPBACKEND} nlpBackendDejavu"
print_info " ++ Déjà Vu location backend"
${NANODROID_BINDIR}/nanodroid-overlay --add DejaVuNlpBackend
${NANODROID_BINDIR}/nanodroid-overlay --add DejaVuBackend
fi
if [ "${nanodroid_nlpbackend:1:1}" -eq 1 ]; then
NLPBACKEND="${NLPBACKEND} nlpBackendIchnaea"
print_info " ++ Ichnaea location backend"
${NANODROID_BINDIR}/nanodroid-overlay --add IchnaeaNlpBackend
${NANODROID_BINDIR}/nanodroid-overlay --add MozillaNlpBackend
fi
if [ "${nanodroid_nlpbackend:2:1}" -eq 1 ]; then
NLPBACKEND="${NLPBACKEND} nlpBackendApple"
print_info " ++ Apple location backend"
fi
if [ "${nanodroid_nlpbackend:3:1}" -eq 1 ]; then
NLPBACKEND="${NLPBACKEND} nlpBackendRadiocell"
print_info " ++ Radiocell location backend"
fi
for app in ${NLPBACKEND}; do
nanodroid_install_apk ${app}
done
nanodroid_install_file etc/sysconfig/microg-a5k.xml
nanodroid_install_file etc/default-permissions/microg-permissions.xml
else print_info " << without microG"
fi
}
##########################################################################################
# Install Maps API v1 support
##########################################################################################
install_mapsv1 () {
# install mapsv1 if requested
if [ "${nanodroid_mapsv1}" -eq 1 ]; then
print_info " << with Maps API version 1"
nanodroid_install_file etc/permissions/com.google.android.maps.xml
nanodroid_install_file framework/com.google.android.maps.jar
else print_info " << without Maps API version 1"
fi
}
##########################################################################################
# Install F-Droid
##########################################################################################
install_fdroid () {
# install F-Droid if requested
# respectively force if it's the F-Droid package
if [ "${nanodroid_fdroid}" -eq 3 ]; then
install_fdroid_fdroid
install_fdroid_aurora
elif [ "${nanodroid_fdroid}" -eq 2 ]; then
install_fdroid_aurora
elif [ "${nanodroid_fdroid}" -eq 1 -o "${MODID}" = "NanoDroid_FDroid" ]; then
install_fdroid_fdroid
else print_info " << without F-Droid"
fi
}
install_fdroid_aurora () {
print_info " << with Aurora Droid"
nanodroid_install_apk AuroraDroid
nanodroid_install_apk AuroraServices
}
install_fdroid_fdroid () {
print_info " << with F-Droid"
nanodroid_install_apk FDroid
nanodroid_install_apk FDroidPrivileged
${NANODROID_BINDIR}/nanodroid-overlay --add FDroidPriv
nanodroid_install_file etc/org.fdroid.fdroid/additional_repos.xml
}
##########################################################################################
# Install Applications
##########################################################################################
install_apps () {
# install apps if requested
if [ "${nanodroid_apps}" -eq 1 ]; then
print_info " << with applications"
APP_STRING=" <<>"
grep -E -v '^(#|[[:space:]]*$)' "${cfg_apps}" | while read app; do
if [ -d "${INSTALLER}/system/app/${app}" ]; then
print_info " ++ ${app}"
nanodroid_install_apk ${app}
else print_info " ++ app: ${app} missing"
fi
done
else print_info " << without applications"
fi
}
##########################################################################################
# Install App Store
##########################################################################################
install_store () {
STORE_CHOICE=${nanodroid_play:0:1}
FAKE_STORE=${nanodroid_play:1:1}
[ "${FAKE_STORE}" -eq 1 ] && STORE_CONFLICT="Phonesky" || STORE_CONFLICT=""
# install Aurora and/or Play Store whichever requested
case "${STORE_CHOICE}" in
1 )
install_store_play
;;
2 )
install_store_aurora
;;
3 )
install_store_play
install_store_aurora
;;
* )
print_info " << without App Store"
;;
esac
# Only install Fake Store if requested and Play Store is not installed
if [ "${FAKE_STORE}" -eq 1 ]; then
print_info " << with Fake Store"
nanodroid_install_apk FakeStore
else print_info " << without Fake Store"
fi
[ -n "${STORE_CONFLICT}" ] && ${NANODROID_BINDIR}/nanodroid-overlay --add ${STORE_CONFLICT}
if [ "${NANODROID_UPGRADE}" -eq 0 ]; then
rm -rf /data/data/com.android.vending
rm -rf /data/user/*/com.android.vending
rm -rf /data/user_de/*/com.android.vending
rm -rf /data/app/com.android.vending-*
fi
}
install_store_play () {
# force unselect Fake Store when user has choosen Play Store
STORE_CONFLICT="FakeStore"
FAKE_STORE=0
print_info " << with Play Store"
${NANODROID_BINDIR}/nanodroid-overlay --remove Phonesky
nanodroid_install_apk Phonesky
nanodroid_install_file etc/default-permissions/phonesky-permissions.xml
}
install_store_aurora () {
print_info " << with Aurora Store"
nanodroid_install_apk AuroraStore
nanodroid_install_apk AuroraServices
}
##########################################################################################
# Install GNU Bash
##########################################################################################
install_bash () {
if [ "${nanodroid_bash}" -eq 1 ]; then
print_info " << with GNU Bash Shell and Less Pager"
for file in etc/bash_logout etc/bashrc; do
nanodroid_install_file ${file}
done
for file in bin/bash bin/bash.bin.${BIN_ARCH} \
bin/bashbug.${BIN_ARCH} bin/less bin/less.bin.${BIN_ARCH} \
bin/lessecho.${BIN_ARCH} bin/lesskey.${BIN_ARCH}; do
nanodroid_install_file ${file} bin
done
else print_info " << without GNU Bash Shell"
fi
}
##########################################################################################
# Install NanoDroid Scripts
##########################################################################################
install_nanodroidscripts () {
print_info " << with NanoDroid Scripts"
for script in npem nutl novl \
nanodroid-perm nanodroid-util \
nanodroid-overlay; do
nanodroid_install_file bin/${script} bin
done
nanodroid_substitute bin/nanodroid-overlay
if [ "${MODE}" = "MAGISK" ]; then
for script in nprp nanodroid-prop; do
nanodroid_install_file bin/${script} bin
done
nanodroid_substitute bin/nanodroid-prop
fi
}
##########################################################################################
# Install init scripts
##########################################################################################
install_initd () {
if [ -n "${nanodroid_init}" ]; then
print_info " << with init scripts"
if [ "${MODE}" = "SYSTEM" ]; then
INIT_BASE="${MODPATH}/system/etc/init.d"
else INIT_BASE="${MODPATH}/init.d"
fi
mkdir -p "${INIT_BASE}"
for script in ${nanodroid_init}; do
if [ -f "${INSTALLER}/system/etc/init.d/${script}" ]; then
cp "${INSTALLER}/system/etc/init.d/${script}" "${INIT_BASE}/"
set_perm_bin "${INIT_BASE}/${script}"
installinfo_add "/system/etc/init.d/${script}"
else
ui_print " -- ${script} is not a known init script"
fi
done
else print_info " << without init scripts"
fi
}
##########################################################################################
# Install Bromite System WebView
##########################################################################################
install_bromite_webview () {
if [ "${MODID}" = "NanoDroid_BromiteWebView" ]; then
local init_base overlaydir lib_suffix i
[ "$(uname -m)" = "aarch64" ] && lib_suffix=64
[ "$(uname -m)" = "x86_64" ] && lib_suffix=64
for i in system_ext/overlay product/overlay overlay; do
[ -d "/system/${i}" ] && overlaydir="${i}" && break
done
mkdir -p "${TMPDIR}/bromite/res/xml" "${INSTALLER}/system/${overlaydir}"
${AAPT} dump xmltree /system/framework/framework-res.apk res/xml/config_webview_packages.xml | \
parse_aapt_dump_xmltree | sed "s|</webviewproviders>|<webviewprovider availableByDefault=\"true\" description=\"${WEBVIEW_DESC:-Bromite Webview}\" packageName=\"${WEBVIEW_PKG:-org.bromite.webview}\"><signature>${WEBVIEW_SIG:-MIIDbTCCAlWgAwIBAgIEHcsmjjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJERTEQMA4GA1UECBMHVW5rbm93bjEPMA0GA1UEBxMGQmVybGluMRAwDgYDVQQKEwdCcm9taXRlMRAwDgYDVQQLEwdCcm9taXRlMRAwDgYDVQQDEwdjc2FnYW41MCAXDTE4MDExOTA3MjE1N1oYDzIwNjgwMTA3MDcyMTU3WjBmMQswCQYDVQQGEwJERTEQMA4GA1UECBMHVW5rbm93bjEPMA0GA1UEBxMGQmVybGluMRAwDgYDVQQKEwdCcm9taXRlMRAwDgYDVQQLEwdCcm9taXRlMRAwDgYDVQQDEwdjc2FnYW41MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtakjGj0eTavbBB2vWXj8KBixWn4zgXAKc+yGFu3SLEGF1VB5aJWwcMHxVI55yH/8M2eNnJP0BkSidfKgPVcm1sk/GrNEs9uk5sWod9byO5M5QWQmGP2REeTd6J0BVVVaMp2MZnqeR3Su3pwFzrSwTqIGyf8dkPSEz7ifj792+EeRNrov4oRQK7lIfqInzwc4d34wU069Lrw6m7J7HM0KbRYISsWMiYj025Qg+dTrtdWt7jbdcj7htW0eYyJoLd90+s43RWnOpENmWpcWv1EVPxUD4mCdV9idYwoHRIESpSu9IWvqDZp1VoRc43nLgsNfNBwmYdTkIaPiz1m7TBcr7QIDAQABoyEwHzAdBgNVHQ4EFgQUuWoGd7W7wMyQ1pOdjiMv10YHTR0wDQYJKoZIhvcNAQELBQADggEBAA7iw6eKz+T8HIpKDoDcX1Ywjn9JUzuCFu20LnsLzreO/Pog1xErYjdLAS7LTZokfbAnitBskO9QhV9BYkDiM0Qr5v2/HsJTtxa1mz9ywCcI36jblMyuXFj8tuwQI9/t9i+Fc3+bOFBV3t7djPo9qX1dIK0lZ6s8HcIhaCNdqm65fH+nWhC/H9djqC6qOtrkTiACKEcHQ4a/5dfROU0q0M4bS4YuiaAQWgjiGbik4LrZ8wZX1aqJCLt0Hs7MzXyyf0cRSO11FIOViHwzh6WTZGufq2J3YBFXPond8kLxkKL3LNezbi5yTcecxsbKQ6OS46CnIKcy/M8asSreLpoCDvw=}</signature></webviewprovider></webviewproviders>|g" > "${TMPDIR}/bromite/res/xml/config_webview_packages.xml"
mkdir -p "${INSTALLER}/system/${overlaydir}"
${AAPT} package -f -M "${INSTALLER}/AndroidManifest.xml" -I /system/framework/framework-res.apk -S "${TMPDIR}/bromite/res" -F "${TMPDIR}/BromiteOverlay.apk" --target-sdk-version "$(getprop ro.system.build.version.sdk)"
${ZIPALIGN} 4 "${TMPDIR}/BromiteOverlay.apk" "${INSTALLER}/system/${overlaydir}/BromiteOverlay.apk"
jar_sign "${TMPDIR}/BromiteOverlay.apk"
apk_sign "${TMPDIR}/BromiteOverlay.apk"
print_info " << with Bromite WebView"
case ${ARCH} in
arm | arm64 | x86 ) BROMITE_ARCH=${ARCH} ;;
x86_64 ) BROMITE_ARCH=x86 ;;
esac
WEBVIEW_REPLACE=BromiteWebView
WEBVIEW_DIR=""
for app in webview webviewstub WebViewStub Webview; do
if [ -d /system/app/${app} ]; then
WEBVIEW_REPLACE=${app}
break
elif [ -d /system/product/app/${app} ]; then
WEBVIEW_REPLACE=${app}
WEBVIEW_DIR="product/app"
break
fi
done
if [ "${NANODROID_UPGRADE}" -eq 0 ]; then
for app in org.bromite.webview; do
rm -rf /data/data/${app}
rm -rf /data/user/*/${app}
rm -rf /data/user_de/*/${app}
rm -rf /data/app/${app}-*
rm -rf /mnt/asec/${app}-*
rm -rf ${STORAGE}/Android/data/${app}
done
fi
nanodroid_install_apk BromiteWebView_${BROMITE_ARCH} multilib ${WEBVIEW_REPLACE} ${WEBVIEW_DIR}
nanodroid_install_file "${overlaydir}/BromiteOverlay.apk"
fi
}
##########################################################################################
# Install OpenStreetMap Android
##########################################################################################
install_osmand () {
if [ "${MODID}" = "NanoDroid_OsmAnd" ]; then
print_info " << with OsmAnd"
nanodroid_install_apk OsmAnd
nanodroid_install_apk OsmAnd_ContourLines
fi
}
##########################################################################################
# Install Google Sync Adapters
##########################################################################################
install_gsync () {
# install GSync if requested
if [ "${nanodroid_gsync}" -eq 1 ]; then
if [ "${GSYNC_UNSUPPORTED}" -eq 1 ]; then
print_info " << Google Sync Adapters are unsupported on SDK ${SDK_VERSION}"
else
print_info " << with Google Sync Adapters (${GSYNC_VER})"
for app in GoogleCalendarSync GoogleContactsSync GoogleBackupTransport; do
nanodroid_install_apk ${app}
done
nanodroid_install_file etc/default-permissions/google-sync-permissions.xml
fi
else print_info " << without Google Sync Adapters"
fi
}
##########################################################################################
# Install swipe libraries
##########################################################################################
install_swipe () {
if [ "${nanodroid_swipe}" -eq 1 ]; then
if [ "${SWIPE_UNSUPPORTED}" -eq 1 ]; then
print_info " << Swipe Libraries are unsupported on SDK ${SDK_VERSION}"
else
print_info " << with swipe libraries"
SWIPE_SRC="${INSTALLER}/swipe/${ARCH}"
SWIPE_DEST="/system/${SWIPE_LIBDIR}"
APPL_IME="/system/app/LatinIME/${SWIPE_LIBDIR}/${ARCH}"
PRODL_IME="/system/product/app/LatinIME/${SWIPE_LIBDIR}/${ARCH}"
mkdir -p "${MODPATH}${SWIPE_DEST}"
cp "${SWIPE_SRC}/libjni_keyboarddecoder.so" "${MODPATH}${SWIPE_DEST}" || \
error "failed to install libjni_keyboarddecoder.so"
set_perm_data "${MODPATH}${SWIPE_DEST}/libjni_keyboarddecoder.so"
cp "${SWIPE_SRC}/${LIBJNI_IME}" "${MODPATH}${SWIPE_DEST}/libjni_latinimegoogle.so" || \
error "failed to install libjni_latinimegoogle.so"
set_perm_data "${MODPATH}${SWIPE_DEST}/libjni_latinimegoogle.so"
installinfo_add "${SWIPE_DEST}/libjni_keyboarddecoder.so"
installinfo_add "${SWIPE_DEST}/libjni_latinimegoogle.so"
link_swipe_libs "${APPL_IME}"
link_swipe_libs "${PRODL_IME}"
fi
else print_info " << without swipe libraries"
fi
}
link_swipe_libs () {
DEST_IME=${1}
if [ -f "${DEST_IME}/libjni_latinime.so" ]; then
decho " swipe: symlinking libjni_latinimegoogle as libjni_latinime in ${DEST_IME}"
mkdir -p "${MODPATH}${DEST_IME}"
ln -sfn "${MODPATH}${SWIPE_DEST}/libjni_latinimegoogle.so" "${MODPATH}${DEST_IME}/libjni_latinime.so"
ln -sfn "${MODPATH}${SWIPE_DEST}/libjni_keyboarddecoder.so" "${MODPATH}${DEST_IME}/libjni_keyboarddecoder.so"
installinfo_add "${MODPATH}${DEST_IME}/libjni_latinime.so"
installinfo_add "${MODPATH}${DEST_IME}/libjni_keyboarddecoder.so"
elif [ -f "${DEST_IME}/libjni_latinimegoogle.so" ]; then
decho " swipe: symlinking libjni_latinimegoogle as libjni_latinimegoogle in ${DEST_IME}"
mkdir -p "${MODPATH}${DEST_IME}"
ln -sfn "${MODPATH}${SWIPE_DEST}/libjni_latinimegoogle.so" "${MODPATH}${DEST_IME}/libjni_latinimegoogle.so"
ln -sfn "${MODPATH}${SWIPE_DEST}/libjni_keyboarddecoder.so" "${MODPATH}${DEST_IME}/libjni_keyboarddecoder.so"
installinfo_add "${MODPATH}${DEST_IME}/libjni_latinimegoogle.so"
installinfo_add "${MODPATH}${DEST_IME}/libjni_keyboarddecoder.so"
fi
}
##########################################################################################
# SYSTEM MODE addon.d
##########################################################################################
install_addond () {
print_info " << System Mode OTA survival"
cp "${INSTALLER}/CommonAddon" "/system/addon.d/91-nanodroid.sh" || \
error "failed to install System Mode OTA survival"
chmod 0755 "/system/addon.d/91-nanodroid.sh"
}
##########################################################################################
# Advanced Installation Functions
##########################################################################################
##########################################################################################
# Create Uninstaller / addon.d filelist for SYSTEM MODE
##########################################################################################
installinfo_add () {
if [ "${MODE}" = "SYSTEM" ]; then
for file in "${@}"; do
echo "${file}" >> ${NANODROID_LIST}
done
fi
}
##########################################################################################
# NanoDroid installation function for files
##########################################################################################
nanodroid_install_file () {
dir="$(dirname "${1}")"
file="$(basename "${1}")"
unset source
for sdir in system gsync; do
if [ -f "${INSTALLER}/${sdir}/${dir}/${file}" ]; then
source="${INSTALLER}/${sdir}/${dir}/${file}"
break
fi
done
[ -z "${source}" ] && error "file: ${file} not found"
# strip off .${BIN_ARCH} from final filename (if any)
xfile=$(basename "${file}" .${BIN_ARCH})
decho " installing file: ${xfile}"
mkdir -p "${MODPATH}/system/${dir}/"
cp "${source}" "${MODPATH}/system/${dir}/${xfile}" || \
error "failed to install ${xfile}"
case ${2} in
bin ) set_perm_bin "${MODPATH}/system/${dir}/${xfile}" ;;
* ) set_perm_data "${MODPATH}/system/${dir}/${xfile}" ;;
esac
installinfo_add "/system/${dir}/${xfile}"
}
##########################################################################################
# NanoDroid installation function for directories
##########################################################################################
nanodroid_install_dir () {
dir="${1}"
[ -n "${2}" ] && dest="${2}" || dest="/system/${dir}"
[ ! -d "${INSTALLER}/system/${dir}" ] && \
error "dir: ${dir} not found"
echo " installing dir: ${dir}"
mkdir -p "${MODPATH}${dest}"
cp -r "${INSTALLER}/system/${dir}"/* "${MODPATH}${dest}/" || \
error "failed to install ${dir}"
case ${2} in
bin ) set_perm_bin -r "${MODPATH}${dest}" ;;
* ) set_perm_data -r "${MODPATH}${dest}" ;;
esac
find "${INSTALLER}/system/${dir}" -type f | \
sed -e "s,^${INSTALLER},,g" | \
installinfo_add
}
##########################################################################################
# NanoDroid installation function for APKs
##########################################################################################
nanodroid_install_apk () {
app=${1}
multilib=${2}
alias=${3}
unset prefix
unset source
for sdir in system/app system/priv-app \
gsync/${GSYNC_VER}/app gsync/${GSYNC_VER}/priv-app; do
if [ -f "${INSTALLER}/${sdir}/${app}/${app}.apk.zst" ]; then
source="${INSTALLER}/${sdir}/${app}/${app}.apk"
dir=system/$(basename ${sdir})
break
fi
done
[ -n "${4}" ] && dir="system/${4}"
[ -z "${source}" ] && error "app ${app} not found"
if [ "${UNFOLD_APP_DIR}" -eq 1 ]; then
dest="${MODPATH}/${dir}"
else
if [ -z "${alias}" ]; then
dest="${MODPATH}/${dir}/${app}"
else dest="${MODPATH}/${dir}/${alias}"
fi
fi
if [ -n "${alias}" ]; then
dest_apk=${alias}.apk
else dest_apk=${app}.apk
fi
mkdir -p "${dest}"
decho " installing app: ${app}"
decho " from: ${source}"
decho " into: ${dest} [${dest_apk}]"
cp "${source}.zst" "${dest}/${dest_apk}.zst" || \
error "failed to install ${source} to ${dest}"
${ZSTD} -fd --rm "${dest}/${dest_apk}.zst" || \
error "failed to decompress ${dest}/${dest_apk}.zst"
installinfo_add "${dest}/${dest_apk}"
nanodroid_install_lib "${dest}/${dest_apk}" "${2}"
[ "${dir}" = "system/priv-app" ] && create_privapp_permissions_whitelist "$app"
set_perm_data -r "${dest}"
}
##########################################################################################
# NanoDroid installation function for libraries
##########################################################################################
nanodroid_install_lib () {
apk="${1}"
dest="$(dirname "$1")"
multilib="${2}"
unset libd
if [ "${UNFOLD_APP_DIR}" -eq 1 ]; then
case ${ARCH} in
arm | x86 ) libd=${MODPATH}/system/lib ;;
arm64 | x86_64 ) libd=${MODPATH}/system/lib64 ;;
esac
else
libd=${dest}/lib
fi
rm -rf ${TMP_LIBDIR}
mkdir -p ${TMP_LIBDIR}
unset srcdir
"${UNZIP}" -oq "${apk}" "lib/*" -d "${TMP_LIBDIR}" \
2>/dev/null
unzip_return=$?
case ${unzip_return} in
0 ) decho " ${app} does have libs" ;;
11 ) decho " ${app} does not have any libs" ;;
50 ) error " not enough space available!" ;;
* ) error " unpacking libs for ${app} failed [${unzip_return}]" ;;
esac
if [ -d ${TMP_LIBDIR}/lib ]; then
for ARCHLIB in ${LIB_ARCHES}; do
if [ -d ${TMP_LIBDIR}/lib/${ARCHLIB} ]; then
srcdir=${TMP_LIBDIR}/lib/${ARCHLIB}
case ${srcdir} in
*arm64* ) decho " ${app}: installing arm64 libs"
lib_arch=arm64 ;;
*arm* ) decho " ${app}: installing arm libs"
lib_arch=arm ;;
*x86_64* ) decho " ${app}: installing x86_64 libs"
lib_arch=x86_64 ;;
*x86* ) decho " ${app}: installing x86 libs"
lib_arch=x86 ;;
esac
decho " from: ${srcdir}"
decho " into: ${libd}/${lib_arch}"
mkdir -p "${libd}/${lib_arch}"
for lib in ${srcdir}/*; do
decho " library: $(basename ${lib})"
cp ${lib} "${libd}/${lib_arch}/" || \
error " installing libs for ${app} failed"
installinfo_add "${libd}/${lib_arch}/$(basename ${lib})"
done
[ -z "${multilib}" ] && break
fi
done
fi
}
##########################################################################################
# substitute values in installed files
##########################################################################################
nanodroid_substitute () {
dir="$(dirname "${1}")"
file="$(basename "${1}")"
target="${MODPATH}/system/${dir}/${file}"
[ ! -f "${target}" ] && error "file: ${file} not found"
if grep -q @MODPATH@ ${target}; then
sed -e "s|@MODPATH@|${MODPATH}|g" -i ${target}
decho " substitute: adjust @MODPATH@ in ${target}"
fi
if grep -q @MODID@ ${target}; then
sed -e "s|@MODID@|${MODID}|g" -i ${target}
decho " substitute: adjust @MODID@ in ${target}"
fi
if grep -q @MODE@ ${target}; then
sed -e "s|@MODE@|${MODE}|g" -i ${target}
decho " substitute: adjust @MODE@ in ${target}"
fi
}
##########################################################################################
# create installation logs
##########################################################################################
nanodroid_storelogs () {
mkdir -p "${STORAGE}/nanodroid_logs"
echo "\
Installation successful: ${INSTALL_SUCCESS}
### VALUES ###
ZIP=${ZIP}
TMPDIR=${TMPDIR}
TMP_LIBDIR=${TMP_LIBDIR}
INSTALLER=${INSTALLER}
MODID=${MODID}
SDK_VERSION=${SDK_VERSION}
ARCH=${ARCH}
LIB_ARCHES=${LIB_ARCHES}
MODPATH=${MODPATH}
SWIPE_LIBDIR=${SWIPE_LIBDIR}
MODE=${MODE}
MAGISK_VER_CODE=${MAGISK_VER_CODE}
NANODROID_UPGRADE=${NANODROID_UPGRADE}
NANODROID_BINDIR=${NANODROID_BINDIR}
HAS_FAKESIGN=${HAS_FAKESIGN}
### MOUNTED PARTITIONS ###
" >> ${nanodroid_logfile}
mount | awk '{print $1 " on " $3 " params: " $6}' \
>> ${nanodroid_logfile}
echo "
### PARTITION INFORMATION ###
DEVICE_AB=${DEVICE_AB}
VENDOR_COMPAT=${VENDOR_COMPAT}
SYSTEM_AS_ROOT=${SYSTEM_AS_ROOT}
SYSTEM_BLOCK=${SYSTEM_BLOCK}
VENDOR_BLOCK=${VENDOR_BLOCK}
### DISK USAGE ###
" >> ${nanodroid_logfile}
df 2>/dev/null | sed '/^\//d' >> ${nanodroid_logfile}
if [ -n "${cfg_setup}" ]; then
echo "
### SETUP ###
configuration: ${cfg_setup}
" >> ${nanodroid_logfile}
cat "${cfg_setup}" >> ${nanodroid_logfile}
fi
if [ -n "${cfg_apps}" ]; then
echo "
### APPS ###
configuration: ${cfg_apps}
" >> ${nanodroid_logfile}
cat "${cfg_apps}" >> ${nanodroid_logfile}
fi
if [ -n "${cfg_overlay}" ]; then
echo "
### OVERLAY ###
configuration: ${cfg_overlay}
" >> ${nanodroid_logfile}
cat "${cfg_overlay}" >> ${nanodroid_logfile}
fi
chown root:sdcard_rw ${nanodroid_logfile}
chmod 0644 ${nanodroid_logfile}
print_info " | storing installation logs in ${STORAGE}/nanodroid_logs/"
print_info " | NanoDroid log:"
print_info " || ""$(basename ${nanodroid_logfile})"
if [ -d /twres ]; then
nanodroid_twrplog="${STORAGE}/nanodroid_logs/${MODID}_${VERSION}_twrp_${curdate}.log"
cat /tmp/recovery.log > ${nanodroid_twrplog}
chown root:sdcard_rw ${nanodroid_twrplog}
chmod 0644 ${nanodroid_twrplog}
print_info " | TWRP log:"
print_info " || $(basename ${nanodroid_twrplog})"
print_info " "
fi
}
##########################################################################################
# NanoDroid Configuration File Handling
##########################################################################################
get_config () {
config=""
config_exists=0
for path in ${config_locations}; do
if test -r "${path}/.nanodroid-${1}"; then
config="${path}/.nanodroid-${1}"
config_exists=1
return
fi
done
}
set_prop () {
echo "${1}=${2}" >> "${cfg_setup}"
}
##########################################################################################
# Load and verify .nanodroid-setup configuration file
##########################################################################################
get_cfg_setup () {
get_config setup
if [ "$config_exists" -eq 1 ]; then
cfg_setup="${config}"
check_cfg_setup
print_info " > Config | nanodroid-setup | $(dirname ${cfg_setup})"
else
cfg_setup="${INSTALLER}/.nanodroid-setup"
source "${cfg_setup}"
print_info " > Config | nanodroid-setup | fallback"
fi
}
# check whether '.nanodroid-setup' has all required entries
check_cfg_setup () {
# see https://gitlab.com/Nanolx/NanoDroid/-/issues/147
dos2unix "${cfg_setup}" &>/dev/null
source "${cfg_setup}"
[ -z "${nanodroid_fdroid}" ] && set_prop nanodroid_fdroid 1
[ -z "${nanodroid_microg}" ] && set_prop nanodroid_microg 1
[ -z "${nanodroid_apps}" ] && set_prop nanodroid_apps 1
[ -z "${nanodroid_play}" ] && set_prop nanodroid_play 10
# in NanoDroid 20.3 nanodroid_play has changed
if [ "${#nanodroid_play}" -lt 2 ]; then
case "${nanodroid_play}" in
0 ) tmp_prop="00" ;;
1 ) tmp_prop="10" ;;
2 ) tmp_prop="20" ;;
3 ) tmp_prop="01" ;;
4 ) tmp_prop="21" ;;
* ) tmp_prop="10" ;;
esac
sed -e '/^nanodroid_play/d' -i "${cfg_setup}"
set_prop nanodroid_play "${tmp_prop}"
fi
# in NanoDroid 22.5 nanodroid_play has changed
if [ "${nanodroid_play}" -gt 30 ]; then
sed -e '/^nanodroid_play/d' -i "${cfg_setup}"
set_prop nanodroid_play 20
fi
if [ "${MODID}" = "NanoDroid" ]; then
[ -z "${nanodroid_overlay}" ] && set_prop nanodroid_overlay 1
else [ -z "${nanodroid_overlay}" ] && set_prop nanodroid_overlay 0
fi
[ -z "${nanodroid_mapsv1}" ] && set_prop nanodroid_mapsv1 1
[ -z "${nanodroid_gsync}" ] && set_prop nanodroid_gsync 0
[ -z "${nanodroid_forcesystem}" ] && set_prop nanodroid_forcesystem 0
[ -z "${nanodroid_swipe}" ] && set_prop nanodroid_swipe 0
[ -z "${nanodroid_bash}" ] && set_prop nanodroid_bash 1
[ -z "${nanodroid_nlpbackend}" ] && set_prop nanodroid_nlpbackend 1000
# in NanoDroid 20.3 nanodroid_nlpbackend has changed
if [ "${#nanodroid_nlpbackend}" -eq 1 ]; then
case "${nanodroid_nlpbackend}" in
0 ) tmp_prop="0000" ;;
1 ) tmp_prop="1000" ;;
2 ) tmp_prop="0100" ;;
3 ) tmp_prop="1100" ;;
* ) tmp_prop="1000" ;;
esac
sed -e '/^nanodroid_nlpbackend/d' -i "${cfg_setup}"
set_prop nanodroid_nlpbackend "${tmp_prop}"
fi
# in NanoDroid 20.5 nanodroid_nlpbackend has changed (again)
if [ "${#nanodroid_nlpbackend}" -eq 3 ]; then
tmp_prop="${nanodroid_nlpbackend}0"
sed -e '/^nanodroid_nlpbackend/d' -i "${cfg_setup}"
set_prop nanodroid_nlpbackend "${tmp_prop}"
fi
[ -z "${nanodroid_init+x}" ] && set_prop nanodroid_init "${nanodroid_all_init}"
# in NanoDroid 22.7 nanodroid_init has changed
if [ "${#nanodroid_init}" -eq 1 ]; then
sed -e '/^nanodroid_init/d' -i "${cfg_setup}"
set_prop nanodroid_init "${nanodroid_all_init}"
fi
# in NanoDroid 21.0.90 nanodroid_override was dropped
sed -e '/^nanodroid_override/d' -i "${cfg_setup}"
# in NanoDroid 22.5 nanodroid_fonts was dropped
sed -e '/^nanodroid_fonts/d' -i "${cfg_setup}"
# in NanoDroid 22.6 nanodroid_nano was dropped
sed -e '/^nanodroid_nano/d' -i "${cfg_setup}"
# in NanoDroid 22.6 nanodroid_zelda was dropped
sed -e '/^nanodroid_zelda/d' -i "${cfg_setup}"
# in NanoDroid 23.0 nanodroid_utils was dropped
sed -e '/^nanodroid_uitls/d' -i "${cfg_setup}"
source "${cfg_setup}"
}
##########################################################################################
# Load and verify .nanodroid-overlay configuration file
##########################################################################################
get_cfg_overlay () {
get_config overlay
if [ "$config_exists" -eq 1 ]; then
cfg_overlay="${config}"
check_cfg_overlay
print_info " > Config | nanodroid-overlay | $(dirname ${cfg_overlay})"
else
cfg_overlay="${INSTALLER}/.nanodroid-overlay"
print_info " > Config | nanodroid-overlay | fallback"
fi
}
# check whether '.nanodroid-overlay' is up to date
check_cfg_overlay () {
# see https://gitlab.com/Nanolx/NanoDroid/-/issues/147
dos2unix "${cfg_overlay}" &>/dev/null
# 22.0 flagged the following for overlay creation which caused issues
grep -q "^GmsCore$" "${cfg_overlay}" && sed '/^GmsCore$/d' -i "${cfg_overlay}"
grep -q "^GsfProxy$" "${cfg_overlay}" && sed '/^GsfProxy$/d' -i "${cfg_overlay}"
grep -q "^DroidGuard$" "${cfg_overlay}" && sed '/^DroidGuard$/d' -i "${cfg_overlay}"
}
##########################################################################################
# Load and verify .nanodroid-apps configuration file
##########################################################################################
get_cfg_apps () {
get_config apps
if [ "$config_exists" -eq 1 ]; then
cfg_apps="${config}"
check_cfg_apps
print_info " > Config | nanodroid-apps | $(dirname ${cfg_apps})"
else
cfg_apps="${INSTALLER}/.nanodroid-apps"
print_info " > Config | nanodroid-apps | fallback"
fi
}
# check whether '.nanodroid-apps' is up to date
check_cfg_apps () {
# see https://gitlab.com/Nanolx/NanoDroid/-/issues/147
dos2unix "${cfg_apps}" &>/dev/null
# <= 16.3 has KeePass DX instead of KeePassDroid, migrate
grep -q KeePassDroid "${cfg_apps}" && sed -e 's/KeePassDroid/KeePassDX/g' -i "${cfg_apps}"
# <= 17.7 has Substratum instead of Bucket (LibreSubtratum), migrate
grep -q Bucket "${cfg_apps}" && sed -e 's/Bucket/Substratum/g' -i "${cfg_apps}"
# <= 18.1 has Orfox instead of TorBrowser, migrate
grep -q Orfox "${cfg_apps}" && sed -e 's/Orfox/TorBrowser/g' -i "${cfg_apps}"
# >= 20.7.92 no longer ships YahooWeatherProvider, remove
grep -q YahooWeatherProvider "${cfg_apps}" && sed -e '/YahooWeatherProvider/d' -i "${cfg_apps}"
# >= 20.8.90 no longer ships OmniJAWS, remove
grep -q OmniJAWS "${cfg_apps}" && sed -e '/OmniJAWS/d' -i "${cfg_apps}"
# >= 21.0.90 has Alarmio instead of OmniClock, migrate
grep -q OmniClock "${cfg_apps}" && sed -e 's/OmniClock/Alarmio/g' -i "${cfg_apps}"
# >= 21.0.90 no longer ships OpenWeatherMapProvider, remove
grep -q OpenWeatherMapProvider "${cfg_apps}" && sed -e '/OpenWeatherMapProvider/d' -i "${cfg_apps}"
# >= 21.0.90 has Lightning instead of Privacy Browser, migrate
grep -q Lightning "${cfg_apps}" && sed -e 's/Lightning/PrivacyBrowser/g' -i "${cfg_apps}"
# >= 21.0.90 has Hacker's Keyboard instead of BeHeKeyboard, migrate
grep -q BeHeKeyboard "${cfg_apps}" && sed -e 's/BeHeKeyboard/HackersKeyboard/g' -i "${cfg_apps}"
# >= 22.1 has SmartPack-Kernel-Manager instead of Kernel Adiutor, migrate
grep -q KernelAdiutor "${cfg_apps}" && sed -e 's/KernelAdiutor/SmartPackKernelManager/g' -i "${cfg_apps}"
# >= 22.6 has Frost instead of FaceSlim, migrate
grep -q FaceSlim "${cfg_apps}" && sed -e 's/FaceSlim/Frost/g' -i "${cfg_apps}"
# >= 22.6 no longer ships Substratum, remove
grep -q Substratum "${cfg_apps}" && sed -e '/Substratum/d' -i "${cfg_apps}"
# >= 22.6 no longer ships Orbot, remove
grep -q Orbot "${cfg_apps}" && sed -e '/Orbot/d' -i "${cfg_apps}"
# >= 22.7 has OAndBackupX instead of Oandbackup
grep -q Oandbackup "${cfg_apps}" && sed -e 's/Oandbackup/OAndBackupX/g' -i "${cfg_apps}"
# >= 23.1 no longer ships XDA Labs, remove
grep -q XDALabs "${cfg_apps}" && sed -e '/XDALabs/d' -i "${cfg_apps}"
# >= 23.2 no longer ships Blokada, remove
grep -q Blokada "${cfg_apps}" && sed -e '/Blokada/d' -i "${cfg_apps}"
}
##########################################################################################
# Destroy all GApps!
##########################################################################################
gapps_solve_conflicts () {
# first get rid of conflicting packages
print_google_apps | while read app; do
decho " ++ removing app: ${app} [google_apps]"
${NANODROID_BINDIR}/nanodroid-overlay --add ${app}
rm -rf /data/dalvik-cache/*/system"@priv-app@${app}"[@\.]*@classes.*
rm -rf /data/dalvik-cache/*/system"@app@${app}"[@\.]*@classes.*
done
print_google_data | while read app; do
decho " ++ removing data for: ${app} [google_data]"
rm -rf /data/data/${app}
rm -rf /data/user/*/${app}
rm -rf /data/user_de/*/${app}
rm -rf /data/app/${app}-*
rm -rf /mnt/asec/${app}-*
rm -rf ${STORAGE}/Android/data/${app}
done
}
gapps_destroy_artifacts () {
# this removes original Play Services
# only if this is a fresh NanoDroid installation
if [ "${NANODROID_UPGRADE}" -eq 0 ]; then
rm -rf /data/dalvik-cache/*/system"@priv-app@GmsCore"[@\.]*@classes.*
print_google_data_dirty | while read app; do
decho " ++ removing data for: ${app} [google_data_dirty]"
rm -rf /data/data/${app}
rm -rf /data/user/*/${app}
rm -rf /data/user_de/*/${app}
rm -rf /data/app/${app}-*
rm -rf /mnt/asec/${app}-*
rm -rf ${STORAGE}/Android/data/${app}
done
find /data/system* -type f -name 'accounts*db' 2>/dev/null | while read database; do
decho " ++ deleting Google Accounts from ${database} (if any)"
${INSTALLER}/sqlite3.${BIN_ARCH} ${database} \
"DELETE FROM accounts WHERE type='com.google';"
done
find /data/system/users -type f -name 'runtime-permissions.xml' 2>/dev/null | while read file; do
if grep -q "com.google.android" "${file}"; then
decho " ++ resetting permissions: ${file}"
rm -f "${file}"
fi
done
if [ -f /data/system/packages.list ]; then
print_google_data_dirty | while read app; do
decho " ++ de-registering app: ${app} (if installed)"
sed -e "/${app}/d" -i /data/system/packages.list
done
fi
fi
}
##########################################################################################
# GApps debloat list
# mostly by @ale5000
# extended for NanoDroid
##########################################################################################
print_google_apps()
{
cat <<EOF
AMAPNetworkLocation
BaiduNetworkLocation
BlankStore
ConfigUpdater
GCS
GmsCoreSetupPrebuilt
GmsCore_update
GoogleFeedback
GoogleLoginService
GoogleOneTimeInitializer
GoogleServicesFramework
GoogleConnectivityServices
GoogleTTS
LegacyNetworkLocation
MarketUpdater
MarkupGoogle
NetworkLocation
Phonesky
PlayGames
PlayStore
PrebuiltGmsCore
PrebuiltGmsCorePi
PrebuiltGmsCorePix
UnifiedNlp
Velvet
Vending
WhisperPush
EOF
}
print_google_data ()
{
cat <<EOF
com.amap.android.location
com.baidu.location
com.google.android.location
org.microg.nlp
org.microg.unifiednlp
EOF
}
print_google_data_dirty ()
{
cat <<EOF
com.android.vending
com.google.android.gms
com.google.android.gsf
com.google.android.gsf.login
com.google.android.feedback
com.mgoogle.android.gms
EOF
}