Только что получил новый телефон Android 7.0 Nougat, и единственной серьезной проблемой до сих пор является исчезновение настройки тайм-аута точки доступа Wi-Fi.
Вероятно, это та же проблема, что и: https://android.stackexchange.com/questions/168549/hotspot-timeout-setting-gone-in-7-1-nougat , но она началась с 7.0, а не 7.1, и поскольку никто не ответил на этот вопрос, я подумал, что могу попробовать.
Точка доступа, кажется, истекает после 1-2 минут бездействия, я думаю, что это соответствует переходу устройства в спящий режим, что требует от меня перезапуска ISC dhclient
и wpa_supplicant
ручного повторного подключения.
Точка доступа переходит в спящий режим из-за бездействия намного раньше, чем истекает срок аренды DHCP, который она выдала.
У меня включены «Настройки WiFi» → «Дополнительно» «Включить во время сна (ВСЕГДА)». Но мне не нужно включать WiFi, чтобы включить WiFi-точку доступа (IP-модем через WiFi, действующий как точка доступа для моего ноутбука), поэтому я не вижу многих настроек WiFi и не знаю, вступят ли в силу какие-либо настройки WiFi. если Wi-Fi отключен. Я думал, что WiFi включается только для подключения в качестве терминала другой точки доступа, а не при предоставлении точки доступа?
Это работает, и раньше работало надежно и долго в Android 4.2.2 с соответствующими настройками тайм-аута, но теперь без настройки тайм-аута это очень ненадежно, и мне приходится постоянно пробуждать устройство, чтобы использовать Интернет через точку доступа - или полностью отключить спящий режим и очень быстро разрядить аккумулятор. Еще одна причина попробовать рутировать телефон, что также стало намного сложнее в 7.0.
Это может быть связано с:
/etc/hostapd/hostapd_default.conf
:
# Station inactivity limit
#
# If a station does not send anything in ap_max_inactivity seconds, an
# empty data frame is sent to it in order to verify whether it is
# still in range. If this frame is not ACKed, the station will be
# disassociated and then deauthenticated. This feature is used to
# clear station table of old entries when the STAs move out of the
# range.
#
# The station can associate again with the AP if it is still in range;
# this inactivity poll is just used as a nicer way of verifying
# inactivity; i.e., client will not report broken connection because
# disassociation frame is not sent immediately without first polling
# the STA with a data frame.
# default: 300 (i.e., 5 minutes)
#ap_max_inactivity=300
Поэтому мне нужно рутировать телефон, чтобы изменить это значение по умолчанию. Кто-нибудь нашел обходные пути?
Да, это из-за тайм-аутов бездействия. Но без рутирования устройства я не могу точно определить, является ли это конкретным hostapd ap_max_inactivity=300
значением по умолчанию, но я считаю, что это так. Я не уверен, что мой драйвер iwlwifi для Linux 4.10 x86_64 (недавно реструктурированный) не работает должным образом, когда получает пустой фрейм данных.
Но я думаю, что Android действительно не должен запрещать пользователям устанавливать этот параметр, когда он разрешал им в предыдущих версиях.
Исправление, конечно же, заключается в запуске «демона монитора ping», такого как этот сценарий оболочки на клиентском хосте AP (в моем случае Linux):
#!/usr/bin/bash
declare -i wpm_should_exit=0;
function wpm_exit()
{ wpm_should_exit=1;
}
function wlan_ping_monitor()
{ trap 'wpm_exit' HUP INT QUIT TERM;
local the_IF="$1";
declare -i ok=1 i=0;
def_router=$(ip route show default 2>/dev/null |\
sed -rn \
'/^default[[:space:]]via/{s/^.*via[[:space:]]+'\
'//;s/[[:space:]].*$//;p}'); # join above lines!
if [ x == x"$def_router" ]; then
echo "$FUNCNAME: default router is not set. Nothing to do." >&2;
return 1;
fi
kernel_org=$(host www.kernel.org | sed -rn \
'/has[[:space:]]+address/{s/^.*address' \
'[[:space:]]'//;p}'); # join above lines!
if [ x = x"$kernel_org" ]; then
echo "$FUNCNAME: Unable to resolve kernel.org -"\
" must be able to ping an internet host." >&2;
return 1;
fi
logger -p user.info "$FUNCNAME : started.";
sleep 60;
while ((0 == wpm_should_exit)); do
((ok=0));
for (( i=0; i < 3 ; i+=1 )); do
if /usr/bin/ping -n -q -c 2 -W 8 $kernel_org >/dev/null 2>&1 || \
/usr/bin/ping -n -q -c 2 -W 4 $def_router >/dev/null 2>&1; \
then ((ok=1)); break 1 ; fi
logger -p daemon.error \
"$FUNCNAME: ping $def_router or $kernel_org failed.";
sleep 1;
done
if (( ok == 0 )); then
logger -p daemon.error \
"$FUNCNAME"': interface '"$the_IF"\
' is down. Could not ping '$def_router' or '$kernel_org\
'. Restarting Network...' ;
/etc/init.d/network restart || break;
((ok=1));
sleep 60;
else
sleep 8;
fi
done
logger -p daemon.error "$FUNCNAME: restarting network failed.";
rm -vf $PID_FILE;
}
declare -i status=0;
case "$0" in
(\*${BASH_SOURCE})
wlan_ping_monitor ;
status=$?;
;;
esac
((status==0));
Для полноты вот daemon.sh , с помощью которого вышеприведенный скрипт вызывается с помощью «/etc/init.d/network start»:
PID_FILE=/run/wlan_ping_monitor.pid \
daemon /etc/init.d/wlan_ping_monitor.sh
Отсутствуют только встроенные модули bash setpgid и noctty, которые:
setpgid( pid = getpid(), pid );
и
ioctl(0, TIOCSCTTY , 0 );
Но их не обязательно тестировать — просто удалите/закомментируйте — эти встроенные модули легко написать и они доступны по запросу. Они должны быть встроенными, а не программными, потому что они должны влиять на текущий процесс.
Одна странная вещь в сценарии ping заключается в том, что он должен отправить пакет в глобальную сеть Интернет, чтобы сбросить таймер бездействия — недостаточно просто пропинговать телефон, который может не ответить на пакеты ICMP в течение 4 секунд, продолжая проходить. пингуется в WAN.
#!/usr/bin/bash
. /usr/lib64/bash-${BASH_VERSION}_loadables/load.sh
if [ ! -v N_DAEMONS ]; then
declare -xi N_DAEMONS=0;
fi
if [ ! -v TMPDIR ]; then
declare -x TMPDIR=/tmp;
fi
if [ ! -v USER ]; then
declare -x USER=$(whoami);
fi
declare -i daemon_status=0;
function daemon()
{ export \
PID_FILE=${PID_FILE:-${TMPDIR}/${USER}- daemon-${N_DAEMONS}.pid};
declare -xi N_DAEMONS=0;
if [[ "$PID_FILE" =~ ^(.*)[\.][pP][iI][dD]$ ]]; then
export PID_FILE="${BASH_REMATCH[1]}";
fi
while [ -f "$PID_FILE".pid ]; do
((N_DAEMONS+=1));
export PID_FILE="${PID_FILE%-\*}-${N_DAEMONS}";
done
export PID_FILE="${PID_FILE}.pid" LOG_FILE="${PID_FILE}.log";
echo "daemon: PID_FILE: $PID_FILE LOG_FILE: $LOG_FILE" >&2;
declare -i checkjobs_enabled=0;
if shopt -q checkjobs; then
((checkjobs_enabled=1));
shopt -u checkjobs;
fi
trap "" CHLD HUP TERM QUIT EXIT ERR;
{ tty=$(ps -o 'tty=' -p $BASHPID 2>/dev/null);
{ trap "-" CHLD HUP TERM QUIT EXIT ERR;
if [ x != x$tty ] && [ -e /dev/$tty ]; then
noctty < /dev/$tty || :; # another built-in -just comment out
fi
setpgid;
echo "$BASHPID" > "$PID_FILE";
declare -a ps=($(cat /proc/${BASHPID}/stat));
if [ x != x"${ps[3]}" ] && [ "${ps[3]}" != 1 ] && \
[ -d /proc/${ps[3]} ] ; then
echo 'DAEMON: '${ps[3]}' : '$(readlink \
/proc/${ps[3]}/exe) >&2;
fi
exec "$@" </dev/null >${LOG_FILE} 2>&1 ;
} &
exit $?; # our child becomes child of init
}&
declare -i ok=$?;
trap "-" CHLD HUP TERM QUIT EXIT ERR;
if ((checkjobs_enabled)); then
shopt -s checkjobs;
fi
return $ok;
}
case "$0" in
(\*/${BASH_SOURCE}) ;&
(${BASH_SOURCE})
daemon "$@";
((daemon_status=$?));
;;
esac
((daemon_status==0));
Этот демон также уничтожается /etc/init.d/network
остановкой (которая вызывается «перезагрузкой сети»).
Обидно, что при простом переходе от использования точки доступа/маршрутизатора телефона Android 4.2.2 к использованию точки доступа Android 7.0 такие методы должны использоваться клиентами для поддержания «постоянного» подключения к глобальной сети через АП.
Я решил проблему, проверив, включается ли точка доступа каждые 30 секунд, и если нет, включите точку доступа.
Решение достаточно хорошее для меня, так как я жду, пока внешнее устройство подключится к моей точке доступа. После подключения точка доступа не отключается. Мне приходится постоянно держать точку доступа включенной, так как я не знаю, когда внешняя система подключится к моей системе.
JVD