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 17 package com.android.settings.wifi; 18 19 import com.android.settings.R; 20 import com.android.settings.SecuritySettings; 21 22 import android.app.AlertDialog; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.Intent; 26 import android.content.res.Resources; 27 import android.security.CertTool; 28 import android.security.Keystore; 29 import android.net.wifi.WifiInfo; 30 import android.net.wifi.WifiManager; 31 import android.os.Bundle; 32 import android.text.InputType; 33 import android.text.TextUtils; 34 import android.text.format.Formatter; 35 import android.text.method.PasswordTransformationMethod; 36 import android.text.method.TransformationMethod; 37 import android.util.Log; 38 import android.view.View; 39 import android.view.ViewGroup; 40 import android.widget.AdapterView; 41 import android.widget.ArrayAdapter; 42 import android.widget.CheckBox; 43 import android.widget.EditText; 44 import android.widget.Spinner; 45 import android.widget.TableLayout; 46 import android.widget.TextView; 47 48 public class AccessPointDialog extends AlertDialog implements DialogInterface.OnClickListener, 49 AdapterView.OnItemSelectedListener, View.OnClickListener { 50 51 private static final String TAG = "AccessPointDialog"; 52 private static final String INSTANCE_KEY_ACCESS_POINT_STATE = 53 "com.android.settings.wifi.AccessPointDialog:accessPointState"; 54 private static final String INSTANCE_KEY_MODE = 55 "com.android.settings.wifi.AccessPointDialog:mode"; 56 private static final String INSTANCE_KEY_CUSTOM_TITLE = 57 "com.android.settings.wifi.AccessPointDialog:customTitle"; 58 private static final String INSTANCE_KEY_AUTO_SECURITY_ALLOWED = 59 "com.android.settings.wifi.AccessPointDialog:autoSecurityAllowed"; 60 61 private static final int POSITIVE_BUTTON = BUTTON1; 62 private static final int NEGATIVE_BUTTON = BUTTON2; 63 private static final int NEUTRAL_BUTTON = BUTTON3; 64 65 /** The dialog should show info connectivity functionality */ 66 public static final int MODE_INFO = 0; 67 /** The dialog should configure the detailed AP properties */ 68 public static final int MODE_CONFIGURE = 1; 69 /** The dialog should have the password field and connect/cancel */ 70 public static final int MODE_RETRY_PASSWORD = 2; 71 72 // These should be matched with the XML. Both arrays in XML depend on this 73 // ordering! 74 private static final int SECURITY_AUTO = 0; 75 private static final int SECURITY_NONE = 1; 76 private static final int SECURITY_WEP = 2; 77 private static final int SECURITY_WPA_PERSONAL = 3; 78 private static final int SECURITY_WPA2_PERSONAL = 4; 79 private static final int SECURITY_WPA_EAP = 5; 80 private static final int SECURITY_IEEE8021X = 6; 81 82 private static final int[] WEP_TYPE_VALUES = { 83 AccessPointState.WEP_PASSWORD_AUTO, AccessPointState.WEP_PASSWORD_ASCII, 84 AccessPointState.WEP_PASSWORD_HEX 85 }; 86 private static final String NOT_APPLICABLE = "N/A"; 87 private static final String BLOB_HEADER = "blob://"; 88 89 // Button positions, default to impossible values 90 private int mConnectButtonPos = Integer.MAX_VALUE; 91 private int mForgetButtonPos = Integer.MAX_VALUE; 92 private int mSaveButtonPos = Integer.MAX_VALUE; 93 94 // Client configurable items. Generally, these should be saved in instance state 95 private int mMode = MODE_INFO; 96 private boolean mAutoSecurityAllowed = true; 97 private CharSequence mCustomTitle; 98 // This does not need to be saved in instance state. 99 private WifiLayer mWifiLayer; 100 private AccessPointState mState; 101 102 // General views 103 private View mView; 104 private View mEnterpriseView; 105 private TextView mPasswordText; 106 private EditText mPasswordEdit; 107 private CheckBox mShowPasswordCheckBox; 108 109 // Enterprise fields 110 private TextView mEapText; 111 private Spinner mEapSpinner; 112 private TextView mPhase2Text; 113 private Spinner mPhase2Spinner; 114 private TextView mIdentityText; 115 private EditText mIdentityEdit; 116 private TextView mAnonymousIdentityText; 117 private EditText mAnonymousIdentityEdit; 118 private TextView mCaCertText; 119 private Spinner mCaCertSpinner; 120 private TextView mClientCertText; 121 private Spinner mClientCertSpinner; 122 private TextView mPrivateKeyPasswdText; 123 private EditText mPrivateKeyPasswdEdit; 124 private EditText[] mEnterpriseTextFields; 125 126 127 // Info-specific views 128 private ViewGroup mTable; 129 130 // Configure-specific views 131 private EditText mSsidEdit; 132 private TextView mSsidText; 133 private TextView mSecurityText; 134 private Spinner mSecuritySpinner; 135 private Spinner mWepTypeSpinner; 136 private CertTool mCertTool; 137 AccessPointDialog(Context context, WifiLayer wifiLayer)138 public AccessPointDialog(Context context, WifiLayer wifiLayer) { 139 super(context); 140 141 mWifiLayer = wifiLayer; 142 mCertTool = CertTool.getInstance(); 143 } 144 145 @Override onCreate(Bundle savedInstanceState)146 protected void onCreate(Bundle savedInstanceState) { 147 onLayout(); 148 onFill(); 149 150 super.onCreate(savedInstanceState); 151 } 152 153 @Override onRestoreInstanceState(Bundle savedInstanceState)154 public void onRestoreInstanceState(Bundle savedInstanceState) { 155 // Set to a class loader that can find AccessPointState 156 savedInstanceState.setClassLoader(getClass().getClassLoader()); 157 158 mState = savedInstanceState.getParcelable(INSTANCE_KEY_ACCESS_POINT_STATE); 159 mState.setContext(getContext()); 160 161 mMode = savedInstanceState.getInt(INSTANCE_KEY_MODE, mMode); 162 mAutoSecurityAllowed = savedInstanceState.getBoolean(INSTANCE_KEY_AUTO_SECURITY_ALLOWED, 163 mAutoSecurityAllowed); 164 mCustomTitle = savedInstanceState.getCharSequence(INSTANCE_KEY_CUSTOM_TITLE); 165 if (mCustomTitle != null) { 166 setTitle(mCustomTitle); 167 } 168 169 // This is called last since it depends on the above values 170 super.onRestoreInstanceState(savedInstanceState); 171 172 if (mShowPasswordCheckBox != null) { 173 // Restore the show-password-state on the edit text 174 setShowPassword(mShowPasswordCheckBox.isChecked()); 175 } 176 } 177 178 @Override onSaveInstanceState()179 public Bundle onSaveInstanceState() { 180 Bundle bundle = super.onSaveInstanceState(); 181 bundle.putParcelable(INSTANCE_KEY_ACCESS_POINT_STATE, mState); 182 bundle.putInt(INSTANCE_KEY_MODE, mMode); 183 bundle.putBoolean(INSTANCE_KEY_AUTO_SECURITY_ALLOWED, mAutoSecurityAllowed); 184 bundle.putCharSequence(INSTANCE_KEY_CUSTOM_TITLE, mCustomTitle); 185 return bundle; 186 } 187 188 /** 189 * Sets state to show in this dialog. 190 * 191 * @param state The state. 192 */ setState(AccessPointState state)193 public void setState(AccessPointState state) { 194 mState = state; 195 } 196 197 /** 198 * Sets the dialog mode. 199 * @param mode One of {@link #MODE_CONFIGURE} or {@link #MODE_INFO} 200 */ setMode(int mode)201 public void setMode(int mode) { 202 mMode = mode; 203 } 204 setAutoSecurityAllowed(boolean autoSecurityAllowed)205 public void setAutoSecurityAllowed(boolean autoSecurityAllowed) { 206 mAutoSecurityAllowed = autoSecurityAllowed; 207 } 208 209 @Override setTitle(CharSequence title)210 public void setTitle(CharSequence title) { 211 super.setTitle(title); 212 mCustomTitle = title; 213 } 214 215 @Override setTitle(int titleId)216 public void setTitle(int titleId) { 217 setTitle(getContext().getString(titleId)); 218 } 219 enableEnterpriseFields()220 public void enableEnterpriseFields() { 221 setEnterpriseFieldsVisible(true); 222 updateCertificateSelection(); 223 setGenericPasswordVisible(true); 224 // Both WPA and WPA2 show the same caption, so either is ok 225 updatePasswordCaption(AccessPointState.WPA); 226 } 227 228 /** Called after flags are set, the dialog's layout/etc should be set up here */ onLayout()229 private void onLayout() { 230 final Context context = getContext(); 231 final String ssid = mState.getHumanReadableSsid(); 232 233 int positiveButtonResId = 0; 234 int negativeButtonResId = R.string.cancel; 235 int neutralButtonResId = 0; 236 237 if (mCustomTitle == null) { 238 // Generic title is the SSID 239 // We don't want to trigger this as a custom title, so call super's 240 super.setTitle(ssid); 241 } 242 setInverseBackgroundForced(true); 243 244 boolean defaultPasswordVisibility = true; 245 246 if (mMode == MODE_CONFIGURE) { 247 setLayout(R.layout.wifi_ap_configure); 248 249 positiveButtonResId = R.string.wifi_save_config; 250 mSaveButtonPos = POSITIVE_BUTTON; 251 252 setEnterpriseFieldsVisible(false); 253 254 } else if (mMode == MODE_INFO) { 255 if (mState.isEnterprise() && !mState.configured) { 256 setLayout(R.layout.wifi_ap_configure); 257 setEnterpriseFieldsVisible(true); 258 } else { 259 setLayout(R.layout.wifi_ap_info); 260 } 261 262 if (mState.isConnectable()) { 263 if (mCustomTitle == null) { 264 // We don't want to trigger this as a custom title, so call super's 265 super.setTitle(context.getString(R.string.connect_to_blank, ssid)); 266 } 267 positiveButtonResId = R.string.connect; 268 mConnectButtonPos = POSITIVE_BUTTON; 269 } 270 271 if (mState.isForgetable()) { 272 if (positiveButtonResId == 0) { 273 positiveButtonResId = R.string.forget_network; 274 mForgetButtonPos = POSITIVE_BUTTON; 275 } else { 276 neutralButtonResId = R.string.forget_network; 277 mForgetButtonPos = NEUTRAL_BUTTON; 278 } 279 } 280 } else if (mMode == MODE_RETRY_PASSWORD) { 281 setLayout(R.layout.wifi_ap_retry_password); 282 283 positiveButtonResId = R.string.connect; 284 mConnectButtonPos = POSITIVE_BUTTON; 285 286 setGenericPasswordVisible(true); 287 defaultPasswordVisibility = false; 288 } 289 290 if (defaultPasswordVisibility) { 291 if (!mState.configured && mState.seen && mState.hasSecurity()) { 292 setGenericPasswordVisible(true); 293 } else { 294 setGenericPasswordVisible(false); 295 } 296 } 297 298 setButtons(positiveButtonResId, negativeButtonResId, neutralButtonResId); 299 } 300 301 /** Called when we need to set our member variables to point to the views. */ onReferenceViews(View view)302 private void onReferenceViews(View view) { 303 mPasswordText = (TextView) view.findViewById(R.id.password_text); 304 mPasswordEdit = (EditText) view.findViewById(R.id.password_edit); 305 mSsidText = (TextView) view.findViewById(R.id.ssid_text); 306 mSsidEdit = (EditText) view.findViewById(R.id.ssid_edit); 307 mSecurityText = (TextView) view.findViewById(R.id.security_text); 308 mSecuritySpinner = (Spinner) view.findViewById(R.id.security_spinner); 309 mWepTypeSpinner = (Spinner) view.findViewById(R.id.wep_type_spinner); 310 mEnterpriseView = mView.findViewById(R.id.enterprise_wrapper); 311 312 mShowPasswordCheckBox = (CheckBox) view.findViewById(R.id.show_password_checkbox); 313 if (mShowPasswordCheckBox != null) { 314 mShowPasswordCheckBox.setOnClickListener(this); 315 } 316 if (mMode == MODE_CONFIGURE) { 317 mSecuritySpinner.setOnItemSelectedListener(this); 318 mSecuritySpinner.setPromptId(R.string.security); 319 setSpinnerAdapter(mSecuritySpinner, mAutoSecurityAllowed ? 320 R.array.wifi_security_entries 321 : R.array.wifi_security_without_auto_entries); 322 } else if (mMode == MODE_INFO) { 323 mTable = (ViewGroup) view.findViewById(R.id.table); 324 } 325 /* for enterprise one */ 326 if (mMode == MODE_CONFIGURE || 327 (mState.isEnterprise() && !mState.configured)) { 328 setEnterpriseFields(view); 329 updateCertificateSelection(); 330 } 331 } 332 updateCertificateSelection()333 private void updateCertificateSelection() { 334 setSpinnerAdapter(mClientCertSpinner, getAllUserCertificateKeys()); 335 setSpinnerAdapter(mCaCertSpinner, getAllCaCertificateKeys()); 336 337 mPhase2Spinner.setSelection(getSelectionIndex( 338 R.array.wifi_phase2_entries, mState.getPhase2())); 339 mEapSpinner.setSelection(getSelectionIndex( 340 R.array.wifi_eap_entries, mState.getEap())); 341 mClientCertSpinner.setSelection(getSelectionIndex( 342 getAllUserCertificateKeys(), mState.getEnterpriseField( 343 AccessPointState.CLIENT_CERT))); 344 mCaCertSpinner.setSelection(getSelectionIndex( 345 getAllCaCertificateKeys(), mState.getEnterpriseField( 346 AccessPointState.CA_CERT))); 347 } 348 getAllCaCertificateKeys()349 private String[] getAllCaCertificateKeys() { 350 return appendEmptyInSelection(mCertTool.getAllCaCertificateKeys()); 351 } 352 getAllUserCertificateKeys()353 private String[] getAllUserCertificateKeys() { 354 return appendEmptyInSelection(mCertTool.getAllUserCertificateKeys()); 355 } 356 appendEmptyInSelection(String[] keys)357 private String[] appendEmptyInSelection(String[] keys) { 358 String[] selections = new String[keys.length + 1]; 359 System.arraycopy(keys, 0, selections, 0, keys.length); 360 selections[keys.length] = NOT_APPLICABLE; 361 return selections; 362 } 363 setEnterpriseFields(View view)364 private void setEnterpriseFields(View view) { 365 mIdentityText = (TextView) view.findViewById(R.id.identity_text); 366 mIdentityEdit = (EditText) view.findViewById(R.id.identity_edit); 367 mAnonymousIdentityText = 368 (TextView) view.findViewById(R.id.anonymous_identity_text); 369 mAnonymousIdentityEdit = 370 (EditText) view.findViewById(R.id.anonymous_identity_edit); 371 mClientCertText = 372 (TextView) view.findViewById(R.id.client_certificate_text); 373 mCaCertText = (TextView) view.findViewById(R.id.ca_certificate_text); 374 mPrivateKeyPasswdEdit = 375 (EditText) view.findViewById(R.id.private_key_passwd_edit); 376 mEapText = (TextView) view.findViewById(R.id.eap_text); 377 mEapSpinner = (Spinner) view.findViewById(R.id.eap_spinner); 378 mEapSpinner.setOnItemSelectedListener(this); 379 mEapSpinner.setPromptId(R.string.please_select_eap); 380 setSpinnerAdapter(mEapSpinner, R.array.wifi_eap_entries); 381 382 mPhase2Text = (TextView) view.findViewById(R.id.phase2_text); 383 mPhase2Spinner = (Spinner) view.findViewById(R.id.phase2_spinner); 384 mPhase2Spinner.setOnItemSelectedListener(this); 385 mPhase2Spinner.setPromptId(R.string.please_select_phase2); 386 setSpinnerAdapter(mPhase2Spinner, R.array.wifi_phase2_entries); 387 388 mClientCertSpinner = 389 (Spinner) view.findViewById(R.id.client_certificate_spinner); 390 mClientCertSpinner.setOnItemSelectedListener(this); 391 mClientCertSpinner.setPromptId( 392 R.string.please_select_client_certificate); 393 setSpinnerAdapter(mClientCertSpinner, getAllUserCertificateKeys()); 394 395 mCaCertSpinner = 396 (Spinner) view.findViewById(R.id.ca_certificate_spinner); 397 mCaCertSpinner.setOnItemSelectedListener(this); 398 mCaCertSpinner.setPromptId(R.string.please_select_ca_certificate); 399 setSpinnerAdapter(mCaCertSpinner, getAllCaCertificateKeys()); 400 401 mEnterpriseTextFields = new EditText[] { 402 mIdentityEdit, mAnonymousIdentityEdit, mPrivateKeyPasswdEdit 403 }; 404 405 } 406 setSpinnerAdapter(Spinner spinner, String[] items)407 private void setSpinnerAdapter(Spinner spinner, String[] items) { 408 if (items != null) { 409 ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>( 410 getContext(), android.R.layout.simple_spinner_item, items); 411 adapter.setDropDownViewResource( 412 android.R.layout.simple_spinner_dropdown_item); 413 spinner.setAdapter(adapter); 414 } 415 } 416 setSpinnerAdapter(Spinner spinner, int arrayResId)417 private void setSpinnerAdapter(Spinner spinner, int arrayResId) { 418 setSpinnerAdapter(spinner, 419 getContext().getResources().getStringArray(arrayResId)); 420 } 421 422 /** Called when the widgets are in-place waiting to be filled with data */ onFill()423 private void onFill() { 424 425 // Appears in the order added 426 if (mMode == MODE_INFO) { 427 if (mState.primary) { 428 addInfoRow(R.string.wifi_status, mState.getSummarizedStatus()); 429 addInfoRow(R.string.wifi_link_speed, mState.linkSpeed + WifiInfo.LINK_SPEED_UNITS); 430 } 431 432 if (mState.seen) { 433 addInfoRow(R.string.signal, getSignalResId(mState.signal)); 434 } 435 436 if (mState.security != null) { 437 addInfoRow(R.string.security, mState.getHumanReadableSecurity()); 438 } 439 440 if (mState.primary && mState.ipAddress != 0) { 441 addInfoRow(R.string.ip_address, Formatter.formatIpAddress(mState.ipAddress)); 442 } 443 444 } else if (mMode == MODE_CONFIGURE) { 445 String ssid = mState.getHumanReadableSsid(); 446 if (!TextUtils.isEmpty(ssid)) { 447 mSsidEdit.setText(ssid); 448 } 449 if (mState.configured) { 450 mPasswordEdit.setHint(R.string.wifi_password_unchanged); 451 } 452 } 453 454 updatePasswordCaption(mState.security); 455 } 456 updatePasswordCaption(String security)457 private void updatePasswordCaption(String security) { 458 459 if (mPasswordText != null && security != null 460 && security.equals(AccessPointState.WEP)) { 461 mPasswordText.setText(R.string.please_type_hex_key); 462 } else { 463 mPasswordText.setText(R.string.please_type_passphrase); 464 } 465 } 466 addInfoRow(int nameResId, String value)467 private void addInfoRow(int nameResId, String value) { 468 View rowView = getLayoutInflater().inflate(R.layout.wifi_ap_info_row, mTable, false); 469 ((TextView) rowView.findViewById(R.id.name)).setText(nameResId); 470 ((TextView) rowView.findViewById(R.id.value)).setText(value); 471 mTable.addView(rowView); 472 } 473 addInfoRow(int nameResId, int valueResId)474 private void addInfoRow(int nameResId, int valueResId) { 475 addInfoRow(nameResId, getContext().getString(valueResId)); 476 } 477 setButtons(int positiveResId, int negativeResId, int neutralResId)478 private void setButtons(int positiveResId, int negativeResId, int neutralResId) { 479 final Context context = getContext(); 480 481 if (positiveResId > 0) { 482 setButton(context.getString(positiveResId), this); 483 } 484 485 if (negativeResId > 0) { 486 setButton2(context.getString(negativeResId), this); 487 } 488 489 if (neutralResId > 0) { 490 setButton3(context.getString(neutralResId), this); 491 } 492 } 493 setLayout(int layoutResId)494 private void setLayout(int layoutResId) { 495 setView(mView = getLayoutInflater().inflate(layoutResId, null)); 496 onReferenceViews(mView); 497 } 498 onClick(DialogInterface dialog, int which)499 public void onClick(DialogInterface dialog, int which) { 500 if (which == mForgetButtonPos) { 501 handleForget(); 502 } else if (which == mConnectButtonPos) { 503 handleConnect(); 504 } else if (which == mSaveButtonPos) { 505 handleSave(); 506 } 507 } 508 handleForget()509 private void handleForget() { 510 if (!replaceStateWithWifiLayerInstance()) return; 511 mWifiLayer.forgetNetwork(mState); 512 } 513 handleConnect()514 private void handleConnect() { 515 if (!replaceStateWithWifiLayerInstance()) { 516 Log.w(TAG, "Assuming connecting to a new network."); 517 } 518 519 if (mState.isEnterprise()) { 520 if(!mState.configured) { 521 updateEnterpriseFields( 522 AccessPointState.WPA_EAP.equals(mState.security) ? 523 SECURITY_WPA_EAP : SECURITY_IEEE8021X); 524 } 525 } 526 updatePasswordField(); 527 528 mWifiLayer.connectToNetwork(mState); 529 } 530 531 /* 532 * If the network is secured and they haven't entered a password, popup an 533 * error. Allow empty passwords if the state already has a password set 534 * (since in that scenario, an empty password means keep the old password). 535 */ updatePasswordField()536 private void updatePasswordField() { 537 538 String password = getEnteredPassword(); 539 boolean passwordIsEmpty = TextUtils.isEmpty(password); 540 /* 541 * When 'retry password', they can not enter a blank password. In any 542 * other mode, we let them enter a blank password if the state already 543 * has a password. 544 */ 545 if (passwordIsEmpty && (!mState.hasPassword() || 546 mMode == MODE_RETRY_PASSWORD) && 547 (mState.security != null) && 548 !mState.security.equals(AccessPointState.OPEN) && 549 !mState.isEnterprise()) { 550 new AlertDialog.Builder(getContext()) 551 .setTitle(R.string.error_title) 552 .setIcon(android.R.drawable.ic_dialog_alert) 553 .setMessage(R.string.wifi_password_incorrect_error) 554 .setPositiveButton(android.R.string.ok, null) 555 .show(); 556 return; 557 } 558 559 if (!passwordIsEmpty) { 560 mState.setPassword(password); 561 } 562 } 563 handleSave()564 private void handleSave() { 565 replaceStateWithWifiLayerInstance(); 566 567 String ssid = mSsidEdit.getText().toString(); 568 String password = mPasswordEdit.getText().toString(); 569 570 mState.setSsid(ssid); 571 572 int securityType = getSecurityTypeFromSpinner(); 573 574 if (!TextUtils.isEmpty(password) && (securityType != SECURITY_WEP)) { 575 mState.setPassword(password); 576 } 577 578 switch (securityType) { 579 case SECURITY_WPA_PERSONAL: { 580 mState.setSecurity(AccessPointState.WPA); 581 break; 582 } 583 584 case SECURITY_WPA2_PERSONAL: { 585 mState.setSecurity(AccessPointState.WPA2); 586 break; 587 } 588 589 case SECURITY_AUTO: { 590 break; 591 } 592 593 case SECURITY_WEP: { 594 mState.setSecurity(AccessPointState.WEP); 595 mState.setPassword(password, WEP_TYPE_VALUES[ 596 mWepTypeSpinner.getSelectedItemPosition()]); 597 break; 598 } 599 600 case SECURITY_WPA_EAP: 601 mState.setSecurity(AccessPointState.WPA_EAP); 602 break; 603 604 case SECURITY_IEEE8021X: 605 mState.setSecurity(AccessPointState.IEEE8021X); 606 break; 607 608 case SECURITY_NONE: 609 default: 610 mState.setSecurity(AccessPointState.OPEN); 611 break; 612 } 613 614 if (mState.isEnterprise() && !mState.configured) { 615 updateEnterpriseFields( 616 AccessPointState.WPA_EAP.equals(mState.security) ? 617 SECURITY_WPA_EAP : SECURITY_IEEE8021X); 618 } 619 620 if (!mWifiLayer.saveNetwork(mState)) { 621 return; 622 } 623 624 // Connect right away if they've touched it 625 if (!mWifiLayer.connectToNetwork(mState)) { 626 return; 627 } 628 629 } 630 getSelectionIndex(String[] array, String selection)631 private int getSelectionIndex(String[] array, String selection) { 632 if(selection != null) { 633 for (int i = 0 ; i < array.length ; i++) { 634 if (selection.contains(array[i])) return i; 635 } 636 } 637 return 0; 638 } 639 getSelectionIndex(int arrayResId, String selection)640 private int getSelectionIndex(int arrayResId, String selection) { 641 return getSelectionIndex( 642 getContext().getResources().getStringArray(arrayResId), selection); 643 } 644 updateEnterpriseFields(int securityType)645 private void updateEnterpriseFields(int securityType) { 646 int i; 647 String value; 648 for (i = AccessPointState.IDENTITY ; 649 i <= AccessPointState.PRIVATE_KEY_PASSWD ; i++) { 650 value = mEnterpriseTextFields[i].getText().toString(); 651 if (!TextUtils.isEmpty(value) || 652 (i == AccessPointState.PRIVATE_KEY_PASSWD)) { 653 mState.setEnterpriseField(i, value); 654 } 655 } 656 Spinner spinner = mClientCertSpinner; 657 int index = spinner.getSelectedItemPosition(); 658 if (index != (spinner.getCount() - 1)) { 659 String key = (String)spinner.getSelectedItem(); 660 value = mCertTool.getUserCertificate(key); 661 if (!TextUtils.isEmpty(value)) { 662 mState.setEnterpriseField(AccessPointState.CLIENT_CERT, 663 BLOB_HEADER + value); 664 } 665 value = mCertTool.getUserPrivateKey(key); 666 if (!TextUtils.isEmpty(value)) { 667 mState.setEnterpriseField(AccessPointState.PRIVATE_KEY, 668 BLOB_HEADER + value); 669 } 670 } 671 spinner = mCaCertSpinner; 672 index = spinner.getSelectedItemPosition(); 673 if (index != (spinner.getCount() - 1)) { 674 String key = (String)spinner.getSelectedItem(); 675 value = mCertTool.getCaCertificate(key); 676 if (!TextUtils.isEmpty(value)) { 677 mState.setEnterpriseField(AccessPointState.CA_CERT, 678 BLOB_HEADER + value); 679 } 680 } 681 switch (securityType) { 682 case SECURITY_IEEE8021X: 683 case SECURITY_WPA_EAP: { 684 if (securityType == SECURITY_WPA_EAP) { 685 mState.setSecurity(AccessPointState.WPA_EAP); 686 } else { 687 mState.setSecurity(AccessPointState.IEEE8021X); 688 } 689 mState.setEap(mEapSpinner.getSelectedItemPosition()); 690 mState.setPhase2((String)mPhase2Spinner.getSelectedItem()); 691 break; 692 } 693 default: 694 mState.setSecurity(AccessPointState.OPEN); 695 } 696 } 697 698 /** 699 * Replaces our {@link #mState} with the equal WifiLayer instance. This is useful after 700 * we unparceled the state previously and before we are calling methods on {@link #mWifiLayer}. 701 * 702 * @return Whether WifiLayer was able to find an equal state in its set. 703 */ replaceStateWithWifiLayerInstance()704 private boolean replaceStateWithWifiLayerInstance() { 705 AccessPointState state = mWifiLayer.getWifiLayerApInstance(mState); 706 if (state == null) { 707 return false; 708 } 709 710 mState = state; 711 return true; 712 } 713 getSecurityTypeFromSpinner()714 private int getSecurityTypeFromSpinner() { 715 int position = mSecuritySpinner.getSelectedItemPosition(); 716 // If there is no AUTO choice, the position needs 1 added to get 717 // to the proper spinner position -> security constants mapping 718 return mAutoSecurityAllowed ? position : position + 1; 719 } 720 getEnteredPassword()721 private String getEnteredPassword() { 722 return mPasswordEdit != null ? mPasswordEdit.getText().toString() : null; 723 } 724 725 /** 726 * Call the one you want to hide first. 727 */ setWepVisible(boolean visible)728 private void setWepVisible(boolean visible) { 729 setGenericPasswordVisible(visible); 730 int visibility = visible ? View.VISIBLE : View.GONE; 731 mWepTypeSpinner.setVisibility(visibility); 732 } 733 734 /** 735 * @see #setWepVisible(boolean) 736 */ setGenericPasswordVisible(boolean visible)737 private void setGenericPasswordVisible(boolean visible) { 738 int visibility = visible ? View.VISIBLE : View.GONE; 739 mPasswordText.setVisibility(visibility); 740 mPasswordEdit.setVisibility(visibility); 741 mShowPasswordCheckBox.setVisibility(visibility); 742 } 743 setEnterpriseFieldsVisible(boolean visible)744 private void setEnterpriseFieldsVisible(boolean visible) { 745 int visibility = visible ? View.VISIBLE : View.GONE; 746 mEnterpriseView.setVisibility(visibility); 747 if (visible) { 748 setWepVisible(false); 749 } 750 if (mMode != MODE_CONFIGURE) { 751 mSsidText.setVisibility(View.GONE); 752 mSsidEdit.setVisibility(View.GONE); 753 mSecurityText.setVisibility(View.GONE); 754 mSecuritySpinner.setVisibility(View.GONE); 755 } 756 } 757 onItemSelected(AdapterView parent, View view, int position, long id)758 public void onItemSelected(AdapterView parent, View view, int position, long id) { 759 if (parent == mSecuritySpinner) { 760 handleSecurityChange(getSecurityTypeFromSpinner()); 761 } 762 } 763 onNothingSelected(AdapterView parent)764 public void onNothingSelected(AdapterView parent) { 765 } 766 handleSecurityChange(int security)767 private void handleSecurityChange(int security) { 768 setEnterpriseFieldsVisible(false); 769 switch (security) { 770 771 case SECURITY_NONE: { 772 setWepVisible(false); 773 setGenericPasswordVisible(false); 774 break; 775 } 776 777 case SECURITY_WEP: { 778 setGenericPasswordVisible(false); 779 setWepVisible(true); 780 updatePasswordCaption(AccessPointState.WEP); 781 break; 782 } 783 784 case SECURITY_AUTO: { 785 setWepVisible(false); 786 setGenericPasswordVisible(mState.hasSecurity()); 787 // Shows the generic 'wireless password' 788 updatePasswordCaption(AccessPointState.WPA); 789 break; 790 } 791 792 case SECURITY_WPA_PERSONAL: 793 case SECURITY_WPA2_PERSONAL: { 794 setWepVisible(false); 795 setGenericPasswordVisible(true); 796 // Both WPA and WPA2 show the same caption, so either is ok 797 updatePasswordCaption(AccessPointState.WPA); 798 break; 799 } 800 case SECURITY_WPA_EAP: 801 case SECURITY_IEEE8021X: { 802 // Unlock the keystore if it is not unlocked yet. 803 if (Keystore.getInstance().getState() != Keystore.UNLOCKED) { 804 getContext().startActivity(new Intent( 805 SecuritySettings.ACTION_UNLOCK_CREDENTIAL_STORAGE)); 806 return; 807 } 808 enableEnterpriseFields(); 809 break; 810 } 811 } 812 } 813 getSignalResId(int signal)814 private static int getSignalResId(int signal) { 815 switch (WifiManager.calculateSignalLevel(signal, 4)) { 816 case 0: { 817 return R.string.wifi_signal_0; 818 } 819 case 1: { 820 return R.string.wifi_signal_1; 821 } 822 case 2: { 823 return R.string.wifi_signal_2; 824 } 825 case 3: { 826 return R.string.wifi_signal_3; 827 } 828 } 829 830 return 0; 831 } 832 833 onClick(View v)834 public void onClick(View v) { 835 if (v == mShowPasswordCheckBox) { 836 setShowPassword(mShowPasswordCheckBox.isChecked()); 837 } 838 } 839 setShowPassword(boolean showPassword)840 private void setShowPassword(boolean showPassword) { 841 if (mPasswordEdit != null) { 842 mPasswordEdit.setInputType(InputType.TYPE_CLASS_TEXT | 843 (showPassword ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD 844 : InputType.TYPE_TEXT_VARIATION_PASSWORD)); 845 } 846 } 847 848 } 849