summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings')
-rw-r--r--src/com/android/settings/AccessibilitySettings.java104
-rw-r--r--src/com/android/settings/AccountPreference.java142
-rw-r--r--src/com/android/settings/AirplaneModeEnabler.java14
-rw-r--r--src/com/android/settings/ApplicationSettings.java12
-rw-r--r--src/com/android/settings/ChooseLockGeneric.java2
-rw-r--r--src/com/android/settings/ChooseLockPassword.java113
-rw-r--r--src/com/android/settings/ChooseLockPatternExample.java1
-rw-r--r--src/com/android/settings/ChooseLockPatternTutorial.java1
-rw-r--r--src/com/android/settings/ChooseLockSettingsHelper.java1
-rw-r--r--src/com/android/settings/ConfirmLockPassword.java3
-rw-r--r--src/com/android/settings/ConfirmLockPattern.java5
-rw-r--r--src/com/android/settings/DateTimeSettings.java235
-rw-r--r--src/com/android/settings/DateTimeSettingsSetupWizard.java202
-rw-r--r--src/com/android/settings/DeviceInfoSettings.java21
-rw-r--r--src/com/android/settings/DisplaySettings.java16
-rw-r--r--src/com/android/settings/DockSettings.java25
-rw-r--r--src/com/android/settings/IconPreferenceScreen.java11
-rw-r--r--src/com/android/settings/LanguageSettings.java50
-rw-r--r--src/com/android/settings/LocalePicker.java176
-rw-r--r--src/com/android/settings/LocalePickerInSetupWizard.java43
-rw-r--r--src/com/android/settings/ManageAccountsSettings.java373
-rw-r--r--src/com/android/settings/PhysicalKeyboardSettings.java12
-rw-r--r--src/com/android/settings/PrivacySettings.java15
-rw-r--r--src/com/android/settings/ProgressCategory.java18
-rw-r--r--src/com/android/settings/ProgressCategoryBase.java33
-rw-r--r--src/com/android/settings/ProxySelector.java154
-rw-r--r--src/com/android/settings/RadioInfo.java23
-rw-r--r--src/com/android/settings/RingerVolumePreference.java27
-rw-r--r--src/com/android/settings/SecuritySettings.java194
-rw-r--r--src/com/android/settings/Settings.java77
-rw-r--r--src/com/android/settings/SettingsPreferenceFragment.java348
-rw-r--r--src/com/android/settings/SoundSettings.java38
-rw-r--r--src/com/android/settings/TetherSettings.java236
-rw-r--r--src/com/android/settings/TextToSpeechSettings.java65
-rw-r--r--src/com/android/settings/UserDictionarySettings.java171
-rw-r--r--src/com/android/settings/UserLeaveHintListener.java24
-rw-r--r--src/com/android/settings/Utils.java73
-rw-r--r--src/com/android/settings/VoiceInputOutputSettings.java5
-rw-r--r--src/com/android/settings/WirelessSettings.java85
-rw-r--r--src/com/android/settings/ZoneList.java273
-rw-r--r--src/com/android/settings/ZonePicker.java276
-rw-r--r--src/com/android/settings/bluetooth/BluetoothDevicePreference.java7
-rw-r--r--src/com/android/settings/bluetooth/BluetoothEventRedirector.java28
-rw-r--r--src/com/android/settings/bluetooth/BluetoothSettings.java183
-rw-r--r--src/com/android/settings/bluetooth/CachedBluetoothDevice.java64
-rw-r--r--src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java5
-rw-r--r--src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java190
-rw-r--r--src/com/android/settings/deviceinfo/Memory.java71
-rw-r--r--src/com/android/settings/vpn/VpnEditor.java76
-rw-r--r--src/com/android/settings/vpn/VpnSettings.java124
-rw-r--r--src/com/android/settings/vpn/VpnTypeSelection.java16
-rw-r--r--src/com/android/settings/wifi/AccessPoint.java74
-rw-r--r--src/com/android/settings/wifi/AccessPointCategoryForSetupWizardXL.java35
-rw-r--r--src/com/android/settings/wifi/AdvancedSettings.java193
-rw-r--r--src/com/android/settings/wifi/Summary.java1
-rw-r--r--src/com/android/settings/wifi/WifiApDialog.java14
-rw-r--r--src/com/android/settings/wifi/WifiApSettings.java51
-rw-r--r--src/com/android/settings/wifi/WifiConfigController.java544
-rw-r--r--src/com/android/settings/wifi/WifiConfigPreference.java129
-rw-r--r--src/com/android/settings/wifi/WifiConfigUiBase.java42
-rw-r--r--src/com/android/settings/wifi/WifiDialog.java337
-rw-r--r--src/com/android/settings/wifi/WifiSettings.java570
-rw-r--r--src/com/android/settings/wifi/WifiSettingsForSetupWizardXL.java209
63 files changed, 4646 insertions, 2014 deletions
diff --git a/src/com/android/settings/AccessibilitySettings.java b/src/com/android/settings/AccessibilitySettings.java
index d78d2d8ef..104ee9e6b 100644
--- a/src/com/android/settings/AccessibilitySettings.java
+++ b/src/com/android/settings/AccessibilitySettings.java
@@ -22,14 +22,13 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
@@ -47,7 +46,7 @@ import java.util.Map;
/**
* Activity with the accessibility settings.
*/
-public class AccessibilitySettings extends PreferenceActivity {
+public class AccessibilitySettings extends SettingsPreferenceFragment {
private static final String DEFAULT_SCREENREADER_MARKET_LINK =
"market://search?q=pname:com.google.android.marvin.talkback";
@@ -57,6 +56,9 @@ public class AccessibilitySettings extends PreferenceActivity {
private static final String ACCESSIBILITY_SERVICES_CATEGORY =
"accessibility_services_category";
+ private static final String TOGGLE_ACCESSIBILITY_SCRIPT_INJECTION_CHECKBOX =
+ "toggle_accessibility_script_injection_checkbox";
+
private static final String POWER_BUTTON_CATEGORY =
"power_button_category";
@@ -65,6 +67,8 @@ public class AccessibilitySettings extends PreferenceActivity {
private CheckBoxPreference mToggleCheckBox;
+ private CheckBoxPreference mToggleScriptInjectionCheckBox;
+
private PreferenceCategory mPowerButtonCategory;
private CheckBoxPreference mPowerButtonEndsCallCheckBox;
@@ -77,23 +81,21 @@ public class AccessibilitySettings extends PreferenceActivity {
private PreferenceGroup mAccessibilityServicesCategory;
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.accessibility_settings);
mToggleCheckBox = (CheckBoxPreference) findPreference(
- TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX);
+ TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX);
+
+ mToggleScriptInjectionCheckBox = (CheckBoxPreference) findPreference(
+ TOGGLE_ACCESSIBILITY_SCRIPT_INJECTION_CHECKBOX);
mPowerButtonCategory = (PreferenceCategory) findPreference(POWER_BUTTON_CATEGORY);
mPowerButtonEndsCallCheckBox = (CheckBoxPreference) findPreference(
- POWER_BUTTON_ENDS_CALL_CHECKBOX);
+ POWER_BUTTON_ENDS_CALL_CHECKBOX);
addAccessibilitServicePreferences();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
final HashSet<String> enabled = new HashSet<String>();
String settingValue = Settings.Secure.getString(getContentResolver(),
@@ -137,7 +139,14 @@ public class AccessibilitySettings extends PreferenceActivity {
displayNoAppsAlert();
}
- if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)) {
+ // set the accessibility script injection category
+ boolean scriptInjectionEnabled = (Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1);
+ mToggleScriptInjectionCheckBox.setChecked(scriptInjectionEnabled);
+ mToggleScriptInjectionCheckBox.setEnabled(true);
+
+ if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
+ && Utils.isVoiceCapable(getActivity())) {
int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
@@ -149,13 +158,14 @@ public class AccessibilitySettings extends PreferenceActivity {
mPowerButtonEndsCallCheckBox.setChecked(powerButtonCheckboxEnabled);
mPowerButtonEndsCallCheckBox.setEnabled(true);
} else {
- // No POWER key on the current device; this entire category is irrelevant.
+ // No POWER key on the current device or no voice capability;
+ // this entire category is irrelevant.
getPreferenceScreen().removePreference(mPowerButtonCategory);
}
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
persistEnabledAccessibilityServices();
@@ -184,7 +194,6 @@ public class AccessibilitySettings extends PreferenceActivity {
final String key = preference.getKey();
if (TOGGLE_ACCESSIBILITY_SERVICE_CHECKBOX.equals(key)) {
- boolean isChecked = ((CheckBoxPreference) preference).isChecked();
handleEnableAccessibilityStateChange((CheckBoxPreference) preference);
} else if (POWER_BUTTON_ENDS_CALL_CHECKBOX.equals(key)) {
boolean isChecked = ((CheckBoxPreference) preference).isChecked();
@@ -195,6 +204,8 @@ public class AccessibilitySettings extends PreferenceActivity {
Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
(isChecked ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP
: Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF));
+ } else if (TOGGLE_ACCESSIBILITY_SCRIPT_INJECTION_CHECKBOX.equals(key)) {
+ handleToggleAccessibilityScriptInjection((CheckBoxPreference) preference);
} else if (preference instanceof CheckBoxPreference) {
handleEnableAccessibilityServiceStateChange((CheckBoxPreference) preference);
}
@@ -214,10 +225,12 @@ public class AccessibilitySettings extends PreferenceActivity {
setAccessibilityServicePreferencesState(true);
} else {
final CheckBoxPreference checkBoxPreference = preference;
- AlertDialog dialog = (new AlertDialog.Builder(this))
+ // TODO: DialogFragment?
+ AlertDialog dialog = (new AlertDialog.Builder(getActivity()))
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(R.string.accessibility_service_disable_warning))
+ .setMessage(getResources().
+ getString(R.string.accessibility_service_disable_warning))
.setCancelable(true)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@@ -239,6 +252,42 @@ public class AccessibilitySettings extends PreferenceActivity {
}
/**
+ * Handles the change of the accessibility script injection setting state.
+ *
+ * @param preference The preference for enabling/disabling accessibility script injection.
+ */
+ private void handleToggleAccessibilityScriptInjection(CheckBoxPreference preference) {
+ if (preference.isChecked()) {
+ final CheckBoxPreference checkBoxPreference = preference;
+ // TODO: DialogFragment?
+ AlertDialog dialog = (new AlertDialog.Builder(getActivity()))
+ .setTitle(android.R.string.dialog_alert_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(getActivity().getString(
+ R.string.accessibility_script_injection_security_warning))
+ .setCancelable(true)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 1);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ checkBoxPreference.setChecked(false);
+ }
+ })
+ .create();
+ dialog.show();
+ } else {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0);
+ }
+ }
+
+ /**
* Handles the change of the preference for enabling/disabling an AccessibilityService.
*
* @param preference The preference.
@@ -246,12 +295,14 @@ public class AccessibilitySettings extends PreferenceActivity {
private void handleEnableAccessibilityServiceStateChange(CheckBoxPreference preference) {
if (preference.isChecked()) {
final CheckBoxPreference checkBoxPreference = preference;
- AlertDialog dialog = (new AlertDialog.Builder(this))
+ // TODO: DialogFragment?
+ AlertDialog dialog = (new AlertDialog.Builder(getActivity()))
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(R.string.accessibility_service_security_warning,
- mAccessibilityServices.get(preference.getKey())
- .applicationInfo.loadLabel(getPackageManager())))
+ .setMessage(getResources().
+ getString(R.string.accessibility_service_security_warning,
+ mAccessibilityServices.get(preference.getKey())
+ .applicationInfo.loadLabel(getActivity().getPackageManager())))
.setCancelable(true)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
@@ -318,9 +369,9 @@ public class AccessibilitySettings extends PreferenceActivity {
mAccessibilityServices.put(key, serviceInfo);
- CheckBoxPreference preference = new CheckBoxPreference(this);
+ CheckBoxPreference preference = new CheckBoxPreference(getActivity());
preference.setKey(key);
- preference.setTitle(serviceInfo.loadLabel(getPackageManager()));
+ preference.setTitle(serviceInfo.loadLabel(getActivity().getPackageManager()));
mAccessibilityServicesCategory.addPreference(preference);
}
}
@@ -332,13 +383,14 @@ public class AccessibilitySettings extends PreferenceActivity {
*/
private void displayNoAppsAlert() {
try {
- PackageManager pm = getPackageManager();
+ PackageManager pm = getActivity().getPackageManager();
ApplicationInfo info = pm.getApplicationInfo("com.android.vending", 0);
} catch (NameNotFoundException e) {
// This is a no-op if the user does not have Android Market
return;
}
- AlertDialog.Builder noAppsAlert = new AlertDialog.Builder(this);
+ // TODO: DialogFragment?
+ AlertDialog.Builder noAppsAlert = new AlertDialog.Builder(getActivity());
noAppsAlert.setTitle(R.string.accessibility_service_no_apps_title);
noAppsAlert.setMessage(R.string.accessibility_service_no_apps_message);
@@ -351,7 +403,7 @@ public class AccessibilitySettings extends PreferenceActivity {
Uri marketUri = Uri.parse(screenreaderMarketLink);
Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
startActivity(marketIntent);
- finish();
+ getFragmentManager().popBackStack();
}
});
diff --git a/src/com/android/settings/AccountPreference.java b/src/com/android/settings/AccountPreference.java
new file mode 100644
index 000000000..a860d1a5d
--- /dev/null
+++ b/src/com/android/settings/AccountPreference.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import java.util.ArrayList;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.preference.Preference;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+
+/**
+ * AccountPreference is used to display a username, status and provider icon for an account on
+ * the device.
+ */
+public class AccountPreference extends Preference {
+ private static final String TAG = "AccountPreference";
+ public static final int SYNC_ENABLED = 0; // all know sync adapters are enabled and OK
+ public static final int SYNC_DISABLED = 1; // no sync adapters are enabled
+ public static final int SYNC_ERROR = 2; // one or more sync adapters have a problem
+ private int mStatus;
+ private Account mAccount;
+ private ArrayList<String> mAuthorities;
+ private Drawable mProviderIcon;
+ private ImageView mSyncStatusIcon;
+ private ImageView mProviderIconView;
+
+ public AccountPreference(Context context, Account account, Drawable icon,
+ ArrayList<String> authorities) {
+ super(context);
+ mAccount = account;
+ mAuthorities = authorities;
+ mProviderIcon = icon;
+ setLayoutResource(R.layout.account_preference);
+ setTitle(mAccount.name);
+ setSummary("");
+ // Add account info to the intent for AccountSyncSettings
+ Intent intent = new Intent("android.settings.ACCOUNT_SYNC_SETTINGS");
+ intent.putExtra("account", mAccount);
+ setIntent(intent);
+ setPersistent(false);
+ setSyncStatus(SYNC_DISABLED);
+ }
+
+ public Account getAccount() {
+ return mAccount;
+ }
+
+ public ArrayList<String> getAuthorities() {
+ return mAuthorities;
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ setSummary(getSyncStatusMessage(mStatus));
+ mProviderIconView = (ImageView) view.findViewById(R.id.providerIcon);
+ mProviderIconView.setImageDrawable(mProviderIcon);
+ mSyncStatusIcon = (ImageView) view.findViewById(R.id.syncStatusIcon);
+ mSyncStatusIcon.setImageResource(getSyncStatusIcon(mStatus));
+ }
+
+ public void setProviderIcon(Drawable icon) {
+ mProviderIcon = icon;
+ if (mProviderIconView != null) {
+ mProviderIconView.setImageDrawable(icon);
+ }
+ }
+
+ public void setSyncStatus(int status) {
+ mStatus = status;
+ if (mSyncStatusIcon != null) {
+ mSyncStatusIcon.setImageResource(getSyncStatusIcon(status));
+ }
+ setSummary(getSyncStatusMessage(status));
+ }
+
+ private int getSyncStatusMessage(int status) {
+ int res;
+ switch (status) {
+ case SYNC_ENABLED:
+ res = R.string.sync_enabled;
+ break;
+ case SYNC_DISABLED:
+ res = R.string.sync_disabled;
+ break;
+ case SYNC_ERROR:
+ res = R.string.sync_error;
+ break;
+ default:
+ res = R.string.sync_error;
+ Log.e(TAG, "Unknown sync status: " + status);
+ }
+ return res;
+ }
+
+ private int getSyncStatusIcon(int status) {
+ int res;
+ switch (status) {
+ case SYNC_ENABLED:
+ res = R.drawable.ic_sync_green;
+ break;
+ case SYNC_DISABLED:
+ res = R.drawable.ic_sync_grey;
+ break;
+ case SYNC_ERROR:
+ res = R.drawable.ic_sync_red;
+ break;
+ default:
+ res = R.drawable.ic_sync_red;
+ Log.e(TAG, "Unknown sync status: " + status);
+ }
+ return res;
+ }
+
+ @Override
+ public int compareTo(Preference other) {
+ if (!(other instanceof AccountPreference)) {
+ // Put other preference types above us
+ return 1;
+ }
+ return mAccount.name.compareTo(((AccountPreference) other).mAccount.name);
+ }
+}
diff --git a/src/com/android/settings/AirplaneModeEnabler.java b/src/com/android/settings/AirplaneModeEnabler.java
index ff4b27dcc..ccfe541c5 100644
--- a/src/com/android/settings/AirplaneModeEnabler.java
+++ b/src/com/android/settings/AirplaneModeEnabler.java
@@ -64,8 +64,6 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
public void resume() {
- // This is the widget enabled state, not the preference toggled state
- mCheckBoxPref.setEnabled(true);
mCheckBoxPref.setChecked(isAirplaneModeOn(mContext));
mPhoneStateReceiver.registerIntent();
@@ -84,13 +82,14 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
private void setAirplaneModeOn(boolean enabling) {
- mCheckBoxPref.setEnabled(false);
mCheckBoxPref.setSummary(enabling ? R.string.airplane_mode_turning_on
: R.string.airplane_mode_turning_off);
// Change the system setting
Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
enabling ? 1 : 0);
+ // Update the UI to reflect system setting
+ mCheckBoxPref.setChecked(enabling);
// Post the intent
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
@@ -100,14 +99,17 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
/**
* Called when we've received confirmation that the airplane mode was set.
+ * TODO: We update the checkbox summary when we get notified
+ * that mobile radio is powered up/down. We should not have dependency
+ * on one radio alone. We need to do the following:
+ * - handle the case of wifi/bluetooth failures
+ * - mobile does not send failure notification, fail on timeout.
*/
private void onAirplaneModeChanged() {
ServiceState serviceState = mPhoneStateReceiver.getServiceState();
boolean airplaneModeEnabled = serviceState.getState() == ServiceState.STATE_POWER_OFF;
- mCheckBoxPref.setChecked(airplaneModeEnabled);
mCheckBoxPref.setSummary(airplaneModeEnabled ? null :
mContext.getString(R.string.airplane_mode_summary));
- mCheckBoxPref.setEnabled(true);
}
/**
@@ -128,7 +130,7 @@ public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListene
// update database based on the current checkbox state
setAirplaneModeOn(isAirplaneModeOn);
} else {
- // update checkbox state based on database value
+ // update summary
onAirplaneModeChanged();
}
}
diff --git a/src/com/android/settings/ApplicationSettings.java b/src/com/android/settings/ApplicationSettings.java
index a919ae849..ed7c7a085 100644
--- a/src/com/android/settings/ApplicationSettings.java
+++ b/src/com/android/settings/ApplicationSettings.java
@@ -23,12 +23,11 @@ import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.preference.Preference.OnPreferenceChangeListener;
import android.provider.Settings;
-public class ApplicationSettings extends PreferenceActivity implements
+public class ApplicationSettings extends SettingsPreferenceFragment implements
DialogInterface.OnClickListener {
private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
@@ -51,7 +50,7 @@ public class ApplicationSettings extends PreferenceActivity implements
private DialogInterface mWarnInstallApps;
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.application_settings);
@@ -102,7 +101,7 @@ public class ApplicationSettings extends PreferenceActivity implements
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
super.onDestroy();
if (mWarnInstallApps != null) {
mWarnInstallApps.dismiss();
@@ -157,8 +156,9 @@ public class ApplicationSettings extends PreferenceActivity implements
}
private void warnAppInstallation() {
- mWarnInstallApps = new AlertDialog.Builder(this)
- .setTitle(getString(R.string.error_title))
+ // TODO: DialogFragment?
+ mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle(
+ getResources().getString(R.string.error_title))
.setIcon(com.android.internal.R.drawable.ic_dialog_alert)
.setMessage(getResources().getString(R.string.install_all_warning))
.setPositiveButton(android.R.string.yes, this)
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 0672ad922..5247e791e 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -138,7 +138,7 @@ public class ChooseLockGeneric extends PreferenceActivity {
} 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 b5e72d7f7..4d447f433 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -48,6 +48,12 @@ public class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 @@ public class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 @@ public class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 @@ public class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 @@ public class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 @@ public class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 class ChooseLockPassword extends Activity implements OnClickListener, OnE
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 cba88b01c..3c96d534f 100644
--- a/src/com/android/settings/ChooseLockPatternExample.java
+++ b/src/com/android/settings/ChooseLockPatternExample.java
@@ -66,6 +66,7 @@ public class ChooseLockPatternExample extends Activity implements View.OnClickLi
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 ee0019f70..e699abff8 100644
--- a/src/com/android/settings/ChooseLockPatternTutorial.java
+++ b/src/com/android/settings/ChooseLockPatternTutorial.java
@@ -35,6 +35,7 @@ public class ChooseLockPatternTutorial extends Activity implements View.OnClickL
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 ba83f8e58..abcfc050f 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -52,6 +52,7 @@ public class ChooseLockSettingsHelper {
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 6bc135b01..0e893faa0 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -65,7 +65,8 @@ public class ConfirmLockPassword extends Activity implements OnClickListener,
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 eb9a4d8e5..8d44875b4 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -144,6 +144,11 @@ public class ConfirmLockPattern extends Activity {
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/DateTimeSettings.java b/src/com/android/settings/DateTimeSettings.java
index 5b38651ce..4d199b8d4 100644
--- a/src/com/android/settings/DateTimeSettings.java
+++ b/src/com/android/settings/DateTimeSettings.java
@@ -16,8 +16,9 @@
package com.android.settings;
-import android.app.Dialog;
+import android.app.Activity;
import android.app.DatePickerDialog;
+import android.app.Dialog;
import android.app.TimePickerDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -30,7 +31,6 @@ import android.os.SystemClock;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -42,51 +42,56 @@ import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
-public class DateTimeSettings
- extends PreferenceActivity
+public class DateTimeSettings extends SettingsPreferenceFragment
implements OnSharedPreferenceChangeListener,
- TimePickerDialog.OnTimeSetListener , DatePickerDialog.OnDateSetListener {
+ TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
private static final String HOURS_12 = "12";
private static final String HOURS_24 = "24";
-
+
+ // Used for showing the current date format, which looks like "12/31/2010", "2010/12/13", etc.
+ // The date value is dummy (independent of actual date).
private Calendar mDummyDate;
+
private static final String KEY_DATE_FORMAT = "date_format";
private static final String KEY_AUTO_TIME = "auto_time";
+ private static final String KEY_AUTO_TIME_ZONE = "auto_zone";
private static final int DIALOG_DATEPICKER = 0;
private static final int DIALOG_TIMEPICKER = 1;
-
- private CheckBoxPreference mAutoPref;
+
+ private CheckBoxPreference mAutoTimePref;
private Preference mTimePref;
private Preference mTime24Pref;
+ private CheckBoxPreference mAutoTimeZonePref;
private Preference mTimeZone;
private Preference mDatePref;
private ListPreference mDateFormat;
-
+
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
+
addPreferencesFromResource(R.xml.date_time_prefs);
-
- initUI();
+
+ initUI();
}
-
+
private void initUI() {
- boolean autoEnabled = getAutoState();
+ boolean autoTimeEnabled = getAutoState(Settings.System.AUTO_TIME);
+ boolean autoTimeZoneEnabled = getAutoState(Settings.System.AUTO_TIME_ZONE);
mDummyDate = Calendar.getInstance();
mDummyDate.set(mDummyDate.get(Calendar.YEAR), 11, 31, 13, 0, 0);
-
- mAutoPref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
- mAutoPref.setChecked(autoEnabled);
+
+ mAutoTimePref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
+ mAutoTimePref.setChecked(autoTimeEnabled);
mTimePref = findPreference("time");
mTime24Pref = findPreference("24 hour");
mTimeZone = findPreference("timezone");
mDatePref = findPreference("date");
mDateFormat = (ListPreference) findPreference(KEY_DATE_FORMAT);
-
+
String [] dateFormats = getResources().getStringArray(R.array.date_format_values);
String [] formattedDates = new String[dateFormats.length];
String currentFormat = getDateFormat();
@@ -97,8 +102,8 @@ public class DateTimeSettings
}
for (int i = 0; i < formattedDates.length; i++) {
String formatted =
- DateFormat.getDateFormatForSetting(this, dateFormats[i]).
- format(mDummyDate.getTime());
+ DateFormat.getDateFormatForSetting(getActivity(), dateFormats[i])
+ .format(mDummyDate.getTime());
if (dateFormats[i].length() == 0) {
formattedDates[i] = getResources().
@@ -107,22 +112,23 @@ public class DateTimeSettings
formattedDates[i] = formatted;
}
}
-
+
mDateFormat.setEntries(formattedDates);
mDateFormat.setEntryValues(R.array.date_format_values);
mDateFormat.setValue(currentFormat);
-
- mTimePref.setEnabled(!autoEnabled);
- mDatePref.setEnabled(!autoEnabled);
- mTimeZone.setEnabled(!autoEnabled);
+
+ mTimePref.setEnabled(!autoTimeEnabled);
+ mDatePref.setEnabled(!autoTimeEnabled);
+ mTimeZone.setEnabled(!autoTimeZoneEnabled);
}
-
+
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
-
- getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+
+ getPreferenceScreen().getSharedPreferences()
+ .registerOnSharedPreferenceChangeListener(this);
((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());
@@ -131,74 +137,70 @@ public class DateTimeSettings
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- registerReceiver(mIntentReceiver, filter, null, null);
-
- updateTimeAndDateDisplay();
+ getActivity().registerReceiver(mIntentReceiver, filter, null, null);
+
+ updateTimeAndDateDisplay(getActivity());
}
- @Override
- protected void onPause() {
+ @Override
+ public void onPause() {
super.onPause();
- unregisterReceiver(mIntentReceiver);
- getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
+ getActivity().unregisterReceiver(mIntentReceiver);
+ getPreferenceScreen().getSharedPreferences()
+ .unregisterOnSharedPreferenceChangeListener(this);
}
-
- private void updateTimeAndDateDisplay() {
- java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(this);
- Date now = Calendar.getInstance().getTime();
+
+ private void updateTimeAndDateDisplay(Context context) {
+ java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
+ final Calendar now = Calendar.getInstance();
Date dummyDate = mDummyDate.getTime();
- mTimePref.setSummary(DateFormat.getTimeFormat(this).format(now));
- mTimeZone.setSummary(getTimeZoneText());
- mDatePref.setSummary(shortDateFormat.format(now));
+ mTimePref.setSummary(DateFormat.getTimeFormat(getActivity()).format(now.getTime()));
+ mTimeZone.setSummary(getTimeZoneText(now.getTimeZone()));
+ mDatePref.setSummary(shortDateFormat.format(now.getTime()));
mDateFormat.setSummary(shortDateFormat.format(dummyDate));
}
+ @Override
public void onDateSet(DatePicker view, int year, int month, int day) {
- Calendar c = Calendar.getInstance();
-
- c.set(Calendar.YEAR, year);
- c.set(Calendar.MONTH, month);
- c.set(Calendar.DAY_OF_MONTH, day);
- long when = c.getTimeInMillis();
-
- if (when / 1000 < Integer.MAX_VALUE) {
- SystemClock.setCurrentTimeMillis(when);
+ setDate(year, month, day);
+ final Activity activity = getActivity();
+ if (activity != null) {
+ updateTimeAndDateDisplay(activity);
}
- updateTimeAndDateDisplay();
}
+ @Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
- Calendar c = Calendar.getInstance();
-
- c.set(Calendar.HOUR_OF_DAY, hourOfDay);
- c.set(Calendar.MINUTE, minute);
- long when = c.getTimeInMillis();
-
- if (when / 1000 < Integer.MAX_VALUE) {
- SystemClock.setCurrentTimeMillis(when);
+ setTime(hourOfDay, minute);
+ final Activity activity = getActivity();
+ if (activity != null) {
+ updateTimeAndDateDisplay(activity);
}
- updateTimeAndDateDisplay();
-
+
// We don't need to call timeUpdated() here because the TIME_CHANGED
// broadcast is sent by the AlarmManager as a side effect of setting the
// SystemClock time.
}
+ @Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (key.equals(KEY_DATE_FORMAT)) {
- String format = preferences.getString(key,
+ String format = preferences.getString(key,
getResources().getString(R.string.default_date_format));
- Settings.System.putString(getContentResolver(),
+ Settings.System.putString(getContentResolver(),
Settings.System.DATE_FORMAT, format);
- updateTimeAndDateDisplay();
+ updateTimeAndDateDisplay(getActivity());
} else if (key.equals(KEY_AUTO_TIME)) {
boolean autoEnabled = preferences.getBoolean(key, true);
- Settings.System.putInt(getContentResolver(),
- Settings.System.AUTO_TIME,
+ Settings.System.putInt(getContentResolver(), Settings.System.AUTO_TIME,
autoEnabled ? 1 : 0);
mTimePref.setEnabled(!autoEnabled);
mDatePref.setEnabled(!autoEnabled);
- mTimeZone.setEnabled(!autoEnabled);
+ } else if (key.equals(KEY_AUTO_TIME_ZONE)) {
+ boolean autoZoneEnabled = preferences.getBoolean(key, true);
+ Settings.System.putInt(
+ getContentResolver(), Settings.System.AUTO_TIME_ZONE, autoZoneEnabled ? 1 : 0);
+ mTimeZone.setEnabled(!autoZoneEnabled);
}
}
@@ -210,7 +212,7 @@ public class DateTimeSettings
case DIALOG_DATEPICKER: {
final Calendar calendar = Calendar.getInstance();
d = new DatePickerDialog(
- this,
+ getActivity(),
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
@@ -221,11 +223,11 @@ public class DateTimeSettings
case DIALOG_TIMEPICKER: {
final Calendar calendar = Calendar.getInstance();
d = new TimePickerDialog(
- this,
+ getActivity(),
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
- DateFormat.is24HourFormat(this));
+ DateFormat.is24HourFormat(getActivity()));
d.setTitle(getResources().getString(R.string.date_time_changeTime_text));
break;
}
@@ -237,6 +239,7 @@ public class DateTimeSettings
return d;
}
+ /*
@Override
public void onPrepareDialog(int id, Dialog d) {
switch (id) {
@@ -261,7 +264,7 @@ public class DateTimeSettings
break;
}
}
-
+ */
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference == mDatePref) {
@@ -272,65 +275,76 @@ public class DateTimeSettings
showDialog(DIALOG_TIMEPICKER);
} else if (preference == mTime24Pref) {
set24Hour(((CheckBoxPreference)mTime24Pref).isChecked());
- updateTimeAndDateDisplay();
+ updateTimeAndDateDisplay(getActivity());
timeUpdated();
- } else if (preference == mTimeZone) {
- Intent intent = new Intent();
- intent.setClass(this, ZoneList.class);
- startActivityForResult(intent, 0);
}
- return false;
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
}
-
+
@Override
- protected void onActivityResult(int requestCode, int resultCode,
+ public void onActivityResult(int requestCode, int resultCode,
Intent data) {
- updateTimeAndDateDisplay();
+ updateTimeAndDateDisplay(getActivity());
}
-
+
private void timeUpdated() {
Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
- sendBroadcast(timeChanged);
+ getActivity().sendBroadcast(timeChanged);
}
-
+
/* Get & Set values from the system settings */
-
+
private boolean is24Hour() {
- return DateFormat.is24HourFormat(this);
+ return DateFormat.is24HourFormat(getActivity());
}
-
+
private void set24Hour(boolean is24Hour) {
Settings.System.putString(getContentResolver(),
Settings.System.TIME_12_24,
is24Hour? HOURS_24 : HOURS_12);
}
-
+
private String getDateFormat() {
- return Settings.System.getString(getContentResolver(),
+ return Settings.System.getString(getContentResolver(),
Settings.System.DATE_FORMAT);
}
-
- private boolean getAutoState() {
+
+ private boolean getAutoState(String name) {
try {
- return Settings.System.getInt(getContentResolver(),
- Settings.System.AUTO_TIME) > 0;
+ return Settings.System.getInt(getContentResolver(), name) > 0;
} catch (SettingNotFoundException snfe) {
return true;
}
}
- private void setDateFormat(String format) {
- if (format.length() == 0) {
- format = null;
+ /* Helper routines to format timezone */
+
+ /* package */ static void setDate(int year, int month, int day) {
+ Calendar c = Calendar.getInstance();
+
+ c.set(Calendar.YEAR, year);
+ c.set(Calendar.MONTH, month);
+ c.set(Calendar.DAY_OF_MONTH, day);
+ long when = c.getTimeInMillis();
+
+ if (when / 1000 < Integer.MAX_VALUE) {
+ SystemClock.setCurrentTimeMillis(when);
}
+ }
+
+ /* package */ static void setTime(int hourOfDay, int minute) {
+ Calendar c = Calendar.getInstance();
+
+ c.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ c.set(Calendar.MINUTE, minute);
+ long when = c.getTimeInMillis();
- Settings.System.putString(getContentResolver(), Settings.System.DATE_FORMAT, format);
+ if (when / 1000 < Integer.MAX_VALUE) {
+ SystemClock.setCurrentTimeMillis(when);
+ }
}
-
- /* Helper routines to format timezone */
-
- private String getTimeZoneText() {
- TimeZone tz = java.util.Calendar.getInstance().getTimeZone();
+
+ /* package */ static String getTimeZoneText(TimeZone tz) {
boolean daylight = tz.inDaylightTime(new Date());
StringBuilder sb = new StringBuilder();
@@ -339,10 +353,10 @@ public class DateTimeSettings
append(", ").
append(tz.getDisplayName(daylight, TimeZone.LONG));
- return sb.toString();
+ return sb.toString();
}
- private char[] formatOffset(int off) {
+ private static char[] formatOffset(int off) {
off = off / 1000 / 60;
char[] buf = new char[9];
@@ -357,7 +371,7 @@ public class DateTimeSettings
buf[3] = '+';
}
- int hours = off / 60;
+ int hours = off / 60;
int minutes = off % 60;
buf[4] = (char) ('0' + hours / 10);
@@ -370,11 +384,14 @@ public class DateTimeSettings
return buf;
}
-
+
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- updateTimeAndDateDisplay();
+ final Activity activity = getActivity();
+ if (activity != null) {
+ updateTimeAndDateDisplay(activity);
+ }
}
};
}
diff --git a/src/com/android/settings/DateTimeSettingsSetupWizard.java b/src/com/android/settings/DateTimeSettingsSetupWizard.java
index a6a60c1b2..61e5255a7 100644
--- a/src/com/android/settings/DateTimeSettingsSetupWizard.java
+++ b/src/com/android/settings/DateTimeSettingsSetupWizard.java
@@ -16,25 +16,205 @@
package com.android.settings;
+import com.android.settings.ZonePicker.ZoneSelectionListener;
+
+import android.app.Activity;
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.content.res.Configuration;
import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
import android.view.View;
-import android.view.Window;
import android.view.View.OnClickListener;
+import android.view.Window;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.DatePicker;
+import android.widget.TimePicker;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+
+public class DateTimeSettingsSetupWizard extends Activity
+ implements OnClickListener, ZoneSelectionListener, OnCheckedChangeListener{
+ private static final String TAG = DateTimeSettingsSetupWizard.class.getSimpleName();
+
+ private boolean mXLargeScreenSize;
+
+ /* Available only in XL */
+ private CompoundButton mAutoDateTimeButton;
+ private CompoundButton mAutoTimeZoneButton;
+ private Button mTimeZone;
+ private TimePicker mTimePicker;
+ private DatePicker mDatePicker;
+ private InputMethodManager mInputMethodManager;
+
+ private StatusBarManager mStatusBarManager;
-public class DateTimeSettingsSetupWizard extends DateTimeSettings implements OnClickListener {
- private View mNextButton;
-
@Override
- protected void onCreate(Bundle icicle) {
+ protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
- super.onCreate(icicle);
+ super.onCreate(savedInstanceState);
setContentView(R.layout.date_time_settings_setupwizard);
- mNextButton = findViewById(R.id.next_button);
- mNextButton.setOnClickListener(this);
+ mStatusBarManager = (StatusBarManager)getSystemService(Context.STATUS_BAR_SERVICE);
+
+ mXLargeScreenSize = (getResources().getConfiguration().screenLayout
+ & Configuration.SCREENLAYOUT_SIZE_MASK)
+ == Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ if (mXLargeScreenSize) {
+ initUiForXl();
+ } else {
+ findViewById(R.id.next_button).setOnClickListener(this);
+ }
+ }
+
+ public void initUiForXl() {
+ final boolean autoTimeZoneEnabled = isAutoTimeZoneEnabled();
+ mAutoTimeZoneButton = (CompoundButton)findViewById(R.id.time_zone_auto);
+ mAutoTimeZoneButton.setChecked(autoTimeZoneEnabled);
+ mAutoTimeZoneButton.setOnCheckedChangeListener(this);
+ mAutoTimeZoneButton.setText(autoTimeZoneEnabled ? R.string.zone_auto_summaryOn :
+ R.string.zone_auto_summaryOff);
+
+ final TimeZone tz = TimeZone.getDefault();
+ mTimeZone = (Button)findViewById(R.id.current_time_zone);
+ mTimeZone.setText(DateTimeSettings.getTimeZoneText(tz));
+ mTimeZone.setOnClickListener(this);
+ mTimeZone.setEnabled(!autoTimeZoneEnabled);
+
+ final boolean autoDateTimeEnabled = isAutoDateTimeEnabled();
+ mAutoDateTimeButton = (CompoundButton)findViewById(R.id.date_time_auto);
+ mAutoDateTimeButton.setChecked(autoDateTimeEnabled);
+ mAutoDateTimeButton.setText(autoDateTimeEnabled ? R.string.date_time_auto_summaryOn :
+ R.string.date_time_auto_summaryOff);
+ mAutoDateTimeButton.setOnCheckedChangeListener(this);
+
+ mTimePicker = (TimePicker)findViewById(R.id.time_picker);
+ mTimePicker.setEnabled(!autoDateTimeEnabled);
+ mDatePicker = (DatePicker)findViewById(R.id.date_picker);
+ mDatePicker.setEnabled(!autoDateTimeEnabled);
+
+ mInputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ ((ZonePicker)getFragmentManager().findFragmentById(R.id.zone_picker_fragment))
+ .setZoneSelectionListener(this);
+
+ ((Button)findViewById(R.id.next_button)).setOnClickListener(this);
+ ((Button)findViewById(R.id.skip_button)).setOnClickListener(this);
+
+ if (mStatusBarManager != null) {
+ mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND
+ | StatusBarManager.DISABLE_NOTIFICATION_ICONS
+ | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
+ | StatusBarManager.DISABLE_SYSTEM_INFO
+ | StatusBarManager.DISABLE_NAVIGATION);
+ } else {
+ Log.e(TAG, "StatusBarManager isn't available.");
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mStatusBarManager != null) {
+ mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.current_time_zone: {
+ findViewById(R.id.current_time_zone).setVisibility(View.GONE);
+ findViewById(R.id.zone_picker).setVisibility(View.VISIBLE);
+ break;
+ }
+ case R.id.next_button: {
+ if (mXLargeScreenSize) {
+ Settings.System.putInt(getContentResolver(), Settings.System.AUTO_TIME_ZONE,
+ mAutoTimeZoneButton.isChecked() ? 1 : 0);
+ Settings.System.putInt(getContentResolver(), Settings.System.AUTO_TIME,
+ mAutoDateTimeButton.isChecked() ? 1 : 0);
+ // Note: in non-XL, Date & Time is stored by DatePickerDialog/TimePickerDialog,
+ // so we don't need to save those values there, while in XL, we need to as
+ // we don't use those Dialogs.
+ DateTimeSettings.setDate(mDatePicker.getYear(), mDatePicker.getMonth(),
+ mDatePicker.getDayOfMonth());
+ DateTimeSettings.setTime(
+ mTimePicker.getCurrentHour(), mTimePicker.getCurrentMinute());
+ }
+ } // $FALL-THROUGH$
+ case R.id.skip_button: {
+ setResult(RESULT_OK);
+ finish();
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ final boolean autoEnabled = isChecked; // just for readibility.
+ if (buttonView == mAutoTimeZoneButton) {
+ // In XL screen, we save all the state only when the next button is pressed.
+ if (!mXLargeScreenSize) {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.AUTO_TIME_ZONE,
+ isChecked ? 1 : 0);
+ }
+ mTimeZone.setEnabled(!autoEnabled);
+ if (isChecked) {
+ findViewById(R.id.current_time_zone).setVisibility(View.VISIBLE);
+ findViewById(R.id.zone_picker).setVisibility(View.GONE);
+ }
+ } else if (buttonView == mAutoDateTimeButton) {
+ if (!mXLargeScreenSize) {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.AUTO_TIME,
+ isChecked ? 1 : 0);
+ }
+ mTimePicker.setEnabled(!autoEnabled);
+ mDatePicker.setEnabled(!autoEnabled);
+ }
+ if (autoEnabled) {
+ final View focusedView = getCurrentFocus();
+ if (focusedView != null) {
+ mInputMethodManager.hideSoftInputFromWindow(focusedView.getWindowToken(), 0);
+ focusedView.clearFocus();
+ }
+ }
+ }
+
+ @Override
+ public void onZoneSelected(TimeZone tz) {
+ findViewById(R.id.current_time_zone).setVisibility(View.VISIBLE);
+ findViewById(R.id.zone_picker).setVisibility(View.GONE);
+ final Calendar now = Calendar.getInstance(tz);
+ mTimeZone.setText(DateTimeSettings.getTimeZoneText(tz));
+ mDatePicker.updateDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH),
+ now.get(Calendar.DAY_OF_MONTH));
+ mTimePicker.setCurrentHour(now.get(Calendar.HOUR));
+ mTimePicker.setCurrentMinute(now.get(Calendar.MINUTE));
+ }
+
+ private boolean isAutoDateTimeEnabled() {
+ try {
+ return Settings.System.getInt(getContentResolver(), Settings.System.AUTO_TIME) > 0;
+ } catch (SettingNotFoundException e) {
+ return true;
+ }
}
- public void onClick(View v) {
- setResult(RESULT_OK);
- finish();
+ private boolean isAutoTimeZoneEnabled() {
+ try {
+ return Settings.System.getInt(getContentResolver(),
+ Settings.System.AUTO_TIME_ZONE) > 0;
+ } catch (SettingNotFoundException e) {
+ return true;
+ }
}
}
diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java
index 048d10aa6..0d6549aa0 100644
--- a/src/com/android/settings/DeviceInfoSettings.java
+++ b/src/com/android/settings/DeviceInfoSettings.java
@@ -16,17 +16,16 @@
package com.android.settings;
+import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.Log;
-import android.view.MotionEvent;
import java.io.BufferedReader;
import java.io.FileReader;
@@ -34,7 +33,7 @@ import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-public class DeviceInfoSettings extends PreferenceActivity {
+public class DeviceInfoSettings extends SettingsPreferenceFragment {
private static final String TAG = "DeviceInfoSettings";
private static final String KEY_CONTAINER = "container";
@@ -49,7 +48,7 @@ public class DeviceInfoSettings extends PreferenceActivity {
long[] mHits = new long[3];
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.device_info_settings);
@@ -69,24 +68,24 @@ public class DeviceInfoSettings extends PreferenceActivity {
* Settings is a generic app and should not contain any device-specific
* info.
*/
-
+ final Activity act = getActivity();
// These are contained in the "container" preference group
PreferenceGroup parentPreference = (PreferenceGroup) findPreference(KEY_CONTAINER);
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_TERMS,
+ Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_TERMS,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_LICENSE,
+ Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_LICENSE,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_COPYRIGHT,
+ Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_COPYRIGHT,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_TEAM,
+ Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_TEAM,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
// These are contained by the root preference screen
parentPreference = getPreferenceScreen();
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference,
+ Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference,
KEY_SYSTEM_UPDATE_SETTINGS,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_CONTRIBUTORS,
+ Utils.updatePreferenceToSpecificActivityOrRemove(act, parentPreference, KEY_CONTRIBUTORS,
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
}
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index fbb07c13c..5945884af 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -18,8 +18,6 @@ package com.android.settings;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import java.util.ArrayList;
-
import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -29,13 +27,14 @@ import android.os.ServiceManager;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.util.Log;
import android.view.IWindowManager;
-public class DisplaySettings extends PreferenceActivity implements
+import java.util.ArrayList;
+
+public class DisplaySettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener {
private static final String TAG = "DisplaySettings";
@@ -53,9 +52,9 @@ public class DisplaySettings extends PreferenceActivity implements
private IWindowManager mWindowManager;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ContentResolver resolver = getContentResolver();
+ ContentResolver resolver = getActivity().getContentResolver();
mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
addPreferencesFromResource(R.xml.display_settings);
@@ -75,7 +74,8 @@ public class DisplaySettings extends PreferenceActivity implements
private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) {
final DevicePolicyManager dpm =
- (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+ (DevicePolicyManager) getActivity().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0;
if (maxTimeout == 0) {
return; // policy not enforced
@@ -109,7 +109,7 @@ public class DisplaySettings extends PreferenceActivity implements
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
updateState(true);
diff --git a/src/com/android/settings/DockSettings.java b/src/com/android/settings/DockSettings.java
index 0d46ce9a9..b36864021 100644
--- a/src/com/android/settings/DockSettings.java
+++ b/src/com/android/settings/DockSettings.java
@@ -16,6 +16,8 @@
package com.android.settings;
+import com.android.settings.bluetooth.DockEventReceiver;
+
import android.app.AlertDialog;
import android.app.Dialog;
import android.bluetooth.BluetoothDevice;
@@ -27,13 +29,10 @@ import android.content.IntentFilter;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
-import com.android.settings.bluetooth.DockEventReceiver;
-
-public class DockSettings extends PreferenceActivity {
+public class DockSettings extends SettingsPreferenceFragment {
private static final int DIALOG_NOT_DOCKED = 1;
private static final String KEY_AUDIO_SETTINGS = "dock_audio";
@@ -52,7 +51,7 @@ public class DockSettings extends PreferenceActivity {
};
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ContentResolver resolver = getContentResolver();
addPreferencesFromResource(R.xml.dock_settings);
@@ -61,18 +60,18 @@ public class DockSettings extends PreferenceActivity {
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
- registerReceiver(mReceiver, filter);
+ getActivity().registerReceiver(mReceiver, filter);
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
- unregisterReceiver(mReceiver);
+ getActivity().unregisterReceiver(mReceiver);
}
private void initDockSettings() {
@@ -120,7 +119,7 @@ public class DockSettings extends PreferenceActivity {
if (dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
// remove undocked dialog if currently showing.
try {
- dismissDialog(DIALOG_NOT_DOCKED);
+ removeDialog(DIALOG_NOT_DOCKED);
} catch (IllegalArgumentException iae) {
// Maybe it was already dismissed
}
@@ -139,8 +138,8 @@ public class DockSettings extends PreferenceActivity {
} else {
Intent i = new Intent(mDockIntent);
i.setAction(DockEventReceiver.ACTION_DOCK_SHOW_UI);
- i.setClass(this, DockEventReceiver.class);
- sendBroadcast(i);
+ i.setClass(getActivity(), DockEventReceiver.class);
+ getActivity().sendBroadcast(i);
}
} else if (preference == mDockSounds) {
Settings.System.putInt(getContentResolver(), Settings.System.DOCK_SOUNDS_ENABLED,
@@ -159,7 +158,7 @@ public class DockSettings extends PreferenceActivity {
}
private Dialog createUndockedMessage() {
- final AlertDialog.Builder ab = new AlertDialog.Builder(this);
+ final AlertDialog.Builder ab = new AlertDialog.Builder(getActivity());
ab.setTitle(R.string.dock_not_found_title);
ab.setMessage(R.string.dock_not_found_text);
ab.setPositiveButton(android.R.string.ok, null);
diff --git a/src/com/android/settings/IconPreferenceScreen.java b/src/com/android/settings/IconPreferenceScreen.java
index 31abf0a86..64fce29de 100644
--- a/src/com/android/settings/IconPreferenceScreen.java
+++ b/src/com/android/settings/IconPreferenceScreen.java
@@ -22,13 +22,16 @@ import android.graphics.drawable.Drawable;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.ImageView;
+import android.widget.TextView;
public class IconPreferenceScreen extends Preference {
private Drawable mIcon;
+ // Whether or not the text and icon should be highlighted (as selected)
+ private boolean mHighlight;
+
public IconPreferenceScreen(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -48,6 +51,7 @@ public class IconPreferenceScreen extends Preference {
if (imageView != null && mIcon != null) {
imageView.setImageDrawable(mIcon);
}
+ TextView textView = (TextView) view.findViewById(android.R.id.title);
}
/**
@@ -71,4 +75,9 @@ public class IconPreferenceScreen extends Preference {
public Drawable getIcon() {
return mIcon;
}
+
+ public void setHighlighted(boolean highlight) {
+ mHighlight = highlight;
+ notifyChanged();
+ }
}
diff --git a/src/com/android/settings/LanguageSettings.java b/src/com/android/settings/LanguageSettings.java
index 1252eec26..2dab6d9f6 100644
--- a/src/com/android/settings/LanguageSettings.java
+++ b/src/com/android/settings/LanguageSettings.java
@@ -16,24 +16,21 @@
package com.android.settings;
+import android.app.Activity;
import android.app.AlertDialog;
-import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.os.Bundle;
-import android.os.Environment;
-import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.text.TextUtils;
-import android.view.View.OnClickListener;
+import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -41,9 +38,12 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
-public class LanguageSettings extends PreferenceActivity {
-
+public class LanguageSettings extends SettingsPreferenceFragment {
+ private static final String TAG = LanguageSettings.class.getSimpleName();
+
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;
@@ -63,12 +63,12 @@ public class LanguageSettings extends PreferenceActivity {
}
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.language_settings);
- if (getAssets().getLocales().length == 1) {
+ if (getActivity().getAssets().getLocales().length == 1) {
getPreferenceScreen().
removePreference(findPreference("language_category"));
} else {
@@ -107,12 +107,12 @@ public class LanguageSettings extends PreferenceActivity {
InputMethodInfo property = mInputMethodProperties.get(i);
String prefKey = property.getId();
- CharSequence label = property.loadLabel(getPackageManager());
+ CharSequence label = property.loadLabel(getActivity().getPackageManager());
boolean systemIME = isSystemIme(property);
// Add a check box.
// Don't show the toggle if it's the only keyboard in the system, or it's a system IME.
if (mHaveHardKeyboard || (N > 1 && !systemIME)) {
- CheckBoxPreference chkbxPref = new CheckBoxPreference(this);
+ CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity());
chkbxPref.setKey(prefKey);
chkbxPref.setTitle(label);
textCategory.addPreference(chkbxPref);
@@ -121,7 +121,7 @@ public class LanguageSettings extends PreferenceActivity {
// If setting activity is available, add a setting screen entry.
if (null != property.getSettingsActivity()) {
- PreferenceScreen prefScreen = new PreferenceScreen(this, null);
+ PreferenceScreen prefScreen = new PreferenceScreen(getActivity(), null);
String settingsActivity = property.getSettingsActivity();
if (settingsActivity.lastIndexOf("/") < 0) {
settingsActivity = property.getPackageName() + "/" + settingsActivity;
@@ -129,7 +129,8 @@ public class LanguageSettings extends PreferenceActivity {
prefScreen.setKey(settingsActivity);
prefScreen.setTitle(label);
if (N == 1) {
- prefScreen.setSummary(getString(R.string.onscreen_keyboard_settings_summary));
+ prefScreen.setSummary(getResources().getString(
+ R.string.onscreen_keyboard_settings_summary));
} else {
CharSequence settingsLabel = getResources().getString(
R.string.input_methods_settings_label_format, label);
@@ -141,7 +142,7 @@ public class LanguageSettings extends PreferenceActivity {
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
final HashSet<String> enabled = new HashSet<String>();
@@ -178,7 +179,7 @@ public class LanguageSettings extends PreferenceActivity {
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
StringBuilder builder = new StringBuilder(256);
@@ -258,7 +259,8 @@ public class LanguageSettings extends PreferenceActivity {
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
if (mDialog == null) {
- mDialog = (new AlertDialog.Builder(this))
+ // TODO: DialogFragment?
+ mDialog = (new AlertDialog.Builder(getActivity()))
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setCancelable(true)
@@ -282,15 +284,21 @@ public class LanguageSettings extends PreferenceActivity {
mDialog.dismiss();
}
}
- mDialog.setMessage(getString(R.string.ime_security_warning,
- selImi.getServiceInfo().applicationInfo.loadLabel(
- getPackageManager())));
+ mDialog.setMessage(getResources().getString(
+ R.string.ime_security_warning,
+ selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager())));
mDialog.show();
} else if (id.equals(mLastTickedInputMethodId)) {
mLastTickedInputMethodId = null;
}
} else if (preference instanceof PreferenceScreen) {
- if (preference.getIntent() == null) {
+ if (preference.getFragment() != null) {
+ // Fragment will be handled correctly by the super class.
+ } else if (KEY_INPUT_METHOD.equals(preference.getKey())) {
+ final 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
@@ -311,7 +319,7 @@ public class LanguageSettings extends PreferenceActivity {
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
super.onDestroy();
if (mDialog != null) {
mDialog.dismiss();
diff --git a/src/com/android/settings/LocalePicker.java b/src/com/android/settings/LocalePicker.java
index dcd61414b..8b94ccb00 100644
--- a/src/com/android/settings/LocalePicker.java
+++ b/src/com/android/settings/LocalePicker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,176 +16,18 @@
package com.android.settings;
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.app.ListActivity;
-import android.app.backup.BackupManager;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
-import java.text.Collator;
-import java.util.Arrays;
import java.util.Locale;
-public class LocalePicker extends ListActivity {
- private static final String TAG = "LocalePicker";
- private static final boolean DEBUG = false;
-
- Loc[] mLocales;
- String[] mSpecialLocaleCodes;
- String[] mSpecialLocaleNames;
-
- private static class Loc implements Comparable {
- static Collator sCollator = Collator.getInstance();
-
- String label;
- Locale locale;
-
- public Loc(String label, Locale locale) {
- this.label = label;
- this.locale = locale;
- }
-
- @Override
- public String toString() {
- return this.label;
- }
-
- public int compareTo(Object o) {
- return sCollator.compare(this.label, ((Loc) o).label);
- }
- }
-
- int getContentView() {
- return R.layout.locale_picker;
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setContentView(getContentView());
-
- mSpecialLocaleCodes = getResources().getStringArray(R.array.special_locale_codes);
- mSpecialLocaleNames = getResources().getStringArray(R.array.special_locale_names);
-
- String[] locales = getAssets().getLocales();
- Arrays.sort(locales);
-
- final int origSize = locales.length;
- Loc[] preprocess = new Loc[origSize];
- int finalSize = 0;
- for (int i = 0 ; i < origSize; i++ ) {
- String s = locales[i];
- int len = s.length();
- if (len == 5) {
- String language = s.substring(0, 2);
- String country = s.substring(3, 5);
- Locale l = new Locale(language, country);
-
- if (finalSize == 0) {
- if (DEBUG) {
- Log.v(TAG, "adding initial "+ toTitleCase(l.getDisplayLanguage(l)));
- }
- preprocess[finalSize++] =
- new Loc(toTitleCase(l.getDisplayLanguage(l)), l);
- } else {
- // check previous entry:
- // same lang and a country -> upgrade to full name and
- // insert ours with full name
- // diff lang -> insert ours with lang-only name
- if (preprocess[finalSize-1].locale.getLanguage().equals(
- language)) {
- if (DEBUG) {
- Log.v(TAG, "backing up and fixing "+
- preprocess[finalSize-1].label+" to "+
- getDisplayName(preprocess[finalSize-1].locale));
- }
- preprocess[finalSize-1].label = toTitleCase(
- getDisplayName(preprocess[finalSize-1].locale));
- if (DEBUG) {
- Log.v(TAG, " and adding "+ toTitleCase(getDisplayName(l)));
- }
- preprocess[finalSize++] =
- new Loc(toTitleCase(getDisplayName(l)), l);
- } else {
- String displayName;
- if (s.equals("zz_ZZ")) {
- displayName = "Pseudo...";
- } else {
- displayName = toTitleCase(l.getDisplayLanguage(l));
- }
- if (DEBUG) {
- Log.v(TAG, "adding "+displayName);
- }
- preprocess[finalSize++] = new Loc(displayName, l);
- }
- }
- }
- }
- mLocales = new Loc[finalSize];
- for (int i = 0; i < finalSize ; i++) {
- mLocales[i] = preprocess[i];
- }
- Arrays.sort(mLocales);
- int layoutId = R.layout.locale_picker_item;
- int fieldId = R.id.locale;
- ArrayAdapter<Loc> adapter =
- new ArrayAdapter<Loc>(this, layoutId, fieldId, mLocales);
- getListView().setAdapter(adapter);
- }
-
- private static String toTitleCase(String s) {
- if (s.length() == 0) {
- return s;
- }
-
- return Character.toUpperCase(s.charAt(0)) + s.substring(1);
- }
-
- private String getDisplayName(Locale l) {
- String code = l.toString();
-
- for (int i = 0; i < mSpecialLocaleCodes.length; i++) {
- if (mSpecialLocaleCodes[i].equals(code)) {
- return mSpecialLocaleNames[i];
- }
- }
-
- return l.getDisplayName(l);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- getListView().requestFocus();
+public class LocalePicker extends com.android.internal.app.LocalePicker
+ implements com.android.internal.app.LocalePicker.LocaleSelectionListener {
+ public LocalePicker() {
+ super();
+ setLocaleSelectionListener(this);
}
@Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- try {
- IActivityManager am = ActivityManagerNative.getDefault();
- Configuration config = am.getConfiguration();
-
- Loc loc = mLocales[position];
- config.locale = loc.locale;
-
- // indicate this isn't some passing default - the user wants this remembered
- config.userSetLocale = true;
-
- am.updateConfiguration(config);
- // Trigger the dirty bit for the Settings Provider.
- BackupManager.dataChanged("com.android.providers.settings");
- } catch (RemoteException e) {
- // Intentionally left blank
- }
- finish();
+ public void onLocaleSelected(Locale locale) {
+ getActivity().onBackPressed();
+ LocalePicker.updateLocale(locale);
}
}
diff --git a/src/com/android/settings/LocalePickerInSetupWizard.java b/src/com/android/settings/LocalePickerInSetupWizard.java
deleted file mode 100644
index b160e899b..000000000
--- a/src/com/android/settings/LocalePickerInSetupWizard.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.app.ListActivity;
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.util.Log;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
-import java.util.Arrays;
-import java.util.Locale;
-
-public class LocalePickerInSetupWizard extends LocalePicker {
-
- @Override
- int getContentView() {
- return R.layout.locale_picker_in_setupwizard;
- }
-
-}
diff --git a/src/com/android/settings/ManageAccountsSettings.java b/src/com/android/settings/ManageAccountsSettings.java
new file mode 100644
index 000000000..f138674bf
--- /dev/null
+++ b/src/com/android/settings/ManageAccountsSettings.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import com.google.android.collect.Maps;
+
+import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
+import android.accounts.OnAccountsUpdateListener;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SyncAdapterType;
+import android.content.SyncInfo;
+import android.content.SyncStatusInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+public class ManageAccountsSettings extends PreferenceFragment
+ implements View.OnClickListener, OnAccountsUpdateListener, DialogCreatable {
+ private static final String TAG = ManageAccountsSettings.class.getSimpleName();
+
+ private static final String AUTHORITIES_FILTER_KEY = "authorities";
+ private static final boolean LDEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final String AUTO_SYNC_CHECKBOX_KEY = "syncAutomaticallyCheckBox";
+ private static final String MANAGE_ACCOUNTS_CATEGORY_KEY = "manageAccountsCategory";
+ private static final String BACKGROUND_DATA_CHECKBOX_KEY = "backgroundDataCheckBox";
+ private static final int DIALOG_DISABLE_BACKGROUND_DATA = 1;
+
+ private CheckBoxPreference mBackgroundDataCheckBox;
+ private PreferenceCategory mManageAccountsCategory;
+ private String[] mAuthorities;
+ private TextView mErrorInfoView;
+ private Button mAddAccountButton;
+ private CheckBoxPreference mAutoSyncCheckbox;
+
+ private SettingsDialogFragment mDialogFragment;
+
+ private AuthenticatorDescription[] mAuthDescs;
+ private Map<String, AuthenticatorDescription> mTypeToAuthDescription
+ = new HashMap<String, AuthenticatorDescription>();
+ private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.manage_accounts_screen, container, false);
+ return view;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ final Activity activity = getActivity();
+ addPreferencesFromResource(R.xml.manage_accounts_settings);
+ final View view = getView();
+
+ mErrorInfoView = (TextView)view.findViewById(R.id.sync_settings_error_info);
+ mErrorInfoView.setVisibility(View.GONE);
+ mErrorInfoView.setCompoundDrawablesWithIntrinsicBounds(
+ activity.getResources().getDrawable(R.drawable.ic_list_syncerror),
+ null, null, null);
+
+ mBackgroundDataCheckBox = (CheckBoxPreference) findPreference(BACKGROUND_DATA_CHECKBOX_KEY);
+ mAutoSyncCheckbox = (CheckBoxPreference) findPreference(AUTO_SYNC_CHECKBOX_KEY);
+
+ mManageAccountsCategory = (PreferenceCategory)findPreference(MANAGE_ACCOUNTS_CATEGORY_KEY);
+ mAuthorities = activity.getIntent().getStringArrayExtra(AUTHORITIES_FILTER_KEY);
+ mAddAccountButton = (Button)view.findViewById(R.id.add_account_button);
+ mAddAccountButton.setOnClickListener(this);
+
+ AccountManager.get(activity).addOnAccountsUpdatedListener(this, null, true);
+ updateAuthDescriptions(activity);
+ }
+
+ @Override
+ public void onDestroy() {
+ AccountManager.get(getActivity()).removeOnAccountsUpdatedListener(this);
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) {
+ if (preference == mBackgroundDataCheckBox) {
+ final ConnectivityManager connManager = (ConnectivityManager)
+ getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ final boolean oldBackgroundDataSetting = connManager.getBackgroundDataSetting();
+ final boolean backgroundDataSetting = mBackgroundDataCheckBox.isChecked();
+ if (oldBackgroundDataSetting != backgroundDataSetting) {
+ if (backgroundDataSetting) {
+ setBackgroundDataInt(true);
+ onSyncStateUpdated();
+ } else {
+ // This will get unchecked only if the user hits "Ok"
+ mBackgroundDataCheckBox.setChecked(true);
+ showDialog(DIALOG_DISABLE_BACKGROUND_DATA);
+ }
+ }
+ } else if (preference == mAutoSyncCheckbox) {
+ ContentResolver.setMasterSyncAutomatically(mAutoSyncCheckbox.isChecked());
+ onSyncStateUpdated();
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public Dialog onCreateDialog(int id) {
+ switch (id) {
+ case DIALOG_DISABLE_BACKGROUND_DATA:
+ final CheckBoxPreference pref =
+ (CheckBoxPreference) findPreference(BACKGROUND_DATA_CHECKBOX_KEY);
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.background_data_dialog_title)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setMessage(R.string.background_data_dialog_message)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ setBackgroundDataInt(false);
+ pref.setChecked(false);
+ onSyncStateUpdated();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .create();
+ }
+
+ return null;
+ }
+
+ void showDialog(int dialogId) {
+ if (mDialogFragment != null) {
+ Log.e(TAG, "Old dialog fragment not null!");
+ }
+ mDialogFragment = new SettingsDialogFragment(this, dialogId);
+ mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
+ }
+
+ private void setBackgroundDataInt(boolean enabled) {
+ final ConnectivityManager connManager = (ConnectivityManager)
+ getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ connManager.setBackgroundDataSetting(enabled);
+ }
+
+ private void onSyncStateUpdated() {
+ // Set background connection state
+ final ConnectivityManager connManager = (ConnectivityManager)
+ getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ final boolean backgroundDataSetting = connManager.getBackgroundDataSetting();
+ mBackgroundDataCheckBox.setChecked(backgroundDataSetting);
+ boolean masterSyncAutomatically = ContentResolver.getMasterSyncAutomatically();
+ mAutoSyncCheckbox.setChecked(masterSyncAutomatically);
+
+ // iterate over all the preferences, setting the state properly for each
+ SyncInfo currentSync = ContentResolver.getCurrentSync();
+
+ boolean anySyncFailed = false; // true if sync on any account failed
+
+ // only track userfacing sync adapters when deciding if account is synced or not
+ final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+ HashSet<String> userFacing = new HashSet<String>();
+ for (int k = 0, n = syncAdapters.length; k < n; k++) {
+ final SyncAdapterType sa = syncAdapters[k];
+ if (sa.isUserVisible()) {
+ userFacing.add(sa.authority);
+ }
+ }
+ for (int i = 0, count = mManageAccountsCategory.getPreferenceCount(); i < count; i++) {
+ Preference pref = mManageAccountsCategory.getPreference(i);
+ if (! (pref instanceof AccountPreference)) {
+ continue;
+ }
+
+ AccountPreference accountPref = (AccountPreference) pref;
+ Account account = accountPref.getAccount();
+ int syncCount = 0;
+ boolean syncIsFailing = false;
+ final ArrayList<String> authorities = accountPref.getAuthorities();
+ if (authorities != null) {
+ for (String authority : authorities) {
+ SyncStatusInfo status = ContentResolver.getSyncStatus(account, authority);
+ boolean syncEnabled = ContentResolver.getSyncAutomatically(account, authority)
+ && masterSyncAutomatically
+ && backgroundDataSetting
+ && (ContentResolver.getIsSyncable(account, authority) > 0);
+ boolean authorityIsPending = ContentResolver.isSyncPending(account, authority);
+ boolean activelySyncing = currentSync != null
+ && currentSync.authority.equals(authority)
+ && new Account(currentSync.account.name, currentSync.account.type)
+ .equals(account);
+ boolean lastSyncFailed = status != null
+ && syncEnabled
+ && status.lastFailureTime != 0
+ && status.getLastFailureMesgAsInt(0)
+ != ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
+ if (lastSyncFailed && !activelySyncing && !authorityIsPending) {
+ syncIsFailing = true;
+ anySyncFailed = true;
+ }
+ syncCount += syncEnabled && userFacing.contains(authority) ? 1 : 0;
+ }
+ } else {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "no syncadapters found for " + account);
+ }
+ }
+ int syncStatus = AccountPreference.SYNC_DISABLED;
+ if (syncIsFailing) {
+ syncStatus = AccountPreference.SYNC_ERROR;
+ } else if (syncCount == 0) {
+ syncStatus = AccountPreference.SYNC_DISABLED;
+ } else if (syncCount > 0) {
+ syncStatus = AccountPreference.SYNC_ENABLED;
+ }
+ accountPref.setSyncStatus(syncStatus);
+ }
+
+ mErrorInfoView.setVisibility(anySyncFailed ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public void onAccountsUpdated(Account[] accounts) {
+ mManageAccountsCategory.removeAll();
+ for (int i = 0, n = accounts.length; i < n; i++) {
+ final Account account = accounts[i];
+ final ArrayList<String> auths = getAuthoritiesForAccountType(account.type);
+
+ boolean showAccount = true;
+ if (mAuthorities != null && auths != null) {
+ showAccount = false;
+ for (String requestedAuthority : mAuthorities) {
+ if (auths.contains(requestedAuthority)) {
+ showAccount = true;
+ break;
+ }
+ }
+ }
+
+ if (showAccount) {
+ final Drawable icon = getDrawableForType(account.type);
+ final AccountPreference preference =
+ new AccountPreference(getActivity(), account, icon, auths);
+ mManageAccountsCategory.addPreference(preference);
+ }
+ }
+ onSyncStateUpdated();
+ }
+
+ private void onAuthDescriptionsUpdated() {
+ // Update account icons for all account preference items
+ for (int i = 0; i < mManageAccountsCategory.getPreferenceCount(); i++) {
+ AccountPreference pref = (AccountPreference) mManageAccountsCategory.getPreference(i);
+ pref.setProviderIcon(getDrawableForType(pref.getAccount().type));
+ pref.setSummary(getLabelForType(pref.getAccount().type));
+ }
+ }
+
+ public void onClick(View v) {
+ if (v == mAddAccountButton) {
+ Intent intent = new Intent("android.settings.ADD_ACCOUNT_SETTINGS");
+ intent.putExtra(AUTHORITIES_FILTER_KEY, mAuthorities);
+ startActivity(intent);
+ }
+ }
+
+ /* The logic below is copied from AcountPrefernceBase */
+
+ private Drawable getDrawableForType(final String accountType) {
+ Drawable icon = null;
+ if (mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+ Context authContext = getActivity().createPackageContext(desc.packageName, 0);
+ icon = authContext.getResources().getDrawable(desc.iconId);
+ } catch (PackageManager.NameNotFoundException e) {
+ // TODO: place holder icon for missing account icons?
+ Log.w(TAG, "No icon for account type " + accountType);
+ }
+ }
+ return icon;
+ }
+
+ private CharSequence getLabelForType(final String accountType) {
+ CharSequence label = null;
+ if (mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+ Context authContext = getActivity().createPackageContext(desc.packageName, 0);
+ label = authContext.getResources().getText(desc.labelId);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "No label for account type " + ", type " + accountType);
+ }
+ }
+ return label;
+ }
+
+ private ArrayList<String> getAuthoritiesForAccountType(String type) {
+ if (mAccountTypeToAuthorities == null) {
+ mAccountTypeToAuthorities = Maps.newHashMap();
+ SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypes();
+ for (int i = 0, n = syncAdapters.length; i < n; i++) {
+ final SyncAdapterType sa = syncAdapters[i];
+ ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
+ if (authorities == null) {
+ authorities = new ArrayList<String>();
+ mAccountTypeToAuthorities.put(sa.accountType, authorities);
+ }
+ if (LDEBUG) {
+ Log.d(TAG, "added authority " + sa.authority + " to accountType "
+ + sa.accountType);
+ }
+ authorities.add(sa.authority);
+ }
+ }
+ return mAccountTypeToAuthorities.get(type);
+ }
+
+ private void updateAuthDescriptions(Context context) {
+ mAuthDescs = AccountManager.get(context).getAuthenticatorTypes();
+ for (int i = 0; i < mAuthDescs.length; i++) {
+ mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
+ }
+ onAuthDescriptionsUpdated();
+ }
+}
diff --git a/src/com/android/settings/PhysicalKeyboardSettings.java b/src/com/android/settings/PhysicalKeyboardSettings.java
index acd0bd677..b9591836c 100644
--- a/src/com/android/settings/PhysicalKeyboardSettings.java
+++ b/src/com/android/settings/PhysicalKeyboardSettings.java
@@ -20,12 +20,11 @@ import android.content.ContentResolver;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings.System;
-public class PhysicalKeyboardSettings extends PreferenceActivity {
-
+public class PhysicalKeyboardSettings extends SettingsPreferenceFragment {
+
private final String[] mSettingsUiKey = {
"auto_caps",
"auto_replace",
@@ -47,14 +46,14 @@ public class PhysicalKeyboardSettings extends PreferenceActivity {
};
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.keyboard_settings);
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
ContentResolver resolver = getContentResolver();
for (int i = 0; i < mSettingsUiKey.length; i++) {
@@ -66,7 +65,8 @@ public class PhysicalKeyboardSettings extends PreferenceActivity {
@Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ public boolean onPreferenceTreeClick(
+ PreferenceScreen preferenceScreen, Preference preference) {
// Physical keyboard stuff
for (int i = 0; i < mSettingsUiKey.length; i++) {
diff --git a/src/com/android/settings/PrivacySettings.java b/src/com/android/settings/PrivacySettings.java
index 29deacf29..826c9cfe1 100644
--- a/src/com/android/settings/PrivacySettings.java
+++ b/src/com/android/settings/PrivacySettings.java
@@ -22,23 +22,18 @@ import android.app.backup.IBackupManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
-import android.text.method.LinkMovementMethod;
-import android.widget.TextView;
/**
* Gesture lock pattern settings.
*/
-public class PrivacySettings extends PreferenceActivity implements
+public class PrivacySettings extends SettingsPreferenceFragment implements
DialogInterface.OnClickListener {
// Vendor specific
@@ -54,7 +49,7 @@ public class PrivacySettings extends PreferenceActivity implements
private int mDialogType;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.privacy_settings);
final PreferenceScreen screen = getPreferenceScreen();
@@ -63,7 +58,8 @@ public class PrivacySettings extends PreferenceActivity implements
mAutoRestore = (CheckBoxPreference) screen.findPreference(AUTO_RESTORE);
// Vendor specific
- if (getPackageManager().resolveContentProvider(GSETTINGS_PROVIDER, 0) == null) {
+ if (getActivity().getPackageManager().
+ resolveContentProvider(GSETTINGS_PROVIDER, 0) == null) {
screen.removePreference(findPreference(BACKUP_CATEGORY));
}
updateToggles();
@@ -110,7 +106,8 @@ public class PrivacySettings extends PreferenceActivity implements
mDialogType = DIALOG_ERASE_BACKUP;
CharSequence msg = getResources().getText(R.string.backup_erase_dialog_message);
- mConfirmDialog = new AlertDialog.Builder(this).setMessage(msg)
+ // TODO: DialogFragment?
+ mConfirmDialog = new AlertDialog.Builder(getActivity()).setMessage(msg)
.setTitle(R.string.backup_erase_dialog_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.ok, this)
diff --git a/src/com/android/settings/ProgressCategory.java b/src/com/android/settings/ProgressCategory.java
index f611137a5..c5b68b6dd 100644
--- a/src/com/android/settings/ProgressCategory.java
+++ b/src/com/android/settings/ProgressCategory.java
@@ -17,13 +17,10 @@
package com.android.settings;
import android.content.Context;
-import android.preference.PreferenceCategory;
import android.util.AttributeSet;
import android.view.View;
-import java.util.Map;
-
-public class ProgressCategory extends PreferenceCategory {
+public class ProgressCategory extends ProgressCategoryBase {
private boolean mProgress = false;
private View oldView = null;
@@ -36,10 +33,10 @@ public class ProgressCategory extends PreferenceCategory {
@Override
public void onBindView(View view) {
super.onBindView(view);
- View textView = view.findViewById(R.id.scanning_text);
- View progressBar = view.findViewById(R.id.scanning_progress);
+ final View textView = view.findViewById(R.id.scanning_text);
+ final View progressBar = view.findViewById(R.id.scanning_progress);
- int visibility = mProgress ? View.VISIBLE : View.INVISIBLE;
+ final int visibility = mProgress ? View.VISIBLE : View.INVISIBLE;
textView.setVisibility(visibility);
progressBar.setVisibility(visibility);
@@ -50,11 +47,8 @@ public class ProgressCategory extends PreferenceCategory {
}
oldView = view;
}
-
- /**
- * Turn on/off the progress indicator and text on the right.
- * @param progressOn whether or not the progress should be displayed
- */
+
+ @Override
public void setProgress(boolean progressOn) {
mProgress = progressOn;
notifyChanged();
diff --git a/src/com/android/settings/ProgressCategoryBase.java b/src/com/android/settings/ProgressCategoryBase.java
new file mode 100644
index 000000000..d120b9495
--- /dev/null
+++ b/src/com/android/settings/ProgressCategoryBase.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.content.Context;
+import android.preference.PreferenceCategory;
+import android.util.AttributeSet;
+
+public abstract class ProgressCategoryBase extends PreferenceCategory {
+ public ProgressCategoryBase(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * Turn on/off the progress indicator and text on the right.
+ * @param progressOn whether or not the progress should be displayed
+ */
+ public abstract void setProgress(boolean progressOn);
+} \ No newline at end of file
diff --git a/src/com/android/settings/ProxySelector.java b/src/com/android/settings/ProxySelector.java
index 66c81c622..aea09e76a 100644
--- a/src/com/android/settings/ProxySelector.java
+++ b/src/com/android/settings/ProxySelector.java
@@ -16,10 +16,15 @@
package com.android.settings;
+import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.Intent;
import android.net.Proxy;
import android.os.Bundle;
@@ -28,9 +33,11 @@ import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.util.Log;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
+import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
@@ -38,112 +45,128 @@ import android.widget.TextView;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * To start the Proxy Selector activity, create the following intent.
- *
- * <code>
- * Intent intent = new Intent();
- * intent.setClassName("com.android.browser.ProxySelector");
- * startActivity(intent);
- * </code>
- *
- * you can add extra options to the intent by using
- *
- * <code>
- * intent.putExtra(key, value);
- * </code>
- *
- * the extra options are:
- *
- * button-label: a string label to display for the okay button
- * title: the title of the window
- * error-text: If not null, will be used as the label of the error message.
- */
-public class ProxySelector extends Activity
-{
- private final static String LOGTAG = "Settings";
+public class ProxySelector extends Fragment implements DialogCreatable {
+ private static final String TAG = "ProxySelector";
EditText mHostnameField;
EditText mPortField;
+ EditText mExclusionListField;
Button mOKButton;
+ Button mClearButton;
+ Button mDefaultButton;
// Matches blank input, ips, and domain names
- private static final String HOSTNAME_REGEXP = "^$|^[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*$";
+ private static final String HOSTNAME_REGEXP =
+ "^$|^[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*$";
private static final Pattern HOSTNAME_PATTERN;
+ private static final String EXCLLIST_REGEXP =
+ "$|^(.?[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*)+" +
+ "(,(.?[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*))*$";
+ private static final Pattern EXCLLIST_PATTERN;
static {
HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
+ EXCLLIST_PATTERN = Pattern.compile(EXCLLIST_REGEXP);
}
private static final int ERROR_DIALOG_ID = 0;
+ private SettingsDialogFragment mDialogFragment;
+ private View mView;
+
+ @Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ }
- if (android.util.Config.LOGV) Log.v(LOGTAG, "[ProxySelector] onStart");
-
- setContentView(R.layout.proxy);
- initView();
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mView = inflater.inflate(R.layout.proxy, container, false);
+ initView(mView);
+ // TODO: Populate based on connection status
populateFields(false);
+ return mView;
}
@Override
- protected Dialog onCreateDialog(int id) {
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ final DevicePolicyManager dpm =
+ (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
+
+ final boolean userSetGlobalProxy = (dpm.getGlobalProxyAdmin() == null);
+ // Disable UI if the Global Proxy is being controlled by a Device Admin
+ mHostnameField.setEnabled(userSetGlobalProxy);
+ mPortField.setEnabled(userSetGlobalProxy);
+ mExclusionListField.setEnabled(userSetGlobalProxy);
+ mOKButton.setEnabled(userSetGlobalProxy);
+ mClearButton.setEnabled(userSetGlobalProxy);
+ mDefaultButton.setEnabled(userSetGlobalProxy);
+ }
+
+ // Dialog management
+
+ @Override
+ public Dialog onCreateDialog(int id) {
if (id == ERROR_DIALOG_ID) {
String hostname = mHostnameField.getText().toString().trim();
String portStr = mPortField.getText().toString().trim();
- String msg = getString(validate(hostname, portStr));
+ String exclList = mExclusionListField.getText().toString().trim();
+ String msg = getActivity().getString(validate(hostname, portStr, exclList));
- return new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(getActivity())
.setTitle(R.string.proxy_error)
.setPositiveButton(R.string.proxy_error_dismiss, null)
.setMessage(msg)
.create();
}
- return super.onCreateDialog(id);
+ return null;
}
- @Override
- protected void onPrepareDialog(int id, Dialog dialog) {
- super.onPrepareDialog(id, dialog);
-
- if (id == ERROR_DIALOG_ID) {
- String hostname = mHostnameField.getText().toString().trim();
- String portStr = mPortField.getText().toString().trim();
- String msg = getString(validate(hostname, portStr));
- ((AlertDialog)dialog).setMessage(msg);
+ private void showDialog(int dialogId) {
+ if (mDialogFragment != null) {
+ Log.e(TAG, "Old dialog fragment not null!");
}
+ mDialogFragment = new SettingsDialogFragment(this, dialogId);
+ mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
}
- void initView() {
-
- mHostnameField = (EditText)findViewById(R.id.hostname);
+ private void initView(View view) {
+ mHostnameField = (EditText)view.findViewById(R.id.hostname);
mHostnameField.setOnFocusChangeListener(mOnFocusChangeHandler);
- mPortField = (EditText)findViewById(R.id.port);
+ mPortField = (EditText)view.findViewById(R.id.port);
mPortField.setOnClickListener(mOKHandler);
mPortField.setOnFocusChangeListener(mOnFocusChangeHandler);
- mOKButton = (Button)findViewById(R.id.action);
+ mExclusionListField = (EditText)view.findViewById(R.id.exclusionlist);
+ mExclusionListField.setOnFocusChangeListener(mOnFocusChangeHandler);
+
+ mOKButton = (Button)view.findViewById(R.id.action);
mOKButton.setOnClickListener(mOKHandler);
- Button b = (Button)findViewById(R.id.clear);
- b.setOnClickListener(mClearHandler);
+ mClearButton = (Button)view.findViewById(R.id.clear);
+ mClearButton.setOnClickListener(mClearHandler);
- b = (Button)findViewById(R.id.defaultView);
- b.setOnClickListener(mDefaultHandler);
+ mDefaultButton = (Button)view.findViewById(R.id.defaultView);
+ mDefaultButton.setOnClickListener(mDefaultHandler);
}
void populateFields(boolean useDefault) {
+ final Activity activity = getActivity();
String hostname = null;
int port = -1;
+ String exclList = null;
if (useDefault) {
// Use the default proxy settings provided by the carrier
hostname = Proxy.getDefaultHost();
port = Proxy.getDefaultPort();
} else {
// Use the last setting given by the user
- hostname = Proxy.getHost(this);
- port = Proxy.getPort(this);
+ ContentResolver res = getActivity().getContentResolver();
+ hostname = Proxy.getHost(activity);
+ port = Proxy.getPort(activity);
+ exclList = Settings.Secure.getString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST);
}
if (hostname == null) {
@@ -155,7 +178,9 @@ public class ProxySelector extends Activity
String portStr = port == -1 ? "" : Integer.toString(port);
mPortField.setText(portStr);
- Intent intent = getIntent();
+ mExclusionListField.setText(exclList);
+
+ final Intent intent = activity.getIntent();
String buttonLabel = intent.getStringExtra("button-label");
if (!TextUtils.isEmpty(buttonLabel)) {
@@ -164,7 +189,7 @@ public class ProxySelector extends Activity
String title = intent.getStringExtra("title");
if (!TextUtils.isEmpty(title)) {
- setTitle(title);
+ activity.setTitle(title);
}
}
@@ -172,11 +197,14 @@ public class ProxySelector extends Activity
* validate syntax of hostname and port entries
* @return 0 on success, string resource ID on failure
*/
- int validate(String hostname, String port) {
+ int validate(String hostname, String port, String exclList) {
Matcher match = HOSTNAME_PATTERN.matcher(hostname);
+ Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
if (!match.matches()) return R.string.proxy_error_invalid_host;
+ if (!listMatch.matches()) return R.string.proxy_error_invalid_exclusion_list;
+
if (hostname.length() > 0 && port.length() == 0) {
return R.string.proxy_error_empty_port;
}
@@ -205,9 +233,10 @@ public class ProxySelector extends Activity
String hostname = mHostnameField.getText().toString().trim();
String portStr = mPortField.getText().toString().trim();
+ String exclList = mExclusionListField.getText().toString().trim();
int port = -1;
- int result = validate(hostname, portStr);
+ int result = validate(hostname, portStr, exclList);
if (result > 0) {
showDialog(ERROR_DIALOG_ID);
return false;
@@ -231,7 +260,7 @@ public class ProxySelector extends Activity
// controls.
// FIXME: If the user types in a proxy that matches the default, should
// we keep that setting? Can be fixed with a new UI.
- ContentResolver res = getContentResolver();
+ ContentResolver res = getActivity().getContentResolver();
if (hostname.equals(Proxy.getDefaultHost())
&& port == Proxy.getDefaultPort()) {
// If the user hit the default button and didn't change any of
@@ -244,7 +273,8 @@ public class ProxySelector extends Activity
hostname += ':' + portStr;
}
Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY, hostname);
- sendBroadcast(new Intent(Proxy.PROXY_CHANGE_ACTION));
+ Settings.Secure.putString(res, Settings.Secure.HTTP_PROXY_EXCLUSION_LIST, exclList);
+ getActivity().sendBroadcast(new Intent(Proxy.PROXY_CHANGE_ACTION));
return true;
}
@@ -252,7 +282,7 @@ public class ProxySelector extends Activity
OnClickListener mOKHandler = new OnClickListener() {
public void onClick(View v) {
if (saveToDb()) {
- finish();
+ getActivity().onBackPressed();
}
}
};
@@ -261,12 +291,14 @@ public class ProxySelector extends Activity
public void onClick(View v) {
mHostnameField.setText("");
mPortField.setText("");
+ mExclusionListField.setText("");
}
};
OnClickListener mDefaultHandler = new OnClickListener() {
public void onClick(View v) {
- populateFields(true);
+ // TODO: populate based on connection status
+ populateFields(false);
}
};
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index f0fcdd7f2..fd643cd69 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -17,13 +17,11 @@
package com.android.settings;
import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.SharedPreferences;
import android.content.res.Resources;
+import android.net.LinkProperties;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
@@ -33,7 +31,6 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.preference.PreferenceManager;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
@@ -66,9 +63,8 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
import java.io.IOException;
+import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
@@ -760,7 +756,7 @@ public class RadioInfo extends Activity {
List<DataConnection> dcs = phone.getCurrentDataConnectionList();
for (DataConnection dc : dcs) {
- sb.append(" State: ").append(dc.getStateAsString()).append("\n");
+ sb.append(" State=").append(dc.getStateAsString()).append("\n");
if (dc.isActive()) {
long timeElapsed =
(System.currentTimeMillis() - dc.getConnectionTime())/1000;
@@ -774,16 +770,8 @@ public class RadioInfo extends Activity {
sb.append("\n to ")
.append(pdp.getApn().toString());
}
- sb.append("\ninterface: ")
- .append(phone.getInterfaceName(phone.getActiveApnTypes()[0]))
- .append("\naddress: ")
- .append(phone.getIpAddress(phone.getActiveApnTypes()[0]))
- .append("\ngateway: ")
- .append(phone.getGateway(phone.getActiveApnTypes()[0]));
- String[] dns = phone.getDnsServers(phone.getActiveApnTypes()[0]);
- if (dns != null) {
- sb.append("\ndns: ").append(dns[0]).append(", ").append(dns[1]);
- }
+ sb.append("\nLinkProperties: ");
+ sb.append(phone.getLinkProperties(phone.getActiveApnTypes()[0]).toString());
} else if (dc.isInactive()) {
sb.append(" disconnected with last try at ")
.append(DateUtils.timeString(dc.getLastFailTime()))
@@ -801,7 +789,6 @@ public class RadioInfo extends Activity {
sb.append("\n===================");
}
-
disconnects.setText(sb.toString());
}
diff --git a/src/com/android/settings/RingerVolumePreference.java b/src/com/android/settings/RingerVolumePreference.java
index 3ecd81969..4479cb0c4 100644
--- a/src/com/android/settings/RingerVolumePreference.java
+++ b/src/com/android/settings/RingerVolumePreference.java
@@ -45,6 +45,12 @@ public class RingerVolumePreference extends VolumePreference implements
R.id.media_volume_seekbar,
R.id.alarm_volume_seekbar
};
+
+ private static final int[] NEED_VOICE_CAPABILITY_ID = new int[] {
+ com.android.internal.R.id.seekbar, R.id.notification_volume_title,
+ R.id.notification_volume_seekbar
+ };
+
private static final int[] SEEKBAR_TYPE = new int[] {
AudioManager.STREAM_NOTIFICATION,
AudioManager.STREAM_MUSIC,
@@ -83,17 +89,28 @@ public class RingerVolumePreference extends VolumePreference implements
getContext().getContentResolver(),
Settings.System.NOTIFICATIONS_USE_RING_VOLUME, 1) == 1);
setNotificationVolumeVisibility(!mNotificationsUseRingVolumeCheckbox.isChecked());
+ disableSettingsThatNeedVoice(view);
+ }
+
+ private void disableSettingsThatNeedVoice(View parent) {
+ final boolean voiceCapable = getContext().getResources()
+ .getBoolean(com.android.internal.R.bool.config_voice_capable);
+ if (!voiceCapable) {
+ for (int id : NEED_VOICE_CAPABILITY_ID) {
+ parent.findViewById(id).setVisibility(View.GONE);
+ }
+ }
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
-
+
if (!positiveResult) {
for (SeekBarVolumizer vol : mSeekBarVolumizer) {
if (vol != null) vol.revertVolume();
}
- }
+ }
cleanup();
}
@@ -102,13 +119,13 @@ public class RingerVolumePreference extends VolumePreference implements
super.onActivityStop();
cleanup();
}
-
+
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setNotificationVolumeVisibility(!isChecked);
-
+
Settings.System.putInt(getContext().getContentResolver(),
Settings.System.NOTIFICATIONS_USE_RING_VOLUME, isChecked ? 1 : 0);
-
+
if (isChecked) {
// The user wants the notification to be same as ring, so do a
// one-time sync right now
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 454ea6023..dacc19f43 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -17,8 +17,9 @@
package com.android.settings;
-import java.util.Observable;
-import java.util.Observer;
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
+import com.android.internal.widget.LockPatternUtils;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -33,25 +34,30 @@ import android.location.LocationManager;
import android.os.Bundle;
import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
+import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
+import android.preference.Preference.OnPreferenceChangeListener;
import android.provider.Settings;
import android.security.Credentials;
import android.security.KeyStore;
import android.telephony.TelephonyManager;
+import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.internal.widget.LockPatternUtils;
+import java.util.ArrayList;
+import java.util.Observable;
+import java.util.Observer;
/**
* Gesture lock pattern settings.
*/
-public class SecuritySettings extends PreferenceActivity {
+public class SecuritySettings extends SettingsPreferenceFragment
+ implements OnPreferenceChangeListener {
private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
// Lock Settings
@@ -75,7 +81,9 @@ public class SecuritySettings extends PreferenceActivity {
private static final String LOCATION_NETWORK = "location_network";
private static final String LOCATION_GPS = "location_gps";
private static final String ASSISTED_GPS = "assisted_gps";
+ private static final String LOCK_AFTER_TIMEOUT_KEY = "lock_after_timeout";
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
+ private static final int FALLBACK_LOCK_AFTER_TIMEOUT_VALUE = 5000; // compatible with pre-Froyo
// Credential storage
private CredentialStorage mCredentialStorage = new CredentialStorage();
@@ -93,8 +101,13 @@ public class SecuritySettings extends PreferenceActivity {
// This is necessary because the Network Location Provider can change settings
// if the user does not confirm enabling the provider.
private ContentQueryMap mContentQueryMap;
+
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private LockPatternUtils mLockPatternUtils;
+ private ListPreference mLockAfter;
+
+ private SettingsObserver mSettingsObserver;
+
private final class SettingsObserver implements Observer {
public void update(Observable o, Object arg) {
updateToggles();
@@ -102,26 +115,36 @@ public class SecuritySettings extends PreferenceActivity {
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mLockPatternUtils = new LockPatternUtils(this);
+ mLockPatternUtils = new LockPatternUtils(getActivity());
mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
- mChooseLockSettingsHelper = new ChooseLockSettingsHelper(this);
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
createPreferenceHierarchy();
updateToggles();
+ }
+ @Override
+ public void onStart() {
+ super.onStart();
// listen for Location Manager settings changes
Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null,
"(" + Settings.System.NAME + "=?)",
new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
null);
mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
- mContentQueryMap.addObserver(new SettingsObserver());
+ mContentQueryMap.addObserver(mSettingsObserver = new SettingsObserver());
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ mContentQueryMap.deleteObserver(mSettingsObserver);
}
private PreferenceScreen createPreferenceHierarchy() {
@@ -151,13 +174,14 @@ public class SecuritySettings extends PreferenceActivity {
break;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
addPreferencesFromResource(R.xml.security_settings_password);
break;
}
}
- // set or change current. Should be common to all unlock preference screens
- // mSetOrChange = (PreferenceScreen) pm.findPreference(KEY_UNLOCK_SET_OR_CHANGE);
+ // lock after preference
+ mLockAfter = setupLockAfterPreference(pm);
// visible pattern
mVisiblePattern = (CheckBoxPreference) pm.findPreference(KEY_VISIBLE_PATTERN);
@@ -171,22 +195,22 @@ public class SecuritySettings extends PreferenceActivity {
if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType)
{
PreferenceScreen simLockPreferences = getPreferenceManager()
- .createPreferenceScreen(this);
+ .createPreferenceScreen(getActivity());
simLockPreferences.setTitle(R.string.sim_lock_settings_category);
// Intent to launch SIM lock settings
simLockPreferences.setIntent(new Intent().setClassName(PACKAGE, ICC_LOCK_SETTINGS));
- PreferenceCategory simLockCat = new PreferenceCategory(this);
+ PreferenceCategory simLockCat = new PreferenceCategory(getActivity());
simLockCat.setTitle(R.string.sim_lock_settings_title);
root.addPreference(simLockCat);
simLockCat.addPreference(simLockPreferences);
}
// Passwords
- PreferenceCategory passwordsCat = new PreferenceCategory(this);
+ PreferenceCategory passwordsCat = new PreferenceCategory(getActivity());
passwordsCat.setTitle(R.string.security_passwords_title);
root.addPreference(passwordsCat);
- CheckBoxPreference showPassword = mShowPassword = new CheckBoxPreference(this);
+ CheckBoxPreference showPassword = mShowPassword = new CheckBoxPreference(getActivity());
showPassword.setKey("show_password");
showPassword.setTitle(R.string.show_password);
showPassword.setSummary(R.string.show_password_summary);
@@ -194,36 +218,91 @@ public class SecuritySettings extends PreferenceActivity {
passwordsCat.addPreference(showPassword);
// Device policies
- PreferenceCategory devicePoliciesCat = new PreferenceCategory(this);
+ PreferenceCategory devicePoliciesCat = new PreferenceCategory(getActivity());
devicePoliciesCat.setTitle(R.string.device_admin_title);
root.addPreference(devicePoliciesCat);
- Preference deviceAdminButton = new Preference(this);
+ Preference deviceAdminButton = new Preference(getActivity());
deviceAdminButton.setTitle(R.string.manage_device_admin);
deviceAdminButton.setSummary(R.string.manage_device_admin_summary);
Intent deviceAdminIntent = new Intent();
- deviceAdminIntent.setClass(this, DeviceAdminSettings.class);
+ deviceAdminIntent.setClass(getActivity(), DeviceAdminSettings.class);
deviceAdminButton.setIntent(deviceAdminIntent);
devicePoliciesCat.addPreference(deviceAdminButton);
// Credential storage
- PreferenceCategory credentialsCat = new PreferenceCategory(this);
+ PreferenceCategory credentialsCat = new PreferenceCategory(getActivity());
credentialsCat.setTitle(R.string.credentials_category);
root.addPreference(credentialsCat);
mCredentialStorage.createPreferences(credentialsCat, CredentialStorage.TYPE_KEYSTORE);
// File System Encryption
- PreferenceCategory encryptedfsCat = new PreferenceCategory(this);
+ PreferenceCategory encryptedfsCat = new PreferenceCategory(getActivity());
encryptedfsCat.setTitle(R.string.encrypted_fs_category);
//root.addPreference(encryptedfsCat);
mCredentialStorage.createPreferences(encryptedfsCat, CredentialStorage.TYPE_ENCRYPTEDFS);
return root;
}
+ private ListPreference setupLockAfterPreference(PreferenceManager pm) {
+ ListPreference result = (ListPreference) pm.findPreference(LOCK_AFTER_TIMEOUT_KEY);
+ if (result != null) {
+ int lockAfterValue = Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+ FALLBACK_LOCK_AFTER_TIMEOUT_VALUE);
+ result.setValue(String.valueOf(lockAfterValue));
+ result.setOnPreferenceChangeListener(this);
+ final long adminTimeout = mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0;
+ final ContentResolver cr = getContentResolver();
+ final long displayTimeout = Math.max(0,
+ Settings.System.getInt(cr, SCREEN_OFF_TIMEOUT, 0));
+ if (adminTimeout > 0) {
+ // This setting is a slave to display timeout when a device policy is enforced.
+ // As such, maxLockTimeout = adminTimeout - displayTimeout.
+ // If there isn't enough time, shows "immediately" setting.
+ disableUnusableTimeouts(result, Math.max(0, adminTimeout - displayTimeout));
+ }
+ }
+ return result;
+ }
+
+ private static void disableUnusableTimeouts(ListPreference pref, long maxTimeout) {
+ final CharSequence[] entries = pref.getEntries();
+ final CharSequence[] values = pref.getEntryValues();
+ ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
+ ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
+ for (int i = 0; i < values.length; i++) {
+ long timeout = Long.valueOf(values[i].toString());
+ if (timeout <= maxTimeout) {
+ revisedEntries.add(entries[i]);
+ revisedValues.add(values[i]);
+ }
+ }
+ if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
+ pref.setEntries(
+ revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
+ pref.setEntryValues(
+ revisedValues.toArray(new CharSequence[revisedValues.size()]));
+ final int userPreference = Integer.valueOf(pref.getValue());
+ if (userPreference <= maxTimeout) {
+ pref.setValue(String.valueOf(userPreference));
+ } else {
+ // There will be no highlighted selection since nothing in the list matches
+ // maxTimeout. The user can still select anything less than maxTimeout.
+ // TODO: maybe append maxTimeout to the list and mark selected.
+ }
+ }
+ pref.setEnabled(revisedEntries.size() > 0);
+ }
+
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
+ // Make sure we reload the preference hierarchy since some of these settings
+ // depend on others...
+ createPreferenceHierarchy();
+
final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
if (mVisiblePattern != null) {
mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
@@ -245,7 +324,7 @@ public class SecuritySettings extends PreferenceActivity {
final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
- Intent intent = new Intent(this, ChooseLockGeneric.class);
+ Intent intent = new Intent(getActivity(), ChooseLockGeneric.class);
startActivityForResult(intent, SET_OR_CHANGE_LOCK_METHOD_REQUEST);
} else if (KEY_LOCK_ENABLED.equals(key)) {
lockPatternUtils.setLockPatternEnabled(isToggled(preference));
@@ -299,7 +378,7 @@ public class SecuritySettings extends PreferenceActivity {
* @see #confirmPatternThenDisableAndClear
*/
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
createPreferenceHierarchy();
}
@@ -341,7 +420,7 @@ public class SecuritySettings extends PreferenceActivity {
mState = mKeyStore.test();
updatePreferences(mState);
- Intent intent = getIntent();
+ Intent intent = getActivity().getIntent();
if (!mExternal && intent != null &&
Credentials.UNLOCK_ACTION.equals(intent.getAction())) {
mExternal = true;
@@ -350,7 +429,8 @@ public class SecuritySettings extends PreferenceActivity {
} else if (mState == KeyStore.LOCKED) {
showUnlockDialog();
} else {
- finish();
+ // TODO: Verify if this is the right way
+ SecuritySettings.this.getFragmentManager().popBackStack();
}
}
}
@@ -392,13 +472,13 @@ public class SecuritySettings extends PreferenceActivity {
Boolean bval = (Boolean)value;
mWillEnableEncryptedFS = bval.booleanValue();
showSwitchEncryptedFSDialog();
- }
+ }
return true;
}
public boolean onPreferenceClick(Preference preference) {
if (preference == mInstallButton) {
- Credentials.getInstance().installFromSdCard(SecuritySettings.this);
+ Credentials.getInstance().installFromSdCard(SecuritySettings.this.getActivity());
} else if (preference == mPasswordButton) {
showPasswordDialog();
} else if (preference == mResetButton) {
@@ -419,11 +499,12 @@ public class SecuritySettings extends PreferenceActivity {
if (button == DialogInterface.BUTTON_POSITIVE) {
Intent intent = new Intent("android.intent.action.MASTER_CLEAR");
intent.putExtra("enableEFS", mWillEnableEncryptedFS);
- sendBroadcast(intent);
+ getActivity().sendBroadcast(intent);
updatePreferences(mState);
} else if (button == DialogInterface.BUTTON_NEGATIVE) {
// Cancel action
- Toast.makeText(SecuritySettings.this, R.string.encrypted_fs_cancel_confirm,
+ Toast.makeText(SecuritySettings.this.getActivity(),
+ R.string.encrypted_fs_cancel_confirm,
Toast.LENGTH_SHORT).show();
updatePreferences(mState);
} else {
@@ -434,7 +515,10 @@ public class SecuritySettings extends PreferenceActivity {
}
public void onDismiss(DialogInterface dialog) {
- if (mSubmit && !isFinishing()) {
+ // TODO:
+ //if (mSubmit && !isFinishing()) {
+
+ if (mSubmit) {
mSubmit = false;
if (!checkPassword((Dialog) dialog)) {
((Dialog) dialog).show();
@@ -443,7 +527,8 @@ public class SecuritySettings extends PreferenceActivity {
}
updatePreferences(mState);
if (mExternal) {
- finish();
+ // TODO:
+ // finish();
}
}
@@ -518,25 +603,25 @@ public class SecuritySettings extends PreferenceActivity {
private void createPreferences(PreferenceCategory category, int type) {
switch(type) {
case TYPE_KEYSTORE:
- mAccessCheckBox = new CheckBoxPreference(SecuritySettings.this);
+ mAccessCheckBox = new CheckBoxPreference(SecuritySettings.this.getActivity());
mAccessCheckBox.setTitle(R.string.credentials_access);
mAccessCheckBox.setSummary(R.string.credentials_access_summary);
mAccessCheckBox.setOnPreferenceChangeListener(this);
category.addPreference(mAccessCheckBox);
- mInstallButton = new Preference(SecuritySettings.this);
+ mInstallButton = new Preference(SecuritySettings.this.getActivity());
mInstallButton.setTitle(R.string.credentials_install_certificates);
mInstallButton.setSummary(R.string.credentials_install_certificates_summary);
mInstallButton.setOnPreferenceClickListener(this);
category.addPreference(mInstallButton);
- mPasswordButton = new Preference(SecuritySettings.this);
+ mPasswordButton = new Preference(SecuritySettings.this.getActivity());
mPasswordButton.setTitle(R.string.credentials_set_password);
mPasswordButton.setSummary(R.string.credentials_set_password_summary);
mPasswordButton.setOnPreferenceClickListener(this);
category.addPreference(mPasswordButton);
- mResetButton = new Preference(SecuritySettings.this);
+ mResetButton = new Preference(SecuritySettings.this.getActivity());
mResetButton.setTitle(R.string.credentials_reset);
mResetButton.setSummary(R.string.credentials_reset_summary);
mResetButton.setOnPreferenceClickListener(this);
@@ -544,7 +629,8 @@ public class SecuritySettings extends PreferenceActivity {
break;
case TYPE_ENCRYPTEDFS:
- mEncryptedFSEnabled = new CheckBoxPreference(SecuritySettings.this);
+ mEncryptedFSEnabled = new CheckBoxPreference(SecuritySettings.this
+ .getActivity());
mEncryptedFSEnabled.setTitle(R.string.encrypted_fs_enable);
mEncryptedFSEnabled.setSummary(R.string.encrypted_fs_enable_summary);
mEncryptedFSEnabled.setOnPreferenceChangeListener(this);
@@ -567,20 +653,20 @@ public class SecuritySettings extends PreferenceActivity {
if (mState == state) {
return;
} else if (state == KeyStore.NO_ERROR) {
- Toast.makeText(SecuritySettings.this, R.string.credentials_enabled,
+ Toast.makeText(SecuritySettings.this.getActivity(), R.string.credentials_enabled,
Toast.LENGTH_SHORT).show();
} else if (state == KeyStore.UNINITIALIZED) {
- Toast.makeText(SecuritySettings.this, R.string.credentials_erased,
+ Toast.makeText(SecuritySettings.this.getActivity(), R.string.credentials_erased,
Toast.LENGTH_SHORT).show();
} else if (state == KeyStore.LOCKED) {
- Toast.makeText(SecuritySettings.this, R.string.credentials_disabled,
+ Toast.makeText(SecuritySettings.this.getActivity(), R.string.credentials_disabled,
Toast.LENGTH_SHORT).show();
}
mState = state;
}
private void showUnlockDialog() {
- View view = View.inflate(SecuritySettings.this,
+ View view = View.inflate(SecuritySettings.this.getActivity(),
R.layout.credentials_unlock_dialog, null);
// Show extra hint only when the action comes from outside.
@@ -588,7 +674,7 @@ public class SecuritySettings extends PreferenceActivity {
view.findViewById(R.id.hint).setVisibility(View.VISIBLE);
}
- Dialog dialog = new AlertDialog.Builder(SecuritySettings.this)
+ Dialog dialog = new AlertDialog.Builder(SecuritySettings.this.getActivity())
.setView(view)
.setTitle(R.string.credentials_unlock)
.setPositiveButton(android.R.string.ok, this)
@@ -600,7 +686,7 @@ public class SecuritySettings extends PreferenceActivity {
}
private void showPasswordDialog() {
- View view = View.inflate(SecuritySettings.this,
+ View view = View.inflate(SecuritySettings.this.getActivity(),
R.layout.credentials_password_dialog, null);
if (mState == KeyStore.UNINITIALIZED) {
@@ -610,7 +696,7 @@ public class SecuritySettings extends PreferenceActivity {
view.findViewById(R.id.old_password).setVisibility(View.VISIBLE);
}
- Dialog dialog = new AlertDialog.Builder(SecuritySettings.this)
+ Dialog dialog = new AlertDialog.Builder(SecuritySettings.this.getActivity())
.setView(view)
.setTitle(R.string.credentials_set_password)
.setPositiveButton(android.R.string.ok, this)
@@ -623,17 +709,18 @@ public class SecuritySettings extends PreferenceActivity {
private void showResetDialog() {
mShowingDialog = DLG_RESET;
- new AlertDialog.Builder(SecuritySettings.this)
+ new AlertDialog.Builder(SecuritySettings.this.getActivity())
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.credentials_reset_hint)
- .setNeutralButton(getString(android.R.string.ok), this)
- .setNegativeButton(getString(android.R.string.cancel), this)
+ .setNeutralButton(getResources().getString(android.R.string.ok), this)
+ .setNegativeButton(getResources().getString(android.R.string.cancel), this)
.create().show();
}
private void showSwitchEncryptedFSDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(SecuritySettings.this)
+ AlertDialog.Builder builder = new AlertDialog.Builder(SecuritySettings.this
+ .getActivity())
.setCancelable(false)
.setTitle(R.string.encrypted_fs_alert_dialog_title);
@@ -651,4 +738,17 @@ public class SecuritySettings extends PreferenceActivity {
}
}
}
+
+ public boolean onPreferenceChange(Preference preference, Object value) {
+ if (preference == mLockAfter) {
+ int lockAfter = Integer.parseInt((String) value);
+ try {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, lockAfter);
+ } catch (NumberFormatException e) {
+ Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
+ }
+ }
+ return true;
+ }
}
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index d92483407..738acc3e2 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,48 +16,61 @@
package com.android.settings;
-import android.net.sip.SipManager;
+import android.app.Fragment;
import android.os.Bundle;
-import android.preference.Preference;
import android.preference.PreferenceActivity;
-import android.preference.PreferenceGroup;
-public class Settings extends PreferenceActivity {
+import java.util.List;
- private static final String KEY_PARENT = "parent";
- private static final String KEY_CALL_SETTINGS = "call_settings";
- private static final String KEY_SYNC_SETTINGS = "sync_settings";
- private static final String KEY_DOCK_SETTINGS = "dock_settings";
-
- private static final String KEY_OPERATOR_SETTINGS = "operator_settings";
- private static final String KEY_MANUFACTURER_SETTINGS = "manufacturer_settings";
+/**
+ * Top-level settings activity to handle single pane and double pane UI layout.
+ */
+public class Settings extends PreferenceActivity implements
+ SettingsPreferenceFragment.FragmentStarter {
+
+ // TODO: Update Call Settings based on airplane mode state.
+ /**
+ * Populate the activity with the top-level headers.
+ */
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.settings);
+ public void onBuildHeaders(List<Header> target) {
+ loadHeadersFromResource(R.xml.settings_headers, target);
- PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
- Utils.updatePreferenceToSpecificActivityOrRemove(this, parent, KEY_SYNC_SETTINGS, 0);
+ updateHeaderList(target);
+ }
- Preference dockSettings = parent.findPreference(KEY_DOCK_SETTINGS);
- if (getResources().getBoolean(R.bool.has_dock_settings) == false && dockSettings != null) {
- parent.removePreference(dockSettings);
+ private void updateHeaderList(List<Header> target) {
+ int i = 0;
+ while (i < target.size()) {
+ Header header = target.get(i);
+ long id = header.id;
+ if (id == R.id.dock_settings) {
+ if (!needsDockSettings())
+ target.remove(header);
+ } else if (id == R.id.operator_settings || id == R.id.manufacturer_settings) {
+ Utils.updateHeaderToSpecificActivityFromMetaDataOrRemove(this, target, header);
+ } else if (id == R.id.call_settings) {
+ if (!Utils.isVoiceCapable(this))
+ target.remove(header);
+ }
+ if (target.get(i) == header)
+ i++;
}
-
- Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(this, parent,
- KEY_OPERATOR_SETTINGS);
- Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(this, parent,
- KEY_MANUFACTURER_SETTINGS);
}
-
- @Override
- protected void onResume() {
- super.onResume();
- findPreference(KEY_CALL_SETTINGS).setEnabled(
- !AirplaneModeEnabler.isAirplaneModeOn(this)
- || SipManager.isVoipSupported(this));
+
+ private boolean needsDockSettings() {
+ return getResources().getBoolean(R.bool.has_dock_settings);
}
+ public boolean startFragment(Fragment caller, String fragmentClass, int requestCode,
+ Bundle extras) {
+ Fragment f = Fragment.instantiate(this, fragmentClass, extras);
+ caller.setTargetFragment(f, requestCode);
+ if (f instanceof SettingsPreferenceFragment) {
+ SettingsPreferenceFragment spf = (SettingsPreferenceFragment) f;
+ spf.setFragmentStarter(this);
+ }
+ return true;
+ }
}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
new file mode 100644
index 000000000..f41561e86
--- /dev/null
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceFragment;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+/**
+ * Letting the class, assumed to be Fragment, create a Dialog on it. Should be useful
+ * you want to utilize some capability in {@link SettingsPreferenceFragment} but don't want
+ * the class inherit the class itself (See {@link ProxySelector} for example).
+ */
+interface DialogCreatable {
+ public Dialog onCreateDialog(int dialogId);
+}
+
+/**
+ * Base class for Settings fragments, with some helper functions and dialog management.
+ */
+public class SettingsPreferenceFragment extends PreferenceFragment
+ implements DialogCreatable {
+
+ private static final String TAG = "SettingsPreferenceFragment";
+
+ // Originally from PreferenceActivity.
+ private static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
+ private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
+ private static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
+ private static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
+
+ private SettingsDialogFragment mDialogFragment;
+
+ private OnStateListener mOnStateListener;
+ private FragmentStarter mFragmentStarter;
+
+ private int mResultCode = Activity.RESULT_CANCELED;
+ private Intent mResultData;
+
+ private Button mNextButton;
+
+ private boolean mReportedCreation;
+
+ interface OnStateListener {
+
+ void onCreated(SettingsPreferenceFragment fragment);
+
+ void onDestroyed(SettingsPreferenceFragment fragment);
+ }
+
+ public void setOnStateListener(OnStateListener listener) {
+ mOnStateListener = listener;
+ }
+
+ /**
+ * Letting the class, assumed to be Fragment, start another Fragment object.
+ * The target Fragment object is stored in the caller Fragment using
+ * {@link Fragment#setTargetFragment(Fragment, int)}. The caller
+ * is able to obtain result code and result data via
+ * {@link SettingsPreferenceFragment#getResultCode()} and
+ * {@link SettingsPreferenceFragment#getResultData()} accordingly.
+ */
+ interface FragmentStarter {
+ public boolean startFragment(
+ Fragment caller, String fragmentClass, int requestCode, Bundle extras);
+ }
+
+ public void setFragmentStarter(FragmentStarter starter) {
+ mFragmentStarter = starter;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ final Fragment f = getTargetFragment();
+ final int requestCode = getTargetRequestCode();
+
+ // TargetFragment becomes invalid when this object is resumed. Notify it to
+ // FragmentManager. Without this code, FragmentManager wrongly take the TargetFragment
+ // as live, and throws IllegalStateException.
+ setTargetFragment(null, -1);
+
+ if (f != null && (f instanceof SettingsPreferenceFragment)) {
+ final SettingsPreferenceFragment spf = (SettingsPreferenceFragment)f;
+ final int resultCode = spf.getResultCode();
+ final Intent resultData = spf.getResultData();
+ onActivityResult(requestCode, resultCode, resultData);
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (mOnStateListener != null && !mReportedCreation) {
+ mOnStateListener.onCreated(this);
+ // So that we don't report it on the way back to this fragment
+ mReportedCreation = true;
+ }
+
+ setupButtonBar();
+ }
+
+ public final void setResult(int resultCode) {
+ mResultCode = resultCode;
+ mResultData = null;
+ }
+
+ public final void setResult(int resultCode, Intent data) {
+ mResultCode = resultCode;
+ mResultData = data;
+ }
+
+ public final int getResultCode() {
+ return mResultCode;
+ }
+
+ public final Intent getResultData() {
+ return mResultData;
+ }
+
+ /*
+ * The name is intentionally made different from Activity#finish(), so that
+ * users won't misunderstand its meaning.
+ */
+ public final void finishFragment() {
+ getActivity().onBackPressed();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mOnStateListener != null) {
+ mOnStateListener.onDestroyed(this);
+ }
+ }
+
+ // Some helpers for functions used by the settings fragments when they were activities
+
+ /**
+ * Returns the ContentResolver from the owning Activity.
+ */
+ protected ContentResolver getContentResolver() {
+ return getActivity().getContentResolver();
+ }
+
+ /**
+ * Returns the specified system service from the owning Activity.
+ */
+ protected Object getSystemService(final String name) {
+ return getActivity().getSystemService(name);
+ }
+
+ /**
+ * Returns the Resources from the owning Activity.
+ */
+ protected Resources getResources() {
+ return getActivity().getResources();
+ }
+
+ /**
+ * Returns the PackageManager from the owning Activity.
+ */
+ protected PackageManager getPackageManager() {
+ return getActivity().getPackageManager();
+ }
+
+ // Dialog management
+
+ protected void showDialog(int dialogId) {
+ if (mDialogFragment != null) {
+ Log.e(TAG, "Old dialog fragment not null!");
+ }
+ mDialogFragment = new SettingsDialogFragment(this, dialogId);
+ mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
+ }
+
+ @Override
+ public Dialog onCreateDialog(int dialogId) {
+ return null;
+ }
+
+ protected void removeDialog(int dialogId) {
+ if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId
+ && mDialogFragment.isVisible()) {
+ mDialogFragment.dismiss();
+ }
+ mDialogFragment = null;
+ }
+
+ static class SettingsDialogFragment extends DialogFragment {
+ private int mDialogId;
+
+ private DialogCreatable mFragment;
+
+ SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
+ mDialogId = dialogId;
+ mFragment = fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return mFragment.onCreateDialog(mDialogId);
+ }
+
+ public int getDialogId() {
+ return mDialogId;
+ }
+ }
+
+ protected boolean hasNextButton() {
+ return mNextButton != null;
+ }
+
+ protected Button getNextButton() {
+ return mNextButton;
+ }
+
+ public void finish() {
+ getActivity().onBackPressed();
+ }
+
+ public boolean startFragment(
+ Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
+ if (mFragmentStarter != null) {
+ return mFragmentStarter.startFragment(caller, fragmentClass, requestCode, extras);
+ } else {
+ Log.w(TAG, "FragmentStarter is not set.");
+ return false;
+ }
+ }
+
+ /**
+ * Sets up Button Bar possibly required in the Fragment. Probably available only in
+ * phones.
+ *
+ * Previously {@link PreferenceActivity} had the capability as hidden functionality.
+ */
+ private void setupButtonBar() {
+ // Originally from PreferenceActivity, which has had button bar inside its layout.
+ final Activity activity = getActivity();
+ final Intent intent = activity.getIntent();
+ final View buttonBar = activity.findViewById(com.android.internal.R.id.button_bar);
+ if (!intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false) || buttonBar == null) {
+ return;
+ }
+
+ buttonBar.setVisibility(View.VISIBLE);
+ View tmpView = activity.findViewById(com.android.internal.R.id.back_button);
+ if (tmpView != null) {
+ // TODO: Assume this is pressed only in single pane, finishing current Activity.
+ try {
+ final Button backButton = (Button)tmpView;
+ backButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ activity.setResult(Activity.RESULT_CANCELED);
+ activity.finish();
+ }
+ });
+ if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
+ String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
+ if (TextUtils.isEmpty(buttonText)) {
+ backButton.setVisibility(View.GONE);
+ }
+ else {
+ backButton.setText(buttonText);
+ }
+ }
+ } catch (ClassCastException e) {
+ Log.w(TAG, "The view originally for back_button is used not as Button. " +
+ "Ignored.");
+ }
+ }
+
+ tmpView = activity.findViewById(com.android.internal.R.id.skip_button);
+ if (tmpView != null) {
+ try {
+ final Button skipButton = (Button)tmpView;
+ skipButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ activity.setResult(Activity.RESULT_OK);
+ activity.finish();
+ }
+ });
+ if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
+ skipButton.setVisibility(View.VISIBLE);
+ }
+ } catch (ClassCastException e) {
+ Log.w(TAG, "The view originally for skip_button is used not as Button. " +
+ "Ignored.");
+ }
+ }
+
+ tmpView = activity.findViewById(com.android.internal.R.id.next_button);
+ if (tmpView != null) {
+ try {
+ mNextButton = (Button)tmpView;
+ mNextButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ activity.setResult(Activity.RESULT_OK);
+ activity.finish();
+ }
+ });
+ // set our various button parameters
+ if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
+ String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
+ if (TextUtils.isEmpty(buttonText)) {
+ mNextButton.setVisibility(View.GONE);
+ }
+ else {
+ mNextButton.setText(buttonText);
+ }
+ }
+ } catch (ClassCastException e) {
+ Log.w(TAG, "The view originally for next_button is used not as Button. " +
+ "Ignored.");
+ mNextButton = null;
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/SoundSettings.java b/src/com/android/settings/SoundSettings.java
index a735268b1..8582f171f 100644
--- a/src/com/android/settings/SoundSettings.java
+++ b/src/com/android/settings/SoundSettings.java
@@ -23,26 +23,21 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.TelephonyManager;
import android.util.Log;
-import android.view.IWindowManager;
-public class SoundSettings extends PreferenceActivity implements
+public class SoundSettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener {
private static final String TAG = "SoundAndDisplaysSettings";
/** If there is no setting in the provider, use this. */
- private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
private static final int FALLBACK_EMERGENCY_TONE_VALUE = 0;
private static final String KEY_SILENT = "silent";
@@ -54,12 +49,21 @@ public class SoundSettings extends PreferenceActivity implements
private static final String KEY_SOUND_SETTINGS = "sound_settings";
private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
private static final String KEY_LOCK_SOUNDS = "lock_sounds";
+ private static final String KEY_RINGTONE = "ringtone";
+ private static final String KEY_NOTIFICATION_SOUND = "notification_sound";
+ private static final String KEY_CATEGORY_CALLS = "category_calls";
+ private static final String KEY_CATEGORY_NOTIFICATION = "category_notification";
private static final String VALUE_VIBRATE_NEVER = "never";
private static final String VALUE_VIBRATE_ALWAYS = "always";
private static final String VALUE_VIBRATE_ONLY_SILENT = "silent";
private static final String VALUE_VIBRATE_UNLESS_SILENT = "notsilent";
+ private static final String[] NEED_VOICE_CAPABILITY = {
+ KEY_RINGTONE, KEY_DTMF_TONE, KEY_CATEGORY_CALLS,
+ KEY_EMERGENCY_TONE
+ };
+
private CheckBoxPreference mSilent;
/*
@@ -90,7 +94,7 @@ public class SoundSettings extends PreferenceActivity implements
private PreferenceGroup mSoundSettings;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ContentResolver resolver = getContentResolver();
int activePhoneType = TelephonyManager.getDefault().getPhoneType();
@@ -137,8 +141,8 @@ public class SoundSettings extends PreferenceActivity implements
mSoundSettings = (PreferenceGroup) findPreference(KEY_SOUND_SETTINGS);
mNotificationPulse = (CheckBoxPreference)
mSoundSettings.findPreference(KEY_NOTIFICATION_PULSE);
- if (mNotificationPulse != null &&
- getResources().getBoolean(R.bool.has_intrusive_led) == false) {
+ if (mNotificationPulse != null
+ && getResources().getBoolean(R.bool.has_intrusive_led) == false) {
mSoundSettings.removePreference(mNotificationPulse);
} else {
try {
@@ -150,23 +154,31 @@ public class SoundSettings extends PreferenceActivity implements
}
}
+ if (!Utils.isVoiceCapable(getActivity())) {
+ for (String prefKey : NEED_VOICE_CAPABILITY) {
+ Preference pref = findPreference(prefKey);
+ if (pref != null) {
+ getPreferenceScreen().removePreference(pref);
+ }
+ }
+ }
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
updateState(true);
IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
- registerReceiver(mReceiver, filter);
+ getActivity().registerReceiver(mReceiver, filter);
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
- unregisterReceiver(mReceiver);
+ getActivity().unregisterReceiver(mReceiver);
}
private String getPhoneVibrateSettingValue() {
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index b92457113..f632a02ce 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -16,21 +16,24 @@
package com.android.settings;
+import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.wifi.WifiApEnabler;
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.os.Bundle;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.AssetManager;
import android.net.ConnectivityManager;
+import android.os.Bundle;
import android.os.Environment;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.webkit.WebView;
@@ -41,10 +44,14 @@ import java.util.Locale;
/*
* Displays preferences for Tethering.
*/
-public class TetherSettings extends PreferenceActivity {
+public class TetherSettings extends SettingsPreferenceFragment {
+ private static final String TAG = "TetheringSettings";
+
private static final String USB_TETHER_SETTINGS = "usb_tether_settings";
private static final String ENABLE_WIFI_AP = "enable_wifi_ap";
private static final String WIFI_AP_SETTINGS = "wifi_ap_settings";
+ private static final String ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering";
+ private static final String BLUETOOTH_TETHER_SETTINGS = "bluetooth_tether_settings";
private static final String TETHERING_HELP = "tethering_help";
private static final String USB_HELP_MODIFIER = "usb_";
private static final String WIFI_HELP_MODIFIER = "wifi_";
@@ -59,6 +66,10 @@ public class TetherSettings extends PreferenceActivity {
private CheckBoxPreference mEnableWifiAp;
private PreferenceScreen mWifiApSettings;
private WifiApEnabler mWifiApEnabler;
+
+ private CheckBoxPreference mBluetoothTether;
+ private PreferenceScreen mBluetoothSettings;
+
private PreferenceScreen mTetherHelp;
private BroadcastReceiver mTetherChangeReceiver;
@@ -67,48 +78,85 @@ public class TetherSettings extends PreferenceActivity {
private String[] mWifiRegexs;
+ private String[] mBluetoothRegexs;
+ private BluetoothPan mBluetoothPan;
+
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
-
addPreferencesFromResource(R.xml.tether_prefs);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ final Activity activity = getActivity();
+ mBluetoothPan = new BluetoothPan(activity);
mEnableWifiAp = (CheckBoxPreference) findPreference(ENABLE_WIFI_AP);
mWifiApSettings = (PreferenceScreen) findPreference(WIFI_AP_SETTINGS);
mUsbTether = (CheckBoxPreference) findPreference(USB_TETHER_SETTINGS);
+ mBluetoothTether = (CheckBoxPreference) findPreference(ENABLE_BLUETOOTH_TETHERING);
+ mBluetoothSettings = (PreferenceScreen) findPreference(BLUETOOTH_TETHER_SETTINGS);
mTetherHelp = (PreferenceScreen) findPreference(TETHERING_HELP);
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
mUsbRegexs = cm.getTetherableUsbRegexs();
- if (mUsbRegexs.length == 0) {
- getPreferenceScreen().removePreference(mUsbTether);
+ mWifiRegexs = cm.getTetherableWifiRegexs();
+ mBluetoothRegexs = cm.getTetherableBluetoothRegexs();
- setTitle(R.string.tether_settings_title_wifi);
- }
+ boolean usbAvailable = mUsbRegexs.length != 0;
+ boolean wifiAvailable = mWifiRegexs.length != 0;
+ boolean bluetoothAvailable = mBluetoothRegexs.length != 0;
- mWifiRegexs = cm.getTetherableWifiRegexs();
- if (mWifiRegexs.length == 0) {
+
+ if (!usbAvailable || Utils.isMonkeyRunning()) {
+ getPreferenceScreen().removePreference(mUsbTether);
+ }
+ if (!wifiAvailable) {
getPreferenceScreen().removePreference(mEnableWifiAp);
getPreferenceScreen().removePreference(mWifiApSettings);
-
- setTitle(R.string.tether_settings_title_usb);
- } else if (mUsbRegexs.length != 0) {
- // have both
- setTitle(R.string.tether_settings_title_both);
}
- mWifiApEnabler = new WifiApEnabler(this, mEnableWifiAp);
- mView = new WebView(this);
+ if (!bluetoothAvailable) {
+ getPreferenceScreen().removePreference(mBluetoothTether);
+ getPreferenceScreen().removePreference(mBluetoothSettings);
+ } else {
+ if (mBluetoothPan.isTetheringOn()) {
+ mBluetoothTether.setChecked(true);
+ mBluetoothSettings.setEnabled(true);
+ } else {
+ mBluetoothTether.setChecked(false);
+ mBluetoothSettings.setEnabled(false);
+ }
+ }
+ if (wifiAvailable && usbAvailable && bluetoothAvailable){
+ activity.setTitle(R.string.tether_settings_title_all);
+ } else if (wifiAvailable && usbAvailable){
+ activity.setTitle(R.string.tether_settings_title_all);
+ } else if (wifiAvailable && bluetoothAvailable){
+ activity.setTitle(R.string.tether_settings_title_all);
+ } else if (wifiAvailable) {
+ activity.setTitle(R.string.tether_settings_title_wifi);
+ } else if (usbAvailable && bluetoothAvailable) {
+ activity.setTitle(R.string.tether_settings_title_usb_bluetooth);
+ } else if (usbAvailable) {
+ activity.setTitle(R.string.tether_settings_title_usb);
+ } else {
+ activity.setTitle(R.string.tether_settings_title_bluetooth);
+ }
+ mWifiApEnabler = new WifiApEnabler(activity, mEnableWifiAp);
+ mView = new WebView(activity);
}
@Override
- protected Dialog onCreateDialog(int id) {
+ public Dialog onCreateDialog(int id) {
if (id == DIALOG_TETHER_HELP) {
Locale locale = Locale.getDefault();
// check for the full language + country resource, if not there, try just language
- AssetManager am = getAssets();
+ final AssetManager am = getActivity().getAssets();
String path = HELP_PATH.replace("%y", locale.getLanguage().toLowerCase());
path = path.replace("%z", "_"+locale.getCountry().toLowerCase());
boolean useCountry = true;
@@ -138,7 +186,7 @@ public class TetherSettings extends PreferenceActivity {
mView.loadUrl(url);
- return new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(getActivity())
.setCancelable(true)
.setTitle(R.string.tethering_help_button_text)
.setView(mView)
@@ -148,6 +196,7 @@ public class TetherSettings extends PreferenceActivity {
}
private class TetherChangeReceiver extends BroadcastReceiver {
+ @Override
public void onReceive(Context content, Intent intent) {
if (intent.getAction().equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
// TODO - this should understand the interface types
@@ -157,37 +206,46 @@ public class TetherSettings extends PreferenceActivity {
ConnectivityManager.EXTRA_ACTIVE_TETHER);
ArrayList<String> errored = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ERRORED_TETHER);
- updateState((String[]) available.toArray(), (String[]) active.toArray(),
- (String[]) errored.toArray());
+ updateState(available.toArray(new String[available.size()]),
+ active.toArray(new String[active.size()]),
+ errored.toArray(new String[errored.size()]));
} else if (intent.getAction().equals(Intent.ACTION_MEDIA_SHARED) ||
intent.getAction().equals(Intent.ACTION_MEDIA_UNSHARED)) {
updateState();
+ } else if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+ updateState();
}
}
}
@Override
- protected void onResume() {
- super.onResume();
+ public void onStart() {
+ super.onStart();
+
+ final Activity activity = getActivity();
- IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
mTetherChangeReceiver = new TetherChangeReceiver();
- Intent intent = registerReceiver(mTetherChangeReceiver, filter);
+ IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+ Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_SHARED);
filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
filter.addDataScheme("file");
- registerReceiver(mTetherChangeReceiver, filter);
+ activity.registerReceiver(mTetherChangeReceiver, filter);
+
+ filter = new IntentFilter();
+ filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ activity.registerReceiver(mTetherChangeReceiver, filter);
- if (intent != null) mTetherChangeReceiver.onReceive(this, intent);
+ if (intent != null) mTetherChangeReceiver.onReceive(activity, intent);
mWifiApEnabler.resume();
}
@Override
- protected void onPause() {
- super.onPause();
- unregisterReceiver(mTetherChangeReceiver);
+ public void onStop() {
+ super.onStop();
+ getActivity().unregisterReceiver(mTetherChangeReceiver);
mTetherChangeReceiver = null;
mWifiApEnabler.pause();
}
@@ -204,6 +262,13 @@ public class TetherSettings extends PreferenceActivity {
private void updateState(String[] available, String[] tethered,
String[] errored) {
+ updateUsbState(available, tethered, errored);
+ updateBluetoothState(available, tethered, errored);
+ }
+
+
+ private void updateUsbState(String[] available, String[] tethered,
+ String[] errored) {
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
boolean usbTethered = false;
@@ -260,8 +325,68 @@ public class TetherSettings extends PreferenceActivity {
}
}
+ private void updateBluetoothState(String[] available, String[] tethered,
+ String[] errored) {
+ ConnectivityManager cm =
+ (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+ boolean bluetoothTethered = false;
+ boolean bluetoothAvailable = false;
+ int bluetoothError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ boolean bluetoothErrored = false;
+ for (String s : available) {
+ for (String regex : mBluetoothRegexs) {
+ if (s.matches(regex)) {
+ bluetoothAvailable = true;
+ if (bluetoothError == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ bluetoothError = cm.getLastTetherError(s);
+ }
+ }
+ }
+ }
+ for (String s : tethered) {
+ for (String regex : mBluetoothRegexs) {
+ if (s.matches(regex)) bluetoothTethered = true;
+ }
+ }
+ for (String s: errored) {
+ for (String regex : mBluetoothRegexs) {
+ if (s.matches(regex)) bluetoothErrored = true;
+ }
+ }
+
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ int btState = adapter.getState();
+ if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
+ mBluetoothTether.setEnabled(false);
+ mBluetoothSettings.setEnabled(false);
+ mBluetoothTether.setSummary(R.string.wifi_stopping);
+ } else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
+ mBluetoothTether.setEnabled(false);
+ mBluetoothSettings.setEnabled(false);
+ mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
+ } else if (mBluetoothPan.isTetheringOn()) {
+ mBluetoothTether.setChecked(true);
+ if (btState == BluetoothAdapter.STATE_ON) {
+ mBluetoothTether.setEnabled(true);
+ mBluetoothSettings.setEnabled(true);
+ if (bluetoothTethered) {
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_connected_subtext);
+ } else if (bluetoothErrored) {
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
+ } else {
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
+ }
+ }
+ } else {
+ mBluetoothTether.setEnabled(true);
+ mBluetoothTether.setChecked(false);
+ mBluetoothSettings.setEnabled(false);
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext);
+ }
+ }
+
@Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (preference == mUsbTether) {
boolean newState = mUsbTether.isChecked();
@@ -296,11 +421,52 @@ public class TetherSettings extends PreferenceActivity {
}
mUsbTether.setSummary("");
}
- } else if (preference == mTetherHelp) {
+ } else if(preference == mBluetoothTether) {
+ boolean bluetoothTetherState = mBluetoothTether.isChecked();
+
+ if (bluetoothTetherState) {
+ // turn on Bluetooth first
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
+ adapter.enable();
+ mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
+ mBluetoothTether.setEnabled(false);
+ mBluetoothSettings.setEnabled(false);
+ } else {
+ mBluetoothSettings.setEnabled(true);
+ }
+
+ mBluetoothPan.setBluetoothTethering(true);
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
+ } else {
+ boolean errored = false;
+ ConnectivityManager cm =
+ (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+ String [] tethered = cm.getTetheredIfaces();
+ String bluetoothIface = findIface(tethered, mBluetoothRegexs);
+ if (bluetoothIface != null &&
+ cm.untether(bluetoothIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ errored = true;
+ }
+
+ mBluetoothPan.setBluetoothTethering(false);
+ mBluetoothSettings.setEnabled(false);
+ if (errored) {
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
+ } else {
+ mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext);
+ }
+ }
+ } else if (preference == mBluetoothSettings) {
+ preference.getExtras().putString(BluetoothSettings.ACTION,
+ BluetoothSettings.ACTION_LAUNCH_TETHER_PICKER);
+ } else if (preference == mTetherHelp) {
showDialog(DIALOG_TETHER_HELP);
+ return true;
}
- return false;
+
+ return super.onPreferenceTreeClick(screen, preference);
}
private String findIface(String[] ifaces, String[] regexes) {
diff --git a/src/com/android/settings/TextToSpeechSettings.java b/src/com/android/settings/TextToSpeechSettings.java
index 89a464198..dc3a96b6b 100644
--- a/src/com/android/settings/TextToSpeechSettings.java
+++ b/src/com/android/settings/TextToSpeechSettings.java
@@ -16,29 +16,30 @@
package com.android.settings;
-import static android.provider.Settings.Secure.TTS_USE_DEFAULTS;
-import static android.provider.Settings.Secure.TTS_DEFAULT_RATE;
-import static android.provider.Settings.Secure.TTS_DEFAULT_LANG;
import static android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY;
-import static android.provider.Settings.Secure.TTS_DEFAULT_VARIANT;
+import static android.provider.Settings.Secure.TTS_DEFAULT_LANG;
+import static android.provider.Settings.Secure.TTS_DEFAULT_RATE;
import static android.provider.Settings.Secure.TTS_DEFAULT_SYNTH;
+import static android.provider.Settings.Secure.TTS_DEFAULT_VARIANT;
import static android.provider.Settings.Secure.TTS_ENABLED_PLUGINS;
+import static android.provider.Settings.Secure.TTS_USE_DEFAULTS;
+import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
-import android.preference.CheckBoxPreference;
+import android.preference.Preference.OnPreferenceClickListener;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.speech.tts.TextToSpeech;
@@ -49,7 +50,7 @@ import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
-public class TextToSpeechSettings extends PreferenceActivity implements
+public class TextToSpeechSettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
TextToSpeech.OnInitListener {
@@ -90,8 +91,6 @@ public class TextToSpeechSettings extends PreferenceActivity implements
private String mDefaultEng = "";
private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
- // Array of strings used to demonstrate TTS in the different languages.
- private String[] mDemoStrings;
// Index of the current string to use for the demo.
private int mDemoStringIndex = 0;
@@ -109,16 +108,14 @@ public class TextToSpeechSettings extends PreferenceActivity implements
private static final int GET_SAMPLE_TEXT = 1983;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
addPreferencesFromResource(R.xml.tts_settings);
- addEngineSpecificSettings();
-
- mDemoStrings = getResources().getStringArray(R.array.tts_demo_strings);
+ final Activity activity = getActivity();
+ addEngineSpecificSettings(activity);
- setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
+ activity.setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
mEnableDemo = false;
mTtsStarted = false;
@@ -128,18 +125,18 @@ public class TextToSpeechSettings extends PreferenceActivity implements
mDefaultCountry = currentLocale.getISO3Country();
mDefaultLocVariant = currentLocale.getVariant();
- mTts = new TextToSpeech(this, this);
+ mTts = new TextToSpeech(activity, this);
+ initClickers();
}
@Override
- protected void onStart() {
+ public void onStart() {
super.onStart();
if (mTtsStarted){
// whenever we return to this screen, we don't know the state of the
// system, so we have to recheck that we can play the demo, or it must be disabled.
// TODO make the TTS service listen to "changes in the system", i.e. sd card un/mount
- initClickers();
updateWidgetState();
checkVoiceData();
}
@@ -147,7 +144,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements
@Override
- protected void onDestroy() {
+ public void onDestroy() {
super.onDestroy();
if (mTts != null) {
mTts.shutdown();
@@ -155,7 +152,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
if ((mDefaultRatePref != null) && (mDefaultRatePref.getDialog() != null)) {
mDefaultRatePref.getDialog().dismiss();
@@ -168,9 +165,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements
}
}
-
-
- private void addEngineSpecificSettings() {
+ private void addEngineSpecificSettings(Context context) {
PreferenceGroup enginesCategory = (PreferenceGroup) findPreference("tts_engines_section");
Intent intent = new Intent("android.intent.action.START_TTS_ENGINE");
ResolveInfo[] enginesArray = new ResolveInfo[0];
@@ -180,14 +175,14 @@ public class TextToSpeechSettings extends PreferenceActivity implements
String prefKey = "";
final String pluginPackageName = enginesArray[i].activityInfo.packageName;
if (!enginesArray[i].activityInfo.packageName.equals(SYSTEM_TTS)) {
- CheckBoxPreference chkbxPref = new CheckBoxPreference(this);
+ CheckBoxPreference chkbxPref = new CheckBoxPreference(context);
prefKey = KEY_PLUGIN_ENABLED_PREFIX + pluginPackageName;
chkbxPref.setKey(prefKey);
chkbxPref.setTitle(enginesArray[i].loadLabel(pm));
enginesCategory.addPreference(chkbxPref);
}
if (pluginHasSettings(pluginPackageName)) {
- Preference pref = new Preference(this);
+ Preference pref = new Preference(context);
prefKey = KEY_PLUGIN_SETTINGS_PREFIX + pluginPackageName;
pref.setKey(prefKey);
pref.setTitle(enginesArray[i].loadLabel(pm));
@@ -360,9 +355,8 @@ public class TextToSpeechSettings extends PreferenceActivity implements
mDefaultLocVariant = new String();
}
mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry, mDefaultLocVariant));
- mTts.setSpeechRate((float)(mDefaultRate/100.0f));
+ mTts.setSpeechRate(mDefaultRate/100.0f);
initDefaultSettings();
- initClickers();
updateWidgetState();
checkVoiceData();
mTtsStarted = true;
@@ -378,7 +372,8 @@ public class TextToSpeechSettings extends PreferenceActivity implements
/**
* Called when voice data integrity check returns
*/
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VOICE_DATA_INTEGRITY_CHECK) {
if (data == null){
// The CHECK_TTS_DATA activity for the plugin did not run properly;
@@ -402,7 +397,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements
}
if (available.size() > 0){
if (mTts == null) {
- mTts = new TextToSpeech(this, this);
+ mTts = new TextToSpeech(getActivity(), this);
}
ListPreference ttsLanguagePref =
(ListPreference) findPreference("tts_default_lang");
@@ -478,7 +473,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements
updateWidgetState();
} else if (requestCode == GET_SAMPLE_TEXT) {
if (resultCode == TextToSpeech.LANG_AVAILABLE) {
- String sample = getString(R.string.tts_demo);
+ String sample = getActivity().getString(R.string.tts_demo);
if ((data != null) && (data.getStringExtra("sampleText") != null)) {
sample = data.getStringExtra("sampleText");
}
@@ -492,7 +487,6 @@ public class TextToSpeechSettings extends PreferenceActivity implements
}
}
-
public boolean onPreferenceChange(Preference preference, Object objValue) {
if (KEY_TTS_USE_DEFAULT.equals(preference.getKey())) {
// "Use Defaults"
@@ -507,7 +501,7 @@ public class TextToSpeechSettings extends PreferenceActivity implements
Settings.Secure.putInt(getContentResolver(),
TTS_DEFAULT_RATE, mDefaultRate);
if (mTts != null) {
- mTts.setSpeechRate((float)(mDefaultRate/100.0f));
+ mTts.setSpeechRate(mDefaultRate/100.0f);
}
Log.i(TAG, "TTS default rate is " + mDefaultRate);
} catch (NumberFormatException e) {
@@ -575,10 +569,11 @@ public class TextToSpeechSettings extends PreferenceActivity implements
if (!chkPref.getKey().equals(KEY_TTS_USE_DEFAULT)){
if (chkPref.isChecked()) {
chkPref.setChecked(false);
- AlertDialog d = (new AlertDialog.Builder(this))
+ AlertDialog d = (new AlertDialog.Builder(getActivity()))
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(getString(R.string.tts_engine_security_warning,
+ .setMessage(
+ getActivity().getString(R.string.tts_engine_security_warning,
chkPref.getTitle()))
.setCancelable(true)
.setPositiveButton(android.R.string.ok,
diff --git a/src/com/android/settings/UserDictionarySettings.java b/src/com/android/settings/UserDictionarySettings.java
index 6ffcb3d6b..7bd5d56ac 100644
--- a/src/com/android/settings/UserDictionarySettings.java
+++ b/src/com/android/settings/UserDictionarySettings.java
@@ -16,23 +16,32 @@
package com.android.settings;
+import com.android.settings.SettingsPreferenceFragment.SettingsDialogFragment;
+
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.ListActivity;
+import android.app.ListFragment;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.UserDictionary;
import android.text.InputType;
+import android.util.Log;
import android.view.ContextMenu;
+import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AlphabetIndexer;
import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SectionIndexer;
@@ -42,7 +51,8 @@ import android.widget.AdapterView.AdapterContextMenuInfo;
import java.util.Locale;
-public class UserDictionarySettings extends ListActivity {
+public class UserDictionarySettings extends ListFragment implements DialogCreatable {
+ private static final String TAG = "UserDictionarySettings";
private static final String INSTANCE_KEY_DIALOG_EDITING_WORD = "DIALOG_EDITING_WORD";
private static final String INSTANCE_KEY_ADDED_WORD = "DIALOG_ADDED_WORD";
@@ -50,7 +60,10 @@ public class UserDictionarySettings extends ListActivity {
private static final String[] QUERY_PROJECTION = {
UserDictionary.Words._ID, UserDictionary.Words.WORD
};
-
+
+ private static final int INDEX_ID = 0;
+ private static final int INDEX_WORD = 1;
+
// Either the locale is empty (means the word is applicable to all locales)
// or the word equals our current locale
private static final String QUERY_SELECTION = UserDictionary.Words.LOCALE + "=? OR "
@@ -69,52 +82,65 @@ public class UserDictionarySettings extends ListActivity {
/** The word being edited in the dialog (null means the user is adding a word). */
private String mDialogEditingWord;
-
+
+ private View mView;
private Cursor mCursor;
private boolean mAddedWordAlready;
private boolean mAutoReturn;
-
+
+ private SettingsDialogFragment mDialogFragment;
+
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mView = inflater.inflate(R.layout.list_content_with_empty_view, container, false);
+ return mView;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
- setContentView(R.layout.list_content_with_empty_view);
-
mCursor = createCursor();
- setListAdapter(createAdapter());
-
- TextView emptyView = (TextView) findViewById(R.id.empty);
+ TextView emptyView = (TextView)mView.findViewById(R.id.empty);
emptyView.setText(R.string.user_dict_settings_empty_text);
-
- ListView listView = getListView();
+
+ final ListView listView = getListView();
+ listView.setAdapter(createAdapter());
listView.setFastScrollEnabled(true);
listView.setEmptyView(emptyView);
registerForContextMenu(listView);
+ setHasOptionsMenu(true);
+
+ if (savedInstanceState != null) {
+ mDialogEditingWord = savedInstanceState.getString(INSTANCE_KEY_DIALOG_EDITING_WORD);
+ mAddedWordAlready = savedInstanceState.getBoolean(INSTANCE_KEY_ADDED_WORD, false);
+ }
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
+ final Intent intent = getActivity().getIntent();
if (!mAddedWordAlready
- && getIntent().getAction().equals("com.android.settings.USER_DICTIONARY_INSERT")) {
- String word = getIntent().getStringExtra(EXTRA_WORD);
+ && intent.getAction().equals("com.android.settings.USER_DICTIONARY_INSERT")) {
+ final String word = intent.getStringExtra(EXTRA_WORD);
mAutoReturn = true;
if (word != null) {
showAddOrEditDialog(word);
}
}
}
- @Override
- protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
- mDialogEditingWord = state.getString(INSTANCE_KEY_DIALOG_EDITING_WORD);
- mAddedWordAlready = state.getBoolean(INSTANCE_KEY_ADDED_WORD, false);
- }
@Override
- protected void onSaveInstanceState(Bundle outState) {
+ public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(INSTANCE_KEY_DIALOG_EDITING_WORD, mDialogEditingWord);
outState.putBoolean(INSTANCE_KEY_ADDED_WORD, mAddedWordAlready);
@@ -123,21 +149,21 @@ public class UserDictionarySettings extends ListActivity {
private Cursor createCursor() {
String currentLocale = Locale.getDefault().toString();
// Case-insensitive sort
- return managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
+ return getActivity().managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION,
QUERY_SELECTION, new String[] { currentLocale },
"UPPER(" + UserDictionary.Words.WORD + ")");
}
private ListAdapter createAdapter() {
- return new MyAdapter(this,
- android.R.layout.simple_list_item_1, mCursor,
- new String[] { UserDictionary.Words.WORD },
- new int[] { android.R.id.text1 });
+ return new MyAdapter(getActivity(),
+ R.layout.user_dictionary_item, mCursor,
+ new String[] { UserDictionary.Words.WORD, UserDictionary.Words._ID },
+ new int[] { android.R.id.text1, R.id.delete_button }, this);
}
@Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- openContextMenu(v);
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ getActivity().openContextMenu(v);
}
@Override
@@ -175,10 +201,11 @@ public class UserDictionarySettings extends ListActivity {
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ MenuItem actionItem =
+ menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title)
.setIcon(R.drawable.ic_menu_add);
- return true;
+ actionItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
@Override
@@ -191,7 +218,7 @@ public class UserDictionarySettings extends ListActivity {
mDialogEditingWord = editingWord;
showDialog(DIALOG_ADD_OR_EDIT);
}
-
+
private String getWord(int position) {
mCursor.moveToPosition(position);
// Handle a possible race-condition
@@ -202,14 +229,16 @@ public class UserDictionarySettings extends ListActivity {
}
@Override
- protected Dialog onCreateDialog(int id) {
- View content = getLayoutInflater().inflate(R.layout.dialog_edittext, null);
+ public Dialog onCreateDialog(int id) {
+ final Activity activity = getActivity();
+ final View content = activity.getLayoutInflater().inflate(R.layout.dialog_edittext, null);
final EditText editText = (EditText) content.findViewById(R.id.edittext);
+ editText.setText(mDialogEditingWord);
// No prediction in soft keyboard mode. TODO: Create a better way to disable prediction
editText.setInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
-
- AlertDialog dialog = new AlertDialog.Builder(this)
+
+ AlertDialog dialog = new AlertDialog.Builder(activity)
.setTitle(mDialogEditingWord != null
? R.string.user_dict_settings_edit_dialog_title
: R.string.user_dict_settings_add_dialog_title)
@@ -217,11 +246,11 @@ public class UserDictionarySettings extends ListActivity {
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
onAddOrEditFinished(editText.getText().toString());
- if (mAutoReturn) finish();
+ if (mAutoReturn) activity.onBackPressed();
}})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- if (mAutoReturn) finish();
+ if (mAutoReturn) activity.onBackPressed();
}})
.create();
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
@@ -229,14 +258,12 @@ public class UserDictionarySettings extends ListActivity {
return dialog;
}
- @Override
- protected void onPrepareDialog(int id, Dialog d) {
- AlertDialog dialog = (AlertDialog) d;
- d.setTitle(mDialogEditingWord != null
- ? R.string.user_dict_settings_edit_dialog_title
- : R.string.user_dict_settings_add_dialog_title);
- EditText editText = (EditText) dialog.findViewById(R.id.edittext);
- editText.setText(mDialogEditingWord);
+ private void showDialog(int dialogId) {
+ if (mDialogFragment != null) {
+ Log.e(TAG, "Old dialog fragment not null!");
+ }
+ mDialogFragment = new SettingsDialogFragment(this, dialogId);
+ mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
}
private void onAddOrEditFinished(String word) {
@@ -249,26 +276,48 @@ public class UserDictionarySettings extends ListActivity {
deleteWord(word);
// TODO: present UI for picking whether to add word to all locales, or current.
- UserDictionary.Words.addWord(this, word.toString(),
+ UserDictionary.Words.addWord(getActivity(), word.toString(),
250, UserDictionary.Words.LOCALE_TYPE_ALL);
- mCursor.requery();
+ if (!mCursor.requery()) {
+ throw new IllegalStateException("can't requery on already-closed cursor.");
+ }
mAddedWordAlready = true;
}
private void deleteWord(String word) {
- getContentResolver().delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION,
- new String[] { word });
+ getActivity().getContentResolver().delete(
+ UserDictionary.Words.CONTENT_URI, DELETE_SELECTION, new String[] { word });
}
-
- private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer {
- private AlphabetIndexer mIndexer;
-
- public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
+
+ private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer,
+ View.OnClickListener {
+
+ private AlphabetIndexer mIndexer;
+ private UserDictionarySettings mSettings;
+
+ private ViewBinder mViewBinder = new ViewBinder() {
+
+ public boolean setViewValue(View v, Cursor c, int columnIndex) {
+ if (v instanceof ImageView && columnIndex == INDEX_ID) {
+ v.setOnClickListener(MyAdapter.this);
+ v.setTag(c.getString(INDEX_WORD));
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to,
+ UserDictionarySettings settings) {
super(context, layout, c, from, to);
+ mSettings = settings;
int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD);
- String alphabet = context.getString(com.android.internal.R.string.fast_scroll_alphabet);
- mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
+ String alphabet = context.getString(
+ com.android.internal.R.string.fast_scroll_alphabet);
+ mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet);
+ setViewBinder(mViewBinder);
}
public int getPositionForSection(int section) {
@@ -282,5 +331,9 @@ public class UserDictionarySettings extends ListActivity {
public Object[] getSections() {
return mIndexer.getSections();
}
+
+ public void onClick(View v) {
+ mSettings.deleteWord((String) v.getTag());
+ }
}
}
diff --git a/src/com/android/settings/UserLeaveHintListener.java b/src/com/android/settings/UserLeaveHintListener.java
new file mode 100644
index 000000000..c5c2a7a47
--- /dev/null
+++ b/src/com/android/settings/UserLeaveHintListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+/**
+ * Interface enabling fragments to listen to Activity#onUserLeaveHint().
+ */
+public interface UserLeaveHintListener {
+ public void onUserLeaveHint();
+} \ No newline at end of file
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index b29ec06f5..d6354035d 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -21,14 +21,16 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.SystemProperties;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.SystemProperties;
import android.preference.Preference;
import android.preference.PreferenceGroup;
+import android.preference.PreferenceActivity.Header;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import java.util.List;
@@ -201,10 +203,79 @@ public class Utils {
return false;
}
+ public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
+ List<Header> target, Header header) {
+
+ Intent intent = header.intent;
+ if (intent != null) {
+ // Find the activity that is in the system image
+ PackageManager pm = context.getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+ int listSize = list.size();
+ for (int i = 0; i < listSize; i++) {
+ ResolveInfo resolveInfo = list.get(i);
+ if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+ != 0) {
+ Drawable icon = null;
+ String title = null;
+ String summary = null;
+
+ // Get the activity's meta-data
+ try {
+ Resources res = pm.getResourcesForApplication(
+ resolveInfo.activityInfo.packageName);
+ Bundle metaData = resolveInfo.activityInfo.metaData;
+
+ if (res != null && metaData != null) {
+ icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
+ title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
+ summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
+ }
+ } catch (NameNotFoundException e) {
+ // Ignore
+ } catch (NotFoundException e) {
+ // Ignore
+ }
+
+ // Set the preference title to the activity's label if no
+ // meta-data is found
+ if (TextUtils.isEmpty(title)) {
+ title = resolveInfo.loadLabel(pm).toString();
+ }
+
+ // Set icon, title and summary for the preference
+ // TODO:
+ //header.icon = icon;
+ header.title = title;
+ header.summary = summary;
+ // Replace the intent with this specific activity
+ header.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
+
+ return true;
+ }
+ }
+ }
+
+ // Did not find a matching activity, so remove the preference
+ if (target.remove(header)) System.err.println("Removed " + header.id);
+
+ return false;
+ }
+
/**
* Returns true if Monkey is running.
*/
public static boolean isMonkeyRunning() {
return SystemProperties.getBoolean("ro.monkey", false);
}
+
+ /**
+ * Returns whether the device is voice-capable (meaning, it is also a phone).
+ */
+ public static boolean isVoiceCapable(Context context) {
+ TelephonyManager telephony =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ return telephony != null && telephony.isVoiceCapable();
+ }
}
diff --git a/src/com/android/settings/VoiceInputOutputSettings.java b/src/com/android/settings/VoiceInputOutputSettings.java
index 30beddad7..b07c69ee6 100644
--- a/src/com/android/settings/VoiceInputOutputSettings.java
+++ b/src/com/android/settings/VoiceInputOutputSettings.java
@@ -31,7 +31,6 @@ import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
@@ -49,7 +48,7 @@ import java.util.List;
/**
* Settings screen for voice input/output.
*/
-public class VoiceInputOutputSettings extends PreferenceActivity
+public class VoiceInputOutputSettings extends SettingsPreferenceFragment
implements OnPreferenceChangeListener {
private static final String TAG = "VoiceInputOutputSettings";
@@ -67,7 +66,7 @@ public class VoiceInputOutputSettings extends PreferenceActivity
private HashMap<String, ResolveInfo> mAvailableRecognizersMap;
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.voice_input_output_settings);
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 78cf8cff6..6d1ce8d27 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -16,27 +16,26 @@
package com.android.settings;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.settings.bluetooth.BluetoothEnabler;
+import com.android.settings.wifi.WifiEnabler;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
-import android.util.Log;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
-import com.android.settings.bluetooth.BluetoothEnabler;
-import com.android.settings.wifi.WifiEnabler;
-
-public class WirelessSettings extends PreferenceActivity {
+public class WirelessSettings extends SettingsPreferenceFragment {
private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
private static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth";
@@ -45,6 +44,7 @@ public class WirelessSettings extends PreferenceActivity {
private static final String KEY_BT_SETTINGS = "bt_settings";
private static final String KEY_VPN_SETTINGS = "vpn_settings";
private static final String KEY_TETHER_SETTINGS = "tether_settings";
+ private static final String KEY_PROXY_SETTINGS = "proxy_settings";
public static final String EXIT_ECM_RESULT = "exit_ecm_result";
public static final int REQUEST_CODE_EXIT_ECM = 1;
@@ -69,7 +69,7 @@ public class WirelessSettings extends PreferenceActivity {
return true;
}
// Let the intents be launched by the Preference manager
- return false;
+ return super.onPreferenceTreeClick(preferenceScreen, preference);
}
public static boolean isRadioAllowed(Context context, String type) {
@@ -83,21 +83,22 @@ public class WirelessSettings extends PreferenceActivity {
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.wireless_settings);
+ final Activity activity = getActivity();
CheckBoxPreference airplane = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);
CheckBoxPreference wifi = (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI);
CheckBoxPreference bt = (CheckBoxPreference) findPreference(KEY_TOGGLE_BLUETOOTH);
- mAirplaneModeEnabler = new AirplaneModeEnabler(this, airplane);
+ mAirplaneModeEnabler = new AirplaneModeEnabler(activity, airplane);
mAirplaneModePreference = (CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE);
- mWifiEnabler = new WifiEnabler(this, wifi);
- mBtEnabler = new BluetoothEnabler(this, bt);
+ mWifiEnabler = new WifiEnabler(activity, wifi);
+ mBtEnabler = new BluetoothEnabler(activity, bt);
- String toggleable = Settings.System.getString(getContentResolver(),
+ String toggleable = Settings.System.getString(activity.getContentResolver(),
Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
// Manually set dependencies for Wifi when not toggleable.
@@ -118,50 +119,72 @@ public class WirelessSettings extends PreferenceActivity {
findPreference(KEY_BT_SETTINGS).setEnabled(false);
}
+ // Enable Proxy selector settings if allowed.
+ Preference mGlobalProxy = findPreference(KEY_PROXY_SETTINGS);
+ DevicePolicyManager mDPM = (DevicePolicyManager)
+ activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ mGlobalProxy.setEnabled(mDPM.getGlobalProxyAdmin() == null);
+
// Disable Tethering if it's not allowed
ConnectivityManager cm =
- (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
+ (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
if (!cm.isTetheringSupported()) {
getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
} else {
String[] usbRegexs = cm.getTetherableUsbRegexs();
String[] wifiRegexs = cm.getTetherableWifiRegexs();
+ String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
+
+ boolean usbAvailable = usbRegexs.length != 0;
+ boolean wifiAvailable = wifiRegexs.length != 0;
+ boolean bluetoothAvailable = bluetoothRegexs.length != 0;
+
Preference p = findPreference(KEY_TETHER_SETTINGS);
- if (wifiRegexs.length == 0) {
+ if (wifiAvailable && usbAvailable && bluetoothAvailable) {
+ p.setTitle(R.string.tether_settings_title_all);
+ p.setSummary(R.string.tether_settings_summary_all);
+ } else if (wifiAvailable && usbAvailable) {
+ p.setTitle(R.string.tether_settings_title_all);
+ p.setSummary(R.string.tether_settings_summary_usb_wifi);
+ } else if (wifiAvailable && bluetoothAvailable) {
+ p.setTitle(R.string.tether_settings_title_all);
+ p.setSummary(R.string.tether_settings_summary_wifi_bluetooth);
+ } else if (wifiAvailable) {
+ p.setTitle(R.string.tether_settings_title_wifi);
+ p.setSummary(R.string.tether_settings_summary_wifi);
+ } else if (usbAvailable && bluetoothAvailable) {
+ p.setTitle(R.string.tether_settings_title_usb_bluetooth);
+ p.setSummary(R.string.tether_settings_summary_usb_bluetooth);
+ } else if (usbAvailable) {
p.setTitle(R.string.tether_settings_title_usb);
p.setSummary(R.string.tether_settings_summary_usb);
} else {
- if (usbRegexs.length == 0) {
- p.setTitle(R.string.tether_settings_title_wifi);
- p.setSummary(R.string.tether_settings_summary_wifi);
- } else {
- p.setTitle(R.string.tether_settings_title_both);
- p.setSummary(R.string.tether_settings_summary_both);
- }
+ p.setTitle(R.string.tether_settings_title_bluetooth);
+ p.setSummary(R.string.tether_settings_summary_bluetooth);
}
}
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
-
+
mAirplaneModeEnabler.resume();
mWifiEnabler.resume();
mBtEnabler.resume();
}
-
+
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
-
+
mAirplaneModeEnabler.pause();
mWifiEnabler.pause();
mBtEnabler.pause();
}
-
+
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_EXIT_ECM) {
Boolean isChoiceYes = data.getBooleanExtra(EXIT_ECM_RESULT, false);
// Set Airplane mode based on the return value and checkbox state
diff --git a/src/com/android/settings/ZoneList.java b/src/com/android/settings/ZoneList.java
deleted file mode 100644
index aaaf98949..000000000
--- a/src/com/android/settings/ZoneList.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings;
-
-import android.app.AlarmManager;
-import android.app.ListActivity;
-import android.content.Context;
-import android.content.res.XmlResourceParser;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.SimpleAdapter;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-
-/**
- * This activity displays a list of time zones that match a filter string
- * such as "Africa", "Europe", etc. Choosing an item from the list will set
- * the time zone. Pressing Back without choosing from the list will not
- * result in a change in the time zone setting.
- */
-public class ZoneList extends ListActivity {
-
- private static final String TAG = "ZoneList";
- private static final String KEY_ID = "id";
- private static final String KEY_DISPLAYNAME = "name";
- private static final String KEY_GMT = "gmt";
- private static final String KEY_OFFSET = "offset";
- private static final String XMLTAG_TIMEZONE = "timezone";
-
- private static final int HOURS_1 = 60 * 60000;
- private static final int HOURS_24 = 24 * HOURS_1;
- private static final int HOURS_HALF = HOURS_1 / 2;
-
- private static final int MENU_TIMEZONE = Menu.FIRST+1;
- private static final int MENU_ALPHABETICAL = Menu.FIRST;
-
- // Initial focus position
- private int mDefault;
-
- private boolean mSortedByTimezone;
-
- private SimpleAdapter mTimezoneSortedAdapter;
- private SimpleAdapter mAlphabeticalAdapter;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT};
- int[] to = new int[] {android.R.id.text1, android.R.id.text2};
-
- MyComparator comparator = new MyComparator(KEY_OFFSET);
-
- List<HashMap> timezoneSortedList = getZones();
- Collections.sort(timezoneSortedList, comparator);
- mTimezoneSortedAdapter = new SimpleAdapter(this,
- (List) timezoneSortedList,
- android.R.layout.simple_list_item_2,
- from,
- to);
-
- List<HashMap> alphabeticalList = new ArrayList<HashMap>(timezoneSortedList);
- comparator.setSortingKey(KEY_DISPLAYNAME);
- Collections.sort(alphabeticalList, comparator);
- mAlphabeticalAdapter = new SimpleAdapter(this,
- (List) alphabeticalList,
- android.R.layout.simple_list_item_2,
- from,
- to);
-
- // Sets the adapter
- setSorting(true);
-
- // If current timezone is in this list, move focus to it
- setSelection(mDefault);
-
- // Assume user may press Back
- setResult(RESULT_CANCELED);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically)
- .setIcon(android.R.drawable.ic_menu_sort_alphabetically);
- menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone)
- .setIcon(R.drawable.ic_menu_3d_globe);
-
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
-
- if (mSortedByTimezone) {
- menu.findItem(MENU_TIMEZONE).setVisible(false);
- menu.findItem(MENU_ALPHABETICAL).setVisible(true);
- } else {
- menu.findItem(MENU_TIMEZONE).setVisible(true);
- menu.findItem(MENU_ALPHABETICAL).setVisible(false);
- }
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case MENU_TIMEZONE:
- setSorting(true);
- return true;
-
- case MENU_ALPHABETICAL:
- setSorting(false);
- return true;
-
- default:
- return false;
- }
- }
-
- private void setSorting(boolean timezone) {
- setListAdapter(timezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter);
- mSortedByTimezone = timezone;
- }
-
- private List<HashMap> getZones() {
- List<HashMap> myData = new ArrayList<HashMap>();
- long date = Calendar.getInstance().getTimeInMillis();
- try {
- XmlResourceParser xrp = getResources().getXml(R.xml.timezones);
- while (xrp.next() != XmlResourceParser.START_TAG)
- continue;
- xrp.next();
- while (xrp.getEventType() != XmlResourceParser.END_TAG) {
- while (xrp.getEventType() != XmlResourceParser.START_TAG) {
- if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) {
- return myData;
- }
- xrp.next();
- }
- if (xrp.getName().equals(XMLTAG_TIMEZONE)) {
- String id = xrp.getAttributeValue(0);
- String displayName = xrp.nextText();
- addItem(myData, id, displayName, date);
- }
- while (xrp.getEventType() != XmlResourceParser.END_TAG) {
- xrp.next();
- }
- xrp.next();
- }
- xrp.close();
- } catch (XmlPullParserException xppe) {
- Log.e(TAG, "Ill-formatted timezones.xml file");
- } catch (java.io.IOException ioe) {
- Log.e(TAG, "Unable to read timezones.xml file");
- }
-
- return myData;
- }
-
- protected void addItem(List<HashMap> myData, String id, String displayName,
- long date) {
- HashMap map = new HashMap();
- map.put(KEY_ID, id);
- map.put(KEY_DISPLAYNAME, displayName);
- TimeZone tz = TimeZone.getTimeZone(id);
- int offset = tz.getOffset(date);
- int p = Math.abs(offset);
- StringBuilder name = new StringBuilder();
- name.append("GMT");
-
- if (offset < 0) {
- name.append('-');
- } else {
- name.append('+');
- }
-
- name.append(p / (HOURS_1));
- name.append(':');
-
- int min = p / 60000;
- min %= 60;
-
- if (min < 10) {
- name.append('0');
- }
- name.append(min);
-
- map.put(KEY_GMT, name.toString());
- map.put(KEY_OFFSET, offset);
-
- if (id.equals(TimeZone.getDefault().getID())) {
- mDefault = myData.size();
- }
-
- myData.add(map);
- }
-
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- Map map = (Map) l.getItemAtPosition(position);
- // Update the system timezone value
- AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
- alarm.setTimeZone((String) map.get(KEY_ID));
- setResult(RESULT_OK);
- finish();
- }
-
- private static class MyComparator implements Comparator<HashMap> {
- private String mSortingKey;
-
- public MyComparator(String sortingKey) {
- mSortingKey = sortingKey;
- }
-
- public void setSortingKey(String sortingKey) {
- mSortingKey = sortingKey;
- }
-
- public int compare(HashMap map1, HashMap map2) {
- Object value1 = map1.get(mSortingKey);
- Object value2 = map2.get(mSortingKey);
-
- /*
- * This should never happen, but just in-case, put non-comparable
- * items at the end.
- */
- if (!isComparable(value1)) {
- return isComparable(value2) ? 1 : 0;
- } else if (!isComparable(value2)) {
- return -1;
- }
-
- return ((Comparable) value1).compareTo(value2);
- }
-
- private boolean isComparable(Object value) {
- return (value != null) && (value instanceof Comparable);
- }
- }
-
-}
diff --git a/src/com/android/settings/ZonePicker.java b/src/com/android/settings/ZonePicker.java
index def5036ae..f0c61edc8 100644
--- a/src/com/android/settings/ZonePicker.java
+++ b/src/com/android/settings/ZonePicker.java
@@ -16,55 +16,265 @@
package com.android.settings;
-import android.app.ListActivity;
-import android.content.Intent;
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.ListFragment;
+import android.content.Context;
+import android.content.res.XmlResourceParser;
import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
-import android.widget.ArrayAdapter;
import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * The class displaying a list of time zones that match a filter string
+ * such as "Africa", "Europe", etc. Choosing an item from the list will set
+ * the time zone. Pressing Back without choosing from the list will not
+ * result in a change in the time zone setting.
+ */
+public class ZonePicker extends ListFragment {
+ private static final String TAG = "ZonePicker";
+
+ public static interface ZoneSelectionListener {
+ // You can add any argument if you really need it...
+ public void onZoneSelected(TimeZone tz);
+ }
+
+ private static final String KEY_ID = "id";
+ private static final String KEY_DISPLAYNAME = "name";
+ private static final String KEY_GMT = "gmt";
+ private static final String KEY_OFFSET = "offset";
+ private static final String XMLTAG_TIMEZONE = "timezone";
+
+ private static final int HOURS_1 = 60 * 60000;
+
+ private static final int MENU_TIMEZONE = Menu.FIRST+1;
+ private static final int MENU_ALPHABETICAL = Menu.FIRST;
+
+ // Initial focus position
+ private int mDefault;
+
+ private boolean mSortedByTimezone;
+
+ private SimpleAdapter mTimezoneSortedAdapter;
+ private SimpleAdapter mAlphabeticalAdapter;
+
+ private ZoneSelectionListener mListener;
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanseState) {
+ super.onActivityCreated(savedInstanseState);
+
+ final String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT};
+ final int[] to = new int[] {android.R.id.text1, android.R.id.text2};
-public class ZonePicker extends ListActivity {
+ MyComparator comparator = new MyComparator(KEY_OFFSET);
+
+ Activity activity = getActivity();
+ List<HashMap> timezoneSortedList = getZones();
+ Collections.sort(timezoneSortedList, comparator);
+ mTimezoneSortedAdapter = new SimpleAdapter(activity,
+ (List) timezoneSortedList,
+ android.R.layout.simple_list_item_2,
+ from,
+ to);
+
+ List<HashMap> alphabeticalList = new ArrayList<HashMap>(timezoneSortedList);
+ comparator.setSortingKey(KEY_DISPLAYNAME);
+ Collections.sort(alphabeticalList, comparator);
+ mAlphabeticalAdapter = new SimpleAdapter(getActivity(),
+ (List) alphabeticalList,
+ android.R.layout.simple_list_item_2,
+ from,
+ to);
+
+ // Sets the adapter
+ setSorting(true);
+
+ // If current timezone is in this list, move focus to it
+ setSelection(mDefault);
+ }
- private ArrayAdapter<CharSequence> mFilterAdapter;
-
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- mFilterAdapter = ArrayAdapter.createFromResource(this,
- R.array.timezone_filters, android.R.layout.simple_list_item_1);
- setListAdapter(mFilterAdapter);
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically)
+ .setIcon(android.R.drawable.ic_menu_sort_alphabetically);
+ menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone)
+ .setIcon(R.drawable.ic_menu_3d_globe);
+ super.onCreateOptionsMenu(menu, inflater);
}
-
- protected void addItem(List<Map> data, String name, String zone) {
- HashMap temp = new HashMap();
- temp.put("title", name);
- temp.put("zone", zone);
- data.add(temp);
+
+ @Override
+ public void onPrepareOptionsMenu(Menu menu) {
+ if (mSortedByTimezone) {
+ menu.findItem(MENU_TIMEZONE).setVisible(false);
+ menu.findItem(MENU_ALPHABETICAL).setVisible(true);
+ } else {
+ menu.findItem(MENU_TIMEZONE).setVisible(true);
+ menu.findItem(MENU_ALPHABETICAL).setVisible(false);
+ }
}
@Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- String filter = (String) mFilterAdapter.getItem(position);
- // If All is chosen, reset the filter
- if (filter.equals("All")) {
- filter = null;
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+
+ case MENU_TIMEZONE:
+ setSorting(true);
+ return true;
+
+ case MENU_ALPHABETICAL:
+ setSorting(false);
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ public void setZoneSelectionListener(ZoneSelectionListener listener) {
+ mListener = listener;
+ }
+
+ private void setSorting(boolean timezone) {
+ setListAdapter(timezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter);
+ mSortedByTimezone = timezone;
+ }
+
+ private List<HashMap> getZones() {
+ List<HashMap> myData = new ArrayList<HashMap>();
+ long date = Calendar.getInstance().getTimeInMillis();
+ try {
+ XmlResourceParser xrp = getActivity().getResources().getXml(R.xml.timezones);
+ while (xrp.next() != XmlResourceParser.START_TAG)
+ continue;
+ xrp.next();
+ while (xrp.getEventType() != XmlResourceParser.END_TAG) {
+ while (xrp.getEventType() != XmlResourceParser.START_TAG) {
+ if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) {
+ return myData;
+ }
+ xrp.next();
+ }
+ if (xrp.getName().equals(XMLTAG_TIMEZONE)) {
+ String id = xrp.getAttributeValue(0);
+ String displayName = xrp.nextText();
+ addItem(myData, id, displayName, date);
+ }
+ while (xrp.getEventType() != XmlResourceParser.END_TAG) {
+ xrp.next();
+ }
+ xrp.next();
+ }
+ xrp.close();
+ } catch (XmlPullParserException xppe) {
+ Log.e(TAG, "Ill-formatted timezones.xml file");
+ } catch (java.io.IOException ioe) {
+ Log.e(TAG, "Unable to read timezones.xml file");
+ }
+
+ return myData;
+ }
+
+ protected void addItem(List<HashMap> myData, String id, String displayName,
+ long date) {
+ HashMap map = new HashMap();
+ map.put(KEY_ID, id);
+ map.put(KEY_DISPLAYNAME, displayName);
+ TimeZone tz = TimeZone.getTimeZone(id);
+ int offset = tz.getOffset(date);
+ int p = Math.abs(offset);
+ StringBuilder name = new StringBuilder();
+ name.append("GMT");
+
+ if (offset < 0) {
+ name.append('-');
+ } else {
+ name.append('+');
+ }
+
+ name.append(p / (HOURS_1));
+ name.append(':');
+
+ int min = p / 60000;
+ min %= 60;
+
+ if (min < 10) {
+ name.append('0');
+ }
+ name.append(min);
+
+ map.put(KEY_GMT, name.toString());
+ map.put(KEY_OFFSET, offset);
+
+ if (id.equals(TimeZone.getDefault().getID())) {
+ mDefault = myData.size();
}
- Intent zoneList = new Intent();
- zoneList.setClass(this, ZoneList.class);
- zoneList.putExtra("filter", filter);
-
- startActivityForResult(zoneList, 0);
+
+ myData.add(map);
}
-
+
@Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // If subactivity has resulted in a timezone selection, close this act.
- if (resultCode == RESULT_OK) {
- finish();
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ Map map = (Map) l.getItemAtPosition(position);
+ // Update the system timezone value
+ final Activity activity = getActivity();
+ AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
+ String tzId = (String) map.get(KEY_ID);
+ alarm.setTimeZone(tzId);
+ final TimeZone tz = TimeZone.getTimeZone(tzId);
+ if (mListener != null) {
+ mListener.onZoneSelected(tz);
+ } else {
+ getActivity().onBackPressed();
+ }
+ }
+
+ private static class MyComparator implements Comparator<HashMap> {
+ private String mSortingKey;
+
+ public MyComparator(String sortingKey) {
+ mSortingKey = sortingKey;
+ }
+
+ public void setSortingKey(String sortingKey) {
+ mSortingKey = sortingKey;
}
- }
+
+ public int compare(HashMap map1, HashMap map2) {
+ Object value1 = map1.get(mSortingKey);
+ Object value2 = map2.get(mSortingKey);
+
+ /*
+ * This should never happen, but just in-case, put non-comparable
+ * items at the end.
+ */
+ if (!isComparable(value1)) {
+ return isComparable(value2) ? 1 : 0;
+ } else if (!isComparable(value2)) {
+ return -1;
+ }
+
+ return ((Comparable) value1).compareTo(value2);
+ }
+
+ private boolean isComparable(Object value) {
+ return (value != null) && (value instanceof Comparable);
+ }
+ }
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index 5b0218fd8..f0b1705b3 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -34,6 +34,7 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
private static int sDimAlpha = Integer.MIN_VALUE;
private CachedBluetoothDevice mCachedDevice;
+ private int mAccessibleProfile;
/**
* Cached local copy of whether the device is busy. This is only updated
@@ -41,7 +42,8 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
*/
private boolean mIsBusy;
- public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice) {
+ public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice,
+ int accessibleProfile) {
super(context);
if (sDimAlpha == Integer.MIN_VALUE) {
@@ -51,6 +53,7 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
}
mCachedDevice = cachedDevice;
+ mAccessibleProfile = accessibleProfile;
setLayoutResource(R.layout.preference_bluetooth);
@@ -83,7 +86,7 @@ public class BluetoothDevicePreference extends Preference implements CachedBluet
* related to BluetoothHeadset not bound to the actual
* BluetoothHeadsetService when we got here.
*/
- setSummary(mCachedDevice.getSummary());
+ setSummary(mCachedDevice.getSummary(mAccessibleProfile));
// Used to gray out the item
mIsBusy = mCachedDevice.isBusy();
diff --git a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
index 4d124b33e..08354310a 100644
--- a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
+++ b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
@@ -24,6 +24,8 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothInputDevice;
+import android.bluetooth.BluetoothPan;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -119,6 +121,31 @@ public class BluetoothEventRedirector {
mManager.getCachedDeviceManager().onProfileStateChanged(device,
Profile.A2DP, newState);
+ } else if (action.equals(BluetoothInputDevice.ACTION_INPUT_DEVICE_STATE_CHANGED)) {
+ final int newState = intent.getIntExtra(
+ BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
+ final int oldState = intent.getIntExtra(
+ BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0);
+ if (newState == BluetoothInputDevice.STATE_DISCONNECTED &&
+ oldState == BluetoothInputDevice.STATE_CONNECTING) {
+ Log.i(TAG, "Failed to connect BT HID");
+ }
+
+ mManager.getCachedDeviceManager().onProfileStateChanged(device,
+ Profile.HID, newState);
+
+ } else if (action.equals(BluetoothPan.ACTION_PAN_STATE_CHANGED)) {
+ final int newState = intent.getIntExtra(
+ BluetoothPan.EXTRA_PAN_STATE, 0);
+ final int oldState = intent.getIntExtra(
+ BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, 0);
+ if (newState == BluetoothPan.STATE_DISCONNECTED &&
+ oldState == BluetoothPan.STATE_CONNECTING) {
+ Log.i(TAG, "Failed to connect BT PAN");
+ }
+ mManager.getCachedDeviceManager().onProfileStateChanged(device,
+ Profile.PAN, newState);
+
} else if (action.equals(BluetoothDevice.ACTION_CLASS_CHANGED)) {
mManager.getCachedDeviceManager().onBtClassChanged(device);
@@ -166,6 +193,7 @@ public class BluetoothEventRedirector {
// Fine-grained state broadcasts
filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
+ filter.addAction(BluetoothPan.ACTION_PAN_STATE_CHANGED);
filter.addAction(BluetoothDevice.ACTION_CLASS_CHANGED);
filter.addAction(BluetoothDevice.ACTION_UUID);
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index 78c531ce3..88d1e83b4 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -18,26 +18,34 @@ package com.android.settings.bluetooth;
import com.android.settings.ProgressCategory;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.UserLeaveHintListener;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+import android.app.Activity;
+import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevicePicker;
+import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothUuid;
import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.Log;
import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuItem;
import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView.AdapterContextMenuInfo;
import java.util.List;
@@ -47,8 +55,8 @@ import java.util.WeakHashMap;
* BluetoothSettings is the Settings screen for Bluetooth configuration and
* connection management.
*/
-public class BluetoothSettings extends PreferenceActivity
- implements LocalBluetoothManager.Callback {
+public class BluetoothSettings extends SettingsPreferenceFragment
+ implements LocalBluetoothManager.Callback, UserLeaveHintListener {
private static final String TAG = "BluetoothSettings";
@@ -60,6 +68,11 @@ public class BluetoothSettings extends PreferenceActivity
private static final int SCREEN_TYPE_SETTINGS = 0;
private static final int SCREEN_TYPE_DEVICEPICKER = 1;
+ private static final int SCREEN_TYPE_TETHERING = 2;
+
+ public static final String ACTION = "bluetooth_action";
+ public static final String ACTION_LAUNCH_TETHER_PICKER =
+ "com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER";
private int mScreenType;
private int mFilterType;
@@ -88,16 +101,19 @@ public class BluetoothSettings extends PreferenceActivity
if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
onBluetoothStateChanged(mLocalManager.getBluetoothState());
- } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
- && mScreenType == SCREEN_TYPE_DEVICEPICKER) {
+ } else if (intent.getAction().equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
int bondState = intent
.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
if (bondState == BluetoothDevice.BOND_BONDED) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.equals(mSelectedDevice)) {
- sendDevicePickedIntent(device);
- finish();
+ if (mScreenType == SCREEN_TYPE_DEVICEPICKER) {
+ sendDevicePickedIntent(device);
+ finish();
+ } else if (mScreenType == SCREEN_TYPE_TETHERING) {
+ onPanDevicePicked();
+ }
}
}
}
@@ -105,11 +121,19 @@ public class BluetoothSettings extends PreferenceActivity
};
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ // We delay calling super.onActivityCreated(). See WifiSettings.java for more info.
- mLocalManager = LocalBluetoothManager.getInstance(this);
- if (mLocalManager == null) finish();
+ final Activity activity = getActivity();
+ mLocalManager = LocalBluetoothManager.getInstance(activity);
+ if (mLocalManager == null) {
+ finish();
+ }
// Note:
// If an application wish to show the BT device list, it can send an
@@ -121,8 +145,13 @@ public class BluetoothSettings extends PreferenceActivity
// -DEVICE_PICKER_NEED_AUTH: to show if bonding procedure needed.
mFilterType = BluetoothDevicePicker.FILTER_TYPE_ALL;
- Intent intent = getIntent();
- String action = intent.getAction();
+ final Intent intent = activity.getIntent();
+
+ // This additional argument comes from PreferenceScreen (See TetherSettings.java).
+ String action = getArguments().getString(ACTION);
+ if (TextUtils.isEmpty(action)) {
+ action = intent.getAction();
+ }
if (action.equals(BluetoothDevicePicker.ACTION_LAUNCH)) {
mScreenType = SCREEN_TYPE_DEVICEPICKER;
@@ -132,17 +161,23 @@ public class BluetoothSettings extends PreferenceActivity
mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
- setTitle(getString(R.string.device_picker));
+ activity.setTitle(activity.getString(R.string.device_picker));
+ addPreferencesFromResource(R.xml.device_picker);
+ } else if (action.equals(ACTION_LAUNCH_TETHER_PICKER)){
+ mScreenType = SCREEN_TYPE_TETHERING;
+ mFilterType = BluetoothDevicePicker.FILTER_TYPE_PANU;
+
+ activity.setTitle(activity.getString(R.string.device_picker));
addPreferencesFromResource(R.xml.device_picker);
} else {
addPreferencesFromResource(R.xml.bluetooth_settings);
mEnabler = new BluetoothEnabler(
- this,
+ activity,
(CheckBoxPreference) findPreference(KEY_BT_CHECKBOX));
mDiscoverableEnabler = new BluetoothDiscoverableEnabler(
- this,
+ activity,
(CheckBoxPreference) findPreference(KEY_BT_DISCOVERABLE));
mNamePreference = (BluetoothNamePreference) findPreference(KEY_BT_NAME);
@@ -153,10 +188,12 @@ public class BluetoothSettings extends PreferenceActivity
mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
registerForContextMenu(getListView());
+
+ super.onActivityCreated(savedInstanceState);
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
// Repopulate (which isn't too bad since it's cached in the settings
@@ -179,18 +216,17 @@ public class BluetoothSettings extends PreferenceActivity
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- registerReceiver(mReceiver, intentFilter);
- mLocalManager.setForegroundActivity(this);
+ getActivity().registerReceiver(mReceiver, intentFilter);
+ mLocalManager.setForegroundActivity(getActivity());
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
-
mLocalManager.setForegroundActivity(null);
mDevicePreferenceMap.clear();
mDeviceList.removeAll();
- unregisterReceiver(mReceiver);
+ getActivity().unregisterReceiver(mReceiver);
mLocalManager.unregisterCallback(this);
if (mScreenType == SCREEN_TYPE_SETTINGS) {
@@ -201,8 +237,7 @@ public class BluetoothSettings extends PreferenceActivity
}
@Override
- protected void onUserLeaveHint() {
- super.onUserLeaveHint();
+ public void onUserLeaveHint() {
mLocalManager.stopScanning();
}
@@ -240,6 +275,18 @@ public class BluetoothSettings extends PreferenceActivity
} else {
btPreference.getCachedDevice().onClicked();
}
+ } else if (mScreenType == SCREEN_TYPE_TETHERING){
+ CachedBluetoothDevice device = btPreference.getCachedDevice();
+
+ mSelectedDevice = device.getDevice();
+ mLocalManager.stopScanning();
+ mLocalManager.persistSelectedDeviceInPicker(mSelectedDevice.getAddress());
+ if ((device.getBondState() == BluetoothDevice.BOND_BONDED)) {
+ onPanDevicePicked();
+ // don't call finish so that users can see it connecting
+ } else {
+ btPreference.getCachedDevice().onClicked();
+ }
}
return true;
}
@@ -301,13 +348,14 @@ public class BluetoothSettings extends PreferenceActivity
switch(mFilterType) {
case BluetoothDevicePicker.FILTER_TYPE_TRANSFER:
- if (uuids != null)
+ if (uuids != null) {
if (BluetoothUuid.containsAnyUuid(uuids,
LocalBluetoothProfileManager.OPP_PROFILE_UUIDS)) return true;
- if (bluetoothClass != null
- && bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_OPP)) {
- return true;
- }
+ }
+ if (bluetoothClass != null
+ && bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_OPP)) {
+ return true;
+ }
break;
case BluetoothDevicePicker.FILTER_TYPE_AUDIO:
if (uuids != null) {
@@ -322,6 +370,27 @@ public class BluetoothSettings extends PreferenceActivity
if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) return true;
}
break;
+ case BluetoothDevicePicker.FILTER_TYPE_PANU:
+ if (uuids != null) {
+ if (BluetoothUuid.containsAnyUuid(uuids,
+ LocalBluetoothProfileManager.PANU_PROFILE_UUIDS)) return true;
+
+ }
+ if (bluetoothClass != null
+ && bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_PANU)) {
+ return true;
+ }
+ break;
+ case BluetoothDevicePicker.FILTER_TYPE_NAP:
+ if (uuids != null) {
+ if (BluetoothUuid.containsAnyUuid(uuids,
+ LocalBluetoothProfileManager.NAP_PROFILE_UUIDS)) return true;
+ }
+ if (bluetoothClass != null
+ && bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_NAP)) {
+ return true;
+ }
+ break;
default:
return true;
}
@@ -329,7 +398,14 @@ public class BluetoothSettings extends PreferenceActivity
}
private void createDevicePreference(CachedBluetoothDevice cachedDevice) {
- BluetoothDevicePreference preference = new BluetoothDevicePreference(this, cachedDevice);
+ BluetoothDevicePreference preference;
+ if (mScreenType == SCREEN_TYPE_TETHERING) {
+ preference = new BluetoothDevicePreference(
+ getActivity(), cachedDevice, CachedBluetoothDevice.PAN_PROFILE);
+ } else {
+ preference = new BluetoothDevicePreference(
+ getActivity(), cachedDevice, CachedBluetoothDevice.OTHER_PROFILES);
+ }
mDeviceList.addPreference(preference);
mDevicePreferenceMap.put(cachedDevice, preference);
}
@@ -355,12 +431,53 @@ public class BluetoothSettings extends PreferenceActivity
}
}
+ private void onPanDevicePicked() {
+ final Activity activity = getActivity();
+ final LocalBluetoothProfileManager profileManager =
+ LocalBluetoothProfileManager.getProfileManager(mLocalManager, Profile.PAN);
+ int status = profileManager.getConnectionStatus(mSelectedDevice);
+ if (SettingsBtStatus.isConnectionStatusConnected(status)) {
+ String name = mSelectedDevice.getName();
+ if (TextUtils.isEmpty(name)) {
+ name = activity.getString(R.string.bluetooth_device);
+ }
+ String message = activity.getString(R.string.bluetooth_untether_blank, name);
+ DialogInterface.OnClickListener disconnectListener =
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ profileManager.disconnect(mSelectedDevice);
+ }
+ };
+ new AlertDialog.Builder(activity)
+ .setTitle(name)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok, disconnectListener)
+ .setNegativeButton(android.R.string.cancel, null)
+ .create()
+ .show();
+ } else if (status == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) {
+ if (profileManager.getConnectedDevices().size() >= BluetoothPan.MAX_CONNECTIONS) {
+ new AlertDialog.Builder(activity)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(R.string.bluetooth_error_title)
+ .setMessage(activity.getString(R.string.bluetooth_tethering_overflow_error,
+ BluetoothPan.MAX_CONNECTIONS))
+ .setNegativeButton(android.R.string.ok, null)
+ .create()
+ .show();
+ return;
+ }
+ profileManager.connect(mSelectedDevice);
+ }
+ }
+
private void sendDevicePickedIntent(BluetoothDevice device) {
Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
- if (mLaunchPackage != null && mLaunchClass != null) {
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ if (mScreenType == SCREEN_TYPE_DEVICEPICKER &&
+ mLaunchPackage != null && mLaunchClass != null) {
intent.setClassName(mLaunchPackage, mLaunchClass);
}
- intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- sendBroadcast(intent);
+ getActivity().sendBroadcast(intent);
}
}
diff --git a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
index d778f1128..53e599d25 100644
--- a/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
+++ b/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
@@ -56,6 +56,9 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
private static final int CONTEXT_ITEM_UNPAIR = Menu.FIRST + 3;
private static final int CONTEXT_ITEM_CONNECT_ADVANCED = Menu.FIRST + 4;
+ public static final int PAN_PROFILE = 1;
+ public static final int OTHER_PROFILES = 2;
+
private final BluetoothDevice mDevice;
private String mName;
private short mRssi;
@@ -565,6 +568,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
Log.v(TAG, "opp classbits != uuid");
printUuids = true;
}
+
+ if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HID) !=
+ mProfiles.contains(Profile.HID)) {
+ Log.v(TAG, "hid classbits != uuid");
+ printUuids = true;
+ }
}
if (printUuids) {
@@ -635,9 +644,9 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
}
- public int getSummary() {
+ public int getSummary(int accessibleProfile) {
// TODO: clean up
- int oneOffSummary = getOneOffSummary();
+ int oneOffSummary = getOneOffSummary(accessibleProfile);
if (oneOffSummary != 0) {
return oneOffSummary;
}
@@ -663,23 +672,43 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
*
* @return A one-off summary that is applicable for the current state, or 0.
*/
- private int getOneOffSummary() {
- boolean isA2dpConnected = false, isHeadsetConnected = false, isConnecting = false;
+ private int getOneOffSummary(int accessibleProfile) {
+ boolean isA2dpConnected = false;
+ boolean isHeadsetConnected = false;
+ boolean isHidConnected = false;
+ boolean isPanConnected = false;
+ boolean isConnecting = false;
+
+ if (accessibleProfile == OTHER_PROFILES) {
+ if (mProfiles.contains(Profile.A2DP)) {
+ LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
+ .getProfileManager(mLocalManager, Profile.A2DP);
+ isConnecting = profileManager.getConnectionStatus(mDevice) ==
+ SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ isA2dpConnected = profileManager.isConnected(mDevice);
+ }
- if (mProfiles.contains(Profile.A2DP)) {
- LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
- .getProfileManager(mLocalManager, Profile.A2DP);
- isConnecting = profileManager.getConnectionStatus(mDevice) ==
- SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
- isA2dpConnected = profileManager.isConnected(mDevice);
- }
+ if (mProfiles.contains(Profile.HEADSET)) {
+ LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
+ .getProfileManager(mLocalManager, Profile.HEADSET);
+ isConnecting |= profileManager.getConnectionStatus(mDevice) ==
+ SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ isHeadsetConnected = profileManager.isConnected(mDevice);
+ }
- if (mProfiles.contains(Profile.HEADSET)) {
+ if (mProfiles.contains(Profile.HID)) {
+ LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
+ .getProfileManager(mLocalManager, Profile.HID);
+ isConnecting |= profileManager.getConnectionStatus(mDevice) ==
+ SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ isHidConnected = profileManager.isConnected(mDevice);
+ }
+ } else if (accessibleProfile == PAN_PROFILE && mProfiles.contains(Profile.PAN)) {
LocalBluetoothProfileManager profileManager = LocalBluetoothProfileManager
- .getProfileManager(mLocalManager, Profile.HEADSET);
+ .getProfileManager(mLocalManager, Profile.PAN);
isConnecting |= profileManager.getConnectionStatus(mDevice) ==
SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
- isHeadsetConnected = profileManager.isConnected(mDevice);
+ isPanConnected = profileManager.isConnected(mDevice);
}
if (isConnecting) {
@@ -692,6 +721,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
return R.string.bluetooth_summary_connected_to_a2dp;
} else if (isHeadsetConnected) {
return R.string.bluetooth_summary_connected_to_headset;
+ } else if (isHidConnected) {
+ return R.string.bluetooth_summary_connected_to_hid;
+ } else if (isPanConnected) {
+ return R.string.bluetooth_summary_connected_to_pan;
} else {
return 0;
}
@@ -708,7 +741,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
}
private boolean isConnectableProfile(Profile profile) {
- return profile.equals(Profile.HEADSET) || profile.equals(Profile.A2DP);
+ return profile.equals(Profile.HEADSET) || profile.equals(Profile.A2DP) ||
+ profile.equals(Profile.HID);
}
public void onCreateContextMenu(ContextMenu menu) {
diff --git a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
index ed9a97411..ac2b4d81a 100644
--- a/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
+++ b/src/com/android/settings/bluetooth/ConnectSpecificProfilesActivity.java
@@ -232,7 +232,8 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
* If the device is online, show status. Otherwise, show a summary that
* describes what the checkbox does.
*/
- mOnlineModePreference.setSummary(mOnlineMode ? mCachedDevice.getSummary()
+ mOnlineModePreference.setSummary(mOnlineMode ?
+ mCachedDevice.getSummary(CachedBluetoothDevice.OTHER_PROFILES)
: R.string.bluetooth_device_advanced_online_mode_summary);
}
@@ -299,6 +300,8 @@ public class ConnectSpecificProfilesActivity extends PreferenceActivity
return R.string.bluetooth_a2dp_profile_summary_use_for;
case HEADSET:
return R.string.bluetooth_headset_profile_summary_use_for;
+ case HID:
+ return R.string.bluetooth_hid_profile_summary_use_for;
default:
return 0;
}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
index 01714fe60..6193a4e87 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java
@@ -21,6 +21,8 @@ import com.android.settings.R;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothInputDevice;
+import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothUuid;
import android.os.Handler;
import android.os.ParcelUuid;
@@ -55,6 +57,18 @@ public abstract class LocalBluetoothProfileManager {
BluetoothUuid.ObexObjectPush
};
+ /* package */ static final ParcelUuid[] HID_PROFILE_UUIDS = new ParcelUuid[] {
+ BluetoothUuid.Hid
+ };
+
+ /* package */ static final ParcelUuid[] PANU_PROFILE_UUIDS = new ParcelUuid[] {
+ BluetoothUuid.PANU
+ };
+
+ /* package */ static final ParcelUuid[] NAP_PROFILE_UUIDS = new ParcelUuid[] {
+ BluetoothUuid.NAP
+ };
+
/**
* An interface for notifying BluetoothHeadset IPC clients when they have
* been connected to the BluetoothHeadset service.
@@ -97,6 +111,12 @@ public abstract class LocalBluetoothProfileManager {
profileManager = new OppProfileManager(localManager);
sProfileMap.put(Profile.OPP, profileManager);
+
+ profileManager = new HidProfileManager(localManager);
+ sProfileMap.put(Profile.HID, profileManager);
+
+ profileManager = new PanProfileManager(localManager);
+ sProfileMap.put(Profile.PAN, profileManager);
}
}
}
@@ -161,6 +181,14 @@ public abstract class LocalBluetoothProfileManager {
if (BluetoothUuid.containsAnyUuid(uuids, OPP_PROFILE_UUIDS)) {
profiles.add(Profile.OPP);
}
+
+ if (BluetoothUuid.containsAnyUuid(uuids, HID_PROFILE_UUIDS)) {
+ profiles.add(Profile.HID);
+ }
+
+ if (BluetoothUuid.containsAnyUuid(uuids, PANU_PROFILE_UUIDS)) {
+ profiles.add(Profile.PAN);
+ }
}
protected LocalBluetoothProfileManager(LocalBluetoothManager localManager) {
@@ -195,7 +223,9 @@ public abstract class LocalBluetoothProfileManager {
public enum Profile {
HEADSET(R.string.bluetooth_profile_headset),
A2DP(R.string.bluetooth_profile_a2dp),
- OPP(R.string.bluetooth_profile_opp);
+ OPP(R.string.bluetooth_profile_opp),
+ HID(R.string.bluetooth_profile_hid),
+ PAN(R.string.bluetooth_profile_pan);
public final int localizedString;
@@ -518,4 +548,162 @@ public abstract class LocalBluetoothProfileManager {
}
}
}
+
+ private static class HidProfileManager extends LocalBluetoothProfileManager {
+ private BluetoothInputDevice mService;
+
+ public HidProfileManager(LocalBluetoothManager localManager) {
+ super(localManager);
+ mService = new BluetoothInputDevice(localManager.getContext());
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device) {
+ return mService.connectInputDevice(device);
+ }
+
+ @Override
+ public int convertState(int hidState) {
+ switch (hidState) {
+ case BluetoothInputDevice.STATE_CONNECTED:
+ return SettingsBtStatus.CONNECTION_STATUS_CONNECTED;
+ case BluetoothInputDevice.STATE_CONNECTING:
+ return SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ case BluetoothInputDevice.STATE_DISCONNECTED:
+ return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED;
+ case BluetoothInputDevice.STATE_DISCONNECTING:
+ return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING;
+ default:
+ return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN;
+ }
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device) {
+ return mService.disconnectInputDevice(device);
+ }
+
+ @Override
+ public Set<BluetoothDevice> getConnectedDevices() {
+ return mService.getConnectedInputDevices();
+ }
+
+ @Override
+ public int getConnectionStatus(BluetoothDevice device) {
+ return convertState(mService.getInputDeviceState(device));
+ }
+
+ @Override
+ public int getPreferred(BluetoothDevice device) {
+ return mService.getInputDevicePriority(device);
+ }
+
+ @Override
+ public int getSummary(BluetoothDevice device) {
+ final int connectionStatus = getConnectionStatus(device);
+
+ if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) {
+ return R.string.bluetooth_hid_profile_summary_connected;
+ } else {
+ return SettingsBtStatus.getConnectionStatusSummary(connectionStatus);
+ }
+ }
+
+ @Override
+ public boolean isPreferred(BluetoothDevice device) {
+ return mService.getInputDevicePriority(device) > BluetoothInputDevice.PRIORITY_OFF;
+ }
+
+ @Override
+ public boolean isProfileReady() {
+ return true;
+ }
+
+ @Override
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (preferred) {
+ if (mService.getInputDevicePriority(device) < BluetoothInputDevice.PRIORITY_ON) {
+ mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON);
+ }
+ } else {
+ mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_OFF);
+ }
+ }
+ }
+
+ private static class PanProfileManager extends LocalBluetoothProfileManager {
+ private BluetoothPan mService;
+
+ public PanProfileManager(LocalBluetoothManager localManager) {
+ super(localManager);
+ mService = new BluetoothPan(localManager.getContext());
+ }
+
+ @Override
+ public boolean connect(BluetoothDevice device) {
+ return mService.connect(device);
+ }
+
+ @Override
+ public int convertState(int panState) {
+ switch (panState) {
+ case BluetoothPan.STATE_CONNECTED:
+ return SettingsBtStatus.CONNECTION_STATUS_CONNECTED;
+ case BluetoothPan.STATE_CONNECTING:
+ return SettingsBtStatus.CONNECTION_STATUS_CONNECTING;
+ case BluetoothPan.STATE_DISCONNECTED:
+ return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED;
+ case BluetoothPan.STATE_DISCONNECTING:
+ return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING;
+ default:
+ return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN;
+ }
+ }
+
+ @Override
+ public boolean disconnect(BluetoothDevice device) {
+ return mService.disconnect(device);
+ }
+
+ @Override
+ public int getSummary(BluetoothDevice device) {
+ final int connectionStatus = getConnectionStatus(device);
+
+ if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) {
+ return R.string.bluetooth_pan_profile_summary_connected;
+ } else {
+ return SettingsBtStatus.getConnectionStatusSummary(connectionStatus);
+ }
+ }
+
+ @Override
+ public boolean isProfileReady() {
+ return true;
+ }
+
+ @Override
+ public Set<BluetoothDevice> getConnectedDevices() {
+ return mService.getConnectedDevices();
+ }
+
+ @Override
+ public int getConnectionStatus(BluetoothDevice device) {
+ return convertState(mService.getPanDeviceState(device));
+ }
+
+ @Override
+ public int getPreferred(BluetoothDevice device) {
+ return -1;
+ }
+
+ @Override
+ public boolean isPreferred(BluetoothDevice device) {
+ return false;
+ }
+
+ @Override
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ return;
+ }
+ }
}
diff --git a/src/com/android/settings/deviceinfo/Memory.java b/src/com/android/settings/deviceinfo/Memory.java
index b57484908..e22c39d62 100644
--- a/src/com/android/settings/deviceinfo/Memory.java
+++ b/src/com/android/settings/deviceinfo/Memory.java
@@ -16,6 +16,9 @@
package com.android.settings.deviceinfo;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -26,35 +29,29 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.DialogInterface.OnCancelListener;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.os.Bundle;
-import android.os.Handler;
+import android.hardware.Usb;
+import android.os.Environment;
import android.os.IBinder;
-import android.os.Message;
import android.os.RemoteException;
-import android.os.Environment;
-import android.os.storage.IMountService;
import android.os.ServiceManager;
import android.os.StatFs;
-import android.os.storage.StorageManager;
+import android.os.storage.IMountService;
import android.os.storage.StorageEventListener;
+import android.os.storage.StorageManager;
+import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
+import android.provider.Settings;
import android.text.format.Formatter;
import android.util.Log;
import android.widget.Toast;
-import com.android.settings.R;
-
import java.io.File;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
-public class Memory extends PreferenceActivity implements OnCancelListener {
+public class Memory extends SettingsPreferenceFragment implements OnCancelListener {
private static final String TAG = "Memory";
private static final boolean localLOGV = false;
@@ -66,6 +63,8 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
private static final String MEMORY_SD_FORMAT = "memory_sd_format";
+ private static final String PTP_MODE_TOGGLE = "ptp_mode_toggle";
+
private static final int DLG_CONFIRM_UNMOUNT = 1;
private static final int DLG_ERROR_UNMOUNT = 2;
@@ -75,6 +74,7 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
private Preference mSdAvail;
private Preference mSdMountToggle;
private Preference mSdFormat;
+ private CheckBoxPreference mPtpModeToggle;
// Access using getMountService()
private IMountService mMountService = null;
@@ -82,7 +82,7 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
private StorageManager mStorageManager = null;
@Override
- protected void onCreate(Bundle icicle) {
+ public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (mStorageManager == null) {
@@ -97,16 +97,26 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
mSdAvail = findPreference(MEMORY_SD_AVAIL);
mSdMountToggle = findPreference(MEMORY_SD_MOUNT_TOGGLE);
mSdFormat = findPreference(MEMORY_SD_FORMAT);
+
+ mPtpModeToggle = (CheckBoxPreference)findPreference(PTP_MODE_TOGGLE);
+ if (Usb.isFunctionSupported(Usb.USB_FUNCTION_MTP)) {
+ mPtpModeToggle.setChecked(Settings.System.getInt(
+ getContentResolver(),
+ Settings.System.USE_PTP_INTERFACE, 0) != 0);
+ } else {
+ // hide the PTP mode toggle checkbox if MTP is not supported
+ getPreferenceScreen().removePreference(mPtpModeToggle);
+ }
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
intentFilter.addDataScheme("file");
- registerReceiver(mReceiver, intentFilter);
+ getActivity().registerReceiver(mReceiver, intentFilter);
updateMemoryStatus();
}
@@ -123,13 +133,13 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
};
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
- unregisterReceiver(mReceiver);
+ getActivity().unregisterReceiver(mReceiver);
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
if (mStorageManager != null && mStorageListener != null) {
mStorageManager.unregisterListener(mStorageListener);
}
@@ -160,11 +170,16 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
return true;
} else if (preference == mSdFormat) {
Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setClass(this, com.android.settings.MediaFormat.class);
+ intent.setClass(getActivity(), com.android.settings.MediaFormat.class);
startActivity(intent);
return true;
+ } else if (preference == mPtpModeToggle) {
+ Settings.System.putInt(getContentResolver(),
+ Settings.System.USE_PTP_INTERFACE,
+ mPtpModeToggle.isChecked() ? 1 : 0);
+ return true;
}
-
+
return false;
}
@@ -176,10 +191,10 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
};
@Override
- public Dialog onCreateDialog(int id, Bundle args) {
+ public Dialog onCreateDialog(int id) {
switch (id) {
case DLG_CONFIRM_UNMOUNT:
- return new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(getActivity())
.setTitle(R.string.dlg_confirm_unmount_title)
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
@@ -190,7 +205,7 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
.setOnCancelListener(this)
.create();
case DLG_ERROR_UNMOUNT:
- return new AlertDialog.Builder(this )
+ return new AlertDialog.Builder(getActivity())
.setTitle(R.string.dlg_error_unmount_title)
.setNeutralButton(R.string.dlg_ok, null)
.setMessage(R.string.dlg_error_unmount_text)
@@ -202,7 +217,7 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
private void doUnmount(boolean force) {
// Present a toast here
- Toast.makeText(this, R.string.unmount_inform_text, Toast.LENGTH_SHORT).show();
+ Toast.makeText(getActivity(), R.string.unmount_inform_text, Toast.LENGTH_SHORT).show();
IMountService mountService = getMountService();
String extStoragePath = Environment.getExternalStorageDirectory().toString();
try {
@@ -225,7 +240,6 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
private boolean hasAppsAccessingStorage() throws RemoteException {
String extStoragePath = Environment.getExternalStorageDirectory().toString();
IMountService mountService = getMountService();
- boolean showPidDialog = false;
int stUsers[] = mountService.getStorageUsers(extStoragePath);
if (stUsers != null && stUsers.length > 0) {
return true;
@@ -325,11 +339,12 @@ public class Memory extends PreferenceActivity implements OnCancelListener {
}
private String formatSize(long size) {
- return Formatter.formatFileSize(this, size);
+ return Formatter.formatFileSize(getActivity(), size);
}
public void onCancel(DialogInterface dialog) {
- finish();
+ // TODO: Is this really required?
+ // finish();
}
}
diff --git a/src/com/android/settings/vpn/VpnEditor.java b/src/com/android/settings/vpn/VpnEditor.java
index 349befbf1..3ab0b909d 100644
--- a/src/com/android/settings/vpn/VpnEditor.java
+++ b/src/com/android/settings/vpn/VpnEditor.java
@@ -17,7 +17,9 @@
package com.android.settings.vpn;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
@@ -27,22 +29,19 @@ import android.net.vpn.L2tpIpsecPskProfile;
import android.net.vpn.L2tpProfile;
import android.net.vpn.PptpProfile;
import android.net.vpn.VpnProfile;
-import android.net.vpn.VpnType;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceGroup;
import android.text.TextUtils;
-import android.view.KeyEvent;
+import android.util.Log;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View;
/**
* The activity class for editing a new or existing VPN profile.
*/
-public class VpnEditor extends PreferenceActivity {
+public class VpnEditor extends SettingsPreferenceFragment {
private static final int MENU_SAVE = Menu.FIRST;
private static final int MENU_CANCEL = Menu.FIRST + 1;
private static final int CONFIRM_DIALOG_ID = 0;
@@ -56,59 +55,75 @@ public class VpnEditor extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- VpnProfile p = (VpnProfile) ((savedInstanceState == null)
- ? getIntent().getParcelableExtra(VpnSettings.KEY_VPN_PROFILE)
- : savedInstanceState.getParcelable(KEY_PROFILE));
- mProfileEditor = getEditor(p);
- mAddingProfile = TextUtils.isEmpty(p.getName());
// Loads the XML preferences file
addPreferencesFromResource(R.xml.vpn_edit);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ VpnProfile p;
+ if (savedInstanceState != null) {
+ p = (VpnProfile)savedInstanceState.getParcelable(KEY_PROFILE);
+ } else {
+ p = (VpnProfile)getArguments().getParcelable(VpnSettings.KEY_VPN_PROFILE);
+ if (p == null) {
+ p = getActivity().getIntent().getParcelableExtra(VpnSettings.KEY_VPN_PROFILE);
+ }
+ }
+
+ mProfileEditor = getEditor(p);
+ mAddingProfile = TextUtils.isEmpty(p.getName());
initViewFor(p);
Parcel parcel = Parcel.obtain();
p.writeToParcel(parcel, 0);
mOriginalProfileData = parcel.marshall();
+
+ registerForContextMenu(getListView());
+ setHasOptionsMenu(true);
}
@Override
- protected synchronized void onSaveInstanceState(Bundle outState) {
+ public synchronized void onSaveInstanceState(Bundle outState) {
if (mProfileEditor == null) return;
outState.putParcelable(KEY_PROFILE, getProfile());
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
menu.add(0, MENU_SAVE, 0, R.string.vpn_menu_done)
.setIcon(android.R.drawable.ic_menu_save);
menu.add(0, MENU_CANCEL, 0,
mAddingProfile ? R.string.vpn_menu_cancel
: R.string.vpn_menu_revert)
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
- return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SAVE:
- if (validateAndSetResult()) finish();
+ if (validateAndSetResult()) finishFragment();
return true;
case MENU_CANCEL:
if (profileChanged()) {
showDialog(CONFIRM_DIALOG_ID);
} else {
- finish();
+ finishFragment();
}
return true;
}
return super.onOptionsItemSelected(item);
}
+ /*
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
@@ -117,7 +132,7 @@ public class VpnEditor extends PreferenceActivity {
return true;
}
return super.onKeyDown(keyCode, event);
- }
+ }*/
private void initViewFor(VpnProfile profile) {
setTitle(profile);
@@ -125,10 +140,11 @@ public class VpnEditor extends PreferenceActivity {
}
private void setTitle(VpnProfile profile) {
+ final Activity activity = getActivity();
String formatString = mAddingProfile
- ? getString(R.string.vpn_edit_title_add)
- : getString(R.string.vpn_edit_title_edit);
- setTitle(String.format(formatString,
+ ? activity.getString(R.string.vpn_edit_title_add)
+ : activity.getString(R.string.vpn_edit_title_edit);
+ activity.setTitle(String.format(formatString,
profile.getType().getDisplayName()));
}
@@ -140,7 +156,7 @@ public class VpnEditor extends PreferenceActivity {
String errorMsg = mProfileEditor.validate();
if (errorMsg != null) {
- Util.showErrorMessage(this, errorMsg);
+ Util.showErrorMessage(getActivity(), errorMsg);
return false;
}
@@ -149,9 +165,9 @@ public class VpnEditor extends PreferenceActivity {
}
private void setResult(VpnProfile p) {
- Intent intent = new Intent(this, VpnSettings.class);
+ Intent intent = new Intent(getActivity(), VpnSettings.class);
intent.putExtra(VpnSettings.KEY_VPN_PROFILE, (Parcelable) p);
- setResult(RESULT_OK, intent);
+ setResult(Activity.RESULT_OK, intent);
}
private VpnProfileEditor getEditor(VpnProfile p) {
@@ -175,10 +191,9 @@ public class VpnEditor extends PreferenceActivity {
@Override
- protected Dialog onCreateDialog(int id) {
-
+ public Dialog onCreateDialog(int id) {
if (id == CONFIRM_DIALOG_ID) {
- return new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(getActivity())
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(mAddingProfile
@@ -187,7 +202,7 @@ public class VpnEditor extends PreferenceActivity {
.setPositiveButton(R.string.vpn_yes_button,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int w) {
- finish();
+ finishFragment();
}
})
.setNegativeButton(R.string.vpn_mistake_button, null)
@@ -197,8 +212,9 @@ public class VpnEditor extends PreferenceActivity {
return super.onCreateDialog(id);
}
+ /*
@Override
- protected void onPrepareDialog(int id, Dialog dialog) {
+ public void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
if (id == CONFIRM_DIALOG_ID) {
@@ -206,7 +222,7 @@ public class VpnEditor extends PreferenceActivity {
? getString(R.string.vpn_confirm_add_profile_cancellation)
: getString(R.string.vpn_confirm_edit_profile_cancellation));
}
- }
+ }*/
private VpnProfile getProfile() {
return mProfileEditor.getProfile();
diff --git a/src/com/android/settings/vpn/VpnSettings.java b/src/com/android/settings/vpn/VpnSettings.java
index 7b8d433ad..e9a4c3dc0 100644
--- a/src/com/android/settings/vpn/VpnSettings.java
+++ b/src/com/android/settings/vpn/VpnSettings.java
@@ -17,11 +17,14 @@
package com.android.settings.vpn;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.content.ComponentName;
+import android.app.Fragment;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -37,12 +40,10 @@ import android.net.vpn.VpnType;
import android.os.Bundle;
import android.os.ConditionVariable;
import android.os.IBinder;
-import android.os.Parcelable;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
+import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
-import android.preference.Preference.OnPreferenceClickListener;
import android.security.Credentials;
import android.security.KeyStore;
import android.text.TextUtils;
@@ -69,8 +70,8 @@ import java.util.Map;
/**
* The preference activity for configuring VPN settings.
*/
-public class VpnSettings extends PreferenceActivity implements
- DialogInterface.OnClickListener {
+public class VpnSettings extends SettingsPreferenceFragment
+ implements DialogInterface.OnClickListener {
// Key to the field exchanged for profile editing.
static final String KEY_VPN_PROFILE = "vpn_profile";
@@ -122,7 +123,7 @@ public class VpnSettings extends PreferenceActivity implements
private KeyStore mKeyStore = KeyStore.getInstance();
- private VpnManager mVpnManager = new VpnManager(this);
+ private VpnManager mVpnManager;
private ConnectivityReceiver mConnectivityReceiver =
new ConnectivityReceiver();
@@ -137,7 +138,13 @@ public class VpnSettings extends PreferenceActivity implements
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.vpn_settings);
+ }
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mVpnManager = new VpnManager(getActivity());
// restore VpnProfile list and construct VpnPreference map
mVpnListContainer = (PreferenceCategory) findPreference(PREF_VPN_LIST);
@@ -168,22 +175,24 @@ public class VpnSettings extends PreferenceActivity implements
if ((mUnlockAction != null) && isKeyStoreUnlocked()) {
Runnable action = mUnlockAction;
mUnlockAction = null;
- runOnUiThread(action);
+ getActivity().runOnUiThread(action);
}
}
@Override
- protected void onDestroy() {
- super.onDestroy();
+ public void onDestroyView() {
unregisterForContextMenu(getListView());
mVpnManager.unregisterConnectivityReceiver(mConnectivityReceiver);
if ((mShowingDialog != null) && mShowingDialog.isShowing()) {
mShowingDialog.dismiss();
}
+ // This should be called after the procedure above as ListView inside this Fragment
+ // will be deleted here.
+ super.onDestroyView();
}
@Override
- protected Dialog onCreateDialog (int id) {
+ public Dialog onCreateDialog (int id) {
switch (id) {
case DIALOG_CONNECT:
return createConnectDialog();
@@ -203,13 +212,14 @@ public class VpnSettings extends PreferenceActivity implements
}
private Dialog createConnectDialog() {
- return new AlertDialog.Builder(this)
+ final Activity activity = getActivity();
+ return new AlertDialog.Builder(activity)
.setView(mConnectingActor.createConnectView())
- .setTitle(String.format(getString(R.string.vpn_connect_to),
+ .setTitle(String.format(activity.getString(R.string.vpn_connect_to),
mActiveProfile.getName()))
- .setPositiveButton(getString(R.string.vpn_connect_button),
+ .setPositiveButton(activity.getString(R.string.vpn_connect_button),
this)
- .setNegativeButton(getString(android.R.string.cancel),
+ .setNegativeButton(activity.getString(android.R.string.cancel),
this)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
@@ -291,7 +301,7 @@ public class VpnSettings extends PreferenceActivity implements
}
private AlertDialog.Builder createCommonDialogBuilder() {
- return new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(getActivity())
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(R.string.vpn_yes_button,
@@ -364,9 +374,9 @@ public class VpnSettings extends PreferenceActivity implements
}
@Override
- protected void onActivityResult(final int requestCode, final int resultCode,
+ public void onActivityResult(final int requestCode, final int resultCode,
final Intent data) {
- if ((resultCode == RESULT_CANCELED) || (data == null)) {
+ if ((resultCode == Activity.RESULT_CANCELED) || (data == null)) {
Log.d(TAG, "no result returned by editor");
return;
}
@@ -381,11 +391,12 @@ public class VpnSettings extends PreferenceActivity implements
return;
}
+ final Activity activity = getActivity();
int index = getProfileIndexFromId(p.getId());
if (checkDuplicateName(p, index)) {
final VpnProfile profile = p;
- Util.showErrorMessage(this, String.format(
- getString(R.string.vpn_error_duplicate_name),
+ Util.showErrorMessage(activity, String.format(
+ activity.getString(R.string.vpn_error_duplicate_name),
p.getName()),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int w) {
@@ -407,30 +418,32 @@ public class VpnSettings extends PreferenceActivity implements
try {
if (index < 0) {
addProfile(p);
- Util.showShortToastMessage(this, String.format(
- getString(R.string.vpn_profile_added), p.getName()));
+ Util.showShortToastMessage(activity, String.format(
+ activity.getString(R.string.vpn_profile_added), p.getName()));
} else {
replaceProfile(index, p);
- Util.showShortToastMessage(this, String.format(
- getString(R.string.vpn_profile_replaced),
+ Util.showShortToastMessage(activity, String.format(
+ activity.getString(R.string.vpn_profile_replaced),
p.getName()));
}
} catch (IOException e) {
final VpnProfile profile = p;
- Util.showErrorMessage(this, e + ": " + e.getMessage(),
+ Util.showErrorMessage(activity, e + ": " + e.getMessage(),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int w) {
startVpnEditor(profile);
}
});
}
+
+ // Remove cached VpnEditor as it is needless anymore.
} else {
throw new RuntimeException("unknown request code: " + requestCode);
}
}
// Called when the buttons on the connect dialog are clicked.
- //@Override
+ @Override
public synchronized void onClick(DialogInterface dialog, int which) {
if (which == CONNECT_BUTTON) {
Dialog d = (Dialog) dialog;
@@ -440,12 +453,15 @@ public class VpnSettings extends PreferenceActivity implements
removeDialog(DIALOG_CONNECT);
return;
} else {
- dismissDialog(DIALOG_CONNECT);
+ // dismissDialog(DIALOG_CONNECT);
+ removeDialog(DIALOG_CONNECT);
+
+ final Activity activity = getActivity();
// show error dialog
- mShowingDialog = new AlertDialog.Builder(this)
+ mShowingDialog = new AlertDialog.Builder(activity)
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
- .setMessage(String.format(getString(
+ .setMessage(String.format(activity.getString(
R.string.vpn_error_miss_entering), error))
.setPositiveButton(R.string.vpn_back_button,
new DialogInterface.OnClickListener() {
@@ -513,7 +529,7 @@ public class VpnSettings extends PreferenceActivity implements
}
}
};
- mShowingDialog = new AlertDialog.Builder(this)
+ mShowingDialog = new AlertDialog.Builder(getActivity())
.setTitle(android.R.string.dialog_alert_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.vpn_confirm_profile_deletion)
@@ -559,7 +575,7 @@ public class VpnSettings extends PreferenceActivity implements
// Adds a preference in mVpnListContainer
private VpnPreference addPreferenceFor(
VpnProfile p, boolean addToContainer) {
- VpnPreference pref = new VpnPreference(this, p);
+ VpnPreference pref = new VpnPreference(getActivity(), p);
mVpnPreferenceMap.put(p.getName(), pref);
if (addToContainer) mVpnListContainer.addPreference(pref);
@@ -599,8 +615,8 @@ public class VpnSettings extends PreferenceActivity implements
}
private void startVpnTypeSelection() {
- Intent intent = new Intent(this, VpnTypeSelection.class);
- startActivityForResult(intent, REQUEST_SELECT_VPN_TYPE);
+ startFragment(this, VpnTypeSelection.class.getCanonicalName(),
+ REQUEST_SELECT_VPN_TYPE, null);
}
private boolean isKeyStoreUnlocked() {
@@ -614,16 +630,14 @@ public class VpnSettings extends PreferenceActivity implements
L2tpIpsecPskProfile pskProfile = (L2tpIpsecPskProfile) p;
String presharedKey = pskProfile.getPresharedKey();
if (!TextUtils.isEmpty(presharedKey)) return true;
- // pass through
-
+ // $FALL-THROUGH$
case L2TP:
L2tpProfile l2tpProfile = (L2tpProfile) p;
if (l2tpProfile.isSecretEnabled() &&
!TextUtils.isEmpty(l2tpProfile.getSecretString())) {
return true;
}
- // pass through
-
+ // $FALL-THROUGH$
default:
return false;
}
@@ -648,14 +662,15 @@ public class VpnSettings extends PreferenceActivity implements
private boolean unlockKeyStore(VpnProfile p, Runnable action) {
if (isKeyStoreUnlocked()) return true;
mUnlockAction = action;
- Credentials.getInstance().unlock(this);
+ Credentials.getInstance().unlock(getActivity());
return false;
}
private void startVpnEditor(final VpnProfile profile) {
- Intent intent = new Intent(this, VpnEditor.class);
- intent.putExtra(KEY_VPN_PROFILE, (Parcelable) profile);
- startActivityForResult(intent, REQUEST_ADD_OR_EDIT_PROFILE);
+ Bundle args = new Bundle();
+ args.putParcelable(KEY_VPN_PROFILE, profile);
+ startFragment(this, VpnEditor.class.getCanonicalName(),
+ REQUEST_ADD_OR_EDIT_PROFILE, args);
}
private synchronized void connect(final VpnProfile p) {
@@ -714,7 +729,7 @@ public class VpnSettings extends PreferenceActivity implements
case CONNECTING:
mConnectingActor = getActor(p);
- // pass through
+ // $FALL-THROUGH$
case DISCONNECTING:
mActiveProfile = p;
disableProfilePreferencesIfOneActive();
@@ -810,11 +825,6 @@ public class VpnSettings extends PreferenceActivity implements
public int compare(VpnProfile p1, VpnProfile p2) {
return p1.getName().compareTo(p2.getName());
}
-
- public boolean equals(VpnProfile p) {
- // not used
- return false;
- }
});
for (VpnProfile p : mVpnProfileList) {
Preference pref = addPreferenceFor(p, false);
@@ -855,20 +865,21 @@ public class VpnSettings extends PreferenceActivity implements
}
private String getProfileSummaryString(VpnProfile p) {
+ final Activity activity = getActivity();
switch (p.getState()) {
case CONNECTING:
- return getString(R.string.vpn_connecting);
+ return activity.getString(R.string.vpn_connecting);
case DISCONNECTING:
- return getString(R.string.vpn_disconnecting);
+ return activity.getString(R.string.vpn_disconnecting);
case CONNECTED:
- return getString(R.string.vpn_connected);
+ return activity.getString(R.string.vpn_connected);
default:
- return getString(R.string.vpn_connect_hint);
+ return activity.getString(R.string.vpn_connect_hint);
}
}
private VpnProfileActor getActor(VpnProfile p) {
- return new AuthenticationActor(this, p);
+ return new AuthenticationActor(getActivity(), p);
}
private VpnProfile createVpnProfile(String type) {
@@ -938,8 +949,7 @@ public class VpnSettings extends PreferenceActivity implements
Log.e(TAG, "keystore write failed: key=" + key);
}
pskProfile.setPresharedKey(key);
- // pass through
-
+ // $FALL-THROUGH$
case L2TP_IPSEC:
case L2TP:
L2tpProfile l2tpProfile = (L2tpProfile) p;
@@ -1007,8 +1017,6 @@ public class VpnSettings extends PreferenceActivity implements
// managing status check in a background thread
private class StatusChecker {
- private List<VpnProfile> mList;
-
synchronized void check(final List<VpnProfile> list) {
final ConditionVariable cv = new ConditionVariable();
cv.close();
@@ -1027,7 +1035,7 @@ public class VpnSettings extends PreferenceActivity implements
changeState(p, VpnState.IDLE);
}
}
- VpnSettings.this.unbindService(this);
+ getActivity().unbindService(this);
showPreferences();
}
@@ -1035,7 +1043,7 @@ public class VpnSettings extends PreferenceActivity implements
cv.open();
setDefaultState(list);
- VpnSettings.this.unbindService(this);
+ getActivity().unbindService(this);
showPreferences();
}
};
diff --git a/src/com/android/settings/vpn/VpnTypeSelection.java b/src/com/android/settings/vpn/VpnTypeSelection.java
index aa4bc5e30..5990ac0ac 100644
--- a/src/com/android/settings/vpn/VpnTypeSelection.java
+++ b/src/com/android/settings/vpn/VpnTypeSelection.java
@@ -17,13 +17,14 @@
package com.android.settings.vpn;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import android.app.Activity;
import android.content.Intent;
import android.net.vpn.VpnManager;
import android.net.vpn.VpnType;
import android.os.Bundle;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import java.util.HashMap;
@@ -32,7 +33,7 @@ import java.util.Map;
/**
* The activity to select a VPN type.
*/
-public class VpnTypeSelection extends PreferenceActivity {
+public class VpnTypeSelection extends SettingsPreferenceFragment {
private Map<String, VpnType> mTypeMap = new HashMap<String, VpnType>();
@Override
@@ -46,19 +47,20 @@ public class VpnTypeSelection extends PreferenceActivity {
@Override
public boolean onPreferenceTreeClick(PreferenceScreen ps, Preference pref) {
setResult(mTypeMap.get(pref.getTitle().toString()));
- finish();
+ finishFragment();
return true;
}
private void initTypeList() {
PreferenceScreen root = getPreferenceScreen();
+ final Activity activity = getActivity();
for (VpnType t : VpnManager.getSupportedVpnTypes()) {
String displayName = t.getDisplayName();
String message = String.format(
- getString(R.string.vpn_edit_title_add), displayName);
+ activity.getString(R.string.vpn_edit_title_add), displayName);
mTypeMap.put(message, t);
- Preference pref = new Preference(this);
+ Preference pref = new Preference(activity);
pref.setTitle(message);
pref.setSummary(t.getDescriptionId());
root.addPreference(pref);
@@ -66,8 +68,8 @@ public class VpnTypeSelection extends PreferenceActivity {
}
private void setResult(VpnType type) {
- Intent intent = new Intent(this, VpnSettings.class);
+ Intent intent = new Intent(getActivity(), VpnSettings.class);
intent.putExtra(VpnSettings.KEY_VPN_TYPE, type.toString());
- setResult(RESULT_OK, intent);
+ setResult(Activity.RESULT_OK, intent);
}
}
diff --git a/src/com/android/settings/wifi/AccessPoint.java b/src/com/android/settings/wifi/AccessPoint.java
index 141c4129c..054c6ff93 100644
--- a/src/com/android/settings/wifi/AccessPoint.java
+++ b/src/com/android/settings/wifi/AccessPoint.java
@@ -20,28 +20,59 @@ import com.android.settings.R;
import android.content.Context;
import android.net.NetworkInfo.DetailedState;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.net.wifi.ScanResult;
import android.preference.Preference;
-import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
+import java.util.Comparator;
+
class AccessPoint extends Preference {
private static final int[] STATE_SECURED = {R.attr.state_encrypted};
private static final int[] STATE_NONE = {};
+ public static final class Comparater
+ implements Comparator<AccessPoint> {
+ @Override
+ public int compare(AccessPoint accessPoint1, AccessPoint accessPoint2) {
+ // Active one goes first.
+ if (accessPoint1.mInfo != accessPoint2.mInfo) {
+ return (accessPoint1.mInfo != null) ? -1 : 1;
+ }
+
+ // Reachable one goes before unreachable one.
+ if ((accessPoint1.mRssi ^ accessPoint2.mRssi) < 0) {
+ return (accessPoint1.mRssi != Integer.MAX_VALUE) ? -1 : 1;
+ }
+ // Configured one goes before unconfigured one.
+ if ((accessPoint1.networkId ^ accessPoint2.networkId) < 0) {
+ return (accessPoint1.networkId != -1) ? -1 : 1;
+ }
+ // Sort by signal strength.
+ int difference = WifiManager.compareSignalLevel(
+ accessPoint2.mRssi, accessPoint1.mRssi);
+ if (difference != 0) {
+ return difference;
+ }
+ // Sort by ssid.
+ return accessPoint1.ssid.compareToIgnoreCase(accessPoint2.ssid);
+ }
+ }
+
static final int SECURITY_NONE = 0;
static final int SECURITY_WEP = 1;
static final int SECURITY_PSK = 2;
static final int SECURITY_EAP = 3;
final String ssid;
+ final String bssid;
final int security;
final int networkId;
+ boolean wpsAvailable = false;
private WifiConfiguration mConfig;
private int mRssi;
@@ -75,6 +106,7 @@ class AccessPoint extends Preference {
super(context);
setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
+ bssid = config.BSSID;
security = getSecurity(config);
networkId = config.networkId;
mConfig = config;
@@ -85,7 +117,10 @@ class AccessPoint extends Preference {
super(context);
setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
ssid = result.SSID;
+ bssid = result.BSSID;
security = getSecurity(result);
+ wpsAvailable = security != SECURITY_NONE && security != SECURITY_EAP &&
+ result.capabilities.contains("WPS");
networkId = -1;
mRssi = result.level;
}
@@ -105,32 +140,6 @@ class AccessPoint extends Preference {
super.onBindView(view);
}
- @Override
- public int compareTo(Preference preference) {
- if (!(preference instanceof AccessPoint)) {
- return 1;
- }
- AccessPoint other = (AccessPoint) preference;
- // Active one goes first.
- if (mInfo != other.mInfo) {
- return (mInfo != null) ? -1 : 1;
- }
- // Reachable one goes before unreachable one.
- if ((mRssi ^ other.mRssi) < 0) {
- return (mRssi != Integer.MAX_VALUE) ? -1 : 1;
- }
- // Configured one goes before unconfigured one.
- if ((networkId ^ other.networkId) < 0) {
- return (networkId != -1) ? -1 : 1;
- }
- // Sort by signal strength.
- int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi);
- if (difference != 0) {
- return difference;
- }
- // Sort by ssid.
- return ssid.compareToIgnoreCase(other.ssid);
- }
boolean update(ScanResult result) {
// We do not call refresh() since this is called before onBindView().
@@ -215,8 +224,13 @@ class AccessPoint extends Preference {
if (security == SECURITY_NONE) {
setSummary(status);
} else {
- String format = context.getString((status == null) ?
- R.string.wifi_secured : R.string.wifi_secured_with_status);
+ String format;
+ if (wpsAvailable && mConfig == null) {
+ format = context.getString(R.string.wifi_secured_with_wps);
+ } else {
+ format = context.getString((status == null) ?
+ R.string.wifi_secured : R.string.wifi_secured_with_status);
+ }
String[] type = context.getResources().getStringArray(R.array.wifi_security);
setSummary(String.format(format, type[security], status));
}
diff --git a/src/com/android/settings/wifi/AccessPointCategoryForSetupWizardXL.java b/src/com/android/settings/wifi/AccessPointCategoryForSetupWizardXL.java
new file mode 100644
index 000000000..7a1623bc5
--- /dev/null
+++ b/src/com/android/settings/wifi/AccessPointCategoryForSetupWizardXL.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import com.android.settings.ProgressCategoryBase;
+import com.android.settings.R;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+public class AccessPointCategoryForSetupWizardXL extends ProgressCategoryBase {
+ public AccessPointCategoryForSetupWizardXL(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.access_point_category_for_setup_wizard_xl);
+ }
+
+ @Override
+ public void setProgress(boolean progressOn) {
+ notifyChanged();
+ }
+} \ No newline at end of file
diff --git a/src/com/android/settings/wifi/AdvancedSettings.java b/src/com/android/settings/wifi/AdvancedSettings.java
index 636e1dffb..c88073d75 100644
--- a/src/com/android/settings/wifi/AdvancedSettings.java
+++ b/src/com/android/settings/wifi/AdvancedSettings.java
@@ -17,64 +17,39 @@
package com.android.settings.wifi;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
-import android.content.ContentResolver;
+import android.app.Activity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.EditTextPreference;
+import android.os.SystemProperties;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.provider.Settings;
-import android.provider.Settings.System;
import android.text.TextUtils;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
import android.widget.Toast;
-import android.os.SystemProperties;
-public class AdvancedSettings extends PreferenceActivity
+public class AdvancedSettings extends SettingsPreferenceFragment
implements Preference.OnPreferenceChangeListener {
private static final String KEY_MAC_ADDRESS = "mac_address";
private static final String KEY_CURRENT_IP_ADDRESS = "current_ip_address";
- private static final String KEY_USE_STATIC_IP = "use_static_ip";
private static final String KEY_NUM_CHANNELS = "num_channels";
private static final String KEY_SLEEP_POLICY = "sleep_policy";
-
- private String[] mSettingNames = {
- System.WIFI_STATIC_IP, System.WIFI_STATIC_GATEWAY, System.WIFI_STATIC_NETMASK,
- System.WIFI_STATIC_DNS1, System.WIFI_STATIC_DNS2
- };
-
- private String[] mPreferenceKeys = {
- "ip_address", "gateway", "netmask", "dns1", "dns2"
- };
-
- private CheckBoxPreference mUseStaticIpCheckBox;
-
- private static final int MENU_ITEM_SAVE = Menu.FIRST;
- private static final int MENU_ITEM_CANCEL = Menu.FIRST + 1;
-
+
//Tracks ro.debuggable (1 on userdebug builds)
private static int DEBUGGABLE;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
addPreferencesFromResource(R.xml.wifi_advanced_settings);
-
- mUseStaticIpCheckBox = (CheckBoxPreference) findPreference(KEY_USE_STATIC_IP);
- mUseStaticIpCheckBox.setOnPreferenceChangeListener(this);
+ }
- for (int i = 0; i < mPreferenceKeys.length; i++) {
- Preference preference = findPreference(mPreferenceKeys[i]);
- preference.setOnPreferenceChangeListener(this);
- }
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0);
@@ -98,10 +73,9 @@ public class AdvancedSettings extends PreferenceActivity
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
-
- updateUi();
+
/**
* Remove user control of regulatory domain
* channel count settings in non userdebug builds
@@ -117,7 +91,7 @@ public class AdvancedSettings extends PreferenceActivity
ListPreference pref = (ListPreference) findPreference(KEY_NUM_CHANNELS);
pref.setOnPreferenceChangeListener(this);
- WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ WifiManager wifiManager = (WifiManager) getSystemService(Activity.WIFI_SERVICE);
/*
* Generate the list of valid channel counts to show in the ListPreference.
* The values are numerical, so the only text to be localized is the
@@ -125,7 +99,7 @@ public class AdvancedSettings extends PreferenceActivity
*/
int[] validChannelCounts = wifiManager.getValidChannelCounts();
if (validChannelCounts == null) {
- Toast.makeText(this, R.string.wifi_setting_num_channels_error,
+ Toast.makeText(getActivity(), R.string.wifi_setting_num_channels_error,
Toast.LENGTH_SHORT).show();
pref.setEnabled(false);
return;
@@ -135,8 +109,8 @@ public class AdvancedSettings extends PreferenceActivity
for (int i = 0; i < validChannelCounts.length; i++) {
entryValues[i] = String.valueOf(validChannelCounts[i]);
- entries[i] = getString(R.string.wifi_setting_num_channels_channel_phrase,
- validChannelCounts[i]);
+ entries[i] = getActivity().getString(R.string.wifi_setting_num_channels_channel_phrase,
+ validChannelCounts[i]);
}
pref.setEntries(entries);
pref.setEntryValues(entryValues);
@@ -155,16 +129,6 @@ public class AdvancedSettings extends PreferenceActivity
pref.setValue(String.valueOf(value));
}
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
-
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- updateSettingsProvider();
- }
-
- return super.onKeyDown(keyCode, event);
- }
-
public boolean onPreferenceChange(Preference preference, Object newValue) {
String key = preference.getKey();
if (key == null) return true;
@@ -172,13 +136,13 @@ public class AdvancedSettings extends PreferenceActivity
if (key.equals(KEY_NUM_CHANNELS)) {
try {
int numChannels = Integer.parseInt((String) newValue);
- WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ WifiManager wifiManager = (WifiManager) getSystemService(Activity.WIFI_SERVICE);
if (!wifiManager.setNumAllowedChannels(numChannels, true)) {
- Toast.makeText(this, R.string.wifi_setting_num_channels_error,
+ Toast.makeText(getActivity(), R.string.wifi_setting_num_channels_error,
Toast.LENGTH_SHORT).show();
}
} catch (NumberFormatException e) {
- Toast.makeText(this, R.string.wifi_setting_num_channels_error,
+ Toast.makeText(getActivity(), R.string.wifi_setting_num_channels_error,
Toast.LENGTH_SHORT).show();
return false;
}
@@ -188,134 +152,23 @@ public class AdvancedSettings extends PreferenceActivity
Settings.System.putInt(getContentResolver(),
Settings.System.WIFI_SLEEP_POLICY, Integer.parseInt(((String) newValue)));
} catch (NumberFormatException e) {
- Toast.makeText(this, R.string.wifi_setting_sleep_policy_error,
+ Toast.makeText(getActivity(), R.string.wifi_setting_sleep_policy_error,
Toast.LENGTH_SHORT).show();
return false;
}
-
- } else if (key.equals(KEY_USE_STATIC_IP)) {
- boolean value = ((Boolean) newValue).booleanValue();
-
- try {
- Settings.System.putInt(getContentResolver(),
- Settings.System.WIFI_USE_STATIC_IP, value ? 1 : 0);
- } catch (NumberFormatException e) {
- return false;
- }
- } else {
- String value = (String) newValue;
-
- if (!isIpAddress(value)) {
- Toast.makeText(this, R.string.wifi_ip_settings_invalid_ip, Toast.LENGTH_LONG).show();
- return false;
- }
-
- preference.setSummary(value);
- for (int i = 0; i < mSettingNames.length; i++) {
- if (key.equals(mPreferenceKeys[i])) {
- Settings.System.putString(getContentResolver(), mSettingNames[i], value);
- break;
- }
- }
}
return true;
}
- private boolean isIpAddress(String value) {
-
- int start = 0;
- int end = value.indexOf('.');
- int numBlocks = 0;
-
- while (start < value.length()) {
-
- if (end == -1) {
- end = value.length();
- }
-
- try {
- int block = Integer.parseInt(value.substring(start, end));
- if ((block > 255) || (block < 0)) {
- return false;
- }
- } catch (NumberFormatException e) {
- return false;
- }
-
- numBlocks++;
-
- start = end + 1;
- end = value.indexOf('.', start);
- }
-
- return numBlocks == 4;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
-
- menu.add(0, MENU_ITEM_SAVE, 0, R.string.wifi_ip_settings_menu_save)
- .setIcon(android.R.drawable.ic_menu_save);
-
- menu.add(0, MENU_ITEM_CANCEL, 0, R.string.wifi_ip_settings_menu_cancel)
- .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
-
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
-
- switch (item.getItemId()) {
-
- case MENU_ITEM_SAVE:
- updateSettingsProvider();
- finish();
- return true;
-
- case MENU_ITEM_CANCEL:
- finish();
- return true;
- }
-
- return super.onOptionsItemSelected(item);
- }
-
- private void updateUi() {
- ContentResolver contentResolver = getContentResolver();
-
- mUseStaticIpCheckBox.setChecked(System.getInt(contentResolver,
- System.WIFI_USE_STATIC_IP, 0) != 0);
-
- for (int i = 0; i < mSettingNames.length; i++) {
- EditTextPreference preference = (EditTextPreference) findPreference(mPreferenceKeys[i]);
- String settingValue = System.getString(contentResolver, mSettingNames[i]);
- preference.setText(settingValue);
- preference.setSummary(settingValue);
- }
- }
-
- private void updateSettingsProvider() {
- ContentResolver contentResolver = getContentResolver();
-
- System.putInt(contentResolver, System.WIFI_USE_STATIC_IP,
- mUseStaticIpCheckBox.isChecked() ? 1 : 0);
-
- for (int i = 0; i < mSettingNames.length; i++) {
- EditTextPreference preference = (EditTextPreference) findPreference(mPreferenceKeys[i]);
- System.putString(contentResolver, mSettingNames[i], preference.getText());
- }
- }
-
private void refreshWifiInfo() {
- WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
+ WifiManager wifiManager = (WifiManager) getSystemService(Activity.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Preference wifiMacAddressPref = findPreference(KEY_MAC_ADDRESS);
String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
- : getString(R.string.status_unavailable));
+ : getActivity().getString(R.string.status_unavailable));
Preference wifiIpAddressPref = findPreference(KEY_CURRENT_IP_ADDRESS);
String ipAddress = null;
@@ -329,7 +182,7 @@ public class AdvancedSettings extends PreferenceActivity
}
}
wifiIpAddressPref.setSummary(ipAddress == null ?
- getString(R.string.status_unavailable) : ipAddress);
+ getActivity().getString(R.string.status_unavailable) : ipAddress);
}
}
diff --git a/src/com/android/settings/wifi/Summary.java b/src/com/android/settings/wifi/Summary.java
index 6da2fa5db..d96d23ecd 100644
--- a/src/com/android/settings/wifi/Summary.java
+++ b/src/com/android/settings/wifi/Summary.java
@@ -20,7 +20,6 @@ import com.android.settings.R;
import android.content.Context;
import android.net.NetworkInfo.DetailedState;
-import android.text.TextUtils;
class Summary {
static String get(Context context, String ssid, DetailedState state) {
diff --git a/src/com/android/settings/wifi/WifiApDialog.java b/src/com/android/settings/wifi/WifiApDialog.java
index 43289d2f9..fde6efc69 100644
--- a/src/com/android/settings/wifi/WifiApDialog.java
+++ b/src/com/android/settings/wifi/WifiApDialog.java
@@ -16,8 +16,6 @@
package com.android.settings.wifi;
-import com.android.settings.R;
-
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
@@ -28,16 +26,15 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
-import android.util.Log;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
+import com.android.settings.R;
+
/**
* Dialog to configure the SSID and security settings
* for Access Point operation
@@ -97,6 +94,7 @@ class WifiApDialog extends AlertDialog implements View.OnClickListener,
return null;
}
+ @Override
protected void onCreate(Bundle savedInstanceState) {
mView = getLayoutInflater().inflate(R.layout.wifi_ap_dialog, null);
@@ -167,7 +165,8 @@ class WifiApDialog extends AlertDialog implements View.OnClickListener,
validate();
}
- public void onItemSelected(AdapterView parent, View view, int position, long id) {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(position == OPEN_INDEX)
mSecurityType = AccessPoint.SECURITY_NONE;
else
@@ -176,7 +175,8 @@ class WifiApDialog extends AlertDialog implements View.OnClickListener,
validate();
}
- public void onNothingSelected(AdapterView parent) {
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
}
private void showSecurityFields() {
diff --git a/src/com/android/settings/wifi/WifiApSettings.java b/src/com/android/settings/wifi/WifiApSettings.java
index ca1b85688..7336c6c5e 100644
--- a/src/com/android/settings/wifi/WifiApSettings.java
+++ b/src/com/android/settings/wifi/WifiApSettings.java
@@ -17,29 +17,24 @@
package com.android.settings.wifi;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+
+import android.app.Activity;
import android.app.Dialog;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceScreen;
-import android.preference.CheckBoxPreference;
-import android.provider.Settings;
-import android.util.Log;
import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
/*
* Displays preferences for Tethering.
*/
-public class WifiApSettings extends PreferenceActivity
+public class WifiApSettings extends SettingsPreferenceFragment
implements DialogInterface.OnClickListener {
private static final String WIFI_AP_SSID_AND_SECURITY = "wifi_ap_ssid_and_security";
@@ -61,26 +56,34 @@ public class WifiApSettings extends PreferenceActivity
private WifiConfiguration mWifiConfig = null;
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.wifi_ap_settings);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ final Activity activity = getActivity();
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mWifiConfig = mWifiManager.getWifiApConfiguration();
mSecurityType = getResources().getStringArray(R.array.wifi_ap_security);
- addPreferencesFromResource(R.xml.wifi_ap_settings);
+
mCreateNetwork = findPreference(WIFI_AP_SSID_AND_SECURITY);
mEnableWifiAp = (CheckBoxPreference) findPreference(ENABLE_WIFI_AP);
- mWifiApEnabler = new WifiApEnabler(this, mEnableWifiAp);
+ mWifiApEnabler = new WifiApEnabler(activity, mEnableWifiAp);
if(mWifiConfig == null) {
- String s = getString(com.android.internal.R.string.wifi_tether_configure_ssid_default);
- mCreateNetwork.setSummary(String.format(getString(CONFIG_SUBTEXT),
+ final String s = activity.getString(
+ com.android.internal.R.string.wifi_tether_configure_ssid_default);
+ mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT),
s, mSecurityType[OPEN_INDEX]));
} else {
- mCreateNetwork.setSummary(String.format(getString(CONFIG_SUBTEXT),
+ mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT),
mWifiConfig.SSID,
mWifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
mSecurityType[WPA_INDEX] : mSecurityType[OPEN_INDEX]));
@@ -88,22 +91,23 @@ public class WifiApSettings extends PreferenceActivity
}
@Override
- protected Dialog onCreateDialog(int id) {
+ public Dialog onCreateDialog(int id) {
if (id == DIALOG_AP_SETTINGS) {
- mDialog = new WifiApDialog(this, this, mWifiConfig);
+ final Activity activity = getActivity();
+ mDialog = new WifiApDialog(activity, this, mWifiConfig);
return mDialog;
}
return null;
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
mWifiApEnabler.resume();
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
mWifiApEnabler.pause();
}
@@ -117,7 +121,6 @@ public class WifiApSettings extends PreferenceActivity
}
public void onClick(DialogInterface dialogInterface, int button) {
-
if (button == DialogInterface.BUTTON_POSITIVE) {
mWifiConfig = mDialog.getConfig();
if (mWifiConfig != null) {
@@ -135,7 +138,7 @@ public class WifiApSettings extends PreferenceActivity
} else {
mWifiManager.setWifiApConfiguration(mWifiConfig);
}
- mCreateNetwork.setSummary(String.format(getString(CONFIG_SUBTEXT),
+ mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT),
mWifiConfig.SSID,
mWifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
mSecurityType[WPA_INDEX] : mSecurityType[OPEN_INDEX]));
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
new file mode 100644
index 000000000..4c04fb553
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.net.DhcpInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.IpAssignment;
+import android.net.wifi.WifiConfiguration.AuthAlgorithm;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
+import android.net.wifi.WifiInfo;
+import android.security.Credentials;
+import android.security.KeyStore;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.text.format.Formatter;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.settings.R;
+import java.net.UnknownHostException;
+
+/**
+ * The class for allowing UIs like {@link WifiDialog} and {@link WifiConfigPreference} to
+ * share the logic for controlling buttons, text fields, etc.
+ */
+public class WifiConfigController implements TextWatcher,
+ View.OnClickListener, AdapterView.OnItemSelectedListener {
+ private static final String KEYSTORE_SPACE = "keystore://";
+
+ private final WifiConfigUiBase mConfigUi;
+ private final View mView;
+ private final AccessPoint mAccessPoint;
+
+ private boolean mEdit;
+
+ private TextView mSsidView;
+
+ // e.g. AccessPoint.SECURITY_NONE
+ private int mAccessPointSecurity;
+ private TextView mPasswordView;
+
+ private Spinner mSecuritySpinner;
+ private Spinner mEapMethodSpinner;
+ private Spinner mEapCaCertSpinner;
+ private Spinner mPhase2Spinner;
+ private Spinner mEapUserCertSpinner;
+ private TextView mEapIdentityView;
+ private TextView mEapAnonymousView;
+
+ /* This value comes from "wifi_ip_settings" resource array */
+ private static final int STATIC_IP = 1;
+
+ /* These values come from "wifi_network_setup" resource array */
+ public static final int MANUAL = 0;
+ public static final int WPS_PBC = 1;
+ public static final int WPS_PIN = 2;
+
+ private Spinner mNetworkSetupSpinner;
+ private Spinner mIpSettingsSpinner;
+ private TextView mIpAddressView;
+ private TextView mGatewayView;
+ private TextView mNetmaskView;
+ private TextView mDns1View;
+ private TextView mDns2View;
+
+ static boolean requireKeyStore(WifiConfiguration config) {
+ String values[] = {config.ca_cert.value(), config.client_cert.value(),
+ config.private_key.value()};
+ for (String value : values) {
+ if (value != null && value.startsWith(KEYSTORE_SPACE)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public WifiConfigController(WifiConfigUiBase parent, View view, AccessPoint accessPoint,
+ boolean edit, DialogInterface.OnClickListener listener) {
+ mConfigUi = parent;
+
+ mView = view;
+ mAccessPoint = accessPoint;
+ mAccessPointSecurity = (accessPoint == null) ? AccessPoint.SECURITY_NONE :
+ accessPoint.security;
+ mEdit = edit;
+
+ final Context context = mConfigUi.getContext();
+ final Resources resources = context.getResources();
+
+ if (mAccessPoint == null) {
+ mConfigUi.setTitle(R.string.wifi_add_network);
+ mView.findViewById(R.id.type).setVisibility(View.VISIBLE);
+ mSsidView = (TextView) mView.findViewById(R.id.ssid);
+ mSsidView.addTextChangedListener(this);
+ mSecuritySpinner = ((Spinner) mView.findViewById(R.id.security));
+ mSecuritySpinner.setOnItemSelectedListener(this);
+ mConfigUi.setSubmitButton(context.getString(R.string.wifi_save));
+ } else {
+ mConfigUi.setTitle(mAccessPoint.ssid);
+ ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
+
+ DetailedState state = mAccessPoint.getState();
+ if (state != null) {
+ addRow(group, R.string.wifi_status, Summary.get(mConfigUi.getContext(), state));
+ }
+
+ String[] type = resources.getStringArray(R.array.wifi_security);
+ addRow(group, R.string.wifi_security, type[mAccessPoint.security]);
+
+ int level = mAccessPoint.getLevel();
+ if (level != -1) {
+ String[] signal = resources.getStringArray(R.array.wifi_signal);
+ addRow(group, R.string.wifi_signal, signal[level]);
+ }
+
+ WifiInfo info = mAccessPoint.getInfo();
+ if (info != null) {
+ addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
+ // TODO: fix the ip address for IPv6.
+ int address = info.getIpAddress();
+ if (address != 0) {
+ addRow(group, R.string.wifi_ip_address, Formatter.formatIpAddress(address));
+ }
+ }
+
+ /* Show network setup options only for a new network */
+ if (mAccessPoint.networkId == INVALID_NETWORK_ID && mAccessPoint.wpsAvailable) {
+ showNetworkSetupFields();
+ }
+
+ if (mAccessPoint.networkId == INVALID_NETWORK_ID || mEdit) {
+ showSecurityFields();
+ showIpConfigFields();
+ }
+
+ if (mEdit) {
+ mConfigUi.setSubmitButton(context.getString(R.string.wifi_save));
+ } else {
+ if (state == null && level != -1) {
+ mConfigUi.setSubmitButton(context.getString(R.string.wifi_connect));
+ } else {
+ mView.findViewById(R.id.ip_fields).setVisibility(View.GONE);
+ }
+ if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
+ mConfigUi.setForgetButton(context.getString(R.string.wifi_forget));
+ }
+ }
+ }
+
+ if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
+ WifiConfiguration config = mAccessPoint.getConfig();
+ if (config.ipAssignment == IpAssignment.STATIC) {
+ mIpSettingsSpinner.setSelection(STATIC_IP);
+ }
+ }
+
+ mConfigUi.setCancelButton(context.getString(R.string.wifi_cancel));
+ if (mConfigUi.getSubmitButton() != null) {
+ enableSubmitIfAppropriate();
+ }
+ }
+
+ private void addRow(ViewGroup group, int name, String value) {
+ View row = mConfigUi.getLayoutInflater().inflate(R.layout.wifi_dialog_row, group, false);
+ ((TextView) row.findViewById(R.id.name)).setText(name);
+ ((TextView) row.findViewById(R.id.value)).setText(value);
+ group.addView(row);
+ }
+
+ /* show submit button if the password is valid */
+ private void enableSubmitIfAppropriate() {
+ if ((mSsidView != null && mSsidView.length() == 0) ||
+ ((mAccessPoint == null || mAccessPoint.networkId == INVALID_NETWORK_ID) &&
+ ((mAccessPointSecurity == AccessPoint.SECURITY_WEP && mPasswordView.length() == 0) ||
+ (mAccessPointSecurity == AccessPoint.SECURITY_PSK && mPasswordView.length() < 8)))) {
+ mConfigUi.getSubmitButton().setEnabled(false);
+ } else {
+ mConfigUi.getSubmitButton().setEnabled(true);
+ }
+ }
+
+ /* package */ WifiConfiguration getConfig() {
+ if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID && !mEdit) {
+ return null;
+ }
+
+ WifiConfiguration config = new WifiConfiguration();
+
+ if (mAccessPoint == null) {
+ config.SSID = AccessPoint.convertToQuotedString(
+ mSsidView.getText().toString());
+ // If the user adds a network manually, assume that it is hidden.
+ config.hiddenSSID = true;
+ } else if (mAccessPoint.networkId == INVALID_NETWORK_ID) {
+ config.SSID = AccessPoint.convertToQuotedString(
+ mAccessPoint.ssid);
+ } else {
+ config.networkId = mAccessPoint.networkId;
+ }
+
+ switch (mAccessPointSecurity) {
+ case AccessPoint.SECURITY_NONE:
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ break;
+
+ case AccessPoint.SECURITY_WEP:
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
+ config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
+ if (mPasswordView.length() != 0) {
+ int length = mPasswordView.length();
+ String password = mPasswordView.getText().toString();
+ // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
+ if ((length == 10 || length == 26 || length == 58) &&
+ password.matches("[0-9A-Fa-f]*")) {
+ config.wepKeys[0] = password;
+ } else {
+ config.wepKeys[0] = '"' + password + '"';
+ }
+ }
+ break;
+
+ case AccessPoint.SECURITY_PSK:
+ config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ if (mPasswordView.length() != 0) {
+ String password = mPasswordView.getText().toString();
+ if (password.matches("[0-9A-Fa-f]{64}")) {
+ config.preSharedKey = password;
+ } else {
+ config.preSharedKey = '"' + password + '"';
+ }
+ }
+ break;
+
+ case AccessPoint.SECURITY_EAP:
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ config.eap.setValue((String) mEapMethodSpinner.getSelectedItem());
+
+ config.phase2.setValue((mPhase2Spinner.getSelectedItemPosition() == 0) ? "" :
+ "auth=" + mPhase2Spinner.getSelectedItem());
+ config.ca_cert.setValue((mEapCaCertSpinner.getSelectedItemPosition() == 0) ? "" :
+ KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
+ (String) mEapCaCertSpinner.getSelectedItem());
+ config.client_cert.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
+ "" : KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
+ (String) mEapUserCertSpinner.getSelectedItem());
+ config.private_key.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
+ "" : KEYSTORE_SPACE + Credentials.USER_PRIVATE_KEY +
+ (String) mEapUserCertSpinner.getSelectedItem());
+ config.identity.setValue((mEapIdentityView.length() == 0) ? "" :
+ mEapIdentityView.getText().toString());
+ config.anonymous_identity.setValue((mEapAnonymousView.length() == 0) ? "" :
+ mEapAnonymousView.getText().toString());
+ if (mPasswordView.length() != 0) {
+ config.password.setValue(mPasswordView.getText().toString());
+ }
+ break;
+
+ default:
+ return null;
+ }
+
+ config.ipAssignment = (mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
+ IpAssignment.STATIC : IpAssignment.DHCP;
+
+ if (config.ipAssignment == IpAssignment.STATIC) {
+ //TODO: A better way to do this is to not dismiss the
+ //dialog as long as one of the fields is invalid
+ try {
+ config.ipConfig.ipAddress = stringToIpAddr(mIpAddressView.getText().toString());
+ config.ipConfig.gateway = stringToIpAddr(mGatewayView.getText().toString());
+ config.ipConfig.netmask = stringToIpAddr(mNetmaskView.getText().toString());
+ config.ipConfig.dns1 = stringToIpAddr(mDns1View.getText().toString());
+ if (mDns2View.getText() != null && mDns2View.getText().length() > 0) {
+ config.ipConfig.dns2 = stringToIpAddr(mDns2View.getText().toString());
+ }
+ } catch (UnknownHostException e) {
+ Toast.makeText(mConfigUi.getContext(), R.string.wifi_ip_settings_invalid_ip,
+ Toast.LENGTH_LONG).show();
+ return null;
+ }
+ }
+
+ return config;
+ }
+
+ int chosenNetworkSetupMethod() {
+ if (mNetworkSetupSpinner != null) {
+ return mNetworkSetupSpinner.getSelectedItemPosition();
+ }
+ return MANUAL;
+ }
+
+ int getWpsPin() {
+ try {
+ String wpsPin = ((TextView) mView.findViewById(R.id.wps_pin)).getText().toString();
+ return Integer.parseInt(wpsPin);
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+
+ private void showSecurityFields() {
+ if (mAccessPointSecurity == AccessPoint.SECURITY_NONE) {
+ mView.findViewById(R.id.security_fields).setVisibility(View.GONE);
+ return;
+ }
+ mView.findViewById(R.id.security_fields).setVisibility(View.VISIBLE);
+
+ if (mPasswordView == null) {
+ mPasswordView = (TextView) mView.findViewById(R.id.password);
+ mPasswordView.addTextChangedListener(this);
+ ((CheckBox) mView.findViewById(R.id.show_password)).setOnClickListener(this);
+
+ if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
+ mPasswordView.setHint(R.string.wifi_unchanged);
+ }
+ }
+
+ if (mAccessPointSecurity != AccessPoint.SECURITY_EAP) {
+ mView.findViewById(R.id.eap).setVisibility(View.GONE);
+ return;
+ }
+ mView.findViewById(R.id.eap).setVisibility(View.VISIBLE);
+
+ if (mEapMethodSpinner == null) {
+ mEapMethodSpinner = (Spinner) mView.findViewById(R.id.method);
+ mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2);
+ mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert);
+ mEapUserCertSpinner = (Spinner) mView.findViewById(R.id.user_cert);
+ mEapIdentityView = (TextView) mView.findViewById(R.id.identity);
+ mEapAnonymousView = (TextView) mView.findViewById(R.id.anonymous);
+
+ loadCertificates(mEapCaCertSpinner, Credentials.CA_CERTIFICATE);
+ loadCertificates(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY);
+
+ if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
+ WifiConfiguration config = mAccessPoint.getConfig();
+ setSelection(mEapMethodSpinner, config.eap.value());
+ setSelection(mPhase2Spinner, config.phase2.value());
+ setCertificate(mEapCaCertSpinner, Credentials.CA_CERTIFICATE,
+ config.ca_cert.value());
+ setCertificate(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY,
+ config.private_key.value());
+ mEapIdentityView.setText(config.identity.value());
+ mEapAnonymousView.setText(config.anonymous_identity.value());
+ }
+ }
+ }
+
+ private void showNetworkSetupFields() {
+ mView.findViewById(R.id.setup_fields).setVisibility(View.VISIBLE);
+
+ if (mNetworkSetupSpinner == null) {
+ mNetworkSetupSpinner = (Spinner) mView.findViewById(R.id.network_setup);
+ mNetworkSetupSpinner.setOnItemSelectedListener(this);
+ }
+
+ int pos = mNetworkSetupSpinner.getSelectedItemPosition();
+
+ /* Show pin text input if needed */
+ if (pos == WPS_PIN) {
+ mView.findViewById(R.id.wps_fields).setVisibility(View.VISIBLE);
+ } else {
+ mView.findViewById(R.id.wps_fields).setVisibility(View.GONE);
+ }
+
+ /* show/hide manual security fields appropriately */
+ if ((pos == WPS_PIN) || (pos == WPS_PBC)) {
+ mView.findViewById(R.id.security_fields).setVisibility(View.GONE);
+ } else {
+ mView.findViewById(R.id.security_fields).setVisibility(View.VISIBLE);
+ }
+
+ }
+
+ private void showIpConfigFields() {
+ WifiConfiguration config = null;
+
+ mView.findViewById(R.id.ip_fields).setVisibility(View.VISIBLE);
+
+ if (mIpSettingsSpinner == null) {
+ mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings);
+ mIpSettingsSpinner.setOnItemSelectedListener(this);
+ }
+
+ if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
+ config = mAccessPoint.getConfig();
+ }
+
+ if (mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) {
+ mView.findViewById(R.id.staticip).setVisibility(View.VISIBLE);
+ if (mIpAddressView == null) {
+ mIpAddressView = (TextView) mView.findViewById(R.id.ipaddress);
+ mGatewayView = (TextView) mView.findViewById(R.id.gateway);
+ mNetmaskView = (TextView) mView.findViewById(R.id.netmask);
+ mDns1View = (TextView) mView.findViewById(R.id.dns1);
+ mDns2View = (TextView) mView.findViewById(R.id.dns2);
+ }
+ if (config != null) {
+ DhcpInfo ipConfig = config.ipConfig;
+ if (ipConfig != null && ipConfig.ipAddress != 0) {
+ mIpAddressView.setText(intToIpString(ipConfig.ipAddress));
+ mGatewayView.setText(intToIpString(ipConfig.gateway));
+ mNetmaskView.setText(intToIpString(ipConfig.netmask));
+ mDns1View.setText(intToIpString(ipConfig.dns1));
+ mDns2View.setText(intToIpString(ipConfig.dns2));
+ }
+ }
+ } else {
+ mView.findViewById(R.id.staticip).setVisibility(View.GONE);
+ }
+ }
+
+
+ private void loadCertificates(Spinner spinner, String prefix) {
+ final Context context = mConfigUi.getContext();
+ final String unspecified = context.getString(R.string.wifi_unspecified);
+
+ String[] certs = KeyStore.getInstance().saw(prefix);
+ if (certs == null || certs.length == 0) {
+ certs = new String[] {unspecified};
+ } else {
+ final String[] array = new String[certs.length + 1];
+ array[0] = unspecified;
+ System.arraycopy(certs, 0, array, 1, certs.length);
+ certs = array;
+ }
+
+ final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+ context, android.R.layout.simple_spinner_item, certs);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spinner.setAdapter(adapter);
+ }
+
+ private void setCertificate(Spinner spinner, String prefix, String cert) {
+ prefix = KEYSTORE_SPACE + prefix;
+ if (cert != null && cert.startsWith(prefix)) {
+ setSelection(spinner, cert.substring(prefix.length()));
+ }
+ }
+
+ private void setSelection(Spinner spinner, String value) {
+ if (value != null) {
+ ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
+ for (int i = adapter.getCount() - 1; i >= 0; --i) {
+ if (value.equals(adapter.getItem(i))) {
+ spinner.setSelection(i);
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ enableSubmitIfAppropriate();
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void onClick(View view) {
+ mPasswordView.setInputType(
+ InputType.TYPE_CLASS_TEXT | (((CheckBox) view).isChecked() ?
+ InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
+ InputType.TYPE_TEXT_VARIATION_PASSWORD));
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ if (parent == mSecuritySpinner) {
+ mAccessPointSecurity = position;
+ showSecurityFields();
+ enableSubmitIfAppropriate();
+ } else if (parent == mNetworkSetupSpinner){
+ showNetworkSetupFields();
+ } else {
+ showIpConfigFields();
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+
+ /* TODO: should go away when we move to IPv6 based config storage */
+ private static int stringToIpAddr(String addrString) throws UnknownHostException {
+ try {
+ String[] parts = addrString.split("\\.");
+ if (parts.length != 4) {
+ throw new UnknownHostException(addrString);
+ }
+
+ int a = Integer.parseInt(parts[0]);
+ int b = Integer.parseInt(parts[1]) << 8;
+ int c = Integer.parseInt(parts[2]) << 16;
+ int d = Integer.parseInt(parts[3]) << 24;
+
+ return a | b | c | d;
+ } catch (NumberFormatException e) {
+ throw new UnknownHostException(addrString);
+ }
+ }
+
+ private static String intToIpString(int i) {
+ return (i & 0xFF) + "." + ((i >> 8 ) & 0xFF) + "." +((i >> 16 ) & 0xFF) + "." +
+ ((i >> 24 ) & 0xFF);
+ }
+
+}
diff --git a/src/com/android/settings/wifi/WifiConfigPreference.java b/src/com/android/settings/wifi/WifiConfigPreference.java
new file mode 100644
index 000000000..5a0982771
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiConfigPreference.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.preference.Preference;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+/**
+ * Preference letting users modify a setting for Wifi network. This work as an alternative UI
+ * for {@link WifiDialog} without shouwing popup Dialog.
+ */
+public class WifiConfigPreference extends Preference implements WifiConfigUiBase {
+ private WifiSettings mWifiSettings;
+ private View mView;
+ private final DialogInterface.OnClickListener mListener;
+ private WifiConfigController mController;
+ private AccessPoint mAccessPoint;
+ private boolean mEdit;
+
+ private LayoutInflater mInflater;
+
+ public WifiConfigPreference(WifiSettings wifiSettings,
+ DialogInterface.OnClickListener listener,
+ AccessPoint accessPoint, boolean edit) {
+ super(wifiSettings.getActivity());
+ mWifiSettings = wifiSettings;
+ setLayoutResource(R.layout.wifi_config_preference);
+ mListener = listener;
+ mAccessPoint = accessPoint;
+ mEdit = edit;
+ mInflater = (LayoutInflater)
+ wifiSettings.getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ @Override
+ protected View onCreateView(ViewGroup parent) {
+ // Called every time the list is created.
+ if (mView != null) {
+ // TODO: we need to re-forcus something.
+ return mView;
+ }
+ mView = mInflater.inflate(getLayoutResource(), parent, false);
+ mController = new WifiConfigController(this, mView, mAccessPoint, mEdit, mListener);
+ return mView;
+ }
+
+ @Override
+ public WifiConfigController getController() {
+ return mController;
+ }
+
+ public View findViewById(int id) {
+ return mView.findViewById(id);
+ }
+
+ public AccessPoint getAccessPoint() {
+ return mAccessPoint;
+ }
+
+ @Override
+ public boolean isEdit() {
+ return mEdit;
+ }
+
+ @Override
+ public LayoutInflater getLayoutInflater() {
+ return mInflater;
+ }
+
+ @Override
+ public Button getSubmitButton() {
+ return (Button)mWifiSettings.getActivity().findViewById(R.id.wifi_setup_connect);
+ }
+
+ @Override
+ public Button getForgetButton() {
+ return (Button)mWifiSettings.getActivity().findViewById(R.id.wifi_setup_forget);
+ }
+
+ @Override
+ public Button getCancelButton() {
+ return (Button)mWifiSettings.getActivity().findViewById(R.id.wifi_setup_cancel);
+ }
+
+ @Override
+ public void setSubmitButton(CharSequence text) {
+ final Button button = (Button)
+ mWifiSettings.getActivity().findViewById(R.id.wifi_setup_connect);
+ button.setVisibility(View.VISIBLE);
+
+ // test
+ mWifiSettings.getActivity().findViewById(R.id.wifi_setup_forget).setVisibility(View.GONE);
+ }
+
+ @Override
+ public void setForgetButton(CharSequence text) {
+ final Button button = (Button)
+ mWifiSettings.getActivity().findViewById(R.id.wifi_setup_forget);
+ button.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void setCancelButton(CharSequence text) {
+ final Button button = (Button)
+ mWifiSettings.getActivity().findViewById(R.id.wifi_setup_cancel);
+ button.setVisibility(View.VISIBLE);
+ }
+} \ No newline at end of file
diff --git a/src/com/android/settings/wifi/WifiConfigUiBase.java b/src/com/android/settings/wifi/WifiConfigUiBase.java
new file mode 100644
index 000000000..e17d49103
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiConfigUiBase.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.widget.Button;
+
+/**
+ * Foundation interface glues between Activities and UIs like
+ * {@link WifiDialog} or {@link WifiConfigController}.
+ */
+public interface WifiConfigUiBase {
+ public Context getContext();
+ public WifiConfigController getController();
+ public LayoutInflater getLayoutInflater();
+ public boolean isEdit();
+
+ public void setTitle(int id);
+ public void setTitle(CharSequence title);
+
+ public void setSubmitButton(CharSequence text);
+ public void setForgetButton(CharSequence text);
+ public void setCancelButton(CharSequence text);
+ public Button getSubmitButton();
+ public Button getForgetButton();
+ public Button getCancelButton();
+} \ No newline at end of file
diff --git a/src/com/android/settings/wifi/WifiDialog.java b/src/com/android/settings/wifi/WifiDialog.java
index a8bf717ca..b6356159d 100644
--- a/src/com/android/settings/wifi/WifiDialog.java
+++ b/src/com/android/settings/wifi/WifiDialog.java
@@ -21,149 +21,32 @@ import com.android.settings.R;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.net.NetworkInfo.DetailedState;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.AuthAlgorithm;
-import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiInfo;
import android.os.Bundle;
-import android.security.Credentials;
-import android.security.KeyStore;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.format.Formatter;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.CheckBox;
-import android.widget.Spinner;
-import android.widget.TextView;
-
-class WifiDialog extends AlertDialog implements View.OnClickListener,
- TextWatcher, AdapterView.OnItemSelectedListener {
- private static final String KEYSTORE_SPACE = "keystore://";
+import android.widget.Button;
+class WifiDialog extends AlertDialog implements WifiConfigUiBase {
static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE;
static final int BUTTON_FORGET = DialogInterface.BUTTON_NEUTRAL;
- final boolean edit;
+ private final boolean mEdit;
private final DialogInterface.OnClickListener mListener;
private final AccessPoint mAccessPoint;
private View mView;
- private TextView mSsid;
- private int mSecurity;
- private TextView mPassword;
-
- private Spinner mEapMethod;
- private Spinner mEapCaCert;
- private Spinner mPhase2;
- private Spinner mEapUserCert;
- private TextView mEapIdentity;
- private TextView mEapAnonymous;
-
- static boolean requireKeyStore(WifiConfiguration config) {
- String values[] = {config.ca_cert.value(), config.client_cert.value(),
- config.private_key.value()};
- for (String value : values) {
- if (value != null && value.startsWith(KEYSTORE_SPACE)) {
- return true;
- }
- }
- return false;
- }
+ private WifiConfigController mController;
- WifiDialog(Context context, DialogInterface.OnClickListener listener,
+ public WifiDialog(Context context, DialogInterface.OnClickListener listener,
AccessPoint accessPoint, boolean edit) {
super(context);
- this.edit = edit;
+ mEdit = edit;
mListener = listener;
mAccessPoint = accessPoint;
- mSecurity = (accessPoint == null) ? AccessPoint.SECURITY_NONE : accessPoint.security;
}
- WifiConfiguration getConfig() {
- if (mAccessPoint != null && mAccessPoint.networkId != -1 && !edit) {
- return null;
- }
-
- WifiConfiguration config = new WifiConfiguration();
-
- if (mAccessPoint == null) {
- config.SSID = AccessPoint.convertToQuotedString(
- mSsid.getText().toString());
- // If the user adds a network manually, assume that it is hidden.
- config.hiddenSSID = true;
- } else if (mAccessPoint.networkId == -1) {
- config.SSID = AccessPoint.convertToQuotedString(
- mAccessPoint.ssid);
- } else {
- config.networkId = mAccessPoint.networkId;
- }
-
- switch (mSecurity) {
- case AccessPoint.SECURITY_NONE:
- config.allowedKeyManagement.set(KeyMgmt.NONE);
- return config;
-
- case AccessPoint.SECURITY_WEP:
- config.allowedKeyManagement.set(KeyMgmt.NONE);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
- config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
- if (mPassword.length() != 0) {
- int length = mPassword.length();
- String password = mPassword.getText().toString();
- // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
- if ((length == 10 || length == 26 || length == 58) &&
- password.matches("[0-9A-Fa-f]*")) {
- config.wepKeys[0] = password;
- } else {
- config.wepKeys[0] = '"' + password + '"';
- }
- }
- return config;
-
- case AccessPoint.SECURITY_PSK:
- config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
- if (mPassword.length() != 0) {
- String password = mPassword.getText().toString();
- if (password.matches("[0-9A-Fa-f]{64}")) {
- config.preSharedKey = password;
- } else {
- config.preSharedKey = '"' + password + '"';
- }
- }
- return config;
-
- case AccessPoint.SECURITY_EAP:
- config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
- config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
- config.eap.setValue((String) mEapMethod.getSelectedItem());
-
- config.phase2.setValue((mPhase2.getSelectedItemPosition() == 0) ? "" :
- "auth=" + mPhase2.getSelectedItem());
- config.ca_cert.setValue((mEapCaCert.getSelectedItemPosition() == 0) ? "" :
- KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
- (String) mEapCaCert.getSelectedItem());
- config.client_cert.setValue((mEapUserCert.getSelectedItemPosition() == 0) ? "" :
- KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
- (String) mEapUserCert.getSelectedItem());
- config.private_key.setValue((mEapUserCert.getSelectedItemPosition() == 0) ? "" :
- KEYSTORE_SPACE + Credentials.USER_PRIVATE_KEY +
- (String) mEapUserCert.getSelectedItem());
- config.identity.setValue((mEapIdentity.length() == 0) ? "" :
- mEapIdentity.getText().toString());
- config.anonymous_identity.setValue((mEapAnonymous.length() == 0) ? "" :
- mEapAnonymous.getText().toString());
- if (mPassword.length() != 0) {
- config.password.setValue(mPassword.getText().toString());
- }
- return config;
- }
- return null;
+ @Override
+ public WifiConfigController getController() {
+ return mController;
}
@Override
@@ -171,200 +54,42 @@ class WifiDialog extends AlertDialog implements View.OnClickListener,
mView = getLayoutInflater().inflate(R.layout.wifi_dialog, null);
setView(mView);
setInverseBackgroundForced(true);
-
- Context context = getContext();
- Resources resources = context.getResources();
-
- if (mAccessPoint == null) {
- setTitle(R.string.wifi_add_network);
- mView.findViewById(R.id.type).setVisibility(View.VISIBLE);
- mSsid = (TextView) mView.findViewById(R.id.ssid);
- mSsid.addTextChangedListener(this);
- ((Spinner) mView.findViewById(R.id.security)).setOnItemSelectedListener(this);
- setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
- } else {
- setTitle(mAccessPoint.ssid);
- ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
-
- DetailedState state = mAccessPoint.getState();
- if (state != null) {
- addRow(group, R.string.wifi_status, Summary.get(getContext(), state));
- }
-
- String[] type = resources.getStringArray(R.array.wifi_security);
- addRow(group, R.string.wifi_security, type[mAccessPoint.security]);
-
- int level = mAccessPoint.getLevel();
- if (level != -1) {
- String[] signal = resources.getStringArray(R.array.wifi_signal);
- addRow(group, R.string.wifi_signal, signal[level]);
- }
-
- WifiInfo info = mAccessPoint.getInfo();
- if (info != null) {
- addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
- // TODO: fix the ip address for IPv6.
- int address = info.getIpAddress();
- if (address != 0) {
- addRow(group, R.string.wifi_ip_address, Formatter.formatIpAddress(address));
- }
- }
-
- if (mAccessPoint.networkId == -1 || edit) {
- showSecurityFields();
- }
-
- if (edit) {
- setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
- } else {
- if (state == null && level != -1) {
- setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_connect), mListener);
- }
- if (mAccessPoint.networkId != -1) {
- setButton(BUTTON_FORGET, context.getString(R.string.wifi_forget), mListener);
- }
- }
- }
-
- setButton(DialogInterface.BUTTON_NEGATIVE,
- context.getString(R.string.wifi_cancel), mListener);
-
+ mController = new WifiConfigController(this, mView, mAccessPoint, mEdit, mListener);
super.onCreate(savedInstanceState);
-
- if (getButton(BUTTON_SUBMIT) != null) {
- validate();
- }
}
- private void addRow(ViewGroup group, int name, String value) {
- View row = getLayoutInflater().inflate(R.layout.wifi_dialog_row, group, false);
- ((TextView) row.findViewById(R.id.name)).setText(name);
- ((TextView) row.findViewById(R.id.value)).setText(value);
- group.addView(row);
- }
-
- private void validate() {
- // TODO: make sure this is complete.
- if ((mSsid != null && mSsid.length() == 0) ||
- ((mAccessPoint == null || mAccessPoint.networkId == -1) &&
- ((mSecurity == AccessPoint.SECURITY_WEP && mPassword.length() == 0) ||
- (mSecurity == AccessPoint.SECURITY_PSK && mPassword.length() < 8)))) {
- getButton(BUTTON_SUBMIT).setEnabled(false);
- } else {
- getButton(BUTTON_SUBMIT).setEnabled(true);
- }
- }
-
- public void onClick(View view) {
- mPassword.setInputType(
- InputType.TYPE_CLASS_TEXT | (((CheckBox) view).isChecked() ?
- InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
- InputType.TYPE_TEXT_VARIATION_PASSWORD));
- }
-
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- public void afterTextChanged(Editable editable) {
- validate();
+ @Override
+ public boolean isEdit() {
+ return mEdit;
}
- public void onItemSelected(AdapterView parent, View view, int position, long id) {
- mSecurity = position;
- showSecurityFields();
- validate();
+ @Override
+ public Button getSubmitButton() {
+ return getButton(BUTTON_SUBMIT);
}
- public void onNothingSelected(AdapterView parent) {
+ @Override
+ public Button getForgetButton() {
+ return getButton(BUTTON_FORGET);
}
- private void showSecurityFields() {
- if (mSecurity == AccessPoint.SECURITY_NONE) {
- mView.findViewById(R.id.fields).setVisibility(View.GONE);
- return;
- }
- mView.findViewById(R.id.fields).setVisibility(View.VISIBLE);
-
- if (mPassword == null) {
- mPassword = (TextView) mView.findViewById(R.id.password);
- mPassword.addTextChangedListener(this);
- ((CheckBox) mView.findViewById(R.id.show_password)).setOnClickListener(this);
-
- if (mAccessPoint != null && mAccessPoint.networkId != -1) {
- mPassword.setHint(R.string.wifi_unchanged);
- }
- }
-
- if (mSecurity != AccessPoint.SECURITY_EAP) {
- mView.findViewById(R.id.eap).setVisibility(View.GONE);
- return;
- }
- mView.findViewById(R.id.eap).setVisibility(View.VISIBLE);
-
- if (mEapMethod == null) {
- mEapMethod = (Spinner) mView.findViewById(R.id.method);
- mPhase2 = (Spinner) mView.findViewById(R.id.phase2);
- mEapCaCert = (Spinner) mView.findViewById(R.id.ca_cert);
- mEapUserCert = (Spinner) mView.findViewById(R.id.user_cert);
- mEapIdentity = (TextView) mView.findViewById(R.id.identity);
- mEapAnonymous = (TextView) mView.findViewById(R.id.anonymous);
-
- loadCertificates(mEapCaCert, Credentials.CA_CERTIFICATE);
- loadCertificates(mEapUserCert, Credentials.USER_PRIVATE_KEY);
-
- if (mAccessPoint != null && mAccessPoint.networkId != -1) {
- WifiConfiguration config = mAccessPoint.getConfig();
- setSelection(mEapMethod, config.eap.value());
- setSelection(mPhase2, config.phase2.value());
- setCertificate(mEapCaCert, Credentials.CA_CERTIFICATE,
- config.ca_cert.value());
- setCertificate(mEapUserCert, Credentials.USER_PRIVATE_KEY,
- config.private_key.value());
- mEapIdentity.setText(config.identity.value());
- mEapAnonymous.setText(config.anonymous_identity.value());
- }
- }
+ @Override
+ public Button getCancelButton() {
+ return getButton(BUTTON_NEGATIVE);
}
- private void loadCertificates(Spinner spinner, String prefix) {
- String[] certs = KeyStore.getInstance().saw(prefix);
- Context context = getContext();
- String unspecified = context.getString(R.string.wifi_unspecified);
-
- if (certs == null || certs.length == 0) {
- certs = new String[] {unspecified};
- } else {
- String[] array = new String[certs.length + 1];
- array[0] = unspecified;
- System.arraycopy(certs, 0, array, 1, certs.length);
- certs = array;
- }
-
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(
- context, android.R.layout.simple_spinner_item, certs);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinner.setAdapter(adapter);
+ @Override
+ public void setSubmitButton(CharSequence text) {
+ setButton(BUTTON_SUBMIT, text, mListener);
}
- private void setCertificate(Spinner spinner, String prefix, String cert) {
- prefix = KEYSTORE_SPACE + prefix;
- if (cert != null && cert.startsWith(prefix)) {
- setSelection(spinner, cert.substring(prefix.length()));
- }
+ @Override
+ public void setForgetButton(CharSequence text) {
+ setButton(BUTTON_FORGET, text, mListener);
}
- private void setSelection(Spinner spinner, String value) {
- if (value != null) {
- ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
- for (int i = adapter.getCount() - 1; i >= 0; --i) {
- if (value.equals(adapter.getItem(i))) {
- spinner.setSelection(i);
- break;
- }
- }
- }
+ @Override
+ public void setCancelButton(CharSequence text) {
+ setButton(BUTTON_NEGATIVE, text, mListener);
}
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index d389cae14..a0b2132c2 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -16,21 +16,24 @@
package com.android.settings.wifi;
-import com.android.settings.ProgressCategory;
+import com.android.settings.ProgressCategoryBase;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
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;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
-import android.net.wifi.WifiConfiguration.Status;
+import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -38,30 +41,58 @@ import android.os.Handler;
import android.os.Message;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings.Secure;
import android.security.Credentials;
import android.security.KeyStore;
-import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.Button;
import android.widget.Toast;
-import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
+import java.util.TreeSet;
-public class WifiSettings extends PreferenceActivity implements DialogInterface.OnClickListener {
+/**
+ * This currently provides three types of UI.
+ *
+ * Two are for phones with relatively small screens: "for SetupWizard" and "for usual Settings".
+ * Users just need to launch WifiSettings Activity as usual. The request will be appropriately
+ * handled by ActivityManager, and they will have appropriate look-and-feel with this fragment.
+ *
+ * Third type is for Setup Wizard with X-Large, landscape UI. Users need to launch
+ * {@link WifiSettingsForSetupWizardXL} Activity, which contains this fragment but also has
+ * other decorations specific to that screen.
+ */
+public class WifiSettings extends SettingsPreferenceFragment
+ implements DialogInterface.OnClickListener {
private static final int MENU_ID_SCAN = Menu.FIRST;
private static final int MENU_ID_ADVANCED = Menu.FIRST + 1;
private static final int MENU_ID_CONNECT = Menu.FIRST + 2;
private static final int MENU_ID_FORGET = Menu.FIRST + 3;
private static final int MENU_ID_MODIFY = Menu.FIRST + 4;
+ // Indicates that this fragment is used as a part of Setup Wizard with XL screen settings.
+ // This fragment should show information which has been shown as Dialog in combined UI
+ // inside this fragment.
+ /* package */ static final String IN_XL_SETUP_WIZARD = "in_setup_wizard";
+
+ // this boolean extra specifies whether to disable the Next button when not connected
+ // Note: this is only effective in Setup Wizard with XL screen size.
+ private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect";
+
+ // In SetupWizard XL, We limit the number of showable access points so that the
+ // ListView won't become larger than the screen.
+ //
+ // This constant doesn't affect other contexts other than SetupWizard XL.
+ private static int MAX_MENU_COUNT_IN_XL = 7;
+
private final IntentFilter mFilter;
private final BroadcastReceiver mReceiver;
private final Scanner mScanner;
@@ -69,25 +100,38 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
private WifiManager mWifiManager;
private WifiEnabler mWifiEnabler;
private CheckBoxPreference mNotifyOpenNetworks;
- private ProgressCategory mAccessPoints;
+ private ProgressCategoryBase mAccessPoints;
private Preference mAddNetwork;
+ // An access point being editted is stored here.
+ private AccessPoint mSelectedAccessPoint;
private DetailedState mLastState;
private WifiInfo mLastInfo;
- private int mLastPriority;
- private boolean mResetNetworks = false;
- private int mKeyStoreNetworkId = -1;
+ private int mKeyStoreNetworkId = INVALID_NETWORK_ID;
+
+ // should Next button only be enabled when we have a connection?
+ private boolean mEnableNextOnConnection;
+ private boolean mInXlSetupWizard;
- private AccessPoint mSelected;
+
+ // TODO: merge into one
+ private WifiConfigPreference mConfigPreference;
private WifiDialog mDialog;
+ // Used only in SetupWizard XL, which remembers the network a user selected and
+ // refrain other available networks when trying to connect it.
+ private AccessPoint mConnectingAccessPoint;
+
+ private boolean mRefrainListUpdate;
+
public WifiSettings() {
mFilter = new IntentFilter();
mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
+ mFilter.addAction(WifiManager.SUPPLICANT_CONFIG_CHANGED_ACTION);
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
@@ -102,16 +146,40 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
}
@Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ public void onActivityCreated(Bundle savedInstanceState) {
+ // We don't call super.onActivityCreated() here, since it assumes we already set up
+ // Preference (probably in onCreate()), while WifiSettings exceptionally set it up in
+ // this method.
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
- if (getIntent().getBooleanExtra("only_access_points", false)) {
+ final Activity activity = getActivity();
+ final Intent intent = activity.getIntent();
+
+ mInXlSetupWizard = intent.getBooleanExtra(IN_XL_SETUP_WIZARD, false);
+
+ // if we're supposed to enable/disable the Next button based on our current connection
+ // state, start it off in the right state
+ mEnableNextOnConnection = intent.getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false);
+
+ if (mEnableNextOnConnection) {
+ if (mEnableNextOnConnection && hasNextButton()) {
+ final ConnectivityManager connectivity = (ConnectivityManager)
+ getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivity != null) {
+ NetworkInfo info = connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
+ changeNextButtonState(info.isConnected());
+ }
+ }
+ }
+
+ if (mInXlSetupWizard) {
+ addPreferencesFromResource(R.xml.wifi_access_points_for_wifi_setup_xl);
+ } else if (intent.getBooleanExtra("only_access_points", false)) {
addPreferencesFromResource(R.xml.wifi_access_points);
} else {
addPreferencesFromResource(R.xml.wifi_settings);
- mWifiEnabler = new WifiEnabler(this,
+ mWifiEnabler = new WifiEnabler(activity,
(CheckBoxPreference) findPreference("enable_wifi"));
mNotifyOpenNetworks =
(CheckBoxPreference) findPreference("notify_open_networks");
@@ -119,50 +187,85 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
}
- mAccessPoints = (ProgressCategory) findPreference("access_points");
- mAccessPoints.setOrderingAsAdded(false);
+ // After confirming PreferenceScreen is available, we call super.
+ super.onActivityCreated(savedInstanceState);
+
+ // This may be either ProgressCategory or AccessPointCategoryForXL.
+ final ProgressCategoryBase preference =
+ (ProgressCategoryBase) findPreference("access_points");
+ mAccessPoints = preference;
+ mAccessPoints.setOrderingAsAdded(true);
mAddNetwork = findPreference("add_network");
registerForContextMenu(getListView());
+ setHasOptionsMenu(true);
}
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
if (mWifiEnabler != null) {
mWifiEnabler.resume();
}
- registerReceiver(mReceiver, mFilter);
- if (mKeyStoreNetworkId != -1 && KeyStore.getInstance().test() == KeyStore.NO_ERROR) {
- connect(mKeyStoreNetworkId);
+ getActivity().registerReceiver(mReceiver, mFilter);
+ if (mKeyStoreNetworkId != INVALID_NETWORK_ID &&
+ KeyStore.getInstance().test() == KeyStore.NO_ERROR) {
+ mWifiManager.connectNetwork(mKeyStoreNetworkId);
+ }
+ mKeyStoreNetworkId = INVALID_NETWORK_ID;
+ if (mInXlSetupWizard) {
+ // We show "Now scanning"
+ final int wifiState = mWifiManager.getWifiState();
+ switch (wifiState) {
+ case WifiManager.WIFI_STATE_ENABLED: {
+ updateAccessPoints();
+ break;
+ }
+ case WifiManager.WIFI_STATE_DISABLED:
+ case WifiManager.WIFI_STATE_DISABLING:
+ case WifiManager.WIFI_STATE_UNKNOWN: {
+ mWifiManager.setWifiEnabled(true);
+ } // $FALL-THROUGH$
+ default: {
+ mAccessPoints.removeAll();
+ Preference preference = new Preference(getActivity());
+ preference.setLayoutResource(R.layout.preference_widget_shortcut);
+ preference.setSelectable(false);
+ preference.setTitle("Connecting");
+ preference.setSummary("COONNECTING");
+ mAccessPoints.addPreference(preference);
+ break;
+ }
+ }
+ } else {
+ updateAccessPoints();
}
- mKeyStoreNetworkId = -1;
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
if (mWifiEnabler != null) {
mWifiEnabler.pause();
}
- unregisterReceiver(mReceiver);
+ getActivity().unregisterReceiver(mReceiver);
mScanner.pause();
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
- if (mResetNetworks) {
- enableNetworks();
- }
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)
- .setIcon(R.drawable.ic_menu_scan_network);
- menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
- .setIcon(android.R.drawable.ic_menu_manage);
- return super.onCreateOptionsMenu(menu);
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ // We don't want menus in Setup Wizard XL.
+ if (!mInXlSetupWizard) {
+ menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)
+ .setIcon(R.drawable.ic_menu_scan_network);
+ menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
+ .setIcon(android.R.drawable.ic_menu_manage);
+ }
+ super.onCreateOptionsMenu(menu, inflater);
}
@Override
@@ -174,7 +277,7 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
}
return true;
case MENU_ID_ADVANCED:
- startActivity(new Intent(this, AdvancedSettings.class));
+ startFragment(this, AdvancedSettings.class.getCanonicalName(), -1, null);
return true;
}
return super.onOptionsItemSelected(item);
@@ -187,16 +290,15 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
((AdapterContextMenuInfo) info).position);
if (preference instanceof AccessPoint) {
- mSelected = (AccessPoint) preference;
- menu.setHeaderTitle(mSelected.ssid);
- if (mSelected.getLevel() != -1 && mSelected.getState() == null) {
+ mSelectedAccessPoint = (AccessPoint) preference;
+ menu.setHeaderTitle(mSelectedAccessPoint.ssid);
+ if (mSelectedAccessPoint.getLevel() != -1
+ && mSelectedAccessPoint.getState() == null) {
menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
}
- if (mSelected.networkId != -1) {
+ if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget);
- if (mSelected.security != AccessPoint.SECURITY_NONE) {
- menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify);
- }
+ menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify);
}
}
}
@@ -204,33 +306,34 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
@Override
public boolean onContextItemSelected(MenuItem item) {
- if (mSelected == null) {
+ if (mSelectedAccessPoint == null) {
return super.onContextItemSelected(item);
}
switch (item.getItemId()) {
- case MENU_ID_CONNECT:
- if (mSelected.networkId != -1) {
- if (!requireKeyStore(mSelected.getConfig())) {
- connect(mSelected.networkId);
+ case MENU_ID_CONNECT: {
+ if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
+ if (!requireKeyStore(mSelectedAccessPoint.getConfig())) {
+ mWifiManager.connectNetwork(mSelectedAccessPoint.networkId);
}
- } else if (mSelected.security == AccessPoint.SECURITY_NONE) {
+ } else if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE) {
// Shortcut for open networks.
WifiConfiguration config = new WifiConfiguration();
- config.SSID = AccessPoint.convertToQuotedString(mSelected.ssid);
+ config.SSID = AccessPoint.convertToQuotedString(mSelectedAccessPoint.ssid);
config.allowedKeyManagement.set(KeyMgmt.NONE);
- int networkId = mWifiManager.addNetwork(config);
- mWifiManager.enableNetwork(networkId, false);
- connect(networkId);
+ mWifiManager.connectNetwork(config);
} else {
- showDialog(mSelected, false);
+ showConfigUi(mSelectedAccessPoint, true);
}
return true;
- case MENU_ID_FORGET:
- forget(mSelected.networkId);
+ }
+ case MENU_ID_FORGET: {
+ mWifiManager.forgetNetwork(mSelectedAccessPoint.networkId);
return true;
- case MENU_ID_MODIFY:
- showDialog(mSelected, true);
+ }
+ case MENU_ID_MODIFY: {
+ showConfigUi(mSelectedAccessPoint, true);
return true;
+ }
}
return super.onContextItemSelected(item);
}
@@ -238,11 +341,10 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (preference instanceof AccessPoint) {
- mSelected = (AccessPoint) preference;
- showDialog(mSelected, false);
+ mSelectedAccessPoint = (AccessPoint) preference;
+ showConfigUi(mSelectedAccessPoint, false);
} else if (preference == mAddNetwork) {
- mSelected = null;
- showDialog(null, true);
+ onAddNetworkPressed();
} else if (preference == mNotifyOpenNetworks) {
Secure.putInt(getContentResolver(),
Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
@@ -253,33 +355,54 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
return true;
}
- public void onClick(DialogInterface dialogInterface, int button) {
- if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {
- forget(mSelected.networkId);
- } else if (button == WifiDialog.BUTTON_SUBMIT && mDialog != null) {
- WifiConfiguration config = mDialog.getConfig();
-
- if (config == null) {
- if (mSelected != null && !requireKeyStore(mSelected.getConfig())) {
- connect(mSelected.networkId);
- }
- } else if (config.networkId != -1) {
- if (mSelected != null) {
- mWifiManager.updateNetwork(config);
- saveNetworks();
- }
- } else {
- int networkId = mWifiManager.addNetwork(config);
- if (networkId != -1) {
- mWifiManager.enableNetwork(networkId, false);
- config.networkId = networkId;
- if (mDialog.edit || requireKeyStore(config)) {
- saveNetworks();
- } else {
- connect(networkId);
- }
- }
- }
+ /**
+ * Called when a user clicks "Add network" preference or relevant button.
+ */
+ private void showConfigUi(AccessPoint accessPoint, boolean edit) {
+ synchronized (this) {
+ mRefrainListUpdate = false;
+ }
+ if (mInXlSetupWizard) {
+ final Activity activity = getActivity();
+ activity.findViewById(R.id.wifi_setup_connect).setVisibility(View.VISIBLE);
+ activity.findViewById(R.id.wifi_setup_cancel).setVisibility(View.VISIBLE);
+ showConfigPreference(accessPoint, edit);
+ } else {
+ showDialog(accessPoint, edit);
+ }
+ }
+
+ private void showConfigPreference(AccessPoint accessPoint, boolean edit) {
+ // We don't want to show more than one WifiConfigPreference
+ if (mConfigPreference != null) {
+ mAccessPoints.removePreference(mConfigPreference);
+ }
+
+ mConfigPreference = new WifiConfigPreference(this, this, accessPoint, edit);
+ toggleButtonsVisibility(false);
+ final Activity activity = getActivity();
+ if (activity instanceof WifiSettingsForSetupWizardXL) {
+ ((WifiSettingsForSetupWizardXL)activity).onWifiConfigPreferenceAttached(edit);
+ }
+ updateAccessPoints();
+ mScanner.pause();
+ }
+
+ private void toggleButtonsVisibility(boolean firstLayout) {
+ final Activity activity = getActivity();
+ if (firstLayout) {
+ activity.findViewById(R.id.wifi_setup_add_network).setVisibility(View.VISIBLE);
+ activity.findViewById(R.id.wifi_setup_refresh_list).setVisibility(View.VISIBLE);
+ activity.findViewById(R.id.wifi_setup_skip_or_next).setVisibility(View.VISIBLE);
+ activity.findViewById(R.id.wifi_setup_connect).setVisibility(View.GONE);
+ activity.findViewById(R.id.wifi_setup_forget).setVisibility(View.GONE);
+ activity.findViewById(R.id.wifi_setup_cancel).setVisibility(View.GONE);
+ } else {
+ activity.findViewById(R.id.wifi_setup_add_network).setVisibility(View.GONE);
+ activity.findViewById(R.id.wifi_setup_refresh_list).setVisibility(View.GONE);
+ activity.findViewById(R.id.wifi_setup_skip_or_next).setVisibility(View.GONE);
+
+ // made visible from controller.
}
}
@@ -287,99 +410,70 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
if (mDialog != null) {
mDialog.dismiss();
}
- mDialog = new WifiDialog(this, this, accessPoint, edit);
+ mDialog = new WifiDialog(getActivity(), this, accessPoint, edit);
mDialog.show();
}
private boolean requireKeyStore(WifiConfiguration config) {
- if (WifiDialog.requireKeyStore(config) &&
+ if (WifiConfigController.requireKeyStore(config) &&
KeyStore.getInstance().test() != KeyStore.NO_ERROR) {
mKeyStoreNetworkId = config.networkId;
- Credentials.getInstance().unlock(this);
+ Credentials.getInstance().unlock(getActivity());
return true;
}
return false;
}
- private void forget(int networkId) {
- mWifiManager.removeNetwork(networkId);
- saveNetworks();
- }
-
- private void connect(int networkId) {
- if (networkId == -1) {
- return;
- }
-
- // Reset the priority of each network if it goes too high.
- if (mLastPriority > 1000000) {
- for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
- AccessPoint accessPoint = (AccessPoint) mAccessPoints.getPreference(i);
- if (accessPoint.networkId != -1) {
- WifiConfiguration config = new WifiConfiguration();
- config.networkId = accessPoint.networkId;
- config.priority = 0;
- mWifiManager.updateNetwork(config);
- }
+ /**
+ * Shows the latest access points available with supplimental information like
+ * the strength of network and the security for it.
+ */
+ private void updateAccessPoints() {
+ synchronized (this) {
+ if (mRefrainListUpdate) {
+ return;
}
- mLastPriority = 0;
}
- // Set to the highest priority and save the configuration.
- WifiConfiguration config = new WifiConfiguration();
- config.networkId = networkId;
- config.priority = ++mLastPriority;
- mWifiManager.updateNetwork(config);
- saveNetworks();
-
- // Connect to network by disabling others.
- mWifiManager.enableNetwork(networkId, true);
- mWifiManager.reconnect();
- mResetNetworks = true;
- }
-
- private void enableNetworks() {
- for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
- WifiConfiguration config = ((AccessPoint) mAccessPoints.getPreference(i)).getConfig();
- if (config != null && config.status != Status.ENABLED) {
- mWifiManager.enableNetwork(config.networkId, false);
+ mAccessPoints.removeAll();
+ if (mConnectingAccessPoint != null) {
+ mAccessPoints.addPreference(mConnectingAccessPoint);
+ } else if (mConfigPreference != null) {
+ final AccessPoint parent = mConfigPreference.getAccessPoint();
+ if (parent != null) {
+ parent.setSelectable(false);
+ mAccessPoints.addPreference(parent);
+ }
+ mAccessPoints.addPreference(mConfigPreference);
+ } else {
+ // AccessPoints are automatically sorted with TreeSet.
+ final Collection<AccessPoint> accessPoints = constructAccessPoints();
+
+ int count = MAX_MENU_COUNT_IN_XL;
+ for (AccessPoint accessPoint : accessPoints) {
+ mAccessPoints.addPreference(accessPoint);
+ count--;
+ if (count <= 0) {
+ break;
+ }
}
}
- mResetNetworks = false;
}
- private void saveNetworks() {
- // Always save the configuration with all networks enabled.
- enableNetworks();
- mWifiManager.saveConfiguration();
- updateAccessPoints();
- }
-
- private void updateAccessPoints() {
- List<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
+ private Collection<AccessPoint> constructAccessPoints() {
+ Collection<AccessPoint> accessPoints =
+ new TreeSet<AccessPoint>(new AccessPoint.Comparater());
- List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
if (configs != null) {
- mLastPriority = 0;
for (WifiConfiguration config : configs) {
- if (config.priority > mLastPriority) {
- mLastPriority = config.priority;
- }
-
- // Shift the status to make enableNetworks() more efficient.
- if (config.status == Status.CURRENT) {
- config.status = Status.ENABLED;
- } else if (mResetNetworks && config.status == Status.DISABLED) {
- config.status = Status.CURRENT;
- }
-
- AccessPoint accessPoint = new AccessPoint(this, config);
+ AccessPoint accessPoint = new AccessPoint(getActivity(), config);
accessPoint.update(mLastInfo, mLastState);
accessPoints.add(accessPoint);
}
}
- List<ScanResult> results = mWifiManager.getScanResults();
+ final List<ScanResult> results = mWifiManager.getScanResults();
if (results != null) {
for (ScanResult result : results) {
// Ignore hidden and ad-hoc networks.
@@ -395,15 +489,12 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
}
}
if (!found) {
- accessPoints.add(new AccessPoint(this, result));
+ accessPoints.add(new AccessPoint(getActivity(), result));
}
}
}
- mAccessPoints.removeAll();
- for (AccessPoint accessPoint : accessPoints) {
- mAccessPoints.addPreference(accessPoint);
- }
+ return accessPoints;
}
private void handleEvent(Intent intent) {
@@ -411,19 +502,17 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN));
- } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
- updateAccessPoints();
- } else if (WifiManager.NETWORK_IDS_CHANGED_ACTION.equals(action)) {
- if (mSelected != null && mSelected.networkId != -1) {
- mSelected = null;
- }
- updateAccessPoints();
+ } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) ||
+ WifiManager.SUPPLICANT_CONFIG_CHANGED_ACTION.equals(action)) {
+ updateAccessPoints();
} else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
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);
+ changeNextButtonState(info.isConnected());
+ updateConnectionState(info.getDetailedState());
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
updateConnectionState(null);
}
@@ -448,20 +537,23 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
}
for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
- ((AccessPoint) mAccessPoints.getPreference(i)).update(mLastInfo, mLastState);
+ // Maybe there's a WifiConfigPreference
+ Preference preference = mAccessPoints.getPreference(i);
+ if (preference instanceof AccessPoint) {
+ final AccessPoint accessPoint = (AccessPoint) preference;
+ accessPoint.update(mLastInfo, mLastState);
+ }
}
- if (mResetNetworks && (state == DetailedState.CONNECTED ||
- state == DetailedState.DISCONNECTED || state == DetailedState.FAILED)) {
- updateAccessPoints();
- enableNetworks();
+ final Activity activity = getActivity();
+ if (activity instanceof WifiSettingsForSetupWizardXL) {
+ ((WifiSettingsForSetupWizardXL)activity).updateConnectionState(mLastState);
}
}
private void updateWifiState(int state) {
if (state == WifiManager.WIFI_STATE_ENABLED) {
mScanner.resume();
- updateAccessPoints();
} else {
mScanner.pause();
mAccessPoints.removeAll();
@@ -472,6 +564,9 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
private int mRetry = 0;
void resume() {
+ synchronized (WifiSettings.this) {
+ mRefrainListUpdate = false;
+ }
if (!hasMessages(0)) {
sendEmptyMessage(0);
}
@@ -480,6 +575,9 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
void pause() {
mRetry = 0;
mAccessPoints.setProgress(false);
+ synchronized (WifiSettings.this) {
+ mRefrainListUpdate = true;
+ }
removeMessages(0);
}
@@ -489,12 +587,132 @@ public class WifiSettings extends PreferenceActivity implements DialogInterface.
mRetry = 0;
} else if (++mRetry >= 3) {
mRetry = 0;
- Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,
+ Toast.makeText(getActivity(), R.string.wifi_fail_to_scan,
Toast.LENGTH_LONG).show();
return;
}
mAccessPoints.setProgress(mRetry != 0);
- sendEmptyMessageDelayed(0, 6000);
+ // Combo scans can take 5-6s to complete. Increase interval to 10s.
+ sendEmptyMessageDelayed(0, 10000);
+ }
+ }
+
+ private void changeNextButtonState(boolean wifiAvailable) {
+ if (mInXlSetupWizard) {
+ final Button button =
+ (Button)getActivity().findViewById(R.id.wifi_setup_skip_or_next);
+ button.setEnabled(true);
+ if (wifiAvailable) {
+ button.setText(R.string.wifi_setup_next);
+ } else {
+ button.setText(R.string.wifi_setup_skip);
+ }
+ } else if (mEnableNextOnConnection && hasNextButton()) {
+ // Assumes layout for phones has next button inside it.
+ getNextButton().setEnabled(wifiAvailable);
+ }
+ }
+
+ public void onClick(DialogInterface dialogInterface, int button) {
+ if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) {
+ forget();
+ } else if (button == WifiDialog.BUTTON_SUBMIT) {
+ submit();
+ }
+ }
+
+ /* package */ void submit() {
+ final WifiConfigUiBase uiBase = (mDialog != null ? mDialog : mConfigPreference);
+ final WifiConfigController configController = uiBase.getController();
+
+ switch(configController.chosenNetworkSetupMethod()) {
+ case WifiConfigController.WPS_PBC:
+ mWifiManager.startWpsPbc(mSelectedAccessPoint.bssid);
+ break;
+ case WifiConfigController.WPS_PIN:
+ int apPin = configController.getWpsPin();
+ mWifiManager.startWpsPin(mSelectedAccessPoint.bssid, apPin);
+ break;
+ case WifiConfigController.MANUAL:
+ final WifiConfiguration config = configController.getConfig();
+
+ if (config == null) {
+ if (mSelectedAccessPoint != null
+ && !requireKeyStore(mSelectedAccessPoint.getConfig())) {
+ mWifiManager.connectNetwork(mSelectedAccessPoint.networkId);
+ }
+ } else if (config.networkId != INVALID_NETWORK_ID) {
+ if (mSelectedAccessPoint != null) {
+ mWifiManager.saveNetwork(config);
+ }
+ } else {
+ if (uiBase.isEdit() || requireKeyStore(config)) {
+ mWifiManager.saveNetwork(config);
+ } else {
+ mWifiManager.connectNetwork(config);
+ }
+ }
+ break;
+ }
+
+ if (mInXlSetupWizard && mConfigPreference != null) {
+ mConnectingAccessPoint = mSelectedAccessPoint;
+ mConnectingAccessPoint.setSelectable(false);
+ }
+
+ detachConfigPreference();
+ }
+
+ /* package */ void forget() {
+ mWifiManager.forgetNetwork(mSelectedAccessPoint.networkId);
+
+ detachConfigPreference();
+
+ changeNextButtonState(false);
+
+ final Activity activity = getActivity();
+ if (activity instanceof WifiSettingsForSetupWizardXL) {
+ ((WifiSettingsForSetupWizardXL)activity).onForget();
+ }
+ }
+
+ /* package */ void refreshAccessPoints() {
+ if (mWifiManager.isWifiEnabled()) {
+ mScanner.resume();
+ }
+
+ mConfigPreference = null;
+ mConnectingAccessPoint = null;
+ mAccessPoints.removeAll();
+
+ final Activity activity = getActivity();
+ if (activity instanceof WifiSettingsForSetupWizardXL) {
+ ((WifiSettingsForSetupWizardXL)activity).onRefreshAccessPoints();
+ }
+ }
+
+ /* package */ void detachConfigPreference() {
+ if (mConfigPreference != null) {
+ if (mWifiManager.isWifiEnabled()) {
+ mScanner.resume();
+ }
+ mAccessPoints.removePreference(mConfigPreference);
+ mConfigPreference = null;
+ updateAccessPoints();
+ toggleButtonsVisibility(true);
+ }
+ }
+
+ /* package */ void onAddNetworkPressed() {
+ mSelectedAccessPoint = null;
+ showConfigUi(null, true);
+ }
+
+ /* package */ int getAccessPointsCount() {
+ if (mAccessPoints != null) {
+ return mAccessPoints.getPreferenceCount();
+ } else {
+ return 0;
}
}
}
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizardXL.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizardXL.java
new file mode 100644
index 000000000..4870bfe5f
--- /dev/null
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizardXL.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi;
+
+import com.android.settings.R;
+
+import android.app.Activity;
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.net.NetworkInfo.DetailedState;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import java.util.EnumMap;
+
+/**
+ * WifiSetings Activity specific for SetupWizard with X-Large screen size.
+ */
+public class WifiSettingsForSetupWizardXL extends Activity implements OnClickListener {
+ private static final String TAG = WifiSettingsForSetupWizardXL.class.getSimpleName();
+
+ private static final EnumMap<DetailedState, DetailedState> stateMap =
+ new EnumMap<DetailedState, DetailedState>(DetailedState.class);
+
+ static {
+ stateMap.put(DetailedState.IDLE, DetailedState.DISCONNECTED);
+ stateMap.put(DetailedState.SCANNING, DetailedState.SCANNING);
+ stateMap.put(DetailedState.CONNECTING, DetailedState.CONNECTING);
+ stateMap.put(DetailedState.AUTHENTICATING, DetailedState.CONNECTING);
+ stateMap.put(DetailedState.OBTAINING_IPADDR, DetailedState.CONNECTING);
+ stateMap.put(DetailedState.CONNECTED, DetailedState.CONNECTED);
+ stateMap.put(DetailedState.SUSPENDED, DetailedState.SUSPENDED); // ?
+ stateMap.put(DetailedState.DISCONNECTING, DetailedState.DISCONNECTED);
+ stateMap.put(DetailedState.DISCONNECTED, DetailedState.DISCONNECTED);
+ stateMap.put(DetailedState.FAILED, DetailedState.DISCONNECTED);
+ }
+
+ private TextView mProgressText;
+ private ProgressBar mProgressBar;
+ private WifiSettings mWifiSettings;
+ private TextView mStatusText;
+
+ private StatusBarManager mStatusBarManager;
+
+ // This count reduces every time when there's a notification about WiFi status change.
+ // During the term this is >0, The system shows the message "connecting", regardless
+ // of the actual WiFi status. After this count's becoming 0, the status message correctly
+ // reflects what WiFi Picker told it. This is a tweak for letting users not confused
+ // with instable WiFi state during the first scan.
+ private int mIgnoringWifiNotificationCount = 5;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.wifi_settings_for_setup_wizard_xl);
+ mWifiSettings =
+ (WifiSettings)getFragmentManager().findFragmentById(R.id.wifi_setup_fragment);
+ setup();
+ // XXX: should we use method?
+ getIntent().putExtra(WifiSettings.IN_XL_SETUP_WIZARD, true);
+
+ mStatusBarManager = (StatusBarManager)getSystemService(Context.STATUS_BAR_SERVICE);
+ if (mStatusBarManager != null) {
+ mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND
+ | StatusBarManager.DISABLE_NOTIFICATION_ICONS
+ | StatusBarManager.DISABLE_NOTIFICATION_ALERTS
+ | StatusBarManager.DISABLE_SYSTEM_INFO
+ | StatusBarManager.DISABLE_NAVIGATION);
+ } else {
+ Log.e(TAG, "StatusBarManager isn't available.");
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ if (mStatusBarManager != null) {
+ mStatusBarManager.disable(StatusBarManager.DISABLE_NONE);
+ }
+ super.onDestroy();
+ }
+
+ public void setup() {
+ mProgressText = (TextView)findViewById(R.id.scanning_progress_text);
+ mProgressText.setText(Summary.get(this, DetailedState.SCANNING));
+ mProgressBar = (ProgressBar)findViewById(R.id.scanning_progress_bar);
+ mProgressBar.setMax(2);
+ mProgressBar.setIndeterminate(true);
+ mStatusText = (TextView)findViewById(R.id.wifi_setup_status);
+
+ ((Button)findViewById(R.id.wifi_setup_refresh_list)).setOnClickListener(this);
+ ((Button)findViewById(R.id.wifi_setup_add_network)).setOnClickListener(this);
+ ((Button)findViewById(R.id.wifi_setup_skip_or_next)).setOnClickListener(this);
+ ((Button)findViewById(R.id.wifi_setup_connect)).setOnClickListener(this);
+ ((Button)findViewById(R.id.wifi_setup_forget)).setOnClickListener(this);
+ ((Button)findViewById(R.id.wifi_setup_cancel)).setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ final int id = view.getId();
+ switch (id) {
+ case R.id.wifi_setup_refresh_list:
+ mWifiSettings.refreshAccessPoints();
+ break;
+ case R.id.wifi_setup_add_network:
+ mWifiSettings.onAddNetworkPressed();
+ break;
+ case R.id.wifi_setup_skip_or_next:
+ setResult(Activity.RESULT_OK);
+ finish();
+ break;
+ case R.id.wifi_setup_connect:
+ mWifiSettings.submit();
+ break;
+ case R.id.wifi_setup_forget:
+ mWifiSettings.forget();
+ break;
+ case R.id.wifi_setup_cancel:
+ mStatusText.setText(R.string.wifi_setup_status_select_network);
+ mWifiSettings.detachConfigPreference();
+ break;
+ }
+ }
+
+ // Called from WifiSettings
+ public void updateConnectionState(DetailedState originalState) {
+ final DetailedState state = stateMap.get(originalState);
+ switch (state) {
+ case SCANNING: {
+ // Let users know the device is working correctly though currently there's
+ // no visible network on the list.
+ if (mWifiSettings.getAccessPointsCount() == 0) {
+ mProgressBar.setIndeterminate(true);
+ mProgressText.setText(Summary.get(this, DetailedState.SCANNING));
+ } else {
+ // Users already already connected to a network, or see available networks.
+ mProgressBar.setIndeterminate(false);
+ }
+ break;
+ }
+ case CONNECTING: {
+ mProgressBar.setIndeterminate(false);
+ mProgressBar.setProgress(1);
+ mStatusText.setText(R.string.wifi_setup_status_connecting);
+ mProgressText.setText(Summary.get(this, state));
+ break;
+ }
+ case CONNECTED: {
+ mProgressBar.setIndeterminate(false);
+ mProgressBar.setProgress(2);
+ mStatusText.setText(R.string.wifi_setup_status_connected);
+ mProgressText.setText(Summary.get(this, state));
+ setResult(Activity.RESULT_OK);
+ finish();
+ break;
+ }
+ default: // Not connected.
+ if (mWifiSettings.getAccessPointsCount() == 0 &&
+ mIgnoringWifiNotificationCount > 0) {
+ mIgnoringWifiNotificationCount--;
+ mProgressBar.setIndeterminate(true);
+ mProgressText.setText(Summary.get(this, DetailedState.SCANNING));
+ return;
+ } else {
+ mProgressBar.setIndeterminate(false);
+ mProgressBar.setProgress(0);
+ mStatusText.setText(R.string.wifi_setup_status_select_network);
+ mProgressText.setText(getString(R.string.wifi_setup_not_connected));
+ }
+ break;
+ }
+ }
+
+ public void onWifiConfigPreferenceAttached(boolean isNewNetwork) {
+ mStatusText.setText(R.string.wifi_setup_status_edit_network);
+ }
+
+ public void onForget() {
+ mProgressBar.setIndeterminate(false);
+ mProgressBar.setProgress(0);
+ mProgressText.setText(getString(R.string.wifi_setup_not_connected));
+ }
+
+ public void onRefreshAccessPoints() {
+ mProgressBar.setIndeterminate(true);
+ mProgressText.setText(Summary.get(this, DetailedState.SCANNING));
+ }
+}