Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2006 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;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.content.ContentUris;
     22 import android.content.ContentValues;
     23 import android.content.Intent;
     24 import android.content.SharedPreferences;
     25 import android.content.res.Resources;
     26 import android.database.Cursor;
     27 import android.net.Uri;
     28 import android.os.Bundle;
     29 import android.os.SystemProperties;
     30 import android.preference.EditTextPreference;
     31 import android.preference.ListPreference;
     32 import android.preference.CheckBoxPreference;
     33 import android.preference.Preference;
     34 import android.preference.PreferenceActivity;
     35 import android.provider.Telephony;
     36 import android.telephony.TelephonyManager;
     37 import android.util.Log;
     38 import android.view.KeyEvent;
     39 import android.view.Menu;
     40 import android.view.MenuItem;
     41 
     42 import com.android.internal.telephony.Phone;
     43 import com.android.internal.telephony.RILConstants;
     44 import com.android.internal.telephony.TelephonyProperties;
     45 
     46 
     47 public class ApnEditor extends PreferenceActivity
     48         implements SharedPreferences.OnSharedPreferenceChangeListener,
     49                     Preference.OnPreferenceChangeListener {
     50 
     51     private final static String TAG = ApnEditor.class.getSimpleName();
     52 
     53     private final static String SAVED_POS = "pos";
     54     private final static String KEY_AUTH_TYPE = "auth_type";
     55     private final static String KEY_PROTOCOL = "apn_protocol";
     56     private final static String KEY_ROAMING_PROTOCOL = "apn_roaming_protocol";
     57     private final static String KEY_CARRIER_ENABLED = "carrier_enabled";
     58     private final static String KEY_BEARER = "bearer";
     59 
     60     private static final int MENU_DELETE = Menu.FIRST;
     61     private static final int MENU_SAVE = Menu.FIRST + 1;
     62     private static final int MENU_CANCEL = Menu.FIRST + 2;
     63     private static final int ERROR_DIALOG_ID = 0;
     64 
     65     private static String sNotSet;
     66     private EditTextPreference mName;
     67     private EditTextPreference mApn;
     68     private EditTextPreference mProxy;
     69     private EditTextPreference mPort;
     70     private EditTextPreference mUser;
     71     private EditTextPreference mServer;
     72     private EditTextPreference mPassword;
     73     private EditTextPreference mMmsc;
     74     private EditTextPreference mMcc;
     75     private EditTextPreference mMnc;
     76     private EditTextPreference mMmsProxy;
     77     private EditTextPreference mMmsPort;
     78     private ListPreference mAuthType;
     79     private EditTextPreference mApnType;
     80     private ListPreference mProtocol;
     81     private ListPreference mRoamingProtocol;
     82     private CheckBoxPreference mCarrierEnabled;
     83     private ListPreference mBearer;
     84 
     85     private String mCurMnc;
     86     private String mCurMcc;
     87 
     88     private Uri mUri;
     89     private Cursor mCursor;
     90     private boolean mNewApn;
     91     private boolean mFirstTime;
     92     private Resources mRes;
     93 
     94     /**
     95      * Standard projection for the interesting columns of a normal note.
     96      */
     97     private static final String[] sProjection = new String[] {
     98             Telephony.Carriers._ID,     // 0
     99             Telephony.Carriers.NAME,    // 1
    100             Telephony.Carriers.APN,     // 2
    101             Telephony.Carriers.PROXY,   // 3
    102             Telephony.Carriers.PORT,    // 4
    103             Telephony.Carriers.USER,    // 5
    104             Telephony.Carriers.SERVER,  // 6
    105             Telephony.Carriers.PASSWORD, // 7
    106             Telephony.Carriers.MMSC, // 8
    107             Telephony.Carriers.MCC, // 9
    108             Telephony.Carriers.MNC, // 10
    109             Telephony.Carriers.NUMERIC, // 11
    110             Telephony.Carriers.MMSPROXY,// 12
    111             Telephony.Carriers.MMSPORT, // 13
    112             Telephony.Carriers.AUTH_TYPE, // 14
    113             Telephony.Carriers.TYPE, // 15
    114             Telephony.Carriers.PROTOCOL, // 16
    115             Telephony.Carriers.CARRIER_ENABLED, // 17
    116             Telephony.Carriers.BEARER, // 18
    117             Telephony.Carriers.ROAMING_PROTOCOL // 19
    118     };
    119 
    120     private static final int ID_INDEX = 0;
    121     private static final int NAME_INDEX = 1;
    122     private static final int APN_INDEX = 2;
    123     private static final int PROXY_INDEX = 3;
    124     private static final int PORT_INDEX = 4;
    125     private static final int USER_INDEX = 5;
    126     private static final int SERVER_INDEX = 6;
    127     private static final int PASSWORD_INDEX = 7;
    128     private static final int MMSC_INDEX = 8;
    129     private static final int MCC_INDEX = 9;
    130     private static final int MNC_INDEX = 10;
    131     private static final int MMSPROXY_INDEX = 12;
    132     private static final int MMSPORT_INDEX = 13;
    133     private static final int AUTH_TYPE_INDEX = 14;
    134     private static final int TYPE_INDEX = 15;
    135     private static final int PROTOCOL_INDEX = 16;
    136     private static final int CARRIER_ENABLED_INDEX = 17;
    137     private static final int BEARER_INDEX = 18;
    138     private static final int ROAMING_PROTOCOL_INDEX = 19;
    139 
    140 
    141     @Override
    142     protected void onCreate(Bundle icicle) {
    143         super.onCreate(icicle);
    144 
    145         addPreferencesFromResource(R.xml.apn_editor);
    146 
    147         sNotSet = getResources().getString(R.string.apn_not_set);
    148         mName = (EditTextPreference) findPreference("apn_name");
    149         mApn = (EditTextPreference) findPreference("apn_apn");
    150         mProxy = (EditTextPreference) findPreference("apn_http_proxy");
    151         mPort = (EditTextPreference) findPreference("apn_http_port");
    152         mUser = (EditTextPreference) findPreference("apn_user");
    153         mServer = (EditTextPreference) findPreference("apn_server");
    154         mPassword = (EditTextPreference) findPreference("apn_password");
    155         mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
    156         mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
    157         mMmsc = (EditTextPreference) findPreference("apn_mmsc");
    158         mMcc = (EditTextPreference) findPreference("apn_mcc");
    159         mMnc = (EditTextPreference) findPreference("apn_mnc");
    160         mApnType = (EditTextPreference) findPreference("apn_type");
    161 
    162         mAuthType = (ListPreference) findPreference(KEY_AUTH_TYPE);
    163         mAuthType.setOnPreferenceChangeListener(this);
    164 
    165         mProtocol = (ListPreference) findPreference(KEY_PROTOCOL);
    166         mProtocol.setOnPreferenceChangeListener(this);
    167 
    168         mRoamingProtocol = (ListPreference) findPreference(KEY_ROAMING_PROTOCOL);
    169         // Only enable this on CDMA phones for now, since it may cause problems on other phone
    170         // types.  (This screen is not normally accessible on CDMA phones, but is useful for
    171         // testing.)
    172         TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
    173         if (tm.getCurrentPhoneType() == Phone.PHONE_TYPE_CDMA) {
    174             mRoamingProtocol.setOnPreferenceChangeListener(this);
    175         } else {
    176             getPreferenceScreen().removePreference(mRoamingProtocol);
    177         }
    178 
    179         mCarrierEnabled = (CheckBoxPreference) findPreference(KEY_CARRIER_ENABLED);
    180 
    181         mBearer = (ListPreference) findPreference(KEY_BEARER);
    182         mBearer.setOnPreferenceChangeListener(this);
    183 
    184         mRes = getResources();
    185 
    186         final Intent intent = getIntent();
    187         final String action = intent.getAction();
    188 
    189         mFirstTime = icicle == null;
    190 
    191         if (action.equals(Intent.ACTION_EDIT)) {
    192             mUri = intent.getData();
    193         } else if (action.equals(Intent.ACTION_INSERT)) {
    194             if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
    195                 mUri = getContentResolver().insert(intent.getData(), new ContentValues());
    196             } else {
    197                 mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
    198                         icicle.getInt(SAVED_POS));
    199             }
    200             mNewApn = true;
    201             // If we were unable to create a new note, then just finish
    202             // this activity.  A RESULT_CANCELED will be sent back to the
    203             // original activity if they requested a result.
    204             if (mUri == null) {
    205                 Log.w(TAG, "Failed to insert new telephony provider into "
    206                         + getIntent().getData());
    207                 finish();
    208                 return;
    209             }
    210 
    211             // The new entry was created, so assume all will end well and
    212             // set the result to be returned.
    213             setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
    214 
    215         } else {
    216             finish();
    217             return;
    218         }
    219 
    220         mCursor = managedQuery(mUri, sProjection, null, null);
    221         mCursor.moveToFirst();
    222 
    223         fillUi();
    224     }
    225 
    226     @Override
    227     public void onResume() {
    228         super.onResume();
    229         getPreferenceScreen().getSharedPreferences()
    230                 .registerOnSharedPreferenceChangeListener(this);
    231     }
    232 
    233     @Override
    234     public void onPause() {
    235         getPreferenceScreen().getSharedPreferences()
    236                 .unregisterOnSharedPreferenceChangeListener(this);
    237         super.onPause();
    238     }
    239 
    240     private void fillUi() {
    241         if (mFirstTime) {
    242             mFirstTime = false;
    243             // Fill in all the values from the db in both text editor and summary
    244             mName.setText(mCursor.getString(NAME_INDEX));
    245             mApn.setText(mCursor.getString(APN_INDEX));
    246             mProxy.setText(mCursor.getString(PROXY_INDEX));
    247             mPort.setText(mCursor.getString(PORT_INDEX));
    248             mUser.setText(mCursor.getString(USER_INDEX));
    249             mServer.setText(mCursor.getString(SERVER_INDEX));
    250             mPassword.setText(mCursor.getString(PASSWORD_INDEX));
    251             mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
    252             mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
    253             mMmsc.setText(mCursor.getString(MMSC_INDEX));
    254             mMcc.setText(mCursor.getString(MCC_INDEX));
    255             mMnc.setText(mCursor.getString(MNC_INDEX));
    256             mApnType.setText(mCursor.getString(TYPE_INDEX));
    257             if (mNewApn) {
    258                 String numeric =
    259                     SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
    260                 // MCC is first 3 chars and then in 2 - 3 chars of MNC
    261                 if (numeric != null && numeric.length() > 4) {
    262                     // Country code
    263                     String mcc = numeric.substring(0, 3);
    264                     // Network code
    265                     String mnc = numeric.substring(3);
    266                     // Auto populate MNC and MCC for new entries, based on what SIM reports
    267                     mMcc.setText(mcc);
    268                     mMnc.setText(mnc);
    269                     mCurMnc = mnc;
    270                     mCurMcc = mcc;
    271                 }
    272             }
    273             int authVal = mCursor.getInt(AUTH_TYPE_INDEX);
    274             if (authVal != -1) {
    275                 mAuthType.setValueIndex(authVal);
    276             } else {
    277                 mAuthType.setValue(null);
    278             }
    279 
    280             mProtocol.setValue(mCursor.getString(PROTOCOL_INDEX));
    281             mRoamingProtocol.setValue(mCursor.getString(ROAMING_PROTOCOL_INDEX));
    282             mCarrierEnabled.setChecked(mCursor.getInt(CARRIER_ENABLED_INDEX)==1);
    283             mBearer.setValue(mCursor.getString(BEARER_INDEX));
    284         }
    285 
    286         mName.setSummary(checkNull(mName.getText()));
    287         mApn.setSummary(checkNull(mApn.getText()));
    288         mProxy.setSummary(checkNull(mProxy.getText()));
    289         mPort.setSummary(checkNull(mPort.getText()));
    290         mUser.setSummary(checkNull(mUser.getText()));
    291         mServer.setSummary(checkNull(mServer.getText()));
    292         mPassword.setSummary(starify(mPassword.getText()));
    293         mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
    294         mMmsPort.setSummary(checkNull(mMmsPort.getText()));
    295         mMmsc.setSummary(checkNull(mMmsc.getText()));
    296         mMcc.setSummary(checkNull(mMcc.getText()));
    297         mMnc.setSummary(checkNull(mMnc.getText()));
    298         mApnType.setSummary(checkNull(mApnType.getText()));
    299 
    300         String authVal = mAuthType.getValue();
    301         if (authVal != null) {
    302             int authValIndex = Integer.parseInt(authVal);
    303             mAuthType.setValueIndex(authValIndex);
    304 
    305             String []values = mRes.getStringArray(R.array.apn_auth_entries);
    306             mAuthType.setSummary(values[authValIndex]);
    307         } else {
    308             mAuthType.setSummary(sNotSet);
    309         }
    310 
    311         mProtocol.setSummary(
    312                 checkNull(protocolDescription(mProtocol.getValue(), mProtocol)));
    313         mRoamingProtocol.setSummary(
    314                 checkNull(protocolDescription(mRoamingProtocol.getValue(), mRoamingProtocol)));
    315         mBearer.setSummary(
    316                 checkNull(bearerDescription(mBearer.getValue())));
    317     }
    318 
    319     /**
    320      * Returns the UI choice (e.g., "IPv4/IPv6") corresponding to the given
    321      * raw value of the protocol preference (e.g., "IPV4V6"). If unknown,
    322      * return null.
    323      */
    324     private String protocolDescription(String raw, ListPreference protocol) {
    325         int protocolIndex = protocol.findIndexOfValue(raw);
    326         if (protocolIndex == -1) {
    327             return null;
    328         } else {
    329             String[] values = mRes.getStringArray(R.array.apn_protocol_entries);
    330             try {
    331                 return values[protocolIndex];
    332             } catch (ArrayIndexOutOfBoundsException e) {
    333                 return null;
    334             }
    335         }
    336     }
    337 
    338     private String bearerDescription(String raw) {
    339         int mBearerIndex = mBearer.findIndexOfValue(raw);
    340         if (mBearerIndex == -1) {
    341             return null;
    342         } else {
    343             String[] values = mRes.getStringArray(R.array.bearer_entries);
    344             try {
    345                 return values[mBearerIndex];
    346             } catch (ArrayIndexOutOfBoundsException e) {
    347                 return null;
    348             }
    349         }
    350     }
    351 
    352     public boolean onPreferenceChange(Preference preference, Object newValue) {
    353         String key = preference.getKey();
    354         if (KEY_AUTH_TYPE.equals(key)) {
    355             try {
    356                 int index = Integer.parseInt((String) newValue);
    357                 mAuthType.setValueIndex(index);
    358 
    359                 String []values = mRes.getStringArray(R.array.apn_auth_entries);
    360                 mAuthType.setSummary(values[index]);
    361             } catch (NumberFormatException e) {
    362                 return false;
    363             }
    364         } else if (KEY_PROTOCOL.equals(key)) {
    365             String protocol = protocolDescription((String) newValue, mProtocol);
    366             if (protocol == null) {
    367                 return false;
    368             }
    369             mProtocol.setSummary(protocol);
    370             mProtocol.setValue((String) newValue);
    371         } else if (KEY_ROAMING_PROTOCOL.equals(key)) {
    372             String protocol = protocolDescription((String) newValue, mRoamingProtocol);
    373             if (protocol == null) {
    374                 return false;
    375             }
    376             mRoamingProtocol.setSummary(protocol);
    377             mRoamingProtocol.setValue((String) newValue);
    378         } else if (KEY_BEARER.equals(key)) {
    379             String bearer = bearerDescription((String) newValue);
    380             if (bearer == null) {
    381                 return false;
    382             }
    383             mBearer.setValue((String) newValue);
    384             mBearer.setSummary(bearer);
    385         }
    386 
    387         return true;
    388     }
    389 
    390     @Override
    391     public boolean onCreateOptionsMenu(Menu menu) {
    392         super.onCreateOptionsMenu(menu);
    393         // If it's a new APN, then cancel will delete the new entry in onPause
    394         if (!mNewApn) {
    395             menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
    396                 .setIcon(R.drawable.ic_menu_delete_holo_dark);
    397         }
    398         menu.add(0, MENU_SAVE, 0, R.string.menu_save)
    399             .setIcon(android.R.drawable.ic_menu_save);
    400         menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel)
    401             .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
    402         return true;
    403     }
    404 
    405     @Override
    406     public boolean onOptionsItemSelected(MenuItem item) {
    407         switch (item.getItemId()) {
    408         case MENU_DELETE:
    409             deleteApn();
    410             return true;
    411         case MENU_SAVE:
    412             if (validateAndSave(false)) {
    413                 finish();
    414             }
    415             return true;
    416         case MENU_CANCEL:
    417             if (mNewApn) {
    418                 getContentResolver().delete(mUri, null, null);
    419             }
    420             finish();
    421             return true;
    422         }
    423         return super.onOptionsItemSelected(item);
    424     }
    425 
    426     @Override
    427     public boolean onKeyDown(int keyCode, KeyEvent event) {
    428         switch (keyCode) {
    429             case KeyEvent.KEYCODE_BACK: {
    430                 if (validateAndSave(false)) {
    431                     finish();
    432                 }
    433                 return true;
    434             }
    435         }
    436         return super.onKeyDown(keyCode, event);
    437     }
    438 
    439     @Override
    440     protected void onSaveInstanceState(Bundle icicle) {
    441         super.onSaveInstanceState(icicle);
    442         if (validateAndSave(true)) {
    443             icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
    444         }
    445     }
    446 
    447     /**
    448      * Check the key fields' validity and save if valid.
    449      * @param force save even if the fields are not valid, if the app is
    450      *        being suspended
    451      * @return true if the data was saved
    452      */
    453     private boolean validateAndSave(boolean force) {
    454         String name = checkNotSet(mName.getText());
    455         String apn = checkNotSet(mApn.getText());
    456         String mcc = checkNotSet(mMcc.getText());
    457         String mnc = checkNotSet(mMnc.getText());
    458 
    459         if (getErrorMsg() != null && !force) {
    460             showDialog(ERROR_DIALOG_ID);
    461             return false;
    462         }
    463 
    464         if (!mCursor.moveToFirst()) {
    465             Log.w(TAG,
    466                     "Could not go to the first row in the Cursor when saving data.");
    467             return false;
    468         }
    469 
    470         // If it's a new APN and a name or apn haven't been entered, then erase the entry
    471         if (force && mNewApn && name.length() < 1 && apn.length() < 1) {
    472             getContentResolver().delete(mUri, null, null);
    473             return false;
    474         }
    475 
    476         ContentValues values = new ContentValues();
    477 
    478         // Add a dummy name "Untitled", if the user exits the screen without adding a name but
    479         // entered other information worth keeping.
    480         values.put(Telephony.Carriers.NAME,
    481                 name.length() < 1 ? getResources().getString(R.string.untitled_apn) : name);
    482         values.put(Telephony.Carriers.APN, apn);
    483         values.put(Telephony.Carriers.PROXY, checkNotSet(mProxy.getText()));
    484         values.put(Telephony.Carriers.PORT, checkNotSet(mPort.getText()));
    485         values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
    486         values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
    487         values.put(Telephony.Carriers.USER, checkNotSet(mUser.getText()));
    488         values.put(Telephony.Carriers.SERVER, checkNotSet(mServer.getText()));
    489         values.put(Telephony.Carriers.PASSWORD, checkNotSet(mPassword.getText()));
    490         values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
    491 
    492         String authVal = mAuthType.getValue();
    493         if (authVal != null) {
    494             values.put(Telephony.Carriers.AUTH_TYPE, Integer.parseInt(authVal));
    495         }
    496 
    497         values.put(Telephony.Carriers.PROTOCOL, checkNotSet(mProtocol.getValue()));
    498         values.put(Telephony.Carriers.ROAMING_PROTOCOL, checkNotSet(mRoamingProtocol.getValue()));
    499 
    500         values.put(Telephony.Carriers.TYPE, checkNotSet(mApnType.getText()));
    501 
    502         values.put(Telephony.Carriers.MCC, mcc);
    503         values.put(Telephony.Carriers.MNC, mnc);
    504 
    505         values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
    506 
    507         if (mCurMnc != null && mCurMcc != null) {
    508             if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
    509                 values.put(Telephony.Carriers.CURRENT, 1);
    510             }
    511         }
    512 
    513         String bearerVal = mBearer.getValue();
    514         if (bearerVal != null) {
    515             values.put(Telephony.Carriers.BEARER, Integer.parseInt(bearerVal));
    516         }
    517 
    518         getContentResolver().update(mUri, values, null, null);
    519 
    520         return true;
    521     }
    522 
    523     private String getErrorMsg() {
    524         String errorMsg = null;
    525 
    526         String name = checkNotSet(mName.getText());
    527         String apn = checkNotSet(mApn.getText());
    528         String mcc = checkNotSet(mMcc.getText());
    529         String mnc = checkNotSet(mMnc.getText());
    530 
    531         if (name.length() < 1) {
    532             errorMsg = mRes.getString(R.string.error_name_empty);
    533         } else if (apn.length() < 1) {
    534             errorMsg = mRes.getString(R.string.error_apn_empty);
    535         } else if (mcc.length() != 3) {
    536             errorMsg = mRes.getString(R.string.error_mcc_not3);
    537         } else if ((mnc.length() & 0xFFFE) != 2) {
    538             errorMsg = mRes.getString(R.string.error_mnc_not23);
    539         }
    540 
    541         return errorMsg;
    542     }
    543 
    544     @Override
    545     protected Dialog onCreateDialog(int id) {
    546 
    547         if (id == ERROR_DIALOG_ID) {
    548             String msg = getErrorMsg();
    549 
    550             return new AlertDialog.Builder(this)
    551                     .setTitle(R.string.error_title)
    552                     .setPositiveButton(android.R.string.ok, null)
    553                     .setMessage(msg)
    554                     .create();
    555         }
    556 
    557         return super.onCreateDialog(id);
    558     }
    559 
    560     @Override
    561     protected void onPrepareDialog(int id, Dialog dialog) {
    562         super.onPrepareDialog(id, dialog);
    563 
    564         if (id == ERROR_DIALOG_ID) {
    565             String msg = getErrorMsg();
    566 
    567             if (msg != null) {
    568                 ((AlertDialog)dialog).setMessage(msg);
    569             }
    570         }
    571     }
    572 
    573     private void deleteApn() {
    574         getContentResolver().delete(mUri, null, null);
    575         finish();
    576     }
    577 
    578     private String starify(String value) {
    579         if (value == null || value.length() == 0) {
    580             return sNotSet;
    581         } else {
    582             char[] password = new char[value.length()];
    583             for (int i = 0; i < password.length; i++) {
    584                 password[i] = '*';
    585             }
    586             return new String(password);
    587         }
    588     }
    589 
    590     private String checkNull(String value) {
    591         if (value == null || value.length() == 0) {
    592             return sNotSet;
    593         } else {
    594             return value;
    595         }
    596     }
    597 
    598     private String checkNotSet(String value) {
    599         if (value == null || value.equals(sNotSet)) {
    600             return "";
    601         } else {
    602             return value;
    603         }
    604     }
    605 
    606     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    607         Preference pref = findPreference(key);
    608         if (pref != null) {
    609             if (pref.equals(mPassword)){
    610                 pref.setSummary(starify(sharedPreferences.getString(key, "")));
    611             } else {
    612                 pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
    613             }
    614         }
    615     }
    616 }
    617