1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings.wifi; 18 19import com.android.settings.R; 20 21import android.content.ContentResolver; 22import android.net.wifi.WifiInfo; 23import android.net.wifi.WifiManager; 24import android.os.Bundle; 25import android.preference.CheckBoxPreference; 26import android.preference.EditTextPreference; 27import android.preference.ListPreference; 28import android.preference.Preference; 29import android.preference.PreferenceActivity; 30import android.provider.Settings; 31import android.provider.Settings.System; 32import android.text.TextUtils; 33import android.view.KeyEvent; 34import android.view.Menu; 35import android.view.MenuItem; 36import android.widget.Toast; 37import android.os.SystemProperties; 38 39public class AdvancedSettings extends PreferenceActivity 40 implements Preference.OnPreferenceChangeListener { 41 42 private static final String KEY_MAC_ADDRESS = "mac_address"; 43 private static final String KEY_USE_STATIC_IP = "use_static_ip"; 44 private static final String KEY_NUM_CHANNELS = "num_channels"; 45 private static final String KEY_SLEEP_POLICY = "sleep_policy"; 46 47 private String[] mSettingNames = { 48 System.WIFI_STATIC_IP, System.WIFI_STATIC_GATEWAY, System.WIFI_STATIC_NETMASK, 49 System.WIFI_STATIC_DNS1, System.WIFI_STATIC_DNS2 50 }; 51 52 private String[] mPreferenceKeys = { 53 "ip_address", "gateway", "netmask", "dns1", "dns2" 54 }; 55 56 private CheckBoxPreference mUseStaticIpCheckBox; 57 58 private static final int MENU_ITEM_SAVE = Menu.FIRST; 59 private static final int MENU_ITEM_CANCEL = Menu.FIRST + 1; 60 61 //Tracks ro.debuggable (1 on userdebug builds) 62 private static int DEBUGGABLE; 63 64 @Override 65 protected void onCreate(Bundle savedInstanceState) { 66 super.onCreate(savedInstanceState); 67 68 addPreferencesFromResource(R.xml.wifi_advanced_settings); 69 70 mUseStaticIpCheckBox = (CheckBoxPreference) findPreference(KEY_USE_STATIC_IP); 71 mUseStaticIpCheckBox.setOnPreferenceChangeListener(this); 72 73 for (int i = 0; i < mPreferenceKeys.length; i++) { 74 Preference preference = findPreference(mPreferenceKeys[i]); 75 preference.setOnPreferenceChangeListener(this); 76 } 77 78 DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0); 79 80 /** 81 * Remove user control of regulatory domain 82 * channel count settings in non userdebug builds 83 */ 84 if (DEBUGGABLE == 1) { 85 /* 86 * Fix the Run-time IllegalStateException that ListPreference requires an entries 87 * array and an entryValues array, this exception occurs when user open/close the 88 * slider in the Regulatory domain dialog. 89 */ 90 initNumChannelsPreference(); 91 } else { 92 Preference chanPref = findPreference(KEY_NUM_CHANNELS); 93 if (chanPref != null) { 94 getPreferenceScreen().removePreference(chanPref); 95 } 96 } 97 } 98 99 @Override 100 protected void onResume() { 101 super.onResume(); 102 103 updateUi(); 104 /** 105 * Remove user control of regulatory domain 106 * channel count settings in non userdebug builds 107 */ 108 if (DEBUGGABLE == 1) { 109 initNumChannelsPreference(); 110 } 111 initSleepPolicyPreference(); 112 refreshMacAddress(); 113 } 114 115 private void initNumChannelsPreference() { 116 ListPreference pref = (ListPreference) findPreference(KEY_NUM_CHANNELS); 117 pref.setOnPreferenceChangeListener(this); 118 119 WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); 120 /* 121 * Generate the list of valid channel counts to show in the ListPreference. 122 * The values are numerical, so the only text to be localized is the 123 * "channel_word" resource. 124 */ 125 int[] validChannelCounts = wifiManager.getValidChannelCounts(); 126 if (validChannelCounts == null) { 127 Toast.makeText(this, R.string.wifi_setting_num_channels_error, 128 Toast.LENGTH_SHORT).show(); 129 pref.setEnabled(false); 130 return; 131 } 132 String[] entries = new String[validChannelCounts.length]; 133 String[] entryValues = new String[validChannelCounts.length]; 134 135 for (int i = 0; i < validChannelCounts.length; i++) { 136 entryValues[i] = String.valueOf(validChannelCounts[i]); 137 entries[i] = getString(R.string.wifi_setting_num_channels_channel_phrase, 138 validChannelCounts[i]); 139 } 140 pref.setEntries(entries); 141 pref.setEntryValues(entryValues); 142 pref.setEnabled(true); 143 int numChannels = wifiManager.getNumAllowedChannels(); 144 if (numChannels >= 0) { 145 pref.setValue(String.valueOf(numChannels)); 146 } 147 } 148 149 private void initSleepPolicyPreference() { 150 ListPreference pref = (ListPreference) findPreference(KEY_SLEEP_POLICY); 151 pref.setOnPreferenceChangeListener(this); 152 int value = Settings.System.getInt(getContentResolver(), 153 Settings.System.WIFI_SLEEP_POLICY,Settings. System.WIFI_SLEEP_POLICY_DEFAULT); 154 pref.setValue(String.valueOf(value)); 155 } 156 157 @Override 158 public boolean onKeyDown(int keyCode, KeyEvent event) { 159 160 if (keyCode == KeyEvent.KEYCODE_BACK) { 161 updateSettingsProvider(); 162 } 163 164 return super.onKeyDown(keyCode, event); 165 } 166 167 public boolean onPreferenceChange(Preference preference, Object newValue) { 168 String key = preference.getKey(); 169 if (key == null) return true; 170 171 if (key.equals(KEY_NUM_CHANNELS)) { 172 try { 173 int numChannels = Integer.parseInt((String) newValue); 174 WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); 175 if (!wifiManager.setNumAllowedChannels(numChannels, true)) { 176 Toast.makeText(this, R.string.wifi_setting_num_channels_error, 177 Toast.LENGTH_SHORT).show(); 178 } 179 } catch (NumberFormatException e) { 180 Toast.makeText(this, R.string.wifi_setting_num_channels_error, 181 Toast.LENGTH_SHORT).show(); 182 return false; 183 } 184 185 } else if (key.equals(KEY_SLEEP_POLICY)) { 186 try { 187 Settings.System.putInt(getContentResolver(), 188 Settings.System.WIFI_SLEEP_POLICY, Integer.parseInt(((String) newValue))); 189 } catch (NumberFormatException e) { 190 Toast.makeText(this, R.string.wifi_setting_sleep_policy_error, 191 Toast.LENGTH_SHORT).show(); 192 return false; 193 } 194 195 } else if (key.equals(KEY_USE_STATIC_IP)) { 196 boolean value = ((Boolean) newValue).booleanValue(); 197 198 try { 199 Settings.System.putInt(getContentResolver(), 200 Settings.System.WIFI_USE_STATIC_IP, value ? 1 : 0); 201 } catch (NumberFormatException e) { 202 return false; 203 } 204 } else { 205 String value = (String) newValue; 206 207 if (!isIpAddress(value)) { 208 Toast.makeText(this, R.string.wifi_ip_settings_invalid_ip, Toast.LENGTH_LONG).show(); 209 return false; 210 } 211 212 preference.setSummary(value); 213 for (int i = 0; i < mSettingNames.length; i++) { 214 if (key.equals(mPreferenceKeys[i])) { 215 Settings.System.putString(getContentResolver(), mSettingNames[i], value); 216 break; 217 } 218 } 219 } 220 221 return true; 222 } 223 224 private boolean isIpAddress(String value) { 225 226 int start = 0; 227 int end = value.indexOf('.'); 228 int numBlocks = 0; 229 230 while (start < value.length()) { 231 232 if (end == -1) { 233 end = value.length(); 234 } 235 236 try { 237 int block = Integer.parseInt(value.substring(start, end)); 238 if ((block > 255) || (block < 0)) { 239 return false; 240 } 241 } catch (NumberFormatException e) { 242 return false; 243 } 244 245 numBlocks++; 246 247 start = end + 1; 248 end = value.indexOf('.', start); 249 } 250 251 return numBlocks == 4; 252 } 253 254 @Override 255 public boolean onCreateOptionsMenu(Menu menu) { 256 257 menu.add(0, MENU_ITEM_SAVE, 0, R.string.wifi_ip_settings_menu_save) 258 .setIcon(android.R.drawable.ic_menu_save); 259 260 menu.add(0, MENU_ITEM_CANCEL, 0, R.string.wifi_ip_settings_menu_cancel) 261 .setIcon(android.R.drawable.ic_menu_close_clear_cancel); 262 263 return super.onCreateOptionsMenu(menu); 264 } 265 266 @Override 267 public boolean onOptionsItemSelected(MenuItem item) { 268 269 switch (item.getItemId()) { 270 271 case MENU_ITEM_SAVE: 272 updateSettingsProvider(); 273 finish(); 274 return true; 275 276 case MENU_ITEM_CANCEL: 277 finish(); 278 return true; 279 } 280 281 return super.onOptionsItemSelected(item); 282 } 283 284 private void updateUi() { 285 ContentResolver contentResolver = getContentResolver(); 286 287 mUseStaticIpCheckBox.setChecked(System.getInt(contentResolver, 288 System.WIFI_USE_STATIC_IP, 0) != 0); 289 290 for (int i = 0; i < mSettingNames.length; i++) { 291 EditTextPreference preference = (EditTextPreference) findPreference(mPreferenceKeys[i]); 292 String settingValue = System.getString(contentResolver, mSettingNames[i]); 293 preference.setText(settingValue); 294 preference.setSummary(settingValue); 295 } 296 } 297 298 private void updateSettingsProvider() { 299 ContentResolver contentResolver = getContentResolver(); 300 301 System.putInt(contentResolver, System.WIFI_USE_STATIC_IP, 302 mUseStaticIpCheckBox.isChecked() ? 1 : 0); 303 304 for (int i = 0; i < mSettingNames.length; i++) { 305 EditTextPreference preference = (EditTextPreference) findPreference(mPreferenceKeys[i]); 306 System.putString(contentResolver, mSettingNames[i], preference.getText()); 307 } 308 } 309 310 private void refreshMacAddress() { 311 WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); 312 WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 313 314 Preference wifiMacAddressPref = findPreference(KEY_MAC_ADDRESS); 315 String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress(); 316 wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress 317 : getString(R.string.status_unavailable)); 318 } 319 320} 321