From 5ea65d609f0c8e1e3a1dcd192c4058aa2ccf3212 Mon Sep 17 00:00:00 2001 From: Irfan Sheriff Date: Sun, 5 Jun 2011 21:29:56 -0700 Subject: [PATCH] Update walled garden detection logic DNS based techniques dont always work. Some hotspots redirect on data fetch on IP. Use a known pattern match on URL to detect a walled garden instead. Also, added gservices capability to turn off the feature or change the URL & the pattern to match Bug: 4378442 Change-Id: I78b4208d3ea3ace20069169e7c01ed769892d94d --- core/java/android/provider/Settings.java | 24 +++++++ .../android/server/WifiWatchdogService.java | 69 ++++++++++++++++--- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 893947d4ad076..2126793ef9f24 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2923,6 +2923,30 @@ public final class Settings { */ public static final String WIFI_WATCHDOG_PING_TIMEOUT_MS = "wifi_watchdog_ping_timeout_ms"; + /** + * Setting to turn off walled garden test on Wi-Fi. Feature is enabled by default and + * the setting needs to be set to 0 to disable it. + * @hide + */ + public static final String WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED = + "wifi_watchdog_walled_garden_test_enabled"; + + /** + * The URL used for walled garden check upon a new conection. WifiWatchdogService + * fetches the URL and checks to see if {@link #WIFI_WATCHDOG_WALLED_GARDEN_PATTERN} + * is not part of the title string to notify the user on the presence of a walled garden. + * @hide + */ + public static final String WIFI_WATCHDOG_WALLED_GARDEN_URL = + "wifi_watchdog_walled_garden_url"; + + /** + * The pattern string in the fetched URL used to detect a walled garden + * @hide + */ + public static final String WIFI_WATCHDOG_WALLED_GARDEN_PATTERN = + "wifi_watchdog_walled_garden_pattern"; + /** * The maximum number of times we will retry a connection to an access * point for which we have failed in acquiring an IP address from DHCP. diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java index 6ef6963c8a691..6c7895e35b142 100644 --- a/services/java/com/android/server/WifiWatchdogService.java +++ b/services/java/com/android/server/WifiWatchdogService.java @@ -36,16 +36,21 @@ import android.provider.Settings; import android.text.TextUtils; import android.util.Slog; +import java.io.BufferedInputStream; +import java.io.InputStream; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; +import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; +import java.net.URL; import java.util.Collection; import java.util.List; import java.util.Random; +import java.util.Scanner; /** * {@link WifiWatchdogService} monitors the initial connection to a Wi-Fi @@ -195,6 +200,34 @@ public class WifiWatchdogService { return Settings.Secure.getInt(mContentResolver, Settings.Secure.WIFI_WATCHDOG_PING_DELAY_MS, 250); } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED + */ + private Boolean isWalledGardenTestEnabled() { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL + */ + private String getWalledGardenUrl() { + String url = Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL); + if (TextUtils.isEmpty(url)) return "http://www.google.com/"; + return url; + } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN + */ + private String getWalledGardenPattern() { + String pattern = Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN); + if (TextUtils.isEmpty(pattern)) return ".*Google.*"; + return pattern; + } /** * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE @@ -509,7 +542,7 @@ public class WifiWatchdogService { // This access point does not require a watchdog, so queue idle on the main thread mHandler.idle(); } - mHandler.checkWalledGarden(ssid); + if (isWalledGardenTestEnabled()) mHandler.checkWalledGarden(ssid); } /** @@ -1118,19 +1151,35 @@ public class WifiWatchdogService { } } + /** + * DNS based detection techniques do not work at all hotspots. The one sure way to check + * a walled garden is to see if a URL fetch on a known address fetches the data we + * expect + */ private boolean isWalledGardenConnection() { - //One way to detect a walled garden is to see if multiple DNS queries - //resolve to the same IP address + InputStream in = null; + HttpURLConnection urlConnection = null; try { - String host1 = "www.google.com"; - String host2 = "www.android.com"; - String address1 = InetAddress.getByName(host1).getHostAddress(); - String address2 = InetAddress.getByName(host2).getHostAddress(); - if (address1.equals(address2)) return true; - } catch (UnknownHostException e) { + URL url = new URL(getWalledGardenUrl()); + urlConnection = (HttpURLConnection) url.openConnection(); + in = new BufferedInputStream(urlConnection.getInputStream()); + Scanner scanner = new Scanner(in); + if (scanner.findInLine(getWalledGardenPattern()) != null) { + return false; + } else { + return true; + } + } catch (IOException e) { return false; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + if (urlConnection != null) urlConnection.disconnect(); } - return false; } private void handleWalledGardenCheck(String ssid) {