5

Just got a new Android 7.0 Nougat phone , and only major gripe so far is disappearance of the Wi-Fi-hotspot timeout setting .

This is probably the same issue as : https://android.stackexchange.com/questions/168549/hotspot-timeout-setting-gone-in-7-1-nougat , but it did start with 7.0, not 7.1 , and since no-one has answered that question, I thought I might as well try.

The Hotspot seems to time out after 1-2 mins of inactivity, I think corresponding to the device going to sleep, requiring me to restart ISC dhclient & wpa_supplicant manually to re-connect.

The Hotspot goes to sleap due to inactivity much sooner than the DHCP lease it has given out expires.

I have WiFi Settings → Advanced 'On during sleep ( ALWAYS )' enabled. But I do not need to enable WiFi to enable the WiFi-Hotspot (IP Tethering over WiFi, acting as an Access Point for my laptop), so I do not see many WiFi settings, and do not know if any WiFi setting would take effect if WiFi is disabled. I thought one enables WiFi only to connect as terminal of another Access Point, not when providing an AP?

It does work, and used to work reliably & long-term in Android 4.2.2 with appropriate timeout settings, but now with no timeout setting it is highly unreliable and I have to keep waking up the device to use the internet via Hotspot - or disable sleep mode entirely and drain the battery very quickly. Another reason to try and root the phone, which is also made much harder by 7.0.

It could be something to do with :

/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

So I need to root the phone to change this default value. Has anyone found any workarounds ?

1
  • Aha! It could be something to do with this file :
    – JVD
    Mar 17, 2017 at 5:31

2 Answers 2

1

Yes, it is because of inactivity timeouts. But without rooting the device I cannot determine for sure if it is that specific hostapd ap_max_inactivity=300 default, but I believe it is. I'm not sure if it is the case that my Linux 4.10 x86_64 iwlwifi driver (recently restructured) is not acting appropriately when it receives the empty data frame.

But, I think it is really not in for Android to decide to prevent users from setting this parameter anymore, when it used to let them in previous versions.

The fix is, of course, to start a 'ping monitor daemon', like this shell script on the AP client host (Linux in my case):

#!/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));

For completeness, here is daemon.sh, with which the above script is invoked by '/etc/init.d/network start':

PID_FILE=/run/wlan_ping_monitor.pid \
   daemon /etc/init.d/wlan_ping_monitor.sh

Missing is only the 'setpgid' and 'noctty' bash built-ins, which does:

setpgid( pid = getpid(), pid );

and

ioctl(0, TIOCSCTTY , 0 );

But, they are not strictly necessary to test - just remove / comment out - these built-ins are easy to write & available on request. They must be built-ins, not programs, because they must effect the current process.

One weird thing about the ping script is that it must send a packet out to the WAN internet to reset the inactivity timer - it is not enough to simply ping the phone , which can fail to respond to ICMP packets within 4 seconds while still passing through pings to the 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));

This daemon is also killed by /etc/init.d/network stop (which is invoked by 'network restart').

It is a shame that it is necessary, when simply moving from using an Android 4.2.2 phone Access Point / router to using an Android 7.0 AP, that such methods must be used by clients to maintain an 'always on' WAN internet connection through the AP.

2
  • or you could use NetworkManager, which I don't.
    – JVD
    Mar 17, 2017 at 18:27
  • This is linux kernel bug : bugzilla.kernel.org/show_bug.cgi?id=194931 The kernel could be responding better to the empty data frame sent by Nougat hostapd on ap_max_inactivity=300 timeout. Also wpa_supplicant should be detecting the link has gone dead & re-initializing.
    – JVD
    Mar 22, 2017 at 19:04
0

I solved the problem by checking if the hotspot was enabled every 30s and if it is not, enable the hot spot.

The solution is good enought for me since I wait for an external device to connect to my hotspot. Once it is connected the hotspot won't disable. I have to keep the hotspot on at all times since I don't know when the external system is going to connect to my system.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .