Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c9705cc authored by bnarasimha's avatar bnarasimha
Browse files

Tethering: Turn off wifi hotspot after inactivity(1/3)

Turn off the Wi-Fi hotspot after a specified time of inactivity.
The hotspot is considered to be inactive when no clients are
connected to it.

Change-Id: I84a66f73bec31b68d1feda3eb0b533cb5aad9fd1
parent 5a79c7ff
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.settingslib;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.SystemProperties;
import android.telephony.CarrierConfigManager;

@@ -28,6 +29,12 @@ public class TetherUtil {
             .KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
    }

    public static boolean setWifiTethering(boolean enable, Context context) {
        final WifiManager wifiManager =
                (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        return wifiManager.setWifiApEnabled(null, enable);
    }

    public static boolean isProvisioningNeeded(Context context) {
        // Keep in sync with other usage of config_mobile_hotspot_provision_app.
        // ConnectivityManager#enforceTetherChangePermission
+52 −5
Original line number Diff line number Diff line
@@ -44,8 +44,10 @@ import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.wifi.WifiDevice;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiConfiguration;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
@@ -206,6 +208,9 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
    private static final int DNSMASQ_POLLING_INTERVAL = 1000;
    private static final int DNSMASQ_POLLING_MAX_TIMES = 10;

    private long mWiFiApInactivityTimeout;
    private final Handler mHandler;

    public Tethering(Context context, INetworkManagementService nmService,
            INetworkStatsService statsService) {
        mContext = context;
@@ -221,6 +226,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
        mTetherMasterSM.start();

        mHandler = new Handler(mLooper);

        mUpstreamNetworkMonitor = new UpstreamNetworkMonitor();

        mStateReceiver = new StateReceiver();
@@ -296,9 +303,6 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
        // Never called directly: only called from interfaceLinkStateChanged.
        // See NetlinkHandler.cpp:71.
        if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
        WifiManager mWifiManager =
                (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        WifiDevice device = new WifiDevice(iface);
        synchronized (mPublicSync) {
            int interfaceType = ifaceNameToType(iface);
            if (interfaceType == ConnectivityManager.TETHERING_INVALID) {
@@ -309,13 +313,27 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
            if (up) {
                if (tetherState == null) {
                    trackNewTetherableInterface(iface, interfaceType);
                    mConnectedDeviceMap.put(device.deviceAddress, device);
                }
                else if (isWifi(iface)) {
                    // check if the user has specified an inactivity timeout for wifi AP and
                    // if so schedule the timeout
                    final WifiManager wm =
                            (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
                    final WifiConfiguration apConfig = wm.getWifiApConfiguration();
                    mWiFiApInactivityTimeout =
                            apConfig != null ? apConfig.wifiApInactivityTimeout : 0;
                    if (mWiFiApInactivityTimeout > 0 && mL2ConnectedDeviceMap.size() == 0) {
                        scheduleInactivityTimeout();
                    }
                }
            } else {
                if (interfaceType == ConnectivityManager.TETHERING_BLUETOOTH) {
                    tetherState.mStateMachine.sendMessage(
                            TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
                    mTetherStates.remove(iface);
                    if(isWifi(iface)) {
                        cancelInactivityTimeout();
                    }
                    mConnectedDeviceMap.remove(iface);
                }
            }
@@ -1187,17 +1205,46 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                    new DnsmasqThread(this, device,
                            DNSMASQ_POLLING_INTERVAL, DNSMASQ_POLLING_MAX_TIMES).start();
                }
                //cancelInactivityTimeout();
                cancelInactivityTimeout();
            } else if (device.deviceState == WifiDevice.DISCONNECTED) {
                mL2ConnectedDeviceMap.remove(device.deviceAddress);
                mConnectedDeviceMap.remove(device.deviceAddress);
                sendTetherConnectStateChangedBroadcast();

                //schedule inactivity timeout if non-zero and no more devices are connected
                if (mWiFiApInactivityTimeout > 0 && mL2ConnectedDeviceMap.size() == 0) {
                    scheduleInactivityTimeout();
                }

            }
        } catch (IllegalArgumentException ex) {
            Log.e(TAG, "WifiDevice IllegalArgument: " + ex);
        }
    }

    private final Runnable mDisableWifiApRunnable = new Runnable() {
        @Override
        public void run() {
            if (VDBG) Log.d(TAG, "Turning off hotpost due to inactivity");
            final WifiManager wifiManager =
                    (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            wifiManager.setWifiApEnabled(null, false);
        }
    };

    private void scheduleInactivityTimeout() {
        if (mWiFiApInactivityTimeout > 0) {
            if (VDBG) Log.d(TAG, "scheduleInactivityTimeout: " + mWiFiApInactivityTimeout);
            mHandler.removeCallbacks(mDisableWifiApRunnable);
            mHandler.postDelayed(mDisableWifiApRunnable, mWiFiApInactivityTimeout);
        }
    }

    private void cancelInactivityTimeout() {
        if (VDBG) Log.d(TAG, "cancelInactivityTimeout");
        mHandler.removeCallbacks(mDisableWifiApRunnable);
    }


    public String[] getTetherableIfaces() {
        ArrayList<String> list = new ArrayList<String>();
+10 −0
Original line number Diff line number Diff line
@@ -460,6 +460,13 @@ public class WifiConfiguration implements Parcelable {
     */
    public int userApproved = USER_UNSPECIFIED;

    /**
     * @hide
     * Inactivity time before wifi tethering is disabled.  Here inactivity means no clients
     * connected.  A value of 0 means the AP will not be disabled when there is no activity
     */
    public long wifiApInactivityTimeout;

    /** The Below RSSI thresholds are used to configure AutoJoin
     *  - GOOD/LOW/BAD thresholds are used so as to calculate link score
     *  - UNWANTED_SOFT are used by the blacklisting logic so as to handle
@@ -1921,6 +1928,7 @@ public class WifiConfiguration implements Parcelable {
            updateTime = source.updateTime;
            shared = source.shared;
            SIMNum = source.SIMNum;
            wifiApInactivityTimeout = source.wifiApInactivityTimeout;
        }
    }

@@ -1992,6 +2000,7 @@ public class WifiConfiguration implements Parcelable {
        dest.writeInt(shared ? 1 : 0);
        dest.writeString(mPasspointManagementObjectTree);
        dest.writeInt(SIMNum);
        dest.writeLong(wifiApInactivityTimeout);
    }

    /** Implement the Parcelable interface {@hide} */
@@ -2064,6 +2073,7 @@ public class WifiConfiguration implements Parcelable {
                config.shared = in.readInt() != 0;
                config.mPasspointManagementObjectTree = in.readString();
                config.SIMNum = in.readInt();
                config.wifiApInactivityTimeout = in.readLong();
                return config;
            }