am 73550d28: merge from froyo-plus-aosp

Merge commit '73550d28df4b7ee2faa39cc4b1b4cc854343632a'

* commit '73550d28df4b7ee2faa39cc4b1b4cc854343632a':
  Settings: Add a hook for operator or vendor specific settings.
  replaced deprecated getIntent with parseURI
diff --git a/res/layout/locale_picker_in_setupwizard.xml b/res/layout/locale_picker_in_setupwizard.xml
index d816f47..e412b07 100644
--- a/res/layout/locale_picker_in_setupwizard.xml
+++ b/res/layout/locale_picker_in_setupwizard.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,22 +18,6 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
-    
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/select_your_language"
-        android:layout_gravity="center_horizontal"
-        android:paddingBottom="10dip"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-    />
-    
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1dip"
-        android:layout_marginTop="8dip"
-        android:background="@android:drawable/divider_horizontal_dark"
-    />
 
     <ListView android:id="@android:id/list"
         android:layout_width="match_parent"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 03d2136..46467c2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -419,9 +419,7 @@
 
     <!-- LocalePicker -->
     <!-- Title for the locale picker activity -->
-    <string name="language_picker_title">Locale</string>
-    <!-- Locale picker screen. Label for choosing the locale -->
-    <string name="select_your_language">Select your language</string>
+    <string name="language_picker_title">Language</string>
 
     <!-- The title of the dialog to pick an activity.  This is shown when there are multiple activities that can do a particular action.  For example, suppose you click on the "Share" menu item in the Browser.  Since you can share the webpage URL via many communication methods, this dialog would come up with choices like "Email", "IM", etc.  This is a generic message, and the previous example is a single possible scenario (so please don't assume it's for the browser or anything :) ). -->
     <string name="activity_picker_label">Select activity</string>
@@ -592,7 +590,7 @@
     <string name="lockpassword_pin_too_short">PIN must be at least %d characters</string>
 
     <!-- Hint shown after minimum password criteria is met -->
-    <string name="lockpassword_press_continue">Press Continue when done</string>
+    <string name="lockpassword_press_continue">Touch Continue when done</string>
 
     <!-- Hint shown after minimum password criteria is met -->
     <string name="lockpassword_continue_label">Continue</string>
@@ -605,6 +603,9 @@
     <!-- Error shown when in PIN mode and user enters a non-digit -->
     <string name="lockpassword_pin_contains_non_digits">PIN must contain only digits 0-9</string>
 
+    <!-- Error shown when in PIN mode and PIN has been used recently. Please keep this string short! -->
+    <string name="lockpassword_pin_recently_used">Device administrator disallows using a recent PIN</string>
+
     <!-- Error shown when in PASSWORD mode and user enters an invalid character -->
     <string name="lockpassword_illegal_character">Password contains an illegal character</string>
 
@@ -617,6 +618,45 @@
     <!-- Error shown when in PASSWORD mode and password doesn't contain any symbols -->
     <string name="lockpassword_password_requires_symbol">Password must contain at least one symbol</string>
 
+    <!-- Error shown when in PASSWORD mode and password doesn't contain the required number of letters -->
+    <plurals name="lockpassword_password_requires_letters">
+        <item quantity="one">Password must contain at least 1 letter</item>
+        <item quantity="other">Password must contain at least %d letters</item>
+    </plurals>
+
+    <!-- Error shown when in PASSWORD mode and password doesn't contain the required number of lowercase letters -->
+    <plurals name="lockpassword_password_requires_lowercase">
+        <item quantity="one">Password must contain at least 1 lowercase letter</item>
+        <item quantity="other">Password must contain at least %d lowercase letters</item>
+    </plurals>
+
+    <!-- Error shown when in PASSWORD mode and password doesn't contain the required number of uppercase letters -->
+    <plurals name="lockpassword_password_requires_uppercase">
+        <item quantity="one">Password must contain at least 1 uppercase letter</item>
+        <item quantity="other">Password must contain at least %d uppercase letters</item>
+    </plurals>
+
+    <!-- Error shown when in PASSWORD mode and password doesn't contain the required number of numerical digits -->
+    <plurals name="lockpassword_password_requires_numeric">
+        <item quantity="one">Password must contain at least 1 numerical digit</item>
+        <item quantity="other">Password must contain at least %d numerical digits</item>
+    </plurals>
+
+    <!-- Error shown when in PASSWORD mode and password doesn't contain the required number of special symbols -->
+    <plurals name="lockpassword_password_requires_symbols">
+        <item quantity="one">Password must contain at least 1 special symbol</item>
+        <item quantity="other">Password must contain at least %d special symbols</item>
+    </plurals>
+
+    <!-- Error shown when in PASSWORD mode and password doesn't contain the required number of non-letter characters -->
+    <plurals name="lockpassword_password_requires_nonletter">
+        <item quantity="one">Password must contain at least 1 non-letter character</item>
+        <item quantity="other">Password must contain at least %d non-letter characters</item>
+    </plurals>
+
+    <!-- Error shown when in PASSWORD mode and password has been used recently. Please keep this string short! -->
+    <string name="lockpassword_password_recently_used">Device administrator disallows using a recent password</string>
+
     <!-- Label for ChoosePassword/PIN OK button -->
     <string name="lockpassword_ok_label">OK</string>
 
@@ -1897,6 +1937,8 @@
 
     <!-- Input methods Settings -->
     <string name="input_methods_settings_title">Text input</string>
+    <!-- Setting name for Input Method chooser -->
+    <string name="input_method">Input method</string>
     <string name="input_methods_settings_summary">Manage text input options</string>
     <!-- Input Methods Settings localized format string for generating the appropriate "Foo settings" menu label for the Input Method named "Foo" -->
     <string name="input_methods_settings_label_format"><xliff:g id="ime_name">%1$s</xliff:g> settings</string>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index d3c0e02..3b94680 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -26,7 +26,13 @@
     </PreferenceScreen>
 
     <PreferenceCategory android:key="text_category"
-            android:title="@string/text_category" />
+            android:title="@string/text_category">
+
+        <PreferenceScreen android:key="input_method"
+                android:title="@string/input_method"
+                android:widgetLayout="@*android:layout/preference_dialog" />
+
+    </PreferenceCategory>
 
     <PreferenceScreen
             android:key="hardkeyboard_category"
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 0672ad9..5247e79 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -138,7 +138,7 @@
                 } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
                     enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
                 } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
-                    enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
+                    enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
                 }
                 if (!enabled) {
                     pref.setSummary(R.string.unlock_set_unlock_disabled_summary);
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index b5e72d7..4d447f4 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -48,6 +48,12 @@
     private TextView mPasswordEntry;
     private int mPasswordMinLength = 4;
     private int mPasswordMaxLength = 16;
+    private int mPasswordMinLetters = 0;
+    private int mPasswordMinUpperCase = 0;
+    private int mPasswordMinLowerCase = 0;
+    private int mPasswordMinSymbols = 0;
+    private int mPasswordMinNumeric = 0;
+    private int mPasswordMinNonLetter = 0;
     private LockPatternUtils mLockPatternUtils;
     private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
@@ -61,6 +67,12 @@
     private Button mNextButton;
     public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
     public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
+    public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters";
+    public static final String PASSWORD_MIN_LOWERCASE_KEY = "lockscreen.password_min_lowercase";
+    public static final String PASSWORD_MIN_UPPERCASE_KEY = "lockscreen.password_min_uppercase";
+    public static final String PASSWORD_MIN_NUMERIC_KEY = "lockscreen.password_min_numeric";
+    public static final String PASSWORD_MIN_SYMBOLS_KEY = "lockscreen.password_min_symbols";
+    public static final String PASSWORD_MIN_NONLETTER_KEY = "lockscreen.password_min_nonletter";
     private static Handler mHandler = new Handler();
     private static final int CONFIRM_EXISTING_REQUEST = 58;
     static final int RESULT_FINISHED = RESULT_FIRST_USER;
@@ -101,19 +113,27 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mLockPatternUtils = new LockPatternUtils(this);
-        mRequestedQuality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, mRequestedQuality);
-        mPasswordMinLength = getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength);
+        mRequestedQuality = Math.max(getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
+                mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality());
+        mPasswordMinLength = Math.max(
+                getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength), mLockPatternUtils
+                        .getRequestedMinimumPasswordLength());
         mPasswordMaxLength = getIntent().getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
-
+        mPasswordMinLetters = Math.max(getIntent().getIntExtra(PASSWORD_MIN_LETTERS_KEY,
+                mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters());
+        mPasswordMinUpperCase = Math.max(getIntent().getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
+                mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase());
+        mPasswordMinLowerCase = Math.max(getIntent().getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
+                mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase());
+        mPasswordMinNumeric = Math.max(getIntent().getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
+                mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric());
+        mPasswordMinSymbols = Math.max(getIntent().getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
+                mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols());
+        mPasswordMinNonLetter = Math.max(getIntent().getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
+                mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter());
         final boolean confirmCredentials = getIntent().getBooleanExtra("confirm_credentials", true);
-        int minMode = mLockPatternUtils.getRequestedPasswordQuality();
-        if (mRequestedQuality < minMode) {
-            mRequestedQuality = minMode;
-        }
-        int minLength = mLockPatternUtils.getRequestedMinimumPasswordLength();
-        if (mPasswordMinLength < minLength) {
-            mPasswordMinLength = minLength;
-        }
+
+
         initViews();
         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
         if (savedInstanceState == null) {
@@ -142,7 +162,8 @@
         mPasswordEntry.addTextChangedListener(this);
 
         mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
-            || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality;
+                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality
+                || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality;
         mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
         mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
                 PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
@@ -212,9 +233,12 @@
                     R.string.lockpassword_password_too_long
                     : R.string.lockpassword_pin_too_long, mPasswordMaxLength);
         }
-        boolean hasAlpha = false;
-        boolean hasDigit = false;
-        boolean hasSymbol = false;
+        int letters = 0;
+        int numbers = 0;
+        int lowercase = 0;
+        int symbols = 0;
+        int uppercase = 0;
+        int nonletter = 0;
         for (int i = 0; i < password.length(); i++) {
             char c = password.charAt(i);
             // allow non white space Latin-1 characters only
@@ -222,32 +246,65 @@
                 return getString(R.string.lockpassword_illegal_character);
             }
             if (c >= '0' && c <= '9') {
-                hasDigit = true;
-            } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
-                hasAlpha = true;
+                numbers++;
+                nonletter++;
+            } else if (c >= 'A' && c <= 'Z') {
+                letters++;
+                uppercase++;
+            } else if (c >= 'a' && c <= 'z') {
+                letters++;
+                lowercase++;
             } else {
-                hasSymbol = true;
+                symbols++;
+                nonletter++;
             }
         }
         if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
-                && (hasAlpha | hasSymbol)) {
-            // This shouldn't be possible unless user finds some way to bring up soft keyboard
+                && (letters > 0 || symbols > 0)) {
+            // This shouldn't be possible unless user finds some way to bring up
+            // soft keyboard
             return getString(R.string.lockpassword_pin_contains_non_digits);
+        } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
+            if (letters < mPasswordMinLetters) {
+                return String.format(getResources().getQuantityString(
+                        R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters),
+                        mPasswordMinLetters);
+            } else if (numbers < mPasswordMinNumeric) {
+                return String.format(getResources().getQuantityString(
+                        R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric),
+                        mPasswordMinNumeric);
+            } else if (lowercase < mPasswordMinLowerCase) {
+                return String.format(getResources().getQuantityString(
+                        R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase),
+                        mPasswordMinLowerCase);
+            } else if (uppercase < mPasswordMinUpperCase) {
+                return String.format(getResources().getQuantityString(
+                        R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase),
+                        mPasswordMinUpperCase);
+            } else if (symbols < mPasswordMinSymbols) {
+                return String.format(getResources().getQuantityString(
+                        R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols),
+                        mPasswordMinSymbols);
+            } else if (nonletter < mPasswordMinNonLetter) {
+                return String.format(getResources().getQuantityString(
+                        R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter),
+                        mPasswordMinNonLetter);
+            }
         } else {
             final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
                     == mRequestedQuality;
             final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
                     == mRequestedQuality;
-            final boolean symbolic = false; // not yet
-            if ((alphabetic || alphanumeric) && !hasAlpha) {
+            if ((alphabetic || alphanumeric) && letters == 0) {
                 return getString(R.string.lockpassword_password_requires_alpha);
             }
-            if (alphanumeric && !hasDigit) {
+            if (alphanumeric && numbers == 0) {
                 return getString(R.string.lockpassword_password_requires_digit);
             }
-            if (symbolic && !hasSymbol) {
-                return getString(R.string.lockpassword_password_requires_symbol);
-            }
+        }
+        if(mLockPatternUtils.checkPasswordHistory(password)) {
+            return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
+                    : R.string.lockpassword_pin_recently_used);
         }
         return null;
     }
@@ -306,7 +363,7 @@
 
     public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
         // Check if this was the result of hitting the enter key
-        if (actionId == EditorInfo.IME_NULL) {
+        if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_DOWN) {
             handleNext();
             return true;
         }
diff --git a/src/com/android/settings/ChooseLockPatternExample.java b/src/com/android/settings/ChooseLockPatternExample.java
index cba88b0..3c96d53 100644
--- a/src/com/android/settings/ChooseLockPatternExample.java
+++ b/src/com/android/settings/ChooseLockPatternExample.java
@@ -66,6 +66,7 @@
             stopAnimation(mAnimation);
             Intent intent = new Intent(this, ChooseLockPattern.class);
             intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            intent.putExtra("confirm_credentials", false);
             startActivity(intent);
             finish();
         }
diff --git a/src/com/android/settings/ChooseLockPatternTutorial.java b/src/com/android/settings/ChooseLockPatternTutorial.java
index ee0019f..e699abf 100644
--- a/src/com/android/settings/ChooseLockPatternTutorial.java
+++ b/src/com/android/settings/ChooseLockPatternTutorial.java
@@ -35,6 +35,7 @@
         if (savedInstanceState == null && lockPatternUtils.isPatternEverChosen()) {
             Intent intent = new Intent(this, ChooseLockPattern.class);
             intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            intent.putExtra("confirm_credentials", false);
             startActivity(intent);
             finish();
         } else {
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index ba83f8e..abcfc05 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -52,6 +52,7 @@
             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
                 // TODO: update UI layout for ConfirmPassword to show message and details
                 launched = confirmPassword(request);
                 break;
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 6bc135b..0e893fa 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -65,7 +65,8 @@
         mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
         mHeaderText = (TextView) findViewById(R.id.headerText);
         final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
-                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality;
+                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality
+                || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == storedQuality;
         mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
                 : R.string.lockpassword_confirm_your_pin_header);
         mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index eb9a4d8..8d44875 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -144,6 +144,11 @@
         long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
         if (deadline != 0) {
             handleAttemptLockout(deadline);
+        } else if (!mLockPatternView.isEnabled()) {
+            // The deadline has passed, but the timer was cancelled...
+            // Need to clean up.
+            mNumWrongConfirmAttempts = 0;
+            updateStage(Stage.NeedToUnlock);
         }
     }
 
diff --git a/src/com/android/settings/LanguageSettings.java b/src/com/android/settings/LanguageSettings.java
index 91d260c..179ac53 100644
--- a/src/com/android/settings/LanguageSettings.java
+++ b/src/com/android/settings/LanguageSettings.java
@@ -44,6 +44,8 @@
 public class LanguageSettings extends PreferenceActivity {
     
     private static final String KEY_PHONE_LANGUAGE = "phone_language";
+    private static final String KEY_INPUT_METHOD = "input_method";
+
     private boolean mHaveHardKeyboard;
 
     private List<InputMethodInfo> mInputMethodProperties;
@@ -282,7 +284,10 @@
                 mLastTickedInputMethodId = null;
             }
         } else if (preference instanceof PreferenceScreen) {
-            if (preference.getIntent() == null) {
+            if (KEY_INPUT_METHOD.equals(preference.getKey())) {
+                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+                imm.showInputMethodPicker();
+            } else if (preference.getIntent() == null) {
                 PreferenceScreen pref = (PreferenceScreen) preference;
                 String activityName = pref.getKey();
                 String packageName = activityName.substring(0, activityName
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 05a655a..312c84a 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -155,6 +155,7 @@
                     break;
                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
                     addPreferencesFromResource(R.xml.security_settings_password);
                     break;
             }
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index d389cae..45bc9da 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -24,6 +24,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.wifi.ScanResult;
@@ -62,6 +63,9 @@
     private static final int MENU_ID_FORGET = Menu.FIRST + 3;
     private static final int MENU_ID_MODIFY = Menu.FIRST + 4;
 
+    // this boolean extra specifies whether to disable the Next button when not connected
+    private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect";
+
     private final IntentFilter mFilter;
     private final BroadcastReceiver mReceiver;
     private final Scanner mScanner;
@@ -82,6 +86,9 @@
     private AccessPoint mSelected;
     private WifiDialog mDialog;
 
+    // should Next button only be enabled when we have a connection?
+    private boolean mEnableNextOnConnection;
+
     public WifiSettings() {
         mFilter = new IntentFilter();
         mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -107,6 +114,18 @@
 
         mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
 
+        // if we're supposed to enable/disable the Next button based on our current connection
+        // state, start it off in the right state
+        mEnableNextOnConnection = getIntent().getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false);
+        if (mEnableNextOnConnection && hasNextButton()) {
+            ConnectivityManager connectivity = (ConnectivityManager)
+                getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+            if (connectivity != null) {
+                NetworkInfo info = connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+                getNextButton().setEnabled(info.isConnected());
+            }
+        }
+
         if (getIntent().getBooleanExtra("only_access_points", false)) {
             addPreferencesFromResource(R.xml.wifi_access_points);
         } else {
@@ -422,8 +441,12 @@
             updateConnectionState(WifiInfo.getDetailedStateOf((SupplicantState)
                     intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));
         } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
-            updateConnectionState(((NetworkInfo) intent.getParcelableExtra(
-                    WifiManager.EXTRA_NETWORK_INFO)).getDetailedState());
+            NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(
+                    WifiManager.EXTRA_NETWORK_INFO);
+            if (mEnableNextOnConnection && hasNextButton()) {
+                getNextButton().setEnabled(info.isConnected());
+            }
+            updateConnectionState(info.getDetailedState());
         } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
             updateConnectionState(null);
         }