Wi-Fi hotspot timeout setting gone in Nougat 7.0 , 7.1, but timeout has not
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&gt;/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." &gt;&amp;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." &gt;&amp;2;
     return 1;
  fi
  logger -p user.info "$FUNCNAME : started.";
  sleep 60;
  while ((0 == wpm_should_exit)); do
      ((ok=0));
        for (( i=0; i &lt; 3 ; i+=1 )); do
        if /usr/bin/ping -n -q -c 2 -W 8 $kernel_org &gt;/dev/null 2&gt;&amp;1 || \
           /usr/bin/ping -n -q -c 2 -W 4 $def_router &gt;/dev/null 2&gt;&amp;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 &amp; 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" &gt;&amp;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&gt;/dev/null);
      { trap "-" CHLD HUP TERM QUIT EXIT ERR;
        if [ x != x$tty ] &amp;&amp; [ -e /dev/$tty ]; then 
           noctty &lt; /dev/$tty || :; # another built-in -just comment out
        fi
        setpgid;
        echo "$BASHPID" &gt; "$PID_FILE";
        declare -a ps=($(cat /proc/${BASHPID}/stat));
        if [ x != x"${ps[3]}" ] &amp;&amp; [ "${ps[3]}" != 1 ] &amp;&amp; \
           [ -d /proc/${ps[3]} ] ; then
           echo 'DAEMON: '${ps[3]}' : '$(readlink  \
              /proc/${ps[3]}/exe) &gt;&amp;2;
        fi
        exec "$@" &lt;/dev/null  &gt;${LOG_FILE} 2&gt;&amp;1 ;
      } &amp;
      exit $?; # our child becomes child of init
    }&amp;
    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}) ;&amp;
   (${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.