En el Moto G3 tengo LineageOS 14.1 y solo adb root (no hay binario su, el root es del adbd, no de las apps). Eso hace que AdAway falle al tocar ENABLE AD-BLOCKING con este error en el logcat:

HostsInstallException: Failed to start a root shell
Caused by: Cannot run program "su": error=13, Permission denied

La solución es hacer a mano los pasos que AdAway haría con su shell root. Probado con AdAway 4.3.6 (la última compatible con Android 7 / SDK 25).

Procedimiento completo

1. Config de fuentes (hosts_sources)

Si tenés otro teléfono ya configurado, copiarle la base de datos:

# En el telefono con Magisk (G4):
su -c cp /data/data/org.adaway/databases/app.db /sdcard/
adb pull /sdcard/app.db .

# En el G3:
adb push app.db /data/data/org.adaway/databases/app.db
adb shell "rm /data/data/org.adaway/databases/app.db-wal \
                /data/data/org.adaway/databases/app.db-shm 2>/dev/null; true"
adb shell "chown u0_a96:u0_a96 /data/data/org.adaway/databases/app.db; chmod 660 ..."

El uid cambia por instalación (stat -c %U o dumpsys package org.adaway).

2. Bajar las listas

Con la config cargada, tocar ENABLE AD-BLOCKING una vez aunque falle: AdAway descarga y deja el merge en /data/data/org.adaway/files/hosts_downloaded (~615k lineas). Alternativa manual: concatenar las URLs y limpiar comentarios.

3. Crear el hosts final en /data/data

El archivo TIENE que empezar con estas dos líneas exactas o AdAway no lo reconoce como instalado (ApplyUtils.isHostsFileCorrect compara la primera linea contra HEADER1):

# This hosts file has been generated by AdAway on:<fecha>
# Please do not modify it directly, it will be overwritten when AdAway is applied again.
<contenido de hosts_downloaded>
adb root && adb shell "
D=\$(date)
{ echo '# This hosts file has been generated by AdAway on:'\$D
  echo '# Please do not modify it directly, it will be overwritten when AdAway is applied again.'
  cat /data/data/org.adaway/files/hosts_downloaded
} > /data/data/hosts
chmod 644 /data/data/hosts"

AdAway valida el estado mirando el symlink (para el metodo writeToDataData, isSymlinkCorrect exige que readlink devuelva exactamente /data/data/hosts):

adb shell "
mount -o remount,rw /system 2>/dev/null || mount -o remount,rw /
rm /system/etc/hosts
ln -s /data/data/hosts /system/etc/hosts
mount -o remount,ro /system"

5. Preferencias: applyMethod = writeToDataData

Editar /data/data/org.adaway/shared_prefs/preferences.xml (force-stop antes) y agregar:

<string name="applyMethod">writeToDataData</string>

chown/chmod igual que en el paso 1 (owner de la app, 660).

6. Marcar las fuentes como instaladas

Sin este paso la UI muestra “Update available” porque last_modified_local=0. Es lo mismo que hace markHostsSourcesAsInstalled():

sqlite3 /data/data/org.adaway/databases/app.db \
  "UPDATE hosts_sources SET last_modified_local = last_modified_online;"

Esquema: hosts_sources(url, enabled, last_modified_local, last_modified_online).

7. Verificar

Abrir AdAway → tiene que decir “Enabled”. Test DNS:

ping -c1 doubleclick.net      # -> unknown host
ping -c1 googleadservices.com # -> 127.0.0.1

IMPORTANTE

No tocar UPDATE HOSTS desde la UI: va a volver a fallar en el paso del su y rompe el estado. Cuando se quieran actualizar las listas, repetir pasos 2→6 (o hacer un script).

Por qué /data/data/hosts y no /system/etc/hosts directo

Podría escribirse el archivo directamente en /system/etc/hosts con applyMethod=writeToSystem, pero entonces isSymlinkCorrect falla y la app queda en “Disabled” aunque el bloqueo ande. Con el symlink ambos chequeos pasan y el estado de la UI es consistente con la realidad. El bloqueo funciona igual en los dos casos (netd lee el path resuelto).