Настройка тайм-аута точки доступа Wi-Fi исчезла в Nougat 7.0, 7.1, но тайм-аута нет

Только что получил новый телефон 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

Поэтому мне нужно рутировать телефон, чтобы изменить это значение по умолчанию. Кто-нибудь нашел обходные пути?

Ага! Это может быть связано с этим файлом:

Ответы (2)

Да, это из-за тайм-аутов бездействия. Но без рутирования устройства я не могу точно определить, является ли это конкретным 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 такие методы должны использоваться клиентами для поддержания «постоянного» подключения к глобальной сети через АП.

или вы можете использовать NetworkManager, чего я не делаю.
Это ошибка ядра Linux: bugzilla.kernel.org/show_bug.cgi?id=194931 Ядро может лучше реагировать на пустой фрейм данных, отправленный Nougat hostapd по тайм-ауту ap_max_inactivity=300. Также wpa_supplicant должен обнаруживать, что ссылка не работает, и повторно инициализировать.

Я решил проблему, проверив, включается ли точка доступа каждые 30 секунд, и если нет, включите точку доступа.

Решение достаточно хорошее для меня, так как я жду, пока внешнее устройство подключится к моей точке доступа. После подключения точка доступа не отключается. Мне приходится постоянно держать точку доступа включенной, так как я не знаю, когда внешняя система подключится к моей системе.