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

Commit e744cfff authored by Irfan Sheriff's avatar Irfan Sheriff
Browse files

Clean up synchronization

- Add delayed disk write in WifiConfigStore
- Remove synchronization and keep all access to config store
throught the state machine thread

Change-Id: I53768a17895e48da7b99542ac95c6c2fddbcb021
parent 95ea6d6d
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -663,7 +663,12 @@ public class WifiService extends IWifiManager.Stub {
     */
    public List<WifiConfiguration> getConfiguredNetworks() {
        enforceAccessPermission();
        return mWifiStateMachine.syncGetConfiguredNetworks();
        if (mWifiStateMachineChannel != null) {
            return mWifiStateMachine.syncGetConfiguredNetworks(mWifiStateMachineChannel);
        } else {
            Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
            return null;
        }
    }

    /**
+192 −177
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ import android.net.wifi.WifiConfiguration.Status;
import android.net.wifi.NetworkUpdateResult;
import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
import android.os.Environment;
import android.os.Message;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Log;

@@ -50,6 +53,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * This class provides the API to manage configured
@@ -136,6 +140,13 @@ class WifiConfigStore {
    private static final String EXCLUSION_LIST_KEY = "exclusionList";
    private static final String EOS = "eos";

    private static HandlerThread sDiskWriteHandlerThread;
    private static DiskWriteHandler sDiskWriteHandler;
    private static Object sDiskWriteHandlerSync = new Object();
    /* Tracks multiple writes on the same thread */
    private static int sWriteSequence = 0;
    private static final int WRITE = 1;

    /**
     * Initialize context, fetch the list of configured networks
     * and enable all stored networks in supplicant.
@@ -153,11 +164,9 @@ class WifiConfigStore {
     */
    static List<WifiConfiguration> getConfiguredNetworks() {
        List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
        synchronized (sConfiguredNetworks) {
        for(WifiConfiguration config : sConfiguredNetworks.values()) {
            networks.add(new WifiConfiguration(config));
        }
        }
        return networks;
    }

@@ -167,7 +176,6 @@ class WifiConfigStore {
     */
    static void enableAllNetworks() {
        boolean networkEnabledStateChanged = false;
        synchronized (sConfiguredNetworks) {
        for(WifiConfiguration config : sConfiguredNetworks.values()) {
            if(config != null && config.status == Status.DISABLED) {
                if(WifiNative.enableNetworkCommand(config.networkId, false)) {
@@ -178,7 +186,6 @@ class WifiConfigStore {
                }
            }
        }
        }

        if (networkEnabledStateChanged) {
            WifiNative.saveConfigCommand();
@@ -226,14 +233,12 @@ class WifiConfigStore {
    static void selectNetwork(int netId) {
        // Reset the priority of each network at start or if it goes too high.
        if (sLastPriority == -1 || sLastPriority > 1000000) {
            synchronized (sConfiguredNetworks) {
            for(WifiConfiguration config : sConfiguredNetworks.values()) {
                if (config.networkId != INVALID_NETWORK_ID) {
                    config.priority = 0;
                    addOrUpdateNetworkNative(config);
                }
            }
            }
            sLastPriority = 0;
        }

@@ -264,10 +269,8 @@ class WifiConfigStore {
        /* enable a new network */
        if (newNetwork && netId != INVALID_NETWORK_ID) {
            WifiNative.enableNetworkCommand(netId, false);
            synchronized (sConfiguredNetworks) {
            sConfiguredNetworks.get(netId).status = Status.ENABLED;
        }
        }
        WifiNative.saveConfigCommand();
        sendConfiguredNetworksChangedBroadcast();
        return result;
@@ -281,13 +284,11 @@ class WifiConfigStore {
    static void forgetNetwork(int netId) {
        if (WifiNative.removeNetworkCommand(netId)) {
            WifiNative.saveConfigCommand();
            synchronized (sConfiguredNetworks) {
            WifiConfiguration config = sConfiguredNetworks.get(netId);
            if (config != null) {
                sConfiguredNetworks.remove(netId);
                sNetworkIds.remove(configKey(config));
            }
            }
            writeIpAndProxyConfigurations();
            sendConfiguredNetworksChangedBroadcast();
        } else {
@@ -319,7 +320,6 @@ class WifiConfigStore {
     */
    static boolean removeNetwork(int netId) {
        boolean ret = WifiNative.removeNetworkCommand(netId);
        synchronized (sConfiguredNetworks) {
        if (ret) {
            WifiConfiguration config = sConfiguredNetworks.get(netId);
            if (config != null) {
@@ -327,7 +327,6 @@ class WifiConfigStore {
                sNetworkIds.remove(configKey(config));
            }
        }
        }
        sendConfiguredNetworksChangedBroadcast();
        return ret;
    }
@@ -349,10 +348,8 @@ class WifiConfigStore {
    static boolean enableNetworkWithoutBroadcast(int netId, boolean disableOthers) {
        boolean ret = WifiNative.enableNetworkCommand(netId, disableOthers);

        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        if (config != null) config.status = Status.ENABLED;
        }

        if (disableOthers) {
            markAllNetworksDisabledExcept(netId);
@@ -375,14 +372,12 @@ class WifiConfigStore {
     */
    static boolean disableNetwork(int netId, int reason) {
        boolean ret = WifiNative.disableNetworkCommand(netId);
        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        /* Only change the reason if the network was not previously disabled */
        if (config != null && config.status != Status.DISABLED) {
            config.status = Status.DISABLED;
            config.disableReason = reason;
        }
        }
        sendConfiguredNetworksChangedBroadcast();
        return ret;
    }
@@ -450,10 +445,8 @@ class WifiConfigStore {
     * Fetch the link properties for a given network id
     */
    static LinkProperties getLinkProperties(int netId) {
        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        if (config != null) return new LinkProperties(config.linkProperties);
        }
        return null;
    }

@@ -493,7 +486,6 @@ class WifiConfigStore {
    static void setIpConfiguration(int netId, DhcpInfoInternal dhcpInfo) {
        LinkProperties linkProperties = dhcpInfo.makeLinkProperties();

        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        if (config != null) {
            // add old proxy details
@@ -503,13 +495,11 @@ class WifiConfigStore {
            config.linkProperties = linkProperties;
        }
    }
    }

    /**
     * clear IP configuration for a given network id
     */
    static void clearIpConfiguration(int netId) {
        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        if (config != null && config.linkProperties != null) {
            // Clear everything except proxy
@@ -518,7 +508,6 @@ class WifiConfigStore {
            config.linkProperties.setHttpProxy(proxy);
        }
    }
    }


    /**
@@ -536,12 +525,10 @@ class WifiConfigStore {
     * Return if the specified network is using static IP
     */
    static boolean isUsingStaticIp(int netId) {
        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        if (config != null && config.ipAssignment == IpAssignment.STATIC) {
            return true;
        }
        }
        return false;
    }

@@ -555,7 +542,6 @@ class WifiConfigStore {
        String listStr = WifiNative.listNetworksCommand();
        sLastPriority = 0;

        synchronized (sConfiguredNetworks) {
        sConfiguredNetworks.clear();
        sNetworkIds.clear();

@@ -590,13 +576,12 @@ class WifiConfigStore {
            sConfiguredNetworks.put(config.networkId, config);
            sNetworkIds.put(configKey(config), config.networkId);
        }
        }

        readIpAndProxyConfigurations();
        sendConfiguredNetworksChangedBroadcast();
    }

    static void updateIpAndProxyFromWpsConfig(int netId, WpsInfo wpsConfig) {
        synchronized (sConfiguredNetworks) {
        WifiConfiguration config = sConfiguredNetworks.get(netId);
        if (config != null) {
            config.ipAssignment = wpsConfig.ipAssignment;
@@ -605,11 +590,9 @@ class WifiConfigStore {
            writeIpAndProxyConfigurations();
        }
    }
    }

    /* Mark all networks except specified netId as disabled */
    private static void markAllNetworksDisabledExcept(int netId) {
        synchronized (sConfiguredNetworks) {
        for(WifiConfiguration config : sConfiguredNetworks.values()) {
            if(config != null && config.networkId != netId) {
                if (config.status != Status.DISABLED) {
@@ -619,7 +602,6 @@ class WifiConfigStore {
            }
        }
    }
    }

    private static void markAllNetworksDisabled() {
        markAllNetworksDisabledExcept(INVALID_NETWORK_ID);
@@ -627,6 +609,38 @@ class WifiConfigStore {

    private static void writeIpAndProxyConfigurations() {

        /* Make a copy */
        List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>();
        for(WifiConfiguration config : sConfiguredNetworks.values()) {
            networks.add(new WifiConfiguration(config));
        }

        /* Do a delayed write to disk on a seperate handler thread */
        synchronized (sDiskWriteHandlerSync) {
            if (++sWriteSequence == 1) {
                sDiskWriteHandlerThread = new HandlerThread("WifiConfigThread");
                sDiskWriteHandlerThread.start();
                sDiskWriteHandler = new DiskWriteHandler(sDiskWriteHandlerThread.getLooper());
            }
        }

        sDiskWriteHandler.sendMessage(Message.obtain(sDiskWriteHandler, WRITE, networks));
    }

    private static class DiskWriteHandler extends Handler {

        DiskWriteHandler(android.os.Looper l) {
            super(l);
        }

        public void handleMessage(Message msg) {

            if (msg.what != WRITE) {
                throw new RuntimeException("Unsupported message in WifiConfigStore: " + msg);
            }

            List<WifiConfiguration> networks = (List<WifiConfiguration>) msg.obj;

            DataOutputStream out = null;
            try {
                out = new DataOutputStream(new BufferedOutputStream(
@@ -634,8 +648,7 @@ class WifiConfigStore {

                out.writeInt(IPCONFIG_FILE_VERSION);

            synchronized (sConfiguredNetworks) {
                for(WifiConfiguration config : sConfiguredNetworks.values()) {
                for(WifiConfiguration config : networks) {
                    boolean writeToFile = false;

                    try {
@@ -720,7 +733,6 @@ class WifiConfigStore {
                    }
                    out.writeUTF(EOS);
                }
            }

            } catch (IOException e) {
                loge("Error writing data file");
@@ -730,6 +742,16 @@ class WifiConfigStore {
                        out.close();
                    } catch (Exception e) {}
                }

                //Quit if no more writes sent
                synchronized (sDiskWriteHandlerSync) {
                    if (--sWriteSequence == 0) {
                        getLooper().quit();
                        sDiskWriteHandlerThread = null;
                        sDiskWriteHandler= null;
                    }
                }
            }
       }
    }

@@ -806,7 +828,6 @@ class WifiConfigStore {
                } while (true);

                if (id != -1) {
                    synchronized (sConfiguredNetworks) {
                    WifiConfiguration config = sConfiguredNetworks.get(
                            sNetworkIds.get(id));

@@ -845,7 +866,6 @@ class WifiConfigStore {
                                break;
                        }
                    }
                    }
                } else {
                    loge("Missing id while parsing configuration");
                }
@@ -1061,10 +1081,7 @@ class WifiConfigStore {
         * when written. For example, wep key is stored as * irrespective
         * of the value sent to the supplicant
         */
        WifiConfiguration sConfig;
        synchronized (sConfiguredNetworks) {
            sConfig = sConfiguredNetworks.get(netId);
        }
        WifiConfiguration sConfig = sConfiguredNetworks.get(netId);
        if (sConfig == null) {
            sConfig = new WifiConfiguration();
            sConfig.networkId = netId;
@@ -1072,10 +1089,8 @@ class WifiConfigStore {

        readNetworkVariables(sConfig);

        synchronized (sConfiguredNetworks) {
        sConfiguredNetworks.put(netId, sConfig);
        sNetworkIds.put(configKey(sConfig), netId);
        }

        NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(sConfig, config);
        result.setNetworkId(netId);
+11 −2
Original line number Diff line number Diff line
@@ -276,6 +276,8 @@ public class WifiStateMachine extends StateMachine {
    static final int CMD_CLEAR_BLACKLIST                  = BASE + 58;
    /* Save configuration */
    static final int CMD_SAVE_CONFIG                      = BASE + 59;
    /* Get configured networks*/
    static final int CMD_GET_CONFIGURED_NETWORKS          = BASE + 60;

    /* Supplicant commands after driver start*/
    /* Initiate a scan */
@@ -847,8 +849,11 @@ public class WifiStateMachine extends StateMachine {
        return result;
    }

    public List<WifiConfiguration> syncGetConfiguredNetworks() {
        return WifiConfigStore.getConfiguredNetworks();
    public List<WifiConfiguration> syncGetConfiguredNetworks(AsyncChannel channel) {
        Message resultMsg = channel.sendMessageSynchronously(CMD_GET_CONFIGURED_NETWORKS);
        List<WifiConfiguration> result = (List<WifiConfiguration>) resultMsg.obj;
        resultMsg.recycle();
        return result;
    }

    /**
@@ -1811,6 +1816,10 @@ public class WifiStateMachine extends StateMachine {
                case CMD_SAVE_CONFIG:
                    mReplyChannel.replyToMessage(message, message.what, FAILURE);
                    break;
                case CMD_GET_CONFIGURED_NETWORKS:
                    mReplyChannel.replyToMessage(message, message.what,
                            WifiConfigStore.getConfiguredNetworks());
                    break;
                case CMD_ENABLE_RSSI_POLL:
                    mEnableRssiPolling = (message.arg1 == 1);
                    break;