#!/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% *}" 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% *}" 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 "${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 <>"${tmpdir}/META-INF/MANIFEST.MF" Name: ${i#${tmpdir}/*} SHA-256-Digest: $(hex2bin "$(sha256sum "${i}" | awk '{print $1}')" | base64 | tr -d '[:space:]') EOF done cat <"${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 <>"${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 ' ' > "${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 ' ' >> "${app_whitelist}" fi done echo ' ' >> "${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||${WEBVIEW_SIG:-MIIDbTCCAlWgAwIBAgIEHcsmjjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJERTEQMA4GA1UECBMHVW5rbm93bjEPMA0GA1UEBxMGQmVybGluMRAwDgYDVQQKEwdCcm9taXRlMRAwDgYDVQQLEwdCcm9taXRlMRAwDgYDVQQDEwdjc2FnYW41MCAXDTE4MDExOTA3MjE1N1oYDzIwNjgwMTA3MDcyMTU3WjBmMQswCQYDVQQGEwJERTEQMA4GA1UECBMHVW5rbm93bjEPMA0GA1UEBxMGQmVybGluMRAwDgYDVQQKEwdCcm9taXRlMRAwDgYDVQQLEwdCcm9taXRlMRAwDgYDVQQDEwdjc2FnYW41MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtakjGj0eTavbBB2vWXj8KBixWn4zgXAKc+yGFu3SLEGF1VB5aJWwcMHxVI55yH/8M2eNnJP0BkSidfKgPVcm1sk/GrNEs9uk5sWod9byO5M5QWQmGP2REeTd6J0BVVVaMp2MZnqeR3Su3pwFzrSwTqIGyf8dkPSEz7ifj792+EeRNrov4oRQK7lIfqInzwc4d34wU069Lrw6m7J7HM0KbRYISsWMiYj025Qg+dTrtdWt7jbdcj7htW0eYyJoLd90+s43RWnOpENmWpcWv1EVPxUD4mCdV9idYwoHRIESpSu9IWvqDZp1VoRc43nLgsNfNBwmYdTkIaPiz1m7TBcr7QIDAQABoyEwHzAdBgNVHQ4EFgQUuWoGd7W7wMyQ1pOdjiMv10YHTR0wDQYJKoZIhvcNAQELBQADggEBAA7iw6eKz+T8HIpKDoDcX1Ywjn9JUzuCFu20LnsLzreO/Pog1xErYjdLAS7LTZokfbAnitBskO9QhV9BYkDiM0Qr5v2/HsJTtxa1mz9ywCcI36jblMyuXFj8tuwQI9/t9i+Fc3+bOFBV3t7djPo9qX1dIK0lZ6s8HcIhaCNdqm65fH+nWhC/H9djqC6qOtrkTiACKEcHQ4a/5dfROU0q0M4bS4YuiaAQWgjiGbik4LrZ8wZX1aqJCLt0Hs7MzXyyf0cRSO11FIOViHwzh6WTZGufq2J3YBFXPond8kLxkKL3LNezbi5yTcecxsbKQ6OS46CnIKcy/M8asSreLpoCDvw=}|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 <