package com.lechucksoftware.proxy.proxysettings; import android.content.Context; import android.content.Intent; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.text.TextUtils; import android.util.Log; import com.lechucksoftware.proxy.proxysettings.constants.Intents; import com.lechucksoftware.proxy.proxysettings.services.SaveWifiNetworkService; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; import be.shouldit.proxy.lib.APL; import be.shouldit.proxy.lib.APLNetworkId; import be.shouldit.proxy.lib.WiFiApConfig; import be.shouldit.proxy.lib.enums.SecurityType; import be.shouldit.proxy.lib.utils.ProxyUtils; import timber.log.Timber; /** * Created by Marco on 15/09/13. */ public class WifiNetworksManager { private static final String TAG = WifiNetworksManager.class.getSimpleName(); private final Object wifiNetworkStatusLock = new Object(); private WifiNetworkStatus wifiNetworkStatus; private Context context; private ConcurrentLinkedQueue<WiFiApConfig> saveOperations; public Integer savingOperationsCount() { Integer current = saveOperations.size(); Timber.d("Saving operations: %d", current); return current; } public WifiNetworkStatus getWifiNetworkStatus() { if (wifiNetworkStatus == null) { Timber.w("Cannot find valid instance of WifiNetworkStatus, trying to instantiate a new one"); wifiNetworkStatus = new WifiNetworkStatus(); } return wifiNetworkStatus; } public void addSavingOperation(List<WiFiApConfig> configurations) { if (configurations != null) { addSavingOperation(configurations.toArray(new WiFiApConfig[configurations.size()])); } } public void addSavingOperation(WiFiApConfig ... config) { saveOperations.addAll(Arrays.asList(config)); Timber.d("Save operations: %d (after ADD)", saveOperations.size()); Intents.callIntent(context, Intents.PROXY_REFRESH_UI); Intent serviceIntent = new Intent(context, SaveWifiNetworkService.class); context.startService(serviceIntent); } public WiFiApConfig getSavingOperation() { WiFiApConfig config = saveOperations.poll(); Timber.d("Save operations: %d (after REMOVE)", saveOperations.size()); return config; } public WifiNetworksManager(Context ctx) { context = ctx; saveOperations = new ConcurrentLinkedQueue<>(); } public void updateWifiApConfigs() { synchronized (wifiNetworkStatusLock) { App.getTraceUtils().startTrace(TAG,"updateWifiApConfigs", Log.DEBUG, true); Map<APLNetworkId,WiFiApConfig> configurations = APL.getWifiAPConfigurations(); for (APLNetworkId aplNetworkId : configurations.keySet()) { getWifiNetworkStatus().put(aplNetworkId, configurations.get(aplNetworkId)); } App.getTraceUtils().partialTrace(TAG,"updateWifiApConfigs", "Got WifiAPConfigurations from APL", Log.DEBUG); updateWifiConfigWithScanResults(APL.getWifiManager().getScanResults()); App.getTraceUtils().partialTrace(TAG,"updateWifiApConfigs", "Updated wifi network status with ScanResults", Log.DEBUG); App.getTraceUtils().stopTrace(TAG, "updateWifiApConfigs", Log.DEBUG); } } public void updateWifiConfig(WiFiApConfig updatedConfiguration) { synchronized (wifiNetworkStatusLock) { // if (wifiNetworkStatus.getWifiApConfigsByAPLNetId() != null) // { APLNetworkId aplNetworkId = updatedConfiguration.getAPLNetworkId(); if (getWifiNetworkStatus().containsKey(aplNetworkId)) { WiFiApConfig currentConfiguration = getWifiNetworkStatus().get(aplNetworkId); currentConfiguration.updateProxyConfiguration(updatedConfiguration); } else { getWifiNetworkStatus().put(aplNetworkId, updatedConfiguration); } // } } } public void removeWifiConfig(APLNetworkId aplNetworkId) { synchronized (wifiNetworkStatusLock) { if (aplNetworkId != null) { getWifiNetworkStatus().remove(aplNetworkId); } } } public void updateCurrentWifiInfo(WifiInfo currentWifiInfo) { App.getTraceUtils().startTrace(TAG,"updateCurrentWifiInfo", Log.DEBUG); synchronized (wifiNetworkStatusLock) { if (!getWifiNetworkStatus().isEmpty()) { for (WiFiApConfig conf : getWifiNetworkStatus().values()) { conf.updateWifiInfo(currentWifiInfo, null); } } } App.getTraceUtils().stopTrace(TAG,"updateCurrentWifiInfo", Log.DEBUG); } public void updateWifiConfigWithScanResults(List<ScanResult> scanResults) { List<String> scanResultsStrings = new ArrayList<String>(); synchronized (wifiNetworkStatusLock) { // clear all the savedConfigurations AP status if (!getWifiNetworkStatus().isEmpty()) { App.getTraceUtils().startTrace(TAG, "Clear scan status from AP configs", Log.DEBUG); for (WiFiApConfig conf : getWifiNetworkStatus().values()) { conf.clearScanStatus(); } App.getTraceUtils().stopTrace(TAG, "Clear scan status from AP configs", Log.DEBUG); } if (scanResults != null) { for (ScanResult res : scanResults) { scanResultsStrings.add(res.SSID + " level: " + res.level); String currSSID = ProxyUtils.cleanUpSSID(res.SSID); SecurityType security = ProxyUtils.getSecurity(res); APLNetworkId aplNetworkId = new APLNetworkId(currSSID, security); if (getWifiNetworkStatus().containsKey(aplNetworkId)) { WiFiApConfig conf = getWifiNetworkStatus().get(aplNetworkId); if (conf != null) { conf.updateScanResults(res); } } else { if (getWifiNetworkStatus().getNotConfiguredWifi().containsKey(aplNetworkId)) { getWifiNetworkStatus().getNotConfiguredWifi().remove(aplNetworkId); } getWifiNetworkStatus().getNotConfiguredWifi().put(aplNetworkId, res); } } } else { Timber.w("No ScanResults available for updateWifiConfigWithScanResults"); } } Timber.d("Updating from scanresult: " + TextUtils.join(", ", scanResultsStrings.toArray())); } public List<WiFiApConfig> getSortedWifiApConfigsList() { App.getTraceUtils().startTrace(TAG, "getSortedWifiApConfigsList", Log.DEBUG); if (getWifiNetworkStatus().isEmpty()) { updateWifiApConfigs(); App.getTraceUtils().partialTrace(TAG, "getSortedWifiApConfigsList", "updateWifiApConfigs", Log.DEBUG); } List<WiFiApConfig> list = null; synchronized (wifiNetworkStatusLock) { list = new ArrayList<WiFiApConfig>(getWifiNetworkStatus().values()); App.getTraceUtils().partialTrace(TAG, "getSortedWifiApConfigsList", "new ArrayList", Log.DEBUG); try { Collections.sort(list); } catch (IllegalArgumentException e) { Timber.e("config_list", configListToDBG().toString()); Timber.e(e, "Exception during sort of WiFiAPConfigs"); } } App.getTraceUtils().partialTrace(TAG, "getSortedWifiApConfigsList", "Collections.sort", Log.DEBUG); App.getTraceUtils().stopTrace(TAG, "getSortedWifiApConfigsList", Log.DEBUG); return list; } public WiFiApConfig getConfiguration(APLNetworkId aplNetworkId) { WiFiApConfig selected = null; synchronized (wifiNetworkStatusLock) { if (getWifiNetworkStatus().containsKey(aplNetworkId)) { try { selected = (WiFiApConfig) getWifiNetworkStatus().get(aplNetworkId); } catch (Exception e) { Timber.e(e,"Exception retrieving WiFiApConfig from APLNetworkId"); } } } return selected; } public WiFiApConfig updateCurrentConfiguration() { WiFiApConfig updatedConf = null; App.getTraceUtils().startTrace(TAG, "updateCurrentConfiguration", Log.DEBUG); try { if (APL.getWifiManager() != null && APL.getWifiManager().isWifiEnabled()) { WifiInfo info = APL.getWifiManager().getConnectionInfo(); if (info != null) { int networkId = info.getNetworkId(); if (networkId != -1) { WifiConfiguration wifiConfiguration = APL.getConfiguredNetwork(networkId); if (wifiConfiguration != null) { WiFiApConfig networkConfig = APL.getWiFiAPConfiguration(wifiConfiguration); synchronized (wifiNetworkStatusLock) { if (getWifiNetworkStatus().containsKey(networkConfig.getAPLNetworkId())) { updatedConf = getWifiNetworkStatus().get(networkConfig.getAPLNetworkId()); } mergeWithCurrentConfiguration(updatedConf); } } } } } } catch (Exception e) { Timber.e(e,"Exception updating current configuration"); } App.getTraceUtils().stopTrace(TAG, "updateCurrentConfiguration", Log.DEBUG); return updatedConf; } private void mergeWithCurrentConfiguration(WiFiApConfig updated) { if (getWifiNetworkStatus().getCurrentConfiguration() == null) { if (updated != null) { getWifiNetworkStatus().setCurrentConfiguration(updated); Timber.d("updateCurrentConfiguration - Set current configuration (was NULL before)"); } else { Timber.d("updateCurrentConfiguration - Same configuration: no need to update it (both NULL)"); } } else if (updated != null && getWifiNetworkStatus().getCurrentConfiguration().compareTo(updated) != 0) { // Update currentConfiguration only if it's different from the previous getWifiNetworkStatus().setCurrentConfiguration(updated); Timber.d("updateCurrentConfiguration - Updated current configuration"); } else { Timber.d("updateCurrentConfiguration - Same configuration: no need to update it"); } } public WiFiApConfig getCachedConfiguration() { // if (currentConfiguration == null) // { return updateCurrentConfiguration(); // } // // return currentConfiguration; } public JSONObject configListToDBG() { JSONObject dbg = new JSONObject(); try { JSONArray configurations = new JSONArray(); synchronized (wifiNetworkStatusLock) { for (WiFiApConfig conf : getSortedWifiApConfigsList()) { configurations.put(conf.toJSON()); } } dbg.put("configurations", configurations); } catch (JSONException e) { Timber.e(e, "Exception preparing configuration list to JSON"); } return dbg; } }